[ironic] Factor out metadata and send to ironic
This change migrates the code currently written only to serve libvirt driver to be generally useful, adding driver-neutral data structures and a method to build them. The libvirt driver is reworked to use get_instance_driver_metadata instead of it's current code. The ironic driver is reworked, per the blueprint, to send along some of this additional metadata to the Ironic node.instance_info. blueprint ironic-guest-metadata Needed-By: https://review.opendev.org/c/openstack/ironic/+/924887 Change-Id: I2b23c8463f66c38e64625486157f245cd74cec61
This commit is contained in:
@@ -1263,6 +1263,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
instance_id=instance.uuid,
|
||||
fields=ironic_driver._NODE_FIELDS)])
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_add_volume_target_info')
|
||||
@@ -1271,11 +1273,15 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
'_add_instance_info_to_node')
|
||||
def _test_spawn(self, mock_aiitn, mock_wait_active,
|
||||
mock_avti, mock_looping, mock_save,
|
||||
config_drive_value=None):
|
||||
mock_metadata, config_drive_value=None):
|
||||
node_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
node = _get_cached_node(driver='fake', id=node_id)
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_id)
|
||||
fake_flavor = objects.Flavor(ephemeral_gb=0)
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_ephemeralgb=0)
|
||||
)
|
||||
instance.flavor = fake_flavor
|
||||
|
||||
self.mock_conn.get_node.return_value = node
|
||||
@@ -1295,9 +1301,10 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
self.mock_conn.validate_node.assert_called_once_with(
|
||||
node_id, required=None,
|
||||
)
|
||||
mock_aiitn.assert_called_once_with(node, instance,
|
||||
test.MatchType(objects.ImageMeta),
|
||||
fake_flavor, block_device_info=None)
|
||||
mock_aiitn.assert_called_once_with(
|
||||
node, instance, test.MatchType(objects.ImageMeta),
|
||||
fake_flavor, test.MatchType(driver.InstanceDriverMetadata),
|
||||
block_device_info=None)
|
||||
mock_avti.assert_called_once_with(self.ctx, instance, None)
|
||||
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
||||
node_id, 'active', config_drive=config_drive_value,
|
||||
@@ -1331,6 +1338,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
mock.ANY, extra_md={},
|
||||
files=[])
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, 'destroy')
|
||||
@@ -1341,13 +1350,18 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
def test_spawn_destroyed_after_failure(self, mock_aiitn,
|
||||
mock_wait_active, mock_avti,
|
||||
mock_destroy,
|
||||
mock_looping, mock_required_by):
|
||||
mock_looping, mock_required_by,
|
||||
mock_metadata):
|
||||
mock_required_by.return_value = False
|
||||
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
node = _get_cached_node(driver='fake', id=node_uuid)
|
||||
fake_flavor = objects.Flavor(ephemeral_gb=0)
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
|
||||
instance.flavor = fake_flavor
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_ephemeralgb=0
|
||||
))
|
||||
|
||||
self.mock_conn.get_node.return_value = node
|
||||
self.mock_conn.validate_node.return_value = \
|
||||
@@ -1368,6 +1382,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
||||
image_meta = ironic_utils.get_test_image_meta()
|
||||
flavor = ironic_utils.get_test_flavor()
|
||||
metadata = ironic_utils.get_test_instance_driver_metadata()
|
||||
instance.flavor = flavor
|
||||
expected_patch = [{'path': '/instance_info/image_source', 'op': 'add',
|
||||
'value': image_meta.id},
|
||||
@@ -1384,10 +1399,25 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
{'path': '/instance_info/memory_mb', 'op': 'add',
|
||||
'value': str(instance.flavor.memory_mb)},
|
||||
{'path': '/instance_info/local_gb', 'op': 'add',
|
||||
'value': str(node.properties.get('local_gb', 0))}]
|
||||
'value': str(node.properties.get('local_gb', 0))},
|
||||
{'path': '/instance_info/project_id', 'op': 'add',
|
||||
'value': 'ppppppp-pppp-pppp-pppp-pppppppppppp'},
|
||||
{'path': '/instance_info/project_name', 'op': 'add',
|
||||
'value': 'testproject'},
|
||||
{'path': '/instance_info/user_id', 'op': 'add',
|
||||
'value': 'uuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu'},
|
||||
{'op': 'add', 'path': '/instance_info/user_name',
|
||||
'value': 'testuser'},
|
||||
{'path': '/instance_info/flavor_name',
|
||||
'op': 'add', 'value': 'fake.flavor'},
|
||||
{'path': '/instance_info/fixed_ips',
|
||||
'op': 'add', 'value': '[]'},
|
||||
{'path': '/instance_info/floating_ips',
|
||||
'op': 'add', 'value': '[]'},
|
||||
]
|
||||
|
||||
self.driver._add_instance_info_to_node(node, instance,
|
||||
image_meta, flavor)
|
||||
image_meta, flavor, metadata)
|
||||
|
||||
# TODO(dustinc): Add check for call to patcher.create
|
||||
self.mock_conn.patch_node.assert_called_once_with(node, expected_patch)
|
||||
@@ -1533,16 +1563,22 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
]
|
||||
)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_add_volume_target_info')
|
||||
def test_spawn_node_driver_validation_fail(self, mock_avti,
|
||||
mock_required_by):
|
||||
mock_required_by,
|
||||
mock_metadata):
|
||||
mock_required_by.return_value = False
|
||||
node_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
node = _get_cached_node(driver='fake', id=node_id)
|
||||
flavor = ironic_utils.get_test_flavor()
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_id)
|
||||
instance.flavor = flavor
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata()
|
||||
)
|
||||
|
||||
self.mock_conn.validate_node.return_value = \
|
||||
ironic_utils.get_test_validation(
|
||||
@@ -1562,20 +1598,23 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
node_id, required=None,
|
||||
)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_add_volume_target_info')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_generate_configdrive')
|
||||
def test_spawn_node_configdrive_fail(self,
|
||||
mock_configdrive,
|
||||
mock_avti, mock_save,
|
||||
mock_required_by):
|
||||
def test_spawn_node_configdrive_fail(self, mock_configdrive, mock_avti,
|
||||
mock_save, mock_required_by,
|
||||
mock_metadata):
|
||||
mock_required_by.return_value = True
|
||||
node_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
node = _get_cached_node(driver='fake', id=node_id)
|
||||
flavor = ironic_utils.get_test_flavor()
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_id)
|
||||
instance.flavor = flavor
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata())
|
||||
self.mock_conn.get_node.return_value = node
|
||||
self.mock_conn.validate_node.return_value = \
|
||||
ironic_utils.get_test_validation()
|
||||
@@ -1594,12 +1633,14 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
)
|
||||
mock_cleanup_deploy.assert_called_with(node, instance, None)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_add_volume_target_info')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_cleanup_deploy')
|
||||
def test_spawn_node_trigger_deploy_fail(self, mock_cleanup_deploy,
|
||||
mock_avti,
|
||||
mock_required_by):
|
||||
mock_required_by, mock_metadata):
|
||||
mock_required_by.return_value = False
|
||||
node_id = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
node = _get_cached_node(driver='fake', id=node_id)
|
||||
@@ -1607,6 +1648,9 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_id)
|
||||
instance.flavor = flavor
|
||||
image_meta = ironic_utils.get_test_image_meta()
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata()
|
||||
)
|
||||
|
||||
self.mock_conn.get_node.return_value = node
|
||||
self.mock_conn.validate_node.return_value = \
|
||||
@@ -1627,6 +1671,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
)
|
||||
mock_cleanup_deploy.assert_called_once_with(node, instance, None)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
@@ -1636,12 +1682,18 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
mock_wait, mock_avti,
|
||||
mock_save,
|
||||
mock_looping,
|
||||
mock_required_by):
|
||||
mock_required_by,
|
||||
mock_metadata):
|
||||
mock_required_by.return_value = False
|
||||
node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'
|
||||
flavor = ironic_utils.get_test_flavor(ephemeral_gb=1)
|
||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid)
|
||||
instance.flavor = flavor
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_ephemeralgb=1)
|
||||
)
|
||||
|
||||
image_meta = ironic_utils.get_test_image_meta()
|
||||
|
||||
self.driver.spawn(self.ctx, instance, image_meta, [], None, {})
|
||||
@@ -2148,13 +2200,16 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
'fake_vif')
|
||||
mock_uv.assert_called_once_with('fake_instance', ['fake_vif'])
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_wait_for_active')
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_add_instance_info_to_node')
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
def _test_rebuild(self, mock_save, mock_add_instance_info,
|
||||
mock_looping, mock_wait_active, preserve=False):
|
||||
mock_looping, mock_wait_active, mock_metadata,
|
||||
preserve=False):
|
||||
node_uuid = uuidutils.generate_uuid()
|
||||
node = _get_cached_node(id=node_uuid, instance_id=self.instance_id)
|
||||
self.mock_conn.get_node.return_value = node
|
||||
@@ -2165,6 +2220,13 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
instance = fake_instance.fake_instance_obj(
|
||||
self.ctx, uuid=self.instance_uuid, node=node_uuid, flavor=flavor)
|
||||
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_id=5,
|
||||
flavor_name='baremetal',
|
||||
instance_uuid=self.instance_uuid,
|
||||
))
|
||||
|
||||
fake_looping_call = FakeLoopingCall()
|
||||
mock_looping.return_value = fake_looping_call
|
||||
|
||||
@@ -2179,6 +2241,7 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
mock_add_instance_info.assert_called_once_with(
|
||||
node, instance,
|
||||
test.MatchType(objects.ImageMeta),
|
||||
test.MatchType(driver.InstanceDriverMetadata),
|
||||
flavor, preserve)
|
||||
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
||||
node_uuid, ironic_states.REBUILD, config_drive=mock.ANY,
|
||||
@@ -2214,6 +2277,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
mock_configdrive.assert_called_once_with(
|
||||
self.ctx, mock.ANY, mock.ANY, mock.ANY, extra_md={}, files=None)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_generate_configdrive')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
@@ -2222,13 +2287,18 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
def test_rebuild_with_configdrive_failure(self, mock_save,
|
||||
mock_add_instance_info,
|
||||
mock_required_by,
|
||||
mock_configdrive):
|
||||
mock_configdrive,
|
||||
mock_metadata):
|
||||
node_uuid = uuidutils.generate_uuid()
|
||||
node = _get_cached_node(
|
||||
id=node_uuid, instance_id=self.instance_uuid)
|
||||
self.mock_conn.get_node.return_value = node
|
||||
mock_required_by.return_value = True
|
||||
mock_configdrive.side_effect = exception.NovaException()
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_id=5, flavor_name='baremetal')
|
||||
)
|
||||
|
||||
image_meta = ironic_utils.get_test_image_meta()
|
||||
flavor = objects.Flavor(flavor_id=5, name='baremetal')
|
||||
@@ -2243,6 +2313,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
bdms=None, detach_block_devices=None,
|
||||
attach_block_devices=None)
|
||||
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'get_instance_driver_metadata')
|
||||
@mock.patch.object(ironic_driver.IronicDriver, '_generate_configdrive')
|
||||
@mock.patch.object(configdrive, 'required_by')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
@@ -2250,7 +2322,8 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
@mock.patch.object(objects.Instance, 'save')
|
||||
def test_rebuild_failures(self, mock_save,
|
||||
mock_add_instance_info,
|
||||
mock_required_by, mock_configdrive):
|
||||
mock_required_by, mock_configdrive,
|
||||
mock_metadata):
|
||||
node_uuid = uuidutils.generate_uuid()
|
||||
node = _get_cached_node(
|
||||
id=node_uuid, instance_id=self.instance_uuid)
|
||||
@@ -2259,6 +2332,12 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
|
||||
image_meta = ironic_utils.get_test_image_meta()
|
||||
flavor = objects.Flavor(flavor_id=5, name='baremetal')
|
||||
mock_metadata.return_value = (
|
||||
ironic_utils.get_test_instance_driver_metadata(
|
||||
flavor_id=5,
|
||||
flavor_name='baremetal',
|
||||
instance_uuid=self.instance_uuid,
|
||||
))
|
||||
|
||||
instance = fake_instance.fake_instance_obj(
|
||||
self.ctx, uuid=self.instance_uuid, node=node_uuid, flavor=flavor)
|
||||
|
||||
@@ -37,6 +37,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
self.instance = fake_instance.fake_instance_obj(self.ctx)
|
||||
self.instance.flavor = self.flavor
|
||||
self.node = ironic_utils.get_test_node(driver='fake')
|
||||
self.metadata = ironic_utils.get_test_instance_driver_metadata()
|
||||
# Generic expected patches
|
||||
self._expected_deploy_patch = [
|
||||
{'path': '/instance_info/image_source',
|
||||
@@ -60,9 +61,24 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
{'path': '/instance_info/local_gb',
|
||||
'value': str(self.node.properties.get('local_gb', 0)),
|
||||
'op': 'add'},
|
||||
{'path': '/instance_info/nova_host_id',
|
||||
'value': u'fake-host',
|
||||
'op': 'add'},
|
||||
{'op': 'add', 'path': '/instance_info/fixed_ips',
|
||||
'value': '[]'},
|
||||
{'op': 'add', 'path': '/instance_info/floating_ips',
|
||||
'value': '[]'},
|
||||
{'op': 'add', 'path': '/instance_info/flavor_name',
|
||||
'value': str(self.flavor.name)},
|
||||
{'op': 'add', 'path': '/instance_info/nova_host_id',
|
||||
'value': 'fake-host'},
|
||||
{'op': 'add',
|
||||
'path': '/instance_info/project_id',
|
||||
'value': 'ppppppp-pppp-pppp-pppp-pppppppppppp'},
|
||||
{'op': 'add', 'path': '/instance_info/project_name',
|
||||
'value': 'testproject'},
|
||||
{'op': 'add', 'path': '/instance_info/user_name',
|
||||
'value': 'testuser'},
|
||||
{'op': 'add',
|
||||
'path': '/instance_info/user_id',
|
||||
'value': 'uuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu'},
|
||||
]
|
||||
|
||||
def assertPatchEqual(self, expected, observed):
|
||||
@@ -79,7 +95,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
def test_generic_get_deploy_patch(self):
|
||||
node = ironic_utils.get_test_node(driver='fake')
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(self._expected_deploy_patch, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_capabilities(self):
|
||||
@@ -90,7 +106,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_capabilities_op(self):
|
||||
@@ -101,7 +117,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_capabilities_nested_key(self):
|
||||
@@ -112,7 +128,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_traits(self):
|
||||
@@ -123,7 +139,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_traits_granular(self):
|
||||
@@ -134,7 +150,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_traits_ignores_not_required(self):
|
||||
@@ -142,7 +158,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
self.flavor['extra_specs']['trait:CUSTOM_FOO'] = 'invalid'
|
||||
expected = self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_image_traits_required(self):
|
||||
@@ -154,7 +170,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_image_flavor_traits_required(self):
|
||||
@@ -167,7 +183,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_image_flavor_traits_none(self):
|
||||
@@ -175,7 +191,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
self.image_meta.properties = objects.ImageMetaProps()
|
||||
expected = self._expected_deploy_patch
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor)
|
||||
self.instance, self.image_meta, self.flavor, self.metadata)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
def test_generic_get_deploy_patch_boot_from_volume_image_traits_required(
|
||||
@@ -192,7 +208,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
'op': 'add'}]
|
||||
expected += expected_deploy_patch_volume
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor,
|
||||
self.instance, self.image_meta, self.flavor, self.metadata,
|
||||
boot_from_volume=True)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
@@ -204,7 +220,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
flavor=objects.Flavor(root_gb=1, vcpus=1,
|
||||
memory_mb=1, ephemeral_gb=10))
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
instance, self.image_meta, self.flavor)
|
||||
instance, self.image_meta, self.flavor, self.metadata)
|
||||
expected = [{'path': '/instance_info/ephemeral_gb',
|
||||
'value': str(instance.flavor.ephemeral_gb),
|
||||
'op': 'add'},
|
||||
@@ -218,7 +234,7 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
node = ironic_utils.get_test_node(driver='fake')
|
||||
for preserve in [True, False]:
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor,
|
||||
self.instance, self.image_meta, self.flavor, self.metadata,
|
||||
preserve_ephemeral=preserve)
|
||||
expected = [{'path': '/instance_info/preserve_ephemeral',
|
||||
'value': str(preserve), 'op': 'add', }]
|
||||
@@ -230,6 +246,6 @@ class IronicDriverFieldsTestCase(test.NoDBTestCase):
|
||||
expected = [patch for patch in self._expected_deploy_patch
|
||||
if patch['path'] != '/instance_info/image_source']
|
||||
patch = patcher.create(node).get_deploy_patch(
|
||||
self.instance, self.image_meta, self.flavor,
|
||||
self.instance, self.image_meta, self.flavor, self.metadata,
|
||||
boot_from_volume=True)
|
||||
self.assertPatchEqual(expected, patch)
|
||||
|
||||
@@ -19,9 +19,27 @@ from openstack.baremetal.v1 import port_group as _port_group
|
||||
from openstack.baremetal.v1 import volume_connector as _volume_connector
|
||||
from openstack.baremetal.v1 import volume_target as _volume_target
|
||||
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.virt import driver
|
||||
from nova.virt.ironic import ironic_states
|
||||
|
||||
# NOTE(JayF): These exist to make it trivial to unify test data
|
||||
# between both the driver_metadata generators and the generated
|
||||
# objects.
|
||||
TEST_IMAGE_UUID = "cccccccc-cccc-cccc-cccc-cccccccccccc"
|
||||
TEST_IMAGE_NAME = "test-image"
|
||||
TEST_FLAVOR_ID = "1"
|
||||
TEST_FLAVOR_NAME = "fake.flavor"
|
||||
TEST_FLAVOR_EXTRA_SPECS = {
|
||||
'baremetal:deploy_kernel_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
'baremetal:deploy_ramdisk_id': 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'}
|
||||
TEST_FLAVOR_SWAP = 1
|
||||
TEST_FLAVOR_ROOTGB = 1
|
||||
TEST_FLAVOR_MEMORYMB = 1
|
||||
TEST_FLAVOR_VCPUS = 1
|
||||
TEST_FLAVOR_EPHEMERALGB = 0
|
||||
|
||||
|
||||
def get_test_validation(**kw):
|
||||
result = {
|
||||
@@ -174,18 +192,15 @@ def get_test_volume_target(**kw):
|
||||
|
||||
|
||||
def get_test_flavor(**kw):
|
||||
default_extra_specs = {
|
||||
'baremetal:deploy_kernel_id': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
'baremetal:deploy_ramdisk_id': 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
|
||||
}
|
||||
flavor = {
|
||||
'name': kw.get('name', 'fake.flavor'),
|
||||
'extra_specs': kw.get('extra_specs', default_extra_specs),
|
||||
'swap': kw.get('swap', 0),
|
||||
'root_gb': 1,
|
||||
'memory_mb': 1,
|
||||
'vcpus': 1,
|
||||
'ephemeral_gb': kw.get('ephemeral_gb', 0),
|
||||
'id': kw.get('id', TEST_FLAVOR_ID),
|
||||
'name': kw.get('name', TEST_FLAVOR_NAME),
|
||||
'extra_specs': kw.get('extra_specs', TEST_FLAVOR_EXTRA_SPECS),
|
||||
'swap': kw.get('swap', TEST_FLAVOR_SWAP),
|
||||
'root_gb': TEST_FLAVOR_ROOTGB,
|
||||
'memory_mb': TEST_FLAVOR_MEMORYMB,
|
||||
'vcpus': TEST_FLAVOR_VCPUS,
|
||||
'ephemeral_gb': kw.get('ephemeral_gb', TEST_FLAVOR_EPHEMERALGB),
|
||||
}
|
||||
|
||||
return objects.Flavor(**flavor)
|
||||
@@ -193,5 +208,41 @@ def get_test_flavor(**kw):
|
||||
|
||||
def get_test_image_meta(**kw):
|
||||
return objects.ImageMeta.from_dict(
|
||||
{'id': kw.get('id', 'cccccccc-cccc-cccc-cccc-cccccccccccc')},
|
||||
{'id': kw.get('id', TEST_IMAGE_UUID)},
|
||||
)
|
||||
|
||||
|
||||
def get_test_instance_driver_metadata(**kw):
|
||||
default_instance_meta = driver.NovaInstanceMeta(
|
||||
name=kw.get('instance_name', 'testinstance'),
|
||||
uuid=kw.get('instance_uuid', 'iiiiiii-iiii-iiii-iiii-iiiiiiiiiiii'))
|
||||
default_owner_meta = driver.OwnerMeta(
|
||||
userid='uuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu',
|
||||
username='testuser',
|
||||
projectid='ppppppp-pppp-pppp-pppp-pppppppppppp',
|
||||
projectname='testproject')
|
||||
default_image_meta = driver.ImageMeta(id=TEST_IMAGE_UUID,
|
||||
name=TEST_IMAGE_NAME,
|
||||
properties={})
|
||||
default_flavor_meta = driver.FlavorMeta(
|
||||
name=kw.get('flavor_name', TEST_FLAVOR_NAME),
|
||||
memory_mb=kw.get('flavor_memorymb',
|
||||
TEST_FLAVOR_MEMORYMB),
|
||||
vcpus=kw.get('flavor_vcpus', TEST_FLAVOR_VCPUS),
|
||||
root_gb=kw.get('flavor_rootgb',
|
||||
TEST_FLAVOR_ROOTGB),
|
||||
ephemeral_gb=kw.get('flavor_ephemeralgb',
|
||||
TEST_FLAVOR_EPHEMERALGB),
|
||||
extra_specs=kw.get('flavor_extra_specs',
|
||||
TEST_FLAVOR_EXTRA_SPECS),
|
||||
swap=kw.get('flavor_swap', TEST_FLAVOR_SWAP))
|
||||
|
||||
return driver.InstanceDriverMetadata(
|
||||
root_type=kw.get('root_type', 'roottype'),
|
||||
root_id=kw.get('root_id', 'rootid'),
|
||||
instance_meta=kw.get('instance_meta', default_instance_meta),
|
||||
owner=kw.get('owner_meta', default_owner_meta),
|
||||
image=kw.get('image_meta', default_image_meta),
|
||||
flavor=kw.get('flavor_meta', default_flavor_meta),
|
||||
network_info=kw.get('network_info', network_model.NetworkInfo())
|
||||
)
|
||||
|
||||
@@ -2591,17 +2591,19 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
|
||||
def test_get_guest_config_meta_with_no_port(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
meta = drvr._get_guest_config_meta(
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**self.test_instance),
|
||||
_fake_network_info(self, num_networks=0))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(len(meta.ports.ports), 0)
|
||||
|
||||
def test_get_guest_config_meta_with_multiple_ports(self):
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
|
||||
meta = drvr._get_guest_config_meta(
|
||||
idm = drvr.get_instance_driver_metadata(
|
||||
objects.Instance(**self.test_instance),
|
||||
_fake_network_info(self, num_networks=2))
|
||||
meta = drvr._get_guest_config_meta(idm)
|
||||
|
||||
self.assertEqual(len(meta.ports.ports), 2)
|
||||
|
||||
@@ -2649,6 +2651,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
user_name="pie",
|
||||
)
|
||||
flavor = objects.Flavor(
|
||||
id=1,
|
||||
name='m1.small',
|
||||
memory_mb=6,
|
||||
vcpus=28,
|
||||
@@ -2775,6 +2778,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
ephemeral_gb=8128,
|
||||
swap=33550336,
|
||||
extra_specs={},
|
||||
id=42
|
||||
)
|
||||
instance_ref = objects.Instance(**test_instance)
|
||||
instance_ref.flavor = flavor
|
||||
@@ -2927,13 +2931,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
user_id=456,
|
||||
user_name="pie")
|
||||
|
||||
flavor = objects.Flavor(name='m1.small',
|
||||
memory_mb=6,
|
||||
vcpus=28,
|
||||
root_gb=496,
|
||||
ephemeral_gb=8128,
|
||||
swap=33550336,
|
||||
extra_specs={})
|
||||
flavor = objects.Flavor(
|
||||
id=42, name='m1.small', memory_mb=6,
|
||||
vcpus=28, root_gb=496, ephemeral_gb=8128,
|
||||
swap=33550336, extra_specs={})
|
||||
instance_ref = objects.Instance(**test_instance)
|
||||
instance_ref.flavor = flavor
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
@@ -3106,7 +3107,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=1, vcpus=2, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3140,7 +3141,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
def test_get_guest_config_numa_host_instance_no_fit(self):
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=4096, vcpus=4, root_gb=496,
|
||||
flavor = objects.Flavor(
|
||||
id=42, memory_mb=4096, vcpus=4, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
instance_ref.flavor = flavor
|
||||
@@ -3475,13 +3477,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
extra_specs = {
|
||||
"hw:mem_encryption": True,
|
||||
}
|
||||
flavor = objects.Flavor(name='m1.small',
|
||||
memory_mb=6,
|
||||
vcpus=28,
|
||||
root_gb=496,
|
||||
ephemeral_gb=8128,
|
||||
swap=33550336,
|
||||
extra_specs=extra_specs)
|
||||
flavor = objects.Flavor(
|
||||
id=42, name='m1.small', memory_mb=6,
|
||||
vcpus=28, root_gb=496, ephemeral_gb=8128,
|
||||
swap=33550336, extra_specs=extra_specs)
|
||||
|
||||
instance_ref = objects.Instance(**self.test_instance)
|
||||
instance_ref.flavor = flavor
|
||||
@@ -3573,7 +3572,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=1, vcpus=2, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3626,7 +3625,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=4096, vcpus=4, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3744,7 +3743,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=1024, vcpus=2, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3787,7 +3786,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=2, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3840,7 +3839,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=4, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3917,7 +3916,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=4, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -3995,7 +3994,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=2, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -4084,7 +4083,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=8, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -4198,7 +4197,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=8, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -4301,7 +4300,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_policy": "mixed",
|
||||
"hw:cpu_realtime_mask": "^2-3"
|
||||
})
|
||||
}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -4410,7 +4409,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
image_meta = objects.ImageMeta.from_dict(self.test_image_meta)
|
||||
flavor = objects.Flavor(memory_mb=2048, vcpus=4, root_gb=496,
|
||||
ephemeral_gb=8128, swap=33550336, name='fake',
|
||||
extra_specs={})
|
||||
extra_specs={}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -4494,7 +4493,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
||||
"hw:cpu_realtime": "yes",
|
||||
"hw:cpu_policy": "dedicated",
|
||||
"hw:cpu_realtime_mask": "^0-1"
|
||||
})
|
||||
}, id=42)
|
||||
instance_ref.flavor = flavor
|
||||
|
||||
caps = vconfig.LibvirtConfigCaps()
|
||||
@@ -22933,6 +22932,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
||||
inst = {}
|
||||
inst['id'] = 1
|
||||
inst['uuid'] = uuids.fake_instance_id
|
||||
inst['display_name'] = 'fake-instance'
|
||||
inst['os_type'] = 'linux'
|
||||
inst['image_ref'] = uuids.fake_image_ref
|
||||
inst['reservation_id'] = 'r-fakeres'
|
||||
@@ -25002,13 +25002,16 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
||||
instance, 'get_network_info', return_value=network_info),
|
||||
mock.patch.object(
|
||||
self.drvr, '_detach_with_retry'),
|
||||
mock.patch.object(
|
||||
self.drvr, 'get_instance_driver_metadata'
|
||||
),
|
||||
mock.patch.object(
|
||||
self.drvr, '_get_guest_config_meta', return_value=config_meta),
|
||||
mock.patch.object(guest, 'set_metadata')
|
||||
) as (
|
||||
mock_get_guest, mock_get_config, mock_get_network_info,
|
||||
mock_detach_with_retry, mock_get_guest_config_meta,
|
||||
mock_set_metadata
|
||||
mock_detach_with_retry, mock_get_instance_driver_metadata,
|
||||
mock_get_guest_config_meta, mock_set_metadata
|
||||
):
|
||||
self.drvr.detach_interface(self.context, instance, vif)
|
||||
mock_get_guest.assert_called_once_with(instance)
|
||||
@@ -25018,8 +25021,9 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
||||
mock_detach_with_retry.assert_called_once_with(
|
||||
guest, instance.uuid, mock.ANY, device_name=None)
|
||||
mock_get_network_info.assert_called_once_with()
|
||||
mock_get_guest_config_meta.assert_called_once_with(
|
||||
mock_get_instance_driver_metadata.assert_called_once_with(
|
||||
instance, network_info[1:])
|
||||
mock_get_guest_config_meta.assert_called_once()
|
||||
mock_set_metadata.assert_called_once_with(config_meta)
|
||||
|
||||
def test__detach_with_retry_persistent_success(self):
|
||||
|
||||
@@ -20,26 +20,78 @@ Driver base-classes:
|
||||
types that support that contract
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import itertools
|
||||
import sys
|
||||
import time
|
||||
import typing as ty
|
||||
|
||||
import os_resource_classes as orc
|
||||
import os_traits
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
|
||||
import nova.conf
|
||||
import nova.virt.node
|
||||
|
||||
from nova import context as nova_context
|
||||
from nova.i18n import _
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova import version
|
||||
from nova.virt import event as virtevent
|
||||
import nova.virt.node
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class FlavorMeta:
|
||||
name: str
|
||||
memory_mb: int
|
||||
vcpus: int
|
||||
root_gb: int
|
||||
ephemeral_gb: int
|
||||
extra_specs: dict
|
||||
swap: int
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ImageMeta:
|
||||
id: str
|
||||
name: str
|
||||
properties: dict
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class NovaInstanceMeta:
|
||||
name: str
|
||||
uuid: str
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class OwnerMeta:
|
||||
userid: str
|
||||
username: str
|
||||
projectid: str
|
||||
projectname: str
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class InstanceDriverMetadata:
|
||||
root_type: str
|
||||
root_id: str
|
||||
instance_meta: NovaInstanceMeta
|
||||
owner: OwnerMeta
|
||||
image: ImageMeta
|
||||
flavor: FlavorMeta
|
||||
network_info: network_model.NetworkInfo
|
||||
nova_package: str = dataclasses.field(
|
||||
default_factory=version.version_string_with_package)
|
||||
creation_time: float = dataclasses.field(default_factory=time.time)
|
||||
|
||||
|
||||
def get_block_device_info(instance, block_device_mapping):
|
||||
"""Converts block device mappings for an instance to driver format.
|
||||
|
||||
@@ -294,6 +346,55 @@ class ComputeDriver(object):
|
||||
# TODO(Vek): Need to pass context in for access to auth_token
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def get_instance_driver_metadata(
|
||||
cls, instance: 'nova.objects.instance.Instance',
|
||||
network_info: network_model.NetworkInfo
|
||||
) -> InstanceDriverMetadata:
|
||||
"""Get driver metadata from instance and network info
|
||||
|
||||
:param instance: nova.objects.instance.Instance
|
||||
:param network_info: instance network information
|
||||
:returns: InstanceDriverMetadata
|
||||
"""
|
||||
|
||||
instance_name = instance.display_name or instance.uuid
|
||||
system_meta = instance.system_metadata
|
||||
instance_meta = NovaInstanceMeta(
|
||||
str(instance_name), str(instance.uuid))
|
||||
owner = OwnerMeta(
|
||||
userid=instance.user_id,
|
||||
username=system_meta.get('owner_user_name', 'N/A'),
|
||||
projectid=instance.project_id,
|
||||
projectname=system_meta.get('owner_project_name', 'N/A')
|
||||
)
|
||||
flavor = FlavorMeta(
|
||||
name=instance.flavor.name,
|
||||
memory_mb=instance.flavor.memory_mb,
|
||||
vcpus=instance.flavor.vcpus,
|
||||
ephemeral_gb=instance.flavor.ephemeral_gb,
|
||||
root_gb=instance.flavor.root_gb,
|
||||
swap=instance.flavor.swap,
|
||||
extra_specs=instance.flavor.extra_specs,
|
||||
)
|
||||
image = ImageMeta(
|
||||
id=instance.image_ref,
|
||||
name=system_meta.get('image_name'),
|
||||
properties=instance.image_meta.properties
|
||||
)
|
||||
meta = InstanceDriverMetadata(
|
||||
instance_meta=instance_meta,
|
||||
owner=owner,
|
||||
flavor=flavor,
|
||||
image=image,
|
||||
root_type = 'image' if instance.image_ref else 'volume',
|
||||
root_id = instance.image_ref,
|
||||
creation_time = time.time(),
|
||||
network_info=network_info
|
||||
)
|
||||
LOG.debug('InstanceDriverMetadata: %s', meta)
|
||||
return meta
|
||||
|
||||
def get_num_instances(self):
|
||||
"""Return the total number of virtual machines.
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
self._cleanup_deploy(node, instance)
|
||||
|
||||
def _add_instance_info_to_node(self, node, instance, image_meta, flavor,
|
||||
preserve_ephemeral=None,
|
||||
metadata, preserve_ephemeral=None,
|
||||
block_device_info=None):
|
||||
|
||||
root_bdm = block_device.get_root_bdm(
|
||||
@@ -413,6 +413,7 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
patch = patcher.create(node).get_deploy_patch(instance,
|
||||
image_meta,
|
||||
flavor,
|
||||
metadata,
|
||||
preserve_ephemeral,
|
||||
boot_from_volume)
|
||||
|
||||
@@ -1157,7 +1158,7 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
:param network_info: Instance network information.
|
||||
:param block_device_info: Instance block device
|
||||
information.
|
||||
:param arqs: Accelerator requests for this instance.
|
||||
:param accel_info: Accelerator requests for this instance.
|
||||
:param power_on: True if the instance should be powered on, False
|
||||
otherwise
|
||||
"""
|
||||
@@ -1175,7 +1176,9 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
node = self._get_node(node_id)
|
||||
flavor = instance.flavor
|
||||
|
||||
metadata = self.get_instance_driver_metadata(instance, network_info)
|
||||
self._add_instance_info_to_node(node, instance, image_meta, flavor,
|
||||
metadata,
|
||||
block_device_info=block_device_info)
|
||||
|
||||
try:
|
||||
@@ -1739,7 +1742,8 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
node_id = instance.node
|
||||
node = self._get_node(node_id)
|
||||
|
||||
self._add_instance_info_to_node(node, instance, image_meta,
|
||||
metadata = self.get_instance_driver_metadata(instance, network_info)
|
||||
self._add_instance_info_to_node(node, instance, image_meta, metadata,
|
||||
instance.flavor, preserve_ephemeral)
|
||||
|
||||
# Config drive
|
||||
|
||||
@@ -40,13 +40,14 @@ class GenericDriverFields(object):
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
||||
def get_deploy_patch(self, instance, image_meta, flavor,
|
||||
def get_deploy_patch(self, instance, image_meta, flavor, metadata,
|
||||
preserve_ephemeral=None, boot_from_volume=False):
|
||||
"""Build a patch to add the required fields to deploy a node.
|
||||
|
||||
:param instance: the instance object.
|
||||
:param image_meta: the nova.objects.ImageMeta object instance
|
||||
:param flavor: the flavor object.
|
||||
:param metadata: nova.virt.driver.InstanceDriverMetadata dataclass
|
||||
:param preserve_ephemeral: preserve_ephemeral status (bool) to be
|
||||
specified during rebuild.
|
||||
:param boot_from_volume: True if node boots from volume. Then,
|
||||
@@ -73,6 +74,21 @@ class GenericDriverFields(object):
|
||||
patch.append({'path': '/instance_info/local_gb', 'op': 'add',
|
||||
'value': str(self.node.properties.get('local_gb', 0))})
|
||||
|
||||
patch.append({'path': '/instance_info/project_id', 'op': 'add',
|
||||
'value': str(metadata.owner.projectid)})
|
||||
patch.append({'path': '/instance_info/project_name', 'op': 'add',
|
||||
'value': str(metadata.owner.projectname)})
|
||||
patch.append({'path': '/instance_info/user_id', 'op': 'add',
|
||||
'value': str(metadata.owner.userid)})
|
||||
patch.append({'path': '/instance_info/user_name', 'op': 'add',
|
||||
'value': str(metadata.owner.username)})
|
||||
patch.append({'path': '/instance_info/flavor_name', 'op': 'add',
|
||||
'value': str(metadata.flavor.name)})
|
||||
patch.append({'path': '/instance_info/fixed_ips', 'op': 'add',
|
||||
'value': str(metadata.network_info.fixed_ips())})
|
||||
patch.append({'path': '/instance_info/floating_ips', 'op': 'add',
|
||||
'value': str(metadata.network_info.floating_ips())})
|
||||
|
||||
if instance.flavor.ephemeral_gb:
|
||||
patch.append({'path': '/instance_info/ephemeral_gb',
|
||||
'op': 'add',
|
||||
|
||||
@@ -3052,7 +3052,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
try:
|
||||
guest.set_metadata(
|
||||
self._get_guest_config_meta(
|
||||
instance, instance.get_network_info()))
|
||||
self.get_instance_driver_metadata(
|
||||
instance, instance.get_network_info())))
|
||||
except libvirt.libvirtError:
|
||||
LOG.warning('updating libvirt metadata failed.', instance=instance)
|
||||
|
||||
@@ -3091,7 +3092,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
network_info = list(filter(lambda info: info['id'] != vif['id'],
|
||||
instance.get_network_info()))
|
||||
guest.set_metadata(
|
||||
self._get_guest_config_meta(instance, network_info))
|
||||
self._get_guest_config_meta(
|
||||
self.get_instance_driver_metadata(
|
||||
instance, network_info)))
|
||||
except libvirt.libvirtError:
|
||||
LOG.warning('updating libvirt metadata failed.', instance=instance)
|
||||
|
||||
@@ -6073,39 +6076,35 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
|
||||
return dev
|
||||
|
||||
def _get_guest_config_meta(self, instance, network_info):
|
||||
def _get_guest_config_meta(self, dmeta: driver.InstanceDriverMetadata):
|
||||
"""Get metadata config for guest."""
|
||||
|
||||
meta = vconfig.LibvirtConfigGuestMetaNovaInstance()
|
||||
meta.package = version.version_string_with_package()
|
||||
meta.name = instance.display_name
|
||||
meta.creationTime = time.time()
|
||||
meta.package = dmeta.nova_package
|
||||
meta.name = dmeta.instance_meta.name
|
||||
meta.creationTime = dmeta.creation_time
|
||||
meta.roottype = dmeta.root_type
|
||||
meta.rootid = dmeta.root_id
|
||||
|
||||
if instance.image_ref not in ("", None):
|
||||
meta.roottype = "image"
|
||||
meta.rootid = instance.image_ref
|
||||
|
||||
system_meta = instance.system_metadata
|
||||
ometa = vconfig.LibvirtConfigGuestMetaNovaOwner()
|
||||
ometa.userid = instance.user_id
|
||||
ometa.username = system_meta.get('owner_user_name', 'N/A')
|
||||
ometa.projectid = instance.project_id
|
||||
ometa.projectname = system_meta.get('owner_project_name', 'N/A')
|
||||
ometa.userid = dmeta.owner.userid
|
||||
ometa.username = dmeta.owner.username
|
||||
ometa.projectid = dmeta.owner.projectid
|
||||
ometa.projectname = dmeta.owner.projectname
|
||||
meta.owner = ometa
|
||||
|
||||
fmeta = vconfig.LibvirtConfigGuestMetaNovaFlavor()
|
||||
flavor = instance.flavor
|
||||
fmeta.name = flavor.name
|
||||
fmeta.memory = flavor.memory_mb
|
||||
fmeta.vcpus = flavor.vcpus
|
||||
fmeta.ephemeral = flavor.ephemeral_gb
|
||||
fmeta.disk = flavor.root_gb
|
||||
fmeta.swap = flavor.swap
|
||||
fmeta.name = dmeta.flavor.name
|
||||
fmeta.memory = dmeta.flavor.memory_mb
|
||||
fmeta.vcpus = dmeta.flavor.vcpus
|
||||
fmeta.ephemeral = dmeta.flavor.ephemeral_gb
|
||||
fmeta.disk = dmeta.flavor.root_gb
|
||||
fmeta.swap = dmeta.flavor.swap
|
||||
|
||||
meta.flavor = fmeta
|
||||
|
||||
ports = []
|
||||
for vif in network_info:
|
||||
for vif in dmeta.network_info:
|
||||
ips = []
|
||||
for subnet in vif.get('network', {}).get('subnets', []):
|
||||
for ip in subnet.get('ips', []):
|
||||
@@ -7353,8 +7352,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
guest_numa_config.numatune,
|
||||
flavor, image_meta)
|
||||
|
||||
guest.metadata.append(self._get_guest_config_meta(
|
||||
instance, network_info))
|
||||
guest.metadata.append(
|
||||
self._get_guest_config_meta(
|
||||
self.get_instance_driver_metadata(
|
||||
instance, network_info)))
|
||||
guest.idmaps = self._get_guest_idmaps()
|
||||
|
||||
for event in self._supported_perf_events:
|
||||
|
||||
Reference in New Issue
Block a user