def create_runtime(self, outfile="/var/tmp/squashfs.img", compression="xz", compressargs=[], size=2): # make live rootfs image - must be named "LiveOS/rootfs.img" for dracut workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") if size: fssize = size * (1024 * 1024 * 1024 ) # 2GB sparse file compresses down to nothin' else: fssize = None # Let mkext4img figure out the needed size os.makedirs(joinpaths(workdir, "LiveOS")) imgutils.mkext4img(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), label="Anaconda", size=fssize) # Reset selinux context on new rootfs with imgutils.LoopDev(joinpaths(workdir, "LiveOS/rootfs.img")) as loopdev: with imgutils.Mount(loopdev) as mnt: cmd = [ "setfiles", "-e", "/proc", "-e", "/sys", "-e", "/dev", "/etc/selinux/targeted/contexts/files/file_contexts", "/" ] runcmd(cmd, root=mnt) # squash the live rootfs and clean up workdir imgutils.mksquashfs(workdir, outfile, compression, compressargs) remove(workdir)
def generate_module_info(moddir, outfile=None): def module_desc(mod): output = runcmd_output(["modinfo", "-F", "description", mod]) return output.strip() def read_module_set(name): return set(l.strip() for l in open(joinpaths(moddir, name)) if ".ko" in l) modsets = { 'scsi': read_module_set("modules.block"), 'eth': read_module_set("modules.networking") } modinfo = list() for root, dirs, files in os.walk(moddir): for modtype, modset in modsets.items(): for mod in modset.intersection(files): # modules in this dir (name, ext) = os.path.splitext(mod) # foo.ko -> (foo, .ko) desc = module_desc(joinpaths(root, mod)) or "%s driver" % name modinfo.append(dict(name=name, type=modtype, desc=desc)) out = open(outfile or joinpaths(moddir, "module-info"), "w") out.write("Version 0\n") for mod in sorted(modinfo, key=lambda m: m.get('name')): out.write('{name}\n\t{type}\n\t"{desc:.65}"\n'.format(**mod))
def findkernels(root="/", kdir="boot"): # To find possible flavors, awk '/BuildKernel/ { print $4 }' kernel.spec flavors = ('debug', 'PAE', 'PAEdebug', 'smp', 'xen', 'lpae', 'tegra') kre = re.compile(r"vmlinuz-(?P<version>.+?\.(?P<arch>[a-z0-9_]+)" r"(\.(?P<flavor>{0}))?)$".format("|".join(flavors))) kernels = [] bootfiles = os.listdir(joinpaths(root, kdir)) for f in bootfiles: match = kre.match(f) if match: kernel = DataHolder(path=joinpaths(kdir, f)) kernel.update(match.groupdict()) # sets version, arch, flavor kernels.append(kernel) # look for associated initrd/initramfs/etc. for kernel in kernels: for f in bootfiles: if f.endswith('-' + kernel.version + '.img'): imgtype, rest = f.split('-', 1) # special backwards-compat case if imgtype == 'initramfs': imgtype = 'initrd' kernel[imgtype] = DataHolder(path=joinpaths(kdir, f)) logger.debug("kernels=%s" % kernels) return kernels
def rebuild_initrds(self, add_args=[], backup="", prefix=""): '''Rebuild all the initrds in the tree. If backup is specified, each initrd will be renamed with backup as a suffix before rebuilding. If backup is empty, the existing initrd files will be overwritten. If suffix is specified, the existing initrd is untouched and a new image is built with the filename "${prefix}-${kernel.version}.img" ''' dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + add_args if not backup: dracut.append("--force") # Hush some dracut warnings. TODO: bind-mount proc in place? open(joinpaths(self.vars.inroot,"/proc/modules"),"w") for kernel in self.kernels: if prefix: idir = os.path.dirname(kernel.initrd.path) outfile = joinpaths(idir, prefix+'-'+kernel.version+'.img') else: outfile = kernel.initrd.path logger.info("rebuilding %s", outfile) if backup: initrd = joinpaths(self.vars.inroot, outfile) os.rename(initrd, initrd + backup) cmd = dracut + [outfile, kernel.version] runcmd(cmd, root=self.vars.inroot) os.unlink(joinpaths(self.vars.inroot,"/proc/modules"))
def findkernels(root="/", kdir="boot"): # To find possible flavors, awk '/BuildKernel/ { print $4 }' kernel.spec flavors = ('debug', 'PAE', 'PAEdebug', 'smp', 'xen', 'lpae', 'tegra') kre = re.compile(r"vmlinuz-(?P<version>.+?\.(?P<arch>[a-z0-9_]+)" r"(\.(?P<flavor>{0}))?)$".format("|".join(flavors))) kernels = [] bootfiles = os.listdir(joinpaths(root, kdir)) for f in bootfiles: match = kre.match(f) if match: kernel = DataHolder(path=joinpaths(kdir, f)) kernel.update(match.groupdict()) # sets version, arch, flavor kernels.append(kernel) # look for associated initrd/initramfs/etc. for kernel in kernels: for f in bootfiles: if f.endswith('-'+kernel.version+'.img'): imgtype, rest = f.split('-',1) # special backwards-compat case if imgtype == 'initramfs': imgtype = 'initrd' kernel[imgtype] = DataHolder(path=joinpaths(kdir, f)) logger.debug("kernels=%s" % kernels) return kernels
def generate_module_data(self): root = self.vars.root moddir = joinpaths(root, "lib/modules/") for kver in os.listdir(moddir): ksyms = joinpaths(root, "boot/System.map-%s" % kver) logger.info("doing depmod and module-info for %s", kver) runcmd(["depmod", "-a", "-F", ksyms, "-b", root, kver]) generate_module_info(moddir+kver, outfile=moddir+"module-info")
def postinstall(self): '''Do some post-install setup work with runtime-postinstall.tmpl''' # copy configdir into runtime root beforehand configdir = joinpaths(self._runner.templatedir,"config_files") configdir_path = "tmp/config_files" fullpath = joinpaths(self.vars.root, configdir_path) if os.path.exists(fullpath): remove(fullpath) copytree(configdir, fullpath) self._runner.run("runtime-postinstall.tmpl", configdir=configdir_path)
def postinstall(self): '''Do some post-install setup work with runtime-postinstall.tmpl''' # copy configdir into runtime root beforehand configdir = joinpaths(self._runner.templatedir, "config_files") configdir_path = "tmp/config_files" fullpath = joinpaths(self.vars.root, configdir_path) if os.path.exists(fullpath): remove(fullpath) copytree(configdir, fullpath) self._runner.run("runtime-postinstall.tmpl", configdir=configdir_path)
def create_runtime(self, outfile="/var/tmp/squashfs.img", compression="xz", compressargs=[], size=2): # make live rootfs image - must be named "LiveOS/rootfs.img" for dracut workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") os.makedirs(joinpaths(workdir, "LiveOS")) imgutils.mkrootfsimg(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), "Anaconda", size=size) # squash the live rootfs and clean up workdir imgutils.mksquashfs(workdir, outfile, compression, compressargs) remove(workdir)
def generate_module_data(self): root = self.vars.root moddir = joinpaths(root, "lib/modules/") # Generate_module_data creates a file called "module-info" in this # directory. If we don't do something to exclude this file, depmod will fail # on the second path of this loop. Let's check to see if kver is a directory # before generating module info from it. for kver in os.listdir(moddir): if os.path.isdir(kver): ksyms = joinpaths(root, "boot/System.map-%s" % kver) logger.info("doing depmod and module-info for %s", kver) runcmd(["depmod", "-a", "-F", ksyms, "-b", root, kver]) generate_module_info(moddir+kver, outfile=moddir+"module-info")
def generate_module_data(self): root = self.vars.root moddir = joinpaths(root, "lib/modules/") # Generate_module_data creates a file called "module-info" in this # directory. If we don't do something to exclude this file, depmod will fail # on the second path of this loop. Let's check to see if kver is a directory # before generating module info from it. for kver in os.listdir(moddir): if os.path.isdir(kver): ksyms = joinpaths(root, "boot/System.map-%s" % kver) logger.info("doing depmod and module-info for %s", kver) runcmd(["depmod", "-a", "-F", ksyms, "-b", root, kver]) generate_module_info(moddir + kver, outfile=moddir + "module-info")
def writepkgsizes(self, pkgsizefile): '''debugging data: write a big list of pkg sizes''' fobj = open(pkgsizefile, "w") getsize = lambda f: os.lstat(f).st_size if os.path.exists(f) else 0 for p in sorted(self.yum.doPackageLists(pkgnarrow='installed').installed): pkgsize = sum(getsize(joinpaths(self.vars.root,f)) for f in p.filelist) fobj.write("{0.name}.{0.arch}: {1}\n".format(p, pkgsize))
def hardlink(self, src, dest): ''' hardlink SRC DEST Create a hardlink at DEST which is linked to SRC. ''' if isdir(self._out(dest)): dest = joinpaths(dest, basename(src)) os.link(self._out(src), self._out(dest))
def writepkglists(self, pkglistdir): '''debugging data: write out lists of package contents''' if not os.path.isdir(pkglistdir): os.makedirs(pkglistdir) for pkgobj in self.yum.doPackageLists(pkgnarrow='installed').installed: with open(joinpaths(pkglistdir, pkgobj.name), "w") as fobj: for fname in pkgobj.filelist + pkgobj.dirlist: fobj.write("{0}\n".format(fname))
def rglob(pathname, root="/", fatal=False): seen = set() rootlen = len(root)+1 for f in glob.iglob(joinpaths(root, pathname)): if f not in seen: seen.add(f) yield f[rootlen:] # remove the root to produce relative path if fatal and not seen: raise IOError, "nothing matching %s in %s" % (pathname, root)
def dracut_hooks_path(self): """ Return the path to the lorax dracut hooks scripts Use the configured share dir if it is setup, otherwise default to /usr/share/lorax/dracut_hooks """ if self.templatedir: return joinpaths(self.templatedir, "dracut_hooks") else: return "/usr/share/lorax/dracut_hooks"
def create_runtime(self, outfile="/var/tmp/squashfs.img", compression="xz", compressargs=[], size=2): # make live rootfs image - must be named "LiveOS/rootfs.img" for dracut workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") if size: fssize = size * (1024*1024*1024) # 2GB sparse file compresses down to nothin' else: fssize = None # Let mkext4img figure out the needed size os.makedirs(joinpaths(workdir, "LiveOS")) imgutils.mkext4img(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), label="Anaconda", size=fssize) # Reset selinux context on new rootfs with imgutils.LoopDev( joinpaths(workdir, "LiveOS/rootfs.img") ) as loopdev: with imgutils.Mount(loopdev) as mnt: cmd = [ "setfiles", "-e", "/proc", "-e", "/sys", "-e", "/dev", "/etc/selinux/targeted/contexts/files/file_contexts", "/"] runcmd(cmd, root=mnt) # squash the live rootfs and clean up workdir imgutils.mksquashfs(workdir, outfile, compression, compressargs) remove(workdir)
def copy_dracut_hooks(self, hooks): """ Copy the hook scripts in hooks into the installroot's /tmp/ and return a list of commands to pass to dracut when creating the initramfs hooks is a list of tuples with the name of the hook script and the target dracut hook directory (eg. [("99anaconda-copy-ks.sh", "/lib/dracut/hooks/pre-pivot")]) """ dracut_commands = [] for hook_script, dracut_path in hooks: src = joinpaths(self.dracut_hooks_path, hook_script) if not os.path.exists(src): logger.error("Missing lorax dracut hook script %s" % (src)) continue dst = joinpaths(self.vars.inroot, "/tmp/", hook_script) copy2(src, dst) dracut_commands += ["--include", joinpaths("/tmp/", hook_script), dracut_path] return dracut_commands
def hardlink(self, src, dest): ''' hardlink SRC DEST Create a hardlink at DEST which is linked to SRC. ''' if isdir(self._out(dest)): dest = joinpaths(dest, basename(src)) if os.path.exists(self._out(dest)): logger.debug("file %s exists...removing before linking" % (self._out(dest))) os.remove(self._out(dest)) os.link(self._out(src), self._out(dest))
def rebuild_initrds(self, add_args=[], backup="", prefix=""): '''Rebuild all the initrds in the tree. If backup is specified, each initrd will be renamed with backup as a suffix before rebuilding. If backup is empty, the existing initrd files will be overwritten. If suffix is specified, the existing initrd is untouched and a new image is built with the filename "${prefix}-${kernel.version}.img" ''' dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + add_args if not backup: dracut.append("--force") kernels = [ kernel for kernel in self.kernels if hasattr(kernel, "initrd") ] if not kernels: raise Exception("No initrds found, cannot rebuild_initrds") # Hush some dracut warnings. TODO: bind-mount proc in place? open(joinpaths(self.vars.inroot, "/proc/modules"), "w") for kernel in kernels: if prefix: idir = os.path.dirname(kernel.initrd.path) outfile = joinpaths(idir, prefix + '-' + kernel.version + '.img') else: outfile = kernel.initrd.path logger.info("rebuilding %s", outfile) if backup: initrd = joinpaths(self.vars.inroot, outfile) os.rename(initrd, initrd + backup) cmd = dracut + [outfile, kernel.version] runcmd(cmd, root=self.vars.inroot) # ppc64 cannot boot images > 32MiB, check size and warn if self.vars.arch.basearch in ( "ppc64", "ppc64le") and os.path.exists(outfile): st = os.stat(outfile) if st.st_size > 32 * 1024 * 1024: logging.warning("ppc64 initrd %s is > 32MiB", outfile) os.unlink(joinpaths(self.vars.inroot, "/proc/modules"))
def generate_module_info(moddir, outfile=None): def module_desc(mod): output = runcmd_output(["modinfo", "-F", "description", mod]) return output.strip() def read_module_set(name): return set(l.strip() for l in open(joinpaths(moddir,name)) if ".ko" in l) modsets = {'scsi':read_module_set("modules.block"), 'eth':read_module_set("modules.networking")} modinfo = list() for root, dirs, files in os.walk(moddir): for modtype, modset in modsets.items(): for mod in modset.intersection(files): # modules in this dir (name, ext) = os.path.splitext(mod) # foo.ko -> (foo, .ko) desc = module_desc(joinpaths(root,mod)) or "%s driver" % name modinfo.append(dict(name=name, type=modtype, desc=desc)) out = open(outfile or joinpaths(moddir,"module-info"), "w") out.write("Version 0\n") for mod in sorted(modinfo, key=lambda m: m.get('name')): out.write('{name}\n\t{type}\n\t"{desc:.65}"\n'.format(**mod))
def rebuild_initrds(self, add_args=[], backup="", prefix=""): '''Rebuild all the initrds in the tree. If backup is specified, each initrd will be renamed with backup as a suffix before rebuilding. If backup is empty, the existing initrd files will be overwritten. If suffix is specified, the existing initrd is untouched and a new image is built with the filename "${prefix}-${kernel.version}.img" ''' dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + add_args if not backup: dracut.append("--force") kernels = [kernel for kernel in self.kernels if hasattr(kernel, "initrd")] if not kernels: raise Exception("No initrds found, cannot rebuild_initrds") # Hush some dracut warnings. TODO: bind-mount proc in place? open(joinpaths(self.vars.inroot,"/proc/modules"),"w") for kernel in kernels: if prefix: idir = os.path.dirname(kernel.initrd.path) outfile = joinpaths(idir, prefix+'-'+kernel.version+'.img') else: outfile = kernel.initrd.path logger.info("rebuilding %s", outfile) if backup: initrd = joinpaths(self.vars.inroot, outfile) os.rename(initrd, initrd + backup) cmd = dracut + [outfile, kernel.version] runcmd(cmd, root=self.vars.inroot) # ppc64 cannot boot images > 32MiB, check size and warn if self.vars.arch.basearch in ("ppc64", "ppc64le") and os.path.exists(outfile): st = os.stat(outfile) if st.st_size > 32 * 1024 * 1024: logging.warning("ppc64 initrd %s is > 32MiB", outfile) os.unlink(joinpaths(self.vars.inroot,"/proc/modules"))
def _in(self, path): return joinpaths(self.inroot, path)
def implantisomd5(self): for section, data in self.treeinfo_data.items(): if 'boot.iso' in data: iso = joinpaths(self.vars.outroot, data['boot.iso']) runcmd(["implantisomd5", iso])
def _out(self, path): return joinpaths(self.outroot, path)
def read_module_set(name): return set(l.strip() for l in open(joinpaths(moddir, name)) if ".ko" in l)
def read_module_set(name): return set(l.strip() for l in open(joinpaths(moddir,name)) if ".ko" in l)