summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nova/tests/test_xenapi.py120
-rw-r--r--nova/tests/virt/xenapi/test_vmops.py153
-rw-r--r--nova/tests/xenapi/test_vm_utils.py80
-rw-r--r--nova/virt/xenapi/fake.py15
-rw-r--r--nova/virt/xenapi/vm_utils.py25
-rw-r--r--nova/virt/xenapi/vmops.py60
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']