Merge "refactors vmops' create_instance"
This commit is contained in:
commit
da73f59389
|
@ -363,28 +363,7 @@ class VMOps(object):
|
|||
|
||||
memory_per_numa_node, cpus_per_numa_node = (
|
||||
self._get_instance_vnuma_config(instance, image_meta))
|
||||
|
||||
if memory_per_numa_node:
|
||||
LOG.debug("Instance requires vNUMA topology. Host's NUMA spanning "
|
||||
"has to be disabled in order for the instance to "
|
||||
"benefit from it.", instance=instance)
|
||||
if CONF.hyperv.dynamic_memory_ratio > 1.0:
|
||||
LOG.warning(_LW(
|
||||
"Instance vNUMA topology requested, but dynamic memory "
|
||||
"ratio is higher than 1.0 in nova.conf. Ignoring dynamic "
|
||||
"memory ratio option."), instance=instance)
|
||||
dynamic_memory_ratio = 1.0
|
||||
vnuma_enabled = True
|
||||
else:
|
||||
dynamic_memory_ratio = CONF.hyperv.dynamic_memory_ratio
|
||||
vnuma_enabled = False
|
||||
|
||||
if instance.pci_requests.requests:
|
||||
# NOTE(claudiub): if the instance requires PCI devices, its
|
||||
# host shutdown action MUST be shutdown.
|
||||
host_shutdown_action = os_win_const.HOST_SHUTDOWN_ACTION_SHUTDOWN
|
||||
else:
|
||||
host_shutdown_action = None
|
||||
vnuma_enabled = bool(memory_per_numa_node)
|
||||
|
||||
self._vmutils.create_vm(instance_name,
|
||||
vnuma_enabled,
|
||||
|
@ -392,17 +371,6 @@ class VMOps(object):
|
|||
instance_path,
|
||||
[instance.uuid])
|
||||
|
||||
self._vmutils.update_vm(instance_name,
|
||||
instance.flavor.memory_mb,
|
||||
memory_per_numa_node,
|
||||
instance.flavor.vcpus,
|
||||
cpus_per_numa_node,
|
||||
CONF.hyperv.limit_cpu_features,
|
||||
dynamic_memory_ratio,
|
||||
host_shutdown_action=host_shutdown_action)
|
||||
|
||||
self._configure_remotefx(instance, vm_gen)
|
||||
|
||||
self._vmutils.create_scsi_controller(instance_name)
|
||||
self._attach_root_device(instance_name, root_device)
|
||||
self._attach_ephemerals(instance_name, block_device_info['ephemerals'])
|
||||
|
@ -421,8 +389,6 @@ class VMOps(object):
|
|||
if CONF.hyperv.enable_instance_metrics_collection:
|
||||
self._metricsutils.enable_vm_metrics_collection(instance_name)
|
||||
|
||||
self._set_instance_disk_qos_specs(instance)
|
||||
|
||||
if secure_boot_enabled:
|
||||
certificate_required = self._requires_certificate(image_meta)
|
||||
self._vmutils.enable_secure_boot(
|
||||
|
@ -431,6 +397,37 @@ class VMOps(object):
|
|||
self._configure_secure_vm(context, instance, image_meta,
|
||||
secure_boot_enabled)
|
||||
|
||||
self.update_vm_resources(instance, vm_gen, image_meta)
|
||||
|
||||
def update_vm_resources(self, instance, vm_gen, image_meta,
|
||||
is_planned_vm=False):
|
||||
"""Updates the VM's reconfigurable resources."""
|
||||
memory_per_numa_node, cpus_per_numa_node = (
|
||||
self._get_instance_vnuma_config(instance, image_meta))
|
||||
vnuma_enabled = bool(memory_per_numa_node)
|
||||
|
||||
dynamic_memory_ratio = self._get_instance_dynamic_memory_ratio(
|
||||
instance, vnuma_enabled)
|
||||
|
||||
if instance.pci_requests.requests:
|
||||
# NOTE(claudiub): if the instance requires PCI devices, its
|
||||
# host shutdown action MUST be shutdown.
|
||||
host_shutdown_action = os_win_const.HOST_SHUTDOWN_ACTION_SHUTDOWN
|
||||
else:
|
||||
host_shutdown_action = None
|
||||
|
||||
self._vmutils.update_vm(instance.name,
|
||||
instance.flavor.memory_mb,
|
||||
memory_per_numa_node,
|
||||
instance.flavor.vcpus,
|
||||
cpus_per_numa_node,
|
||||
CONF.hyperv.limit_cpu_features,
|
||||
dynamic_memory_ratio,
|
||||
host_shutdown_action=host_shutdown_action,
|
||||
is_planned_vm=is_planned_vm)
|
||||
|
||||
self._configure_remotefx(instance, vm_gen)
|
||||
self._set_instance_disk_qos_specs(instance)
|
||||
self._attach_pci_devices(instance)
|
||||
|
||||
def _attach_pci_devices(self, instance):
|
||||
|
@ -483,6 +480,20 @@ class VMOps(object):
|
|||
|
||||
return memory_per_numa_node, cpus_per_numa_node
|
||||
|
||||
def _get_instance_dynamic_memory_ratio(self, instance, vnuma_enabled):
|
||||
dynamic_memory_ratio = CONF.hyperv.dynamic_memory_ratio
|
||||
if vnuma_enabled:
|
||||
LOG.debug("Instance requires vNUMA topology. Host's NUMA spanning "
|
||||
"has to be disabled in order for the instance to "
|
||||
"benefit from it.", instance=instance)
|
||||
if CONF.hyperv.dynamic_memory_ratio > 1.0:
|
||||
LOG.warning(_LW(
|
||||
"Instance vNUMA topology requested, but dynamic memory "
|
||||
"ratio is higher than 1.0 in nova.conf. Ignoring dynamic "
|
||||
"memory ratio option."), instance=instance)
|
||||
dynamic_memory_ratio = 1.0
|
||||
return dynamic_memory_ratio
|
||||
|
||||
def _configure_remotefx(self, instance, vm_gen):
|
||||
extra_specs = instance.flavor.extra_specs
|
||||
remotefx_max_resolution = extra_specs.get(
|
||||
|
|
|
@ -14,14 +14,13 @@
|
|||
|
||||
import os
|
||||
|
||||
import ddt
|
||||
from eventlet import timeout as etimeout
|
||||
import mock
|
||||
from nova.compute import vm_states
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova.objects import fields
|
||||
from nova.objects import flavor as flavor_obj
|
||||
from nova.tests.unit.objects import test_flavor
|
||||
from nova.tests.unit.objects import test_virtual_interface
|
||||
from nova.virt import hardware
|
||||
from os_win import constants as os_win_const
|
||||
|
@ -42,6 +41,7 @@ from hyperv.tests.unit import test_base
|
|||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
||||
"""Unit tests for the Hyper-V VMOps class."""
|
||||
|
||||
|
@ -566,37 +566,27 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
self.assertEqual([], events)
|
||||
mock_is_neutron.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_attach_pci_devices')
|
||||
@mock.patch.object(vmops.VMOps, 'update_vm_resources')
|
||||
@mock.patch.object(vmops.VMOps, '_configure_secure_vm')
|
||||
@mock.patch.object(vmops.VMOps, '_requires_secure_boot')
|
||||
@mock.patch.object(vmops.VMOps, '_requires_certificate')
|
||||
@mock.patch.object(vmops.VMOps, '_get_instance_vnuma_config')
|
||||
@mock.patch.object(vmops.volumeops.VolumeOps, 'attach_volumes')
|
||||
@mock.patch.object(vmops.VMOps, '_set_instance_disk_qos_specs')
|
||||
@mock.patch.object(vmops.VMOps, '_attach_root_device')
|
||||
@mock.patch.object(vmops.VMOps, '_get_image_serial_port_settings')
|
||||
@mock.patch.object(vmops.VMOps, '_create_vm_com_port_pipes')
|
||||
@mock.patch.object(vmops.VMOps, '_attach_ephemerals')
|
||||
@mock.patch.object(vmops.VMOps, '_configure_remotefx')
|
||||
def _test_create_instance(self, mock_configure_remotefx,
|
||||
mock_attach_ephemerals,
|
||||
mock_create_pipes,
|
||||
mock_get_port_settings,
|
||||
mock_attach_root_device,
|
||||
mock_set_qos_specs,
|
||||
mock_attach_volumes,
|
||||
mock_get_vnuma_config,
|
||||
mock_requires_certificate,
|
||||
mock_requires_secure_boot,
|
||||
mock_configure_secure_vm,
|
||||
mock_attach_pci_devices,
|
||||
enable_instance_metrics,
|
||||
vm_gen=constants.VM_GEN_1,
|
||||
vnuma_enabled=False,
|
||||
pci_requests=None,
|
||||
requires_sec_boot=True):
|
||||
self.flags(dynamic_memory_ratio=2.0, group='hyperv')
|
||||
self.flags(enable_instance_metrics_collection=enable_instance_metrics,
|
||||
def test_create_instance(self, mock_attach_ephemerals,
|
||||
mock_create_pipes,
|
||||
mock_get_port_settings,
|
||||
mock_attach_root_device,
|
||||
mock_attach_volumes,
|
||||
mock_get_vnuma_config,
|
||||
mock_requires_certificate,
|
||||
mock_requires_secure_boot,
|
||||
mock_configure_secure_vm,
|
||||
mock_update_vm_resources):
|
||||
self.flags(enable_instance_metrics_collection=True,
|
||||
group='hyperv')
|
||||
root_device_info = mock.sentinel.ROOT_DEV_INFO
|
||||
block_device_info = {'root_disk': root_device_info, 'ephemerals': [],
|
||||
|
@ -605,46 +595,23 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
'address': mock.sentinel.ADDRESS}
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
instance_path = os.path.join(CONF.instances_path, mock_instance.name)
|
||||
mock_requires_secure_boot.return_value = True
|
||||
|
||||
flavor = flavor_obj.Flavor(**test_flavor.fake_flavor)
|
||||
mock_instance.flavor = flavor
|
||||
instance_pci_requests = objects.InstancePCIRequests(
|
||||
requests=pci_requests or [], instance_uuid=mock_instance.uuid)
|
||||
mock_instance.pci_requests = instance_pci_requests
|
||||
host_shutdown_action = (os_win_const.HOST_SHUTDOWN_ACTION_SHUTDOWN
|
||||
if pci_requests else None)
|
||||
|
||||
if vnuma_enabled:
|
||||
mock_get_vnuma_config.return_value = (
|
||||
mock.sentinel.mem_per_numa, mock.sentinel.cpus_per_numa)
|
||||
cpus_per_numa = mock.sentinel.cpus_per_numa
|
||||
mem_per_numa = mock.sentinel.mem_per_numa
|
||||
dynamic_memory_ratio = 1.0
|
||||
else:
|
||||
mock_get_vnuma_config.return_value = (None, None)
|
||||
mem_per_numa, cpus_per_numa = (None, None)
|
||||
dynamic_memory_ratio = CONF.hyperv.dynamic_memory_ratio
|
||||
mock_get_vnuma_config.return_value = (mock.sentinel.mem_per_numa_node,
|
||||
mock.sentinel.vnuma_cpus)
|
||||
|
||||
self._vmops.create_instance(context=self.context,
|
||||
instance=mock_instance,
|
||||
network_info=[fake_network_info],
|
||||
block_device_info=block_device_info,
|
||||
vm_gen=vm_gen,
|
||||
vm_gen=mock.sentinel.vm_gen,
|
||||
image_meta=mock.sentinel.image_meta)
|
||||
|
||||
mock_get_vnuma_config.assert_called_once_with(mock_instance,
|
||||
mock.sentinel.image_meta)
|
||||
self._vmops._vmutils.create_vm.assert_called_once_with(
|
||||
mock_instance.name, vnuma_enabled, vm_gen,
|
||||
mock_instance.name, True, mock.sentinel.vm_gen,
|
||||
instance_path, [mock_instance.uuid])
|
||||
self._vmops._vmutils.update_vm.assert_called_once_with(
|
||||
mock_instance.name, mock_instance.flavor.memory_mb, mem_per_numa,
|
||||
mock_instance.flavor.vcpus, cpus_per_numa,
|
||||
CONF.hyperv.limit_cpu_features, dynamic_memory_ratio,
|
||||
host_shutdown_action=host_shutdown_action)
|
||||
|
||||
mock_configure_remotefx.assert_called_once_with(mock_instance, vm_gen)
|
||||
mock_create_scsi_ctrl = self._vmops._vmutils.create_scsi_controller
|
||||
mock_create_scsi_ctrl.assert_called_once_with(mock_instance.name)
|
||||
|
||||
|
@ -662,11 +629,9 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
self._vmops._vmutils.create_nic.assert_called_once_with(
|
||||
mock_instance.name, mock.sentinel.ID, mock.sentinel.ADDRESS)
|
||||
mock_enable = self._vmops._metricsutils.enable_vm_metrics_collection
|
||||
if enable_instance_metrics:
|
||||
mock_enable.assert_called_once_with(mock_instance.name)
|
||||
mock_set_qos_specs.assert_called_once_with(mock_instance)
|
||||
mock_enable.assert_called_once_with(mock_instance.name)
|
||||
mock_requires_secure_boot.assert_called_once_with(
|
||||
mock_instance, mock.sentinel.image_meta, vm_gen)
|
||||
mock_instance, mock.sentinel.image_meta, mock.sentinel.vm_gen)
|
||||
mock_requires_certificate.assert_called_once_with(
|
||||
mock.sentinel.image_meta)
|
||||
enable_secure_boot = self._vmops._vmutils.enable_secure_boot
|
||||
|
@ -674,30 +639,61 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
mock_instance.name,
|
||||
msft_ca_required=mock_requires_certificate.return_value)
|
||||
mock_configure_secure_vm.assert_called_once_with(self.context,
|
||||
mock_instance, mock.sentinel.image_meta, requires_sec_boot)
|
||||
mock_instance, mock.sentinel.image_meta,
|
||||
mock_requires_secure_boot.return_value)
|
||||
mock_update_vm_resources.assert_called_once_with(
|
||||
mock_instance, mock.sentinel.vm_gen, mock.sentinel.image_meta)
|
||||
|
||||
@mock.patch.object(vmops.VMOps, '_attach_pci_devices')
|
||||
@mock.patch.object(vmops.VMOps, '_set_instance_disk_qos_specs')
|
||||
@mock.patch.object(vmops.VMOps, '_configure_remotefx')
|
||||
@mock.patch.object(vmops.VMOps, '_get_instance_dynamic_memory_ratio')
|
||||
@mock.patch.object(vmops.VMOps, '_get_instance_vnuma_config')
|
||||
def _check_update_vm_resources(self, mock_get_vnuma_config,
|
||||
mock_get_dynamic_memory_ratio,
|
||||
mock_configure_remotefx,
|
||||
mock_set_qos_specs,
|
||||
mock_attach_pci_devices,
|
||||
pci_requests=None):
|
||||
mock_get_vnuma_config.return_value = (mock.sentinel.mem_per_numa_node,
|
||||
mock.sentinel.vnuma_cpus)
|
||||
dynamic_memory_ratio = mock_get_dynamic_memory_ratio.return_value
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
|
||||
instance_pci_requests = objects.InstancePCIRequests(
|
||||
requests=pci_requests or [], instance_uuid=mock_instance.uuid)
|
||||
mock_instance.pci_requests = instance_pci_requests
|
||||
host_shutdown_action = (os_win_const.HOST_SHUTDOWN_ACTION_SHUTDOWN
|
||||
if pci_requests else None)
|
||||
|
||||
self._vmops.update_vm_resources(mock_instance, mock.sentinel.vm_gen,
|
||||
mock.sentinel.image_meta,
|
||||
mock.sentinel.is_planned_vm)
|
||||
|
||||
mock_get_vnuma_config.assert_called_once_with(mock_instance,
|
||||
mock.sentinel.image_meta)
|
||||
mock_get_dynamic_memory_ratio.assert_called_once_with(
|
||||
mock_instance, True)
|
||||
self._vmops._vmutils.update_vm.assert_called_once_with(
|
||||
mock_instance.name, mock_instance.flavor.memory_mb,
|
||||
mock.sentinel.mem_per_numa_node, mock_instance.flavor.vcpus,
|
||||
mock.sentinel.vnuma_cpus, CONF.hyperv.limit_cpu_features,
|
||||
dynamic_memory_ratio, host_shutdown_action=host_shutdown_action,
|
||||
is_planned_vm=mock.sentinel.is_planned_vm)
|
||||
mock_configure_remotefx.assert_called_once_with(mock_instance,
|
||||
mock.sentinel.vm_gen)
|
||||
mock_set_qos_specs.assert_called_once_with(mock_instance)
|
||||
mock_attach_pci_devices.assert_called_once_with(mock_instance)
|
||||
|
||||
def test_create_instance(self):
|
||||
self._test_create_instance(enable_instance_metrics=True)
|
||||
def test_update_vm_resources(self):
|
||||
self._check_update_vm_resources()
|
||||
|
||||
def test_create_instance_enable_instance_metrics_false(self):
|
||||
self._test_create_instance(enable_instance_metrics=False)
|
||||
|
||||
def test_create_instance_gen2(self):
|
||||
self._test_create_instance(enable_instance_metrics=False,
|
||||
vm_gen=constants.VM_GEN_2)
|
||||
|
||||
def test_create_instance_vnuma_enabled(self):
|
||||
self._test_create_instance(enable_instance_metrics=False,
|
||||
vnuma_enabled=True)
|
||||
|
||||
def test_create_instance_pci_requested(self):
|
||||
def test_update_vm_resources_pci_requested(self):
|
||||
vendor_id = 'fake_vendor_id'
|
||||
product_id = 'fake_product_id'
|
||||
spec = {'vendor_id': vendor_id, 'product_id': product_id}
|
||||
request = objects.InstancePCIRequest(count=1, spec=[spec])
|
||||
self._test_create_instance(enable_instance_metrics=False,
|
||||
pci_requests=[request])
|
||||
self._check_update_vm_resources(pci_requests=[request])
|
||||
|
||||
def test_attach_pci_devices(self):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
|
@ -765,6 +761,18 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
|
|||
def test_get_instance_vnuma_config_no_topology(self):
|
||||
self._check_get_instance_vnuma_config()
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_get_instance_dynamic_memory_ratio(self, vnuma_enabled):
|
||||
expected_dyn_memory_ratio = 2.0
|
||||
self.flags(dynamic_memory_ratio=expected_dyn_memory_ratio,
|
||||
group='hyperv')
|
||||
if vnuma_enabled:
|
||||
expected_dyn_memory_ratio = 1.0
|
||||
|
||||
response = self._vmops._get_instance_dynamic_memory_ratio(
|
||||
mock.sentinel.instance, vnuma_enabled)
|
||||
self.assertEqual(expected_dyn_memory_ratio, response)
|
||||
|
||||
@mock.patch.object(vmops.volumeops.VolumeOps, 'attach_volume')
|
||||
def test_attach_root_device_volume(self, mock_attach_volume):
|
||||
mock_instance = fake_instance.fake_instance_obj(self.context)
|
||||
|
|
Loading…
Reference in New Issue