def _parse_driver_info(node): """Gets the information needed for accessing the node. :param node: the Node of interest. :returns: dictionary of information. :raises: InvalidParameterValue if any required parameters are incorrect. :raises: MissingParameterValue if any required parameters are missing. """ info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue( _("SSHPowerDriver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info) address = info.get('ssh_address') username = info.get('ssh_username') password = info.get('ssh_password') port = info.get('ssh_port', 22) port = utils.validate_network_port(port, 'ssh_port') key_contents = info.get('ssh_key_contents') key_filename = info.get('ssh_key_filename') virt_type = info.get('ssh_virt_type') terminal_port = info.get('ssh_terminal_port') if terminal_port is not None: terminal_port = utils.validate_network_port(terminal_port, 'ssh_terminal_port') # NOTE(deva): we map 'address' from API to 'host' for common utils res = { 'host': address, 'username': username, 'port': port, 'virt_type': virt_type, 'uuid': node.uuid, 'terminal_port': terminal_port } cmd_set = _get_command_sets(virt_type) res['cmd_set'] = cmd_set # Only one credential may be set (avoids complexity around having # precedence etc). if len([v for v in (password, key_filename, key_contents) if v]) != 1: raise exception.InvalidParameterValue( _("SSHPowerDriver requires one and only one of password, " "key_contents and key_filename to be set.")) if password: res['password'] = password elif key_contents: res['key_contents'] = key_contents else: if not os.path.isfile(key_filename): raise exception.InvalidParameterValue( _("SSH key file %s not found.") % key_filename) res['key_filename'] = key_filename return res
def _parse_driver_info(node): """Gets the information needed for accessing the node. :param node: the Node of interest. :returns: dictionary of information. :raises: InvalidParameterValue if any required parameters are incorrect. :raises: MissingParameterValue if any required parameters are missing. """ info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue(_( "SSHPowerDriver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info) address = info.get('ssh_address') username = info.get('ssh_username') password = info.get('ssh_password') port = info.get('ssh_port', 22) port = utils.validate_network_port(port, 'ssh_port') key_contents = info.get('ssh_key_contents') key_filename = info.get('ssh_key_filename') virt_type = info.get('ssh_virt_type') terminal_port = info.get('ssh_terminal_port') if terminal_port is not None: terminal_port = utils.validate_network_port(terminal_port, 'ssh_terminal_port') # NOTE(deva): we map 'address' from API to 'host' for common utils res = { 'host': address, 'username': username, 'port': port, 'virt_type': virt_type, 'uuid': node.uuid, 'terminal_port': terminal_port } cmd_set = _get_command_sets(virt_type) res['cmd_set'] = cmd_set # Only one credential may be set (avoids complexity around having # precedence etc). if len([v for v in (password, key_filename, key_contents) if v]) != 1: raise exception.InvalidParameterValue(_( "SSHPowerDriver requires one and only one of password, " "key_contents and key_filename to be set.")) if password: res['password'] = password elif key_contents: res['key_contents'] = key_contents else: if not os.path.isfile(key_filename): raise exception.InvalidParameterValue(_( "SSH key file %s not found.") % key_filename) res['key_filename'] = key_filename return res
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) elif param == "ca_file": if value and not os.path.isfile(value): raise exception.InvalidParameterValue( _('%(param)s "%(value)s" is not found.') % { 'param': param, 'value': value }) d_info[param] = value 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
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) elif param == "ca_file": if value and not os.path.isfile(value): raise exception.InvalidParameterValue(_( '%(param)s "%(value)s" is not found.') % {'param': param, 'value': value}) d_info[param] = value 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
def _parse_driver_info(node): """Gets the bmc access info for the given node. :raises: MissingParameterValue when required ipmi credentials are missing. :raises: InvalidParameterValue when the IPMI terminal port is not an integer. """ info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue( _("Missing the following IPMI credentials in node's" " driver_info: %s.") % missing_info) bmc_info = {} bmc_info['address'] = info.get('ipmi_address') bmc_info['username'] = info.get('ipmi_username') bmc_info['password'] = info.get('ipmi_password') bmc_info['force_boot_device'] = info.get('ipmi_force_boot_device', False) # get additional info bmc_info['uuid'] = node.uuid # terminal port must be an integer port = info.get('ipmi_terminal_port') if port is not None: port = utils.validate_network_port(port, 'ipmi_terminal_port') bmc_info['port'] = port return bmc_info
def _parse_driver_info(node): info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue( _("Missing the following iBoot credentials in node's" " driver_info: %s.") % missing_info) address = info.get('iboot_address', None) username = info.get('iboot_username', None) password = info.get('iboot_password', None) relay_id = info.get('iboot_relay_id', 1) try: relay_id = int(relay_id) except ValueError: raise exception.InvalidParameterValue( _("iBoot PDU relay id must be an integer.")) port = info.get('iboot_port', 9100) port = utils.validate_network_port(port, 'iboot_port') return { 'address': address, 'username': username, 'password': password, 'port': port, 'relay_id': relay_id, 'uuid': node.uuid, }
def _parse_driver_info(node): """Gets the bmc access info for the given node. :raises: MissingParameterValue when required ipmi credentials are missing. :raises: InvalidParameterValue when the IPMI terminal port is not an integer. """ info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue(_( "Missing the following IPMI credentials in node's" " driver_info: %s.") % missing_info) bmc_info = {} bmc_info['address'] = info.get('ipmi_address') bmc_info['username'] = info.get('ipmi_username') bmc_info['password'] = info.get('ipmi_password') bmc_info['force_boot_device'] = info.get('ipmi_force_boot_device', False) # get additional info bmc_info['uuid'] = node.uuid # terminal port must be an integer port = info.get('ipmi_terminal_port') if port is not None: port = utils.validate_network_port(port, 'ipmi_terminal_port') bmc_info['port'] = port return bmc_info
def _parse_driver_info(node): """Parse a node's driver_info values. Return a dictionary of validated driver information, usable for SNMPDriver object creation. :param node: An Ironic node object. :returns: SNMP driver info. :raises: MissingParameterValue if any required parameters are missing. :raises: InvalidParameterValue if any parameters 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( _("SNMP driver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info ) snmp_info = {} # Validate PDU driver type snmp_info["driver"] = info.get("snmp_driver") if snmp_info["driver"] not in DRIVER_CLASSES: raise exception.InvalidParameterValue(_("SNMPPowerDriver: unknown driver: '%s'") % snmp_info["driver"]) # In absence of a version, default to SNMPv1 snmp_info["version"] = info.get("snmp_version", SNMP_V1) if snmp_info["version"] not in (SNMP_V1, SNMP_V2C, SNMP_V3): raise exception.InvalidParameterValue(_("SNMPPowerDriver: unknown SNMP version: '%s'") % snmp_info["version"]) # In absence of a configured UDP port, default to the standard port port_str = info.get("snmp_port", SNMP_PORT) snmp_info["port"] = utils.validate_network_port(port_str, "snmp_port") if snmp_info["port"] < 1 or snmp_info["port"] > 65535: raise exception.InvalidParameterValue(_("SNMPPowerDriver: SNMP UDP port out of range: %d") % snmp_info["port"]) # Extract version-dependent required parameters if snmp_info["version"] in (SNMP_V1, SNMP_V2C): if "snmp_community" not in info: raise exception.MissingParameterValue( _("SNMP driver requires snmp_community to be set for version " "%s.") % snmp_info["version"] ) snmp_info["community"] = info.get("snmp_community") elif snmp_info["version"] == SNMP_V3: if "snmp_security" not in info: raise exception.MissingParameterValue( _("SNMP driver requires snmp_security to be set for version %s.") % (SNMP_V3) ) snmp_info["security"] = info.get("snmp_security") # Target PDU IP address and power outlet identification snmp_info["address"] = info.get("snmp_address") snmp_info["outlet"] = info.get("snmp_outlet") return snmp_info
def parse_driver_info(node): """Parse a node's driver_info values. Parses the driver_info of the node, reads default values and returns a dict containing the combination of both. :param node: an ironic node object to get informatin from. :returns: a dict containing information parsed from driver_info. :raises: InvalidParameterValue if some required information is missing on the node or inputs is invalid. """ driver_info = node.driver_info parsed_driver_info = {} error_msgs = [] for param in REQUIRED_ON_DRIVER_INFO: if param == "xclarity_hardware_id": try: parsed_driver_info[param] = str(driver_info[param]) except KeyError: error_msgs.append(_("'%s' not provided to XClarity.") % param) except UnicodeEncodeError: error_msgs.append(_("'%s' contains non-ASCII symbol.") % param) else: # corresponding config names don't have 'xclarity_' prefix if param in driver_info: parsed_driver_info[param] = str(driver_info[param]) elif param not in driver_info and\ CONF.xclarity.get(param[len('xclarity_'):]) is not None: parsed_driver_info[param] = str( CONF.xclarity.get(param[len('xclarity_'):])) LOG.warning( 'The configuration [xclarity]/%(config)s ' 'is deprecated and will be removed in the ' 'Stein release. Please update the node ' '%(node_uuid)s driver_info field to use ' '"%(field)s" instead', { 'config': param[len('xclarity_'):], 'node_uuid': node.uuid, 'field': param }) else: error_msgs.append(_("'%s' not provided to XClarity.") % param) port = driver_info.get('xclarity_port', CONF.xclarity.get('port')) parsed_driver_info['xclarity_port'] = utils.validate_network_port( port, 'xclarity_port') if error_msgs: msg = (_('The following errors were encountered while parsing ' 'driver_info:\n%s') % '\n'.join(error_msgs)) raise exception.InvalidParameterValue(msg) return parsed_driver_info
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}
def parse_driver_info(node): """Parse a node's driver_info values. Parses the driver_info of the node, reads default values and returns a dict containing the combination of both. :param node: an ironic node object. :returns: a dict containing information from driver_info and default values. :raises: InvalidParameterValue if some mandatory information is missing on the node or on invalid inputs. """ driver_info = node.driver_info parsed_driver_info = {} error_msgs = [] for param in REQUIRED_PROPERTIES: try: parsed_driver_info[param] = str(driver_info[param]) except KeyError: error_msgs.append(_("'%s' not supplied to DracDriver.") % param) except UnicodeEncodeError: error_msgs.append(_("'%s' contains non-ASCII symbol.") % param) parsed_driver_info['drac_port'] = driver_info.get('drac_port', 443) try: parsed_driver_info['drac_path'] = str( driver_info.get('drac_path', '/wsman')) except UnicodeEncodeError: error_msgs.append(_("'drac_path' contains non-ASCII symbol.")) try: parsed_driver_info['drac_protocol'] = str( driver_info.get('drac_protocol', 'https')) if parsed_driver_info['drac_protocol'] not in ['http', 'https']: error_msgs.append( _("'drac_protocol' must be either 'http' or " "'https'.")) except UnicodeEncodeError: error_msgs.append(_("'drac_protocol' contains non-ASCII symbol.")) if error_msgs: msg = (_('The following errors were encountered while parsing ' 'driver_info:\n%s') % '\n'.join(error_msgs)) raise exception.InvalidParameterValue(msg) port = parsed_driver_info['drac_port'] parsed_driver_info['drac_port'] = utils.validate_network_port( port, 'drac_port') return parsed_driver_info
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}
def parse_driver_info(node): """Parse a node's driver_info values. Parses the driver_info of the node, reads default values and returns a dict containing the combination of both. :param node: an ironic node object. :returns: a dict containing information from driver_info and default values. :raises: InvalidParameterValue if some mandatory information is missing on the node or on invalid inputs. """ driver_info = node.driver_info parsed_driver_info = {} error_msgs = [] for param in REQUIRED_PROPERTIES: try: parsed_driver_info[param] = str(driver_info[param]) except KeyError: error_msgs.append(_("'%s' not supplied to DracDriver.") % param) except UnicodeEncodeError: error_msgs.append(_("'%s' contains non-ASCII symbol.") % param) parsed_driver_info['drac_port'] = driver_info.get('drac_port', 443) try: parsed_driver_info['drac_path'] = str(driver_info.get('drac_path', '/wsman')) except UnicodeEncodeError: error_msgs.append(_("'drac_path' contains non-ASCII symbol.")) try: parsed_driver_info['drac_protocol'] = str( driver_info.get('drac_protocol', 'https')) if parsed_driver_info['drac_protocol'] not in ['http', 'https']: error_msgs.append(_("'drac_protocol' must be either 'http' or " "'https'.")) except UnicodeEncodeError: error_msgs.append(_("'drac_protocol' contains non-ASCII symbol.")) if error_msgs: msg = (_('The following errors were encountered while parsing ' 'driver_info:\n%s') % '\n'.join(error_msgs)) raise exception.InvalidParameterValue(msg) port = parsed_driver_info['drac_port'] parsed_driver_info['drac_port'] = utils.validate_network_port( port, 'drac_port') return parsed_driver_info
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 is not None: port = utils.validate_network_port(port, 'seamicro_terminal_port') 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
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 is not None: port = utils.validate_network_port(port, 'seamicro_terminal_port') 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
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) optional_info = _parse_optional_driver_info(node) d_info.update(optional_info) snmp_info = _parse_snmp_driver_info(info) if snmp_info: d_info.update(snmp_info) 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) return d_info
def _parse_driver_info(node): """Gets the information needed for accessing the node. :param node: the Node of interest. :returns: dictionary of information. :raises: InvalidParameterValue if any required parameters are incorrect. :raises: MissingParameterValue if any required parameters are missing. """ info = node.driver_info or {} missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue( _("SSHPowerDriver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info) address = info.get('ssh_address') username = info.get('ssh_username') key_contents = info.get('ssh_key_contents') terminal_port = info.get('ssh_terminal_port') if terminal_port is not None: terminal_port = utils.validate_network_port(terminal_port, 'ssh_terminal_port') # NOTE(deva): we map 'address' from API to 'host' for common utils res = { 'host': address, 'username': username, 'port': 22, 'uuid': node.uuid, 'terminal_port': terminal_port } cmd_set = _get_command_sets() res['cmd_set'] = cmd_set if key_contents: res['key_contents'] = key_contents else: raise exception.InvalidParameterValue( _("ssh_virtmedia Driver requires ssh_key_contents to be set.")) return res
def _parse_driver_info(node): """Gets the driver specific node driver 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: 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. """ info = node.driver_info d_info = {} missing_params = [] for param in REQUIRED_PROPERTIES: try: d_info_param_name = _strip_virtualbox_from_param_name(param) d_info[d_info_param_name] = info[param] except KeyError: missing_params.append(param) if missing_params: msg = (_("The following parameters are missing in driver_info: %s") % ', '.join(missing_params)) raise exception.MissingParameterValue(msg) for param in OPTIONAL_PROPERTIES: if param in info: d_info_param_name = _strip_virtualbox_from_param_name(param) d_info[d_info_param_name] = info[param] port = d_info.get('port', CONF.virtualbox.port) d_info['port'] = utils.validate_network_port(port, 'virtualbox_port') return d_info
def parse_driver_info(node): """Parse a node's driver_info values. Parses the driver_info of the node, reads default values and returns a dict containing the combination of both. :param node: an ironic node object. :returns: a dict containing information from driver_info and default values. :raises: InvalidParameterValue if some mandatory information is missing on the node or on invalid inputs. """ driver_info = node.driver_info parsed_driver_info = {} if 'drac_host' in driver_info and 'drac_address' not in driver_info: LOG.warning(_LW('The driver_info["drac_host"] property is deprecated ' 'and will be removed in the Pike release. Please ' 'update the node %s driver_info field to use ' '"drac_address" instead'), node.uuid) address = driver_info.pop('drac_host', None) if address: driver_info['drac_address'] = address elif 'drac_host' in driver_info and 'drac_address' in driver_info: LOG.warning(_LW('Both driver_info["drac_address"] and ' 'driver_info["drac_host"] properties are ' 'specified for node %s. Please remove the ' '"drac_host" property from the node. Ignoring ' '"drac_host" for now'), node.uuid) error_msgs = [] for param in REQUIRED_PROPERTIES: try: parsed_driver_info[param] = str(driver_info[param]) except KeyError: error_msgs.append(_("'%s' not supplied to DracDriver.") % param) except UnicodeEncodeError: error_msgs.append(_("'%s' contains non-ASCII symbol.") % param) parsed_driver_info['drac_port'] = driver_info.get('drac_port', 443) try: parsed_driver_info['drac_path'] = str(driver_info.get('drac_path', '/wsman')) except UnicodeEncodeError: error_msgs.append(_("'drac_path' contains non-ASCII symbol.")) try: parsed_driver_info['drac_protocol'] = str( driver_info.get('drac_protocol', 'https')) if parsed_driver_info['drac_protocol'] not in ['http', 'https']: error_msgs.append(_("'drac_protocol' must be either 'http' or " "'https'.")) except UnicodeEncodeError: error_msgs.append(_("'drac_protocol' contains non-ASCII symbol.")) if error_msgs: msg = (_('The following errors were encountered while parsing ' 'driver_info:\n%s') % '\n'.join(error_msgs)) raise exception.InvalidParameterValue(msg) port = parsed_driver_info['drac_port'] parsed_driver_info['drac_port'] = utils.validate_network_port( port, 'drac_port') return parsed_driver_info
def _parse_driver_info(node): """Parse a node's driver_info values. Return a dictionary of validated driver information, usable for SNMPDriver object creation. :param node: An Ironic node object. :returns: SNMP driver info. :raises: MissingParameterValue if any required parameters are missing. :raises: InvalidParameterValue if any parameters 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(_( "SNMP driver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info) snmp_info = {} # Validate PDU driver type snmp_info['driver'] = info['snmp_driver'] if snmp_info['driver'] not in DRIVER_CLASSES: raise exception.InvalidParameterValue(_( "SNMPPowerDriver: unknown driver: '%s'") % snmp_info['driver']) # In absence of a version, default to SNMPv1 snmp_info['version'] = info.get('snmp_version', SNMP_V1) if snmp_info['version'] not in (SNMP_V1, SNMP_V2C, SNMP_V3): raise exception.InvalidParameterValue(_( "SNMPPowerDriver: unknown SNMP version: '%s'") % snmp_info['version']) # In absence of a configured UDP port, default to the standard port port_str = info.get('snmp_port', SNMP_PORT) snmp_info['port'] = utils.validate_network_port(port_str, 'snmp_port') if snmp_info['port'] < 1 or snmp_info['port'] > 65535: raise exception.InvalidParameterValue(_( "SNMPPowerDriver: SNMP UDP port out of range: %d") % snmp_info['port']) # Extract version-dependent required parameters if snmp_info['version'] in (SNMP_V1, SNMP_V2C): read_community = info.get('snmp_community_read') if read_community is None: read_community = info.get('snmp_community') write_community = info.get('snmp_community_write') if write_community is None: write_community = info.get('snmp_community') if not read_community or not write_community: raise exception.MissingParameterValue(_( "SNMP driver requires `snmp_community` or " "`snmp_community_read`/`snmp_community_write` properties " "to be set for version %s.") % snmp_info['version']) snmp_info['read_community'] = read_community snmp_info['write_community'] = write_community elif snmp_info['version'] == SNMP_V3: snmp_info.update(_parse_driver_info_snmpv3_user(node, info)) snmp_info.update(_parse_driver_info_snmpv3_crypto(node, info)) snmp_info.update(_parse_driver_info_snmpv3_context(node, info)) # Target PDU IP address and power outlet identification snmp_info['address'] = info['snmp_address'] outlet = info['snmp_outlet'] try: snmp_info['outlet'] = int(outlet) except ValueError: raise exception.InvalidParameterValue(_( "SNMPPowerDriver: PDU power outlet index is not an integer: %s") % outlet) return snmp_info
def _parse_driver_info(node): """Parse a node's driver_info values. Return a dictionary of validated driver information, usable for SNMPDriver object creation. :param node: An Ironic node object. :returns: SNMP driver info. :raises: MissingParameterValue if any required parameters are missing. :raises: InvalidParameterValue if any parameters 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( _("SNMP driver requires the following parameters to be set in " "node's driver_info: %s.") % missing_info) snmp_info = {} # Validate PDU driver type snmp_info['driver'] = info.get('snmp_driver') if snmp_info['driver'] not in DRIVER_CLASSES: raise exception.InvalidParameterValue( _("SNMPPowerDriver: unknown driver: '%s'") % snmp_info['driver']) # In absence of a version, default to SNMPv1 snmp_info['version'] = info.get('snmp_version', SNMP_V1) if snmp_info['version'] not in (SNMP_V1, SNMP_V2C, SNMP_V3): raise exception.InvalidParameterValue( _("SNMPPowerDriver: unknown SNMP version: '%s'") % snmp_info['version']) # In absence of a configured UDP port, default to the standard port port_str = info.get('snmp_port', SNMP_PORT) snmp_info['port'] = utils.validate_network_port(port_str, 'snmp_port') if snmp_info['port'] < 1 or snmp_info['port'] > 65535: raise exception.InvalidParameterValue( _("SNMPPowerDriver: SNMP UDP port out of range: %d") % snmp_info['port']) # Extract version-dependent required parameters if snmp_info['version'] in (SNMP_V1, SNMP_V2C): if 'snmp_community' not in info: raise exception.MissingParameterValue( _("SNMP driver requires snmp_community to be set for version " "%s.") % snmp_info['version']) snmp_info['community'] = info.get('snmp_community') elif snmp_info['version'] == SNMP_V3: if 'snmp_security' not in info: raise exception.MissingParameterValue( _("SNMP driver requires snmp_security to be set for version %s." ) % (SNMP_V3)) snmp_info['security'] = info.get('snmp_security') # Target PDU IP address and power outlet identification snmp_info['address'] = info.get('snmp_address') snmp_info['outlet'] = info.get('snmp_outlet') return snmp_info
def _parse_driver_info(node): """Gets the parameters required for ipmitool to access the node. :param node: the Node of interest. :returns: dictionary of parameters. :raises: InvalidParameterValue when an invalid value is specified :raises: MissingParameterValue when a required ipmi parameter is missing. """ info = node.driver_info or {} bridging_types = ['single', 'dual'] missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue(_( "Missing the following IPMI credentials in node's" " driver_info: %s.") % missing_info) address = info.get('ipmi_address') username = info.get('ipmi_username') password = six.text_type(info.get('ipmi_password', '')) dest_port = info.get('ipmi_port') port = info.get('ipmi_terminal_port') priv_level = info.get('ipmi_priv_level', 'ADMINISTRATOR') bridging_type = info.get('ipmi_bridging', 'no') local_address = info.get('ipmi_local_address') transit_channel = info.get('ipmi_transit_channel') transit_address = info.get('ipmi_transit_address') target_channel = info.get('ipmi_target_channel') target_address = info.get('ipmi_target_address') protocol_version = str(info.get('ipmi_protocol_version', '2.0')) force_boot_device = info.get('ipmi_force_boot_device', False) if not username: LOG.warning(_LW('ipmi_username is not defined or empty for node %s: ' 'NULL user will be utilized.') % node.uuid) if not password: LOG.warning(_LW('ipmi_password is not defined or empty for node %s: ' 'NULL password will be utilized.') % node.uuid) if protocol_version not in VALID_PROTO_VERSIONS: valid_versions = ', '.join(VALID_PROTO_VERSIONS) raise exception.InvalidParameterValue(_( "Invalid IPMI protocol version value %(version)s, the valid " "value can be one of %(valid_versions)s") % {'version': protocol_version, 'valid_versions': valid_versions}) if port is not None: port = utils.validate_network_port(port, 'ipmi_terminal_port') if dest_port is not None: dest_port = utils.validate_network_port(dest_port, 'ipmi_port') # check if ipmi_bridging has proper value if bridging_type == 'no': # if bridging is not selected, then set all bridging params to None (local_address, transit_channel, transit_address, target_channel, target_address) = (None,) * 5 elif bridging_type in bridging_types: # check if the particular bridging option is supported on host if not _is_option_supported('%s_bridge' % bridging_type): raise exception.InvalidParameterValue(_( "Value for ipmi_bridging is provided as %s, but IPMI " "bridging is not supported by the IPMI utility installed " "on host. Ensure ipmitool version is > 1.8.11" ) % bridging_type) # ensure that all the required parameters are provided params_undefined = [param for param, value in [ ("ipmi_target_channel", target_channel), ('ipmi_target_address', target_address)] if value is None] if bridging_type == 'dual': params_undefined2 = [param for param, value in [ ("ipmi_transit_channel", transit_channel), ('ipmi_transit_address', transit_address) ] if value is None] params_undefined.extend(params_undefined2) else: # if single bridging was selected, set dual bridge params to None transit_channel = transit_address = None # If the required parameters were not provided, # raise an exception if params_undefined: raise exception.MissingParameterValue(_( "%(param)s not provided") % {'param': params_undefined}) else: raise exception.InvalidParameterValue(_( "Invalid value for ipmi_bridging: %(bridging_type)s," " the valid value can be one of: %(bridging_types)s" ) % {'bridging_type': bridging_type, 'bridging_types': bridging_types + ['no']}) if priv_level not in VALID_PRIV_LEVELS: valid_priv_lvls = ', '.join(VALID_PRIV_LEVELS) raise exception.InvalidParameterValue(_( "Invalid privilege level value:%(priv_level)s, the valid value" " can be one of %(valid_levels)s") % {'priv_level': priv_level, 'valid_levels': valid_priv_lvls}) return { 'address': address, 'dest_port': dest_port, 'username': username, 'password': password, 'port': port, 'uuid': node.uuid, 'priv_level': priv_level, 'local_address': local_address, 'transit_channel': transit_channel, 'transit_address': transit_address, 'target_channel': target_channel, 'target_address': target_address, 'protocol_version': protocol_version, 'force_boot_device': force_boot_device, }
def parse_driver_info(node): """Parse a node's driver_info values. Parses the driver_info of the node, reads default values and returns a dict containing the combination of both. :param node: an ironic node object. :returns: a dict containing information from driver_info and default values. :raises: InvalidParameterValue if some mandatory information is missing on the node or on invalid inputs. """ driver_info = node.driver_info parsed_driver_info = {} if 'drac_host' in driver_info and 'drac_address' not in driver_info: LOG.warning( 'The driver_info["drac_host"] property is deprecated ' 'and will be removed in the Pike release. Please ' 'update the node %s driver_info field to use ' '"drac_address" instead', node.uuid) address = driver_info.pop('drac_host', None) if address: driver_info['drac_address'] = address elif 'drac_host' in driver_info and 'drac_address' in driver_info: LOG.warning( 'Both driver_info["drac_address"] and ' 'driver_info["drac_host"] properties are ' 'specified for node %s. Please remove the ' '"drac_host" property from the node. Ignoring ' '"drac_host" for now', node.uuid) error_msgs = [] for param in REQUIRED_PROPERTIES: try: parsed_driver_info[param] = str(driver_info[param]) except KeyError: error_msgs.append(_("'%s' not supplied to DracDriver.") % param) except UnicodeEncodeError: error_msgs.append(_("'%s' contains non-ASCII symbol.") % param) parsed_driver_info['drac_port'] = driver_info.get('drac_port', 443) try: parsed_driver_info['drac_path'] = str( driver_info.get('drac_path', '/wsman')) except UnicodeEncodeError: error_msgs.append(_("'drac_path' contains non-ASCII symbol.")) try: parsed_driver_info['drac_protocol'] = str( driver_info.get('drac_protocol', 'https')) if parsed_driver_info['drac_protocol'] not in ['http', 'https']: error_msgs.append( _("'drac_protocol' must be either 'http' or " "'https'.")) except UnicodeEncodeError: error_msgs.append(_("'drac_protocol' contains non-ASCII symbol.")) if error_msgs: msg = (_('The following errors were encountered while parsing ' 'driver_info:\n%s') % '\n'.join(error_msgs)) raise exception.InvalidParameterValue(msg) port = parsed_driver_info['drac_port'] parsed_driver_info['drac_port'] = utils.validate_network_port( port, 'drac_port') return parsed_driver_info
def test_validate_network_port(self): port = utils.validate_network_port('0', 'message') self.assertEqual(0, port) port = utils.validate_network_port('65535') self.assertEqual(65535, port)
def _parse_optional_driver_info(node): """Parses the optional driver_info parameters. :param node: an ironic Node object. :returns: a dictionary containing information of optional properties. :raises: InvalidParameterValue if any parameters are incorrect """ info = node.driver_info optional_info = {} not_integers = [] for param in OPTIONAL_PROPERTIES: if param != 'ilo_verify_ca': value = info.get(param, CONF.ilo.get(param)) if param == "client_port": optional_info[param] = utils.validate_network_port(value, param) elif param == "client_timeout": try: optional_info[param] = int(value) except ValueError: not_integers.append(param) if not_integers: raise exception.InvalidParameterValue( _("The following iLO parameters from the node's driver_info " "should be integers: %s") % not_integers) ca_file_value = info.get('ca_file', CONF.ilo.get('ca_file')) verify_ca = info.get('ilo_verify_ca', CONF.ilo.get('verify_ca')) if ca_file_value: LOG.warning( "The `driver_info/ca_file` parameter is deprecated " "in favor of `driver_info/ilo_verify_ca` parameter. " "Please use `driver_info/ilo_verify_ca` instead of " "`driver_info/ca_file` in node %(node)s " "configuration.", {'node': node.uuid}) if not os.path.isfile(ca_file_value): raise exception.InvalidParameterValue( _('ca_file "%(value)s" is not found.') % {'value': ca_file_value}) optional_info['verify_ca'] = ca_file_value else: # Check if ilo_verify_ca is a Boolean or a file/directory # in the file-system if isinstance(verify_ca, str): if not os.path.isdir(verify_ca) and not os.path.isfile(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/' 'ilo_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/ilo_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 }) optional_info['verify_ca'] = verify_ca return optional_info
def test_validate_network_port(self): port = utils.validate_network_port("1", "message") self.assertEqual(1, port) port = utils.validate_network_port("65535") self.assertEqual(65535, port)
def test_validate_network_port(self): port = utils.validate_network_port('1', 'message') self.assertEqual(1, port) port = utils.validate_network_port('65535') self.assertEqual(65535, port)
def _parse_driver_info(node): """Gets the parameters required for ipmitool to access the node. :param node: the Node of interest. :returns: dictionary of parameters. :raises: InvalidParameterValue when an invalid value is specified :raises: MissingParameterValue when a required ipmi parameter is missing. """ info = node.driver_info or {} bridging_types = ['single', 'dual'] missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)] if missing_info: raise exception.MissingParameterValue( _("Missing the following IPMI credentials in node's" " driver_info: %s.") % missing_info) address = info.get('ipmi_address') username = info.get('ipmi_username') password = six.text_type(info.get('ipmi_password', '')) dest_port = info.get('ipmi_port') port = info.get('ipmi_terminal_port') priv_level = info.get('ipmi_priv_level', 'ADMINISTRATOR') bridging_type = info.get('ipmi_bridging', 'no') local_address = info.get('ipmi_local_address') transit_channel = info.get('ipmi_transit_channel') transit_address = info.get('ipmi_transit_address') target_channel = info.get('ipmi_target_channel') target_address = info.get('ipmi_target_address') protocol_version = str(info.get('ipmi_protocol_version', '2.0')) force_boot_device = info.get('ipmi_force_boot_device', False) if not username: LOG.warning( _LW('ipmi_username is not defined or empty for node %s: ' 'NULL user will be utilized.') % node.uuid) if not password: LOG.warning( _LW('ipmi_password is not defined or empty for node %s: ' 'NULL password will be utilized.') % node.uuid) if protocol_version not in VALID_PROTO_VERSIONS: valid_versions = ', '.join(VALID_PROTO_VERSIONS) raise exception.InvalidParameterValue( _("Invalid IPMI protocol version value %(version)s, the valid " "value can be one of %(valid_versions)s") % { 'version': protocol_version, 'valid_versions': valid_versions }) if port is not None: port = utils.validate_network_port(port, 'ipmi_terminal_port') if dest_port is not None: dest_port = utils.validate_network_port(dest_port, 'ipmi_port') # check if ipmi_bridging has proper value if bridging_type == 'no': # if bridging is not selected, then set all bridging params to None (local_address, transit_channel, transit_address, target_channel, target_address) = (None, ) * 5 elif bridging_type in bridging_types: # check if the particular bridging option is supported on host if not _is_option_supported('%s_bridge' % bridging_type): raise exception.InvalidParameterValue( _("Value for ipmi_bridging is provided as %s, but IPMI " "bridging is not supported by the IPMI utility installed " "on host. Ensure ipmitool version is > 1.8.11") % bridging_type) # ensure that all the required parameters are provided params_undefined = [ param for param, value in [( "ipmi_target_channel", target_channel), ('ipmi_target_address', target_address)] if value is None ] if bridging_type == 'dual': params_undefined2 = [ param for param, value in [( "ipmi_transit_channel", transit_channel), ('ipmi_transit_address', transit_address)] if value is None ] params_undefined.extend(params_undefined2) else: # if single bridging was selected, set dual bridge params to None transit_channel = transit_address = None # If the required parameters were not provided, # raise an exception if params_undefined: raise exception.MissingParameterValue( _("%(param)s not provided") % {'param': params_undefined}) else: raise exception.InvalidParameterValue( _("Invalid value for ipmi_bridging: %(bridging_type)s," " the valid value can be one of: %(bridging_types)s") % { 'bridging_type': bridging_type, 'bridging_types': bridging_types + ['no'] }) if priv_level not in VALID_PRIV_LEVELS: valid_priv_lvls = ', '.join(VALID_PRIV_LEVELS) raise exception.InvalidParameterValue( _("Invalid privilege level value:%(priv_level)s, the valid value" " can be one of %(valid_levels)s") % { 'priv_level': priv_level, 'valid_levels': valid_priv_lvls }) return { 'address': address, 'dest_port': dest_port, 'username': username, 'password': password, 'port': port, 'uuid': node.uuid, 'priv_level': priv_level, 'local_address': local_address, 'transit_channel': transit_channel, 'transit_address': transit_address, 'target_channel': target_channel, 'target_address': target_address, 'protocol_version': protocol_version, 'force_boot_device': force_boot_device, }