container support with '%attachment' in ks
authorGui Chen <gui.chen@intel.com>
Wed, 9 May 2012 14:39:17 +0000 (22:39 +0800)
committerGui Chen <gui.chen@intel.com>
Wed, 9 May 2012 14:39:17 +0000 (22:39 +0800)
section %attachment in ks file will list file path or package name,
container will copy the files or content of the packages inside image.
then they are all taring together in loop image with '--taring-to'.

Signed-off-by: Gui Chen <gui.chen@intel.com>
mic/imager/baseimager.py
mic/imager/loop.py
mic/kickstart/__init__.py
plugins/backend/yumpkgmgr.py
plugins/backend/zypppkgmgr.py

index 83bdc01..b8e1888 100644 (file)
@@ -842,6 +842,22 @@ class BaseImageCreator(object):
         for pkg in self._preinstall_pkgs:
             pkg_manager.preInstall(pkg)
 
+    def __attachment_packages(self, pkg_manager):
+        if not self.ks:
+            return
+
+        self._attachment = []
+        for item in kickstart.get_attachment(self.ks):
+            if item.startswith('/'):
+                self._attachment.append(item)
+                continue
+            filelist = pkg_manager.getFilelist(item)
+            if not filelist:
+                msger.warning("No files found in package: %s" % item)
+                continue
+            for pfile in pkg_manager.getFilelist(item):
+                self._attachment.append(pfile)
+
     def install(self, repo_urls = {}):
         """Install packages into the install root.
 
@@ -908,9 +924,13 @@ class BaseImageCreator(object):
         finally:
             self._pkgs_content = pkg_manager.getAllContent()
             self._pkgs_license = pkg_manager.getPkgsLicense()
+            self.__attachment_packages(pkg_manager)
 
             pkg_manager.close()
 
+        # hook post install
+        self.postinstall()
+
         # do some clean up to avoid lvm info leakage.  this sucks.
         for subdir in ("cache", "backup", "archive"):
             lvmdir = self._instroot + "/etc/lvm/" + subdir
@@ -920,6 +940,9 @@ class BaseImageCreator(object):
             except:
                 pass
 
+    def postinstall(self):
+        self.copy_attachment()
+
     def __run_post_scripts(self):
         msger.info("Running scripts ...")
         if os.path.exists(self._instroot + "/tmp"):
@@ -1205,5 +1228,13 @@ class BaseImageCreator(object):
             shutil.copy(kernel, kernelfilename)
             self.outimage.append(kernelfilename)
 
+
+    def copy_attachment(self):
+        """ Subclass implement it to handle attachment files
+
+        NOTE: This needs to be called before unmounting the instroot.
+        """
+        pass
+
     def get_pkg_manager(self):
         return self.pkgmgr(target_arch = self.target_arch, instroot = self._instroot, cachedir = self.cachedir)
index 2d7cdc1..c85ef50 100644 (file)
@@ -16,6 +16,7 @@
 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 import os
+import glob
 import shutil
 
 from mic import kickstart, msger
@@ -368,15 +369,18 @@ class LoopImageCreator(BaseImageCreator):
             tarfile_name = self.taring_to
             mountfp_xml = os.path.splitext(tarfile_name)[0] + ".xml"
 
-            msger.info("Tar all loop images together to %s" % tarfile_name)
-            tar = tarfile.open(os.path.join(self._outdir, tarfile_name), 'w')
             for item in self._instloops:
                 imgfile = os.path.join(self.__imgdir, item['name'])
                 if item['fstype'] == "ext4":
                     runner.show('/sbin/tune2fs '
                                 '-O ^huge_file,extents,uninit_bg %s ' \
                                 % imgfile)
-                tar.add(imgfile, item['name'])
+
+            msger.info("Tar all loop images together to %s" % tarfile_name)
+            tar = tarfile.open(os.path.join(self._outdir, tarfile_name), 'w')
+            for item in os.listdir(self.__imgdir):
+                fpath = os.path.join(self.__imgdir, item)
+                tar.add(fpath, item)
 
             tar.close()
 
@@ -390,3 +394,18 @@ class LoopImageCreator(BaseImageCreator):
             for item in self._instloops:
                 shutil.move(os.path.join(self.__imgdir, item['name']),
                             os.path.join(self._outdir, item['name']))
+
+    def copy_attachment(self):
+        if not hasattr(self, '_attachment') or not self._attachment:
+            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)
+
index 81246a2..2410580 100644 (file)
@@ -54,6 +54,21 @@ class PrepackageSection(kssections.Section):
     def handleHeader(self, lineno, args):
         kssections.Section.handleHeader(self, lineno, args)
 
+class AttachmentSection(kssections.Section):
+    sectionOpen = "%attachment"
+
+    def handleLine(self, line):
+        if not self.handler:
+            return
+
+        (h, s, t) = line.partition('#')
+        line = h.rstrip()
+
+        self.handler.attachment.add([line])
+
+    def handleHeader(self, lineno, args):
+        kssections.Section.handleHeader(self, lineno, args)
+
 def read_kickstart(path):
     """Parse a kickstart file and return a KickstartParser instance.
 
@@ -81,9 +96,11 @@ def read_kickstart(path):
         def __init__(self, mapping={}):
             superclass.__init__(self, mapping=commandMap[using_version])
             self.prepackages = ksparser.Packages()
+            self.attachment = ksparser.Packages()
 
     ks = ksparser.KickstartParser(KSHandlers())
     ks.registerSection(PrepackageSection(ks.handler))
+    ks.registerSection(AttachmentSection(ks.handler))
 
     try:
         ks.readKickstart(path)
@@ -754,6 +771,9 @@ def convert_method_to_repo(ks):
     except (AttributeError, kserrors.KickstartError):
         pass
 
+def get_attachment(ks, required = []):
+    return ks.handler.attachment.packageList + required
+
 def get_pre_packages(ks, required = []):
     return ks.handler.prepackages.packageList + required
 
index efa26bd..c8f1701 100644 (file)
@@ -436,3 +436,13 @@ class Yum(BackendPlugin, yum.YumBase):
 
     def getPkgsLicense(self):
         return self.__pkgs_license
+
+    def getFilelist(self, pkgname):
+        if not pkgname:
+            return None
+
+        pkg = filter(lambda txmbr: txmbr.po.name == pkgname, self.tsInfo.getMembers())
+        if not pkg:
+            return None
+        return pkg[0].po.filelist
+
index 2d94cb5..5a20212 100755 (executable)
@@ -479,6 +479,17 @@ class Zypp(BackendPlugin):
     def getPkgsLicense(self):
         return self.__pkgs_license
 
+    def getFilelist(self, pkgname):
+        if not pkgname:
+            return None
+
+        if not self.ts:
+            self.__initialize_transaction()
+
+        mi = self.ts.dbMatch('name', pkgname)
+        for header in mi:
+            return header['FILENAMES']
+
     def __initialize_repo_manager(self):
         if self.repo_manager:
             return