nova-manage: Declare a PciDevice online migration script

We want to make sure there is a way for operators to migrate all PciDevice
records to the new format. The original online migration code was added
was part of the following change:

https://review.openstack.org/#/c/249015/

Closes-bug: 1543562
Change-Id: I2fc2f9ffac860cf25535abc9b53733bce6ddf345
This commit is contained in:
Nikola Dipanov
2016-02-12 21:40:47 +00:00
committed by John Garbutt
parent c1e9a241d2
commit 0970f2a900
4 changed files with 84 additions and 3 deletions

View File

@@ -923,7 +923,9 @@ class HostCommands(object):
class DbCommands(object):
"""Class for managing the main database."""
online_migrations = ()
online_migrations = (
db.pcidevice_online_data_migration,
)
def __init__(self):
pass

View File

@@ -1969,6 +1969,10 @@ def archive_deleted_rows(max_rows=None):
return IMPL.archive_deleted_rows(max_rows=max_rows)
def pcidevice_online_data_migration(context, max_count):
return IMPL.pcidevice_online_data_migration(context, max_count)
####################

View File

@@ -6382,6 +6382,31 @@ def archive_deleted_rows(max_rows=None):
return table_to_rows_archived
@main_context_manager.writer
def pcidevice_online_data_migration(context, max_count):
from nova.objects import pci_device as pci_dev_obj
count_all = 0
count_hit = 0
if not pci_dev_obj.PciDevice.should_migrate_data():
LOG.error(_LE("Data migrations for PciDevice are not safe, likely "
"because not all services that access the DB directly "
"are updated to the latest version"))
else:
results = model_query(context, models.PciDevice).filter_by(
parent_addr=None).limit(max_count)
for db_dict in results:
count_all += 1
pci_dev = pci_dev_obj.PciDevice._from_db_object(
context, pci_dev_obj.PciDevice(), db_dict)
if pci_dev.obj_what_changed():
pci_dev.save()
count_hit += 1
return count_all, count_hit
####################

View File

@@ -9122,7 +9122,7 @@ class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
'numa_node': 1,
'dev_type': fields.PciDeviceType.SRIOV_VF,
'dev_id': 'pci_0000:0f:08.7',
'extra_info': None,
'extra_info': '{}',
'label': 'label_8086_1520',
'status': fields.PciDeviceStatus.AVAILABLE,
'instance_uuid': '00000000-0000-0000-0000-000000000010',
@@ -9137,7 +9137,7 @@ class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
'numa_node': 0,
'dev_type': fields.PciDeviceType.SRIOV_VF,
'dev_id': 'pci_0000:0f:08.7',
'extra_info': None,
'extra_info': '{}',
'label': 'label_8086_1520',
'status': fields.PciDeviceStatus.AVAILABLE,
'instance_uuid': '00000000-0000-0000-0000-000000000010',
@@ -9278,6 +9278,56 @@ class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
v1['compute_node_id'],
v1['address'])
def _create_fake_pci_devs_old_format(self):
v1, v2 = self._get_fake_pci_devs()
for v in (v1, v2):
v['parent_addr'] = None
v['extra_info'] = jsonutils.dumps(
{'phys_function': 'fake-phys-func'})
db.pci_device_update(self.admin_context, v['compute_node_id'],
v['address'], v)
@mock.patch.object(objects.PciDevice, 'should_migrate_data',
return_value=False)
def test_pcidevice_online_mig_not_ready(self, mock_should_migrate):
self._create_fake_pci_devs_old_format()
found, done = db.pcidevice_online_data_migration(self.admin_context,
None)
self.assertEqual(0, found)
self.assertEqual(0, done)
@mock.patch.object(objects.PciDevice, 'should_migrate_data',
return_value=True)
def test_pcidevice_online_mig_data_migrated_limit(self,
mock_should_migrate):
self._create_fake_pci_devs_old_format()
found, done = db.pcidevice_online_data_migration(self.admin_context, 1)
self.assertEqual(1, found)
self.assertEqual(1, done)
@mock.patch.object(objects.PciDevice, 'should_migrate_data',
return_value=True)
def test_pcidevice_online_mig(self, mock_should_migrate):
self._create_fake_pci_devs_old_format()
found, done = db.pcidevice_online_data_migration(self.admin_context,
50)
self.assertEqual(2, found)
self.assertEqual(2, done)
results = db.pci_device_get_all_by_node(self.admin_context,
self.compute_node['id'])
for result in results:
self.assertEqual('fake-phys-func', result['parent_addr'])
found, done = db.pcidevice_online_data_migration(self.admin_context,
50)
self.assertEqual(0, found)
self.assertEqual(0, done)
class RetryOnDeadlockTestCase(test.TestCase):
def test_without_deadlock(self):