Exemple #1
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded"""
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device )
            rc, kpartxOutput = runner.runtool([self.kpartx, "-l", "-v", d['disk'].device])
            kpartxOutput = kpartxOutput.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartxOutput) and kpartxOutput[i][0:4] != "loop":
               i = i + 1
            kpartxOutput = kpartxOutput[i:]

            # Quick sanity check that the number of partitions matches
            # our expectation. If it doesn't, someone broke the code
            # further up
            if len(kpartxOutput) != d['numpart']:
                raise MountError("Unexpected number of partitions from kpartx: %d != %d" %
                                 (len(kpartxOutput), d['numpart']))

            for i in range(len(kpartxOutput)):
                line = kpartxOutput[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-a", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-d", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            d['mapped'] = True
Exemple #2
0
    def __create_subvolumes(self, p, pdisk):
        """ Create all the subvolumes. """

        for subvol in self.subvolumes:
            argv = [ self.btrfscmd, "subvolume", "create", pdisk.mountdir + "/" + subvol["subvol"]]

            rc = runner.show(argv)
            if rc != 0:
                raise MountError("Failed to create subvolume '%s', return code: %d." % (subvol["subvol"], rc))

        # Set default subvolume, subvolume for "/" is default
        subvol = None
        for subvolume in self.subvolumes:
            if subvolume["mountpoint"] == "/" and p['disk_name'] == subvolume['disk_name']:
                subvol = subvolume
                break

        if subvol:
            # Get default subvolume id
            subvolid = self. __get_subvolume_id(pdisk.mountdir, subvol["subvol"])
            # Set default subvolume
            if subvolid != -1:
                rc = runner.show([ self.btrfscmd, "subvolume", "set-default", "%d" % subvolid, pdisk.mountdir])
                if rc != 0:
                    raise MountError("Failed to set default subvolume id: %d', return code: %d." % (subvolid, rc))

        self.__create_subvolume_metadata(p, pdisk)
Exemple #3
0
    def __create_subvolume_metadata(self, p, pdisk):
        if len(self.subvolumes) == 0:
            return

        argv = [ self.btrfscmd, "subvolume", "list", pdisk.mountdir ]
        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (pdisk.mountdir, rc))

        subvolid_items = out.splitlines()
        subvolume_metadata = ""
        for subvol in self.subvolumes:
            for line in subvolid_items:
                if line.endswith(" path %s" % subvol["subvol"]):
                    subvolid = line.split()[1]
                    if not subvolid.isdigit():
                        raise MountError("Invalid subvolume id: %s" % subvolid)

                    subvolid = int(subvolid)
                    opts = subvol["fsopts"].split(",")
                    for opt in opts:
                        if opt.strip().startswith("subvol="):
                            opts.remove(opt)
                            break
                    fsopts = ",".join(opts)
                    subvolume_metadata += "%d\t%s\t%s\t%s\n" % (subvolid, subvol["subvol"], subvol['mountpoint'], fsopts)

        if subvolume_metadata:
            fd = open("%s/.subvolume_metadata" % pdisk.mountdir, "w")
            fd.write(subvolume_metadata)
            fd.close()
Exemple #4
0
    def _install_syslinux(self):
        for name in self.__disks.keys():
            loopdev = self.__disks[name].device

            # Set MBR
            mbrfile = "%s/usr/share/syslinux/" % self._instroot
            if self._ptable_format == 'gpt':
                mbrfile += "gptmbr.bin"
            else:
                mbrfile += "mbr.bin"

            msger.debug("Installing syslinux bootloader '%s' to %s" % \
                        (mbrfile, loopdev))

            mbrsize = os.stat(mbrfile)[stat.ST_SIZE]
            rc = runner.show(['dd', 'if=%s' % mbrfile, 'of=' + loopdev])
            if rc != 0:
                raise MountError("Unable to set MBR to %s" % loopdev)


            # Ensure all data is flushed to disk before doing syslinux install
            runner.quiet('sync')

            fullpathsyslinux = fs_related.find_binary_path("extlinux")
            rc = runner.show([fullpathsyslinux,
                              "-i",
                              "%s/boot/extlinux" % self._instroot])
            if rc != 0:
                raise MountError("Unable to install syslinux bootloader to %s" \
                                 % loopdev)
Exemple #5
0
def _validate_header(raw_hdr):
    """ Validate the GPT header. The 'raw_hdr' parameter has to be a list or a
    tuple containing all the elements of the GPT header in a "raw" form,
    meaning that it should simply contain "unpacked" disk data. """

    # Validate the signature
    if raw_hdr[0] != 'EFI PART':
        raise MountError("GPT partition table not found")

    # Validate the revision
    if raw_hdr[1] != _SUPPORTED_GPT_REVISION:
        raise MountError("Unsupported GPT revision '%s', supported revision " \
                         "is '%s'" % \
                          (binascii.hexlify(raw_hdr[1]),
                           binascii.hexlify(_SUPPORTED_GPT_REVISION)))

    # Validate header size
    if raw_hdr[2] != _GPT_HEADER_SIZE:
        raise MountError("Bad GPT header size: %d bytes, expected %d" % \
                         (raw_hdr[2], _GPT_HEADER_SIZE))

    crc = _calc_header_crc(raw_hdr)
    if raw_hdr[3] != crc:
        raise MountError("GPT header crc mismatch: %#x, should be %#x" % \
                         (crc, raw_hdr[3]))
Exemple #6
0
    def __create_subvolume_snapshots(self, p, pdisk):
        import time

        if self.snapshot_created:
            return

        # Remount with subvolid=0
        rc = runner.show([self.umountcmd, pdisk.mountdir])
        if rc != 0:
            raise MountError("Failed to umount %s" % pdisk.mountdir)
        if pdisk.fsopts:
            mountopts = pdisk.fsopts + ",subvolid=0"
        else:
            mountopts = "subvolid=0"
        rc = runner.show([
            self.mountcmd, "-o", mountopts, pdisk.disk.device, pdisk.mountdir
        ])
        if rc != 0:
            raise MountError("Failed to umount %s" % pdisk.mountdir)

        # Create all the subvolume snapshots
        snapshotts = time.strftime("%Y%m%d-%H%M")
        for subvol in self.subvolumes:
            subvolpath = pdisk.mountdir + "/" + subvol["subvol"]
            snapshotpath = subvolpath + "_%s-1" % snapshotts
            rc = runner.show([
                self.btrfscmd, "subvolume", "snapshot", subvolpath,
                snapshotpath
            ])
            if rc != 0:
                raise MountError(
                    "Failed to create subvolume snapshot '%s' for '%s', return code:"
                    "%d." % (snapshotpath, subvolpath, rc))

        self.snapshot_created = True
Exemple #7
0
    def __mount_subvolumes(self, p, pdisk):
        if self.skipformat:
            # Get subvolume info
            self.__get_subvolume_metadata(p, pdisk)
            # Set default mount options
            if len(self.subvolumes) != 0:
                for subvol in self.subvolumes:
                    if subvol["mountpoint"] == p["mountpoint"] == "/":
                        opts = subvol["fsopts"].split(",")
                        for opt in opts:
                            if opt.strip().startswith("subvol="):
                                opts.remove(opt)
                                break
                        pdisk.fsopts = ",".join(opts)
                        break

        if len(self.subvolumes) == 0:
            # Return directly if no subvolumes
            return

        # Remount to make default subvolume mounted
        rc = runner.show([self.umountcmd, pdisk.mountdir])
        if rc != 0:
            raise MountError("Failed to umount %s" % pdisk.mountdir)

        rc = runner.show([
            self.mountcmd, "-o", pdisk.fsopts, pdisk.disk.device,
            pdisk.mountdir
        ])
        if rc != 0:
            raise MountError("Failed to umount %s" % pdisk.mountdir)

        for subvol in self.subvolumes:
            if subvol["mountpoint"] == "/":
                continue
            subvolid = self.__get_subvolume_id(pdisk.mountdir,
                                               subvol["subvol"])
            if subvolid == -1:
                msger.debug("WARNING: invalid subvolume %s" % subvol["subvol"])
                continue
            # Replace subvolume name with subvolume ID
            opts = subvol["fsopts"].split(",")
            for opt in opts:
                if opt.strip().startswith("subvol="):
                    opts.remove(opt)
                    break

            opts.extend(["subvolrootid=0", "subvol=%s" % subvol["subvol"]])
            fsopts = ",".join(opts)
            subvol['fsopts'] = fsopts
            mountpoint = self.mountdir + subvol['mountpoint']
            makedirs(mountpoint)
            rc = runner.show(
                [self.mountcmd, "-o", fsopts, pdisk.disk.device, mountpoint])
            if rc != 0:
                raise MountError("Failed to mount subvolume %s to %s" %
                                 (subvol["subvol"], mountpoint))
            subvol["mounted"] = True
Exemple #8
0
    def _mount_instroot(self, base_on=None):

        if base_on and os.path.isfile(base_on):
            self._imgdir = os.path.dirname(base_on)
            imgname = os.path.basename(base_on)
            self._base_on(base_on)
            self._set_image_size(misc.get_file_size(self._image))

            # here, self._instloops must be []
            self._instloops.append({
                "mountpoint": "/",
                "label": self.name,
                "name": imgname,
                "size": self.__image_size or 4096L,
                "fstype": self.__fstype or "ext3",
                "extopts": None,
                "loop": None,
                "uuid": None,
                "kspart": None
            })

        self._check_imgdir()

        for loop in self._instloops:
            fstype = loop['fstype']
            mp = os.path.join(self._instroot, loop['mountpoint'].lstrip('/'))
            size = loop['size'] * 1024L * 1024L
            imgname = loop['name']

            if fstype in ("ext2", "ext3", "ext4"):
                MyDiskMount = fs.ExtDiskMount
            elif fstype == "btrfs":
                MyDiskMount = fs.BtrfsDiskMount
            elif fstype in ("vfat", "msdos"):
                MyDiskMount = fs.VfatDiskMount
            else:
                raise MountError('Cannot support fstype: %s' % fstype)

            loop['loop'] = MyDiskMount(fs.SparseLoopbackDisk(
                os.path.join(self._imgdir, imgname), size),
                                       mp,
                                       fstype,
                                       self._blocksize,
                                       loop['label'],
                                       fsuuid=loop['uuid'])

            if fstype in ("ext2", "ext3", "ext4"):
                loop['loop'].extopts = loop['extopts']

            try:
                msger.verbose('Mounting image "%s" on "%s"' % (imgname, mp))
                fs.makedirs(mp)
                loop['loop'].mount()
                # Make an autogenerated uuid avaialble in _get_post_scripts_env()
                if loop['kspart'] and loop['kspart'].uuid is None and \
                   loop['loop'].uuid:
                    loop['kspart'].uuid = loop['loop'].uuid

            except MountError, e:
                raise
Exemple #9
0
    def _install_syslinux(self):
        i = 0
        for name in self.__disks.keys():
            loopdev = self.__disks[name].device
            i =i+1

        msger.debug("Installing syslinux bootloader to %s" % loopdev)

        (bootdevnum, rootdevnum, rootdev, prefix) = \
                                    self._get_syslinux_boot_config()


        #Set MBR
        mbrsize = os.stat("%s/usr/share/syslinux/mbr.bin" \
                          % self._instroot)[stat.ST_SIZE]
        rc = runner.show(['dd',
                          'if=%s/usr/share/syslinux/mbr.bin' % self._instroot,
                          'of=' + loopdev])
        if rc != 0:
            raise MountError("Unable to set MBR to %s" % loopdev)

        #Set Bootable flag
        parted = fs_related.find_binary_path("parted")
        rc = runner.quiet([parted,
                           "-s",
                           loopdev,
                           "set",
                           "%d" % (bootdevnum + 1),
                           "boot",
                           "on"])
        #XXX disabled return code check because parted always fails to
        #reload part table with loop devices. Annoying because we can't
        #distinguish this failure from real partition failures :-(
        if rc != 0 and 1 == 0:
            raise MountError("Unable to set bootable flag to %sp%d" \
                             % (loopdev, (bootdevnum + 1)))

        #Ensure all data is flushed to disk before doing syslinux install
        runner.quiet('sync')

        fullpathsyslinux = fs_related.find_binary_path("extlinux")
        rc = runner.show([fullpathsyslinux,
                          "-i",
                          "%s/boot/extlinux" % self._instroot])
        if rc != 0:
            raise MountError("Unable to install syslinux bootloader to %sp%d" \
                             % (loopdev, (bootdevnum + 1)))
Exemple #10
0
    def _read_disk(self, offset, size):
        """ A helper function which reads 'size' bytes from offset 'offset' of
        the disk and checks all the error conditions. """

        self._disk_obj.seek(offset)
        try:
            data = self._disk_obj.read(size)
        except IOError as err:
            raise MountError("cannot read from '%s': %s" % \
                             (self.disk_path, err))

        if len(data) != size:
            raise MountError("cannot read %d bytes from offset '%d' of '%s', " \
                             "read only %d bytes" % \
                             (size, offset, self.disk_path, len(data)))

        return data
Exemple #11
0
    def add_partition(self, size, disk_name, mountpoint, fstype = None,
                      label=None, fsopts = None, boot = False, align = None,
                      part_type = None):
        """ Add the next partition. Prtitions have to be added in the
        first-to-last order. """

        # Converting MB to sectors for parted
        size = size * 1024 * 1024 / self.sector_size

        # We need to handle subvolumes for btrfs
        if fstype == "btrfs" and fsopts and fsopts.find("subvol=") != -1:
            self.btrfscmd=find_binary_path("btrfs")
            subvol = None
            opts = fsopts.split(",")
            for opt in opts:
                if opt.find("subvol=") != -1:
                    subvol = opt.replace("subvol=", "").strip()
                    break
            if not subvol:
                raise MountError("No subvolume: %s" % fsopts)
            self.subvolumes.append({'size': size, # In sectors
                                    'mountpoint': mountpoint, # Mount relative to chroot
                                    'fstype': fstype, # Filesystem type
                                    'fsopts': fsopts, # Filesystem mount options
                                    'disk_name': disk_name, # physical disk name holding partition
                                    'device': None, # kpartx device node for partition
                                    'mount': None, # Mount object
                                    'subvol': subvol, # Subvolume name
                                    'boot': boot, # Bootable flag
                                    'mounted': False # Mount flag
                                   })

        # We still need partition for "/" or non-subvolume
        if mountpoint == "/" or not fsopts or fsopts.find("subvol=") == -1:
            # Don't need subvolume for "/" because it will be set as default subvolume
            if fsopts and fsopts.find("subvol=") != -1:
                opts = fsopts.split(",")
                for opt in opts:
                    if opt.strip().startswith("subvol="):
                        opts.remove(opt)
                        break
                fsopts = ",".join(opts)

            part = { 'size': size, # In sectors
                     'mountpoint': mountpoint, # Mount relative to chroot
                     'fstype': fstype, # Filesystem type
                     'fsopts': fsopts, # Filesystem mount options
                     'label': label, # Partition label
                     'disk_name': disk_name, # physical disk name holding partition
                     'device': None, # kpartx device node for partition
                     'mount': None, # Mount object
                     'num': None, # Partition number
                     'boot': boot, # Bootable flag
                     'align': align, # Partition alignment
                     'part_type' : part_type, # Partition type
                     'partuuid': None } # Partition UUID (GPT-only)

            self.__add_partition(part)
Exemple #12
0
    def __get_subvolume_id(self, rootpath, subvol):
        if not self.btrfscmd:
            self.btrfscmd=find_binary_path("btrfs")
        argv = [ self.btrfscmd, "subvolume", "list", rootpath ]

        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (rootpath, rc))

        subvolid = -1
        for line in out.splitlines():
            if line.endswith(" path %s" % subvol):
                subvolid = line.split()[1]
                if not subvolid.isdigit():
                    raise MountError("Invalid subvolume id: %s" % subvolid)
                subvolid = int(subvolid)
                break
        return subvolid
Exemple #13
0
 def __unmount_subvolumes(self):
     """ It may be called multiple times, so we need to chekc if it is still mounted. """
     for subvol in self.subvolumes:
         if subvol["mountpoint"] == "/":
             continue
         if not subvol["mounted"]:
             continue
         mountpoint = self.mountdir + subvol['mountpoint']
         rc = runner.show([self.umountcmd, mountpoint])
         if rc != 0:
             raise MountError("Failed to unmount subvolume %s from %s" % (subvol["subvol"], mountpoint))
         subvol["mounted"] = False
Exemple #14
0
 def add_partition(self,
                   size,
                   disk,
                   mountpoint,
                   fstype=None,
                   fsopts=None,
                   boot=False):
     # Converting M to s for parted
     size = size * 1024 * 1024 / self.sector_size
     """ We need to handle subvolumes for btrfs """
     if fstype == "btrfs" and fsopts and fsopts.find("subvol=") != -1:
         self.btrfscmd = find_binary_path("btrfs")
         subvol = None
         opts = fsopts.split(",")
         for opt in opts:
             if opt.find("subvol=") != -1:
                 subvol = opt.replace("subvol=", "").strip()
                 break
         if not subvol:
             raise MountError("No subvolume: %s" % fsopts)
         self.subvolumes.append({
             'size': size,  # In sectors
             'mountpoint': mountpoint,  # Mount relative to chroot
             'fstype': fstype,  # Filesystem type
             'fsopts': fsopts,  # Filesystem mount options
             'disk': disk,  # physical disk name holding partition
             'device': None,  # kpartx device node for partition
             'mount': None,  # Mount object
             'subvol': subvol,  # Subvolume name
             'boot': boot,  # Bootable flag
             'mounted': False  # Mount flag
         })
     """ We still need partition for "/" or non-subvolume """
     if mountpoint == "/" or not fsopts or fsopts.find("subvol=") == -1:
         """ Don't need subvolume for "/" because it will be set as default subvolume """
         if fsopts and fsopts.find("subvol=") != -1:
             opts = fsopts.split(",")
             for opt in opts:
                 if opt.strip().startswith("subvol="):
                     opts.remove(opt)
                     break
             fsopts = ",".join(opts)
         self.partitions.append({
             'size': size,  # In sectors
             'mountpoint': mountpoint,  # Mount relative to chroot
             'fstype': fstype,  # Filesystem type
             'fsopts': fsopts,  # Filesystem mount options
             'disk': disk,  # physical disk name holding partition
             'device': None,  # kpartx device node for partition
             'mount': None,  # Mount object
             'num': None,  # Partition number
             'boot': boot
         })  # Bootable flag
Exemple #15
0
    def __init__(self, disk_path, sector_size = 512):
        """ The class constructor which accepts the following parameters:
            * disk_path - full path to the disk image or device node
            * sector_size - size of a disk sector in bytes """

        self.sector_size = sector_size
        self.disk_path = disk_path

        try:
            self._disk_obj = open(disk_path, 'r+b')
        except IOError as err:
            raise MountError("Cannot open file '%s' for reading GPT " \
                             "partitions: %s" % (disk_path, err))
Exemple #16
0
    def mount(self):
        for dev in self.disks.keys():
            d = self.disks[dev]
            d['disk'].create()

        self.__format_disks()
        self.__map_partitions()
        self.__calculate_mountorder()

        for mp in self.mountOrder:
            p = None
            for p1 in self.partitions:
                if p1['mountpoint'] == mp:
                    p = p1
                    break

            if mp == 'swap':
                runner.show([self.mkswap, p['device']])
                continue

            rmmountdir = False
            if p['mountpoint'] == "/":
                rmmountdir = True
            if p['fstype'] == "vfat" or p['fstype'] == "msdos":
                myDiskMount = VfatDiskMount
            elif p['fstype'] in ("ext2", "ext3", "ext4"):
                myDiskMount = ExtDiskMount
            elif p['fstype'] == "btrfs":
                myDiskMount = BtrfsDiskMount
            else:
                raise MountError("Fail to support file system " + p['fstype'])

            if p['fstype'] == "btrfs" and not p['fsopts']:
                p['fsopts'] = "subvolid=0"

            pdisk = myDiskMount(RawDisk(p['size'] * self.sector_size,
                                        p['device']),
                                self.mountdir + p['mountpoint'],
                                p['fstype'],
                                4096,
                                p['mountpoint'],
                                rmmountdir,
                                self.skipformat,
                                fsopts=p['fsopts'])
            pdisk.mount(pdisk.fsopts)
            if p['fstype'] == "btrfs" and p['mountpoint'] == "/":
                if not self.skipformat:
                    self.__create_subvolumes(p, pdisk)
                self.__mount_subvolumes(p, pdisk)
            p['mount'] = pdisk
    def _create_syslinux_config(self):
        hdddir = "%s/hdd/boot" % self.workdir
        rm_cmd = "rm -rf " + self.workdir
        exec_cmd(rm_cmd)

        install_cmd = "install -d %s" % hdddir
        tmp = exec_cmd(install_cmd)

        splash = os.path.join(self.workdir, "/hdd/boot/splash.jpg")
        if os.path.exists(splash):
            splashline = "menu background splash.jpg"
        else:
            splashline = ""

        (rootdev, root_part_uuid) = self._get_boot_config()
        options = self.ks.handler.bootloader.appendLine

        syslinux_conf = ""
        syslinux_conf += "PROMPT 0\n"
        timeout = kickstart.get_timeout(self.ks)
        if not timeout:
            timeout = 0
        syslinux_conf += "TIMEOUT " + str(timeout) + "\n"
        syslinux_conf += "\n"
        syslinux_conf += "ALLOWOPTIONS 1\n"
        syslinux_conf += "SERIAL 0 115200\n"
        syslinux_conf += "\n"
        if splashline:
            syslinux_conf += "%s\n" % splashline
        syslinux_conf += "DEFAULT boot\n"
        syslinux_conf += "LABEL boot\n"

        kernel = "/vmlinuz"
        syslinux_conf += "KERNEL " + kernel + "\n"

        if self._ptable_format == 'msdos':
            rootstr = rootdev
        else:
            if not root_part_uuid:
                raise MountError("Cannot find the root GPT partition UUID")
            rootstr = "PARTUUID=%s" % root_part_uuid

        syslinux_conf += "APPEND label=boot root=%s %s\n" % (rootstr, options)

        msger.debug("Writing syslinux config %s/hdd/boot/syslinux.cfg" \
                    % self.workdir)
        cfg = open("%s/hdd/boot/syslinux.cfg" % self.workdir, "w")
        cfg.write(syslinux_conf)
        cfg.close()
Exemple #18
0
    def _read_raw_ptable(self, header):
        """ Read and validate primary or backup partition table. The 'header'
        argument is the GPT header. If it is the primary GPT header, then the
        primary partition table is read and validated, otherwise - the backup
        one. The 'header' argument is a dictionary which is returned by the
        'read_header()' method. """

        raw_ptable = self._read_disk(header['ptable_offs'],
                                     header['ptable_size'])

        crc = binascii.crc32(raw_ptable) & 0xFFFFFFFF
        if crc != header['ptable_crc']:
            raise MountError("Partition table at LBA %d (%s) is corrupted" % \
                             (header['ptable_lba'], header['primary_str']))

        return raw_ptable
    def _create_grubefi_config(self):
        hdddir = "%s/hdd/boot" % self.workdir
        rm_cmd = "rm -rf %s" % self.workdir
        exec_cmd(rm_cmd)

        install_cmd = "install -d %s/EFI/BOOT" % hdddir
        tmp = exec_cmd(install_cmd)

        splash = os.path.join(self.workdir, "/EFI/boot/splash.jpg")
        if os.path.exists(splash):
            splashline = "menu background splash.jpg"
        else:
            splashline = ""

        (rootdev, root_part_uuid) = self._get_boot_config()
        options = self.ks.handler.bootloader.appendLine

        grubefi_conf = ""
        grubefi_conf += "serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1\n"
        grubefi_conf += "default=boot\n"
        timeout = kickstart.get_timeout(self.ks)
        if not timeout:
            timeout = 0
        grubefi_conf += "timeout=%s\n" % timeout
        grubefi_conf += "menuentry 'boot'{\n"

        kernel = "/vmlinuz"

        if self._ptable_format == 'msdos':
            rootstr = rootdev
        else:
            if not root_part_uuid:
                raise MountError("Cannot find the root GPT partition UUID")
            rootstr = "PARTUUID=%s" % root_part_uuid

        grubefi_conf += "linux %s root=%s rootwait %s\n" \
            % (kernel, rootstr, options)
        grubefi_conf += "}\n"
        if splashline:
            syslinux_conf += "%s\n" % splashline

        msger.debug("Writing grubefi config %s/hdd/boot/EFI/BOOT/grub.cfg" \
                        % self.workdir)
        cfg = open("%s/hdd/boot/EFI/BOOT/grub.cfg" % self.workdir, "w")
        cfg.write(grubefi_conf)
        cfg.close()
Exemple #20
0
    def __unmap_partitions(self):
        for dev in self.disks.keys():
            d = self.disks[dev]
            if not d['mapped']:
                continue

            msger.debug("Removing compat symlinks")
            for pnum in d['partitions']:
                if self.partitions[pnum]['device'] != None:
                    os.unlink(self.partitions[pnum]['device'])
                    self.partitions[pnum]['device'] = None

            msger.debug("Unmapping %s" % d['disk'].device)
            rc = runner.quiet([self.kpartx, "-sd", d['disk'].device])
            if rc != 0:
                raise MountError("Failed to unmap partitions for '%s'" %
                                 d['disk'].device)

            d['mapped'] = False
Exemple #21
0
    def _write_disk(self, offset, buf):
        """ A helper function which writes buffer 'buf' to offset 'offset' of
        the disk. This function takes care of unaligned writes and checks all
        the error conditions. """

        # Since we may be dealing with a block device, we only can write in
        # 'self.sector_size' chunks. Find the aligned starting and ending
        # disk offsets to read.
        start =  (offset / self.sector_size) * self.sector_size
        end = ((start + len(buf)) / self.sector_size + 1) * self.sector_size

        data = self._read_disk(start, end - start)
        off = offset - start
        data = data[:off] + buf + data[off + len(buf):]

        self._disk_obj.seek(start)
        try:
            self._disk_obj.write(data)
        except IOError as err:
            raise MountError("cannot write to '%s': %s" % (self.disk_path, err))
Exemple #22
0
    def __unmap_partitions(self):
        for dev in list(self.disks.keys()):
            d = self.disks[dev]
            if not d['mapped']:
                continue

            msger.debug("Removing compat symlinks")
            for pnum in d['partitions']:
                if self.partitions[pnum]['device'] != None:
                    os.unlink(self.partitions[pnum]['device'])
                    self.partitions[pnum]['device'] = None

            msger.debug("Unmapping %s" % d['disk'].device)
            #FIXME: find a better way to workaround delayed IO keeping the devices busy
            time.sleep(4)
            rc = runner.quiet([self.kpartx, "-d", d['disk'].device])
            if rc != 0:
                raise MountError("Failed to unmap partitions for '%s'" %
                                 d['disk'].device)

            d['mapped'] = False
Exemple #23
0
    def _change_partition(self, header, entry):
        """ A helper function for 'change_partitions()' which changes a
        a paricular instance of the partition table (primary or backup). """

        if entry['index'] >= header['entries_cnt']:
            raise MountError("Partition table at LBA %d has only %d "   \
                             "records cannot change record number %d" % \
                             (header['entries_cnt'], entry['index']))
        # Read raw GPT header
        raw_hdr = self._read_disk(header['hdr_offs'], _GPT_HEADER_SIZE)
        raw_hdr = list(struct.unpack(_GPT_HEADER_FORMAT, raw_hdr))
        _validate_header(raw_hdr)

        # Prepare the new partition table entry
        raw_entry = struct.pack(_GPT_ENTRY_FORMAT,
                                uuid.UUID(entry['type_uuid']).bytes_le,
                                uuid.UUID(entry['part_uuid']).bytes_le,
                                entry['first_lba'],
                                entry['last_lba'],
                                entry['flags'],
                                entry['name'].encode('UTF-16'))

        # Write the updated entry to the disk
        entry_offs = header['ptable_offs'] + \
                     header['entry_size'] * entry['index']
        self._write_disk(entry_offs, raw_entry)

        # Calculate and update partition table CRC32
        raw_ptable = self._read_disk(header['ptable_offs'],
                                     header['ptable_size'])
        raw_hdr[13] = binascii.crc32(raw_ptable) & 0xFFFFFFFF

        # Calculate and update the GPT header CRC
        raw_hdr[3] = _calc_header_crc(raw_hdr)

        # Write the updated header to the disk
        raw_hdr = struct.pack(_GPT_HEADER_FORMAT, *raw_hdr)
        self._write_disk(header['hdr_offs'], raw_hdr)
    def _install_syslinux(self):
        mbrfile = "%s/syslinux/" % self.bootimg_dir
        if self._ptable_format == 'gpt':
            mbrfile += "gptmbr.bin"
        else:
            mbrfile += "mbr.bin"

        if not os.path.exists(mbrfile):
            msger.error(
                "Couldn't find %s.  If using the -e option, do you have the right MACHINE set in local.conf?  If not, is the bootimg_dir path correct?"
                % mbrfile)

        for disk_name, disk in self.__instimage.disks.items():
            full_path = self._full_path(self.__imgdir, disk_name, "direct")
            msger.debug("Installing MBR on disk %s as %s with size %s bytes" \
                            % (disk_name, full_path, disk['min_size']))

            rc = runner.show(
                ['dd',
                 'if=%s' % mbrfile,
                 'of=%s' % full_path, 'conv=notrunc'])
            if rc != 0:
                raise MountError("Unable to set MBR to %s" % full_path)
Exemple #25
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        # Go through partitions in the order they are added in .ks file
        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" %
                                 (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                #  This hack is used to remove one sector from the first partition,
                #  that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            # Get the disk where the partition is located
            d = self.disks[p['disk']]
            d['numpart'] += 1

            # alignment in sectors
            align_sectors = None
            # if first partition then we need to skip the first sector
            # where the MBR is located, if the alignment isn't set
            # See: https://wiki.linaro.org/WorkingGroups/Kernel/Projects/FlashCardSurvey
            if d['numpart'] == 1:
                if p['align'] and p['align'] > 0:
                    align_sectors = p['align'] * 1024 / self.sector_size
                else:
                    align_sectors = MBR_SECTOR_LEN
            elif p['align']:
                # If not first partition and we do have alignment set we need
                # to align the partition.
                # FIXME: This leaves a empty spaces to the disk. To fill the
                # gaps we could enlargea the previous partition?

                # Calc how much the alignment is off.
                align_sectors = d['offset'] % (p['align'] * 1024 /
                                               self.sector_size)
                # We need to move forward to the next alignment point
                align_sectors = (p['align'] * 1024 /
                                 self.sector_size) - align_sectors

            if align_sectors:
                if p['align'] and p['align'] > 0:
                    msger.debug(
                        "Realignment for %s%s with %s sectors, original"
                        " offset %s, target alignment is %sK." %
                        (p['disk'], d['numpart'], align_sectors, d['offset'],
                         p['align']))
                # p['size'] already converted in secctors
                if p['size'] <= align_sectors:
                    raise MountError("Partition for %s is too small to handle "
                                     "the alignment change." % p['mountpoint'])

                # increase the offset so we actually start the partition on right alignment
                d['offset'] += align_sectors

            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug(
                "Assigned %s to %s%d at Sector %d with size %d sectors "
                "/ %d bytes." %
                (p['mountpoint'], p['disk'], p['num'], p['start'], p['size'],
                 p['size'] * self.sector_size))

        if self.skipformat:
            msger.debug(
                "Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" %
                        (d['disk'].device))
            rc, out = runner.runtool(
                [self.parted, "-s", d['disk'].device, "mklabel", "msdos"],
                catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug(
                    "WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'."
                    % (rc, d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device, "extended", None,
                                            p['start'], d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in [
                    "vfat", "msdos"
            ] and p['size'] % 2:
                msger.debug(
                    "Substracting one sector from '%s' partition to get even number of sectors for the partition."
                    % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device, p['type'],
                                              parted_fs_type, p['start'],
                                              p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug(
                    "WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'."
                    % (ret, p['mountpoint'], d['disk'].device))

            if p['boot']:
                msger.debug(
                    "Setting boot flag for partition '%s' on disk '%s'." %
                    (p['num'], d['disk'].device))
                boot_cmd = [
                    self.parted, "-s", d['disk'].device, "set",
                    "%d" % p['num'], "boot", "on"
                ]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning(
                        "parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'."
                        % (rc, p['num'], d['disk'].device))
Exemple #26
0
    def mount(self):
        for dev in list(self.disks.keys()):
            d = self.disks[dev]
            d['disk'].create()

        self.__format_disks()
        self.__map_partitions()
        self.__calculate_mountorder()

        for mp in self.mountOrder:
            p = None
            for p1 in self.partitions:
                if p1['mountpoint'] == mp:
                    p = p1
                    break

            if not p['label']:
                if p['mountpoint'] == "/":
                    p['label'] = 'platform'
                else:
                    p['label'] = mp.split('/')[-1]

            if mp == 'swap':
                import uuid
                p['uuid'] = str(uuid.uuid1())
                runner.show([
                    self.mkswap, '-L', p['label'], '-U', p['uuid'], p['device']
                ])
                continue

            dkwargs = {}

            rmmountdir = False
            if p['mountpoint'] == "/":
                rmmountdir = True
            if p['fstype'] == "vfat" or p['fstype'] == "msdos":
                myDiskMount = VfatDiskMount
            elif p['fstype'] in ("ext2", "ext3", "ext4"):
                myDiskMount = ExtDiskMount
            elif p['fstype'] == "btrfs":
                myDiskMount = BtrfsDiskMount
                dkwargs['subvolumes'] = self.subvolumes
            else:
                raise MountError("Fail to support file system " + p['fstype'])

            if p['fstype'] == "btrfs" and not p['fsopts']:
                p['fsopts'] = "subvolid=0"

            dkwargs['fsopts'] = p['fsopts']

            pdisk = myDiskMount(
                RawDisk(p['size'] * self.sector_size, p['device']),
                self.mountdir + p['mountpoint'], p['fstype'], 4096, p['label'],
                rmmountdir, self.skipformat, **dkwargs)
            pdisk.mount(pdisk.fsopts)
            if p['fstype'] == "btrfs" and p['mountpoint'] == "/":
                if not self.skipformat:
                    self.__create_subvolumes(p, pdisk)
                self.__mount_subvolumes(p, pdisk)
            p['mount'] = pdisk
            p['uuid'] = pdisk.uuid
Exemple #27
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded. """
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device)
            rc, kpartx_output = runner.runtool(
                [self.kpartx, "-l", "-v", d['disk'].device])
            kpartx_output = kpartx_output.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartx_output) and kpartx_output[i][0:4] != "loop":
                i = i + 1
            kpartx_output = kpartx_output[i:]

            # Make sure kpartx reported the right count of partitions
            if len(kpartx_output) != d['numpart']:
                # If this disk has more than 3 partitions, then in case of MBR
                # paritions there is an extended parition. Different versions
                # of kpartx behave differently WRT the extended partition -
                # some map it, some ignore it. This is why we do the below hack
                # - if kpartx reported one more partition and the partition
                # table type is "msdos" and the amount of partitions is more
                # than 3, we just assume kpartx mapped the extended parition
                # and we remove it.
                if len(kpartx_output) == d['numpart'] + 1 \
                   and d['ptable_format'] == 'msdos' and len(kpartx_output) > 3:
                    kpartx_output.pop(3)
                else:
                    raise MountError("Unexpected number of partitions from " \
                                     "kpartx: %d != %d" % \
                                        (len(kpartx_output), d['numpart']))

            for i in range(len(kpartx_output)):
                line = kpartx_output[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev
                self.partitions[pnum]['mapper_device'] = mapperdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-sa", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-sd", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            for p in self.partitions:
                if p['mapper_device'] and os.path.islink(p['mapper_device']):
                    p['mpath_device'] = resolve_ref(p['mapper_device'])
                else:
                    p['mpath_device'] = ''

            # FIXME: need a better way to fix the latency
            import time
            time.sleep(1)

            if not os.path.exists(mapperdev):
                # load mapper device if not updated
                runner.quiet([self.dmsetup, "mknodes"])
                # still not updated, roll back
                if not os.path.exists(mapperdev):
                    runner.quiet([self.kpartx, "-sd", d['disk'].device])
                    raise MountError("Failed to load mapper devices for '%s'" %
                                     d['disk'].device)

            d['mapped'] = True
Exemple #28
0
    def layout_partitions(self, ptable_format="msdos"):
        """ Layout the partitions, meaning calculate the position of every
        partition on the disk. The 'ptable_format' parameter defines the
        partition table format, and may be either "msdos" or "gpt". """

        msger.debug("Assigning %s partitions to disks" % ptable_format)

        if ptable_format not in ('msdos', 'gpt'):
            raise MountError("Unknown partition table format '%s', supported " \
                             "formats are: 'msdos' and 'gpt'" % ptable_format)

        if self._partitions_layed_out:
            return

        self._partitions_layed_out = True

        # Go through partitions in the order they are added in .ks file
        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk_name']):
                raise MountError("No disk %s for partition %s" \
                                 % (p['disk_name'], p['mountpoint']))

            if p['part_type'] and ptable_format != 'gpt':
                # The --part-type can also be implemented for MBR partitions,
                # in which case it would map to the 1-byte "partition type"
                # filed at offset 3 of the partition entry.
                raise MountError("setting custom partition type is only " \
                                 "implemented for GPT partitions")

            # Get the disk where the partition is located
            d = self.disks[p['disk_name']]
            d['numpart'] += 1
            d['ptable_format'] = ptable_format

            if d['numpart'] == 1:
                if ptable_format == "msdos":
                    overhead = MBR_OVERHEAD
                else:
                    overhead = GPT_OVERHEAD

                # Skip one sector required for the partitioning scheme overhead
                d['offset'] += overhead
                # Steal few sectors from the first partition to offset for the
                # partitioning overhead
                p['size'] -= overhead

            if p['align']:
                # If not first partition and we do have alignment set we need
                # to align the partition.
                # FIXME: This leaves a empty spaces to the disk. To fill the
                # gaps we could enlarge the previous partition?

                # Calc how much the alignment is off.
                align_sectors = d['offset'] % (p['align'] * 1024 /
                                               self.sector_size)
                # We need to move forward to the next alignment point
                align_sectors = (p['align'] * 1024 /
                                 self.sector_size) - align_sectors

                msger.debug("Realignment for %s%s with %s sectors, original"
                            " offset %s, target alignment is %sK." %
                            (p['disk_name'], d['numpart'], align_sectors,
                             d['offset'], p['align']))

                # increase the offset so we actually start the partition on right alignment
                d['offset'] += align_sectors

            p['start'] = d['offset']
            d['offset'] += p['size']

            p['type'] = 'primary'
            p['num'] = d['numpart']

            if d['ptable_format'] == "msdos":
                if d['numpart'] > 2:
                    # Every logical partition requires an additional sector for
                    # the EBR, so steal the last sector from the end of each
                    # partition starting from the 3rd one for the EBR. This
                    # will make sure the logical partitions are aligned
                    # correctly.
                    p['size'] -= 1

                if d['numpart'] > 3:
                    p['type'] = 'logical'
                    p['num'] = d['numpart'] + 1

            d['partitions'].append(n)
            msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d "
                        "sectors (%d bytes)." \
                            % (p['mountpoint'], p['disk_name'], p['num'],
                               p['start'], p['start'] + p['size'] - 1,
                               p['size'], p['size'] * self.sector_size))

        # Once all the partitions have been laid out, we can calculate the
        # minimum disk sizes.
        for disk_name, d in self.disks.items():
            d['min_size'] = d['offset']
            if d['ptable_format'] == 'gpt':
                # Account for the backup partition table at the end of the disk
                d['min_size'] += GPT_OVERHEAD

            d['min_size'] *= self.sector_size
Exemple #29
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" % (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                # This hack is used to remove one sector from the first partition,
                # that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            d = self.disks[p['disk']]
            d['numpart'] += 1
            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug("Assigned %s to %s%d at %d at size %d" % (p['mountpoint'], p['disk'], p['num'], p['start'], p['size']))

        if self.skipformat:
            msger.debug("Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" % (d['disk'].device))
            rc, out = runner.runtool([self.parted, "-s", d['disk'].device, "mklabel", "msdos"], catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'." % (p1.returncode,d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device,"extended",None,p['start'],d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat","msdos"] and p['size'] % 2:
                msger.debug("Substracting one sector from '%s' partition to get even number of sectors for the partition." % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device,p['type'],
                                             parted_fs_type, p['start'],
                                             p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'." % (p1.returncode,p['mountpoint'],d['disk'].device))

            if p['boot']:
                msger.debug("Setting boot flag for partition '%s' on disk '%s'." % (p['num'],d['disk'].device))
                boot_cmd = [self.parted, "-s", d['disk'].device, "set", "%d" % p['num'], "boot", "on"]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning("parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'." % (rc,p['num'],d['disk'].device))
Exemple #30
0
    def _create_syslinux_config(self):

        splash = os.path.join(self._instroot, "boot/extlinux")
        if os.path.exists(splash):
            splashline = "menu background splash.jpg"
        else:
            splashline = ""

        (rootdev, root_part_uuid) = self._get_syslinux_boot_config()
        options = self.ks.handler.bootloader.appendLine

        #XXX don't hardcode default kernel - see livecd code
        syslinux_conf = ""
        syslinux_conf += "prompt 0\n"
        syslinux_conf += "timeout 1\n"
        syslinux_conf += "\n"
        syslinux_conf += "default vesamenu.c32\n"
        syslinux_conf += "menu autoboot Starting %s...\n" % self.distro_name
        syslinux_conf += "menu hidden\n"
        syslinux_conf += "\n"
        syslinux_conf += "%s\n" % splashline
        syslinux_conf += "menu title Welcome to %s!\n" % self.distro_name
        syslinux_conf += "menu color border 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color sel 7 #ffffffff #ff000000\n"
        syslinux_conf += "menu color title 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color tabmsg 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color unsel 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color hotsel 0 #ff000000 #ffffffff\n"
        syslinux_conf += "menu color hotkey 7 #ffffffff #ff000000\n"
        syslinux_conf += "menu color timeout_msg 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color timeout 0 #ffffffff #00000000\n"
        syslinux_conf += "menu color cmdline 0 #ffffffff #00000000\n"

        versions = []
        kernels = self._get_kernel_versions()
        symkern = "%s/boot/vmlinuz" % self._instroot

        if os.path.lexists(symkern):
            v = os.path.realpath(symkern).replace('%s-' % symkern, "")
            syslinux_conf += "label %s\n" % self.distro_name.lower()
            syslinux_conf += "\tmenu label %s (%s)\n" % (self.distro_name, v)
            syslinux_conf += "\tlinux ../vmlinuz\n"
            if self._ptable_format == 'msdos':
                rootstr = rootdev
            else:
                if not root_part_uuid:
                    raise MountError("Cannot find the root GPT partition UUID")
                rootstr = "PARTUUID=%s" % root_part_uuid
            syslinux_conf += "\tappend ro root=%s %s\n" % (rootstr, options)
            syslinux_conf += "\tmenu default\n"
        else:
            for kernel in kernels:
                for version in kernels[kernel]:
                    versions.append(version)

            footlabel = 0
            for v in versions:
                syslinux_conf += "label %s%d\n" \
                                 % (self.distro_name.lower(), footlabel)
                syslinux_conf += "\tmenu label %s (%s)\n" % (self.distro_name, v)
                syslinux_conf += "\tlinux ../vmlinuz-%s\n" % v
                syslinux_conf += "\tappend ro root=%s %s\n" \
                                 % (rootdev, options)
                if footlabel == 0:
                    syslinux_conf += "\tmenu default\n"
                footlabel += 1;

        msger.debug("Writing syslinux config %s/boot/extlinux/extlinux.conf" \
                    % self._instroot)
        cfg = open(self._instroot + "/boot/extlinux/extlinux.conf", "w")
        cfg.write(syslinux_conf)
        cfg.close()