Merge "Another method of install tpk." into devel
authorChunhua Liu <chunhua1.liu@samsung.com>
Mon, 29 Jan 2018 05:29:00 +0000 (05:29 +0000)
committerGerrit Code Review <gerrit@review.ap-northeast-2.compute.internal>
Mon, 29 Jan 2018 05:29:01 +0000 (05:29 +0000)
1  2 
mic/3rdparty/pykickstart/parser.py
mic/3rdparty/pykickstart/sections.py
mic/conf.py
mic/imager/baseimager.py
mic/kickstart/__init__.py
mic/rt_util.py
plugins/imager/fs_plugin.py
plugins/imager/loop_plugin.py
plugins/imager/qcow_plugin.py
plugins/imager/raw_plugin.py

@@@ -30,7 -30,6 +30,6 @@@ This module exports several important c
  
      KickstartParser - The kickstart file parser state machine.
  """
  from collections import Iterator
  import os
  import shlex
@@@ -204,8 -203,6 +203,8 @@@ class Script(KickstartObject)
              retval += '\n%traceback'
          elif self.type == constants.KS_SCRIPT_RUN:
              retval += '\n%runscript'
 +        elif self.type == constants.KS_SCRIPT_UMOUNT:
 +            retval += '\n%post-umount'
  
          if self.interp != "/bin/sh" and self.interp != "":
              retval += " --interpreter=%s" % self.interp
@@@ -295,6 -292,7 +294,7 @@@ class Packages(KickstartObject)
          self.groupList = []
          self.handleMissing = constants.KS_MISSING_PROMPT
          self.packageList = []
+         self.tpk_packageList = []
          self.instLangs = None
  
      def __str__(self):
          self.packageList = list(existingPackageSet)
          self.excludedList = list(existingExcludedSet)
  
+ class TpkPackages(KickstartObject):
+     """A class representing the %tpk_packages section of the kickstart file."""
+     def __init__(self, *args, **kwargs):
+         KickstartObject.__init__(self, *args, **kwargs)
+         self.tpk_packageList = []
+     def __str__(self):
+         tpk_pkgs = ""
+         retval = "\n%tpk_packages"
+         p = self.packageList
+         p.sort()
+         for pkg in p:
+             tpk_pkgs += "%s\n" % pkg
+         return retval + "\n" +tpk_pkgs
+     def add(self, tpkPackageList):
+         tpk_PackageSet = set(self.tpk_packageList)
+         for tpk_pkg in tpkPackageList:
+             stripped = tpk_pkg.strip()
+             tpk_PackageSet.add(stripped)
+         self.tpk_packageList = list(tpk_PackageSet)
  ###
  ### PARSER
  ###
@@@ -704,5 -720,6 +722,7 @@@ class KickstartParser
          self.registerSection(PostScriptSection(self.handler, dataObj=Script))
          self.registerSection(TracebackScriptSection(self.handler, dataObj=Script))
          self.registerSection(RunScriptSection(self.handler, dataObj=Script))
 +        self.registerSection(PostUmountScriptSection(self.handler, dataObj=Script))
          self.registerSection(PackageSection(self.handler))
+         self.registerSection(TpkPackageSection(self.handler))
@@@ -30,7 -30,6 +30,7 @@@ is necessary is to create a new subclas
  parser.registerSection with an instance of your new class.
  """
  from constants import *
 +from errors import *
  from options import KSOptionParser
  from version import *
  
@@@ -197,34 -196,9 +197,34 @@@ class TracebackScriptSection(ScriptSect
  
  class RunScriptSection(ScriptSection):
      sectionOpen = "%runscript"
 +
      def _resetScript(self):
          ScriptSection._resetScript(self)
          self._script["type"] = KS_SCRIPT_RUN
 +
 +    def finalize(self):
 +        ScriptSection.finalize(self)
 +        if self.handler:
 +            for s in self.handler.scripts:
 +                if s.type == KS_SCRIPT_UMOUNT:
 +                    raise KickstartError("%runscript and %post-umount " \
 +                                         "can not be defined together")
 +
 +class PostUmountScriptSection(ScriptSection):
 +    sectionOpen = "%post-umount"
 +
 +    def _resetScript(self):
 +        ScriptSection._resetScript(self)
 +        self._script["type"] = KS_SCRIPT_UMOUNT
 +
 +    def finalize(self):
 +        ScriptSection.finalize(self)
 +        if self.handler:
 +            for s in self.handler.scripts:
 +                if s.type == KS_SCRIPT_RUN:
 +                    raise KickstartError("%runscript and %post-umount " \
 +                                         "can not be defined together")
 +
  class PackageSection(Section):
      sectionOpen = "%packages"
  
  
          (h, s, t) = line.partition('#')
          line = h.rstrip()
          self.handler.packages.add([line])
  
      def handleHeader(self, lineno, args):
  
          if opts.instLangs:
              self.handler.packages.instLangs = opts.instLangs
+ class TpkPackageSection(Section):
+     sectionOpen = "%tpk_packages"
+     def handleLine(self, line):
+         if not self.handler:
+             return
+         (h, s, t) = line.partition('#')
+         line = h.rstrip()
+         self.handler.tpk_packages.add([line])
+     def handleHeader(self, lineno, args):
+         """Process the arguments to the %tpk_packages header and set attributes
+            on the Version's TpkPackages instance appropriate.  This method may be
+            overridden in a subclass if necessary.
+         """
+         Section.handleHeader(self, lineno, args)
diff --combined mic/conf.py
@@@ -71,13 -71,13 +71,14 @@@ class ConfigMgr(object)
                      "check_pkgs": [],
                      "repourl": {},
                      "localrepos": [],  # save localrepos
+                     "localtpkrepos":[],
                      "runtime": "bootstrap",
                      "extrarepos": {},
                      "ignore_ksrepo": False,
                      "strict_mode": False,
                      "run_script": None,
                      "tpk_install": None,
 +                    "use_mic_in_bootstrap": False,
                  },
                  'chroot': {
                      "saveto": None,
                  packages = packages.split()
              self.bootstrap['packages'] = packages
  
 +        if type(self.create['use_mic_in_bootstrap']) != 'bool':
 +            use_mic_in_bootstrap = str(self.create['use_mic_in_bootstrap'])
 +            if use_mic_in_bootstrap.lower() in ('on', 'yes', 'true', '1'):
 +                self.create['use_mic_in_bootstrap'] = True
 +            else:
 +                self.create['use_mic_in_bootstrap'] = False
 +
      def _parse_kickstart(self, ksconf=None):
          if not ksconf:
              return
                                                             self.create['release'],
                                                             self.create['name'])
              self.create['name'] = self.create['release'] + '_' + self.create['name']
 +            if self.create['pack_to'] is not None:
 +                if '@NAME@' in self.create['pack_to']:
 +                    self.create['pack_to'] = self.create['pack_to'].replace('@NAME@', self.create['name'])
 +                self.create['name'] = misc.strip_archive_suffix(self.create['pack_to'])
 +                if self.create['name'] is None:
 +                    raise errors.CreatorError("Not supported archive file format: %s" % self.create['pack_to'])
  
              if not self.create['logfile']:
                  self.create['logfile'] = os.path.join(self.create['destdir'],
                  self.create['releaselog'] = True
                  self.set_logfile()
  
 +        elif self.create['pack_to'] is not None:
 +            if '@NAME@' in self.create['pack_to']:
 +                self.create['pack_to'] = self.create['pack_to'].replace('@NAME@', self.create['name'])
 +            self.create['name'] = misc.strip_archive_suffix(self.create['pack_to'])
 +            if self.create['name'] is None:
 +                raise errors.CreatorError("Not supported archive file format: %s" % self.create['pack_to'])
 +
          msger.info("Retrieving repo metadata:")
          ksrepos = kickstart.get_repos(ks,
                                        self.create['extrarepos'],
          self.create['repomd'] = misc.get_metadata_from_repos(
                                                      ksrepos,
                                                      self.create['cachedir'])
+         kstpkrepos = kickstart.get_tpkrepos(ks)
+         if kstpkrepos:
+             for tpk_repo in kstpkrepos:
+                 if hasattr(tpk_repo,'baseurl') and tpk_repo.baseurl.startswith("file:"):
+                     tpk_repourl = tpk_repo.baseurl.replace('file:','')
+                     tpk_repourl = "/%s" % tpk_repourl.lstrip('/')
+                     self.create['localtpkrepos'].append(tpk_repourl)
          msger.raw(" DONE")
  
          target_archlist, archlist = misc.get_arch(self.create['repomd'])
diff --combined mic/imager/baseimager.py
@@@ -1,4 -1,3 +1,3 @@@
  #!/usr/bin/python -tt
  #
  # Copyright (c) 2007 Red Hat  Inc.
@@@ -28,16 -27,16 +27,16 @@@ import tarfil
  import glob
  import json
  from datetime import datetime
  import rpm
  import time
  from mic import kickstart
  from mic import msger, __version__ as VERSION
 -from mic.utils.errors import CreatorError, Abort
 +from mic.utils.errors import CreatorError, KsError, Abort
  from mic.utils import misc, grabber, runner, fs_related as fs
  from mic.chroot import kill_proc_inchroot
  from mic.archive import get_archive_suffixes
  from mic.conf import configmgr
+ from mic.utils.grabber import myurlgrab
  #post script max run time
  MAX_RUN_TIME = 120
  
@@@ -117,6 -116,8 +116,6 @@@ class BaseImageCreator(object)
              self.destdir = os.path.abspath(os.path.expanduser(self.destdir))
  
              if self.pack_to:
 -                if '@NAME@' in self.pack_to:
 -                    self.pack_to = self.pack_to.replace('@NAME@', self.name)
                  (tar, ext) = os.path.splitext(self.pack_to)
                  if ext in (".gz", ".bz2", ".lzo", ".bz") and tar.endswith(".tar"):
                      ext = ".tar" + ext
                  if part.fstype and part.fstype == "btrfs":
                      self._dep_checks.append("mkfs.btrfs")
                      break
 -                if part.fstype == "cpio":
 -                    part.fstype = "ext4"
 +                if part.cpioopts:
 +                    if part.fstype == "cpio": 
 +                        part.fstype = "ext4"
 +                    else:
 +                        raise KsError("The '--fstype' in ks file need to set 'cpio' when you want to generate image by cpio.")
              if len(self.ks.handler.partition.partitions) > 1:
                  self.multiple_partitions = True
  
          for pkg in self._excluded_pkgs:
              pkg_manager.deselectPackage(pkg)
  
 -    def __localinst_packages(self, pkg_manager):
 +    """def __localinst_packages(self, pkg_manager):
          for rpm_path in self._get_local_packages():
 -            pkg_manager.installLocal(rpm_path)
 +            pkg_manager.installLocal(rpm_path)"""
  
      def __preinstall_packages(self, pkg_manager):
          if not self.ks:
              if 'debuginfo' in self.install_pkgs:
                  pkg_manager.install_debuginfo = True
  
          for repo in kickstart.get_repos(self.ks, repo_urls, self.ignore_ksrepo):
              (name, baseurl, mirrorlist, inc, exc,
               proxy, proxy_username, proxy_password, debuginfo,
              self.__select_packages(pkg_manager)
              self.__select_groups(pkg_manager)
              self.__deselect_packages(pkg_manager)
 -            self.__localinst_packages(pkg_manager)
 +            #self.__localinst_packages(pkg_manager)
              self.__check_packages(pkg_manager)
  
              BOOT_SAFEGUARD = 256L * 1024 * 1024 # 256M
              except:
                  pass
  
+     def tpkinstall(self):
+         if self.ks:
+             tpk_pkgs = kickstart.get_tpkpackages(self.ks)
+             tpk_repoList = kickstart.get_tpkrepos(self.ks)
+             if tpk_repoList and tpk_pkgs:
+                 tpk_dir = "/usr/apps/.preload-tpk"
+                 fs.makedirs(self._instroot + "/usr/apps")
+                 fs.makedirs(self._instroot + tpk_dir)
+             for pkg in tpk_pkgs:
+                 flag = 0
+                 for tpk_repo in tpk_repoList:
+                     if hasattr(tpk_repo,'baseurl') and tpk_repo.baseurl.startswith("file:"):
+                         tpk_repourl = tpk_repo.baseurl.replace('file:','')
+                         tpk_repourl = "/%s" % tpk_repourl.lstrip('/')
+                         tpk_pkgpath = tpk_repourl + "/"+ pkg
+                         if os.path.isfile(tpk_pkgpath):
+                             shutil.copy(tpk_pkgpath,self._instroot + tpk_dir)
+                             flag = 1
+                             break
+                     elif hasattr(tpk_repo,'baseurl'):
+                         url = tpk_repo.baseurl.join(pkg)
+                         filename = self._instroot+tpk_dir+"/"+pkg
+                         if tpk_repo.baseurl.startswith("http:"):
+                             import urllib
+                             status = urllib.urlopen(url).code
+                             if status == 200:
+                                 filename = myurlgrab(url.full, filename, None)
+                                 flag = 1
+                                 break
+                             elif status == 404 or status == None:
+                                 continue
+                         #url is ok, then download, url wrong, check other url.
+                         elif tpk_repo.baseurl.startswith("https:") :
+                             try:
+                                 flag = 1
+                                 filename = myurlgrab(url.full, filename, None)
+                             except CreatorError:
+                                 continue
+                 if flag == 0:
+                     raise CreatorError("Tpk package missing.")
      def postinstall(self):
 -        self.copy_attachment()
 +        pass
  
      def _get_sign_scripts_env(self):
          """Return an environment dict for %post-umount scripts.
                          runner.show('find . | cpio --create %s | gzip > %s' % (item['cpioopts'], tmp_cpio_imgfile))
                          os.chdir(oldoutdir)
                  except OSError, (errno, msg):
 -                    raise errors.CreatorError("Create image by cpio error: %s" % msg)
 +                    raise CreatorError("Create image by cpio error: %s" % msg)
  
      def copy_cpio_image(self):
          for item in self._instloops:
                  try:
                      shutil.copyfile(os.path.join(tmp_cpio, item['name']),os.path.join(self._imgdir, item['name']))
                  except IOError:
 -                    raise errors.CreatorError("Copy cpio image error")
 +                    raise CreatorError("Copy cpio image error")
                  os.remove(os.path.join(tmp_cpio, item['name']))
                  if not os.listdir(tmp_cpio):
                      shutil.rmtree(tmp_cpio, ignore_errors=True)
@@@ -100,11 -100,13 +100,13 @@@ def read_kickstart(path)
      using_version = ksversion.DEVEL
      commandMap[using_version]["desktop"] = desktop.Mic_Desktop
      commandMap[using_version]["repo"] = micrepo.Mic_Repo
+     commandMap[using_version]["tpk_repo"] = micrepo.Mic_Tpk_Repo
      commandMap[using_version]["bootloader"] = micboot.Mic_Bootloader
      commandMap[using_version]["part"] = partition.Mic_Partition
      commandMap[using_version]["partition"] = partition.Mic_Partition
      commandMap[using_version]["installerfw_plugins"] = installerfw.Mic_installerfw
      dataMap[using_version]["RepoData"] = micrepo.Mic_RepoData
+     dataMap[using_version]["Tpk_RepoData"] = micrepo.Mic_Tpk_RepoData
      dataMap[using_version]["PartData"] = partition.Mic_PartData
      superclass = ksversion.returnClassForVersion(version=using_version)
  
@@@ -772,9 -774,32 +774,32 @@@ def get_repos(ks, repo_urls=None, ignor
                                            repo.get('user', None),
                                            repo.get('passwd', None))
              repos[name] = Repo(**repo)
      return repos.values()
  
+ TpkRepoType = collections.namedtuple("TpkRepo",
+                "name, baseurl,proxy,proxy_username,proxy_password,ssl_verify")
+ def TpkRepo(name, baseurl, proxy=None,proxy_username=None, proxy_password=None,ssl_verify=None):
+     return TpkRepoType(name, baseurl,proxy,proxy_username,proxy_password,ssl_verify)
+ def get_tpkrepos(ks):
+     tpkrepos = {}
+     for tpkrepodata in ks.handler.tpk_repo.tpkRepoList:
+         tpkrepo = {}
+         for field in TpkRepoType._fields:
+             if hasattr(tpkrepodata, field) and getattr(tpkrepodata, field):
+                 tpkrepo[field] = getattr(tpkrepodata, field)
+         if hasattr(tpkrepodata, 'baseurl') and getattr(tpkrepodata, 'baseurl'):
+             tpkrepo['baseurl'] = SafeURL(getattr(tpkrepodata, 'baseurl'),getattr(tpkrepodata, 'user',None),getattr(tpkrepodata, 'passwd',None))
+         if 'name' in tpkrepo:
+             tpkrepos[tpkrepo['name']] = TpkRepo(**tpkrepo)
+     return tpkrepos.values()
  def convert_method_to_repo(ks):
      try:
          ks.handler.repo.methodToRepo()
@@@ -790,6 -815,9 +815,9 @@@ def get_pre_packages(ks, required=())
  def get_packages(ks, required=()):
      return ks.handler.packages.packageList + list(required)
  
+ def get_tpkpackages(ks):
+     return ks.handler.tpk_packages.tpk_packageList
  def get_groups(ks, required=()):
      return ks.handler.packages.groupList + list(required)
  
@@@ -823,11 -851,10 +851,11 @@@ def get_post_scripts(ks)
  def get_sign_scripts(ks):
      scripts = []
      for s in ks.handler.scripts:
 -        if s.type != ksparser.KS_SCRIPT_RUN:
 -            continue
 -        scripts.append(s)
 +        if (s.type == ksparser.KS_SCRIPT_RUN or \
 +            s.type == ksparser.KS_SCRIPT_UMOUNT):
 +            scripts.append(s)
      return scripts
 +
  def add_repo(ks, repostr):
      args = repostr.split()
      repoobj = ks.handler.repo.parse(args[1:])
diff --combined mic/rt_util.py
@@@ -104,11 -104,7 +104,11 @@@ def bootstrap_mic(argv=None)
              rootdir = os.path.join(rootdir, "bootstrap")
  
          bsenv.dirsetup(rootdir)
 -        sync_mic(rootdir, plugin=cropts['plugin_dir'])
 +        if cropts['use_mic_in_bootstrap']:
 +            msger.info("No copy host mic")
 +        else:
 +            msger.info("Copy host mic to bootstrap")
 +            sync_mic(rootdir, plugin=cropts['plugin_dir'])
  
          #FIXME: sync the ks file to bootstrap
          if "/" == os.path.dirname(os.path.abspath(configmgr._ksconf)):
@@@ -148,6 -144,8 +148,8 @@@ def get_bindmounts(cropts)
  
      for lrepo in cropts['localrepos']:
          binddirs.append(lrepo)
+     for ltpkrepo in cropts['localtpkrepos']:
+         binddirs.append(ltpkrepo)
  
      bindlist = map(expath, filter(None, binddirs))
      bindlist += map(os.path.dirname, map(expath, filter(None, bindfiles)))
@@@ -93,6 -93,7 +93,7 @@@ class FsPlugin(ImagerPlugin)
              creator.check_depend_tools()
              creator.mount(None, creatoropts["cachedir"])
              creator.install()
+             creator.tpkinstall()
              #Download the source packages ###private options
              if args.include_src:
                  installed_pkgs =  creator.get_installed_packages()
  
              creator.configure(creatoropts["repomd"])
              creator.copy_kernel()
 +            creator.copy_attachment()
              creator.unmount()
              creator.package(creatoropts["destdir"])
              creator.create_manifest()
@@@ -101,9 -101,9 +101,10 @@@ class LoopPlugin(ImagerPlugin)
              creator.check_depend_tools()
              creator.mount(None, creatoropts["cachedir"])
              creator.install()
+             creator.tpkinstall()
              creator.configure(creatoropts["repomd"])
              creator.copy_kernel()
 +            creator.copy_attachment()
              creator.create_cpio_image()
              creator.unmount()
              creator.copy_cpio_image()
@@@ -132,9 -132,9 +132,10 @@@ class QcowPlugin(ImagerPlugin)
              creator.check_depend_tools()
              creator.mount(None, creatoropts["cachedir"])
              creator.install()
+             creator.tpkinstall()
              creator.configure(creatoropts["repomd"])
              creator.copy_kernel()
 +            creator.copy_attachment()
              creator.create_cpio_image()
              creator.unmount()
              creator.copy_cpio_image()
@@@ -99,9 -99,9 +99,10 @@@ class RawPlugin(ImagerPlugin)
              creator.check_depend_tools()
              creator.mount(None, creatoropts["cachedir"])
              creator.install()
+             creator.tpkinstall()
              creator.configure(creatoropts["repomd"])
              creator.copy_kernel()
 +            creator.copy_attachment()
              creator.unmount()
              creator.generate_bmap()
              creator.package(creatoropts["destdir"])