Define cross-driver standardized vm_mode values

Currently the XenAPI driver allows for a 'vm_mode' parameter to
be set against an instance to determine whether it is launched
a paravirt or fullvirt domain. This allows the values 'pv', 'hv'
and 'hvm'.

The libvirt driver also needs to be extended to allow a 'vm_mode'
parameter, and to facilitate deployment of heterogeneous Nova
compute farms, it is desirable to have standardization of the
VM mode values across all drivers.

To address this, the nova.compute.vm_mode module is introduced
which defines a set of constants. The constants provide four
possible vm modes:

 - vm_mode.XEN = 'xen' - for Xen 3.0 paravirt ABI
 - vm_mode.HVM = 'hvm' - for native ABI
 - vm_mode.UML = 'uml' - for User Mode Linux paravirt ABI
 - vm_mode.EXE = 'exe' - for container virt executable ABI

The existing 'pv' value from XenAPI is deprecated, because it
is ambiguous - both Xen and UML are paravirt, and other
paravirt hypervisor ABIs also exist

The existing 'hv' value is also deprecated since it duplicates
the other existing 'hvm' value.

The 'vm_mode.get_from_instance' method will extract the
vm_mode value for an instance. It normalizes the value to
all lower case, translates 'hv' and 'pv' into the new
values for back compat, and validates that the value
matches one of the defined constants

The XenAPI and libvirt drivers are then updated to use the
nova.compute.vm_mode constants instead of bare strings.
The test_xenapi.py test case is updated to set 'vm_mode'
to exercise the new codepaths. A new test_vmmode.py
case is also written to fully exercise the logic

NB, previously the libvirt driver would set 'guest.os_type'
to 'linux' to request Xen paravirt. This is a legacy value,
with libvirt preferring the string 'xen'. So although the
new code sets a different value for Xen paravirt os_type,
the functional result is unchanged.

DocImpact
blueprint hypervisor-code-consolidation
Change-Id: I23efc5dc1528b0d8472d752a8a30f55c85310b21
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange
2012-07-25 13:32:28 +01:00
parent 6b133b2b37
commit 33af1c9d8b
3 changed files with 68 additions and 8 deletions

View File

@@ -32,6 +32,7 @@ from nova.compute import instance_types
from nova.compute import power_state
from nova.compute import rpcapi as compute_rpcapi
from nova.compute import utils as compute_utils
from nova.compute import vm_mode
from nova.compute import vm_states
from nova import context
from nova import db
@@ -508,7 +509,7 @@ class LibvirtConnTestCase(test.TestCase):
self.assertEquals(cfg.acpi, True)
self.assertEquals(cfg.memory, 1024 * 1024 * 2)
self.assertEquals(cfg.vcpus, 1)
self.assertEquals(cfg.os_type, "hvm")
self.assertEquals(cfg.os_type, vm_mode.HVM)
self.assertEquals(cfg.os_boot_dev, "hd")
self.assertEquals(cfg.os_root, None)
self.assertEquals(len(cfg.devices), 7)
@@ -552,7 +553,7 @@ class LibvirtConnTestCase(test.TestCase):
self.assertEquals(cfg.acpi, True)
self.assertEquals(cfg.memory, 1024 * 1024 * 2)
self.assertEquals(cfg.vcpus, 1)
self.assertEquals(cfg.os_type, "hvm")
self.assertEquals(cfg.os_type, vm_mode.HVM)
self.assertEquals(cfg.os_boot_dev, "hd")
self.assertEquals(cfg.os_root, None)
self.assertEquals(len(cfg.devices), 8)
@@ -1363,18 +1364,22 @@ class LibvirtConnTestCase(test.TestCase):
type_uri_map = {'qemu': ('qemu:///system',
[(lambda t: t.find('.').get('type'), 'qemu'),
(lambda t: t.find('./os/type').text, 'hvm'),
(lambda t: t.find('./os/type').text,
vm_mode.HVM),
(lambda t: t.find('./devices/emulator'), None)]),
'kvm': ('qemu:///system',
[(lambda t: t.find('.').get('type'), 'kvm'),
(lambda t: t.find('./os/type').text, 'hvm'),
(lambda t: t.find('./os/type').text,
vm_mode.HVM),
(lambda t: t.find('./devices/emulator'), None)]),
'uml': ('uml:///system',
[(lambda t: t.find('.').get('type'), 'uml'),
(lambda t: t.find('./os/type').text, 'uml')]),
(lambda t: t.find('./os/type').text,
vm_mode.UML)]),
'xen': ('xen:///',
[(lambda t: t.find('.').get('type'), 'xen'),
(lambda t: t.find('./os/type').text, 'linux')]),
(lambda t: t.find('./os/type').text,
vm_mode.XEN)]),
}
for hypervisor_type in ['qemu', 'kvm', 'xen']:
@@ -2149,12 +2154,12 @@ class LibvirtConnTestCase(test.TestCase):
caps.host.cpu = cpu
guest = config.LibvirtConfigGuest()
guest.ostype = "hvm"
guest.ostype = vm_mode.HVM
guest.arch = "x86_64"
caps.guests.append(guest)
guest = config.LibvirtConfigGuest()
guest.ostype = "hvm"
guest.ostype = vm_mode.HVM
guest.arch = "i686"
caps.guests.append(guest)

54
nova/tests/test_vmmode.py Normal file
View File

@@ -0,0 +1,54 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2012 Red Hat, Inc.
#
# 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 import exception
from nova import test
from nova.compute import vm_mode
class ComputeVMModeTest(test.TestCase):
class testinstance(object):
def __init__(self, mode):
self.vm_mode = mode
def test_case(self):
inst = ComputeVMModeTest.testinstance("HVM")
mode = vm_mode.get_from_instance(inst)
self.assertEqual(mode, "hvm")
def test_legacy_pv(self):
inst = ComputeVMModeTest.testinstance("pv")
mode = vm_mode.get_from_instance(inst)
self.assertEqual(mode, "xen")
def test_legacy_hv(self):
inst = ComputeVMModeTest.testinstance("hv")
mode = vm_mode.get_from_instance(inst)
self.assertEqual(mode, "hvm")
def test_bogus(self):
inst = ComputeVMModeTest.testinstance("wibble")
self.assertRaises(exception.Invalid,
vm_mode.get_from_instance,
inst)
def test_good(self):
inst = ComputeVMModeTest.testinstance("hvm")
mode = vm_mode.get_from_instance(inst)
self.assertEqual(mode, "hvm")

View File

@@ -849,6 +849,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
'root_gb': 20,
'instance_type_id': '3', # m1.large
'os_type': 'linux',
'vm_mode': 'hvm',
'architecture': 'x86-64'}
instance = db.instance_create(self.context, instance_values)
network_info = fake_network.fake_get_instance_nw_info(self.stubs,