Adds Hyper-V vNic hot-plug implementation

The new Hyper-V version adds support for adding and removing
vNICs on a running instance.

This is a driver feature parity blueprint.

Implementation is straightforward and consists in providing the
virt driver's class attach_interface and detach_interface methods.

Implements: blueprint hyper-v-vnic-hot-plug

Change-Id: I14aba8b14b7036a09a8dde8235fd4345af4da510
This commit is contained in:
Adelina Tuvenie
2015-04-21 03:42:51 -07:00
committed by Claudiu Belu
parent 24590966f7
commit bc9abe0930
5 changed files with 176 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ from nova import exception
from nova.objects import flavor as flavor_obj
from nova.openstack.common import fileutils
from nova.tests.unit.objects import test_flavor
from nova.tests.unit.objects import test_virtual_interface
from nova.virt import hardware
from oslo_concurrency import processutils
from oslo_config import cfg
@@ -46,6 +47,8 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
FAKE_CONFIG_DRIVE_VHD = 'configdrive.vhd'
FAKE_UUID = '4f54fb69-d3a2-45b7-bb9b-b6e6b3d893b3'
FAKE_LOG = 'fake_log'
_WIN_VERSION_6_3 = '6.3.0'
_WIN_VERSION_6_4 = '6.4.0'
ISO9660 = 'iso9660'
_FAKE_CONFIGDRIVE_PATH = 'C:/fake_instance_dir/configdrive.vhd'
@@ -1324,3 +1327,110 @@ class VMOpsTestCase(test_base.HyperVBaseTestCase):
def test_configure_remotefx(self):
self._test_configure_remotefx()
@mock.patch.object(vmops.VMOps, '_get_vm_state')
def _test_check_hotplug_is_available(self, mock_get_vm_state, vm_gen,
windows_version, vm_state):
fake_vm = fake_instance.fake_instance_obj(self.context)
mock_get_vm_state.return_value = vm_state
self._vmops._vmutils.get_vm_gen.return_value = vm_gen
fake_check_win_vers = self._vmops._hostutils.check_min_windows_version
if windows_version == self._WIN_VERSION_6_3:
fake_check_win_vers.return_value = False
else:
fake_check_win_vers.return_value = True
if (windows_version == self._WIN_VERSION_6_3 or
vm_gen == constants.VM_GEN_1):
self.assertRaises(exception.InterfaceAttachFailed,
self._vmops._check_hotplug_is_available, fake_vm)
else:
ret = self._vmops._check_hotplug_is_available(fake_vm)
if vm_state == constants.HYPERV_VM_STATE_DISABLED:
self.assertFalse(ret)
else:
self.assertTrue(ret)
def test_check_if_hotplug_is_available_gen1(self):
self._test_check_hotplug_is_available(vm_gen=constants.VM_GEN_1,
windows_version=self._WIN_VERSION_6_4,
vm_state=constants.HYPERV_VM_STATE_ENABLED)
def test_check_if_hotplug_is_available_gen2(self):
self._test_check_hotplug_is_available(vm_gen=constants.VM_GEN_2,
windows_version=self._WIN_VERSION_6_4,
vm_state=constants.HYPERV_VM_STATE_ENABLED)
def test_check_if_hotplug_is_available_win_6_3(self):
self._test_check_hotplug_is_available(vm_gen=constants.VM_GEN_2,
windows_version=self._WIN_VERSION_6_3,
vm_state=constants.HYPERV_VM_STATE_ENABLED)
def test_check_if_hotplug_is_available_vm_disabled(self):
self._test_check_hotplug_is_available(vm_gen=constants.VM_GEN_2,
windows_version=self._WIN_VERSION_6_4,
vm_state=constants.HYPERV_VM_STATE_DISABLED)
@mock.patch.object(vmops.VMOps, '_get_vif_driver')
def _test_create_and_attach_interface(self, mock_get_vif_driver, hot_plug):
fake_vm = fake_instance.fake_instance_obj(self.context)
fake_vif = test_virtual_interface.fake_vif
fake_vif['type'] = mock.sentinel.VIF_TYPE
fake_vif_driver = mock_get_vif_driver.return_value
self._vmops._create_and_attach_interface(fake_vm, fake_vif, hot_plug)
self._vmops._vmutils.create_nic.assert_called_with(fake_vm.name,
fake_vif['id'], fake_vif['address'])
mock_get_vif_driver.assert_called_once_with(mock.sentinel.VIF_TYPE)
fake_vif_driver.plug.assert_called_once_with(fake_vm, fake_vif)
if hot_plug:
fake_vif_driver.post_start.assert_called_once_with(fake_vm,
fake_vif)
def test_create_and_attach_interface_hot_plugged(self):
self._test_create_and_attach_interface(hot_plug=True)
def test_create_and_attach_interface(self):
self._test_create_and_attach_interface(hot_plug=False)
@mock.patch.object(vmops.VMOps, '_check_hotplug_is_available')
@mock.patch.object(vmops.VMOps, '_create_and_attach_interface')
def _test_attach_interface(self, mock_create_and_attach_interface,
mock_check_hotplug_is_available, hot_plug):
mock_check_hotplug_is_available.return_value = hot_plug
self._vmops.attach_interface(mock.sentinel.FAKE_VM,
mock.sentinel.FAKE_VIF)
mock_check_hotplug_is_available.assert_called_once_with(
mock.sentinel.FAKE_VM)
mock_create_and_attach_interface.assert_called_once_with(
mock.sentinel.FAKE_VM, mock.sentinel.FAKE_VIF, hot_plug)
def test_attach_interface_hot_plugged(self):
self._test_attach_interface(hot_plug=True)
def test_attach_interface(self):
self._test_attach_interface(hot_plug=False)
@mock.patch.object(vmops.VMOps, '_get_vif_driver')
def test_detach_and_destroy_interface(self, mock_get_vif_driver):
fake_vm = fake_instance.fake_instance_obj(self.context)
fake_vif = test_virtual_interface.fake_vif
fake_vif['type'] = mock.sentinel.VIF_TYPE
fake_vif_driver = mock_get_vif_driver.return_value
self._vmops._detach_and_destroy_interface(fake_vm, fake_vif)
fake_vif_driver.unplug.assert_called_once_with(fake_vm, fake_vif)
self._vmops._vmutils.destroy_nic.assert_called_once_with(
fake_vm.name, fake_vif['id'])
@mock.patch.object(vmops.VMOps, '_check_hotplug_is_available')
@mock.patch.object(vmops.VMOps, '_detach_and_destroy_interface')
def test_detach_interface(self, mock_detach_and_destroy_interface,
mock_check_hotplug_is_available):
self._vmops.detach_interface(mock.sentinel.FAKE_VM,
mock.sentinel.FAKE_VIF)
mock_check_hotplug_is_available.assert_called_once_with(
mock.sentinel.FAKE_VM)
mock_detach_and_destroy_interface.assert_called_once_with(
mock.sentinel.FAKE_VM, mock.sentinel.FAKE_VIF)

View File

@@ -390,6 +390,18 @@ class VMUtilsTestCase(test.NoDBTestCase):
mock_add_virt_res.assert_called_with(mock_nic, self._FAKE_VM_PATH)
@mock.patch.object(vmutils.VMUtils, '_get_nic_data_by_name')
def test_destroy_nic(self, mock_get_nic_data_by_name):
self._lookup_vm()
fake_nic_data = mock_get_nic_data_by_name.return_value
with mock.patch.object(self._vmutils,
'_remove_virt_resource') as mock_rem_virt_res:
self._vmutils.destroy_nic(self._FAKE_VM_NAME,
mock.sentinel.FAKE_NIC_NAME)
mock_rem_virt_res.assert_called_once_with(fake_nic_data,
self._FAKE_VM_PATH)
def test_set_vm_state(self):
mock_vm = self._lookup_vm()
mock_vm.RequestStateChange.return_value = (