Skip to content

Commit

Permalink
virt: use compute.virttype constants and validate virt type
Browse files Browse the repository at this point in the history
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
  • Loading branch information
berrange committed Sep 12, 2014
1 parent 348ef10 commit a4fd236
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 34 deletions.
3 changes: 3 additions & 0 deletions nova/compute/hvtype.py
Expand Up @@ -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)

Expand Down
3 changes: 2 additions & 1 deletion nova/scheduler/filters/image_props_filter.py
Expand Up @@ -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
Expand Down Expand Up @@ -46,7 +47,7 @@ def _instance_supported(self, host_state, image_props,
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)
)

Expand Down
3 changes: 3 additions & 0 deletions nova/tests/compute/test_hvtype.py
Expand Up @@ -34,6 +34,9 @@ def test_canonicalize_none(self):
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,
Expand Down
59 changes: 42 additions & 17 deletions nova/tests/scheduler/test_host_filters.py
Expand Up @@ -23,6 +23,7 @@
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
Expand Down Expand Up @@ -672,13 +673,14 @@ def test_image_properties_filter_passes_same_inst_props_and_version(self):
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))
Expand All @@ -687,11 +689,12 @@ def test_image_properties_filter_fails_different_inst_props(self):
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))
Expand All @@ -700,13 +703,14 @@ def test_image_properties_filter_fails_different_hyper_version(self):
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))
Expand All @@ -718,7 +722,8 @@ def test_image_properties_filter_passes_partial_inst_props(self):
'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))
Expand All @@ -730,7 +735,8 @@ def test_image_properties_filter_fails_partial_inst_props(self):
'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))
Expand All @@ -740,7 +746,8 @@ def test_image_properties_filter_passes_without_inst_props(self):
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))
Expand All @@ -749,7 +756,7 @@ def test_image_properties_filter_fails_without_host_props(self):
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')
Expand All @@ -762,25 +769,27 @@ def test_image_properties_filter_passes_without_hyper_version(self):
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))

def test_image_properties_filter_fails_with_unsupported_hyper_ver(self):
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))
Expand All @@ -792,7 +801,8 @@ def test_image_properties_filter_pv_mode_compat(self):
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))
Expand All @@ -804,7 +814,8 @@ def test_image_properties_filter_hvm_mode_compat(self):
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))
Expand All @@ -816,7 +827,21 @@ def test_image_properties_filter_xen_arch_compat(self):
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))
Expand Down
9 changes: 5 additions & 4 deletions nova/tests/virt/xenapi/test_xenapi.py
Expand Up @@ -29,6 +29,7 @@
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
Expand Down Expand Up @@ -2168,18 +2169,18 @@ def test_default_return_value(self):
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'])
)
Expand Down
3 changes: 2 additions & 1 deletion nova/virt/baremetal/driver.py
Expand Up @@ -24,6 +24,7 @@

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
Expand Down Expand Up @@ -153,7 +154,7 @@ def __init__(self, virtapi, read_only=False):
else:
self.supported_instances = [(
arch.canonicalize(extra_specs['cpu_arch']),
'baremetal',
hvtype.BAREMETAL,
'baremetal'
), ]

Expand Down
11 changes: 6 additions & 5 deletions nova/virt/hyperv/hostops.py
Expand Up @@ -24,6 +24,7 @@
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
Expand Down Expand Up @@ -129,9 +130,9 @@ def get_available_resource(self):
'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,
}

Expand All @@ -154,8 +155,8 @@ def _update_stats(self):
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
Expand Down
3 changes: 2 additions & 1 deletion nova/virt/libvirt/driver.py
Expand Up @@ -53,6 +53,7 @@
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
Expand Down Expand Up @@ -4492,7 +4493,7 @@ def _get_instance_capabilities(self):
for dt in g.domtype:
instance_cap = (
arch.canonicalize(g.arch),
dt,
hvtype.canonicalize(dt),
g.ostype)
instance_caps.append(instance_cap)

Expand Down
11 changes: 7 additions & 4 deletions nova/virt/vmwareapi/host.py
Expand Up @@ -18,6 +18,7 @@
"""

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
Expand Down Expand Up @@ -90,8 +91,9 @@ def update_status(self):
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
Expand Down Expand Up @@ -140,8 +142,9 @@ def update_status(self):
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
3 changes: 2 additions & 1 deletion nova/virt/xenapi/host.py
Expand Up @@ -22,6 +22,7 @@
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
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit a4fd236

Please sign in to comment.