virt: use compute.virttype constants and validate virt type

Where we have hardcoded hypervisor types, use compute.hvtype
constants. Where we get hypervisor types from external systems,
validate them against the list of acceptable names.

The Xen hypervisor is reporting a virt type of 'xapi' for
supported instances which is confusing the virtualization
type with the hypervisor API access method. It should be
reporting 'xen' as the virtualization type.

On the other side, the ImagePropertiesFilter will canonicalize
the hvtype it fetches from image metadata, so that 'xapi' gets
remapped to 'xen' during comparison.

Upgrade-impact: the hyervisor type will intentionally no longer
  distinguish libvirt Xen from XenAPI within a compute cloud.
  The driver name should be used instead
Closes-bug: #1348623
Change-Id: I2c740e8eb068a5d93ba5f72292fb30d899931ea5
This commit is contained in:
Daniel P. Berrange 2014-07-25 11:46:04 +01:00
parent 348ef1006e
commit a4fd236baa
10 changed files with 74 additions and 34 deletions

View File

@ -87,6 +87,9 @@ def canonicalize(name):
newname = name.lower()
if newname == "xapi":
newname = XEN
if not is_valid(newname):
raise exception.InvalidHypervisorVirtType(hvtype=name)

View File

@ -17,6 +17,7 @@
from distutils import versionpredicate
from nova.compute import arch
from nova.compute import hvtype
from nova.compute import vm_mode
from nova.openstack.common import log as logging
from nova.scheduler import filters
@ -46,7 +47,7 @@ class ImagePropertiesFilter(filters.BaseHostFilter):
img_vm_mode = image_props.get('vm_mode', None)
checked_img_props = (
arch.canonicalize(img_arch),
img_h_type,
hvtype.canonicalize(img_h_type),
vm_mode.name(img_vm_mode)
)

View File

@ -34,6 +34,9 @@ class HvTypeTest(test.NoDBTestCase):
def test_canonicalize_case(self):
self.assertEqual(hvtype.QEMU, hvtype.canonicalize("QeMu"))
def test_canonicalize_xapi(self):
self.assertEqual(hvtype.XEN, hvtype.canonicalize("xapi"))
def test_canonicalize_invalid(self):
self.assertRaises(exception.InvalidHypervisorVirtType,
hvtype.canonicalize,

View File

@ -23,6 +23,7 @@ import six
import stubout
from nova.compute import arch
from nova.compute import hvtype
from nova import context
from nova import db
from nova.openstack.common import jsonutils
@ -672,13 +673,14 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'_architecture': arch.X86_64,
'hypervisor_type': 'kvm',
'hypervisor_type': hvtype.KVM,
'vm_mode': 'hvm',
'hypervisor_version_requires': '>=6.0,<6.2'
}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -687,11 +689,12 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'architecture': arch.ARMV7,
'hypervisor_type': 'qemu',
'hypervisor_type': hvtype.QEMU,
'vm_mode': 'hvm'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertFalse(filt_cls.host_passes(host, filter_properties))
@ -700,13 +703,14 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'architecture': arch.X86_64,
'hypervisor_type': 'kvm',
'hypervisor_type': hvtype.KVM,
'vm_mode': 'hvm',
'hypervisor_version_requires': '>=6.2'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'enabled': True,
'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertFalse(filt_cls.host_passes(host, filter_properties))
@ -718,7 +722,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
'vm_mode': 'hvm'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -730,7 +735,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
'vm_mode': 'hvm'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'xen', 'xen')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.XEN, 'xen')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertFalse(filt_cls.host_passes(host, filter_properties))
@ -740,7 +746,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
filt_cls = self.class_map['ImagePropertiesFilter']()
filter_properties = {'request_spec': {}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -749,7 +756,7 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'architecture': arch.X86_64,
'hypervisor_type': 'kvm',
'hypervisor_type': hvtype.KVM,
'vm_mode': 'hvm'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
@ -762,12 +769,13 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'architecture': arch.X86_64,
'hypervisor_type': 'kvm',
'hypervisor_type': hvtype.KVM,
'vm_mode': 'hvm',
'hypervisor_version_requires': '>=6.0'}}
filter_properties = {'request_spec': {'image': img_props}}
capabilities = {'enabled': True,
'supported_instances': [(arch.X86_64, 'kvm', 'hvm')]}
'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')]}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -775,12 +783,13 @@ class HostFiltersTestCase(test.NoDBTestCase):
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'architecture': arch.X86_64,
'hypervisor_type': 'kvm',
'hypervisor_type': hvtype.KVM,
'vm_mode': 'hvm',
'hypervisor_version_requires': '>=6.0'}}
filter_properties = {'request_spec': {'image': img_props}}
capabilities = {'enabled': True,
'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': 5000}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertFalse(filt_cls.host_passes(host, filter_properties))
@ -792,7 +801,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
img_props = {'properties': {'vm_mode': 'pv'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'xapi', 'xen')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.XEN, 'xen')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -804,7 +814,8 @@ class HostFiltersTestCase(test.NoDBTestCase):
img_props = {'properties': {'vm_mode': 'hv'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.X86_64, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.X86_64, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
@ -816,7 +827,21 @@ class HostFiltersTestCase(test.NoDBTestCase):
img_props = {'properties': {'architecture': 'x86_32'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances': [(arch.I686, 'kvm', 'hvm')],
capabilities = {'supported_instances':
[(arch.I686, hvtype.KVM, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))
def test_image_properties_filter_xen_hvtype_compat(self):
# if an old image has 'xapi' for hvtype it should be treated as xen
self._stub_service_is_up(True)
filt_cls = self.class_map['ImagePropertiesFilter']()
img_props = {'properties': {'hypervisor_type': 'xapi'}}
filter_properties = {'request_spec': {'image': img_props}}
hypervisor_version = utils.convert_version_to_int('6.0.0')
capabilities = {'supported_instances':
[(arch.I686, hvtype.XEN, 'hvm')],
'hypervisor_version': hypervisor_version}
host = fakes.FakeHostState('host1', 'node1', capabilities)
self.assertTrue(filt_cls.host_passes(host, filter_properties))

View File

@ -29,6 +29,7 @@ from oslo.config import cfg
from nova.compute import api as compute_api
from nova.compute import arch
from nova.compute import flavors
from nova.compute import hvtype
from nova.compute import power_state
from nova.compute import task_states
from nova.compute import utils as compute_utils
@ -2168,18 +2169,18 @@ class ToSupportedInstancesTestCase(test.NoDBTestCase):
host.to_supported_instances(None))
def test_return_value(self):
self.assertEqual([(arch.X86_64, 'xapi', 'xen')],
self.assertEqual([(arch.X86_64, hvtype.XEN, 'xen')],
host.to_supported_instances([u'xen-3.0-x86_64']))
def test_invalid_values_do_not_break(self):
self.assertEqual([(arch.X86_64, 'xapi', 'xen')],
self.assertEqual([(arch.X86_64, hvtype.XEN, 'xen')],
host.to_supported_instances([u'xen-3.0-x86_64', 'spam']))
def test_multiple_values(self):
self.assertEqual(
[
(arch.X86_64, 'xapi', 'xen'),
(arch.I686, 'xapi', 'hvm')
(arch.X86_64, hvtype.XEN, 'xen'),
(arch.I686, hvtype.XEN, 'hvm')
],
host.to_supported_instances([u'xen-3.0-x86_64', 'hvm-3.0-x86_32'])
)

View File

@ -24,6 +24,7 @@ from oslo.config import cfg
from nova.compute import arch
from nova.compute import flavors
from nova.compute import hvtype
from nova.compute import power_state
from nova.compute import task_states
from nova import context as nova_context
@ -153,7 +154,7 @@ class BareMetalDriver(driver.ComputeDriver):
else:
self.supported_instances = [(
arch.canonicalize(extra_specs['cpu_arch']),
'baremetal',
hvtype.BAREMETAL,
'baremetal'
), ]

View File

@ -24,6 +24,7 @@ import time
from oslo.config import cfg
from nova.compute import arch
from nova.compute import hvtype
from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging
from nova.openstack.common import units
@ -129,9 +130,9 @@ class HostOps(object):
'hypervisor_hostname': platform.node(),
'vcpus_used': 0,
'cpu_info': jsonutils.dumps(cpu_info),
'supported_instances': jsonutils.dumps(
[(arch.I686, 'hyperv', 'hvm'),
(arch.X86_64, 'hyperv', 'hvm')]),
'supported_instances': jsonutils.dumps(
[(arch.I686, hvtype.HYPERV, 'hvm'),
(arch.X86_64, hvtype.HYPERV, 'hvm')]),
'numa_topology': None,
}
@ -154,8 +155,8 @@ class HostOps(object):
data["host_memory_free"] = free_mem_mb
data["host_memory_free_computed"] = free_mem_mb
data["supported_instances"] = [
(arch.I686, 'hyperv', 'hvm'),
(arch.X86_64, 'hyperv', 'hvm')]
(arch.I686, hvtype.HYPERV, 'hvm'),
(arch.X86_64, hvtype.HYPERV, 'hvm')]
data["hypervisor_hostname"] = platform.node()
self._stats = data

View File

@ -53,6 +53,7 @@ from nova.api.metadata import base as instance_metadata
from nova import block_device
from nova.compute import arch
from nova.compute import flavors
from nova.compute import hvtype
from nova.compute import power_state
from nova.compute import task_states
from nova.compute import utils as compute_utils
@ -4492,7 +4493,7 @@ class LibvirtDriver(driver.ComputeDriver):
for dt in g.domtype:
instance_cap = (
arch.canonicalize(g.arch),
dt,
hvtype.canonicalize(dt),
g.ostype)
instance_caps.append(instance_cap)

View File

@ -18,6 +18,7 @@ Management class for host-related functions (start, reboot, etc).
"""
from nova.compute import arch
from nova.compute import hvtype
from nova import exception
from nova.openstack.common import log as logging
from nova.openstack.common import units
@ -90,8 +91,9 @@ class HostState(object):
data["hypervisor_version"] = utils.convert_version_to_int(
str(summary.config.product.version))
data["hypervisor_hostname"] = self._host_name
data["supported_instances"] = [(arch.I686, 'vmware', 'hvm'),
(arch.X86_64, 'vmware', 'hvm')]
data["supported_instances"] = [
(arch.I686, hvtype.VMWARE, 'hvm'),
(arch.X86_64, hvtype.VMWARE, 'hvm')]
self._stats = data
return data
@ -140,8 +142,9 @@ class VCState(object):
data["hypervisor_version"] = utils.convert_version_to_int(
str(about_info.version))
data["hypervisor_hostname"] = self._host_name
data["supported_instances"] = [(arch.I686, 'vmware', 'hvm'),
(arch.X86_64, 'vmware', 'hvm')]
data["supported_instances"] = [
(arch.I686, hvtype.VMWARE, 'hvm'),
(arch.X86_64, hvtype.VMWARE, 'hvm')]
self._stats = data
return data

View File

@ -22,6 +22,7 @@ import re
from oslo.config import cfg
from nova.compute import arch
from nova.compute import hvtype
from nova.compute import task_states
from nova.compute import vm_states
from nova import context
@ -285,7 +286,7 @@ def to_supported_instances(host_capabilities):
guestarch = arch.canonicalize(guestarch)
result.append((guestarch, 'xapi', ostype))
result.append((guestarch, hvtype.XEN, ostype))
except ValueError:
LOG.warning(
_("Failed to extract instance support from %s"), capability)