Example #1
0
    def delprop(self, key):
        "Delete a Boot Loader property"

        self._prop_validate(key, validate_value=False)

        # Check pseudoproperties:
        if key == BootLoader.PROP_BOOT_TARGS:
            raise BootmgmtUnsupportedOperationError("key `%s' may not be "
                                                    "deleted" % key)
        try:
            del self._bl_props[key]
            self.dirty = True
        except KeyError as err:
            raise BootmgmtUnsupportedOperationError(
                "key `%s' does not exist" % key, err)
def autogenerate_boot_instances(bootconfig):
    sbia = SolarisBootInstanceAutogenerator()

    # XXX - Handle bootconfig instances that have boot_class != disk
    if bootconfig.boot_class != BootConfig.BOOT_CLASS_DISK:
        raise BootmgmtUnsupportedOperationError('XXX - Fix Me')

    # Use libbe_py to get the list of boot environments, then iterate
    # over the list, creating a new SolarisDiskBootInstance for each
    # Note that the title will just be the last portion of the bootfs
    # (i.e. <pool>/ROOT/<title>)
    retcode, belist = libbe_py.beList()
    if retcode != 0:
        sbia._debug('libbe_py.beList() failed; return code was ' +
                    str(retcode))
        return []

    inst_list = []
    for bootenv in belist:
        if bootenv.get('orig_be_name', None) is None:
            continue  # skip over snapshots
        bootinst = SolarisDiskBootInstance(None,
                                           title=bootenv['orig_be_name'],
                                           bootfs=bootenv['root_ds'])
        if bootenv['active'] is True:
            sbia._debug('default boot instance is:\n' + str(bootinst))
            bootinst.default = True

        inst_list.append(bootinst)

    return inst_list
Example #3
0
 def load_config(self):
     """Load boot instances and GRUB properties from the menu.lst file"""
     if self._boot_config.boot_class == BootConfig.BOOT_CLASS_DISK:
         self._load_config_disk()
         self.dirty = False  # We just loaded a clean config from disk!
     else:
         raise BootmgmtUnsupportedOperationError('XXX - Fix Me')
Example #4
0
    def _zfs_boot_data_rootdir_disk(self):
        if self._boot_config.boot_fstype != 'zfs':
            raise BootmgmtUnsupportedOperationError(
                'Filesystem %s not '
                'supported by the ZFS boot block' %
                self._boot_config.boot_fstype)

        return self._boot_config.zfstop
 def setprop(self, propname, value):
     """Setting properties is not supported on BIOS systems"""
     if propname == SystemFirmware.PROP_BOOT_DEVICE:
         raise BootmgmtWriteError('Properties are read-only on systems '
                                  'with BIOS firmware')
     raise BootmgmtUnsupportedOperationError(
         'Properties cannot be set '
         'on systems with BIOS firmware')
 def getprop(self, propname):
     if not propname == SystemFirmware.PROP_BOOT_DEVICE:
         raise BootmgmtUnsupportedOperationError('Property not supported')
     # libdevinfo's devfs_bootdev_get_list returns an ordered list of
     # boot devices.  The form of the return value is a tuple of tuples:
     # ((<physpath>, (<logicalpath1>, <logicalpath2>, ...), ...)
     if propname == SystemFirmware.PROP_BOOT_DEVICE:
         return devfs_bootdev_get_list()
Example #7
0
    def _menu_lst_dir_disk(self):
        fstype = self._boot_config.boot_fstype
        if fstype != 'zfs' and fstype != 'ufs':
            raise BootmgmtUnsupportedOperationError('Unknown filesystem: %s' %
                                                    fstype)
        if fstype == 'zfs':
            menu_lst_dir = self._boot_config.zfstop
        elif fstype == 'ufs':
            menu_lst_dir = self._boot_config.get_root()

        return menu_lst_dir
Example #8
0
    def __init__(self, flags, **kwargs):
        ""
        # Weed out unsupported flags:
        if BootConfig.BCF_MIGRATE in flags:
            raise BootmgmtUnsupportedOperationError(self.__class__.__name__ +
                                                    ': Migration is not \
                                                    supported')

        # Save the image's root directory:
        self.odd_image_root = kwargs.get('oddimage_root', None)
        if self.odd_image_root is None:
            raise BootmgmtArgumentError('Missing oddimage_root argument')

        super(self.__class__,
              self).__init__(flags,
                             boot_class=BootConfig.BOOT_CLASS_ODD,
                             **kwargs)
Example #9
0
    def _write_config(self, basepath):
        """There are two files that need to be written: the menu.lst file,
        using information from the BootConfig instance to which we have a
        reference, and the bootlst program (which will be copied from the
        data source boot instance's mounted filesystem.)
        """

        if self._boot_config is None:
            msg = 'Cannot _write_config(%s) - _boot_config is None' % basepath
            self._debug(msg)
            raise BootmgmtInterfaceCodingError(msg)
        elif self._boot_config.boot_class != BootConfig.BOOT_CLASS_DISK:
            msg = ('ZFS boot block boot loader does not support non-disk '
                   'configs')
            raise BootmgmtUnsupportedOperationError(msg)

        return self._write_config_disk(basepath)
Example #10
0
    def _write_config_disk(self, basepath):
        """Write the boot loader's configuration file and boot program to
        disk"""

        if self._boot_config.boot_fstype != 'zfs':
            raise BootmgmtUnsupportedOperationError(
                'Filesystem type %s '
                'not supported by the SPARC ZFS boot block' %
                self._boot_config.boot_fstype)

        dataroot_dir = self._zfs_boot_data_rootdir_disk()

        generic_tuples = self._write_config_generic(basepath, dataroot_dir)

        bootlst_tuples = self._write_bootlst(basepath, dataroot_dir)

        if basepath is None:
            return None

        tuples = []
        if generic_tuples is not None:
            tuples += generic_tuples
        if bootlst_tuples is not None:
            tuples += bootlst_tuples

        for idx, item in enumerate(tuples):
            if (item[BootConfig.IDX_FILETYPE] == BootConfig.OUTPUT_TYPE_FILE
                    and item[BootConfig.IDX_DESTNAME]
                    in (ZFSBootLoader.MENU_LST_PATH,
                        ZFSBootLoader.BOOTLST_PATH)):

                # Make a copy of the tuple so we can change it:
                item = list(item)

                item[BootConfig.IDX_DESTNAME] = (
                    '%(' + DiskBootConfig.TOKEN_ZFS_RPOOL_TOP_DATASET + ')s' +
                    item[BootConfig.IDX_DESTNAME])

                # Update tuple in the list:
                tuples[idx] = tuple(item)

        return tuples
Example #11
0
    def _write_config(self, basepath):
        """The only file that needs to be written is the menu.lst file, using
        information from the BootConfig instance to which we have a reference.
        Information from the boot loader's properties is also used to
        determine which commands are emitted at the global level"""

        if self._boot_config is None:
            msg = ('Cannot _write_config(%s) - _boot_config is None' %
                   str(basepath))
            self._debug(msg)
            raise BootmgmtInterfaceCodingError(msg)

        # Determine the type of boot configuration we're dealing with, then
        # determine the filesystem type that will hold the menu.lst.  Only
        # then can we tell the caller the appropriate path to copy it into.
        if self._boot_config.boot_class == BootConfig.BOOT_CLASS_DISK:
            return self._write_config_disk(basepath)
        elif self._boot_config.boot_class == BootConfig.BOOT_CLASS_ODD:
            return self._write_config_odd(basepath)
        else:
            raise BootmgmtUnsupportedOperationError('XXX - Fix Me')
Example #12
0
    def probe(cls, **kwargs):
        """Probe for Legacy GRUB files for use with the BootConfig passed
        in"""

        if get_current_arch_string() != 'x86':
            cls._debug('Legacy GRUB boot loader not supported on this '
                       'platform')
            return (None, None)

        bootconfig = kwargs.get('bootconfig', None)

        if (bootconfig is None or bootconfig.boot_class is None):
            return (None, None)

        if (bootconfig.boot_class == BootConfig.BOOT_CLASS_DISK
                and bootconfig.boot_fstype is not None):
            return LegacyGRUBBootLoader._probe_disk(**kwargs)
        elif bootconfig.boot_class == BootConfig.BOOT_CLASS_ODD:
            return LegacyGRUBBootLoader._probe_odd(**kwargs)
        else:
            raise BootmgmtUnsupportedOperationError('XXX - Fix Me')
Example #13
0
    def probe(**kwargs):
        """Probe for ZFS boot block files for use with the BootConfig passed
        in"""

        try:
            OBPBootLoader.probe_generic(**kwargs)
        except BootmgmtError:
            return (None, None)

        bootconfig = kwargs.get('bootconfig', None)

        if (bootconfig is None or bootconfig.boot_class is None):
            return (None, None)

        if (bootconfig.boot_class == BootConfig.BOOT_CLASS_DISK
                and bootconfig.boot_fstype == 'zfs'):
            return ZFSBootLoader._probe_disk(**kwargs)
        else:
            raise BootmgmtUnsupportedOperationError(
                'ZFSBootLoader only '
                'supports ZFS-based disk boot '
                'configurations')
Example #14
0
    def autogen(self, bootconfig):
        "The workhorse of the autogenerator"

        # XXX - Handle bootconfig instances that have boot_class != disk
        if bootconfig.boot_class != BootConfig.BOOT_CLASS_DISK:
            raise BootmgmtUnsupportedOperationError('XXX - Fix Me')

        # This is only supported on x86:
        if get_current_arch_string() != 'x86':
            self._debug('Chainloader entry autogeneration only supported on '
                        'x86')
            return []

        try:
            helper_cmd = ['/usr/lib/boot/bootmgmt-helper-chain']
            script_output = Popen.check_call(helper_cmd, stdout=Popen.STORE,
                stderr=Popen.STORE)
            script_stdout = script_output.stdout
        except OSError as error_exc:
            self._debug('Executing helper script failed: %s' % error_exc)
            return []
        except CalledProcessError as cpe:
            self._debug('Helper script returned %d' % cpe.returncode)
            if cpe.popen and cpe.popen.stdout:
                self._debug('stdout was: %s\n' % cpe.popen.stdout)
            if cpe.popen and cpe.popen.stderr:
                self._debug('stderr was: %s\n' % cpe.popen.stderr)
            return []

        inst_list = []

        lineno = 0
        for line in script_stdout.splitlines():
            lineno += 1
            self._debug('Output line %d: "%s"' % (lineno, line))
            if line.startswith('#') or line.strip() == '':
                continue
            try:
                title, disk, partition, active = line.split(':')

                disk = int(disk)
                # partition can be empty, an int or a comma-separated list of
                # strings
                if partition.strip() != '':
                    if partition.find(',') != -1:
                        partition = tuple(partition.split(','))
                    else:
                        partition = int(partition)
                else:
                    partition = None

                active = True if active == 'True' else False

            except ValueError:
                self._debug('Malformed output line from helper: "%s"' % line)
                continue

            if partition is None:
                chain_info = (disk,)
            else:
                chain_info = (disk, partition)

            bootinst = ChainDiskBootInstance(None, title=title,
                                             chaininfo=chain_info,
                                             forceactive=active)
            inst_list.append(bootinst)

        self._debug('%d line(s) read from helper script.' % lineno)
        self._debug('%d boot instances autogenerated.' % len(inst_list))

        return inst_list
Example #15
0
    def __init__(self, flags, **kwargs):
        """
        Initialize the basic set of attributes for all BootConfig classes
        -----------------------------------------------------------------
        Argument|  Valid Value(s)
        --------+--------------------------------------------------------
        flags   | <Tuple of flags that modify the behavior of this
                |  BootConfig object> [tuple]
                |
                | Allowed values in the tuple:
                | ----------------------------
                | BootConfig.BCF_CREATE: Create a new boot
                |                        configuration.  If one already 
                |                        exists, it will be discarded.
                |                        If this flag is not present and
                |                        no boot configuration exists,
                |                        an exception
                |                        (BootmgmtConfigurationReadError)
                |                        will be raised.
                | BootConfig.BCF_ONESHOT:If True, only the final boot
                |                        configuration files will be
                |                        created when the
                |                        commit_boot_config() is called.
                |                        This is useful for one-shot
                |                        creation of boot configurations
                |                        for installation media.
                | BootConfig.BCF_AUTOGEN:The set of boot instances will be
                |                        automatically generated by
                |                        scanning the system.  The list of
                |                        boot instances found by the scan
                |                        will be available after
                |                        the BootConfig object is created.
                |                        This set of boot instances can
                |                        then be tailored before calling
                |                        commit_boot_config().  Note that
                |                        the set of BootInstance objects
                |                        added to this object's boot_instances
                |                        are only guaranteed to include
                |                        Solaris boot instances.
                | BootConfig.BCF_MIGRATE:If supported, the existing boot
                |                        configuration will be migrated
                |                        from an older form to a newer
                |                        form (i.e. conversion from legacy
                |                        GRUB's menu.lst to GRUB2's
                |                        configuration format). The conversion
                |                        is performed at commit_boot_config()
                |                        time.  Cannot be used with the
                |                        BCF_CREATE flag.
                |
        platform| [optional] The target system architecture / firmware for
        (keyword| which this boot configuration will be written.  Useful
         arg)   | for the creation of boot configuration files for network
                | boot instances, or when a boot configuration is created
                | on a system of a different architecture / firmware than
                | the target.  If this is not supplied, the assumption is
                | that the boot configuration will be for the current
                | system.  Supported tuple values are:
                | { ('sparc', 'obp' (or None)),
                |   ('x86', 'bios' (or None)),
                |   ('x86', 'uefi64') }
                | If a particular BootConfig subclass does not support  
                | manipulation of a different platform's boot
                | configuration, a BootmgmtNotSupportedError will be
                | raised.
        -----------------------------------------------------------------
        """

        self.boot_instances = []
        self.boot_class = kwargs.get('boot_class', None)
        self.boot_fstype = kwargs.get('boot_fstype', None)
        self._platform = kwargs.get('platform', None)
        self._dirty = False
        self._flags = flags
        self.boot_loader = self._get_boot_loader(**kwargs)

        if (BootConfig.BCF_CREATE in self._flags
                and BootConfig.BCF_MIGRATE in self._flags):
            raise BootmgmtUnsupportedOperationError(
                'Migration cannot be combined with creation')

        if BootConfig.BCF_CREATE in self._flags:
            self._new_boot_config(**kwargs)
        else:
            # _load_boot_config raises BootmgmtConfigurationReadError
            self._load_boot_config(**kwargs)
            self.dirty = False

        if BootConfig.BCF_AUTOGEN in self._flags:
            self._autogenerate_config(**kwargs)
Example #16
0
 def delprop(self, propname):
     """Deleting properties is not supported on BIOS systems"""
     raise BootmgmtUnsupportedOperationError(
         'Properties cannot be '
         'deleted on systems with BIOS firmware')