repoconf class for repos.yaml
authorHasan Wan <hasan.wan@intel.com>
Wed, 6 Mar 2013 06:25:23 +0000 (14:25 +0800)
committerHasan Wan <hasan.wan@intel.com>
Wed, 6 Mar 2013 07:11:55 +0000 (15:11 +0800)
Change-Id: I85bcb73226fdb4c3cae65f5df7fb14186e536eee

common/tempbuildpkg.py

index 93a2f4b..87d38c8 100644 (file)
@@ -10,6 +10,13 @@ from buildservice import BuildService
 from urllib import quote_plus
 from osc import core
 from xml.etree import cElementTree as ET
+from xml.dom import minidom
+
+import yaml
+
+# fixing of buggy xml.dom.minidom.toprettyxml
+XMLTEXT_RE = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL)
+
 
 ARCH_LIST = [
     ['ia32', 'i586', 'i486', 'i686'],
@@ -45,9 +52,26 @@ class BuildService2(BuildService):
 
         core.http_PUT(meta_url, file=metaconf)
 
+    def getRepoState(self, project):
+        """ overwirte core deleteproject method, due to it always not work """
+        targets = {}
+        url = core.makeurl(self.apiurl, ['build', project, "_result"])
+        try:
+            output = os.popen('curl %s -k --user %s:%s' %(url,
+                                                          self.apiuser,
+                                                          self.apipasswd))
+            tree = ET.fromstring(output.read())
+        except ET.ParseError:
+            raise ET.ParseError, "Internal Error"
+
+        for result in tree.findall('result'):
+            targets[('/'.join((result.get('repository'), result.get('arch'))))] = result.get('state')
+        return targets
+
+
     def deleteProject(self, project):
         """ overwirte core deleteproject method, due to it always not work """
-        u = core. makeurl(self.apiurl, ['source', project])
+        u = core.makeurl(self.apiurl, ['source', project])
         os.system('curl -X DELETE %s -k --user %s:%s '%(u,
                                                         self.apiuser,
                                                         self.apipasswd))
@@ -60,17 +84,28 @@ class BuildService2(BuildService):
                                       path_args=quote_plus(project))
         retry = 3
         while retry:
-            meta = core.http_GET(meta_url).readlines()
-            if meta:
-                return meta
-            else:
+            try:
+                output = os.popen('curl %s -k --user %s:%s' %(meta_url,
+                                                           self.apiuser,
+                                                           self.apipasswd))
+                meta = output.read()
+
+                if meta:
+                    return meta
+
+            except:
+                time.sleep(2)
+                print "WARN: retrying %s" %retry
                 retry = retry - 1
-        return
+        return "</>"
 
     def get_project_desp(self, project):
         meta_xml = self.get_meta(project)
-        xml_root = ET.fromstringlist(meta_xml)
-        return xml_root.find('description').text
+        desp = ET.fromstringlist(meta_xml).find('description')
+        if desp is not None:
+            return desp.text
+        else:
+            return None
 
     def get_project_arch(self, project, repo_name):
         meta_xml = self.get_meta(project)
@@ -194,7 +229,6 @@ class TempPackageBuild:
                 print '-------------------------------------'
                 print 'key:value  %s' %(line)
                 pass
         return git_info
 
     def del_itself(self):
@@ -274,6 +308,59 @@ class TempBuildService():
         os.close(fileh)
         os.unlink(filename)
 
+class RepoConf:
+    def __init__(self, repos_conf_file):
+
+        if os.path.isfile(repos_conf_file):
+            self.repos = yaml.load(file(repos_conf_file))['Repositories']
+        else:
+            raise Exception, "Fatal: Invalid repo configuration file: %s"  %(repos_conf_file)
+
+    def get_repo(self, project_name):
+
+        for repo in self.repos:
+            if 'Project' not in repo or 'Target' not in repo:
+                continue
+
+            if repo['Project'] == project_name:
+                return repo
+        return None
+    def get_local_base(self, project_name):
+        repo = self.get_repo(project_name)
+        if repo:
+            return repo['SnapshotDir']
+
+    def get_path_to_project(self, project_name):
+        repo = self.get_repo(project_name)
+        if repo:
+            path_to_project =  repo['Location'].replace(repo['TopLevel'], '')
+            if path_to_project.startswith('/'):
+                return path_to_project[1:]
+            else:
+                return path_to_project
+
+    def get_name(self, project_name):
+        repo = self.get_repo(project_name)
+        if repo:
+            return repo['Name']
+
+    def get_repo_by_name(self, repo_name):
+
+        for repo in self.repos:
+            if 'Project' not in repo or 'Target' not in repo:
+                continue
+
+            if repo['Name'] == repo_name:
+                return repo
+        return None
+
+    def save_to_file(self, path_to_file, ext = None):
+
+        stream = file(path_to_file, 'w')
+        if ext:
+            self.repos.append(ext)
+        yaml.dump({"Repositories" : self.repos}, stream)
+
 class BuildData:
     def __init__(self):
         self.__dict__['archs'] = []
@@ -324,7 +411,7 @@ class ProjectRepository:
     """ The Repository information class for OBS project, the instance must
     be schedualed to runs on OBS server."""
 
-    def __init__(self, project, repo_conf = {},
+    def __init__(self, project, repo_conf = None,
                  server_conf = {}, repo_category = 'standard'):
         self.project = project
         self.repo_conf = repo_conf
@@ -343,10 +430,9 @@ class ProjectRepository:
         if not project:
             project = self.project
 
-        path_base = self.server_conf.get('LIVE_REPO_PATH') or \
-            'http://localhost:82/'
+        url_base = self.server_conf.get('LIVEREPO_PUB_BASE_URL')
 
-        return os.path.join(path_base,
+        return os.path.join(url_base,
                             project.replace(':', ':/'),
                             self.repo_category)
 
@@ -354,21 +440,31 @@ class ProjectRepository:
         if not project:
             project = self.project
 
-        # SERVER CONF HARDCODE
+        # Home project has no repo(snapshot), only have live_repo
         if project.startswith('home'):
             return None
+        if self.repo_conf:
+            path_base = self.repo_conf.get_local_base(project)
+            path_to_project = self.repo_conf.get_path_to_project(project)
+        # REPO CONF 'latest' HARDCODE
+            return os.path.realpath(os.path.join(path_base,
+                                                 'latest',
+                                                 path_to_project))
+        return None
 
-        path_base = self.repo_conf.get('REPO_BASE_PATH') or '/srv/snapshots/'
-
-        # TODO:
-        return ''
-
-    def get_latest_repo_pub_url(self):
+    def get_latest_repo_pub_url(self, project = None):
         if project.startswith('home'):
             return None
-        # TODO:
-        return ''
-        pass
+
+        # TODO: ugly way to get latest repo pub url
+        url_base = self.server_conf.get('REPO_PUB_BASE_URL')
+        local_path_to_project_list = self.get_latest_repo_path(project).split('/')
+        join_path = url_base.split('/')[-1]
+        url_to_project = '/'.join(
+            local_path_to_project_list[local_path_to_project_list.index(join_path)+1:])
+
+        return os.path.join(url_base,
+                            url_to_project)
 
     def get_builddata_path(self, repo_path = None):
         # HARDCODE: builddata/
@@ -383,13 +479,16 @@ class ProjectRepository:
         else:
             return os.path.join(path, 'build.xml')
 
-    def save_builddata():
-        if os.path.isdir(os.path.join(live_repo_path, "builddata")):
-            shutil.rmtree(os.path.join(live_repo_path, "builddata"))
+    def save_builddata(self, builddata, repo_path = None):
+        builddata_path = self.get_builddata_path(repo_path)
+        if not os.path.isdir(builddata_path):
+            os.makedirs(builddata_path)
 
-        pass
+        builddata.save_to_file(os.path.join(builddata_path,
+                                            'build.xml'))
 
     def save_buildlogs():
+        # TODO: copy build logs
         os.makedirs(os.path.join(live_repo_path, "builddata/buildlogs"))
         pass
 
@@ -404,7 +503,6 @@ class ProjectRepository:
             if root.find('noarch') < 0:
                 continue
             for f in files:
-                print root,f
                 if re.match(pkg_pattern, f):
                     print "image configurations found: %s/%s" %(root,f)
                     return "%s/%s" %(root, f)
@@ -425,13 +523,12 @@ class ProjectRepository:
         tmpdir = tempfile.mkdtemp()
         os.chdir(tmpdir)
         os.system("rpm2cpio %s | cpio -idmv" %(image_conf_pkg))
-        os.system("cp %s/usr/share/image-configurations/*.ks %s/image-configs"\
+        os.system("cp %s/usr/share/image-configurations/*.ks %s/"\
                       %(tmpdir, image_conf_path))
 
         if os.path.exists("%s/usr/share/image-configurations/image-configs.xml" %tmpdir):
             shutil.copyfile("%s/usr/share/image-configurations/image-configs.xml" %tmpdir,
                             '%s/image-configs.xml' %self.get_builddata_path(repo_path))
-
         shutil.rmtree(tmpdir)
 
     def get_image_conf(self, path = None):
@@ -457,7 +554,7 @@ class ProjectRepository:
 
             for arch in root.find('archs'):
                 valid_arch.append(safe_strip(arch.text))
-
+            print 'valid_arch list', valid_arch
             if conf_str:
                 root = ET.XML(conf_str)
                 for ks in root.findall('config'):
@@ -467,7 +564,11 @@ class ProjectRepository:
                             attr = {}
                         else:
                             attr[child.tag] = safe_strip(child.text)
-                    ks_info[name] = attr
+                    # make sure this arch packages are released
+                    ks_arch = ks.find('arch').text
+                    for arch in valid_arch:
+                        if is_same_arch(ks_arch, arch):
+                            ks_info[name] = attr
         # complete the ks info dict
         for key in ks_info.keys():
             ks_info[key]['images_path'] = os.path.join(path, images_path) \