vmutils: Allows updating and disabling instance RemoteFX
When resizing an instance, if it was imported, its resources
needs to be updated according to the new flavor. If a flavor
has different RemoteFX requirements, os_win should allow updates
to the instance's RemoteFX configuration.
Change-Id: Ib83bbc5c7fd07b55888f58d3407e1dd1a50e9b7e
Partial-Bug: #1663238
(cherry picked from commit ac07fcd78b
)
This commit is contained in:
parent
e0e92d0099
commit
3c7d3b732d
|
@ -1210,12 +1210,51 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase):
|
|||
self._vmutils._validate_remotefx_params,
|
||||
1, '1024x700')
|
||||
|
||||
@ddt.data(True, False)
|
||||
@mock.patch.object(vmutils.VMUtils, '_set_remotefx_vram')
|
||||
@mock.patch.object(vmutils.VMUtils, '_get_new_resource_setting_data')
|
||||
def test_set_remotefx_display_controller(self, new_obj, mock_get_new_rsd,
|
||||
mock_set_remotefx_vram):
|
||||
if new_obj:
|
||||
remotefx_ctrl_res = None
|
||||
expected_res = mock_get_new_rsd.return_value
|
||||
else:
|
||||
remotefx_ctrl_res = mock.MagicMock()
|
||||
expected_res = remotefx_ctrl_res
|
||||
|
||||
self._vmutils._set_remotefx_display_controller(
|
||||
mock.sentinel.fake_vm, remotefx_ctrl_res,
|
||||
mock.sentinel.monitor_count, mock.sentinel.max_resolution,
|
||||
mock.sentinel.vram_bytes)
|
||||
|
||||
self.assertEqual(mock.sentinel.monitor_count,
|
||||
expected_res.MaximumMonitors)
|
||||
self.assertEqual(mock.sentinel.max_resolution,
|
||||
expected_res.MaximumScreenResolution)
|
||||
mock_set_remotefx_vram.assert_called_once_with(
|
||||
expected_res, mock.sentinel.vram_bytes)
|
||||
|
||||
if new_obj:
|
||||
mock_get_new_rsd.assert_called_once_with(
|
||||
self._vmutils._REMOTEFX_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._vmutils._REMOTEFX_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
self._vmutils._jobutils.add_virt_resource.assert_called_once_with(
|
||||
expected_res, mock.sentinel.fake_vm)
|
||||
else:
|
||||
self.assertFalse(mock_get_new_rsd.called)
|
||||
modify_virt_res = self._vmutils._jobutils.modify_virt_resource
|
||||
modify_virt_res.assert_called_once_with(expected_res)
|
||||
|
||||
def test_set_remotefx_vram(self):
|
||||
self._vmutils._set_remotefx_vram(mock.sentinel.remotefx_ctrl_res,
|
||||
mock.sentinel.vram_bytes)
|
||||
|
||||
@mock.patch.object(_wqlutils, 'get_element_associated_class')
|
||||
@mock.patch.object(vmutils.VMUtils, '_add_3d_display_controller')
|
||||
@mock.patch.object(vmutils.VMUtils, '_set_remotefx_display_controller')
|
||||
@mock.patch.object(vmutils.VMUtils, '_vm_has_s3_controller')
|
||||
def test_enable_remotefx_video_adapter(self,
|
||||
mock_vm_has_s3_controller,
|
||||
mock_add_3d_ctrl,
|
||||
mock_set_remotefx_ctrl,
|
||||
mock_get_element_associated_class):
|
||||
mock_vm = self._lookup_vm()
|
||||
|
||||
|
@ -1235,12 +1274,12 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase):
|
|||
mock_get_element_associated_class.assert_called_once_with(
|
||||
self._vmutils._conn,
|
||||
self._vmutils._CIM_RES_ALLOC_SETTING_DATA_CLASS,
|
||||
element_uuid=mock_vm.Name)
|
||||
element_instance_id=mock_vm.InstanceID)
|
||||
self._vmutils._jobutils.remove_virt_resource.assert_called_once_with(
|
||||
mock_r1)
|
||||
|
||||
mock_add_3d_ctrl.assert_called_once_with(
|
||||
mock_vm, self._FAKE_MONITOR_COUNT,
|
||||
mock_set_remotefx_ctrl.assert_called_once_with(
|
||||
mock_vm, None, self._FAKE_MONITOR_COUNT,
|
||||
self._vmutils._remote_fx_res_map[
|
||||
constants.REMOTEFX_MAX_RES_1024x768],
|
||||
None)
|
||||
|
@ -1250,24 +1289,53 @@ class VMUtilsTestCase(test_base.OsWinBaseTestCase):
|
|||
self.assertEqual(self._vmutils._DISP_CTRL_ADDRESS_DX_11,
|
||||
mock_r2.Address)
|
||||
|
||||
@mock.patch.object(vmutils.VMUtils, '_vm_has_s3_controller')
|
||||
@mock.patch.object(vmutils.VMUtils, '_get_new_resource_setting_data')
|
||||
@mock.patch.object(_wqlutils, 'get_element_associated_class')
|
||||
def test_enable_remotefx_video_adapter_already_configured(
|
||||
self, mock_get_element_associated_class):
|
||||
def test_disable_remotefx_video_adapter(self,
|
||||
mock_get_element_associated_class,
|
||||
mock_get_new_rsd,
|
||||
mock_vm_has_s3_controller):
|
||||
mock_vm = self._lookup_vm()
|
||||
mock_r1 = mock.MagicMock(
|
||||
ResourceSubType=self._vmutils._REMOTEFX_DISP_CTRL_RES_SUB_TYPE)
|
||||
mock_r2 = mock.MagicMock(
|
||||
ResourceSubType=self._vmutils._S3_DISP_CTRL_RES_SUB_TYPE)
|
||||
|
||||
mock_r = mock.MagicMock()
|
||||
mock_r.ResourceSubType = self._vmutils._SYNTH_3D_DISP_CTRL_RES_SUB_TYPE
|
||||
mock_get_element_associated_class.return_value = [mock_r1, mock_r2]
|
||||
|
||||
mock_get_element_associated_class.return_value = [mock_r]
|
||||
self._vmutils.disable_remotefx_video_adapter(
|
||||
mock.sentinel.fake_vm_name)
|
||||
|
||||
self.assertRaises(exceptions.HyperVRemoteFXException,
|
||||
self._vmutils.enable_remotefx_video_adapter,
|
||||
mock.sentinel.fake_vm_name, self._FAKE_MONITOR_COUNT,
|
||||
constants.REMOTEFX_MAX_RES_1024x768)
|
||||
mock_get_element_associated_class.assert_called_once_with(
|
||||
self._vmutils._conn,
|
||||
self._vmutils._CIM_RES_ALLOC_SETTING_DATA_CLASS,
|
||||
element_uuid=mock_vm.Name)
|
||||
element_instance_id=mock_vm.InstanceID)
|
||||
self._vmutils._jobutils.remove_virt_resource.assert_called_once_with(
|
||||
mock_r1)
|
||||
mock_get_new_rsd.assert_called_once_with(
|
||||
self._vmutils._SYNTH_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._vmutils._SYNTH_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
self._vmutils._jobutils.add_virt_resource.assert_called_once_with(
|
||||
mock_get_new_rsd.return_value, mock_vm)
|
||||
self._vmutils._jobutils.modify_virt_resource.assert_called_once_with(
|
||||
mock_r2)
|
||||
self.assertEqual(self._vmutils._DISP_CTRL_ADDRESS, mock_r2.Address)
|
||||
|
||||
@mock.patch.object(_wqlutils, 'get_element_associated_class')
|
||||
def test_disable_remotefx_video_adapter_not_found(
|
||||
self, mock_get_element_associated_class):
|
||||
mock_vm = self._lookup_vm()
|
||||
mock_get_element_associated_class.return_value = []
|
||||
|
||||
self._vmutils.disable_remotefx_video_adapter(
|
||||
mock.sentinel.fake_vm_name)
|
||||
|
||||
mock_get_element_associated_class.assert_called_once_with(
|
||||
self._vmutils._conn,
|
||||
self._vmutils._CIM_RES_ALLOC_SETTING_DATA_CLASS,
|
||||
element_instance_id=mock_vm.InstanceID)
|
||||
self.assertFalse(self._vmutils._jobutils.remove_virt_resource.called)
|
||||
|
||||
@mock.patch.object(vmutils.VMUtils, 'get_vm_generation')
|
||||
def test_vm_has_s3_controller(self, mock_get_vm_generation):
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import ddt
|
||||
import mock
|
||||
import six
|
||||
|
||||
from os_win import constants
|
||||
from os_win import exceptions
|
||||
|
@ -118,6 +119,18 @@ class VMUtils10TestCase(test_base.OsWinBaseTestCase):
|
|||
1, constants.REMOTEFX_MAX_RES_1024x768,
|
||||
vram_bytes=10000)
|
||||
|
||||
def test_validate_remotefx(self):
|
||||
self._vmutils._validate_remotefx_params(
|
||||
1, constants.REMOTEFX_MAX_RES_1024x768)
|
||||
|
||||
def test_set_remotefx_vram(self):
|
||||
remotefx_ctrl_res = mock.MagicMock()
|
||||
vram_bytes = 512
|
||||
|
||||
self._vmutils._set_remotefx_vram(remotefx_ctrl_res, vram_bytes)
|
||||
self.assertEqual(six.text_type(vram_bytes),
|
||||
remotefx_ctrl_res.VRAMSizeBytes)
|
||||
|
||||
@mock.patch.object(vmutils10.VMUtils10, 'get_vm_generation')
|
||||
def _test_vm_has_s3_controller(self, vm_gen, mock_get_vm_gen):
|
||||
mock_get_vm_gen.return_value = vm_gen
|
||||
|
|
|
@ -75,9 +75,11 @@ class VMUtils(baseutils.BaseUtilsVirt):
|
|||
_S3_DISP_CTRL_RES_SUB_TYPE = 'Microsoft:Hyper-V:S3 Display Controller'
|
||||
_SYNTH_DISP_CTRL_RES_SUB_TYPE = ('Microsoft:Hyper-V:Synthetic Display '
|
||||
'Controller')
|
||||
_SYNTH_3D_DISP_CTRL_RES_SUB_TYPE = ('Microsoft:Hyper-V:Synthetic 3D '
|
||||
_REMOTEFX_DISP_CTRL_RES_SUB_TYPE = ('Microsoft:Hyper-V:Synthetic 3D '
|
||||
'Display Controller')
|
||||
_SYNTH_3D_DISP_ALLOCATION_SETTING_DATA_CLASS = (
|
||||
_SYNTH_DISP_ALLOCATION_SETTING_DATA_CLASS = (
|
||||
'Msvm_SyntheticDisplayControllerSettingData')
|
||||
_REMOTEFX_DISP_ALLOCATION_SETTING_DATA_CLASS = (
|
||||
'Msvm_Synthetic3DDisplayControllerSettingData')
|
||||
|
||||
_VIRTUAL_SYSTEM_SUBTYPE = 'VirtualSystemSubType'
|
||||
|
@ -112,6 +114,7 @@ class VMUtils(baseutils.BaseUtilsVirt):
|
|||
}
|
||||
|
||||
_DISP_CTRL_ADDRESS_DX_11 = "02C1,00000000,01"
|
||||
_DISP_CTRL_ADDRESS = "5353,00000000,00"
|
||||
|
||||
_vm_power_states_map = {constants.HYPERV_VM_STATE_ENABLED: 2,
|
||||
constants.HYPERV_VM_STATE_DISABLED: 3,
|
||||
|
@ -1067,44 +1070,86 @@ class VMUtils(baseutils.BaseUtilsVirt):
|
|||
'max_monitors':
|
||||
self._remotefx_max_monitors_map[max_resolution]})
|
||||
|
||||
def _add_3d_display_controller(self, vm, monitor_count,
|
||||
max_resolution, vram_bytes=None):
|
||||
synth_3d_disp_ctrl_res = self._get_new_resource_setting_data(
|
||||
self._SYNTH_3D_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._SYNTH_3D_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
def _set_remotefx_display_controller(self, vm, remotefx_disp_ctrl_res,
|
||||
monitor_count, max_resolution,
|
||||
vram_bytes=None):
|
||||
new_wmi_obj = False
|
||||
if not remotefx_disp_ctrl_res:
|
||||
new_wmi_obj = True
|
||||
remotefx_disp_ctrl_res = self._get_new_resource_setting_data(
|
||||
self._REMOTEFX_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._REMOTEFX_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
|
||||
synth_3d_disp_ctrl_res.MaximumMonitors = monitor_count
|
||||
synth_3d_disp_ctrl_res.MaximumScreenResolution = max_resolution
|
||||
remotefx_disp_ctrl_res.MaximumMonitors = monitor_count
|
||||
remotefx_disp_ctrl_res.MaximumScreenResolution = max_resolution
|
||||
self._set_remotefx_vram(remotefx_disp_ctrl_res, vram_bytes)
|
||||
|
||||
self._jobutils.add_virt_resource(synth_3d_disp_ctrl_res, vm)
|
||||
if new_wmi_obj:
|
||||
self._jobutils.add_virt_resource(remotefx_disp_ctrl_res, vm)
|
||||
else:
|
||||
self._jobutils.modify_virt_resource(remotefx_disp_ctrl_res)
|
||||
|
||||
def _set_remotefx_vram(self, remotefx_disp_ctrl_res, vram_bytes):
|
||||
pass
|
||||
|
||||
def enable_remotefx_video_adapter(self, vm_name, monitor_count,
|
||||
max_resolution, vram_bytes=None):
|
||||
vm = self._lookup_vm_check(vm_name, as_vssd=False)
|
||||
|
||||
self._validate_remotefx_params(monitor_count, max_resolution,
|
||||
vram_bytes=vram_bytes)
|
||||
|
||||
vm = self._lookup_vm_check(vm_name)
|
||||
rasds = _wqlutils.get_element_associated_class(
|
||||
self._compat_conn, self._CIM_RES_ALLOC_SETTING_DATA_CLASS,
|
||||
element_uuid=vm.Name)
|
||||
if [r for r in rasds if r.ResourceSubType ==
|
||||
self._SYNTH_3D_DISP_CTRL_RES_SUB_TYPE]:
|
||||
raise exceptions.HyperVRemoteFXException(
|
||||
_("RemoteFX is already configured for this VM"))
|
||||
element_instance_id=vm.InstanceID)
|
||||
|
||||
synth_disp_ctrl_res_list = [r for r in rasds if r.ResourceSubType ==
|
||||
self._SYNTH_DISP_CTRL_RES_SUB_TYPE]
|
||||
if synth_disp_ctrl_res_list:
|
||||
# we need to remove the generic display controller first.
|
||||
self._jobutils.remove_virt_resource(synth_disp_ctrl_res_list[0])
|
||||
|
||||
remotefx_disp_ctrl_res = [r for r in rasds if r.ResourceSubType ==
|
||||
self._REMOTEFX_DISP_CTRL_RES_SUB_TYPE]
|
||||
remotefx_disp_ctrl_res = (remotefx_disp_ctrl_res[0]
|
||||
if remotefx_disp_ctrl_res else None)
|
||||
|
||||
max_res_value = self._remote_fx_res_map.get(max_resolution)
|
||||
self._add_3d_display_controller(vm, monitor_count, max_res_value,
|
||||
vram_bytes)
|
||||
if self._vm_has_s3_controller(vm.ElementName):
|
||||
self._set_remotefx_display_controller(
|
||||
vm, remotefx_disp_ctrl_res, monitor_count, max_res_value,
|
||||
vram_bytes)
|
||||
|
||||
if self._vm_has_s3_controller(vm_name):
|
||||
s3_disp_ctrl_res = [r for r in rasds if r.ResourceSubType ==
|
||||
self._S3_DISP_CTRL_RES_SUB_TYPE][0]
|
||||
s3_disp_ctrl_res.Address = self._DISP_CTRL_ADDRESS_DX_11
|
||||
if s3_disp_ctrl_res.Address != self._DISP_CTRL_ADDRESS_DX_11:
|
||||
s3_disp_ctrl_res.Address = self._DISP_CTRL_ADDRESS_DX_11
|
||||
self._jobutils.modify_virt_resource(s3_disp_ctrl_res)
|
||||
|
||||
def disable_remotefx_video_adapter(self, vm_name):
|
||||
vm = self._lookup_vm_check(vm_name)
|
||||
rasds = _wqlutils.get_element_associated_class(
|
||||
self._compat_conn, self._CIM_RES_ALLOC_SETTING_DATA_CLASS,
|
||||
element_instance_id=vm.InstanceID)
|
||||
|
||||
remotefx_disp_ctrl_res = [r for r in rasds if r.ResourceSubType ==
|
||||
self._REMOTEFX_DISP_CTRL_RES_SUB_TYPE]
|
||||
|
||||
if not remotefx_disp_ctrl_res:
|
||||
# VM does not have RemoteFX configured.
|
||||
return
|
||||
|
||||
# we need to remove the RemoteFX display controller first.
|
||||
self._jobutils.remove_virt_resource(remotefx_disp_ctrl_res[0])
|
||||
|
||||
synth_disp_ctrl_res = self._get_new_resource_setting_data(
|
||||
self._SYNTH_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._SYNTH_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
self._jobutils.add_virt_resource(synth_disp_ctrl_res, vm)
|
||||
|
||||
if self._vm_has_s3_controller(vm_name):
|
||||
s3_disp_ctrl_res = [r for r in rasds if r.ResourceSubType ==
|
||||
self._S3_DISP_CTRL_RES_SUB_TYPE][0]
|
||||
s3_disp_ctrl_res.Address = self._DISP_CTRL_ADDRESS
|
||||
self._jobutils.modify_virt_resource(s3_disp_ctrl_res)
|
||||
|
||||
def _vm_has_s3_controller(self, vm_name):
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import re
|
||||
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
|
||||
from os_win._i18n import _
|
||||
from os_win import constants
|
||||
|
@ -112,26 +113,16 @@ class VMUtils10(vmutils.VMUtils):
|
|||
vram_bytes=None):
|
||||
super(VMUtils10, self)._validate_remotefx_params(monitor_count,
|
||||
max_resolution)
|
||||
if vram_bytes not in self._remotefx_vram_vals:
|
||||
if vram_bytes and vram_bytes not in self._remotefx_vram_vals:
|
||||
raise exceptions.HyperVRemoteFXException(
|
||||
_("Unsuported RemoteFX VRAM value: %(requested_value)s."
|
||||
"The supported VRAM values are: %(supported_values)s") %
|
||||
{'requested_value': vram_bytes,
|
||||
'supported_values': self._remotefx_vram_vals})
|
||||
|
||||
def _add_3d_display_controller(self, vm, monitor_count,
|
||||
max_resolution, vram_bytes=None):
|
||||
synth_3d_disp_ctrl_res = self._get_new_resource_setting_data(
|
||||
self._SYNTH_3D_DISP_CTRL_RES_SUB_TYPE,
|
||||
self._SYNTH_3D_DISP_ALLOCATION_SETTING_DATA_CLASS)
|
||||
|
||||
synth_3d_disp_ctrl_res.MaximumMonitors = monitor_count
|
||||
synth_3d_disp_ctrl_res.MaximumScreenResolution = max_resolution
|
||||
|
||||
def _set_remotefx_vram(self, remotefx_disp_ctrl_res, vram_bytes):
|
||||
if vram_bytes:
|
||||
synth_3d_disp_ctrl_res.VRAMSizeBytes = unicode(vram_bytes)
|
||||
|
||||
self._jobutils.add_virt_resource(synth_3d_disp_ctrl_res, vm)
|
||||
remotefx_disp_ctrl_res.VRAMSizeBytes = six.text_type(vram_bytes)
|
||||
|
||||
def _vm_has_s3_controller(self, vm_name):
|
||||
return self.get_vm_generation(vm_name) == constants.VM_GEN_1
|
||||
|
|
Loading…
Reference in New Issue