Merge "XenAPI: Add the mechanism to attach a pci device to a VM."
This commit is contained in:
@@ -19,6 +19,7 @@ import mock
|
||||
from nova.compute import power_state
|
||||
from nova.compute import task_states
|
||||
from nova import exception
|
||||
from nova.pci import pci_manager
|
||||
from nova import test
|
||||
from nova.tests.virt.xenapi import stubs
|
||||
from nova.virt import fake
|
||||
@@ -216,6 +217,8 @@ class SpawnTestCase(VMOpsTestBase):
|
||||
self.mox.StubOutWithMock(self.vmops, '_create_vm_record')
|
||||
self.mox.StubOutWithMock(self.vmops, '_destroy')
|
||||
self.mox.StubOutWithMock(self.vmops, '_attach_disks')
|
||||
self.mox.StubOutWithMock(pci_manager, 'get_instance_pci_devs')
|
||||
self.mox.StubOutWithMock(vm_utils, 'set_other_config_pci')
|
||||
self.mox.StubOutWithMock(self.vmops, '_attach_orig_disk_for_rescue')
|
||||
self.mox.StubOutWithMock(self.vmops, 'inject_network_info')
|
||||
self.mox.StubOutWithMock(self.vmops, '_inject_hostname')
|
||||
@@ -236,8 +239,8 @@ class SpawnTestCase(VMOpsTestBase):
|
||||
'apply_instance_filter')
|
||||
|
||||
def _test_spawn(self, name_label_param=None, block_device_info_param=None,
|
||||
rescue=False, include_root_vdi=True,
|
||||
throw_exception=None):
|
||||
rescue=False, include_root_vdi=True, throw_exception=None,
|
||||
attach_pci_dev=False):
|
||||
self._stub_out_common()
|
||||
|
||||
instance = {"name": "dummy", "uuid": "fake_uuid"}
|
||||
@@ -293,6 +296,30 @@ class SpawnTestCase(VMOpsTestBase):
|
||||
|
||||
self.vmops._attach_disks(instance, vm_ref, name_label, vdis, di_type,
|
||||
network_info, admin_password, injected_files)
|
||||
if attach_pci_dev:
|
||||
fake_dev = {
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': None,
|
||||
'id': 1,
|
||||
'compute_node_id': 1,
|
||||
'address': '00:00.0',
|
||||
'vendor_id': '1234',
|
||||
'product_id': 'abcd',
|
||||
'dev_type': 'type-PCI',
|
||||
'status': 'available',
|
||||
'dev_id': 'devid',
|
||||
'label': 'label',
|
||||
'instance_uuid': None,
|
||||
'extra_info': '{}',
|
||||
}
|
||||
pci_manager.get_instance_pci_devs(instance).AndReturn([fake_dev])
|
||||
vm_utils.set_other_config_pci(self.vmops._session,
|
||||
vm_ref,
|
||||
"0/0000:00:00.0")
|
||||
else:
|
||||
pci_manager.get_instance_pci_devs(instance).AndReturn([])
|
||||
step += 1
|
||||
self.vmops._update_instance_progress(context, instance, step, steps)
|
||||
|
||||
@@ -354,6 +381,9 @@ class SpawnTestCase(VMOpsTestBase):
|
||||
name_label_param="bob",
|
||||
block_device_info_param={"root_device_name": ""})
|
||||
|
||||
def test_spawn_with_pci_available_on_the_host(self):
|
||||
self._test_spawn(attach_pci_dev=True)
|
||||
|
||||
def test_spawn_performs_rollback_and_throws_exception(self):
|
||||
self.assertRaises(test.TestingException, self._test_spawn,
|
||||
throw_exception=test.TestingException())
|
||||
@@ -401,6 +431,7 @@ class SpawnTestCase(VMOpsTestBase):
|
||||
self.vmops._attach_disks(instance, vm_ref, name_label, vdis, di_type,
|
||||
network_info, None, None)
|
||||
self.vmops._attach_mapped_block_devices(instance, block_device_info)
|
||||
pci_manager.get_instance_pci_devs(instance).AndReturn([])
|
||||
|
||||
self.vmops._inject_instance_metadata(instance, vm_ref)
|
||||
self.vmops._inject_auto_disk_config(instance, vm_ref)
|
||||
|
||||
@@ -2722,3 +2722,10 @@ def handle_ipxe_iso(session, instance, cd_vdi, network_info):
|
||||
CONF.xenserver.ipxe_mkisofs_cmd, instance=instance)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def set_other_config_pci(session, vm_ref, params):
|
||||
"""Set the pci key of other-config parameter to params."""
|
||||
other_config = session.call_xenapi("VM.get_other_config", vm_ref)
|
||||
other_config['pci'] = params
|
||||
session.call_xenapi("VM.set_other_config", vm_ref, other_config)
|
||||
|
||||
@@ -44,6 +44,7 @@ from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import strutils
|
||||
from nova.openstack.common import timeutils
|
||||
from nova.openstack.common import units
|
||||
from nova.pci import pci_manager
|
||||
from nova import utils
|
||||
from nova.virt import configdrive
|
||||
from nova.virt import driver as virt_driver
|
||||
@@ -368,6 +369,48 @@ class VMOps(object):
|
||||
self._ensure_instance_name_unique(name_label)
|
||||
self._ensure_enough_free_mem(instance)
|
||||
|
||||
def attach_disks(undo_mgr, vm_ref, vdis, disk_image_type):
|
||||
try:
|
||||
ipxe_boot = strutils.bool_from_string(
|
||||
image_meta['properties']['ipxe_boot'])
|
||||
except KeyError:
|
||||
ipxe_boot = False
|
||||
|
||||
if ipxe_boot:
|
||||
if 'iso' in vdis:
|
||||
vm_utils.handle_ipxe_iso(
|
||||
self._session, instance, vdis['iso'], network_info)
|
||||
else:
|
||||
LOG.warning(_('ipxe_boot is True but no ISO image found'),
|
||||
instance=instance)
|
||||
|
||||
if resize:
|
||||
self._resize_up_vdis(instance, vdis)
|
||||
|
||||
self._attach_disks(instance, vm_ref, name_label, vdis,
|
||||
disk_image_type, network_info, admin_password,
|
||||
injected_files)
|
||||
if not first_boot:
|
||||
self._attach_mapped_block_devices(instance,
|
||||
block_device_info)
|
||||
|
||||
def attach_pci_devices(undo_mgr, vm_ref):
|
||||
dev_to_passthrough = ""
|
||||
devices = pci_manager.get_instance_pci_devs(instance)
|
||||
for d in devices:
|
||||
pci_address = d["address"]
|
||||
if pci_address.count(":") == 1:
|
||||
pci_address = "0000:" + pci_address
|
||||
dev_to_passthrough += ",0/" + pci_address
|
||||
|
||||
# Remove the first comma if string is not empty.
|
||||
# Note(guillaume-thouvenin): If dev_to_passthrough is empty, we
|
||||
# don't need to update other_config.
|
||||
if dev_to_passthrough:
|
||||
vm_utils.set_other_config_pci(self._session,
|
||||
vm_ref,
|
||||
dev_to_passthrough[1:])
|
||||
|
||||
@step
|
||||
def determine_disk_image_type_step(undo_mgr):
|
||||
return vm_utils.determine_disk_image_type(image_meta)
|
||||
@@ -398,30 +441,9 @@ class VMOps(object):
|
||||
return vm_ref
|
||||
|
||||
@step
|
||||
def attach_disks_step(undo_mgr, vm_ref, vdis, disk_image_type):
|
||||
try:
|
||||
ipxe_boot = strutils.bool_from_string(
|
||||
image_meta['properties']['ipxe_boot'])
|
||||
except KeyError:
|
||||
ipxe_boot = False
|
||||
|
||||
if ipxe_boot:
|
||||
if 'iso' in vdis:
|
||||
vm_utils.handle_ipxe_iso(
|
||||
self._session, instance, vdis['iso'], network_info)
|
||||
else:
|
||||
LOG.warning(_('ipxe_boot is True but no ISO image found'),
|
||||
instance=instance)
|
||||
|
||||
if resize:
|
||||
self._resize_up_vdis(instance, vdis)
|
||||
|
||||
self._attach_disks(instance, vm_ref, name_label, vdis,
|
||||
disk_image_type, network_info, admin_password,
|
||||
injected_files)
|
||||
if not first_boot:
|
||||
self._attach_mapped_block_devices(instance,
|
||||
block_device_info)
|
||||
def attach_devices_step(undo_mgr, vm_ref, vdis, disk_image_type):
|
||||
attach_disks(undo_mgr, vm_ref, vdis, disk_image_type)
|
||||
attach_pci_devices(undo_mgr, vm_ref)
|
||||
|
||||
if rescue:
|
||||
# NOTE(johannes): Attach root disk to rescue VM now, before
|
||||
@@ -486,7 +508,7 @@ class VMOps(object):
|
||||
|
||||
vm_ref = create_vm_record_step(undo_mgr, disk_image_type,
|
||||
kernel_file, ramdisk_file)
|
||||
attach_disks_step(undo_mgr, vm_ref, vdis, disk_image_type)
|
||||
attach_devices_step(undo_mgr, vm_ref, vdis, disk_image_type)
|
||||
|
||||
inject_instance_data_step(undo_mgr, vm_ref, vdis)
|
||||
setup_network_step(undo_mgr, vm_ref)
|
||||
|
||||
Reference in New Issue
Block a user