Пример #1
0
def get_deploy_info(node, address, iqn, port=None, lun='1'):
    """Returns the information required for doing iSCSI deploy in a dictionary.

    :param node: ironic node object
    :param address: iSCSI address
    :param iqn: iSCSI iqn for the target disk
    :param port: iSCSI port, defaults to one specified in the configuration
    :param lun: iSCSI lun, defaults to '1'
    :raises: MissingParameterValue, if some required parameters were not
        passed.
    :raises: InvalidParameterValue, if any of the parameters have invalid
        value.
    """
    i_info = deploy_utils.parse_instance_info(node)

    params = {
        'address': address,
        'port': port or CONF.iscsi.portal_port,
        'iqn': iqn,
        'lun': lun,
        'image_path': _get_image_file_path(node.uuid),
        'node_uuid': node.uuid
    }

    is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
    if not is_whole_disk_image:
        params.update({
            'root_mb': i_info['root_mb'],
            'swap_mb': i_info['swap_mb'],
            'ephemeral_mb': i_info['ephemeral_mb'],
            'preserve_ephemeral': i_info['preserve_ephemeral'],
            'boot_option': deploy_utils.get_boot_option(node),
            'boot_mode': _get_boot_mode(node)
        })

        # Append disk label if specified
        disk_label = deploy_utils.get_disk_label(node)
        if disk_label is not None:
            params['disk_label'] = disk_label

    missing = [key for key in params if params[key] is None]
    if missing:
        raise exception.MissingParameterValue(
            _("Parameters %s were not passed to ironic"
              " for deploy.") % missing)

    # configdrive is nullable
    params['configdrive'] = i_info.get('configdrive')
    if is_whole_disk_image:
        return params

    # ephemeral_format is nullable
    params['ephemeral_format'] = i_info.get('ephemeral_format')

    return params
Пример #2
0
    def set_indicator_state(self, task, component, indicator, state):
        """Set indicator on the hardware component to the desired state.

        :param task: A task from TaskManager.
        :param component: The hardware component, one of
            :mod:`ironic.common.components`.
        :param indicator: Indicator ID (as reported by
            `get_supported_indicators`).
        :param state: Desired state of the indicator, one of
            :mod:`ironic.common.indicator_states`.
        :raises: InvalidParameterValue if an invalid component, indicator
                 or state is specified.
        :raises: MissingParameterValue if a required parameter is missing
        :raises: RedfishError on an error from the Sushy library
        """
        system = redfish_utils.get_system(task.node)

        try:
            if (component == components.SYSTEM and indicator == system.uuid):
                system.set_indicator_led(INDICATOR_MAP_REV[state])
                return

            elif (component == components.CHASSIS and system.chassis):
                for chassis in system.chassis:
                    if chassis.uuid == indicator:
                        chassis.set_indicator_led(INDICATOR_MAP_REV[state])
                        return

            elif (component == components.DISK and system.simple_storage
                  and system.simple_storage.drives):
                for drive in system.simple_storage.drives:
                    if drive.uuid == indicator:
                        drive.set_indicator_led(INDICATOR_MAP_REV[state])
                        return

        except sushy.exceptions.SushyError as e:
            error_msg = (_('Redfish set %(component)s indicator %(indicator)s '
                           'state %(state)s failed for node %(node)s. Error: '
                           '%(error)s') % {
                               'component': component,
                               'indicator': indicator,
                               'state': state,
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.RedfishError(error=error_msg)

        raise exception.MissingParameterValue(
            _("Unknown indicator %(indicator)s for component %(component)s of "
              "node %(uuid)s") % {
                  'indicator': indicator,
                  'component': component,
                  'uuid': task.node.uuid
              })
Пример #3
0
    def validate(self, task):
        """Validate the driver-specific Node deployment info.

        This method validates whether the properties of the supplied node
        contain the required information for this driver to deploy images to
        the node.

        :param task: a TaskManager instance
        :raises: MissingParameterValue, if any of the required parameters are
            missing.
        :raises: InvalidParameterValue, if any of the parameters have invalid
            value.
        """
        if CONF.agent.manage_agent_boot:
            task.driver.boot.validate(task)

        node = task.node

        # Validate node capabilities
        deploy_utils.validate_capabilities(node)

        if not task.driver.storage.should_write_image(task):
            # NOTE(TheJulia): There is no reason to validate
            # image properties if we will not be writing an image
            # in a boot from volume case. As such, return to the caller.
            return

        params = {}
        image_source = node.instance_info.get('image_source')
        params['instance_info.image_source'] = image_source
        error_msg = _('Node %s failed to validate deploy image info. Some '
                      'parameters were missing') % node.uuid

        deploy_utils.check_for_missing_params(params, error_msg)

        if not service_utils.is_glance_image(image_source):
            if not node.instance_info.get('image_checksum'):
                raise exception.MissingParameterValue(
                    _("image_source's image_checksum must be provided in "
                      "instance_info for node %s") % node.uuid)

        check_image_size(task, image_source)
        # Validate the root device hints
        try:
            root_device = node.properties.get('root_device')
            il_utils.parse_root_device_hints(root_device)
        except ValueError as e:
            raise exception.InvalidParameterValue(
                _('Failed to validate the root device hints for node '
                  '%(node)s. Error: %(error)s') % {
                      'node': node.uuid,
                      'error': e
                  })

        validate_image_proxies(node)
Пример #4
0
    def _validate_common(self, task):
        node = task.node

        if not driver_utils.get_node_mac_addresses(task):
            raise exception.MissingParameterValue(
                _("Node %s does not have any port associated with it.")
                % node.uuid)

        if self.ipxe_enabled:
            if not CONF.deploy.http_url or not CONF.deploy.http_root:
                raise exception.MissingParameterValue(_(
                    "iPXE boot is enabled but no HTTP URL or HTTP "
                    "root was specified."))

        # Check the trusted_boot capabilities value.
        deploy_utils.validate_capabilities(node)
        if deploy_utils.is_trusted_boot_requested(node):
            # Check if 'boot_option' and boot mode is compatible with
            # trusted boot.
            if self.ipxe_enabled:
                # NOTE(TheJulia): So in theory (huge theory here, not put to
                # practice or tested), that one can define the kernel as tboot
                # and define the actual kernel and ramdisk as appended data.
                # Similar to how one can iPXE load the XEN hypervisor.
                # tboot mailing list seem to indicate pxe/ipxe support, or
                # more specifically avoiding breaking the scenarios of use,
                # but there is also no definitive documentation on the subject.
                LOG.warning('Trusted boot has been requested for %(node)s in '
                            'concert with iPXE. This is not a supported '
                            'configuration for an ironic deployment.',
                            {'node': node.uuid})
            pxe_utils.validate_boot_parameters_for_trusted_boot(node)

        # Check if we have invalid parameters being passed which will not work
        # for ramdisk configurations.
        if (node.instance_info.get('image_source')
            and node.instance_info.get('boot_iso')):
            raise exception.InvalidParameterValue(_(
                "An 'image_source' and 'boot_iso' parameter may not be "
                "specified at the same time."))

        pxe_utils.parse_driver_info(node)
Пример #5
0
def get_deploy_info(node, **kwargs):
    """Returns the information required for doing iSCSI deploy in a dictionary.

    :param node: ironic node object
    :param kwargs: the keyword args passed from the conductor node.
    :raises: MissingParameterValue, if some required parameters were not
        passed.
    :raises: InvalidParameterValue, if any of the parameters have invalid
        value.
    """
    deploy_key = kwargs.get('key')
    i_info = deploy_utils.parse_instance_info(node)
    if i_info['deploy_key'] != deploy_key:
        raise exception.InvalidParameterValue(_("Deploy key does not match"))

    params = {
        'address': kwargs.get('address'),
        'port': kwargs.get('port', CONF.iscsi.portal_port),
        'iqn': kwargs.get('iqn'),
        'lun': kwargs.get('lun', '1'),
        'image_path': _get_image_file_path(node.uuid),
        'node_uuid': node.uuid
    }

    is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
    if not is_whole_disk_image:
        params.update({
            'root_mb': 1024 * int(i_info['root_gb']),
            'swap_mb': int(i_info['swap_mb']),
            'ephemeral_mb': 1024 * int(i_info['ephemeral_gb']),
            'preserve_ephemeral': i_info['preserve_ephemeral'],
            'boot_option': deploy_utils.get_boot_option(node),
            'boot_mode': _get_boot_mode(node)
        })

        # Append disk label if specified
        disk_label = deploy_utils.get_disk_label(node)
        if disk_label is not None:
            params['disk_label'] = disk_label

    missing = [key for key in params if params[key] is None]
    if missing:
        raise exception.MissingParameterValue(
            _("Parameters %s were not passed to ironic"
              " for deploy.") % missing)

    if is_whole_disk_image:
        return params

    # configdrive and ephemeral_format are nullable
    params['ephemeral_format'] = i_info.get('ephemeral_format')
    params['configdrive'] = i_info.get('configdrive')

    return params
Пример #6
0
 def _test_create_configuration_skip_root_skip_non_root(
         self, ilo_mock, filter_target_raid_config_mock):
     ilo_mock_object = ilo_mock.return_value
     with task_manager.acquire(self.context, self.node.uuid) as task:
         msg = "Node %s has no target RAID configuration" % self.node.uuid
         filter_target_raid_config_mock.side_effect = (
             exception.MissingParameterValue(msg))
         self.assertRaises(exception.MissingParameterValue,
                           task.driver.raid.create_configuration, task,
                           False, False)
         self.assertFalse(ilo_mock_object.create_raid_configuration.called)
Пример #7
0
def _parse_driver_info(node):
    """Parses and creates seamicro driver info

    :param node: An Ironic node object.
    :returns: SeaMicro driver info.
    :raises: MissingParameterValue if any required parameters are missing.
    :raises: InvalidParameterValue if required parameter are invalid.
    """

    info = node.driver_info or {}
    missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)]
    if missing_info:
        raise exception.MissingParameterValue(
            _("SeaMicro driver requires the following parameters to be set in"
              " node's driver_info: %s.") % missing_info)

    api_endpoint = info.get('seamicro_api_endpoint')
    username = info.get('seamicro_username')
    password = info.get('seamicro_password')
    server_id = info.get('seamicro_server_id')
    api_version = info.get('seamicro_api_version', "2")
    port = info.get('seamicro_terminal_port')

    if port:
        try:
            port = int(port)
        except ValueError:
            raise exception.InvalidParameterValue(
                _("SeaMicro terminal port is not an integer."))

    r = re.compile(r"(^[0-9]+)/([0-9]+$)")
    if not r.match(server_id):
        raise exception.InvalidParameterValue(
            _("Invalid 'seamicro_server_id' parameter in node's "
              "driver_info. Expected format of 'seamicro_server_id' "
              "is <int>/<int>"))

    url = urlparse.urlparse(api_endpoint)
    if (not (url.scheme == "http") or not url.netloc):
        raise exception.InvalidParameterValue(
            _("Invalid 'seamicro_api_endpoint' parameter in node's "
              "driver_info."))

    res = {
        'username': username,
        'password': password,
        'api_endpoint': api_endpoint,
        'server_id': server_id,
        'api_version': api_version,
        'uuid': node.uuid,
        'port': port
    }

    return res
Пример #8
0
def _parse_parameters(task):
    driver_info = task.node.driver_info
    host = driver_info.get('wol_host', '255.255.255.255')
    port = driver_info.get('wol_port', 9)
    port = utils.validate_network_port(port, 'wol_port')

    if len(task.ports) < 1:
        raise exception.MissingParameterValue(
            _('Wake-On-Lan needs at least one port resource to be '
              'registered in the node'))

    return {'host': host, 'port': port}
Пример #9
0
    def _get_ports_collection(self,
                              node_ident,
                              address,
                              marker,
                              limit,
                              sort_key,
                              sort_dir,
                              resource_url=None,
                              fields=None):
        if self.from_nodes and not node_ident:
            raise exception.MissingParameterValue(
                _("Node identifier not specified."))

        limit = api_utils.validate_limit(limit)
        sort_dir = api_utils.validate_sort_dir(sort_dir)

        marker_obj = None
        if marker:
            marker_obj = objects.Port.get_by_uuid(pecan.request.context,
                                                  marker)

        if sort_key in self.invalid_sort_key_list:
            raise exception.InvalidParameterValue(
                _("The sort_key value %(key)s is an invalid field for "
                  "sorting") % {'key': sort_key})

        if node_ident:
            # FIXME(comstud): Since all we need is the node ID, we can
            #                 make this more efficient by only querying
            #                 for that column. This will get cleaned up
            #                 as we move to the object interface.
            node = api_utils.get_rpc_node(node_ident)
            ports = objects.Port.list_by_node_id(pecan.request.context,
                                                 node.id,
                                                 limit,
                                                 marker_obj,
                                                 sort_key=sort_key,
                                                 sort_dir=sort_dir)
        elif address:
            ports = self._get_ports_by_address(address)
        else:
            ports = objects.Port.list(pecan.request.context,
                                      limit,
                                      marker_obj,
                                      sort_key=sort_key,
                                      sort_dir=sort_dir)

        return PortCollection.convert_with_links(ports,
                                                 limit,
                                                 url=resource_url,
                                                 fields=fields,
                                                 sort_key=sort_key,
                                                 sort_dir=sort_dir)
Пример #10
0
def _check_required_properties(driver_info):
    """Checks if all required properties are present.

    :param driver_info: the node's driver_info dict.
    :raises: MissingParameterValue if one or more required properties are
        missing.
    """
    missing_properties = set(REQUIRED_PROPERTIES) - set(driver_info)
    if missing_properties:
        raise exception.MissingParameterValue(
            _('The following parameters were missing: %s') %
            ' '.join(missing_properties))
Пример #11
0
    def validate(self, task):
        """Validate the Node console info.

        :param task: a task from TaskManager.
        :raises: InvalidParameterValue
        :raises: MissingParameterValue when a required parameter is missing

        """
        driver_info = _parse_driver_info(task.node)
        if not driver_info['port']:
            raise exception.MissingParameterValue(
                _("IPMI terminal port not supplied to IPMI driver."))
Пример #12
0
    def _validate_iscsi_connectors(self, task):
        """Validate if volume connectors are properly registered for iSCSI.

        For connecting a node to a iSCSI volume, volume connectors containing
        an IQN and an IP address are necessary. One of connectors must have
        a physical ID of the PCI card. Network size of a storage network is
        also required by iRMC. which should be registered in the node's
        driver_info.

        :param task: a TaskManager instance containing the node to act on.
        :raises: InvalidParameterValue if a volume connector with a required
            type is not registered.
        :raises: InvalidParameterValue if a physical ID is not registered in
            any volume connectors.
        :raises: InvalidParameterValue if a physical ID is invalid.
        """
        vc_dict = self._get_volume_connectors_by_type(task)
        node = task.node
        missing_types = []
        for vc_type in ('iqn', 'ip'):
            vc = vc_dict.get(vc_type)
            if not vc:
                missing_types.append(vc_type)

        if missing_types:
            raise exception.MissingParameterValue(
                _('Failed to validate for node %(node)s because of missing '
                  'volume connector(s) with type(s) %(types)s') % {
                      'node': node.uuid,
                      'types': ', '.join(missing_types)
                  })

        if not self._get_connector_physical_id(task, ['iqn', 'ip']):
            raise exception.MissingParameterValue(
                _('Failed to validate for node %(node)s because of missing '
                  'physical port information for iSCSI connector. This '
                  'information must be set in "pci_physical_ids" parameter of '
                  'node\'s driver_info as <connector uuid>:<physical id>.') %
                {'node': node.uuid})
        self._get_network_size(node)
Пример #13
0
def parse_driver_info(node):
    """Gets the driver specific Node info.

    This method validates whether the 'driver_info' property of the
    supplied node contains the required information for this driver.

    :param node: an ironic Node object.
    :returns: a dict containing information from driver_info (or where
        applicable, config values).
    :raises: InvalidParameterValue if any parameters are incorrect
    :raises: MissingParameterValue if some mandatory information
        is missing on the node
    """
    info = node.driver_info
    d_info = {}

    missing_info = []
    for param in REQUIRED_PROPERTIES:
        try:
            d_info[param] = info[param]
        except KeyError:
            missing_info.append(param)
    if missing_info:
        raise exception.MissingParameterValue(
            _("The following required iLO parameters are missing from the "
              "node's driver_info: %s") % missing_info)

    not_integers = []
    for param in OPTIONAL_PROPERTIES:
        value = info.get(param, CONF.ilo.get(param))
        if param == "client_port":
            d_info[param] = utils.validate_network_port(value, param)
        else:
            try:
                d_info[param] = int(value)
            except ValueError:
                not_integers.append(param)

    for param in CONSOLE_PROPERTIES:
        value = info.get(param)
        if value:
            # Currently there's only "console_port" parameter
            # in CONSOLE_PROPERTIES
            if param == "console_port":
                d_info[param] = utils.validate_network_port(value, param)

    if not_integers:
        raise exception.InvalidParameterValue(
            _("The following iLO parameters from the node's driver_info "
              "should be integers: %s") % not_integers)

    return d_info
Пример #14
0
def parse_driver_info(node):
    """Parse the information required for Ironic to connect to iBMC.

    :param node: an Ironic node object
    :returns: dictionary of parameters
    :raises: InvalidParameterValue on malformed parameter(s)
    :raises: MissingParameterValue on missing parameter(s)
    """
    driver_info = node.driver_info or {}
    missing_info = [key for key in REQUIRED_PROPERTIES
                    if not driver_info.get(key)]
    if missing_info:
        raise exception.MissingParameterValue(_(
            'Missing the following iBMC properties in node '
            '%(node)s driver_info: %(info)s') % {'node': node.uuid,
                                                 'info': missing_info})

    # Validate the iBMC address
    address = driver_info['ibmc_address']
    if '://' not in address:
        address = 'https://%s' % address

    parsed = netutils.urlsplit(address)
    if not parsed.netloc:
        raise exception.InvalidParameterValue(
            _('Invalid iBMC address %(address)s set in '
              'driver_info/ibmc_address on node %(node)s') %
            {'address': address, 'node': node.uuid})

    # Check if verify_ca is a Boolean or a file/directory in the file-system
    verify_ca = driver_info.get('ibmc_verify_ca', True)
    if isinstance(verify_ca, str):
        if not os.path.exists(verify_ca):
            try:
                verify_ca = strutils.bool_from_string(verify_ca, strict=True)
            except ValueError:
                raise exception.InvalidParameterValue(
                    _('Invalid value type set in driver_info/'
                      'ibmc_verify_ca on node %(node)s. '
                      'The value should be a Boolean or the path '
                      'to a file/directory, not "%(value)s"'
                      ) % {'value': verify_ca, 'node': node.uuid})
    elif not isinstance(verify_ca, bool):
        raise exception.InvalidParameterValue(
            _('Invalid value type set in driver_info/ibmc_verify_ca '
              'on node %(node)s. The value should be a Boolean or the path '
              'to a file/directory, not "%(value)s"') % {'value': verify_ca,
                                                         'node': node.uuid})
    return {'address': address,
            'username': driver_info.get('ibmc_username'),
            'password': driver_info.get('ibmc_password'),
            'verify_ca': verify_ca}
Пример #15
0
    def validate(self, task):
        """Validate the Node console info.

        :param task: a TaskManager instance containing the node to act on.
        :raises: MissingParameterValue when required IPMI credentials or
            the IPMI terminal port are missing
        :raises: InvalidParameterValue when the IPMI terminal port is not
                an integer.
        """
        driver_info = _parse_driver_info(task.node)
        if not driver_info['port']:
            raise exception.MissingParameterValue(_(
                "IPMI terminal port not supplied to the IPMI driver."))
Пример #16
0
def _verify_node_info(node_namespace, node_info_dict, info_required):
    """Verify if info_required is present in node_namespace."""
    missing_keys = set(info_required) - set(node_info_dict)

    if missing_keys:
        raise exception.MissingParameterValue(
            _("Missing the keys for the following OneView data in node's "
              "%(namespace)s: %(missing_keys)s.") %
            {'namespace': node_namespace,
             'missing_keys': ', '.join(missing_keys)
             }
        )

    # False and 0 can still be considered as valid values
    missing_values_keys = [k for k in info_required
                           if node_info_dict[k] in ('', None)]
    if missing_values_keys:
        missing_keys = ["%s:%s" % (node_namespace, k)
                        for k in missing_values_keys]
        raise exception.MissingParameterValue(
            _("Missing parameter value for: '%s'") % "', '".join(missing_keys)
        )
Пример #17
0
    def validate(self, task):
        info = task.node.instance_info

        for item in REQUIRED_PROPERTIES:
            if not info.get(item):
                error_msg = _(
                    "Cannot validate driver deploy. Some parameters were missing"
                    " in node's instance_info")
                exc_msg = _("%(error_msg)s. Missing are: %(missing_info)s")
                raise exception.MissingParameterValue(exc_msg % {
                    'error_msg': error_msg,
                    'missing_info': item
                })
Пример #18
0
    def validate(self, task):
        """Validate the Node console info.

        :param task: a task from TaskManager.
        :raises: MissingParameterValue if required seamicro parameters are
                 missing
        :raises: InvalidParameterValue if required parameter are invalid.
        """
        driver_info = _parse_driver_info(task.node)
        if not driver_info['port']:
            raise exception.MissingParameterValue(
                _("Missing 'seamicro_terminal_port' parameter in node's "
                  "driver_info"))
Пример #19
0
 def test_clean_up_fail_get_image_info(self, mock_image_info, mock_cache,
                                       mock_pxe_clean, mock_iscsi_clean,
                                       mock_unlink):
     mock_image_info.side_effect = exception.MissingParameterValue('foo')
     with task_manager.acquire(self.context, self.node.uuid,
                               shared=True) as task:
         task.driver.deploy.clean_up(task)
         mock_image_info.assert_called_once_with(task.node, task.context)
         mock_pxe_clean.assert_called_once_with(task)
         mock_unlink.assert_called_once_with(
             pxe._get_token_file_path(task.node.uuid))
         mock_iscsi_clean.assert_called_once_with(task.node.uuid)
     mock_cache.return_value.clean_up.assert_called_once_with()
Пример #20
0
def parse_driver_info(node):
    """Gets the driver specific Node deployment info.

    This method validates whether the 'driver_info' property of the
    supplied node contains the required information for this driver.

    :param node: an ironic node object.
    :returns: a dict containing information from driver_info
        and default values.
    :raises: InvalidParameterValue on invalid inputs.
    :raises: MissingParameterValue if some mandatory information
        is missing on the node
    """
    info = node.driver_info
    d_info = {}

    error_msgs = []
    for param in REQUIRED_PROPERTIES:
        try:
            d_info[param] = info[param]
        except KeyError:
            error_msgs.append(_("'%s' not supplied to IloDriver.") % param)
    if error_msgs:
        msg = (_("The following parameters were mising while parsing "
                 "driver_info:\n%s") % "\n".join(error_msgs))
        raise exception.MissingParameterValue(msg)

    for param in OPTIONAL_PROPERTIES:
        value = info.get(param, CONF.ilo.get(param))
        try:
            value = int(value)
        except ValueError:
            error_msgs.append(_("'%s' is not an integer.") % param)
            continue
        d_info[param] = value

    for param in CONSOLE_PROPERTIES:
        value = info.get(param)
        if value:
            try:
                value = int(value)
                d_info[param] = value
            except ValueError:
                error_msgs.append(_("'%s' is not an integer.") % param)

    if error_msgs:
        msg = (_("The following errors were encountered while parsing "
                 "driver_info:\n%s") % "\n".join(error_msgs))
        raise exception.InvalidParameterValue(msg)

    return d_info
Пример #21
0
    def validate(self, task):
        """Validate the deployment information for the task's node.

        :param task: a TaskManager instance containing the node to act on.
        :raises: InvalidParameterValue.
        :raises: MissingParameterValue
        """
        node = task.node

        # Check the boot_mode and boot_option capabilities values.
        deploy_utils.validate_capabilities(node)

        boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node)

        if CONF.pxe.ipxe_enabled:
            if not CONF.pxe.http_url or not CONF.pxe.http_root:
                raise exception.MissingParameterValue(
                    _("iPXE boot is enabled but no HTTP URL or HTTP "
                      "root was specified."))
            # iPXE and UEFI should not be configured together.
            if boot_mode == 'uefi':
                LOG.error(
                    _LE("UEFI boot mode is not supported with "
                        "iPXE boot enabled."))
                raise exception.InvalidParameterValue(
                    _("Conflict: iPXE is enabled, but cannot be used with node"
                      "%(node_uuid)s configured to use UEFI boot") %
                    {'node_uuid': node.uuid})

        # Check if 'boot_option' is compatible with 'boot_mode' of uefi and
        # image being deployed
        if boot_mode == 'uefi':
            validate_boot_option_for_uefi(task.node)

        if deploy_utils.is_trusted_boot_requested(task.node):
            # Check if 'boot_option' and boot mode is compatible with
            # trusted boot.
            validate_boot_parameters_for_trusted_boot(task.node)

        d_info = _parse_deploy_info(node)

        iscsi_deploy.validate(task)

        if node.driver_internal_info.get('is_whole_disk_image'):
            props = []
        elif service_utils.is_glance_image(d_info['image_source']):
            props = ['kernel_id', 'ramdisk_id']
        else:
            props = ['kernel', 'ramdisk']

        iscsi_deploy.validate_image_properties(task.context, d_info, props)
Пример #22
0
    def driver_validate(self, method, **kwargs):
        """Validate the driver deployment info.

        :param method: method to be validated.
        """
        version = kwargs.get('version')

        if not version:
            raise exception.MissingParameterValue(_('Missing parameter '
                                                    'version'))
        if version not in self.supported_payload_versions:
            raise exception.InvalidParameterValue(_('Unknown lookup '
                                                    'payload version: %s')
                                                  % version)
Пример #23
0
    def _get_nodes_collection(self,
                              chassis_uuid,
                              instance_uuid,
                              associated,
                              maintenance,
                              marker,
                              limit,
                              sort_key,
                              sort_dir,
                              expand=False,
                              resource_url=None):
        if self.from_chassis and not chassis_uuid:
            raise exception.MissingParameterValue(
                _("Chassis id not specified."))

        limit = api_utils.validate_limit(limit)
        sort_dir = api_utils.validate_sort_dir(sort_dir)

        marker_obj = None
        if marker:
            marker_obj = objects.Node.get_by_uuid(pecan.request.context,
                                                  marker)
        if instance_uuid:
            nodes = self._get_nodes_by_instance(instance_uuid)
        else:
            filters = {}
            if chassis_uuid:
                filters['chassis_uuid'] = chassis_uuid
            if associated is not None:
                filters['associated'] = associated
            if maintenance is not None:
                filters['maintenance'] = maintenance

            nodes = objects.Node.list(pecan.request.context,
                                      limit,
                                      marker_obj,
                                      sort_key=sort_key,
                                      sort_dir=sort_dir,
                                      filters=filters)

        parameters = {'sort_key': sort_key, 'sort_dir': sort_dir}
        if associated:
            parameters['associated'] = associated
        if maintenance:
            parameters['maintenance'] = maintenance
        return NodeCollection.convert_with_links(nodes,
                                                 limit,
                                                 url=resource_url,
                                                 expand=expand,
                                                 **parameters)
Пример #24
0
 def _validate_temp_url_config(self):
     """Validate the required settings for a temporary URL."""
     if not CONF.glance.swift_temp_url_key:
         raise exc.MissingParameterValue(_(
             'Swift temporary URLs require a shared secret to be created. '
             'You must provide "swift_temp_url_key" as a config option.'))
     if not CONF.glance.swift_endpoint_url:
         raise exc.MissingParameterValue(_(
             'Swift temporary URLs require a Swift endpoint URL. '
             'You must provide "swift_endpoint_url" as a config option.'))
     if not CONF.glance.swift_account:
         raise exc.MissingParameterValue(_(
             'Swift temporary URLs require a Swift account string. '
             'You must provide "swift_account" as a config option.'))
     if CONF.glance.swift_temp_url_duration < 0:
         raise exc.InvalidParameterValue(_(
             '"swift_temp_url_duration" must be a positive integer.'))
     seed_num_chars = CONF.glance.swift_store_multiple_containers_seed
     if (seed_num_chars is None or seed_num_chars < 0
             or seed_num_chars > 32):
         raise exc.InvalidParameterValue(_(
             "An integer value between 0 and 32 is required for"
             " swift_store_multiple_containers_seed."))
Пример #25
0
    def validate(self, task):
        """Validate the driver-specific Node deployment info.

        This method validates whether the properties of the supplied node
        contain the required information for this driver to deploy images to
        the node.

        :param task: a TaskManager instance
        :raises: MissingParameterValue, if any of the required parameters are
            missing.
        :raises: InvalidParameterValue, if any of the parameters have invalid
            value.
        """
        if CONF.agent.manage_agent_boot:
            task.driver.boot.validate(task)

        node = task.node
        params = {}
        image_source = node.instance_info.get('image_source')
        params['instance_info.image_source'] = image_source
        error_msg = _('Node %s failed to validate deploy image info. Some '
                      'parameters were missing') % node.uuid
        deploy_utils.check_for_missing_params(params, error_msg)

        if not service_utils.is_glance_image(image_source):
            if not node.instance_info.get('image_checksum'):
                raise exception.MissingParameterValue(
                    _("image_source's image_checksum must be provided in "
                      "instance_info for node %s") % node.uuid)

        check_image_size(task, image_source)
        is_whole_disk_image = node.driver_internal_info.get(
            'is_whole_disk_image')
        # TODO(sirushtim): Remove once IPA has support for partition images.
        if is_whole_disk_image is False:
            raise exception.InvalidParameterValue(
                _("Node %(node)s is configured to use the %(driver)s driver "
                  "which currently does not support deploying partition "
                  "images.") % {
                      'node': node.uuid,
                      'driver': node.driver
                  })

        # Validate the root device hints
        deploy_utils.parse_root_device_hints(node)

        # Validate node capabilities
        deploy_utils.validate_capabilities(node)

        validate_image_proxies(node)
Пример #26
0
    def validate(self, task):
        # TODO(jroll) validate we can put images in /httpboot?
        # validate image, kernel, ramdisk as UUID
        node = task.node

        missing_keys = []
        for key in SECUREBOOT_PROPERTIES:
            if not node.driver_info.get(key):
                missing_keys.append(key)

        if missing_keys:
            raise ironic_exc.MissingParameterValue(
                'Node %s is missing secureboot configuration data %s' %
                (node.uuid, missing_keys))
Пример #27
0
    def get_indicator_state(self, task, component, indicator):
        """Get current state of the indicator of the hardware component.

        :param task: A task from TaskManager.
        :param component: The hardware component, one of
            :mod:`ironic.common.components`.
        :param indicator: Indicator ID (as reported by
            `get_supported_indicators`).
        :raises: MissingParameterValue if a required parameter is missing
        :raises: RedfishError on an error from the Sushy library
        :returns: Current state of the indicator, one of
            :mod:`ironic.common.indicator_states`.
        """
        system = redfish_utils.get_system(task.node)

        try:
            if (component == components.SYSTEM and indicator == system.uuid):
                return INDICATOR_MAP[system.indicator_led]

            if (component == components.CHASSIS and system.chassis):
                for chassis in system.chassis:
                    if chassis.uuid == indicator:
                        return INDICATOR_MAP[chassis.indicator_led]

            if (component == components.DISK and system.simple_storage
                    and system.simple_storage.drives):
                for drive in system.simple_storage.drives:
                    if drive.uuid == indicator:
                        return INDICATOR_MAP[drive.indicator_led]

        except sushy.exceptions.SushyError as e:
            error_msg = (_('Redfish get %(component)s indicator %(indicator)s '
                           'state failed for node %(node)s. Error: '
                           '%(error)s') % {
                               'component': component,
                               'indicator': indicator,
                               'node': task.node.uuid,
                               'error': e
                           })
            LOG.error(error_msg)
            raise exception.RedfishError(error=error_msg)

        raise exception.MissingParameterValue(
            _("Unknown indicator %(indicator)s for component %(component)s of "
              "node %(uuid)s") % {
                  'indicator': indicator,
                  'component': component,
                  'uuid': task.node.uuid
              })
Пример #28
0
    def _validate_common(self, task):
        node = task.node

        if not driver_utils.get_node_mac_addresses(task):
            raise exception.MissingParameterValue(
                _("Node %s does not have any port associated with it.") %
                node.uuid)

        # TODO(TheJulia): Once ipxe support is remove from the pxe
        # interface, this can be removed.
        if CONF.pxe.ipxe_enabled:
            if (not CONF.deploy.http_url or not CONF.deploy.http_root):
                raise exception.MissingParameterValue(
                    _("iPXE boot is enabled but no HTTP URL or HTTP "
                      "root was specified."))

        # Check the trusted_boot capabilities value.
        deploy_utils.validate_capabilities(node)
        if deploy_utils.is_trusted_boot_requested(node):
            # Check if 'boot_option' and boot mode is compatible with
            # trusted boot.
            validate_boot_parameters_for_trusted_boot(node)

        pxe_utils.parse_driver_info(node)
Пример #29
0
    def heartbeat(self, task, **kwargs):
        """Method for agent to periodically check in.

        The agent should be sending its agent_url (so Ironic can talk back)
        as a kwarg. kwargs should have the following format::

         {
             'agent_url': 'http://AGENT_HOST:AGENT_PORT'
         }

        AGENT_PORT defaults to 9999.
        """
        node = task.node
        driver_info = node.driver_info
        LOG.debug(
            'Heartbeat from %(node)s, last heartbeat at %(heartbeat)s.', {
                'node': node.uuid,
                'heartbeat': driver_info.get('agent_last_heartbeat')
            })
        driver_info['agent_last_heartbeat'] = int(_time())
        try:
            driver_info['agent_url'] = kwargs['agent_url']
        except KeyError:
            raise exception.MissingParameterValue(
                _('For heartbeat operation, '
                  '"agent_url" must be '
                  'specified.'))

        node.driver_info = driver_info
        node.save()

        # Async call backs don't set error state on their own
        # TODO(jimrollenhagen) improve error messages here
        msg = _('Failed checking if deploy is done.')
        try:
            if node.provision_state == states.DEPLOYWAIT:
                msg = _('Node failed to get image for deploy.')
                self._continue_deploy(task, **kwargs)
            elif (node.provision_state == states.DEPLOYING
                  and self._deploy_is_done(node)):
                msg = _('Node failed to move to active state.')
                self._reboot_to_instance(task, **kwargs)
        except Exception:
            LOG.exception(_LE('Async exception for %(node)s: %(msg)s'), {
                'node': node,
                'msg': msg
            })
            deploy_utils.set_failed_state(task, msg)
Пример #30
0
    def _get_route(self, method):
        """Return the driver interface which contains the given method.

        :param method: The name of the vendor method.
        """
        if not method:
            raise exception.MissingParameterValue(
                _("Method not specified when calling vendor extension."))

        try:
            route = self.mapping[method]
        except KeyError:
            raise exception.InvalidParameterValue(
                _('No handler for method %s') % method)

        return route