def __init__( self, context: ctx.RequestContext, compute_node: 'objects.ComputeNode', ): """Create a pci device tracker. :param context: The request context. :param compute_node: The object.ComputeNode whose PCI devices we're tracking. """ self.stale: ty.Dict[str, objects.PciDevice] = {} self.node_id: str = compute_node.id self.dev_filter = whitelist.Whitelist(CONF.pci.passthrough_whitelist) numa_topology = compute_node.numa_topology if numa_topology: # For legacy reasons, the NUMATopology is stored as a JSON blob. # Deserialize it into a real object. numa_topology = objects.NUMATopology.obj_from_db_obj(numa_topology) self.stats = stats.PciDeviceStats(numa_topology, dev_filter=self.dev_filter) self._context = context self.pci_devs = objects.PciDeviceList.get_by_compute_node( context, self.node_id) self._build_device_tree(self.pci_devs) self._initial_instance_usage()
def test_device_not_assignable_regex(self): white_list = ('{"address":{"domain": ".*", "bus": ".*", ' '"slot": "0a", "function": "[2-3]"}, ' '"physical_network":"hr_net"}') parsed = whitelist.Whitelist( [white_list]) self.assertFalse(parsed.device_assignable(dev_dict))
def __init__(self, stats=None, dev_filter=None): super(PciDeviceStats, self).__init__() # NOTE(sbauza): Stats are a PCIDevicePoolList object self.pools = [pci_pool.to_dict() for pci_pool in stats] if stats else [] self.pools.sort(key=lambda item: len(item)) self.dev_filter = dev_filter or whitelist.Whitelist( CONF.pci.passthrough_whitelist)
def setUp(self): super(PciDeviceStatsWithTagsTestCase, self).setUp() white_list = ['{"vendor_id":"1137","product_id":"0071",' '"address":"*:0a:00.*","physical_network":"physnet1"}', '{"vendor_id":"1137","product_id":"0072"}'] self.flags(pci_passthrough_whitelist=white_list) dev_filter = whitelist.Whitelist(white_list) self.pci_stats = stats.PciDeviceStats(dev_filter=dev_filter)
def test_device_assignable_multiple(self): white_list_1 = '{"product_id":"0001", "vendor_id":"8086"}' white_list_2 = '{"product_id":"0002", "vendor_id":"8087"}' parsed = whitelist.Whitelist([white_list_1, white_list_2]) self.assertTrue(parsed.device_assignable(dev_dict)) dev_dict1 = dev_dict.copy() dev_dict1['vendor_id'] = '8087' dev_dict1['product_id'] = '0002' self.assertTrue(parsed.device_assignable(dev_dict1))
def index(self, req): """Returns list of devices. The list is filtered by device id or alias if specified in the request, else all devices are returned. """ context = req.environ['nova.context'] context.can(wrs_pci_policies.BASE_POLICY_NAME) nodes = objects.ComputeNodeList.get_all(context) # The pci alias parameter has the same format as the PCI whitelist. # Load the list of devices that are enabled for passthrough to a # guest, and show resource usage for each. pci_filter = whitelist.Whitelist(CONF.pci.alias) device_usage = [] for spec in pci_filter.specs: tags = spec.get_tags() dev_name = tags.get('name') device_id = spec.product_id # Optional request to list by (PCI alias) name, or device id. if 'device' in req.GET: req_device = req.GET['device'] if req_device == dev_name or req_device == spec.product_id: device_id = spec.product_id else: continue class_id = tags.get("class_id", None) usage = WrsPciUsage(device_id, spec.vendor_id, class_id) for node in nodes: usage.get_device_usage_by_node(node) if (usage.pci_pfs_configured > 0 or usage.pci_vfs_configured > 0): device_usage.append({ 'device_name': str(dev_name), 'device_id': usage.product_id, 'vendor_id': usage.vendor_id, 'class_id': usage.class_id, 'pci_pfs_configured': usage.pci_pfs_configured, 'pci_pfs_used': usage.pci_pfs_configured - usage.pci_pfs_count, 'pci_vfs_configured': usage.pci_vfs_configured, 'pci_vfs_used': usage.pci_vfs_configured - usage.pci_vfs_count }) return {'pci_device_usage': device_usage}
def __init__( self, numa_topology: 'objects.NUMATopology', stats: 'objects.PCIDevicePoolList' = None, dev_filter: whitelist.Whitelist = None, ) -> None: self.numa_topology = numa_topology self.pools = ([pci_pool.to_dict() for pci_pool in stats] if stats else []) self.pools.sort(key=lambda item: len(item)) self.dev_filter = dev_filter or whitelist.Whitelist( CONF.pci.passthrough_whitelist)
def setUp(self): super(PciDeviceStatsWithTagsTestCase, self).setUp() white_list = [ '{"vendor_id":"1137","product_id":"0071",' '"address":"*:0a:00.*","physical_network":"physnet1"}', '{"vendor_id":"1137","product_id":"0072"}', '{"vendor_id":"15b3","product_id":"101e", ' '"remote_managed": "true"}', '{"vendor_id":"15b3","product_id":"101c"}', '{"vendor_id":"15b3","product_id":"1018", ' '"remote_managed": "false"}' ] self.flags(passthrough_whitelist=white_list, group='pci') dev_filter = whitelist.Whitelist(white_list) self.pci_stats = stats.PciDeviceStats(objects.NUMATopology(), dev_filter=dev_filter)
def __init__(self, context, node_id=None): """Create a pci device tracker. If a node_id is passed in, it will fetch pci devices information from database, otherwise, it will create an empty devices list and the resource tracker will update the node_id information later. """ super(PciDevTracker, self).__init__() self.stale = {} self.node_id = node_id self.stats = stats.PciDeviceStats() self.dev_filter = whitelist.Whitelist(CONF.pci_passthrough_whitelist) if node_id: self.pci_devs = objects.PciDeviceList.get_by_compute_node( context, node_id) else: self.pci_devs = objects.PciDeviceList(objects=[]) self._initial_instance_usage()
def show(self, req, id): """Returns list of host usage for a particular device. The list is filtered by host if specified in the request, else all hosts are returned. Note that the id parameter can be the PCI alias or PCI device id. """ context = req.environ['nova.context'] context.can(wrs_pci_policies.BASE_POLICY_NAME) host = None if 'host' in req.GET: host = req.GET['host'] if host: nodes = objects.ComputeNodeList.get_all_by_host(context, host) else: nodes = objects.ComputeNodeList.get_all(context) # The pci alias parameter has the same format as the PCI whitelist. # Load the list of devices that are enabled for passthrough to a # guest, and show resource usage for each. pci_filter = whitelist.Whitelist(CONF.pci.alias) device_usage = [] for spec in pci_filter.specs: tags = spec.get_tags() # Devices can be shown by (PCI alias) name, or device id. dev_name = tags.get('name') if id == dev_name: device_id = spec.product_id else: device_id = id if device_id != spec.product_id: continue for node in nodes: class_id = tags.get("class_id", None) usage = WrsPciUsage(device_id, spec.vendor_id, class_id) usage.get_device_usage_by_node(node) device_usage.append({ 'device_name': str(dev_name), 'device_id': usage.product_id, 'vendor_id': usage.vendor_id, 'class_id': usage.class_id, 'host': node.host, 'pci_pfs_configured': usage.pci_pfs_configured, 'pci_pfs_used': usage.pci_pfs_configured - usage.pci_pfs_count, 'pci_vfs_configured': usage.pci_vfs_configured, 'pci_vfs_used': usage.pci_vfs_configured - usage.pci_vfs_count }) return {'pci_device_usage': device_usage}
def test_device_assignable(self): white_list = '{"product_id":"0001", "vendor_id":"8086"}' parsed = whitelist.Whitelist([white_list]) self.assertTrue(parsed.device_assignable(dev_dict))
def test_device_not_assignable_glob(self): white_list = '{"address":"*:00:0b.*", "physical_network":"hr_net"}' parsed = whitelist.Whitelist( [white_list]) self.assertFalse(parsed.device_assignable(dev_dict))
def test_whitelist_multiple(self): wl1 = '{"product_id":"0001", "vendor_id":"8086"}' wl2 = '{"product_id":"0002", "vendor_id":"8087"}' parsed = whitelist.Whitelist([wl1, wl2]) self.assertEqual(2, len(parsed.specs))
def test_whitelist_empty(self): parsed = whitelist.Whitelist() self.assertFalse(parsed.device_assignable(dev_dict))
def test_whitelist_list_format(self): white_list = '[{"product_id":"0001", "vendor_id":"8086"},'\ '{"product_id":"0002", "vendor_id":"8086"}]' parsed = whitelist.Whitelist([white_list]) self.assertEqual(2, len(parsed.specs))
def test_whitelist(self): white_list = '{"product_id":"0001", "vendor_id":"8086"}' parsed = whitelist.Whitelist([white_list]) self.assertEqual(1, len(parsed.specs))