extract rpm listed in attachment which not found in rootfs
authorGui Chen <gui.chen@intel.com>
Mon, 14 May 2012 13:25:10 +0000 (21:25 +0800)
committerGui Chen <gui.chen@intel.com>
Tue, 15 May 2012 01:34:21 +0000 (09:34 +0800)
Signed-off-by: Gui Chen <gui.chen@intel.com>
mic/imager/baseimager.py
mic/imager/loop.py
mic/utils/misc.py
plugins/backend/yumpkgmgr.py
plugins/backend/zypppkgmgr.py

index b8e1888..2bc82e6 100644 (file)
@@ -32,7 +32,7 @@ import rpm
 from mic import kickstart
 from mic import msger
 from mic.utils.errors import CreatorError, Abort
-from mic.utils import misc, rpmmisc, runner, fs_related as fs
+from mic.utils import misc, rpmmisc, runner, proxy, fs_related as fs
 
 class BaseImageCreator(object):
     """Installs a system to a chroot directory.
@@ -849,14 +849,38 @@ class BaseImageCreator(object):
         self._attachment = []
         for item in kickstart.get_attachment(self.ks):
             if item.startswith('/'):
-                self._attachment.append(item)
+                fpaths = os.path.join(self._instroot, item.lstrip('/'))
+                for fpath in glob.glob(fpaths):
+                    self._attachment.append(fpath)
                 continue
             filelist = pkg_manager.getFilelist(item)
-            if not filelist:
-                msger.warning("No files found in package: %s" % item)
+            if filelist:
+                # found rpm in rootfs
+                for pfile in pkg_manager.getFilelist(item):
+                    fpath = os.path.join(self._instroot, pfile.lstrip('/'))
+                    self._attachment.append(fpath)
                 continue
-            for pfile in pkg_manager.getFilelist(item):
-                self._attachment.append(pfile)
+
+            # try to retrieve rpm file
+            url = pkg_manager.package_url(item)
+            if not url:
+                msger.warning("Can't get url from repo for %s" % item)
+                continue
+            proxies = proxy.get_proxy_for(url)
+            fpath = os.path.join(self.cachedir, os.path.basename(url))
+            if not os.path.exists(fpath):
+                # download pkgs
+                try:
+                    fpath = rpmmisc.myurlgrab(url, fpath, proxies, None)
+                except CreatorError:
+                    raise
+
+            tmpdir = self._mkdtemp()
+            misc.extract_rpm(fpath, tmpdir)
+            for (root, dirs, files) in os.walk(tmpdir):
+                for fname in files:
+                    fpath = os.path.join(root, fname)
+                    self._attachment.append(fpath)
 
     def install(self, repo_urls = {}):
         """Install packages into the install root.
index 35bb413..f4f708b 100644 (file)
@@ -402,15 +402,13 @@ class LoopImageCreator(BaseImageCreator):
 
     def copy_attachment(self):
         if not hasattr(self, '_attachment') or not self._attachment:
-            return 
+            return
 
         self._check_imgdir()
 
         msger.info("Copying attachment files...")
         for item in self._attachment:
-            files = glob.glob("%s/%s" % (self._instroot, item))
-            for fpath in files:
-                dpath = "%s/%s" % (self.__imgdir, os.path.basename(fpath))
-                msger.verbose("Copy attachment %s to %s" % (item, dpath))
-                shutil.copy(fpath, dpath)
+            dpath = os.path.join(self.__imgdir, os.path.basename(item))
+            msger.verbose("Copy attachment %s to %s" % (item, dpath))
+            shutil.copy(item, dpath)
 
index 5e0e077..0c9cf10 100644 (file)
@@ -23,6 +23,7 @@ import re
 import shutil
 import glob
 import hashlib
+import subprocess
 import rpmmisc
 
 try:
@@ -53,6 +54,22 @@ RPM_RE  = re.compile("(.*)\.(.*) (.*)-(.*)")
 RPM_FMT = "%(name)s.%(arch)s %(ver_rel)s"
 SRPM_RE = re.compile("(.*)-(\d+.*)-(\d+\.\d+).src.rpm")
 
+def extract_rpm(rpmfile, targetdir):
+    rpm2cpio = find_binary_path("rpm2cpio")
+    cpio = find_binary_path("cpio")
+
+    olddir = os.getcwd()
+    os.chdir(targetdir)
+
+    msger.verbose("Extract rpm file with cpio: %s" % rpmfile)
+    p1 = subprocess.Popen([rpm2cpio, rpmfile], stdout=subprocess.PIPE)
+    p2 = subprocess.Popen([cpio, "-idv"], stdin=p1.stdout,
+                          stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    (sout, serr) = p2.communicate()
+    msger.verbose(sout or serr)
+
+    os.chdir(olddir)
+
 def taring(dstfile, targetdir):
     import tarfile
     wf = tarfile.open(dstfile, 'w')
index c8f1701..db846d9 100644 (file)
@@ -446,3 +446,9 @@ class Yum(BackendPlugin, yum.YumBase):
             return None
         return pkg[0].po.filelist
 
+    def package_url(self, pkg):
+        pkgs = self.pkgSack.searchNevra(name=pkg)
+        if pkgs:
+            return pkgs[0].remote_url
+        else:
+            return None
index 5a20212..8466dc1 100755 (executable)
@@ -819,3 +819,28 @@ class Zypp(BackendPlugin):
         else:
             repourl = str(repoinfo.baseUrls()[0])
             return get_proxy_for(repourl)
+
+    def package_url(self, pkg):
+
+        def cmpEVR(ed1, ed2):
+            (e1, v1, r1) = map(str, [ed1.epoch(), ed1.version(), ed1.release()])
+            (e2, v2, r2) = map(str, [ed2.epoch(), ed2.version(), ed2.release()])
+            return rpm.labelCompare((e1, v1, r1), (e2, v2, r2))
+
+        if not self.Z:
+            self.__initialize_zypp()
+
+        q = zypp.PoolQuery()
+        q.addKind(zypp.ResKind.package)
+        q.setMatchExact()
+        q.addAttribute(zypp.SolvAttr.name,pkg)
+        items = sorted(q.queryResults(self.Z.pool()),
+                       cmp=lambda x,y: cmpEVR(x.edition(), y.edition()),
+                       reverse=True)
+
+        if items:
+            baseurl = items[0].repoInfo().baseUrls()[0]
+            location = zypp.asKindPackage(items[0]).location()
+            return os.path.join(str(baseurl), str(location.filename()))
+
+        return None