diff options
-rw-r--r-- | nova/tests/test_xenapi.py | 120 | ||||
-rw-r--r-- | nova/tests/virt/xenapi/test_vmops.py | 153 | ||||
-rw-r--r-- | nova/tests/xenapi/test_vm_utils.py | 80 | ||||
-rw-r--r-- | nova/virt/xenapi/fake.py | 15 | ||||
-rw-r--r-- | nova/virt/xenapi/vm_utils.py | 25 | ||||
-rw-r--r-- | nova/virt/xenapi/vmops.py | 60 |
6 files changed, 350 insertions, 103 deletions
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 8d00aa924..474fd1eb9 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -689,8 +689,6 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): hostname="test", architecture="x86-64", instance_id=1, injected_files=None, check_injection=False, create_record=True, empty_dns=False, - image_meta={'id': IMAGE_VHD, - 'disk_format': 'vhd'}, block_device_info=None, key_data=None): if injected_files is None: @@ -726,6 +724,9 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): # NOTE(tr3buchet): this is a terrible way to do this... network_info[0]['network']['subnets'][0]['dns'] = [] + image_meta = {} + if image_ref: + image_meta = IMAGE_FIXTURES[image_ref]["image_meta"] self.conn.spawn(self.context, instance, image_meta, injected_files, 'herp', network_info, block_device_info) self.create_vm_record(self.conn, os_type, instance['name']) @@ -743,7 +744,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): def test_spawn_not_enough_memory(self): self.assertRaises(exception.InsufficientFreeMemory, self._test_spawn, - 1, 2, 3, "4") # m1.xlarge + '1', 2, 3, "4") # m1.xlarge def test_spawn_fail_cleanup_1(self): """Simulates an error while downloading an image. @@ -754,7 +755,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): start_vms = self._list_vms() stubs.stubout_fetch_disk_image(self.stubs, raise_failure=True) self.assertRaises(xenapi_fake.Failure, - self._test_spawn, 1, 2, 3) + self._test_spawn, '1', 2, 3) # No additional VDI should be found. vdi_recs_end = self._list_vdis() end_vms = self._list_vms() @@ -771,7 +772,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): start_vms = self._list_vms() stubs.stubout_create_vm(self.stubs) self.assertRaises(xenapi_fake.Failure, - self._test_spawn, 1, 2, 3) + self._test_spawn, '1', 2, 3) # No additional VDI should be found. vdi_recs_end = self._list_vdis() end_vms = self._list_vms() @@ -788,7 +789,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): vdi_recs_start = self._list_vdis() start_vms = self._list_vms() self.assertRaises(xenapi_fake.Failure, - self._test_spawn, 1, 2, 3) + self._test_spawn, '1', 2, 3) # No additional VDI should be found. vdi_recs_end = self._list_vdis() end_vms = self._list_vms() @@ -817,7 +818,19 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): self.check_vm_params_for_windows() def test_spawn_glance(self): - stubs.stubout_fetch_disk_image(self.stubs) + + def fake_fetch_disk_image(context, session, instance, name_label, + image_id, image_type): + sr_ref = vm_utils.safe_find_sr(session) + image_type_str = vm_utils.ImageType.to_string(image_type) + vdi_ref = vm_utils.create_vdi(session, sr_ref, instance, + name_label, image_type_str, "20") + vdi_role = vm_utils.ImageType.get_role(image_type) + vdi_uuid = session.call_xenapi("VDI.get_uuid", vdi_ref) + return {vdi_role: dict(uuid=vdi_uuid, file=None)} + self.stubs.Set(vm_utils, '_fetch_disk_image', + fake_fetch_disk_image) + self._test_spawn(IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK) @@ -826,7 +839,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): def test_spawn_boot_from_volume_no_image_meta(self): dev_info = get_fake_device_info() self._test_spawn(None, None, None, - image_meta={}, block_device_info=dev_info) + block_device_info=dev_info) def test_spawn_boot_from_volume_with_image_meta(self): dev_info = get_fake_device_info() @@ -908,7 +921,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): (r'mount', _mount_handler), (r'umount', _umount_handler), (r'tee.*interfaces', _tee_handler)]) - self._test_spawn(1, 2, 3, check_injection=True) + self._test_spawn('1', 2, 3, check_injection=True) # tee must not run in this case, where an injection-capable # guest agent is detected @@ -1808,22 +1821,27 @@ class XenAPIGenerateLocal(stubs.XenAPITestBase): def fake_create_vbd(session, vm_ref, vdi_ref, userdevice, vbd_type='disk', read_only=False, bootable=True, - osvol=False): - pass + osvol=False, empty=False, unpluggable=True): + return session.call_xenapi('VBD.create', {'VM': vm_ref, + 'VDI': vdi_ref}) self.stubs.Set(vm_utils, 'create_vbd', fake_create_vbd) - def assertCalled(self, instance): + def assertCalled(self, instance, + disk_image_type=vm_utils.ImageType.DISK_VHD): ctx = context.RequestContext(self.user_id, self.project_id) session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass', fake.FakeVirtAPI()) - disk_image_type = vm_utils.ImageType.DISK_VHD vm_ref = xenapi_fake.create_vm(instance['name'], 'Halted') vdi_ref = xenapi_fake.create_vdi(instance['name'], 'fake') vdi_uuid = session.call_xenapi('VDI.get_record', vdi_ref)['uuid'] - vdis = {'root': {'uuid': vdi_uuid, 'ref': vdi_ref}} + + vdi_key = 'root' + if disk_image_type == vm_utils.ImageType.DISK_ISO: + vdi_key = 'iso' + vdis = {vdi_key: {'uuid': vdi_uuid, 'ref': vdi_ref}} self.called = False self.conn._vmops._attach_disks(instance, vm_ref, instance['name'], @@ -1854,6 +1872,24 @@ class XenAPIGenerateLocal(stubs.XenAPITestBase): self.assertCalled(instance) + def test_generate_iso_blank_root_disk(self): + instance_values = dict(self.instance_values, instance_type_id=4) + instance_values.pop('kernel_id') + instance_values.pop('ramdisk_id') + instance = create_instance_with_system_metadata(self.context, + instance_values) + + def fake_generate_ephemeral(*args): + pass + self.stubs.Set(vm_utils, 'generate_ephemeral', fake_generate_ephemeral) + + def fake_generate_iso(*args): + self.called = True + self.stubs.Set(vm_utils, 'generate_iso_blank_root_disk', + fake_generate_iso) + + self.assertCalled(instance, vm_utils.ImageType.DISK_ISO) + class XenAPIBWCountersTestCase(stubs.XenAPITestBase): FAKE_VMS = {'test1:ref': dict(name_label='test1', @@ -3201,62 +3237,6 @@ class XenAPIInjectMetadataTestCase(stubs.XenAPITestBase): }) -class VMOpsTestCase(test.TestCase): - def _get_mock_session(self, product_brand, product_version): - class Mock(object): - pass - - mock_session = Mock() - mock_session.product_brand = product_brand - mock_session.product_version = product_version - - return mock_session - - def test_check_resize_func_name_defaults_to_VDI_resize(self): - session = self._get_mock_session(None, None) - ops = vmops.VMOps(session, fake.FakeVirtAPI()) - - self.assertEquals( - 'VDI.resize', - ops.check_resize_func_name()) - - def _test_finish_revert_migration_after_crash(self, backup_made, new_made): - instance = {'name': 'foo', - 'task_state': task_states.RESIZE_MIGRATING} - session = self._get_mock_session(None, None) - ops = vmops.VMOps(session, fake.FakeVirtAPI()) - - self.mox.StubOutWithMock(vm_utils, 'lookup') - self.mox.StubOutWithMock(ops, '_destroy') - self.mox.StubOutWithMock(vm_utils, 'set_vm_name_label') - self.mox.StubOutWithMock(ops, '_attach_mapped_block_devices') - self.mox.StubOutWithMock(ops, '_start') - - vm_utils.lookup(session, 'foo-orig').AndReturn( - backup_made and 'foo' or None) - vm_utils.lookup(session, 'foo').AndReturn( - (not backup_made or new_made) and 'foo' or None) - if backup_made: - if new_made: - ops._destroy(instance, 'foo') - vm_utils.set_vm_name_label(session, 'foo', 'foo') - ops._attach_mapped_block_devices(instance, []) - ops._start(instance, 'foo') - - self.mox.ReplayAll() - - ops.finish_revert_migration(instance, []) - - def test_finish_revert_migration_after_crash(self): - self._test_finish_revert_migration_after_crash(True, True) - - def test_finish_revert_migration_after_crash_before_new(self): - self._test_finish_revert_migration_after_crash(True, False) - - def test_finish_revert_migration_after_crash_before_backup(self): - self._test_finish_revert_migration_after_crash(False, False) - - class XenAPISessionTestCase(test.TestCase): def _get_mock_xapisession(self, software_version): class XcpXapiSession(xenapi_conn.XenAPISession): diff --git a/nova/tests/virt/xenapi/test_vmops.py b/nova/tests/virt/xenapi/test_vmops.py new file mode 100644 index 000000000..1acc4d515 --- /dev/null +++ b/nova/tests/virt/xenapi/test_vmops.py @@ -0,0 +1,153 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 OpenStack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from nova.compute import task_states +from nova.compute import vm_mode +from nova import test +from nova.virt import fake +from nova.virt.xenapi import vm_utils +from nova.virt.xenapi import vmops + + +class VMOpsTestCase(test.TestCase): + def setUp(self): + super(VMOpsTestCase, self).setUp() + self._setup_mock_vmops() + + def _setup_mock_vmops(self, product_brand=None, product_version=None): + self._session = self._get_mock_session(product_brand, product_version) + self._vmops = vmops.VMOps(self._session, fake.FakeVirtAPI()) + + def _get_mock_session(self, product_brand, product_version): + class Mock(object): + pass + + mock_session = Mock() + mock_session.product_brand = product_brand + mock_session.product_version = product_version + return mock_session + + def test_check_resize_func_name_defaults_to_VDI_resize(self): + self.assertEquals( + 'VDI.resize', + self._vmops.check_resize_func_name()) + + def _test_finish_revert_migration_after_crash(self, backup_made, new_made): + instance = {'name': 'foo', + 'task_state': task_states.RESIZE_MIGRATING} + + self.mox.StubOutWithMock(vm_utils, 'lookup') + self.mox.StubOutWithMock(self._vmops, '_destroy') + self.mox.StubOutWithMock(vm_utils, 'set_vm_name_label') + self.mox.StubOutWithMock(self._vmops, '_attach_mapped_block_devices') + self.mox.StubOutWithMock(self._vmops, '_start') + + vm_utils.lookup(self._session, 'foo-orig').AndReturn( + backup_made and 'foo' or None) + vm_utils.lookup(self._session, 'foo').AndReturn( + (not backup_made or new_made) and 'foo' or None) + if backup_made: + if new_made: + self._vmops._destroy(instance, 'foo') + vm_utils.set_vm_name_label(self._session, 'foo', 'foo') + self._vmops._attach_mapped_block_devices(instance, []) + self._vmops._start(instance, 'foo') + + self.mox.ReplayAll() + + self._vmops.finish_revert_migration(instance, []) + + def test_finish_revert_migration_after_crash(self): + self._test_finish_revert_migration_after_crash(True, True) + + def test_finish_revert_migration_after_crash_before_new(self): + self._test_finish_revert_migration_after_crash(True, False) + + def test_finish_revert_migration_after_crash_before_backup(self): + self._test_finish_revert_migration_after_crash(False, False) + + def test_determine_vm_mode_returns_xen(self): + self.mox.StubOutWithMock(vm_mode, 'get_from_instance') + + fake_instance = "instance" + vm_mode.get_from_instance(fake_instance).AndReturn(vm_mode.XEN) + + self.mox.ReplayAll() + self.assertEquals(vm_mode.XEN, + self._vmops._determine_vm_mode(fake_instance, None, None)) + self.mox.VerifyAll() + + def test_determine_vm_mode_returns_hvm(self): + self.mox.StubOutWithMock(vm_mode, 'get_from_instance') + + fake_instance = "instance" + vm_mode.get_from_instance(fake_instance).AndReturn(vm_mode.HVM) + + self.mox.ReplayAll() + self.assertEquals(vm_mode.HVM, + self._vmops._determine_vm_mode(fake_instance, None, None)) + self.mox.VerifyAll() + + def test_determine_vm_mode_returns_is_pv(self): + self.mox.StubOutWithMock(vm_mode, 'get_from_instance') + self.mox.StubOutWithMock(vm_utils, 'determine_is_pv') + + fake_instance = {"os_type": "foo"} + fake_vdis = {'root': {"ref": 'fake'}} + fake_disk_type = "disk" + vm_mode.get_from_instance(fake_instance).AndReturn(None) + vm_utils.determine_is_pv(self._session, "fake", fake_disk_type, + "foo").AndReturn(True) + + self.mox.ReplayAll() + self.assertEquals(vm_mode.XEN, + self._vmops._determine_vm_mode(fake_instance, fake_vdis, + fake_disk_type)) + self.mox.VerifyAll() + + def test_determine_vm_mode_returns_is_not_pv(self): + self.mox.StubOutWithMock(vm_mode, 'get_from_instance') + self.mox.StubOutWithMock(vm_utils, 'determine_is_pv') + + fake_instance = {"os_type": "foo"} + fake_vdis = {'root': {"ref": 'fake'}} + fake_disk_type = "disk" + vm_mode.get_from_instance(fake_instance).AndReturn(None) + vm_utils.determine_is_pv(self._session, "fake", fake_disk_type, + "foo").AndReturn(False) + + self.mox.ReplayAll() + self.assertEquals(vm_mode.HVM, + self._vmops._determine_vm_mode(fake_instance, fake_vdis, + fake_disk_type)) + self.mox.VerifyAll() + + def test_determine_vm_mode_returns_is_not_pv_no_root_disk(self): + self.mox.StubOutWithMock(vm_mode, 'get_from_instance') + self.mox.StubOutWithMock(vm_utils, 'determine_is_pv') + + fake_instance = {"os_type": "foo"} + fake_vdis = {'iso': {"ref": 'fake'}} + fake_disk_type = "disk" + vm_mode.get_from_instance(fake_instance).AndReturn(None) + + self.mox.ReplayAll() + self.assertEquals(vm_mode.HVM, + self._vmops._determine_vm_mode(fake_instance, fake_vdis, + fake_disk_type)) + self.mox.VerifyAll() diff --git a/nova/tests/xenapi/test_vm_utils.py b/nova/tests/xenapi/test_vm_utils.py index a701efdd9..1f540709e 100644 --- a/nova/tests/xenapi/test_vm_utils.py +++ b/nova/tests/xenapi/test_vm_utils.py @@ -204,3 +204,83 @@ class BittorrentTestCase(stubs.XenAPITestBase): def test_create_image_uncached(self): self._test_create_image('none') + + +class CreateVBDTestCase(test.TestCase): + def setUp(self): + super(CreateVBDTestCase, self).setUp() + + class FakeSession(): + def call_xenapi(*args): + pass + + self.session = FakeSession() + self.mock = mox.Mox() + self.mock.StubOutWithMock(self.session, 'call_xenapi') + self.vbd_rec = self._generate_vbd_rec() + + def _generate_vbd_rec(self): + vbd_rec = {} + vbd_rec['VM'] = 'vm_ref' + vbd_rec['VDI'] = 'vdi_ref' + vbd_rec['userdevice'] = '0' + vbd_rec['bootable'] = False + vbd_rec['mode'] = 'RW' + vbd_rec['type'] = 'disk' + vbd_rec['unpluggable'] = True + vbd_rec['empty'] = False + vbd_rec['other_config'] = {} + vbd_rec['qos_algorithm_type'] = '' + vbd_rec['qos_algorithm_params'] = {} + vbd_rec['qos_supported_algorithms'] = [] + return vbd_rec + + def test_create_vbd_default_args(self): + self.session.call_xenapi('VBD.create', + self.vbd_rec).AndReturn("vbd_ref") + self.mock.ReplayAll() + + result = vm_utils.create_vbd(self.session, "vm_ref", "vdi_ref", 0) + self.assertEquals(result, "vbd_ref") + self.mock.VerifyAll() + + def test_create_vbd_osvol(self): + self.session.call_xenapi('VBD.create', + self.vbd_rec).AndReturn("vbd_ref") + self.session.call_xenapi('VBD.add_to_other_config', "vbd_ref", + "osvol", "True") + self.mock.ReplayAll() + result = vm_utils.create_vbd(self.session, "vm_ref", "vdi_ref", 0, + osvol=True) + self.assertEquals(result, "vbd_ref") + self.mock.VerifyAll() + + def test_create_vbd_extra_args(self): + self.vbd_rec['VDI'] = 'OpaqueRef:NULL' + self.vbd_rec['type'] = 'a' + self.vbd_rec['mode'] = 'RO' + self.vbd_rec['bootable'] = True + self.vbd_rec['empty'] = True + self.vbd_rec['unpluggable'] = False + self.session.call_xenapi('VBD.create', + self.vbd_rec).AndReturn("vbd_ref") + self.mock.ReplayAll() + + result = vm_utils.create_vbd(self.session, "vm_ref", None, 0, + vbd_type="a", read_only=True, bootable=True, + empty=True, unpluggable=False) + self.assertEquals(result, "vbd_ref") + self.mock.VerifyAll() + + def test_attach_cd(self): + self.mock.StubOutWithMock(vm_utils, 'create_vbd') + + vm_utils.create_vbd(self.session, "vm_ref", None, 1, + vbd_type='cd', read_only=True, bootable=True, + empty=True, unpluggable=False).AndReturn("vbd_ref") + self.session.call_xenapi('VBD.insert', "vbd_ref", "vdi_ref") + self.mock.ReplayAll() + + result = vm_utils.attach_cd(self.session, "vm_ref", "vdi_ref", 1) + self.assertEquals(result, "vbd_ref") + self.mock.VerifyAll() diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py index bdadfbc38..eeea9d11c 100644 --- a/nova/virt/xenapi/fake.py +++ b/nova/virt/xenapi/fake.py @@ -206,13 +206,14 @@ def after_VBD_create(vbd_ref, vbd_rec): vm_rec = _db_content['VM'][vm_ref] vm_rec['VBDs'].append(vbd_ref) - vdi_ref = vbd_rec['VDI'] - vdi_rec = _db_content['VDI'][vdi_ref] - vdi_rec['VBDs'].append(vbd_ref) - vm_name_label = _db_content['VM'][vm_ref]['name_label'] vbd_rec['vm_name_label'] = vm_name_label + vdi_ref = vbd_rec['VDI'] + if vdi_ref and vdi_ref != "OpaqueRef:NULL": + vdi_rec = _db_content['VDI'][vdi_ref] + vdi_rec['VBDs'].append(vbd_ref) + def after_VM_create(vm_ref, vm_rec): """Create read-only fields in the VM record.""" @@ -401,6 +402,12 @@ class SessionBase(object): def pool_get_default_SR(self, _1, pool_ref): return 'FAKE DEFAULT SR' + def VBD_insert(self, _1, vbd_ref, vdi_ref): + vbd_rec = get_record('VBD', vbd_ref) + get_record('VDI', vdi_ref) + vbd_rec['empty'] = False + vbd_rec['VDI'] = vdi_ref + def VBD_plug(self, _1, ref): rec = get_record('VBD', ref) if rec['currently_attached']: diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 99e7712c8..bae9676f2 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -387,17 +387,20 @@ def destroy_vbd(session, vbd_ref): def create_vbd(session, vm_ref, vdi_ref, userdevice, vbd_type='disk', - read_only=False, bootable=False, osvol=False): + read_only=False, bootable=False, osvol=False, + empty=False, unpluggable=True): """Create a VBD record and returns its reference.""" vbd_rec = {} vbd_rec['VM'] = vm_ref + if vdi_ref == None: + vdi_ref = 'OpaqueRef:NULL' vbd_rec['VDI'] = vdi_ref vbd_rec['userdevice'] = str(userdevice) vbd_rec['bootable'] = bootable vbd_rec['mode'] = read_only and 'RO' or 'RW' vbd_rec['type'] = vbd_type - vbd_rec['unpluggable'] = True - vbd_rec['empty'] = False + vbd_rec['unpluggable'] = unpluggable + vbd_rec['empty'] = empty vbd_rec['other_config'] = {} vbd_rec['qos_algorithm_type'] = '' vbd_rec['qos_algorithm_params'] = {} @@ -415,6 +418,16 @@ def create_vbd(session, vm_ref, vdi_ref, userdevice, vbd_type='disk', return vbd_ref +def attach_cd(session, vm_ref, vdi_ref, userdevice): + """Create an empty VBD, then insert the CD.""" + vbd_ref = create_vbd(session, vm_ref, None, userdevice, + vbd_type='cd', read_only=True, + bootable=True, empty=True, + unpluggable=False) + session.call_xenapi('VBD.insert', vbd_ref, vdi_ref) + return vbd_ref + + def destroy_vdi(session, vdi_ref): try: session.call_xenapi('VDI.destroy', vdi_ref) @@ -837,6 +850,12 @@ def generate_ephemeral(session, instance, vm_ref, userdevice, name_label, CONF.default_ephemeral_format) +def generate_iso_blank_root_disk(session, instance, vm_ref, userdevice, + name_label, size_gb): + _generate_disk(session, instance, vm_ref, userdevice, name_label, + 'user', size_gb * 1024, CONF.default_ephemeral_format) + + def generate_configdrive(session, instance, vm_ref, userdevice, admin_password=None, files=None): sr_ref = safe_find_sr(session) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index ca1aa46cc..d8f750e0a 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -81,9 +81,14 @@ RESIZE_TOTAL_STEPS = 5 DEVICE_ROOT = '0' DEVICE_RESCUE = '1' DEVICE_SWAP = '2' -DEVICE_EPHEMERAL = '3' -DEVICE_CD = '4' -DEVICE_CONFIGDRIVE = '5' +DEVICE_CONFIGDRIVE = '3' +# Note(johngarbutt) HVM guests only support four devices +# until the PV tools activate, when others before available +# As such, ephemeral disk only available once PV tools load +DEVICE_EPHEMERAL = '4' +# Note(johngarbutt) Currently don't support ISO boot during rescue +# and we must have the ISO visible before the PV drivers start +DEVICE_CD = '1' def cmp_version(a, b): @@ -529,25 +534,33 @@ class VMOps(object): if not vm_utils.ensure_free_mem(self._session, instance): raise exception.InsufficientFreeMemory(uuid=instance['uuid']) - mode = vm_mode.get_from_instance(instance) - if mode == vm_mode.XEN: - use_pv_kernel = True - elif mode == vm_mode.HVM: - use_pv_kernel = False - else: - use_pv_kernel = vm_utils.determine_is_pv(self._session, - vdis['root']['ref'], disk_image_type, instance['os_type']) - mode = use_pv_kernel and vm_mode.XEN or vm_mode.HVM - + mode = self._determine_vm_mode(instance, vdis, disk_image_type) if instance['vm_mode'] != mode: # Update database with normalized (or determined) value self._virtapi.instance_update(context, instance['uuid'], {'vm_mode': mode}) + use_pv_kernel = (mode == vm_mode.XEN) vm_ref = vm_utils.create_vm(self._session, instance, name_label, kernel_file, ramdisk_file, use_pv_kernel) return vm_ref + def _determine_vm_mode(self, instance, vdis, disk_image_type): + current_mode = vm_mode.get_from_instance(instance) + if current_mode == vm_mode.XEN or current_mode == vm_mode.HVM: + return current_mode + + is_pv = False + if 'root' in vdis: + os_type = instance['os_type'] + vdi_ref = vdis['root']['ref'] + is_pv = vm_utils.determine_is_pv(self._session, vdi_ref, + disk_image_type, os_type) + if is_pv: + return vm_mode.XEN + else: + return vm_mode.HVM + def _attach_disks(self, instance, vm_ref, name_label, vdis, disk_image_type, admin_password=None, files=None): ctx = nova_context.get_admin_context() @@ -556,19 +569,14 @@ class VMOps(object): # Attach (required) root disk if disk_image_type == vm_utils.ImageType.DISK_ISO: # DISK_ISO needs two VBDs: the ISO disk and a blank RW disk - LOG.debug(_("Detected ISO image type, creating blank VM " - "for install"), instance=instance) - - cd_vdi = vdis.pop('root') - root_vdi = vm_utils.fetch_blank_disk(self._session, - instance_type['id']) - vdis['root'] = root_vdi - - vm_utils.create_vbd(self._session, vm_ref, root_vdi['ref'], - DEVICE_ROOT, bootable=False) - - vm_utils.create_vbd(self._session, vm_ref, cd_vdi['ref'], - DEVICE_CD, vbd_type='CD', bootable=True) + root_disk_size = instance_type['root_gb'] + if root_disk_size > 0: + vm_utils.generate_iso_blank_root_disk(self._session, instance, + vm_ref, DEVICE_ROOT, name_label, root_disk_size) + + cd_vdi = vdis.pop('iso') + vm_utils.attach_cd(self._session, vm_ref, cd_vdi['ref'], + DEVICE_CD) else: root_vdi = vdis['root'] |