diff options
-rw-r--r-- | scripts/lib/mic/imager/baseimager.py | 1030 | ||||
-rw-r--r-- | scripts/lib/mic/imager/direct.py | 4 |
2 files changed, 9 insertions, 1025 deletions
diff --git a/scripts/lib/mic/imager/baseimager.py b/scripts/lib/mic/imager/baseimager.py index b7212493b4..55f2deaf2c 100644 --- a/scripts/lib/mic/imager/baseimager.py +++ b/scripts/lib/mic/imager/baseimager.py @@ -18,37 +18,31 @@ from __future__ import with_statement import os, sys -import stat import tempfile import shutil -import subprocess -import re -import tarfile -import glob from mic import kickstart from mic import msger -from mic.utils.errors import CreatorError, Abort +from mic.utils.errors import CreatorError from mic.utils import misc, runner, fs_related as fs class BaseImageCreator(object): - """Installs a system to a chroot directory. + """Base class for image creation. - ImageCreator is the simplest creator class available; it will install and - configure a system image according to the supplied kickstart file. + BaseImageCreator is the simplest creator class available; it will + create a system image according to the supplied kickstart file. e.g. import mic.imgcreate as imgcreate ks = imgcreate.read_kickstart("foo.ks") imgcreate.ImageCreator(ks, "foo").create() - """ def __del__(self): self.cleanup() - def __init__(self, createopts = None, pkgmgr = None): + def __init__(self, createopts = None): """Initialize an ImageCreator instance. ks -- a pykickstart.KickstartParser instance; this instance will be @@ -59,36 +53,19 @@ class BaseImageCreator(object): filesystem labels """ - self.pkgmgr = pkgmgr - self.__builddir = None - self.__bindmounts = [] self.ks = None self.name = "target" self.tmpdir = "/var/tmp/wic" - self.cachedir = "/var/tmp/wic/cache" self.workdir = "/var/tmp/wic/build" - self.destdir = "." - self.installerfw_prefix = "INSTALLERFW_" - self.target_arch = "noarch" - self._local_pkgs_path = None - self.pack_to = None - self.repourl = {} - - # If the kernel is save to the destdir when copy_kernel cmd is called. - self._need_copy_kernel = False # setup tmpfs tmpdir when enabletmpfs is True self.enabletmpfs = False if createopts: # Mapping table for variables that have different names. - optmap = {"pkgmgr" : "pkgmgr_name", - "outdir" : "destdir", - "arch" : "target_arch", - "local_pkgs_path" : "_local_pkgs_path", - "copy_kernel" : "_need_copy_kernel", + optmap = {"outdir" : "destdir", } # update setting from createopts @@ -101,41 +78,11 @@ class BaseImageCreator(object): self.destdir = os.path.abspath(os.path.expanduser(self.destdir)) - if 'release' in createopts and createopts['release']: - self.name = createopts['release'] + '_' + self.name - - 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") and tar.endswith(".tar"): - ext = ".tar" + ext - if ext not in misc.pack_formats: - self.pack_to += ".tar" - - self._dep_checks = ["ls", "bash", "cp", "echo", "modprobe"] + self._dep_checks = ["ls", "bash", "cp", "echo"] # Output image file names self.outimage = [] - # A flag to generate checksum - self._genchecksum = False - - self._alt_initrd_name = None - - self._recording_pkgs = [] - - # available size in root fs, init to 0 - self._root_fs_avail = 0 - - # Name of the disk image file that is created. - self._img_name = None - - self.image_format = None - - # Save qemu emulator file name in order to clean up it finally - self.qemu_emulator = None - # No ks provided when called by convertor, so skip the dependency check if self.ks: # If we have btrfs partition we need to check necessary tools @@ -144,31 +91,9 @@ class BaseImageCreator(object): self._dep_checks.append("mkfs.btrfs") break - if self.target_arch and self.target_arch.startswith("arm"): - for dep in self._dep_checks: - if dep == "extlinux": - self._dep_checks.remove(dep) - - if not os.path.exists("/usr/bin/qemu-arm") or \ - not misc.is_statically_linked("/usr/bin/qemu-arm"): - self._dep_checks.append("qemu-arm-static") - - if os.path.exists("/proc/sys/vm/vdso_enabled"): - vdso_fh = open("/proc/sys/vm/vdso_enabled","r") - vdso_value = vdso_fh.read().strip() - vdso_fh.close() - if (int)(vdso_value) == 1: - msger.warning("vdso is enabled on your host, which might " - "cause problems with arm emulations.\n" - "\tYou can disable vdso with following command before " - "starting image build:\n" - "\techo 0 | sudo tee /proc/sys/vm/vdso_enabled") - # make sure the specified tmpdir and cachedir exist if not os.path.exists(self.tmpdir): os.makedirs(self.tmpdir) - if not os.path.exists(self.cachedir): - os.makedirs(self.cachedir) # @@ -190,23 +115,6 @@ class BaseImageCreator(object): """ - def __get_outdir(self): - if self.__builddir is None: - raise CreatorError("_outdir is not valid before calling mount()") - return self.__builddir + "/out" - _outdir = property(__get_outdir) - """The staging location for the final image. - - This is where subclasses should stage any files that are part of the final - image. ImageCreator.package() will copy any files found here into the - requested destination directory. - - Note, this directory does not exist before ImageCreator.mount() is called. - - Note also, this is a read-only attribute. - - """ - # # Hooks for subclasses @@ -239,408 +147,6 @@ class BaseImageCreator(object): """ pass - def _create_bootconfig(self): - """Configure the image so that it's bootable. - - This is the hook where subclasses may prepare the image for booting by - e.g. creating an initramfs and bootloader configuration. - - This hook is called while the install root is still mounted, after the - packages have been installed and the kickstart configuration has been - applied, but before the %post scripts have been executed. - - There is no default implementation. - - """ - pass - - def _stage_final_image(self): - """Stage the final system image in _outdir. - - This is the hook where subclasses should place the image in _outdir - so that package() can copy it to the requested destination directory. - - By default, this moves the install root into _outdir. - - """ - shutil.move(self._instroot, self._outdir + "/" + self.name) - - def get_installed_packages(self): - return self._pkgs_content.keys() - - def _save_recording_pkgs(self, destdir): - """Save the list or content of installed packages to file. - """ - pkgs = self._pkgs_content.keys() - pkgs.sort() # inplace op - - if not os.path.exists(destdir): - os.makedirs(destdir) - - content = None - if 'vcs' in self._recording_pkgs: - vcslst = ["%s %s" % (k, v) for (k, v) in self._pkgs_vcsinfo.items()] - content = '\n'.join(sorted(vcslst)) - elif 'name' in self._recording_pkgs: - content = '\n'.join(pkgs) - if content: - namefile = os.path.join(destdir, self.name + '.packages') - f = open(namefile, "w") - f.write(content) - f.close() - self.outimage.append(namefile); - - # if 'content', save more details - if 'content' in self._recording_pkgs: - contfile = os.path.join(destdir, self.name + '.files') - f = open(contfile, "w") - - for pkg in pkgs: - content = pkg + '\n' - - pkgcont = self._pkgs_content[pkg] - content += ' ' - content += '\n '.join(pkgcont) - content += '\n' - - content += '\n' - f.write(content) - f.close() - self.outimage.append(contfile) - - if 'license' in self._recording_pkgs: - licensefile = os.path.join(destdir, self.name + '.license') - f = open(licensefile, "w") - - f.write('Summary:\n') - for license in reversed(sorted(self._pkgs_license, key=\ - lambda license: len(self._pkgs_license[license]))): - f.write(" - %s: %s\n" \ - % (license, len(self._pkgs_license[license]))) - - f.write('\nDetails:\n') - for license in reversed(sorted(self._pkgs_license, key=\ - lambda license: len(self._pkgs_license[license]))): - f.write(" - %s:\n" % (license)) - for pkg in sorted(self._pkgs_license[license]): - f.write(" - %s\n" % (pkg)) - f.write('\n') - - f.close() - self.outimage.append(licensefile) - - def _get_required_packages(self): - """Return a list of required packages. - - This is the hook where subclasses may specify a set of packages which - it requires to be installed. - - This returns an empty list by default. - - Note, subclasses should usually chain up to the base class - implementation of this hook. - - """ - return [] - - def _get_excluded_packages(self): - """Return a list of excluded packages. - - This is the hook where subclasses may specify a set of packages which - it requires _not_ to be installed. - - This returns an empty list by default. - - Note, subclasses should usually chain up to the base class - implementation of this hook. - - """ - return [] - - def _get_local_packages(self): - """Return a list of rpm path to be local installed. - - This is the hook where subclasses may specify a set of rpms which - it requires to be installed locally. - - This returns an empty list by default. - - Note, subclasses should usually chain up to the base class - implementation of this hook. - - """ - if self._local_pkgs_path: - if os.path.isdir(self._local_pkgs_path): - return glob.glob( - os.path.join(self._local_pkgs_path, '*.rpm')) - elif os.path.splitext(self._local_pkgs_path)[-1] == '.rpm': - return [self._local_pkgs_path] - - return [] - - def _get_fstab(self): - """Return the desired contents of /etc/fstab. - - This is the hook where subclasses may specify the contents of - /etc/fstab by returning a string containing the desired contents. - - A sensible default implementation is provided. - - """ - s = "/dev/root / %s %s 0 0\n" \ - % (self._fstype, - "defaults,noatime" if not self._fsopts else self._fsopts) - s += self._get_fstab_special() - return s - - def _get_fstab_special(self): - s = "devpts /dev/pts devpts gid=5,mode=620 0 0\n" - s += "tmpfs /dev/shm tmpfs defaults 0 0\n" - s += "proc /proc proc defaults 0 0\n" - s += "sysfs /sys sysfs defaults 0 0\n" - return s - - def _set_part_env(self, pnum, prop, value): - """ This is a helper function which generates an environment variable - for a property "prop" with value "value" of a partition number "pnum". - - The naming convention is: - * Variables start with INSTALLERFW_PART - * Then goes the partition number, the order is the same as - specified in the KS file - * Then goes the property name - """ - - if value == None: - value = "" - else: - value = str(value) - - name = self.installerfw_prefix + ("PART%d_" % pnum) + prop - return { name : value } - - def _get_post_scripts_env(self, in_chroot): - """Return an environment dict for %post scripts. - - This is the hook where subclasses may specify some environment - variables for %post scripts by return a dict containing the desired - environment. - - in_chroot -- whether this %post script is to be executed chroot()ed - into _instroot. - """ - - env = {} - pnum = 0 - - for p in kickstart.get_partitions(self.ks): - env.update(self._set_part_env(pnum, "SIZE", p.size)) - env.update(self._set_part_env(pnum, "MOUNTPOINT", p.mountpoint)) - env.update(self._set_part_env(pnum, "FSTYPE", p.fstype)) - env.update(self._set_part_env(pnum, "LABEL", p.label)) - env.update(self._set_part_env(pnum, "FSOPTS", p.fsopts)) - env.update(self._set_part_env(pnum, "BOOTFLAG", p.active)) - env.update(self._set_part_env(pnum, "ALIGN", p.align)) - env.update(self._set_part_env(pnum, "TYPE_ID", p.part_type)) - env.update(self._set_part_env(pnum, "DEVNODE", - "/dev/%s%d" % (p.disk, pnum + 1))) - pnum += 1 - - # Count of paritions - env[self.installerfw_prefix + "PART_COUNT"] = str(pnum) - - # Partition table format - ptable_format = self.ks.handler.bootloader.ptable - env[self.installerfw_prefix + "PTABLE_FORMAT"] = ptable_format - - # The kerned boot parameters - kernel_opts = self.ks.handler.bootloader.appendLine - env[self.installerfw_prefix + "KERNEL_OPTS"] = kernel_opts - - # Name of the distribution - env[self.installerfw_prefix + "DISTRO_NAME"] = self.distro_name - - # Name of the image creation tool - env[self.installerfw_prefix + "INSTALLER_NAME"] = "wic" - - # The real current location of the mounted file-systems - if in_chroot: - mount_prefix = "/" - else: - mount_prefix = self._instroot - env[self.installerfw_prefix + "MOUNT_PREFIX"] = mount_prefix - - # These are historical variables which lack the common name prefix - if not in_chroot: - env["INSTALL_ROOT"] = self._instroot - env["IMG_NAME"] = self._name - - return env - - def __get_imgname(self): - return self.name - _name = property(__get_imgname) - """The name of the image file. - - """ - - def _get_kernel_versions(self): - """Return a dict detailing the available kernel types/versions. - - This is the hook where subclasses may override what kernel types and - versions should be available for e.g. creating the booloader - configuration. - - A dict should be returned mapping the available kernel types to a list - of the available versions for those kernels. - - The default implementation uses rpm to iterate over everything - providing 'kernel', finds /boot/vmlinuz-* and returns the version - obtained from the vmlinuz filename. (This can differ from the kernel - RPM's n-v-r in the case of e.g. xen) - - """ - def get_kernel_versions(instroot): - ret = {} - versions = set() - files = glob.glob(instroot + "/boot/vmlinuz-*") - for file in files: - version = os.path.basename(file)[8:] - if version is None: - continue - versions.add(version) - ret["kernel"] = list(versions) - return ret - - def get_version(header): - version = None - for f in header['filenames']: - if f.startswith('/boot/vmlinuz-'): - version = f[14:] - return version - - if self.ks is None: - return get_kernel_versions(self._instroot) - - ts = rpm.TransactionSet(self._instroot) - - ret = {} - for header in ts.dbMatch('provides', 'kernel'): - version = get_version(header) - if version is None: - continue - - name = header['name'] - if not name in ret: - ret[name] = [version] - elif not version in ret[name]: - ret[name].append(version) - - return ret - - - # - # Helpers for subclasses - # - def _do_bindmounts(self): - """Mount various system directories onto _instroot. - - This method is called by mount(), but may also be used by subclasses - in order to re-mount the bindmounts after modifying the underlying - filesystem. - - """ - for b in self.__bindmounts: - b.mount() - - def _undo_bindmounts(self): - """Unmount the bind-mounted system directories from _instroot. - - This method is usually only called by unmount(), but may also be used - by subclasses in order to gain access to the filesystem obscured by - the bindmounts - e.g. in order to create device nodes on the image - filesystem. - - """ - self.__bindmounts.reverse() - for b in self.__bindmounts: - b.unmount() - - def _chroot(self): - """Chroot into the install root. - - This method may be used by subclasses when executing programs inside - the install root e.g. - - subprocess.call(["/bin/ls"], preexec_fn = self.chroot) - - """ - os.chroot(self._instroot) - os.chdir("/") - - def _mkdtemp(self, prefix = "tmp-"): - """Create a temporary directory. - - This method may be used by subclasses to create a temporary directory - for use in building the final image - e.g. a subclass might create - a temporary directory in order to bundle a set of files into a package. - - The subclass may delete this directory if it wishes, but it will be - automatically deleted by cleanup(). - - The absolute path to the temporary directory is returned. - - Note, this method should only be called after mount() has been called. - - prefix -- a prefix which should be used when creating the directory; - defaults to "tmp-". - - """ - self.__ensure_builddir() - return tempfile.mkdtemp(dir = self.__builddir, prefix = prefix) - - def _mkstemp(self, prefix = "tmp-"): - """Create a temporary file. - - This method may be used by subclasses to create a temporary file - for use in building the final image - e.g. a subclass might need - a temporary location to unpack a compressed file. - - The subclass may delete this file if it wishes, but it will be - automatically deleted by cleanup(). - - A tuple containing a file descriptor (returned from os.open() and the - absolute path to the temporary directory is returned. - - Note, this method should only be called after mount() has been called. - - prefix -- a prefix which should be used when creating the file; - defaults to "tmp-". - - """ - self.__ensure_builddir() - return tempfile.mkstemp(dir = self.__builddir, prefix = prefix) - - def _mktemp(self, prefix = "tmp-"): - """Create a temporary file. - - This method simply calls _mkstemp() and closes the returned file - descriptor. - - The absolute path to the temporary file is returned. - - Note, this method should only be called after mount() has been called. - - prefix -- a prefix which should be used when creating the file; - defaults to "tmp-". - - """ - - (f, path) = self._mkstemp(prefix) - os.close(f) - return path - - # # Actual implementation # @@ -658,64 +164,6 @@ class BaseImageCreator(object): raise CreatorError("Failed create build directory in %s: %s" % (self.tmpdir, msg)) - def get_cachedir(self, cachedir = None): - if self.cachedir: - return self.cachedir - - self.__ensure_builddir() - if cachedir: - self.cachedir = cachedir - else: - self.cachedir = self.__builddir + "/wic-cache" - fs.makedirs(self.cachedir) - return self.cachedir - - def __sanity_check(self): - """Ensure that the config we've been given is sane.""" - if not (kickstart.get_packages(self.ks) or - kickstart.get_groups(self.ks)): - raise CreatorError("No packages or groups specified") - - kickstart.convert_method_to_repo(self.ks) - - if not kickstart.get_repos(self.ks): - raise CreatorError("No repositories specified") - - def __write_fstab(self): - fstab_contents = self._get_fstab() - if fstab_contents: - fstab = open(self._instroot + "/etc/fstab", "w") - fstab.write(fstab_contents) - fstab.close() - - def __create_minimal_dev(self): - """Create a minimal /dev so that we don't corrupt the host /dev""" - origumask = os.umask(0000) - devices = (('null', 1, 3, 0666), - ('urandom',1, 9, 0666), - ('random', 1, 8, 0666), - ('full', 1, 7, 0666), - ('ptmx', 5, 2, 0666), - ('tty', 5, 0, 0666), - ('zero', 1, 5, 0666)) - - links = (("/proc/self/fd", "/dev/fd"), - ("/proc/self/fd/0", "/dev/stdin"), - ("/proc/self/fd/1", "/dev/stdout"), - ("/proc/self/fd/2", "/dev/stderr")) - - for (node, major, minor, perm) in devices: - if not os.path.exists(self._instroot + "/dev/" + node): - os.mknod(self._instroot + "/dev/" + node, - perm | stat.S_IFCHR, - os.makedev(major,minor)) - - for (src, dest) in links: - if not os.path.exists(self._instroot + dest): - os.symlink(src, self._instroot + dest) - - os.umask(origumask) - def __setup_tmpdir(self): if not self.enabletmpfs: return @@ -789,338 +237,6 @@ class BaseImageCreator(object): self.__clean_tmpdir() - def __is_excluded_pkg(self, pkg): - if pkg in self._excluded_pkgs: - self._excluded_pkgs.remove(pkg) - return True - - for xpkg in self._excluded_pkgs: - if xpkg.endswith('*'): - if pkg.startswith(xpkg[:-1]): - return True - elif xpkg.startswith('*'): - if pkg.endswith(xpkg[1:]): - return True - - return None - - def __select_packages(self, pkg_manager): - skipped_pkgs = [] - for pkg in self._required_pkgs: - e = pkg_manager.selectPackage(pkg) - if e: - if kickstart.ignore_missing(self.ks): - skipped_pkgs.append(pkg) - elif self.__is_excluded_pkg(pkg): - skipped_pkgs.append(pkg) - else: - raise CreatorError("Failed to find package '%s' : %s" % - (pkg, e)) - - for pkg in skipped_pkgs: - msger.warning("Skipping missing package '%s'" % (pkg,)) - - def __select_groups(self, pkg_manager): - skipped_groups = [] - for group in self._required_groups: - e = pkg_manager.selectGroup(group.name, group.include) - if e: - if kickstart.ignore_missing(self.ks): - skipped_groups.append(group) - else: - raise CreatorError("Failed to find group '%s' : %s" % - (group.name, e)) - - for group in skipped_groups: - msger.warning("Skipping missing group '%s'" % (group.name,)) - - def __deselect_packages(self, pkg_manager): - for pkg in self._excluded_pkgs: - pkg_manager.deselectPackage(pkg) - - def __localinst_packages(self, pkg_manager): - for rpm_path in self._get_local_packages(): - pkg_manager.installLocal(rpm_path) - - def __preinstall_packages(self, pkg_manager): - if not self.ks: - return - - self._preinstall_pkgs = kickstart.get_pre_packages(self.ks) - 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('/'): - 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 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 - - # try to retrieve rpm file - (url, proxies) = pkg_manager.package_url(item) - if not url: - msger.warning("Can't get url from repo for %s" % item) - continue - fpath = os.path.join(self.cachedir, os.path.basename(url)) - if not os.path.exists(fpath): - # download pkgs - try: - fpath = grabber.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=None): - """Install packages into the install root. - - This function installs the packages listed in the supplied kickstart - into the install root. By default, the packages are installed from the - repository URLs specified in the kickstart. - - repo_urls -- a dict which maps a repository name to a repository URL; - if supplied, this causes any repository URLs specified in - the kickstart to be overridden. - - """ - - # initialize pkg list to install - if self.ks: - self.__sanity_check() - - self._required_pkgs = \ - kickstart.get_packages(self.ks, self._get_required_packages()) - self._excluded_pkgs = \ - kickstart.get_excluded(self.ks, self._get_excluded_packages()) - self._required_groups = kickstart.get_groups(self.ks) - else: - self._required_pkgs = None - self._excluded_pkgs = None - self._required_groups = None - - pkg_manager = self.get_pkg_manager() - pkg_manager.setup() - - if hasattr(self, 'install_pkgs') and self.install_pkgs: - if 'debuginfo' in self.install_pkgs: - pkg_manager.install_debuginfo = True - - for repo in kickstart.get_repos(self.ks, repo_urls): - (name, baseurl, mirrorlist, inc, exc, - proxy, proxy_username, proxy_password, debuginfo, - source, gpgkey, disable, ssl_verify, nocache, - cost, priority) = repo - - yr = pkg_manager.addRepository(name, baseurl, mirrorlist, proxy, - proxy_username, proxy_password, inc, exc, ssl_verify, - nocache, cost, priority) - - if kickstart.exclude_docs(self.ks): - rpm.addMacro("_excludedocs", "1") - rpm.addMacro("_dbpath", "/var/lib/rpm") - rpm.addMacro("__file_context_path", "%{nil}") - if kickstart.inst_langs(self.ks) != None: - rpm.addMacro("_install_langs", kickstart.inst_langs(self.ks)) - - try: - self.__preinstall_packages(pkg_manager) - self.__select_packages(pkg_manager) - self.__select_groups(pkg_manager) - self.__deselect_packages(pkg_manager) - self.__localinst_packages(pkg_manager) - - BOOT_SAFEGUARD = 256L * 1024 * 1024 # 256M - checksize = self._root_fs_avail - if checksize: - checksize -= BOOT_SAFEGUARD - if self.target_arch: - pkg_manager._add_prob_flags(rpm.RPMPROB_FILTER_IGNOREARCH) - pkg_manager.runInstall(checksize) - except CreatorError, e: - raise - except KeyboardInterrupt: - raise - else: - self._pkgs_content = pkg_manager.getAllContent() - self._pkgs_license = pkg_manager.getPkgsLicense() - self._pkgs_vcsinfo = pkg_manager.getVcsInfo() - self.__attachment_packages(pkg_manager) - finally: - 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 - try: - for f in os.listdir(lvmdir): - os.unlink(lvmdir + "/" + f) - except: - pass - - def postinstall(self): - self.copy_attachment() - - def __run_post_scripts(self): - msger.info("Running scripts ...") - if os.path.exists(self._instroot + "/tmp"): - shutil.rmtree(self._instroot + "/tmp") - os.mkdir (self._instroot + "/tmp", 0755) - for s in kickstart.get_post_scripts(self.ks): - (fd, path) = tempfile.mkstemp(prefix = "ks-script-", - dir = self._instroot + "/tmp") - - s.script = s.script.replace("\r", "") - os.write(fd, s.script) - os.close(fd) - os.chmod(path, 0700) - - env = self._get_post_scripts_env(s.inChroot) - - if not s.inChroot: - preexec = None - script = path - else: - preexec = self._chroot - script = "/tmp/" + os.path.basename(path) - - try: - try: - subprocess.call([s.interp, script], - preexec_fn = preexec, - env = env, - stdout = sys.stdout, - stderr = sys.stderr) - except OSError, (err, msg): - raise CreatorError("Failed to execute %%post script " - "with '%s' : %s" % (s.interp, msg)) - finally: - os.unlink(path) - - def __save_repo_keys(self, repodata): - if not repodata: - return None - - gpgkeydir = "/etc/pki/rpm-gpg" - fs.makedirs(self._instroot + gpgkeydir) - for repo in repodata: - if repo["repokey"]: - repokey = gpgkeydir + "/RPM-GPG-KEY-%s" % repo["name"] - shutil.copy(repo["repokey"], self._instroot + repokey) - - def configure(self, repodata = None): - """Configure the system image according to the kickstart. - - This method applies the (e.g. keyboard or network) configuration - specified in the kickstart and executes the kickstart %post scripts. - - If necessary, it also prepares the image to be bootable by e.g. - creating an initrd and bootloader configuration. - - """ - ksh = self.ks.handler - - msger.info('Applying configurations ...') - try: - kickstart.LanguageConfig(self._instroot).apply(ksh.lang) - kickstart.KeyboardConfig(self._instroot).apply(ksh.keyboard) - kickstart.TimezoneConfig(self._instroot).apply(ksh.timezone) - #kickstart.AuthConfig(self._instroot).apply(ksh.authconfig) - kickstart.FirewallConfig(self._instroot).apply(ksh.firewall) - kickstart.RootPasswordConfig(self._instroot).apply(ksh.rootpw) - kickstart.UserConfig(self._instroot).apply(ksh.user) - kickstart.ServicesConfig(self._instroot).apply(ksh.services) - kickstart.XConfig(self._instroot).apply(ksh.xconfig) - kickstart.NetworkConfig(self._instroot).apply(ksh.network) - kickstart.RPMMacroConfig(self._instroot).apply(self.ks) - kickstart.DesktopConfig(self._instroot).apply(ksh.desktop) - self.__save_repo_keys(repodata) - kickstart.MoblinRepoConfig(self._instroot).apply(ksh.repo, repodata, self.repourl) - except: - msger.warning("Failed to apply configuration to image") - raise - - self._create_bootconfig() - self.__run_post_scripts() - - def launch_shell(self, launch): - """Launch a shell in the install root. - - This method is launches a bash shell chroot()ed in the install root; - this can be useful for debugging. - - """ - if launch: - msger.info("Launching shell. Exit to continue.") - subprocess.call(["/bin/bash"], preexec_fn = self._chroot) - - def do_genchecksum(self, image_name): - if not self._genchecksum: - return - - md5sum = misc.get_md5sum(image_name) - with open(image_name + ".md5sum", "w") as f: - f.write("%s %s" % (md5sum, os.path.basename(image_name))) - self.outimage.append(image_name+".md5sum") - - def package(self, destdir = "."): - """Prepares the created image for final delivery. - - In its simplest form, this method merely copies the install root to the - supplied destination directory; other subclasses may choose to package - the image by e.g. creating a bootable ISO containing the image and - bootloader configuration. - - destdir -- the directory into which the final image should be moved; - this defaults to the current directory. - - """ - self._stage_final_image() - - if not os.path.exists(destdir): - fs.makedirs(destdir) - - if self._recording_pkgs: - self._save_recording_pkgs(destdir) - - # For image formats with two or multiple image files, it will be - # better to put them under a directory - if self.image_format in ("raw", "vmdk", "vdi", "nand", "mrstnand"): - destdir = os.path.join(destdir, "%s-%s" \ - % (self.name, self.image_format)) - msger.debug("creating destination dir: %s" % destdir) - fs.makedirs(destdir) - - # Ensure all data is flushed to _outdir - runner.quiet('sync') - - misc.check_space_pre_cp(self._outdir, destdir) - for f in os.listdir(self._outdir): - shutil.move(os.path.join(self._outdir, f), - os.path.join(destdir, f)) - self.outimage.append(os.path.join(destdir, f)) - self.do_genchecksum(os.path.join(destdir, f)) def print_outimage_info(self): msg = "The new image can be found here:\n" @@ -1129,135 +245,3 @@ class BaseImageCreator(object): msg += ' %s\n' % os.path.abspath(file) msger.info(msg) - - def check_depend_tools(self): - for tool in self._dep_checks: - fs.find_binary_path(tool) - - def package_output(self, image_format, destdir = ".", package="none"): - if not package or package == "none": - return - - destdir = os.path.abspath(os.path.expanduser(destdir)) - (pkg, comp) = os.path.splitext(package) - if comp: - comp=comp.lstrip(".") - - if pkg == "tar": - if comp: - dst = "%s/%s-%s.tar.%s" %\ - (destdir, self.name, image_format, comp) - else: - dst = "%s/%s-%s.tar" %\ - (destdir, self.name, image_format) - - msger.info("creating %s" % dst) - tar = tarfile.open(dst, "w:" + comp) - - for file in self.outimage: - msger.info("adding %s to %s" % (file, dst)) - tar.add(file, - arcname=os.path.join("%s-%s" \ - % (self.name, image_format), - os.path.basename(file))) - if os.path.isdir(file): - shutil.rmtree(file, ignore_errors = True) - else: - os.remove(file) - - tar.close() - - '''All the file in outimage has been packaged into tar.* file''' - self.outimage = [dst] - - def release_output(self, config, destdir, release): - """ Create release directory and files - """ - - def _rpath(fn): - """ release path """ - return os.path.join(destdir, fn) - - outimages = self.outimage - - # new ks - new_kspath = _rpath(self.name+'.ks') - with open(config) as fr: - with open(new_kspath, "w") as wf: - # When building a release we want to make sure the .ks - # file generates the same build even when --release not used. - wf.write(fr.read().replace("@BUILD_ID@", release)) - outimages.append(new_kspath) - - # save log file, logfile is only available in creator attrs - if hasattr(self, 'logfile') and not self.logfile: - log_path = _rpath(self.name + ".log") - # touch the log file, else outimages will filter it out - with open(log_path, 'w') as wf: - wf.write('') - msger.set_logfile(log_path) - outimages.append(_rpath(self.name + ".log")) - - # rename iso and usbimg - for f in os.listdir(destdir): - if f.endswith(".iso"): - newf = f[:-4] + '.img' - elif f.endswith(".usbimg"): - newf = f[:-7] + '.img' - else: - continue - os.rename(_rpath(f), _rpath(newf)) - outimages.append(_rpath(newf)) - - # generate MD5SUMS - with open(_rpath("MD5SUMS"), "w") as wf: - for f in os.listdir(destdir): - if f == "MD5SUMS": - continue - - if os.path.isdir(os.path.join(destdir, f)): - continue - - md5sum = misc.get_md5sum(_rpath(f)) - # There needs to be two spaces between the sum and - # filepath to match the syntax with md5sum. - # This way also md5sum -c MD5SUMS can be used by users - wf.write("%s *%s\n" % (md5sum, f)) - - outimages.append("%s/MD5SUMS" % destdir) - - # Filter out the nonexist file - for fp in outimages[:]: - if not os.path.exists("%s" % fp): - outimages.remove(fp) - - def copy_kernel(self): - """ Copy kernel files to the outimage directory. - NOTE: This needs to be called before unmounting the instroot. - """ - - if not self._need_copy_kernel: - return - - if not os.path.exists(self.destdir): - os.makedirs(self.destdir) - - for kernel in glob.glob("%s/boot/vmlinuz-*" % self._instroot): - kernelfilename = "%s/%s-%s" % (self.destdir, - self.name, - os.path.basename(kernel)) - msger.info('copy kernel file %s as %s' % (os.path.basename(kernel), - kernelfilename)) - 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) diff --git a/scripts/lib/mic/imager/direct.py b/scripts/lib/mic/imager/direct.py index 7e2b63a37c..93f0cd9e6c 100644 --- a/scripts/lib/mic/imager/direct.py +++ b/scripts/lib/mic/imager/direct.py @@ -54,14 +54,14 @@ class DirectImageCreator(BaseImageCreator): def __init__(self, oe_builddir, image_output_dir, rootfs_dir, bootimg_dir, kernel_dir, native_sysroot, hdddir, staging_data_dir, - creatoropts=None, pkgmgr=None, compress_image=None, + creatoropts=None, compress_image=None, generate_bmap=None, fstab_entry="uuid"): """ Initialize a DirectImageCreator instance. This method takes the same arguments as ImageCreator.__init__() """ - BaseImageCreator.__init__(self, creatoropts, pkgmgr) + BaseImageCreator.__init__(self, creatoropts) self.__instimage = None self.__imgdir = None |