Adds validation for hw machine type in host caps

Added function '_check_machine_type' which accept host
capabilities (caps) and machine type as param and look
for machine type in host caps object, if machine type
is not found raises exception InvalidMachineType

Closes-Bug: #1933097
Change-Id: I59d22c0342d6b0f3c0398ce62ec177dae39b5677
This commit is contained in:
Amit Uniyal
2022-06-21 20:23:47 +00:00
parent 84a84f7f2f
commit 7b9312ef8e
6 changed files with 140 additions and 24 deletions

View File

@@ -103,7 +103,7 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
self.computes['compute1'].stop()
self._unset_machine_type(server_without['id'])
self.flags(hw_machine_type='x86_64=pc-q35-1.2.3', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-q35-2.4', group='libvirt')
# Restart the compute
self.computes['compute1'].start()
@@ -115,9 +115,9 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
# is able to pass. This just keeps the tests clean.
self._reboot_server(server_without, hard=True)
# Assert server_without now has a machine type of pc-q35-1.2.3 picked
# Assert server_without now has a machine type of pc-q35-2.4 picked
# up from [libvirt]hw_machine_type during init_host
self._assert_machine_type(server_without['id'], 'pc-q35-1.2.3')
self._assert_machine_type(server_without['id'], 'pc-q35-2.4')
def test_machine_type_after_config_change(self):
"""Assert new instances pick up a new default machine type after the
@@ -129,11 +129,11 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
self._assert_machine_type(server_with['id'], 'q35')
self._assert_machine_type(server_without['id'], 'pc')
self.flags(hw_machine_type='x86_64=pc-q35-1.2.3', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-q35-2.4', group='libvirt')
server_with_new, server_without_new = self._create_servers()
self._assert_machine_type(server_with_new['id'], 'q35')
self._assert_machine_type(server_without_new['id'], 'pc-q35-1.2.3')
self._assert_machine_type(server_without_new['id'], 'pc-q35-2.4')
def test_machine_type_after_server_rebuild(self):
"""Assert that the machine type of an instance changes with a full
@@ -202,26 +202,26 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
)
def test_machine_type_update_stopped(self):
self.flags(hw_machine_type='x86_64=pc-1.2.3', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-1.2', group='libvirt')
server = self._create_server(networks='none')
self._assert_machine_type(server['id'], 'pc-1.2.3')
self._assert_machine_type(server['id'], 'pc-1.2')
self._stop_server(server)
machine_type_utils.update_machine_type(
self.context,
server['id'],
'pc-1.2.4'
'pc-1.2'
)
self._start_server(server)
self._assert_machine_type(server['id'], 'pc-1.2.4')
self._assert_machine_type(server['id'], 'pc-1.2')
def test_machine_type_update_blocked_active(self):
self.flags(hw_machine_type='x86_64=pc-1.2.3', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-1.2', group='libvirt')
server = self._create_server(networks='none')
self._assert_machine_type(server['id'], 'pc-1.2.3')
self._assert_machine_type(server['id'], 'pc-1.2')
self.assertRaises(
exception.InstanceInvalidState,
@@ -247,10 +247,10 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
)
def test_machine_type_update_blocked_between_versioned_and_alias(self):
self.flags(hw_machine_type='x86_64=pc-1.2.3', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-1.2', group='libvirt')
server = self._create_server(networks='none')
self._assert_machine_type(server['id'], 'pc-1.2.3')
self._assert_machine_type(server['id'], 'pc-1.2')
self._stop_server(server)
self.assertRaises(
@@ -372,7 +372,7 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
)
# Change the actual config on the compute
self.flags(hw_machine_type='x86_64=pc-q35-1.2', group='libvirt')
self.flags(hw_machine_type='x86_64=pc-q35-2.4', group='libvirt')
# Assert the existing instances remain the same after being rebooted or
# unshelved, rebuilding their domain configs
@@ -389,4 +389,4 @@ class LibvirtMachineTypeTest(base.ServersTestBase):
# Assert that new instances are spawned with the expected machine types
server_with_new, server_without_new = self._create_servers()
self._assert_machine_type(server_with_new['id'], 'q35')
self._assert_machine_type(server_without_new['id'], 'pc-q35-1.2')
self._assert_machine_type(server_without_new['id'], 'pc-q35-2.4')

View File

@@ -2677,6 +2677,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(33550336,
cfg.metadata[0].flavor.swap)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_q35(self):
self.flags(virt_type="kvm",
group='libvirt')
@@ -2711,6 +2712,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(TEST_AMOUNT_OF_PCIE_SLOTS, num_ports)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_pcie_i440fx(self):
self.flags(virt_type="kvm",
group='libvirt')
@@ -2746,6 +2748,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
# i440fx is not pcie machine so there should be no pcie ports
self.assertEqual(0, num_ports)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch('nova.virt.libvirt.utils.get_default_machine_type',
new=mock.Mock(return_value='config-machine_type'))
def test_get_guest_config_records_machine_type_in_instance(self):
@@ -2957,6 +2960,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
'fake-instance-numa-topology',
'fake-flavor', 'fake-image-meta').obj_to_primitive())
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_fits(self, is_able):
@@ -2994,6 +2998,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch('nova.privsep.utils.supports_direct_io',
new=mock.Mock(return_value=True))
@mock.patch.object(
@@ -3389,6 +3394,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self._test_get_guest_memory_backing_config,
host_topology, inst_topology, numa_tune)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_pci_no_numa_info(
@@ -3439,11 +3445,13 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch('nova.privsep.utils.supports_direct_io',
new=mock.Mock(return_value=True))
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_2pci_no_fit(self, is_able):
def test_get_guest_config_numa_host_instance_2pci_no_fit(
self, is_able):
self.flags(cpu_shared_set='3', cpu_dedicated_set=None,
group='compute')
instance_ref = objects.Instance(**self.test_instance)
@@ -3551,6 +3559,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
exception.NUMATopologyUnsupported,
None)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_fit_w_cpu_pinset(
@@ -3592,9 +3601,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_non_numa_host_instance_topo(self, is_able):
def test_get_guest_config_non_numa_host_instance_topo(
self, is_able):
instance_topology = objects.InstanceNUMATopology(cells=[
objects.InstanceNUMACell(
id=0, cpuset=set([0]), pcpuset=set(), memory=1024),
@@ -3641,9 +3652,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(instance_cell.memory * units.Ki,
numa_cfg_cell.memory)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_topo(self, is_able):
def test_get_guest_config_numa_host_instance_topo(
self, is_able):
self.flags(cpu_shared_set='0-5', cpu_dedicated_set=None,
group='compute')
@@ -3724,6 +3737,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual([instance_cell.id], memnode.nodeset)
self.assertEqual("strict", memnode.mode)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_topo_reordered(self):
instance_topology = objects.InstanceNUMATopology(cells=[
objects.InstanceNUMACell(
@@ -3799,6 +3813,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual([instance_cell.id], memnode.nodeset)
self.assertEqual("strict", memnode.mode)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_topo_cpu_pinning(self):
instance_topology = objects.InstanceNUMATopology(cells=[
objects.InstanceNUMACell(
@@ -3877,6 +3892,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual([instance_cell.id], memnode.nodeset)
self.assertEqual("strict", memnode.mode)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_cpu_mixed(self):
"""Test to create mixed instance libvirt configuration which has a
default emulator thread policy and verify the NUMA topology related
@@ -3994,7 +4010,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(i, memnode.cellid)
self.assertEqual([instance_cell.id], memnode.nodeset)
def test_get_guest_config_numa_host_instance_cpu_mixed_isolated_emu(self):
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_cpu_mixed_isolated_emu(
self):
"""Test to create mixed instance libvirt configuration which has an
ISOLATED emulator thread policy and verify the NUMA topology related
settings.
@@ -4081,6 +4099,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(i, memnode.cellid)
self.assertEqual([instance_cell.id], memnode.nodeset)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_cpu_mixed_realtime(self):
"""Test of creating mixed instance libvirt configuration. which is
created through 'hw:cpu_realtime_mask' and 'hw:cpu_realtime' extra
@@ -4206,6 +4225,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual("fifo", cfg.cputune.vcpusched[0].scheduler)
self.assertEqual(set([0, 1, 4, 5]), cfg.cputune.vcpusched[0].vcpus)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_mempages_shared(self):
self.flags(cpu_shared_set='2-5', cpu_dedicated_set=None,
group='compute')
@@ -4279,7 +4299,9 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpusched))
self.assertEqual(set([2, 3, 4, 5]), cfg.cputune.emulatorpin.cpuset)
def test_get_guest_config_numa_host_instance_cpu_pinning_realtime(self):
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_cpu_pinning_realtime(
self):
self.flags(cpu_shared_set=None, cpu_dedicated_set='4-7',
group='compute')
@@ -4374,6 +4396,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
# which are 6, 7
self.assertEqual(set([2, 3]), cfg.cputune.vcpusched[0].vcpus)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_isolated_emulthreads(self):
self.flags(cpu_shared_set=None, cpu_dedicated_set='4-8',
group='compute')
@@ -4480,8 +4503,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertRaises(exception.Invalid, drvr._get_guest_config,
instance_ref, [], image_meta, disk_info)
def test_get_guest_config_numa_host_instance_shared_emulator_threads(
self):
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_numa_host_instance_shared_emulator_threads(self):
self.flags(cpu_shared_set='0,1', cpu_dedicated_set='2-7',
group='compute')
instance_topology = objects.InstanceNUMATopology(
@@ -4687,6 +4710,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertTrue(drvr._wants_hugepages(host_topology,
instance_topology))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_clock(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -4730,6 +4754,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
else:
self.assertEqual(2, len(cfg.clock.timers))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_clock_hpet_false(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -4775,6 +4800,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
else:
self.assertEqual(2, len(cfg.clock.timers))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_clock_hpet_true(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -4821,6 +4847,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
else:
self.assertEqual(2, len(cfg.clock.timers))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_clock_hpet_invalid(self):
self.flags(virt_type='kvm', group='libvirt')
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@@ -5314,6 +5341,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(cfg.devices[2].target_dev, 'vdd')
mock_save.assert_called_with()
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_with_configdrive(self):
# It's necessary to check if the architecture is power, because
# power doesn't have support to ide, and so libvirt translate
@@ -5700,6 +5728,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertIsNone(cfg.devices[3].keymap)
self.assertEqual(cfg.devices[5].type, 'tablet')
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_with_spice_and_agent(self):
self.flags(enabled=False, group='vnc')
self.flags(virt_type='kvm', group='libvirt')
@@ -6175,6 +6204,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
i = drvr._get_scsi_controller_next_unit(guest)
self.assertEqual(expect_num, i)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_with_type_kvm_on_s390(self):
self.flags(enabled=False, group='vnc')
self.flags(virt_type='kvm', group='libvirt')
@@ -7674,16 +7704,20 @@ class LibvirtConnTestCase(test.NoDBTestCase,
return drvr._get_guest_config(
instance_ref, _fake_network_info(self), image_meta, disk_info)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_machine_type_through_image_meta(self):
cfg = self._get_guest_config_machine_type_through_image_meta(
"fake_machine_type")
self.assertEqual(cfg.os_mach_type, "fake_machine_type")
def test_get_guest_config_machine_type_through_image_meta_sev(self):
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_machine_type_through_image_meta_sev(
self):
fake_q35 = "fake-q35-2.11"
cfg = self._get_guest_config_machine_type_through_image_meta(fake_q35)
self.assertEqual(cfg.os_mach_type, fake_q35)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_machine_type_from_config(self):
self.flags(virt_type='kvm', group='libvirt')
self.flags(hw_machine_type=['x86_64=fake_machine_type'],
@@ -7812,11 +7846,14 @@ class LibvirtConnTestCase(test.NoDBTestCase,
cfg.devices[device_index], vconfig.LibvirtConfigGuestVideo)
self.assertEqual(cfg.devices[device_index].type, 'vga')
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_ppc64_through_image_meta_vnc_enabled(self):
self.flags(enabled=True, group='vnc')
self._test_get_guest_config_ppc64(4)
def test_get_guest_config_ppc64_through_image_meta_spice_enabled(self):
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_config_ppc64_through_image_meta_spice_enabled(
self):
self.flags(enabled=True,
agent_enabled=True,
group='spice')
@@ -7904,6 +7941,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
image_meta, disk_info)
self.assertIsNone(conf.cpu)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_cpu_config_automatic(self):
expected = {
fields.Architecture.X86_64: "host-model",
@@ -8481,6 +8519,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
break
self.assertTrue(no_exist)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_get_guest_usb_controller(self):
self.flags(enabled=True, group='vnc')
@@ -8633,6 +8672,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
None,
(("disk", "virtio", "vda"),))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_xml_disk_bus_ide(self):
# It's necessary to check if the architecture is power, because
# power doesn't have support to ide, and so libvirt translate
@@ -8668,6 +8708,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
block_device_info,
(expected,))
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_xml_disk_bus_ide_and_virtio(self):
expected = {
fields.Architecture.X86_64: ("cdrom", "ide", "hda"),
@@ -14809,6 +14850,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock_stat.assert_called_once_with(path)
mock_get_size.assert_called_once_with(path)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
@mock.patch.object(libvirt_driver.LibvirtDriver,
'_register_undefined_instance_details',
new=mock.Mock())
@@ -14946,6 +14988,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock_build_device_metadata.assert_called_once_with(self.context,
instance)
@mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock())
def test_spawn_power_on_false(self):
self.test_spawn_with_network_info(power_on=False)

View File

@@ -1096,6 +1096,48 @@ Active: 8381604 kB
guest = self.host.write_instance_config(fake_dom_xml)
self.assertIsInstance(guest, libvirt_guest.Guest)
def test_check_machine_type_invalid(self):
fake_dom_xml = u"""
<capabilities>
<guest>
<os_type>hvm</os_type>
<arch name="alpha">
<emulator>/usr/bin/qemu-system-alpha</emulator>
<machine maxCpus="4">q35</machine>
<machine maxCpus="1">integratorcp</machine>
<machine maxCpus="1">versatileab</machine>
<domain type="qemu"/>
</arch>
</guest>
</capabilities>
"""
self.assertRaises(
exception.InvalidMachineType,
self.host._check_machine_type, fake_dom_xml, 'Q35'
)
def test_check_machine_type_valid(self):
fake_dom_xml = u"""
<capabilities>
<guest>
<os_type>hvm</os_type>
<arch name="alpha">
<emulator>/usr/bin/qemu-system-alpha</emulator>
<machine maxCpus="4">q35</machine>
<machine maxCpus="1">integratorcp</machine>
<machine maxCpus="1">versatileab</machine>
<domain type="qemu"/>
</arch>
</guest>
</capabilities>
"""
self.assertIsNone(
self.host._check_machine_type(fake_dom_xml, 'q35'),
"None msg"
)
@mock.patch.object(fakelibvirt.virConnect, "nodeDeviceLookupByName")
def test_device_lookup_by_name(self, mock_nodeDeviceLookupByName):
self.host.device_lookup_by_name("foo")

View File

@@ -6446,6 +6446,8 @@ class LibvirtDriver(driver.ComputeDriver):
guest.os_smbios = vconfig.LibvirtConfigGuestSMBIOS()
mach_type = libvirt_utils.get_machine_type(image_meta)
self._host._check_machine_type(caps, mach_type)
guest.os_mach_type = mach_type
hw_firmware_type = image_meta.properties.get('hw_firmware_type')

View File

@@ -31,6 +31,7 @@ from collections import defaultdict
import fnmatch
import glob
import inspect
from lxml import etree
import operator
import os
import queue
@@ -1198,6 +1199,25 @@ class Host(object):
stats["frequency"] = self._get_hardware_info()[3]
return stats
def _check_machine_type(self, caps, mach_type):
"""Validate if hw machine type is in capabilities of the host
:param caps: host capabilities
:param mach_type: machine type
"""
possible_machine_types = []
caps_tree = etree.fromstring(str(caps))
for guest in caps_tree.findall('guest'):
for machine in guest.xpath('arch/machine'):
possible_machine_types.append(machine.text)
if mach_type not in possible_machine_types:
raise exception.InvalidMachineType(
message="'%s' is not valid/supported machine type, "
"Supported machine types are: %s" % (
mach_type, possible_machine_types))
def write_instance_config(self, xml):
"""Defines a domain, but does not start it.

View File

@@ -0,0 +1,9 @@
---
fixes:
- |
Added validation for image machine type property. Different APIs which
uses machine type for server creation, resize or rebuild will raise
InvalidMachineType exception with message "provided machine type is not
supported by host" and suggest possible/valid machine types in compute logs.
.. _bug 1933097: https://bugs.launchpad.net/nova/+bug/1933097