コード例 #1
0
    def upgradeBootLoader(self):
        """Upgrade the boot loader settings."""

        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))

        code = self.installGrubCfg()
        if code: return code

        return 0
コード例 #2
0
    def upgradeBootLoader(self):
        """Upgrade the boot loader settings as part of a loader upgrade."""

        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))

        # XXX boot-config (and saved boot-config) should be unchanged during loader upgrade

        code = self.installUbootEnv()
        if code: return code

        return 0
コード例 #3
0
    def run(self):

        self.platform = onl.platform.current.OnlPlatform()
        self.pc = self.platform.platform_config

        self.pm = ProcMountsParser()
        self.blkid = BlkidParser(log=self.log.getChild("blkid"))

        if 'grub' in self.pc:
            return self.runGrub()

        if 'flat_image_tree' in self.pc:
            return self.runUboot()

        self.log.error("invalid platform-config")
        return 1
コード例 #4
0
    def umountAny(self, device=None, label=None):
        p = ProcMountsParser()
        if label is not None:
            b = BlkidParser(log=self.log)
            for e in b.parts:
                if label == e.label:
                    device = e.device
                    break

        for m in p.mounts:
            if device is not None and device in m.device:
                try:
                    self.check_call(('umount', m.device,),
                                    vmode=self.V1)
                except CalledProcessError, what:
                    self.log.warn("cannot umount %s: %s",
                                  m.device, str(what))
コード例 #5
0
    def upgradeBootLoader(self):
        """Upgrade the boot loader settings."""

        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))

        code = self.findGpt()
        if code: return code

        if self.isUEFI:
            code = self.findEsp()
            if code: return code
            self.im.grubEnv.__dict__['espPart'] = self.espDevice
        else:
            self.im.grubEnv.__dict__['espPart'] = None

        code = self.installGrubCfg()
        if code: return code

        return 0
コード例 #6
0
    def findGpt(self):
        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))

        deviceOrLabel = self.im.platformConf['grub']['device']
        if deviceOrLabel.startswith('/dev'):
            tgtDevice, tgtLabel = deviceOrLabel, None
        else:
            tgtDevice, tgtLabel = None, deviceOrLabel

        # enumerate labeled partitions to try to identify
        # the boot device
        for part in self.blkidParts:
            dev, partno = part.splitDev()
            if tgtLabel is not None and tgtLabel == part.label:
                if not len(partno):
                    self.log.error("cannot use whole disk")
                    return 1
                if self.device is None:
                    self.device = dev
                else:
                    self.log.error("found multiple devices: %s, %s",
                                   dev, self.device)
                    return 1
            elif tgtDevice is not None and tgtDevice == dev:
                if not len(partno):
                    self.log.error("cannot use whole disk")
                    return 1
                if self.device is None:
                    self.device = dev
                else:
                    self.log.error("found multiple devices: %s, %s",
                                   dev, self.device)
                    return 1
        if self.device is None:
            self.log.error("cannot find an install device")
            return 1

        if not self.isUEFI:
            code = self.assertUnmounted()
            if code: return code

        # optionally back up a config partition
        # if it's on the boot device
        for part in self.blkidParts:
            dev, partno = part.splitDev()
            if dev == self.device and part.label == 'ONL-CONFIG':
                self.backupConfig(part.device)

        self.partedDevice = parted.getDevice(self.device)
        self.partedDisk = parted.newDisk(self.partedDevice)

        # enumerate the partitions that will stay and go
        minpart = -1
        for part in self.partedDisk.partitions:

            if part.getFlag(parted.PARTITION_HIDDEN):
                minpart = max(minpart, part.number+1)
                continue

            # else, the partition should exist
            blkidParts = [x for x in self.blkidParts if x.device == part.path]
            if not blkidParts:
                self.log.warn("cannot identify partition %s", part)
                continue

            blkidPart = blkidParts[0]
            if not blkidPart.isOnieReserved(): continue

            # else, check the GPT label for reserved-ness
            if (part.name
                and ('GRUB' in part.name
                     or 'ONIE-BOOT' in part.name
                     or 'DIAG' in part.name)):
                minpart = max(minpart, part.number+1)

        if minpart < 0:
            self.log.error("cannot find an install partition")
            return 1
        self.minpart = minpart

        return 0
コード例 #7
0
    def partitionParted(self):
        """Build partitions according to the partition spec.

        XXX roth -- hopefully the GPT labels specified here
        work correctly (that is, are ignored) on an msdos label
        """

        constraint = self.partedDevice.optimalAlignedConstraint
        # default partition layout constraint

        devices = {}

        def _u2s(sz, u):
            """Convert to units of logical sectors."""
            bsz = sz * u
            bsz = bsz + self.partedDevice.sectorSize - 1
            return bsz / self.partedDevice.sectorSize

        def _align(spos):
            """Align this sector number."""
            sz = self.partedDevice.sectorSize
            psz = self.partedDevice.physicalSectorSize

            if type(psz) != int: return spos
            if psz <= sz: return spos
            if (psz % sz) != 0: return spos
            if psz > 1048576: return spos

            stride = psz / sz
            off = spos % stride
            off = stride - off
            off = off % stride

            spos += off
            return spos

        UNITS = {
            'GiB' : 1024 * 1024 * 1024,
            'G' : 1000 * 1000 * 1000,
            'MiB' : 1024 * 1024,
            'M' : 1000 * 1000,
            'KiB' : 1024,
            'K' : 1000,
        }

        for part in self.im.platformConf['installer']:

            label, partData = list(part.items())[0]
            if type(partData) == dict:
                sz, fmt = partData['='], partData.get('format', 'ext4')
            else:
                sz, fmt = partData, 'ext4'

            cnt = None
            nextBlock = self.nextBlock or 1
            minpart = self.minpart or 1
            for ul, ub in UNITS.items():
                if sz.endswith(ul):
                    cnt = _u2s(int(sz[:-len(ul)], 10), ub)
                    break
            if sz == '100%':
                cnt = self.partedDevice.getLength() - nextBlock
            if cnt is None:
                self.log.error("invalid size (no units) for %s: %s",
                               part, sz)
                return 1

            start = _align(nextBlock)
            end = start + cnt - 1
            if end <= self.partedDevice.getLength():
                self.log.info("Allocating %d sectors for %s",
                              cnt, label)
            else:
                self.log.warn("%s: start sector %d, end sector %d, max %d",
                              label, start, end,
                              self.partedDevice.getLength())
                self.log.error("invalid partition %s [%s] (too big)",
                               label, sz)
                return 1

            geom = parted.Geometry(device=self.partedDevice,
                                   start=start, length=end-start+1)
            fs = parted.FileSystem(type=fmt, geometry=geom)
            part = parted.Partition(disk=self.partedDisk,
                                    type=parted.PARTITION_NORMAL,
                                    fs=fs,
                                    geometry=geom)
            if self.partedDisk.type == 'gpt':
                part.getPedPartition().set_name(label)
            self.partedDisk.addPartition(part, constraint=constraint)
            self.partedDisk.commit()
            self.check_call(('partprobe', self.device,))

            if fmt == 'raw':
                self.log.info("Leaving %s (%s) unformatted (raw)",
                              part.path, label)
            else:
                self.log.info("Formatting %s (%s) as %s",
                              part.path, label, fmt)
                if fmt == 'msdos':
                    self.mkdosfs(part.path, label=label)
                elif fmt == 'ext4':
                    self.mke4fs(part.path, label=label, huge_file=False)
                elif fmt == 'ext2':
                    self.mke2fs(part.path, label=label)
                else:
                    self.mkfs(part.path, fstype=fmt)

            self.nextBlock, self.minpart = end+1, minpart+1

            devices[label] = part.path

            if label == 'ONL-CONFIG' and self.configArchive is not None:
                self.restoreConfig(part.path)

        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))
        # re-read the partitions

        return 0
コード例 #8
0
    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
コード例 #9
0
    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")
コード例 #10
0
    def installUboot(self):

        if self.device is None:
            self.log.error("missing block device YAML config")
            return 1
        st = os.stat(self.device)
        if not stat.S_ISBLK(st[stat.ST_MODE]):
            self.log.error("not a block device: %s", self.device)
            return 1

        # get a handle to the installer zip
        p = os.path.join(self.im.installerConf.installer_dir,
                         self.im.installerConf.installer_zip)
        self.zf = zipfile.ZipFile(p)

        code = self.loadPlugins()
        if code: return code

        code = self.runPlugins(Plugin.PLUGIN_PREINSTALL)
        if code: return code

        code = self.assertUnmounted()
        if code: return code

        if "mtdblock" in self.device:
            code = self.ubifsinit()
            if code: return code
            code = self.ubi_getinfo()
            if code: return code
            code = self.ubi_installSwi()
            if code: return code
            code = self.ubi_installLoader()
            if code: return code
            code = self.ubi_installBootConfig()
            if code: return code
            code = self.ubi_installOnlConfig()
            if code: return code
            code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
            if code: return code
            code = self.installUbootEnv()
            return code

        code = self.maybeCreateLabel()
        if code: return code

        self.log.info("Installing to %s", self.device)

        self.log.info("found %s partitions (bsz %s, lbsz %s)",
                      self.partedDisk.type, self.partedDevice.sectorSize,
                      self.partedDevice.physicalSectorSize)
        if self.partedDisk.type != 'msdos':
            self.log.error("not an MSDOS partition table")
            return 1
        if self.partedDevice.sectorSize != 512:
            self.log.warn("invalid logical block size, expected 512")
        if self.partedDevice.physicalSectorSize != 512:
            self.log.warn("invalid physical block size, expected 512")

        self.log.info("found a disk with %d blocks",
                      self.partedDevice.getLength())

        self.blkidParts = BlkidParser(log=self.log.getChild("blkid"))
        code = self.findMsdos()
        if code: return code

        code = self.deletePartitions()
        if code: return code

        self.log.info("next usable block is %s", self.nextBlock)

        code = self.partitionParted()
        if code: return code

        # compute the path to the raw loader partition,
        # if indicated by the configuration

        self.rawLoaderDevice = None
        for item in self.im.platformConf['installer']:
            partIdx, partData = list(item.items())[0]
            label, part = list(partData.items())[0]
            if label == 'ONL-BOOT' and part['format'] == 'raw':
                self.rawLoaderDevice = self.device + str(partIdx + 1)
                break

        code = self.installSwi()
        if code: return code

        code = self.installLoader()
        if code: return code

        if self.rawLoaderDevice is None:
            code = self.installBootConfig()
            if code: return code
        else:
            self.log.info(
                "ONL-BOOT is a raw partition (%s), skipping boot-config",
                self.rawLoaderDevice)

        code = self.installOnlConfig()
        if code: return code

        self.log.info("syncing block devices")
        self.check_call(('sync', ))
        # XXX roth probably not needed

        code = self.installUbootEnv()
        if code: return code

        code = self.runPlugins(Plugin.PLUGIN_POSTINSTALL)
        if code: return code

        return 0