def _parse_node_properties(self, node): """Helper method to parse the node's properties.""" properties = {} for prop in ("cpus", "memory_mb", "local_gb"): try: properties[prop] = int(node.properties.get(prop, 0)) except (TypeError, ValueError): LOG.warning( _LW('Node %(uuid)s has a malformed "%(prop)s". ' "It should be an integer."), {"uuid": node.uuid, "prop": prop}, ) properties[prop] = 0 raw_cpu_arch = node.properties.get("cpu_arch", None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warning(_LW("cpu_arch not defined for node '%s'"), node.uuid) properties["cpu_arch"] = cpu_arch properties["raw_cpu_arch"] = raw_cpu_arch properties["capabilities"] = node.properties.get("capabilities") return properties
def coerce(self, obj, attr, value): try: value = arch.canonicalize(value) except exception.InvalidArchitectureName: msg = _("Architecture name '%s' is not valid") % value raise ValueError(msg) return super(Architecture, self).coerce(obj, attr, value)
def _parse_node_properties(self, node): """Helper method to parse the node's properties.""" properties = {} for prop in ('cpus', 'memory_mb', 'local_gb'): try: properties[prop] = int(node.properties.get(prop, 0)) except (TypeError, ValueError): LOG.warning( _LW('Node %(uuid)s has a malformed "%(prop)s". ' 'It should be an integer.'), { 'uuid': node.uuid, 'prop': prop }) properties[prop] = 0 raw_cpu_arch = node.properties.get('cpu_arch', None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warning(_LW("cpu_arch not defined for node '%s'"), node.uuid) properties['cpu_arch'] = cpu_arch properties['raw_cpu_arch'] = raw_cpu_arch properties['capabilities'] = node.properties.get('capabilities') return properties
def __init__(self, virtapi, read_only=False): super(BareMetalDriver, self).__init__(virtapi) self.driver = importutils.import_object( CONF.baremetal.driver, virtapi) self.vif_driver = importutils.import_object( CONF.baremetal.vif_driver) self.firewall_driver = firewall.load_driver( default=DEFAULT_FIREWALL_DRIVER) self.volume_driver = importutils.import_object( CONF.baremetal.volume_driver, virtapi) self.image_cache_manager = imagecache.ImageCacheManager() extra_specs = {} extra_specs["baremetal_driver"] = CONF.baremetal.driver for pair in CONF.baremetal.flavor_extra_specs: keyval = pair.split(':', 1) keyval[0] = keyval[0].strip() keyval[1] = keyval[1].strip() extra_specs[keyval[0]] = keyval[1] self.extra_specs = extra_specs if 'cpu_arch' not in extra_specs: LOG.info( _('cpu_arch is not found in flavor_extra_specs')) self.supported_instances = [] else: self.supported_instances = [( arch.canonicalize(extra_specs['cpu_arch']), hvtype.BAREMETAL, vm_mode.HVM ), ]
def _parse_node_properties(self, node): """Helper method to parse the node's properties.""" properties = {} for prop in ('cpus', 'memory_mb', 'local_gb'): try: properties[prop] = int(node.properties.get(prop, 0)) except (TypeError, ValueError): LOG.warning(_LW('Node %(uuid)s has a malformed "%(prop)s". ' 'It should be an integer.'), {'uuid': node.uuid, 'prop': prop}) properties[prop] = 0 raw_cpu_arch = node.properties.get('cpu_arch', None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warning(_LW("cpu_arch not defined for node '%s'"), node.uuid) properties['cpu_arch'] = cpu_arch properties['raw_cpu_arch'] = raw_cpu_arch properties['capabilities'] = node.properties.get('capabilities') return properties
def _instance_supported(self, host_state, image_props, hypervisor_version): img_arch = image_props.get('hw_architecture') img_h_type = image_props.get('img_hv_type') if not img_h_type: img_h_type = 'qemu' img_vm_mode = image_props.get('hw_vm_mode') checked_img_props = ( arch.canonicalize(img_arch), hv_type.canonicalize(img_h_type), vm_mode.canonicalize(img_vm_mode) ) # Supported if no compute-related instance properties are specified if not any(checked_img_props): return True supp_instances = host_state.supported_instances # Not supported if an instance property is requested but nothing # advertised by the host. if not supp_instances: LOG.debug("Instance contains properties %(image_props)s, " "but no corresponding supported_instances are " "advertised by the compute node", {'image_props': image_props}) return False def _compare_props(props, other_props): for i in props: if i and i not in other_props: return False return True def _compare_product_version(hyper_version, image_props): version_required = image_props.get('img_hv_requested_version') if not(hypervisor_version and version_required): return True img_prop_predicate = versionpredicate.VersionPredicate( 'image_prop (%s)' % version_required) hyper_ver_str = versionutils.convert_version_to_str(hyper_version) return img_prop_predicate.satisfied_by(hyper_ver_str) for supp_inst in supp_instances: if _compare_props(checked_img_props, supp_inst): if _compare_product_version(hypervisor_version, image_props): return True LOG.debug("Instance contains properties %(image_props)s " "that are not provided by the compute node " "supported_instances %(supp_instances)s or " "hypervisor version %(hypervisor_version)s do not match", {'image_props': image_props, 'supp_instances': supp_instances, 'hypervisor_version': hypervisor_version}) return False
def _instance_supported(self, host_state, image_props, hypervisor_version): img_arch = image_props.get('hw_architecture') img_h_type = image_props.get('img_hv_type') img_vm_mode = image_props.get('hw_vm_mode') checked_img_props = ( arch.canonicalize(img_arch), hv_type.canonicalize(img_h_type), vm_mode.canonicalize(img_vm_mode) ) # Supported if no compute-related instance properties are specified if not any(checked_img_props): return True supp_instances = host_state.supported_instances # Not supported if an instance property is requested but nothing # advertised by the host. if not supp_instances: LOG.debug("Instance contains properties %(image_props)s, " "but no corresponding supported_instances are " "advertised by the compute node", {'image_props': image_props}) return False def _compare_props(props, other_props): for i in props: if i and i not in other_props: return False return True def _compare_product_version(hyper_version, image_props): version_required = image_props.get('img_hv_requested_version') if not(hypervisor_version and version_required): return True img_prop_predicate = versionpredicate.VersionPredicate( 'image_prop ({0!s})'.format(version_required)) hyper_ver_str = versionutils.convert_version_to_str(hyper_version) return img_prop_predicate.satisfied_by(hyper_ver_str) for supp_inst in supp_instances: if _compare_props(checked_img_props, supp_inst): if _compare_product_version(hypervisor_version, image_props): return True LOG.debug("Instance contains properties %(image_props)s " "that are not provided by the compute node " "supported_instances %(supp_instances)s or " "hypervisor version %(hypervisor_version)s do not match", {'image_props': image_props, 'supp_instances': supp_instances, 'hypervisor_version': hypervisor_version}) return False
def get_arch(image_meta): """Determine the architecture of the guest (or host). This method determines the CPU architecture that must be supported by the hypervisor. It gets the (guest) arch info from image_meta properties, and it will fallback to the nova-compute (host) arch if no architecture info is provided in image_meta. :param image_meta: the metadata associated with the instance image :returns: guest (or host) architecture """ if image_meta: image_arch = image_meta.get('properties', {}).get('architecture') if image_arch is not None: return arch.canonicalize(image_arch) return arch.from_host()
def to_supported_instances(host_capabilities): if not host_capabilities: return [] result = [] for capability in host_capabilities: try: # 'capability'is unicode but we want arch/ostype # to be strings to match the standard constants capability = str(capability) ostype, _version, guestarch = capability.split("-") guestarch = arch.canonicalize(guestarch) result.append((guestarch, 'xapi', ostype)) except ValueError: LOG.warning( _("Failed to extract instance support from %s"), capability) return result
def to_supported_instances(host_capabilities): if not host_capabilities: return [] result = [] for capability in host_capabilities: try: # 'capability'is unicode but we want arch/ostype # to be strings to match the standard constants capability = str(capability) ostype, _version, guestarch = capability.split("-") guestarch = arch.canonicalize(guestarch) result.append((guestarch, hvtype.XEN, ostype)) except ValueError: LOG.warning(_("Failed to extract instance support from %s"), capability) return result
def test_canonicalize_compat_xen2(self): self.assertEqual(arch.I686, arch.canonicalize("x86_32p"))
def test_canonicalize_i386(self): self.assertEqual(arch.I686, arch.canonicalize("i386"))
def _node_resource(self, node): """Helper method to create resource dict from node stats.""" vcpus = int(node.properties.get('cpus', 0)) memory_mb = int(node.properties.get('memory_mb', 0)) local_gb = int(node.properties.get('local_gb', 0)) raw_cpu_arch = node.properties.get('cpu_arch', None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warn(_LW("cpu_arch not defined for node '%s'"), node.uuid) nodes_extra_specs = {} # NOTE(deva): In Havana and Icehouse, the flavor was required to link # to an arch-specific deploy kernel and ramdisk pair, and so the flavor # also had to have extra_specs['cpu_arch'], which was matched against # the ironic node.properties['cpu_arch']. # With Juno, the deploy image(s) may be referenced directly by the # node.driver_info, and a flavor no longer needs to contain any of # these three extra specs, though the cpu_arch may still be used # in a heterogeneous environment, if so desired. # NOTE(dprince): we use the raw cpu_arch here because extra_specs # filters aren't canonicalized nodes_extra_specs['cpu_arch'] = raw_cpu_arch # NOTE(gilliard): To assist with more precise scheduling, if the # node.properties contains a key 'capabilities', we expect the value # to be of the form "k1:v1,k2:v2,etc.." which we add directly as # key/value pairs into the node_extra_specs to be used by the # ComputeCapabilitiesFilter capabilities = node.properties.get('capabilities') if capabilities: for capability in str(capabilities).split(','): parts = capability.split(':') if len(parts) == 2 and parts[0] and parts[1]: nodes_extra_specs[parts[0]] = parts[1] else: LOG.warn( _LW("Ignoring malformed capability '%s'. " "Format should be 'key:val'."), capability) vcpus_used = 0 memory_mb_used = 0 local_gb_used = 0 if node.instance_uuid: # Node has an instance, report all resource as unavailable vcpus_used = vcpus memory_mb_used = memory_mb local_gb_used = local_gb elif self._node_resources_unavailable(node): # The node's current state is such that it should not present any # of its resources to Nova vcpus = 0 memory_mb = 0 local_gb = 0 dic = { 'node': str(node.uuid), 'hypervisor_hostname': str(node.uuid), 'hypervisor_type': self._get_hypervisor_type(), 'hypervisor_version': self._get_hypervisor_version(), 'cpu_info': 'baremetal cpu', 'vcpus': vcpus, 'vcpus_used': vcpus_used, 'local_gb': local_gb, 'local_gb_used': local_gb_used, 'disk_total': local_gb, 'disk_used': local_gb_used, 'disk_available': local_gb - local_gb_used, 'memory_mb': memory_mb, 'memory_mb_used': memory_mb_used, 'host_memory_total': memory_mb, 'host_memory_free': memory_mb - memory_mb_used, 'supported_instances': jsonutils.dumps(_get_nodes_supported_instances(cpu_arch)), 'stats': jsonutils.dumps(nodes_extra_specs), 'host': CONF.host, } dic.update(nodes_extra_specs) return dic
def _node_resource(self, node): """Helper method to create resource dict from node stats.""" vcpus = int(node.properties.get('cpus', 0)) memory_mb = int(node.properties.get('memory_mb', 0)) local_gb = int(node.properties.get('local_gb', 0)) raw_cpu_arch = node.properties.get('cpu_arch', None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warning(_LW("cpu_arch not defined for node '%s'"), node.uuid) nodes_extra_specs = {} # NOTE(deva): In Havana and Icehouse, the flavor was required to link # to an arch-specific deploy kernel and ramdisk pair, and so the flavor # also had to have extra_specs['cpu_arch'], which was matched against # the ironic node.properties['cpu_arch']. # With Juno, the deploy image(s) may be referenced directly by the # node.driver_info, and a flavor no longer needs to contain any of # these three extra specs, though the cpu_arch may still be used # in a heterogeneous environment, if so desired. # NOTE(dprince): we use the raw cpu_arch here because extra_specs # filters aren't canonicalized nodes_extra_specs['cpu_arch'] = raw_cpu_arch # NOTE(gilliard): To assist with more precise scheduling, if the # node.properties contains a key 'capabilities', we expect the value # to be of the form "k1:v1,k2:v2,etc.." which we add directly as # key/value pairs into the node_extra_specs to be used by the # ComputeCapabilitiesFilter capabilities = node.properties.get('capabilities') if capabilities: for capability in str(capabilities).split(','): parts = capability.split(':') if len(parts) == 2 and parts[0] and parts[1]: nodes_extra_specs[parts[0]] = parts[1] else: LOG.warning(_LW("Ignoring malformed capability '%s'. " "Format should be 'key:val'."), capability) vcpus_used = 0 memory_mb_used = 0 local_gb_used = 0 if node.instance_uuid: # Node has an instance, report all resource as unavailable vcpus_used = vcpus memory_mb_used = memory_mb local_gb_used = local_gb elif self._node_resources_unavailable(node): # The node's current state is such that it should not present any # of its resources to Nova vcpus = 0 memory_mb = 0 local_gb = 0 def _get_total_network_bandwidth (): ethersOut = os.popen('ls -d /sys/class/net/eth*'); ethers = ethersOut.readlines(); totalSpeed = 0; for ether in ethers: cmd = 'cat ' + ether[:-1] + '/speed'; speed = os.popen(cmd); speedInMB = int (speed.read()); totalSpeed = totalSpeed + speedInMB; speed.close(); ethersOut.close(); return totalSpeed; total_bandwidth = _get_total_network_bandwidth (); bandwidth_used = 0; dic = { 'node': str(node.uuid), 'hypervisor_hostname': str(node.uuid), 'hypervisor_type': self._get_hypervisor_type(), 'hypervisor_version': self._get_hypervisor_version(), 'cpu_info': 'baremetal cpu', 'vcpus': vcpus, 'vcpus_used': vcpus_used, 'local_gb': local_gb, 'local_gb_used': local_gb_used, 'disk_total': local_gb, 'disk_used': local_gb_used, 'disk_available': local_gb - local_gb_used, 'memory_mb': memory_mb, 'memory_mb_used': memory_mb_used, 'host_memory_total': memory_mb, 'host_memory_free': memory_mb - memory_mb_used, 'supported_instances': jsonutils.dumps( _get_nodes_supported_instances(cpu_arch)), 'stats': jsonutils.dumps(nodes_extra_specs), 'host': CONF.host, 'total_bandwidth': total_bandwidth, 'bandwidth_used': bandwidth_used } dic.update(nodes_extra_specs) return dic
def _node_resource(self, node): """Helper method to create resource dict from node stats.""" vcpus = int(node.properties.get("cpus", 0)) memory_mb = int(node.properties.get("memory_mb", 0)) local_gb = int(node.properties.get("local_gb", 0)) raw_cpu_arch = node.properties.get("cpu_arch", None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warn(_LW("cpu_arch not defined for node '%s'"), node.uuid) nodes_extra_specs = {} # NOTE(deva): In Havana and Icehouse, the flavor was required to link # to an arch-specific deploy kernel and ramdisk pair, and so the flavor # also had to have extra_specs['cpu_arch'], which was matched against # the ironic node.properties['cpu_arch']. # With Juno, the deploy image(s) may be referenced directly by the # node.driver_info, and a flavor no longer needs to contain any of # these three extra specs, though the cpu_arch may still be used # in a heterogeneous environment, if so desired. # NOTE(dprince): we use the raw cpu_arch here because extra_specs # filters aren't canonicalized nodes_extra_specs["cpu_arch"] = raw_cpu_arch # NOTE(gilliard): To assist with more precise scheduling, if the # node.properties contains a key 'capabilities', we expect the value # to be of the form "k1:v1,k2:v2,etc.." which we add directly as # key/value pairs into the node_extra_specs to be used by the # ComputeCapabilitiesFilter capabilities = node.properties.get("capabilities") if capabilities: for capability in str(capabilities).split(","): parts = capability.split(":") if len(parts) == 2 and parts[0] and parts[1]: nodes_extra_specs[parts[0]] = parts[1] else: LOG.warn(_LW("Ignoring malformed capability '%s'. " "Format should be 'key:val'."), capability) vcpus_used = 0 memory_mb_used = 0 local_gb_used = 0 if node.instance_uuid: # Node has an instance, report all resource as unavailable vcpus_used = vcpus memory_mb_used = memory_mb local_gb_used = local_gb elif self._node_resources_unavailable(node): # The node's current state is such that it should not present any # of its resources to Nova vcpus = 0 memory_mb = 0 local_gb = 0 dic = { "node": str(node.uuid), "hypervisor_hostname": str(node.uuid), "hypervisor_type": self._get_hypervisor_type(), "hypervisor_version": self._get_hypervisor_version(), "cpu_info": "baremetal cpu", "vcpus": vcpus, "vcpus_used": vcpus_used, "local_gb": local_gb, "local_gb_used": local_gb_used, "disk_total": local_gb, "disk_used": local_gb_used, "disk_available": local_gb - local_gb_used, "memory_mb": memory_mb, "memory_mb_used": memory_mb_used, "host_memory_total": memory_mb, "host_memory_free": memory_mb - memory_mb_used, "supported_instances": jsonutils.dumps(_get_nodes_supported_instances(cpu_arch)), "stats": jsonutils.dumps(nodes_extra_specs), "host": CONF.host, } dic.update(nodes_extra_specs) return dic
def test_canonicalize_case(self): self.assertEqual(arch.X86_64, arch.canonicalize("X86_64"))
def _node_resource(self, node): """Helper method to create resource dict from node stats.""" vcpus = int(node.properties.get('cpus', 0)) memory_mb = int(node.properties.get('memory_mb', 0)) local_gb = int(node.properties.get('local_gb', 0)) raw_cpu_arch = node.properties.get('cpu_arch', None) try: cpu_arch = arch.canonicalize(raw_cpu_arch) except exception.InvalidArchitectureName: cpu_arch = None if not cpu_arch: LOG.warning(_LW("cpu_arch not defined for node '%s'"), node.uuid) nodes_extra_specs = {} # NOTE(deva): In Havana and Icehouse, the flavor was required to link # to an arch-specific deploy kernel and ramdisk pair, and so the flavor # also had to have extra_specs['cpu_arch'], which was matched against # the ironic node.properties['cpu_arch']. # With Juno, the deploy image(s) may be referenced directly by the # node.driver_info, and a flavor no longer needs to contain any of # these three extra specs, though the cpu_arch may still be used # in a heterogeneous environment, if so desired. # NOTE(dprince): we use the raw cpu_arch here because extra_specs # filters aren't canonicalized nodes_extra_specs['cpu_arch'] = raw_cpu_arch # NOTE(gilliard): To assist with more precise scheduling, if the # node.properties contains a key 'capabilities', we expect the value # to be of the form "k1:v1,k2:v2,etc.." which we add directly as # key/value pairs into the node_extra_specs to be used by the # ComputeCapabilitiesFilter capabilities = node.properties.get('capabilities') if capabilities: for capability in str(capabilities).split(','): parts = capability.split(':') if len(parts) == 2 and parts[0] and parts[1]: nodes_extra_specs[parts[0]] = parts[1] else: LOG.warning(_LW("Ignoring malformed capability '%s'. " "Format should be 'key:val'."), capability) vcpus_used = 0 memory_mb_used = 0 local_gb_used = 0 if self._node_resources_used(node): # Node is in the process of deploying, is deployed, or is in # the process of cleaning up from a deploy. Report all of its # resources as in use. vcpus_used = vcpus memory_mb_used = memory_mb local_gb_used = local_gb elif self._node_resources_unavailable(node): # The node's current state is such that it should not present any # of its resources to Nova vcpus = 0 memory_mb = 0 local_gb = 0 dic = { 'hypervisor_hostname': str(node.uuid), 'hypervisor_type': self._get_hypervisor_type(), 'hypervisor_version': self._get_hypervisor_version(), # The Ironic driver manages multiple hosts, so there are # likely many different CPU models in use. As such it is # impossible to provide any meaningful info on the CPU # model of the "host" 'cpu_info': None, 'vcpus': vcpus, 'vcpus_used': vcpus_used, 'local_gb': local_gb, 'local_gb_used': local_gb_used, 'disk_available_least': local_gb - local_gb_used, 'memory_mb': memory_mb, 'memory_mb_used': memory_mb_used, 'supported_instances': jsonutils.dumps( _get_nodes_supported_instances(cpu_arch)), 'stats': jsonutils.dumps(nodes_extra_specs), } return dic
def test_canonicalize_amd64(self): self.assertEqual(arch.X86_64, arch.canonicalize("amd64"))