def get_boot_device(self, task): """Get the current boot device for the task's node. Provides the current boot device of the node. :param task: a task from TaskManager. :returns: a dictionary containing: :boot_device: the boot device, one of :mod:`ironic.common.boot_devices` [PXE, DISK, CDROM] :persistent: Whether the boot device will persist to all future boots or not, None if it is unknown. :raises: OperationNotPermitted if no Server Profile is associated with the node :raises: InvalidParameterValue if the boot device is unknown :raises: OneViewError if the communication with OneView fails """ oneview_info = common.get_oneview_info(task.node) try: boot_order = self.oneview_client.get_boot_order(oneview_info) except oneview_exceptions.OneViewException as oneview_exc: msg = (_("Error getting boot device from OneView. Error: %s") % oneview_exc) raise exception.OneViewError(msg) primary_device = boot_order[0] if primary_device not in BOOT_DEVICE_OV_TO_GENERIC: raise exception.InvalidParameterValue( _("Unsupported boot Device %(device)s for Node: %(node)s") % { "device": primary_device, "node": task.node.uuid }) boot_device = { 'boot_device': BOOT_DEVICE_OV_TO_GENERIC.get(primary_device), 'persistent': True, } return boot_device
def validate(self, task): """Checks required info on 'driver_info' and validates node with OneView Validates whether the 'driver_info' property of the supplied task's node contains the required info such as server_hardware_uri, server_hardware_type, server_profile_template_uri and enclosure_group_uri. Also, checks if the server profile of the node is applied, if NICs are valid for the server profile of the node, and if the server hardware attributes (ram, memory, vcpus count) are consistent with OneView. :param task: a task from TaskManager. :raises: InvalidParameterValue if parameters set are inconsistent with resources in OneView """ common.verify_node_info(task.node) try: common.validate_oneview_resources_compatibility(task) except exception.OneViewError as oneview_exc: raise exception.InvalidParameterValue(oneview_exc)
def set_boot_device(self, task, device, persistent=False): """Set the boot device for a node. Set the boot device to use on next reboot of the node. :param task: a task from TaskManager. :param device: the boot device, one of the supported devices listed in :mod:`ironic.common.boot_devices`. :param persistent: Boolean value. True if the boot device will persist to all future boots, False if not. Default: False. :raises: InvalidParameterValue if an invalid boot device is specified. :raises: MissingParameterValue if a required parameter is missing. :raises: IloOperationError on an error from IloClient library. """ try: boot_device = BOOT_DEVICE_MAPPING_TO_ILO[device] except KeyError: raise exception.InvalidParameterValue( _("Invalid boot device %s specified.") % device) try: ilo_object = ilo_common.get_ilo_object(task.node) if not persistent: ilo_object.set_one_time_boot(boot_device) else: ilo_object.update_persistent_boot([boot_device]) except ilo_error.IloError as ilo_exception: operation = _("Setting %s as boot device") % device raise exception.IloOperationError(operation=operation, error=ilo_exception) LOG.debug("Node %(uuid)s set to boot from %(device)s.", { 'uuid': task.node.uuid, 'device': device })
def test_node_power_action_failed_getting_state(self): """Test for exception when we can't get the current power state.""" node = obj_utils.create_test_node(self.context, uuid=uuidutils.generate_uuid(), driver='fake', power_state=states.POWER_ON) task = task_manager.TaskManager(self.context, node.uuid) with mock.patch.object(self.driver.power, 'get_power_state') as get_power_state_mock: get_power_state_mock.side_effect = ( exception.InvalidParameterValue('failed getting power state')) self.assertRaises(exception.InvalidParameterValue, conductor_utils.node_power_action, task, states.POWER_ON) node.refresh() get_power_state_mock.assert_called_once_with(mock.ANY) self.assertEqual(states.POWER_ON, node['power_state']) self.assertIsNone(node['target_power_state']) self.assertIsNotNone(node['last_error'])
def node_set_boot_mode(task, mode): """Set the boot mode for a node. Sets the boot mode for a node if the node's driver interface contains a 'management' interface. If the node that the boot mode change is being requested for is in ADOPTING state, the boot mode will not be set as that change could potentially result in the future running state of an adopted node being modified erroneously. :param task: a TaskManager instance. :param mode: Boot mode. Values are one of :mod:`ironic.common.boot_modes` :raises: InvalidParameterValue if the validation of the ManagementInterface fails. :raises: DriverOperationError or its derivative in case of driver runtime error. :raises: UnsupportedDriverExtension if current driver does not have vendor interface or method is unsupported. """ if task.node.provision_state == states.ADOPTING: return task.driver.management.validate(task) boot_modes = task.driver.management.get_supported_boot_modes(task) if mode not in boot_modes: msg = _("Unsupported boot mode %(mode)s specified for " "node %(node_id)s. Supported boot modes are: " "%(modes)s") % { 'mode': mode, 'modes': ', '.join(boot_modes), 'node_id': task.node.uuid } raise exception.InvalidParameterValue(msg) task.driver.management.set_boot_mode(task, mode=mode)
def _parse_config_option(): """Parse config file options. This method checks config file options validity. :raises: InvalidParameterValue, if config option has invalid value. """ error_msgs = [] if not os.path.isdir(CONF.irmc.remote_image_share_root): error_msgs.append( _("Value '%s' for remote_image_share_root isn't a directory " "or doesn't exist.") % CONF.irmc.remote_image_share_root) if CONF.irmc.remote_image_share_type.lower() not in ('nfs', 'cifs'): error_msgs.append( _("Value '%s' for remote_image_share_type is not supported " "value either 'NFS' or 'CIFS'.") % CONF.irmc.remote_image_share_type) if error_msgs: msg = (_("The following errors were encountered while parsing " "config file:%s") % error_msgs) raise exception.InvalidParameterValue(msg)
def validate_boot_option_for_uefi(node): """In uefi boot mode, validate if the boot option is compatible. This method raises exception if whole disk image being deployed in UEFI boot mode without 'boot_option' being set to 'local'. :param node: a single Node. :raises: InvalidParameterValue """ boot_mode = deploy_utils.get_boot_mode_for_deploy(node) boot_option = iscsi_deploy.get_boot_option(node) if (boot_mode == 'uefi' and node.driver_internal_info.get('is_whole_disk_image') and boot_option != 'local'): LOG.error( _LE("Whole disk image with netboot is not supported in UEFI " "boot mode.")) raise exception.InvalidParameterValue( _("Conflict: Whole disk image being used for deploy, but " "cannot be used with node %(node_uuid)s configured to use " "UEFI boot with netboot option") % {'node_uuid': node.uuid})
def set_power_state(self, task, pstate): """Turn the power on or off. :param task: a TaskManager instance containing the node to act on. :param pstate: a power state that will be set on the task's node. :raises: IPMIFailure when the native ipmi call fails. :raises: InvalidParameterValue when an invalid power state is specified or required ipmi credentials are missing. :raises: PowerStateFailure when invalid power state is returned from ipmi. """ driver_info = _parse_driver_info(task.node) if pstate == states.POWER_ON: _power_on(driver_info) elif pstate == states.POWER_OFF: _power_off(driver_info) else: raise exception.InvalidParameterValue( _("set_power_state called with an invalid power state: %s.") % pstate)
def set_power_state(self, task, pstate): """Turn the power on or off. Set the power state of a node. :param task: a TaskManager instance containing the node to act on. :param pstate: Either POWER_ON or POWER_OFF from :class: `ironic.common.states`. :raises: InvalidParameterValue if an invalid power state was specified. :raises: PowerStateFailure if the desired power state couldn't be set. """ if pstate == states.POWER_ON: state = _power_on(task.node) elif pstate == states.POWER_OFF: state = _power_off(task.node) else: raise exception.InvalidParameterValue( _("set_power_state called with invalid power state.")) if state != pstate: raise exception.PowerStateFailure(pstate=pstate)
def validate(self, task, method, http_method, **kwargs): """Validates the vendor method's parameters. This method validates whether the supplied data contains the required information for the driver. :param task: a TaskManager instance. :param method: name of vendor method. :param http_method: HTTP method. :param kwargs: data passed to vendor's method. :raises: InvalidParameterValue if supplied data is not valid. :raises: MissingParameterValue if parameters missing in supplied data. """ try: if 'statistics' in method: self._validate_statistics_methods(method, **kwargs) else: self._validate_policy_methods(method, **kwargs) except json_schema_exc.ValidationError as e: raise exception.InvalidParameterValue( _('Input data validation ' 'error: %s') % e)
def validate(self, task): """Check that the node's 'driver_info' is valid. Check that the node's 'driver_info' contains the requisite fields and that an SSH connection to the node can be established. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue if any connection parameters are incorrect or if ssh failed to connect to the node. :raises: MissingParameterValue if no ports are enrolled for the given node. """ if not driver_utils.get_node_mac_addresses(task): raise exception.MissingParameterValue( _("Node %s does not have any port associated with it.") % task.node.uuid) try: _get_connection(task.node) except exception.SSHConnectFailed as e: raise exception.InvalidParameterValue( _("SSH connection cannot" " be established: %s") % e)
def validate(self, task): """Validate the driver-specific Node deployment info.""" task.driver.boot.validate(task) node = task.node iwdi = node.driver_internal_info.get('is_whole_disk_image') if not iwdi and deploy_utils.get_boot_option(node) == "netboot": raise exception.InvalidParameterValue( _("Node %(node)s is configured to use the %(driver)s driver " "which does not support netboot.") % { 'node': node.uuid, 'driver': node.driver }) 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) # validate root device hints, proper exceptions are raised from there _parse_root_device_hints(node)
def activate_license(self, task, **kwargs): """Activates iLO Advanced license. :param task: a TaskManager object. :raises: InvalidParameterValue, if any of the arguments are invalid. :raises: NodeCleaningFailure, on failure to execute of clean step. """ ilo_license_key = kwargs.get('ilo_license_key') node = task.node if not isinstance(ilo_license_key, str): msg = (_("Value of 'ilo_license_key' must be a string instead of " "'%(value)s'. Step 'activate_license' is not executed " "for %(node)s.") % {'value': ilo_license_key, 'node': node.uuid}) LOG.error(msg) raise exception.InvalidParameterValue(msg) LOG.debug("Activating iLO license for node %(node)s ...", {'node': node.uuid}) _execute_ilo_step(node, 'activate_license', ilo_license_key) LOG.info("iLO license activated for node %s.", node.uuid)
def _get_chassis_collection(self, marker, limit, sort_key, sort_dir, resource_url=None, fields=None): limit = api_utils.validate_limit(limit) sort_dir = api_utils.validate_sort_dir(sort_dir) marker_obj = None if marker: marker_obj = objects.Chassis.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}) chassis = objects.Chassis.list(pecan.request.context, limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir) return ChassisCollection.convert_with_links(chassis, limit, url=resource_url, fields=fields, sort_key=sort_key, sort_dir=sort_dir)
def validate_boot_parameters_for_trusted_boot(node): """Check if boot parameters are valid for trusted boot.""" boot_mode = boot_mode_utils.get_boot_mode(node) boot_option = deploy_utils.get_boot_option(node) is_whole_disk_image = node.driver_internal_info.get('is_whole_disk_image') # 'is_whole_disk_image' is not supported by trusted boot, because there is # no Kernel/Ramdisk to measure at all. if (boot_mode != 'bios' or is_whole_disk_image or boot_option != 'netboot'): msg = (_("Trusted boot is only supported in BIOS boot mode with " "netboot and without whole_disk_image, but Node " "%(node_uuid)s was configured with boot_mode: %(boot_mode)s, " "boot_option: %(boot_option)s, is_whole_disk_image: " "%(is_whole_disk_image)s: at least one of them is wrong, and " "this can be caused by enable secure boot.") % { 'node_uuid': node.uuid, 'boot_mode': boot_mode, 'boot_option': boot_option, 'is_whole_disk_image': is_whole_disk_image }) LOG.error(msg) raise exception.InvalidParameterValue(msg)
def validate_configuration(raid_config, raid_config_schema): """Validates the RAID configuration passed using JSON schema. This method validates a RAID configuration against a RAID configuration schema. :param raid_config: A dictionary containing RAID configuration information :param raid_config_schema: A dictionary which is the schema to be used for validation. :raises: InvalidParameterValue, if validation of the RAID configuration fails. """ try: jsonschema.validate(raid_config, raid_config_schema) except json_schema_exc.ValidationError as e: # NOTE: Even though e.message is deprecated in general, it is said # in jsonschema documentation to use this still. msg = _("RAID config validation error: %s") % e.message raise exception.InvalidParameterValue(msg) # Check if there are multiple root volumes specified. _check_and_return_root_volumes(raid_config)
def update_volume_connector(self, ident, connector_info): if 'uuid' in connector_info: msg = _("Cannot overwrite UUID for an existing Volume Connector.") raise exception.InvalidParameterValue(err=msg) try: with _session_for_write() as session: query = model_query(models.VolumeConnector) query = add_identity_filter(query, ident) ref = query.one() orig_type = ref['type'] orig_connector_id = ref['connector_id'] ref.update(connector_info) session.flush() except db_exc.DBDuplicateEntry: raise exception.VolumeConnectorTypeAndIdAlreadyExists( type=connector_info.get('type', orig_type), connector_id=connector_info.get('connector_id', orig_connector_id)) except NoResultFound: raise exception.VolumeConnectorNotFound(connector=ident) return ref
def _get_conductors_collection(self, marker, limit, sort_key, sort_dir, resource_url=None, fields=None, detail=None): limit = api_utils.validate_limit(limit) sort_dir = api_utils.validate_sort_dir(sort_dir) 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}) marker_obj = None if marker: marker_obj = objects.Conductor.get_by_hostname(api.request.context, marker, online=None) conductors = objects.Conductor.list(api.request.context, limit=limit, marker=marker_obj, sort_key=sort_key, sort_dir=sort_dir) parameters = {'sort_key': sort_key, 'sort_dir': sort_dir} if detail is not None: parameters['detail'] = detail return ConductorCollection.convert_with_links(conductors, limit, url=resource_url, fields=fields, **parameters)
def post(self, node_ident, callback_url, agent_version=None): """Process a heartbeat from the deploy ramdisk. :param node_ident: the UUID or logical name of a node. :param callback_url: the URL to reach back to the ramdisk. :param agent_version: The version of the agent that is heartbeating. ``None`` indicates that the agent that is heartbeating is a version before sending agent_version was introduced so agent v3.0.0 (the last release before sending agent_version was introduced) will be assumed. :raises: NodeNotFound if node with provided UUID or name was not found. :raises: InvalidUuidOrName if node_ident is not valid name or UUID. :raises: NoValidHost if RPC topic for node could not be retrieved. :raises: NotFound if requested API version does not allow this endpoint. """ if not api_utils.allow_ramdisk_endpoints(): raise exception.NotFound() if agent_version and not api_utils.allow_agent_version_in_heartbeat(): raise exception.InvalidParameterValue( _('Field "agent_version" not recognised')) cdict = pecan.request.context.to_policy_values() policy.authorize('baremetal:node:ipa_heartbeat', cdict, cdict) rpc_node = api_utils.get_rpc_node_with_suffix(node_ident) try: topic = pecan.request.rpcapi.get_topic_for(rpc_node) except exception.NoValidHost as e: e.code = http_client.BAD_REQUEST raise pecan.request.rpcapi.heartbeat(pecan.request.context, rpc_node.uuid, callback_url, agent_version, topic=topic)
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 = 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', '3260'), 'iqn': kwargs.get('iqn'), 'lun': kwargs.get('lun', '1'), 'image_path': _get_image_file_path(node.uuid), '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'], 'node_uuid': node.uuid, } 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 and ephemeral_format are nullable params['ephemeral_format'] = i_info.get('ephemeral_format') params['configdrive'] = i_info.get('configdrive') return params
def set_power_state(self, task, pstate): """Turn the power on or off. :param task: a TaskManager instance containing the node to act on. :param pstate: The desired power state, one of ironic.common.states POWER_ON, POWER_OFF. :raises: InvalidParameterValue if required ipmi parameters are missing or if an invalid power state was specified. :raises: PowerStateFailure if the power couldn't be set to pstate. """ driver_info = _parse_driver_info(task.node) if pstate == states.POWER_ON: state = _power_on(driver_info) elif pstate == states.POWER_OFF: state = _power_off(driver_info) else: raise exception.InvalidParameterValue(_("set_power_state called " "with invalid power state %s.") % pstate) if state != pstate: raise exception.PowerStateFailure(pstate=pstate)
def check_image_size(task, image_source): """Check if the requested image is larger than the ram size. :param task: a TaskManager instance containing the node to act on. :param image_source: href of the image. :raises: InvalidParameterValue if size of the image is greater than the available ram size. """ node = task.node properties = node.properties # skip check if 'memory_mb' is not defined if 'memory_mb' not in properties: LOG.warning( 'Skip the image size check as memory_mb is not ' 'defined in properties on node %s.', node.uuid) return image_show = images.image_show(task.context, image_source) if CONF.agent.stream_raw_images and image_show.get('disk_format') == 'raw': LOG.debug( 'Skip the image size check since the image is going to be ' 'streamed directly onto the disk for node %s', node.uuid) return memory_size = int(properties.get('memory_mb')) image_size = int(image_show['size']) reserved_size = CONF.agent.memory_consumed_by_agent if (image_size + (reserved_size * units.Mi)) > (memory_size * units.Mi): msg = (_('Memory size is too small for requested image, if it is ' 'less than (image size + reserved RAM size), will break ' 'the IPA deployments. Image size: %(image_size)d MiB, ' 'Memory size: %(memory_size)d MiB, Reserved size: ' '%(reserved_size)d MiB.') % { 'image_size': image_size / units.Mi, 'memory_size': memory_size, 'reserved_size': reserved_size }) raise exception.InvalidParameterValue(msg)
def _get_volume_targets_collection(self, node_ident, marker, limit, sort_key, sort_dir, resource_url=None, fields=None, detail=None): limit = api_utils.validate_limit(limit) sort_dir = api_utils.validate_sort_dir(sort_dir) marker_obj = None if marker: marker_obj = objects.VolumeTarget.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}) node_ident = self.parent_node_ident or node_ident 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) targets = objects.VolumeTarget.list_by_node_id( pecan.request.context, node.id, limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir) else: targets = objects.VolumeTarget.list(pecan.request.context, limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir) return VolumeTargetCollection.convert_with_links(targets, limit, url=resource_url, fields=fields, sort_key=sort_key, sort_dir=sort_dir, detail=detail)
def set_boot_device(self, task, device, persistent=False): """Set the boot device for a node. Set the boot device to use on next reboot of the node. :param task: a TaskManager instance containing the node to act on. :param device: the boot device, one of :mod:`ironic.common.boot_devices`. :param persistent: Boolean value. True if the boot device will persist to all future boots, False if not. Default: False. :raises: InvalidParameterValue if an invalid boot device is specified. """ node = task.node if device not in _BOOT_DEVICES_MAP: raise exception.InvalidParameterValue( _("set_boot_device called with invalid device '%(device)s' " "for node %(node_id)s.") % { 'device': device, 'node_id': node.uuid }) # NOTE(ifarkas): DRAC interface doesn't allow changing the boot device # multiple times in a row without a reboot. This is # because a change need to be committed via a # configuration job, and further configuration jobs # cannot be created until the previous one is processed # at the next boot. As a workaround, saving it to # driver_internal_info and committing the change during # power state change. driver_internal_info = node.driver_internal_info driver_internal_info['drac_boot_device'] = { 'boot_device': device, 'persistent': persistent } node.driver_internal_info = driver_internal_info node.save()
def parse_driver_info(node): """Parses and creates AMT driver info :param node: an Ironic node object. :returns: AMT driver info. :raises: MissingParameterValue if any required parameters are missing. :raises: InvalidParameterValue if any parameters have invalid values. """ info = node.driver_info or {} d_info = {} missing_info = [] for param in REQUIRED_PROPERTIES: value = info.get(param) if value: if not isinstance(value, six.binary_type): value = value.encode() d_info[param[4:]] = value else: missing_info.append(param) if missing_info: raise exception.MissingParameterValue( _("AMT driver requires the following to be set in " "node's driver_info: %s.") % missing_info) d_info['uuid'] = node.uuid param = 'amt_protocol' protocol = info.get(param, CONF.amt.get(param[4:])) if protocol not in AMT_PROTOCOL_PORT_MAP: raise exception.InvalidParameterValue( _("Invalid protocol %s.") % protocol) if not isinstance(value, six.binary_type): protocol = protocol.encode() d_info[param[4:]] = protocol return d_info
def _get_certificate_file_list(cert_file_list): """Get the list of certificates to use. :param cert_file_list: certificates file list. :returns: cert_file_list if it's not empty. If empty or None, returns the list of path configured for "webserver_verify_ca" configuration option if the path exists. If the path does not exist, returns empty list. :raises: InvalidParameterValue if argument provided is other than a list. """ cfl = cert_file_list if not cfl: try: verify = strutils.bool_from_string(CONF.webserver_verify_ca, strict=True) except ValueError: verify = CONF.webserver_verify_ca if isinstance(verify, bool): return [] if not os.path.exists(verify): LOG.error( "Path to the certificate file %(path)s " "does not exist.", {'path': verify}) return [] cfl = [verify] if not isinstance(cfl, list): raise exception.InvalidParameterValue( _('List of files is expected whereas "%(atype)s" type ' 'is provided.') % {'atype': type(cfl)}) return cfl
def get_all(self, node=None, marker=None, limit=None, sort_key='id', sort_dir='asc', fields=None, detail=None, project=None): """Retrieve a list of volume connectors. :param node: UUID or name of a node, to get only volume connectors for that node. :param marker: pagination marker for large data sets. :param limit: maximum number of resources to return in a single result. This value cannot be larger than the value of max_limit in the [api] section of the ironic configuration, or only max_limit resources will be returned. :param sort_key: column to sort results by. Default: id. :param sort_dir: direction to sort. "asc" or "desc". Default: "asc". :param fields: Optional, a list with a specified set of fields of the resource to be returned. :param detail: Optional, whether to retrieve with detail. :returns: a list of volume connectors, or an empty list if no volume connector is found. :raises: InvalidParameterValue if sort_key does not exist :raises: InvalidParameterValue if sort key is invalid for sorting. :raises: InvalidParameterValue if both fields and detail are specified. """ project = api_utils.check_volume_list_policy( parent_node=self.parent_node_ident) if fields is None and not detail: fields = _DEFAULT_RETURN_FIELDS if fields and detail: raise exception.InvalidParameterValue( _("Can't fetch a subset of fields with 'detail' set")) resource_url = 'volume/connectors' return self._get_volume_connectors_collection( node, marker, limit, sort_key, sort_dir, resource_url=resource_url, fields=fields, detail=detail, project=project)
def set_power_state(self, task, target_state, timeout=None): """Turn the current power state on or off. :param task: a TaskManager instance. :param target_state: The desired power state POWER_ON, POWER_OFF or REBOOT from :mod:`ironic.common.states`. :raises: MissingParameterValue, if some required parameter(s) are missing in the node's driver_info. :raises: InvalidParameterValue, if some parameter(s) have invalid value(s) in the node's driver_info OR if an invalid power state was specified. """ driver_info = _parse_driver_info(task.node) vm_name = driver_info['ovirt_vm_name'] vm = _getvm(driver_info) try: if target_state == states.POWER_OFF: vm.stop() elif target_state == states.POWER_ON: vm.start() elif target_state == states.REBOOT: status = vm.get().status.value if status == 'down': vm.start() else: vm.reboot() else: msg = _("'set_power_state' called with invalid power " "state '%s'") % target_state raise exception.InvalidParameterValue(msg) except sdk.Error as e: LOG.error( "Could not change status of VM vm %(name)s " "got error: %(error)s", { 'name': vm_name, 'error': e }) raise staging_exception.OVirtError(err=e)
def set_boot_device(self, task, device, persistent=False): """Set the boot device for the task's node. Set the boot device to use on next reboot of the node. :param task: a task from TaskManager. :param device: the boot device, one of :mod:`ironic.common.boot_devices`. :param persistent: Boolean value. True if the boot device will persist to all future boots, False if not. Default: False. Ignored by this driver. :raises: InvalidParameterValue if an invalid boot device is specified or if any connection parameters are incorrect. :raises: MissingParameterValue if a required parameter is missing :raises: SSHConnectFailed if ssh failed to connect to the node. :raises: SSHCommandFailed on an error from ssh. :raises: NotImplementedError if the virt_type does not support setting the boot device. """ node = task.node driver_info = _parse_driver_info(node) if device not in self.get_supported_boot_devices(task): raise exception.InvalidParameterValue(_( "Invalid boot device %s specified.") % device) driver_info['macs'] = driver_utils.get_node_mac_addresses(task) ssh_obj = _get_connection(node) boot_device_map = _get_boot_device_map(driver_info['virt_type']) try: _set_boot_device(ssh_obj, driver_info, boot_device_map[device]) except NotImplementedError: with excutils.save_and_reraise_exception(): LOG.error(_LE("Failed to set boot device for node %(node)s, " "virt_type %(vtype)s does not support this " "operation"), {'node': node.uuid, 'vtype': driver_info['virt_type']})
def add_cleaning_network(self, task): """Add the cleaning network to a node. :param task: A TaskManager instance. :returns: a dictionary in the form {port.uuid: neutron_port['id']} :raises: NetworkError, InvalidParameterValue """ if not uuidutils.is_uuid_like(CONF.neutron.cleaning_network_uuid): raise exception.InvalidParameterValue(_( 'You must provide a valid cleaning network UUID in ' '[neutron]cleaning_network_uuid configuration option.')) # If we have left over ports from a previous cleaning, remove them neutron.rollback_ports(task, CONF.neutron.cleaning_network_uuid) LOG.info(_LI('Adding cleaning network to node %s'), task.node.uuid) vifs = neutron.add_ports_to_network( task, CONF.neutron.cleaning_network_uuid, is_flat=True) for port in task.ports: if port.uuid in vifs: internal_info = port.internal_info internal_info['cleaning_vif_port_id'] = vifs[port.uuid] port.internal_info = internal_info port.save() return vifs