def recoverUbootConfig(self): with MountContext(self.flashDev, log=self.log) as ctx: dst = os.path.join(ctx.dir, 'boot-config') with open(dst, "w") as fd: self.log.debug("+ cat > %s", dst) fd.write(self.platform.bootConfigEnv) return 0
def installBootConfig(self): try: dev = self.blkidParts['ONL-BOOT'] except IndexError as ex: self.log.warn("cannot find ONL-BOOT partition (maybe raw?) : %s", str(ex)) return 1 self.log.info("Installing boot-config to %s", dev.device) basename = 'boot-config' with MountContext(dev.device, log=self.log) as ctx: dst = os.path.join(ctx.dir, basename) if not self.installerCopy(basename, dst, True): return with open(dst) as fd: buf = fd.read() ecf = buf.encode('base64', 'strict').strip() if self.im.grub and self.im.grubEnv is not None: setattr(self.im.grubEnv, 'boot_config_default', ecf) if self.im.uboot and self.im.ubootEnv is not None: setattr(self.im.ubootEnv, 'boot-config-default', ecf) return 0
def installGrubCfg(self): dev = self.blkidParts['ONL-BOOT'] self.log.info("Installing grub.cfg to %s", dev.device) ctx = {} kernel = self.im.platformConf['grub']['kernel'] ctx['kernel'] = kernel['='] if type(kernel) == dict else kernel ctx['args'] = self.im.platformConf['grub']['args'] ctx['platform'] = self.im.installerConf.installer_platform ctx['serial'] = self.im.platformConf['grub']['serial'] ctx['boot_menu_entry'] = sysconfig.installer.menu_name ctx['boot_loading_name'] = sysconfig.installer.os_name if self.isUEFI: ctx['onie_boot_uuid'] = self.espFsUuid else: ctx['onie_boot_uuid'] = "" cf = GRUB_TPL % ctx with MountContext(dev.device, log=self.log) as ctx: d = os.path.join(ctx.dir, "grub") if not os.path.exists(d): self.makedirs(d) dst = os.path.join(ctx.dir, 'grub/grub.cfg') with open(dst, "w") as fd: fd.write(cf) return 0
def installLoader(self): kernels = [] for f in set(os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()): if 'kernel' in f: kernels.append(f) initrd = None for f in set(os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()): for i in sysconfig.installer.grub: if f == i: initrd = i break dev = self.blkidParts['ONL-BOOT'] self.log.info("Installing kernel to %s", dev.device) with MountContext(dev.device, log=self.log) as ctx: def _cp(b, dstname=None): if dstname is None: dstname = b dst = os.path.join(ctx.dir, dstname) self.installerCopy(b, dst, optional=True) [_cp(e) for e in kernels] _cp(initrd, "%s.cpio.gz" % self.im.installerConf.installer_platform) return 0
def runGrub(self): try: dev = self.blkid['ONL-BOOT'].device except KeyError: pass if dev is None: self.log.error("cannot find GRUB partition %s", dev) return 1 initrd = self.pc['grub']['initrd'] if type(initrd) == dict: initrd = initrd['='] parts = [p for p in self.pm.mounts if p.device == dev] if parts: grubDir = parts[0] self.log.debug("found loader device %s mounted at %s", dev, grubDir) p = os.path.join(grubDir, initrd) if not os.path.exists(p): self.log.error("cannot find initrd %s", p) return 1 self.log.debug("found loader initrd at %s", p) return self._runInitrdShell(p) with MountContext(dev, log=self.log) as ctx: p = os.path.join(ctx.dir, initrd) if not os.path.exists(p): self.log.error("cannot find initrd %s:%s", dev, p) return 1 self.log.debug("found loader initrd at %s:%s", dev, p) return self._runInitrdShell(p)
def installLoader(self): loaderBasename = None for c in sysconfig.installer.fit: if self.installerExists(c): loaderBasename = c break if not loaderBasename: self.log.error("The platform loader file is missing.") return 1 self.log.info("Installing the ONL loader from %s...", loaderBasename) if self.rawLoaderDevice is not None: self.log.info("Installing ONL loader %s --> %s...", loaderBasename, self.rawLoaderDevice) self.installerDd(loaderBasename, self.rawLoaderDevice) return 0 dev = self.blkidParts['ONL-BOOT'] self.log.info("Installing ONL loader %s --> %s:%s...", loaderBasename, dev.device, loaderBasename) with MountContext(dev.device, log=self.log) as ctx: dst = os.path.join(ctx.dir, "%s.itb" % self.im.installerConf.installer_platform) self.installerCopy(loaderBasename, dst) return 0
def recoverGrubConfig(self): with MountContext(label='ONIE-BOOT', log=self.log) as octx: pat = "%s/onie/initrd.img*" % octx.dir l = glob.glob(pat) if not l: raise ValueError("cannot find ONIE initrd") initrd = l[0] with InitrdContext(initrd=initrd, log=self.log) as ictx: # copy the Switch Light grubenv out of its GRUB directory dst = os.path.join(ictx.dir, "tmp/grubenv") with MountContext(label='SL-BOOT', log=self.log) as sctx: src = os.path.join(sctx.dir, "grub/grubenv") self.copy2(src, dst) # use the ONIE runtime's GRUB tools to read it grubEnv = ChrootGrubEnv(ictx.dir, mounted=True, bootDir="/", path="/tmp/grubenv", log=self.log) buf = getattr(grubEnv, 'boot_config_default', None) if buf is None: raise ValueError("Cannot recover filesystem(s) -- missing boot_config_default.") if buf == "": raise ValueError("Cannot recover filesystem(s) -- empty boot_config_default.") try: buf = buf.decode('base64', 'strict') except binascii.Error: raise ValueError("Cannot recover filesystem(s) -- corrupted boot_config_default.") if "SWI=flash" in buf: raise ValueError("Cannot recover filesystem(s) -- local SWI cannot be recovered.") with MountContext(label='FLASH', log=self.log) as ctx: dst = os.path.join(ctx.dir, 'boot-config') with open(dst, "w") as fd: self.log.debug("+ cat > %s", dst) fd.write(buf) return 0
def restoreConfig(self, dev): """Restore the saved ONL-CONFIG.""" archive, self.configArchive = self.configArchive, None self.log.info("restoring ONL-CONFIG archive %s to %s", archive, dev) with MountContext(dev, log=self.log) as ctx: self.log.debug("+ tar -zxf %s -C %s", archive, ctx.dir) pipe = subprocess.Popen(["tar", "-zxf", archive,], cwd=ctx.dir) pipe.communicate() code = pipe.wait() if code: raise SystemExit("backup of ONL-CONFIG failed") self.unlink(archive)
def backupConfig(self, dev): """Back up the ONL-CONFIG partition for later restore.""" self.configArchive = tempfile.mktemp(prefix="onl-config-", suffix=".tar.gz") self.log.info("backing up ONL-CONFIG partition %s to %s", dev, self.configArchive) with MountContext(dev, log=self.log) as ctx: self.log.debug("+ tar -zcf %s -C %s .", self.configArchive, ctx.dir) pipe = subprocess.Popen(["tar", "-zcf", self.configArchive, ".",], cwd=ctx.dir) pipe.communicate() code = pipe.wait() if code: raise SystemExit("backup of ONL-CONFIG failed")
def installLoader(self): ctx = {} kernel = self.im.platformConf['grub']['kernel'] ctx['kernel'] = kernel['='] if type(kernel) == dict else kernel ctx['args'] = self.im.platformConf['grub']['args'] ctx['platform'] = self.im.installerConf.installer_platform ctx['serial'] = self.im.platformConf['grub']['serial'] ctx['boot_menu_entry'] = sysconfig.installer.menu_name ctx['boot_loading_name'] = sysconfig.installer.os_name kernels = [] for f in set(os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()): if 'kernel' in f: kernels.append(f) initrd = None for f in set(os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist()): for i in sysconfig.installer.grub: if f == i: initrd = i break cf = GRUB_TPL % ctx self.log.info("Installing kernel") dev = self.blkidParts['ONL-BOOT'] with MountContext(dev.device, log=self.log) as ctx: def _cp(b, dstname=None): if dstname is None: dstname = b dst = os.path.join(ctx.dir, dstname) self.installerCopy(b, dst, optional=True) [_cp(e) for e in kernels] _cp(initrd, "%s.cpio.gz" % self.im.installerConf.installer_platform) d = os.path.join(ctx.dir, "grub") self.makedirs(d) dst = os.path.join(ctx.dir, 'grub/grub.cfg') with open(dst, "w") as fd: fd.write(cf) return 0
def installOnlConfig(self): try: dev = self.blkidParts['ONL-CONFIG'] except IndexError as ex: self.log.warn("cannot find ONL-CONFIG partition : %s", str(ex)) return 1 with MountContext(dev.device, log=self.log) as ctx: for f in self.zf.namelist(): d = 'config/' if f.startswith(d) and f != d: dst = os.path.join(ctx.dir, os.path.basename(f)) if not os.path.exists(dst): self.installerCopy(f, dst) return 0
def installGrubCfg(self): dev = self.blkidParts['ONL-BOOT'] self.log.info("Installing grub.cfg to %s", dev.device) ctx = {} kernel = self.im.platformConf['grub']['kernel'] ctx['kernel'] = kernel['='] if type(kernel) == dict else kernel ctx['args'] = self.im.platformConf['grub']['args'] ctx['platform'] = self.im.installerConf.installer_platform ctx['serial'] = self.im.platformConf['grub']['serial'] ctx['boot_menu_entry'] = sysconfig.installer.menu_name ctx['boot_loading_name'] = sysconfig.installer.os_name if self.isUEFI: ctx['set_root_para'] = "set root='(hd0,gpt1)'" ctx['set_search_para2'] = "--fs-uuid" ctx['set_save_entry_para'] = "" ctx['set_save_env_para'] = "" dev_UEFI = self.blkidParts['EFI System'] ctx['onie_boot'] = dev_UEFI.uuid ctx['set_chainloader_para'] = "/EFI/onie/grubx64.efi" else: ctx['set_root_para'] = "" ctx['set_search_para2'] = "--label" ctx['set_save_entry_para'] = "set saved_entry=\"0\"" ctx['set_save_env_para'] = "save_env saved_entry" ctx['onie_boot'] = "ONIE-BOOT" ctx['set_chainloader_para'] = "+1" cf = GRUB_TPL % ctx with MountContext(dev.device, log=self.log) as ctx: d = os.path.join(ctx.dir, "grub") if not os.path.exists(d): self.makedirs(d) dst = os.path.join(ctx.dir, 'grub/grub.cfg') with open(dst, "w") as fd: fd.write(cf) return 0
def installSwi(self): files = os.listdir(self.im.installerConf.installer_dir) + self.zf.namelist() swis = [x for x in files if x.endswith('.swi')] if not swis: self.log.info("No ONL Software Image available for installation.") self.log.info("Post-install ZTN installation will be required.") return if len(swis) > 1: self.log.warn("Multiple SWIs found in installer: %s", " ".join(swis)) return base = swis[0] self.log.info("Installing ONL Software Image (%s)...", base) dev = self.blkidParts['ONL-IMAGES'] with MountContext(dev.device, log=self.log) as ctx: dst = os.path.join(ctx.dir, base) self.installerCopy(base, dst) return 0
def mountCtx(self, device): return MountContext(device, chroot=self.chrootDir, fsType='ext4', log=self.log)
def __enter__(self): self.pm = ProcMountsParser() self.blkid = BlkidParser(log=self.log.getChild("blkid")) self.mtd = ProcMtdParser(log=self.log.getChild("mtd")) def _g(d): pat = os.path.join(d, "onie/initrd.img*") l = glob.glob(pat) if l: return l[0] return None # try to find a mounted, labeled partition try: dev = self.blkid['ONIE-BOOT'].device except IndexError: dev = None if dev is not None: self.log.debug("found ONIE boot device %s", dev) parts = [p for p in self.pm.mounts if p.device == dev] if parts: self.log.debug("found ONIE boot mounted at %s", parts[0].dir) initrd = _g(parts[0].dir) if initrd is None: raise ValueError("cannot find ONIE initrd on %s" % parts[0].dir) self.log.debug("found ONIE initrd at %s", initrd) with InitrdContext(initrd=initrd, log=self.log) as self.ictx: self.initrd = initrd self.initrdDir = self.ictx.dir self.ictx.detach() return self # else, try to mount the directory containing the initrd with MountContext(dev, log=self.log) as self.dctx: initrd = _g(self.dctx.dir) if initrd is None: raise ValueError("cannot find ONIE initrd on %s" % dev) self.onieDir = self.dctx.dir self.dctx.detach() self.log.debug("found ONIE initrd at %s", initrd) with InitrdContext(initrd=initrd, log=self.log) as self.ictx: self.initrd = initrd self.initrdDir = self.ictx.dir self.ictx.detach() return self raise ValueError("cannot find an ONIE initrd") # try to find onie initrd on a mounted fs (GRUB); # for ONIE images this is usually /mnt/onie-boot for part in self.pm.mounts: if not part.device.startswith('/dev/'): continue initrd = _g(part.dir) if initrd is None: self.log.debug("cannot find ONIE initrd on %s (%s)", part.device, part.dir) else: self.onieDir = part.dir self.log.debug("found ONIE initrd at %s", initrd) with InitrdContext(initrd=initrd, log=self.log) as self.ictx: self.initrd = initrd self.initrdDir = self.ictx.dir self.ictx.detach() return self # grovel through MTD devices (u-boot) parts = [p for p in self.mtd.parts if p.label == "onie"] if parts: part = parts[0] self.log.debug("found ONIE MTD device %s", part.charDevice or part.blockDevice) with UbootInitrdContext(part.blockDevice, log=self.log) as self.fctx: with InitrdContext(initrd=self.fctx.initrd, log=self.log) as self.ictx: self.initrd = self.fctx.initrd self.fctx.detach() self.initrdDir = self.ictx.dir self.ictx.detach() return self if self.mtd.mounts: raise ValueError("cannot find ONIE MTD device") raise ValueError("cannot find ONIE initrd")
def run(self): self.pm = ProcMountsParser() self.blkid = BlkidParser(log=self.log.getChild("blkid")) self.mtd = ProcMtdParser(log=self.log.getChild("mtd")) def _g(d): pat = os.path.join(d, "onie/initrd.img*") l = glob.glob(pat) if l: return l[0] return None # try to find a mounted, labeled partition try: dev = self.blkid['ONIE-BOOT'].device except IndexError: dev = None if dev is not None: self.log.debug("found ONIE boot device %s", dev) parts = [p for p in self.pm.mounts if p.device == dev] if parts: onieDir = parts[0] self.log.debug("found ONIE boot mounted at %s", onieDir) initrd = _g(onieDir) if initrd is None: self.log.warn("cannot find ONIE initrd on %s", onieDir) else: self.log.debug("found ONIE initrd at %s", initrd) return _runInitrdShell(initrd) with MountContext(dev, log=self.log) as ctx: initrd = _g(ctx.dir) if initrd is None: self.log.warn("cannot find ONIE initrd on %s", dev) else: self.log.debug("found ONIE initrd at %s", initrd) return self._runInitrdShell(initrd) self.log.warn("cannot find an ONIE initrd") return 1 # try to find onie initrd on a mounted fs (GRUB); # for ONIE images this is usually /mnt/onie-boot for part in self.pm.mounts: if not part.device.startswith('/dev/'): continue initrd = _g(part.dir) if initrd is None: self.log.debug("cannot find ONIE initrd on %s (%s)", part.device, part.dir) else: self.log.debug("found ONIE initrd at %s", initrd) return self._runInitrdShell(initrd) # grovel through MTD devices (u-boot) parts = [p for p in self.mtd.parts if p.label == "onie"] if parts: part = parts[0] self.log.debug("found ONIE MTD device %s", part.charDevice or part.blockDevice) return self._runFitShell(part.blockDevice) elif self.mtd.mounts: self.log.error("cannot find ONIE MTD device") return 1 self.log.error("cannot find ONIE initrd") return 1
def mountCtx(self, device, fsType='ext4'): return MountContext(device, fsType=fsType, log=self.log)
def runUboot(self): dev = self.pc['loader']['device'] self.log.info("found loader device %s", dev) parts = self.pc['installer'] bootPart = None bootPartno = None for idx, part in enumerate(self.pc['installer']): label, pdata = list(part.items())[0] if label == 'ONL-BOOT': bootPart = pdata bootPartno = idx + 1 break if bootPart is None: self.log.info("cannot find ONL-BOOT declaration") return 1 fmt = bootPart.get('format', 'ext2') if fmt == 'raw': bootDevice = dev + str(bootPartno) else: bootDevice = self.blkid['ONL-BOOT'].device # run from a raw partition if fmt == 'raw': self.log.info("found (raw) boot partition %s", bootDevice) return self._runFitShell(bootDevice) l = [] p = self.pc['flat_image_tree']['itb'] if type(p) == dict: p = p['='] if p not in l: l.append(p) p = self.platform.platform() + '.itb' if p not in l: l.append(p) p = 'onl-loader-fit.itb' if p not in l: l.append(p) self.log.info("looking for loader images %s", ", ".join(l)) # run from a file in a mounted filesystem parts = [p for p in self.pm.mounts if p.device == bootDevice] if parts: loaderDir = parts[0] self.log.debug("found loader device mounted at %s", loaderDir) for e in l: p = os.path.join(loaderDir, e) if os.path.exists(p): return self._runFitShell(p) self.log.error("cannot find an ITB") return 1 # run from a file in an umounted filesystem with MountContext(bootDevice, log=self.log) as ctx: self.log.info("found (%s) loader device %s", fmt, bootDevice) for e in l: p = os.path.join(ctx.dir, e) if os.path.exists(p): return self._runFitShell(p) self.log.error("cannot find an ITB") return 1