Example #1
0
    def set_hvdevs(self, devices):
        """Sync the pci device tracker with hypervisor information.

        To support pci device hot plug, we sync with the hypervisor
        periodically, fetching all devices information from hypervisor,
        update the tracker and sync the DB information.

        Devices should not be hot-plugged when assigned to a guest,
        but possibly the hypervisor has no such guarantee. The best
        we can do is to give a warning if a device is changed
        or removed while assigned.
        """

        exist_addrs = set([dev['address'] for dev in self.pci_devs])
        new_addrs = set([dev['address'] for dev in devices])

        for existed in self.pci_devs:
            if existed['address'] in exist_addrs - new_addrs:
                try:
                    pci_device.remove(existed)
                except exception.PciDeviceInvalidStatus as e:
                    LOG.warn(_("Trying to remove device with %(status)s "
                               "ownership %(instance_uuid)s because of "
                               "%(pci_exception)s"), {'status': existed.status,
                                  'instance_uuid': existed.instance_uuid,
                                  'pci_exception': e.format_message()})
                    # Note(yjiang5): remove the device by force so that
                    # db entry is cleaned in next sync.
                    existed.status = 'removed'
                else:
                    # Note(yjiang5): no need to update stats if an assigned
                    # device is hot removed.
                    self.stats.consume_device(existed)
            else:
                new_value = next((dev for dev in devices if
                    dev['address'] == existed['address']))
                new_value['compute_node_id'] = self.node_id
                if existed['status'] in ('claimed', 'allocated'):
                    # Pci properties may change while assigned because of
                    # hotplug or config changes. Although normally this should
                    # not happen.

                    # As the devices have been assigned to a instance, we defer
                    # the change till the instance is destroyed. We will
                    # not sync the new properties with database before that.

                    # TODO(yjiang5): Not sure if this is a right policy, but
                    # at least it avoids some confusion and, if needed,
                    # we can add more action like killing the instance
                    # by force in future.
                    self.stale[dev['address']] = dev
                else:
                    pci_device.update_device(existed, new_value)

        for dev in [dev for dev in devices if
                    dev['address'] in new_addrs - exist_addrs]:
            dev['compute_node_id'] = self.node_id
            dev_obj = pci_device_obj.PciDevice.create(dev)
            self.pci_devs.append(dev_obj)
            self.stats.add_device(dev_obj)
Example #2
0
    def set_hvdevs(self, devices):
        """Sync the pci device tracker with hypervisor information.

        To support pci device hot plug, we sync with the hypervisor
        periodically, fetching all devices information from hypervisor,
        update the tracker and sync the DB information.

        Devices should not be hot-plugged when assigned to a guest,
        but possibly the hypervisor has no such guarantee. The best
        we can do is to give a warning if a device is changed
        or removed while assigned.
        """

        exist_addrs = set([dev['address'] for dev in self.pci_devs])
        new_addrs = set([dev['address'] for dev in devices])

        for existed in self.pci_devs:
            if existed['address'] in exist_addrs - new_addrs:
                try:
                    pci_device.remove(existed)
                except exception.PciDeviceInvalidStatus as e:
                    LOG.warn(_("Trying to remove device with %(status)s "
                               "ownership %(instance_uuid)s because of "
                               "%(pci_exception)s"), {'status': existed.status,
                                  'instance_uuid': existed.instance_uuid,
                                  'pci_exception': e.format_message()})
                    # Note(yjiang5): remove the device by force so that
                    # db entry is cleaned in next sync.
                    existed.status = 'removed'
                else:
                    # Note(yjiang5): no need to update stats if an assigned
                    # device is hot removed.
                    self.stats.remove_device(existed)
            else:
                new_value = next((dev for dev in devices if
                    dev['address'] == existed['address']))
                new_value['compute_node_id'] = self.node_id
                if existed['status'] in ('claimed', 'allocated'):
                    # Pci properties may change while assigned because of
                    # hotplug or config changes. Although normally this should
                    # not happen.

                    # As the devices have been assigned to a instance, we defer
                    # the change till the instance is destroyed. We will
                    # not sync the new properties with database before that.

                    # TODO(yjiang5): Not sure if this is a right policy, but
                    # at least it avoids some confusion and, if needed,
                    # we can add more action like killing the instance
                    # by force in future.
                    self.stale[dev['address']] = dev
                else:
                    pci_device.update_device(existed, new_value)

        for dev in [dev for dev in devices if
                    dev['address'] in new_addrs - exist_addrs]:
            dev['compute_node_id'] = self.node_id
            dev_obj = objects.PciDevice.create(dev)
            self.pci_devs.append(dev_obj)
            self.stats.add_device(dev_obj)
Example #3
0
 def test_save_removed(self):
     self.stubs.Set(db, "pci_device_update", self._fake_pci_device_update)
     self.stubs.Set(db, "pci_device_destroy", self._fake_pci_device_destroy)
     self.destroy_called = 0
     self.assertEqual(len(self.tracker.pci_devs), 3)
     dev = self.tracker.pci_devs[0]
     self.update_called = 0
     pci_device.remove(dev)
     self.tracker.save(self.fake_context)
     self.assertEqual(len(self.tracker.pci_devs), 2)
     self.assertEqual(self.destroy_called, 1)
Example #4
0
 def test_save_removed(self):
     self.stubs.Set(db, "pci_device_update", self._fake_pci_device_update)
     self.stubs.Set(db, "pci_device_destroy", self._fake_pci_device_destroy)
     self.destroy_called = 0
     self.assertEqual(len(self.tracker.pci_devs), 3)
     dev = self.tracker.pci_devs[0]
     self.update_called = 0
     pci_device.remove(dev)
     self.tracker.save(self.fake_context)
     self.assertEqual(len(self.tracker.pci_devs), 2)
     self.assertEqual(self.destroy_called, 1)
Example #5
0
 def test_remove_device(self):
     pci_device.remove(self.devobj)
     self.assertEqual(self.devobj.status, 'removed')
     self.assertIsNone(self.devobj.instance_uuid)
 def test_remove_device(self):
     pci_device.remove(self.devobj)
     self.assertEqual(self.devobj.status, 'removed')
     self.assertIsNone(self.devobj.instance_uuid)