Merge "Refactoring required for blueprint xenapi-live-migration"

This commit is contained in:
Jenkins 2012-07-16 20:38:14 +00:00 committed by Gerrit Code Review
commit 9a283c6b37
4 changed files with 298 additions and 451 deletions

View File

@ -212,36 +212,30 @@ class Scheduler(object):
The host where instance is running currently. The host where instance is running currently.
Then scheduler send request that host. Then scheduler send request that host.
""" """
# Whether instance exists and is running. # Check we can do live migration
instance_ref = db.instance_get(context, instance_id) instance_ref = db.instance_get(context, instance_id)
# Checking instance.
self._live_migration_src_check(context, instance_ref) self._live_migration_src_check(context, instance_ref)
self._live_migration_dest_check(context, instance_ref, dest)
self._live_migration_common_check(context, instance_ref, dest)
self.compute_rpcapi.check_can_live_migrate_destination(context,
instance_ref, dest, block_migration, disk_over_commit)
# Checking destination host. # Change instance_state
self._live_migration_dest_check(context, instance_ref,
dest, block_migration,
disk_over_commit)
# Common checking.
self._live_migration_common_check(context, instance_ref,
dest, block_migration,
disk_over_commit)
# Changing instance_state.
values = {"task_state": task_states.MIGRATING} values = {"task_state": task_states.MIGRATING}
# update instance state and notify # update instance state and notify
(old_ref, new_instance_ref) = db.instance_update_and_get_original( (old_ref, new_instance_ref) = db.instance_update_and_get_original(
context, instance_id, values) context, instance_ref['uuid'], values)
notifications.send_update(context, old_ref, new_instance_ref, notifications.send_update(context, old_ref, new_instance_ref,
service="scheduler") service="scheduler")
# Perform migration
src = instance_ref['host'] src = instance_ref['host']
cast_to_compute_host(context, src, 'live_migration', cast_to_compute_host(context, src, 'live_migration',
update_db=False, update_db=False,
instance_id=instance_id, instance_id=instance_id,
dest=dest, dest=dest,
block_migration=block_migration) block_migration=block_migration)
def _live_migration_src_check(self, context, instance_ref): def _live_migration_src_check(self, context, instance_ref):
"""Live migration check routine (for src host). """Live migration check routine (for src host).
@ -250,7 +244,7 @@ class Scheduler(object):
:param instance_ref: nova.db.sqlalchemy.models.Instance object :param instance_ref: nova.db.sqlalchemy.models.Instance object
""" """
# TODO(johngar) why is this not in the API layer?
# Checking instance is running. # Checking instance is running.
if instance_ref['power_state'] != power_state.RUNNING: if instance_ref['power_state'] != power_state.RUNNING:
raise exception.InstanceNotRunning( raise exception.InstanceNotRunning(
@ -258,22 +252,21 @@ class Scheduler(object):
# Checking src host exists and compute node # Checking src host exists and compute node
src = instance_ref['host'] src = instance_ref['host']
services = db.service_get_all_compute_by_host(context, src) try:
services = db.service_get_all_compute_by_host(context, src)
except exception.NotFound:
raise exception.ComputeServiceUnavailable(host=src)
# Checking src host is alive. # Checking src host is alive.
if not utils.service_is_up(services[0]): if not utils.service_is_up(services[0]):
raise exception.ComputeServiceUnavailable(host=src) raise exception.ComputeServiceUnavailable(host=src)
def _live_migration_dest_check(self, context, instance_ref, dest, def _live_migration_dest_check(self, context, instance_ref, dest):
block_migration, disk_over_commit):
"""Live migration check routine (for destination host). """Live migration check routine (for destination host).
:param context: security context :param context: security context
:param instance_ref: nova.db.sqlalchemy.models.Instance object :param instance_ref: nova.db.sqlalchemy.models.Instance object
:param dest: destination host :param dest: destination host
:param block_migration: if true, block_migration.
:param disk_over_commit: if True, consider real(not virtual)
disk size.
""" """
# Checking dest exists and compute node. # Checking dest exists and compute node.
@ -291,15 +284,11 @@ class Scheduler(object):
raise exception.UnableToMigrateToSelf( raise exception.UnableToMigrateToSelf(
instance_id=instance_ref['uuid'], host=dest) instance_id=instance_ref['uuid'], host=dest)
# Checking dst host still has enough capacities. # Check memory requirements
self.assert_compute_node_has_enough_resources(context, self._assert_compute_node_has_enough_memory(context,
instance_ref, instance_ref, dest)
dest,
block_migration,
disk_over_commit)
def _live_migration_common_check(self, context, instance_ref, dest, def _live_migration_common_check(self, context, instance_ref, dest):
block_migration, disk_over_commit):
"""Live migration common check routine. """Live migration common check routine.
Below checkings are followed by Below checkings are followed by
@ -308,38 +297,10 @@ class Scheduler(object):
:param context: security context :param context: security context
:param instance_ref: nova.db.sqlalchemy.models.Instance object :param instance_ref: nova.db.sqlalchemy.models.Instance object
:param dest: destination host :param dest: destination host
:param block_migration: if true, block_migration.
:param disk_over_commit: if True, consider real(not virtual)
disk size.
""" """
dservice_ref = self._get_compute_info(context, dest)
# Checking shared storage connectivity src = instance_ref['host']
# if block migration, instances_paths should not be on shared storage. oservice_ref = self._get_compute_info(context, src)
shared = self.mounted_on_same_shared_storage(context, instance_ref,
dest)
if block_migration:
if shared:
reason = _("Block migration can not be used "
"with shared storage.")
raise exception.InvalidSharedStorage(reason=reason, path=dest)
elif not shared:
reason = _("Live migration can not be used "
"without shared storage.")
raise exception.InvalidSharedStorage(reason=reason, path=dest)
# Checking destination host exists.
dservice_refs = db.service_get_all_compute_by_host(context, dest)
dservice_ref = dservice_refs[0]['compute_node'][0]
# Checking original host( where instance was launched at) exists.
try:
oservice_refs = db.service_get_all_compute_by_host(context,
instance_ref['host'])
except exception.NotFound:
raise exception.SourceHostUnavailable()
oservice_ref = oservice_refs[0]['compute_node'][0]
# Checking hypervisor is same. # Checking hypervisor is same.
orig_hypervisor = oservice_ref['hypervisor_type'] orig_hypervisor = oservice_ref['hypervisor_type']
@ -353,40 +314,7 @@ class Scheduler(object):
if orig_hypervisor > dest_hypervisor: if orig_hypervisor > dest_hypervisor:
raise exception.DestinationHypervisorTooOld() raise exception.DestinationHypervisorTooOld()
# Checking cpuinfo. def _assert_compute_node_has_enough_memory(self, context,
try:
self.compute_rpcapi.compare_cpu(context, oservice_ref['cpu_info'],
dest)
except exception.InvalidCPUInfo:
src = instance_ref['host']
LOG.exception(_("host %(dest)s is not compatible with "
"original host %(src)s.") % locals())
raise
def assert_compute_node_has_enough_resources(self, context, instance_ref,
dest, block_migration,
disk_over_commit):
"""Checks if destination host has enough resource for live migration.
:param context: security context
:param instance_ref: nova.db.sqlalchemy.models.Instance object
:param dest: destination host
:param block_migration: if true, block_migration.
:param disk_over_commit: if True, consider real(not virtual)
disk size.
"""
self.assert_compute_node_has_enough_memory(context,
instance_ref, dest)
if not block_migration:
return
self.assert_compute_node_has_enough_disk(context,
instance_ref, dest,
disk_over_commit)
def assert_compute_node_has_enough_memory(self, context,
instance_ref, dest): instance_ref, dest):
"""Checks if destination host has enough memory for live migration. """Checks if destination host has enough memory for live migration.
@ -397,7 +325,7 @@ class Scheduler(object):
""" """
# Getting total available memory of host # Getting total available memory of host
avail = self._get_compute_info(context, dest, 'memory_mb') avail = self._get_compute_info(context, dest)['memory_mb']
# Getting total used memory and disk of host # Getting total used memory and disk of host
# It should be sum of memories that are assigned as max value, # It should be sum of memories that are assigned as max value,
@ -414,54 +342,7 @@ class Scheduler(object):
"instance:%(mem_inst)s)") "instance:%(mem_inst)s)")
raise exception.MigrationError(reason=reason % locals()) raise exception.MigrationError(reason=reason % locals())
def assert_compute_node_has_enough_disk(self, context, instance_ref, dest, def _get_compute_info(self, context, host):
disk_over_commit):
"""Checks if destination host has enough disk for block migration.
:param context: security context
:param instance_ref: nova.db.sqlalchemy.models.Instance object
:param dest: destination host
:param disk_over_commit: if True, consider real(not virtual)
disk size.
"""
# Libvirt supports qcow2 disk format,which is usually compressed
# on compute nodes.
# Real disk image (compressed) may enlarged to "virtual disk size",
# that is specified as the maximum disk size.
# (See qemu-img -f path-to-disk)
# Scheduler recognizes destination host still has enough disk space
# if real disk size < available disk size
# if disk_over_commit is True,
# otherwise virtual disk size < available disk size.
# Getting total available disk of host
available_gb = self._get_compute_info(context,
dest, 'disk_available_least')
available = available_gb * (1024 ** 3)
# Getting necessary disk size
ret = self.compute_rpcapi.get_instance_disk_info(context, instance_ref)
disk_infos = jsonutils.loads(ret)
necessary = 0
if disk_over_commit:
for info in disk_infos:
necessary += int(info['disk_size'])
else:
for info in disk_infos:
necessary += int(info['virt_disk_size'])
# Check that available disk > necessary disk
if (available - necessary) < 0:
instance_uuid = instance_ref['uuid']
reason = _("Unable to migrate %(instance_uuid)s to %(dest)s: "
"Lack of disk(host:%(available)s "
"<= instance:%(necessary)s)")
raise exception.MigrationError(reason=reason % locals())
def _get_compute_info(self, context, host, key):
"""get compute node's information specified by key """get compute node's information specified by key
:param context: security context :param context: security context
@ -471,33 +352,4 @@ class Scheduler(object):
""" """
compute_node_ref = db.service_get_all_compute_by_host(context, host) compute_node_ref = db.service_get_all_compute_by_host(context, host)
compute_node_ref = compute_node_ref[0]['compute_node'][0] return compute_node_ref[0]['compute_node'][0]
return compute_node_ref[key]
def mounted_on_same_shared_storage(self, context, instance_ref, dest):
"""Check if the src and dest host mount same shared storage.
At first, dest host creates temp file, and src host can see
it if they mounts same shared storage. Then src host erase it.
:param context: security context
:param instance_ref: nova.db.sqlalchemy.models.Instance object
:param dest: destination host
"""
src = instance_ref['host']
filename = self.compute_rpcapi.create_shared_storage_test_file(context,
dest)
try:
# make sure existence at src host.
ret = self.compute_rpcapi.check_shared_storage_test_file(context,
filename, src)
finally:
self.compute_rpcapi.cleanup_shared_storage_test_file(context,
filename, dest)
return ret

View File

@ -28,6 +28,7 @@ from nova import context
from nova import db from nova import db
from nova import exception from nova import exception
from nova import flags from nova import flags
from nova import notifications
from nova.openstack.common import jsonutils from nova.openstack.common import jsonutils
from nova.openstack.common import rpc from nova.openstack.common import rpc
from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common.rpc import common as rpc_common
@ -440,23 +441,32 @@ class SchedulerTestCase(test.TestCase):
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_common_check') self.mox.StubOutWithMock(self.driver, '_live_migration_common_check')
self.mox.StubOutWithMock(self.driver.compute_rpcapi,
'check_can_live_migrate_destination')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
self.mox.StubOutWithMock(driver, 'cast_to_compute_host') self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
self.mox.StubOutWithMock(notifications, 'send_update')
dest = 'fake_host2' dest = 'fake_host2'
block_migration = False block_migration = False
disk_over_commit = False disk_over_commit = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
instance_uuid = instance['uuid']
db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance, self.driver._live_migration_dest_check(self.context, instance, dest)
dest, block_migration, disk_over_commit)
self.driver._live_migration_common_check(self.context, instance, self.driver._live_migration_common_check(self.context, instance,
dest, block_migration, disk_over_commit) dest)
db.instance_update_and_get_original(self.context, instance['id'], self.driver.compute_rpcapi.check_can_live_migrate_destination(
self.context, instance, dest, block_migration, disk_over_commit)
db.instance_update_and_get_original(self.context, instance_uuid,
{"task_state": task_states.MIGRATING}).AndReturn( {"task_state": task_states.MIGRATING}).AndReturn(
(instance, instance)) (instance, instance))
notifications.send_update(self.context, instance, instance,
service="scheduler")
driver.cast_to_compute_host(self.context, instance['host'], driver.cast_to_compute_host(self.context, instance['host'],
'live_migration', update_db=False, 'live_migration', update_db=False,
@ -469,38 +479,13 @@ class SchedulerTestCase(test.TestCase):
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
def _check_shared_storage(self, dest, instance, check_result):
tmp_filename = 'test-filename'
rpc.queue_get_for(self.context, FLAGS.compute_topic,
dest).AndReturn('dest_queue')
rpc.call(self.context, 'dest_queue',
{'method': 'create_shared_storage_test_file',
'args': {},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
None).AndReturn(tmp_filename)
rpc.queue_get_for(self.context, FLAGS.compute_topic,
instance['host']).AndReturn('src_queue')
rpc.call(self.context, 'src_queue',
{'method': 'check_shared_storage_test_file',
'args': {'filename': tmp_filename},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
None).AndReturn(check_result)
rpc.queue_get_for(self.context, FLAGS.compute_topic,
dest).AndReturn('dest_queue')
rpc.cast(self.context, 'dest_queue',
{'method': 'cleanup_shared_storage_test_file',
'args': {'filename': tmp_filename},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION})
def test_live_migration_all_checks_pass(self): def test_live_migration_all_checks_pass(self):
"""Test live migration when all checks pass.""" """Test live migration when all checks pass."""
self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(utils, 'service_is_up') self.mox.StubOutWithMock(utils, 'service_is_up')
self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host') self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host')
self.mox.StubOutWithMock(self.driver, '_get_compute_info')
self.mox.StubOutWithMock(db, 'instance_get_all_by_host') self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'call') self.mox.StubOutWithMock(rpc, 'call')
self.mox.StubOutWithMock(rpc, 'cast') self.mox.StubOutWithMock(rpc, 'cast')
self.mox.StubOutWithMock(db, 'instance_update_and_get_original') self.mox.StubOutWithMock(db, 'instance_update_and_get_original')
@ -510,8 +495,12 @@ class SchedulerTestCase(test.TestCase):
block_migration = True block_migration = True
disk_over_commit = True disk_over_commit = True
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
instance_uuid = instance['uuid']
db.instance_get(self.context,
instance_id).AndReturn(instance)
# Source checks
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
instance['host']).AndReturn(['fake_service2']) instance['host']).AndReturn(['fake_service2'])
utils.service_is_up('fake_service2').AndReturn(True) utils.service_is_up('fake_service2').AndReturn(True)
@ -521,60 +510,42 @@ class SchedulerTestCase(test.TestCase):
dest).AndReturn(['fake_service3']) dest).AndReturn(['fake_service3'])
utils.service_is_up('fake_service3').AndReturn(True) utils.service_is_up('fake_service3').AndReturn(True)
# assert_compute_node_has_enough_memory() # assert_compute_node_has_enough_memory()
self.driver._get_compute_info(self.context, dest, db.service_get_all_compute_by_host(self.context, dest).AndReturn(
'memory_mb').AndReturn(2048) [{'compute_node': [{'memory_mb': 2048,
'hypervisor_version': 1}]}])
db.instance_get_all_by_host(self.context, dest).AndReturn( db.instance_get_all_by_host(self.context, dest).AndReturn(
[dict(memory_mb=256), dict(memory_mb=512)]) [dict(memory_mb=256), dict(memory_mb=512)])
# assert_compute_node_has_enough_disk()
self.driver._get_compute_info(self.context, dest,
'disk_available_least').AndReturn(1025)
rpc.queue_get_for(self.context, FLAGS.compute_topic,
instance['host']).AndReturn('src_queue1')
instance_disk_info_msg = {
'method': 'get_instance_disk_info',
'args': {
'instance_name': instance['name'],
},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION,
}
instance_disk_info = [{'disk_size': 1024 * (1024 ** 3)}]
rpc.call(self.context,
'src_queue1',
instance_disk_info_msg,
None).AndReturn(jsonutils.dumps(instance_disk_info))
# Common checks (shared storage ok, same hypervisor, etc)
self._check_shared_storage(dest, instance, False)
# Common checks (same hypervisor, etc)
db.service_get_all_compute_by_host(self.context, dest).AndReturn( db.service_get_all_compute_by_host(self.context, dest).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen', [{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1}]}]) 'hypervisor_version': 1}]}])
# newer hypervisor version for src
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
instance['host']).AndReturn( instance['host']).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen', [{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1, 'hypervisor_version': 1,
'cpu_info': 'fake_cpu_info'}]}]) 'cpu_info': 'fake_cpu_info'}]}])
rpc.queue_get_for(self.context, FLAGS.compute_topic,
dest).AndReturn('dest_queue')
rpc.call(self.context, 'dest_queue',
{'method': 'compare_cpu',
'args': {'cpu_info': 'fake_cpu_info'},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
None).AndReturn(True)
db.instance_update_and_get_original(self.context, instance['id'], rpc.call(self.context, "compute.fake_host2",
{"method": 'check_can_live_migrate_destination',
"args": {'instance_id': instance_id,
'block_migration': block_migration,
'disk_over_commit': disk_over_commit},
"version": "1.2"},
None)
db.instance_update_and_get_original(self.context, instance_uuid,
{"task_state": task_states.MIGRATING}).AndReturn( {"task_state": task_states.MIGRATING}).AndReturn(
(instance, instance)) (instance, instance))
driver.cast_to_compute_host(self.context, instance['host'], driver.cast_to_compute_host(self.context, instance['host'],
'live_migration', update_db=False, 'live_migration', update_db=False,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration) block_migration=block_migration)
self.mox.ReplayAll() self.mox.ReplayAll()
result = self.driver.schedule_live_migration(self.context, result = self.driver.schedule_live_migration(self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
self.assertEqual(result, None) self.assertEqual(result, None)
@ -587,17 +558,44 @@ class SchedulerTestCase(test.TestCase):
dest = 'fake_host2' dest = 'fake_host2'
block_migration = False block_migration = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
instance_id = instance['id']
instance['power_state'] = power_state.NOSTATE instance['power_state'] = power_state.NOSTATE
db.instance_get(self.context, instance['id']).AndReturn(instance) db.instance_get(self.context,
instance_id).AndReturn(instance)
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.InstanceNotRunning, self.assertRaises(exception.InstanceNotRunning,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration) block_migration=block_migration)
def test_live_migration_compute_src_not_exist(self):
"""Raise exception when src compute node is does not exist."""
self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(utils, 'service_is_up')
self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host')
dest = 'fake_host2'
block_migration = False
instance = self._live_migration_instance()
instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
# Compute down
db.service_get_all_compute_by_host(self.context,
instance['host']).AndRaise(
exception.NotFound())
self.mox.ReplayAll()
self.assertRaises(exception.ComputeServiceUnavailable,
self.driver.schedule_live_migration, self.context,
instance_id=instance_id, dest=dest,
block_migration=block_migration)
def test_live_migration_compute_src_not_alive(self): def test_live_migration_compute_src_not_alive(self):
"""Raise exception when src compute node is not alive.""" """Raise exception when src compute node is not alive."""
@ -608,7 +606,9 @@ class SchedulerTestCase(test.TestCase):
dest = 'fake_host2' dest = 'fake_host2'
block_migration = False block_migration = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
# Compute down # Compute down
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
@ -618,7 +618,7 @@ class SchedulerTestCase(test.TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.ComputeServiceUnavailable, self.assertRaises(exception.ComputeServiceUnavailable,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration) block_migration=block_migration)
def test_live_migration_compute_dest_not_alive(self): def test_live_migration_compute_dest_not_alive(self):
@ -632,7 +632,9 @@ class SchedulerTestCase(test.TestCase):
dest = 'fake_host2' dest = 'fake_host2'
block_migration = False block_migration = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
@ -643,7 +645,7 @@ class SchedulerTestCase(test.TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.ComputeServiceUnavailable, self.assertRaises(exception.ComputeServiceUnavailable,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration) block_migration=block_migration)
def test_live_migration_dest_check_service_same_host(self): def test_live_migration_dest_check_service_same_host(self):
@ -657,10 +659,12 @@ class SchedulerTestCase(test.TestCase):
block_migration = False block_migration = False
disk_over_commit = False disk_over_commit = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
instance_id = instance['id']
# make dest same as src # make dest same as src
dest = instance['host'] dest = instance['host']
db.instance_get(self.context, instance['id']).AndReturn(instance) db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
@ -670,7 +674,7 @@ class SchedulerTestCase(test.TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.UnableToMigrateToSelf, self.assertRaises(exception.UnableToMigrateToSelf,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=False) disk_over_commit=False)
@ -688,138 +692,29 @@ class SchedulerTestCase(test.TestCase):
block_migration = False block_migration = False
disk_over_commit = False disk_over_commit = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
dest).AndReturn(['fake_service3']) dest).AndReturn(['fake_service3'])
utils.service_is_up('fake_service3').AndReturn(True) utils.service_is_up('fake_service3').AndReturn(True)
self.driver._get_compute_info(self.context, dest, self.driver._get_compute_info(self.context, dest).AndReturn(
'memory_mb').AndReturn(2048) {'memory_mb': 2048})
db.instance_get_all_by_host(self.context, dest).AndReturn( db.instance_get_all_by_host(self.context, dest).AndReturn(
[dict(memory_mb=1024), dict(memory_mb=512)]) [dict(memory_mb=1024), dict(memory_mb=512)])
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.MigrationError, self.assertRaises(exception.MigrationError,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration,
disk_over_commit=disk_over_commit)
def test_block_migration_dest_check_service_lack_disk(self):
"""Confirms exception raises when dest doesn't have enough disk."""
self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host')
self.mox.StubOutWithMock(utils, 'service_is_up')
self.mox.StubOutWithMock(self.driver,
'assert_compute_node_has_enough_memory')
self.mox.StubOutWithMock(self.driver, '_get_compute_info')
self.mox.StubOutWithMock(db, 'instance_get_all_by_host')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'call')
dest = 'fake_host2'
block_migration = True
disk_over_commit = True
instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance)
db.service_get_all_compute_by_host(self.context,
dest).AndReturn(['fake_service3'])
utils.service_is_up('fake_service3').AndReturn(True)
# Enough memory
self.driver.assert_compute_node_has_enough_memory(self.context,
instance, dest)
# Not enough disk
self.driver._get_compute_info(self.context, dest,
'disk_available_least').AndReturn(1023)
rpc.queue_get_for(self.context, FLAGS.compute_topic,
instance['host']).AndReturn('src_queue')
instance_disk_info_msg = {
'method': 'get_instance_disk_info',
'args': {
'instance_name': instance['name'],
},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION,
}
instance_disk_info = [{'disk_size': 1024 * (1024 ** 3)}]
rpc.call(self.context,
'src_queue',
instance_disk_info_msg,
None).AndReturn(jsonutils.dumps(instance_disk_info))
self.mox.ReplayAll()
self.assertRaises(exception.MigrationError,
self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest,
block_migration=block_migration,
disk_over_commit=disk_over_commit)
def test_live_migration_different_shared_storage_raises(self):
"""Src and dest must have same shared storage for live migration"""
self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'call')
self.mox.StubOutWithMock(rpc, 'cast')
dest = 'fake_host2'
block_migration = False
disk_over_commit = False
instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance,
dest, block_migration, disk_over_commit)
self._check_shared_storage(dest, instance, False)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidSharedStorage,
self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest,
block_migration=block_migration,
disk_over_commit=disk_over_commit)
def test_live_migration_same_shared_storage_okay(self):
"""live migration works with same src and dest shared storage"""
self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'call')
self.mox.StubOutWithMock(rpc, 'cast')
dest = 'fake_host2'
block_migration = False
disk_over_commit = False
instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance,
dest, block_migration, disk_over_commit)
self._check_shared_storage(dest, instance, False)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidSharedStorage,
self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
def test_live_migration_different_hypervisor_type_raises(self): def test_live_migration_different_hypervisor_type_raises(self):
"""Confirm live_migration to hypervisor of different type raises"""
self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
@ -832,18 +727,16 @@ class SchedulerTestCase(test.TestCase):
block_migration = False block_migration = False
disk_over_commit = False disk_over_commit = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance, self.driver._live_migration_dest_check(self.context, instance, dest)
dest, block_migration, disk_over_commit)
self._check_shared_storage(dest, instance, True)
db.service_get_all_compute_by_host(self.context, dest).AndReturn( db.service_get_all_compute_by_host(self.context, dest).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen', [{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1}]}]) 'hypervisor_version': 1}]}])
# different hypervisor type
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
instance['host']).AndReturn( instance['host']).AndReturn(
[{'compute_node': [{'hypervisor_type': 'not-xen', [{'compute_node': [{'hypervisor_type': 'not-xen',
@ -852,11 +745,12 @@ class SchedulerTestCase(test.TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.InvalidHypervisorType, self.assertRaises(exception.InvalidHypervisorType,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
def test_live_migration_dest_hypervisor_version_older_raises(self): def test_live_migration_dest_hypervisor_version_older_raises(self):
"""Confirm live migration to older hypervisor raises"""
self.mox.StubOutWithMock(db, 'instance_get') self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check') self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
@ -869,18 +763,16 @@ class SchedulerTestCase(test.TestCase):
block_migration = False block_migration = False
disk_over_commit = False disk_over_commit = False
instance = self._live_migration_instance() instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance) instance_id = instance['id']
db.instance_get(self.context,
instance_id).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance) self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance, self.driver._live_migration_dest_check(self.context, instance, dest)
dest, block_migration, disk_over_commit)
self._check_shared_storage(dest, instance, True)
db.service_get_all_compute_by_host(self.context, dest).AndReturn( db.service_get_all_compute_by_host(self.context, dest).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen', [{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1}]}]) 'hypervisor_version': 1}]}])
# newer hypervisor version for src
db.service_get_all_compute_by_host(self.context, db.service_get_all_compute_by_host(self.context,
instance['host']).AndReturn( instance['host']).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen', [{'compute_node': [{'hypervisor_type': 'xen',
@ -888,53 +780,10 @@ class SchedulerTestCase(test.TestCase):
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertRaises(exception.DestinationHypervisorTooOld, self.assertRaises(exception.DestinationHypervisorTooOld,
self.driver.schedule_live_migration, self.context, self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest, instance_id=instance_id, dest=dest,
block_migration=block_migration, block_migration=block_migration,
disk_over_commit=disk_over_commit) disk_over_commit=disk_over_commit)
def test_live_migration_dest_host_incompatable_cpu_raises(self):
self.mox.StubOutWithMock(db, 'instance_get')
self.mox.StubOutWithMock(self.driver, '_live_migration_src_check')
self.mox.StubOutWithMock(self.driver, '_live_migration_dest_check')
self.mox.StubOutWithMock(rpc, 'queue_get_for')
self.mox.StubOutWithMock(rpc, 'call')
self.mox.StubOutWithMock(rpc, 'cast')
self.mox.StubOutWithMock(db, 'service_get_all_compute_by_host')
dest = 'fake_host2'
block_migration = False
disk_over_commit = False
instance = self._live_migration_instance()
db.instance_get(self.context, instance['id']).AndReturn(instance)
self.driver._live_migration_src_check(self.context, instance)
self.driver._live_migration_dest_check(self.context, instance,
dest, block_migration, disk_over_commit)
self._check_shared_storage(dest, instance, True)
db.service_get_all_compute_by_host(self.context, dest).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1}]}])
db.service_get_all_compute_by_host(self.context,
instance['host']).AndReturn(
[{'compute_node': [{'hypervisor_type': 'xen',
'hypervisor_version': 1,
'cpu_info': 'fake_cpu_info'}]}])
rpc.queue_get_for(self.context, FLAGS.compute_topic,
dest).AndReturn('dest_queue')
rpc.call(self.context, 'dest_queue',
{'method': 'compare_cpu',
'args': {'cpu_info': 'fake_cpu_info'},
'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION},
None).AndRaise(rpc_common.RemoteError())
self.mox.ReplayAll()
self.assertRaises(rpc_common.RemoteError,
self.driver.schedule_live_migration, self.context,
instance_id=instance['id'], dest=dest,
block_migration=block_migration)
class SchedulerDriverBaseTestCase(SchedulerTestCase): class SchedulerDriverBaseTestCase(SchedulerTestCase):
"""Test cases for base scheduler driver class methods """Test cases for base scheduler driver class methods

View File

@ -30,6 +30,8 @@ from xml.dom import minidom
from nova.api.ec2 import cloud from nova.api.ec2 import cloud
from nova.compute import instance_types from nova.compute import instance_types
from nova.compute import power_state 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_states from nova.compute import vm_states
from nova import context from nova import context
from nova import db from nova import db
@ -1483,6 +1485,166 @@ class LibvirtConnTestCase(test.TestCase):
db.instance_destroy(self.context, instance_ref['uuid']) db.instance_destroy(self.context, instance_ref['uuid'])
def test_check_can_live_migrate_dest_all_pass_with_block_migration(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest = "fake_host_2"
src = instance_ref['host']
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_get_compute_info')
self.mox.StubOutWithMock(conn, 'get_instance_disk_info')
self.mox.StubOutWithMock(conn, '_create_shared_storage_test_file')
self.mox.StubOutWithMock(conn, '_compare_cpu')
conn._get_compute_info(self.context, FLAGS.host).AndReturn(
{'disk_available_least': 400})
conn.get_instance_disk_info(instance_ref["name"]).AndReturn(
'[{"virt_disk_size":2}]')
# _check_cpu_match
conn._get_compute_info(self.context,
src).AndReturn({'cpu_info': "asdf"})
conn._compare_cpu("asdf")
# mounted_on_same_shared_storage
filename = "file"
conn._create_shared_storage_test_file().AndReturn(filename)
self.mox.ReplayAll()
return_value = conn.check_can_live_migrate_destination(self.context,
instance_ref, True, False)
self.assertDictMatch(return_value,
{"filename": "file", "block_migration": True})
def test_check_can_live_migrate_dest_all_pass_no_block_migration(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest = "fake_host_2"
src = instance_ref['host']
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_get_compute_info')
self.mox.StubOutWithMock(conn, '_create_shared_storage_test_file')
self.mox.StubOutWithMock(conn, '_compare_cpu')
# _check_cpu_match
conn._get_compute_info(self.context,
src).AndReturn({'cpu_info': "asdf"})
conn._compare_cpu("asdf")
# mounted_on_same_shared_storage
filename = "file"
conn._create_shared_storage_test_file().AndReturn(filename)
self.mox.ReplayAll()
return_value = conn.check_can_live_migrate_destination(self.context,
instance_ref, False, False)
self.assertDictMatch(return_value,
{"filename": "file", "block_migration": False})
def test_check_can_live_migrate_dest_fails_not_enough_disk(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest = "fake_host_2"
src = instance_ref['host']
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_get_compute_info')
self.mox.StubOutWithMock(conn, 'get_instance_disk_info')
conn._get_compute_info(self.context, FLAGS.host).AndReturn(
{'disk_available_least': 0})
conn.get_instance_disk_info(instance_ref["name"]).AndReturn(
'[{"virt_disk_size":2}]')
self.mox.ReplayAll()
self.assertRaises(exception.MigrationError,
conn.check_can_live_migrate_destination,
self.context, instance_ref, True, False)
def test_check_can_live_migrate_dest_incompatible_cpu_raises(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest = "fake_host_2"
src = instance_ref['host']
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_get_compute_info')
self.mox.StubOutWithMock(conn, '_compare_cpu')
conn._get_compute_info(self.context, src).AndReturn(
{'cpu_info': "asdf"})
conn._compare_cpu("asdf").AndRaise(exception.InvalidCPUInfo)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidCPUInfo,
conn.check_can_live_migrate_destination,
self.context, instance_ref, False, False)
def test_check_can_live_migrate_dest_fail_space_with_block_migration(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest = "fake_host_2"
src = instance_ref['host']
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_get_compute_info')
self.mox.StubOutWithMock(conn, 'get_instance_disk_info')
conn._get_compute_info(self.context, FLAGS.host).AndReturn(
{'disk_available_least': 0})
conn.get_instance_disk_info(instance_ref["name"]).AndReturn(
'[{"virt_disk_size":2}]')
self.mox.ReplayAll()
self.assertRaises(exception.MigrationError,
conn.check_can_live_migrate_destination,
self.context, instance_ref, True, False)
def test_check_can_live_migrate_dest_cleanup_works_correctly(self):
dest_check_data = {"filename": "file", "block_migration": True}
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, '_cleanup_shared_storage_test_file')
conn._cleanup_shared_storage_test_file("file")
self.mox.ReplayAll()
conn.check_can_live_migrate_destination_cleanup(self.context,
dest_check_data)
def test_check_can_live_migrate_source_works_correctly(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest_check_data = {"filename": "file", "block_migration": True}
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, "_check_shared_storage_test_file")
conn._check_shared_storage_test_file("file").AndReturn(False)
self.mox.ReplayAll()
conn.check_can_live_migrate_source(self.context, instance_ref,
dest_check_data)
def test_check_can_live_migrate_dest_fail_shared_storage_with_blockm(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest_check_data = {"filename": "file", "block_migration": True}
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, "_check_shared_storage_test_file")
conn._check_shared_storage_test_file("file").AndReturn(True)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidSharedStorage,
conn.check_can_live_migrate_source,
self.context, instance_ref, dest_check_data)
def test_check_can_live_migrate_no_shared_storage_no_blck_mig_raises(self):
instance_ref = db.instance_create(self.context, self.test_instance)
dest_check_data = {"filename": "file", "block_migration": False}
conn = libvirt_driver.LibvirtDriver(False)
self.mox.StubOutWithMock(conn, "_check_shared_storage_test_file")
conn._check_shared_storage_test_file("file").AndReturn(False)
self.mox.ReplayAll()
self.assertRaises(exception.InvalidSharedStorage,
conn.check_can_live_migrate_source,
self.context, instance_ref, dest_check_data)
def test_live_migration_raises_exception(self): def test_live_migration_raises_exception(self):
"""Confirms recover method is called when exceptions are raised.""" """Confirms recover method is called when exceptions are raised."""
# Preparing data # Preparing data
@ -1535,7 +1697,7 @@ class LibvirtConnTestCase(test.TestCase):
db.volume_destroy(self.context, volume_ref['id']) db.volume_destroy(self.context, volume_ref['id'])
db.instance_destroy(self.context, instance_ref['uuid']) db.instance_destroy(self.context, instance_ref['uuid'])
def test_pre_live_migration_works_correctly(self): def test_pre_live_migration_works_correctly_mocked(self):
"""Confirms pre_block_migration works correctly.""" """Confirms pre_block_migration works correctly."""
# Creating testdata # Creating testdata
vol = {'block_device_mapping': [ vol = {'block_device_mapping': [
@ -1543,6 +1705,14 @@ class LibvirtConnTestCase(test.TestCase):
{'connection_info': 'dummy', 'mount_device': '/dev/sdb'}]} {'connection_info': 'dummy', 'mount_device': '/dev/sdb'}]}
conn = libvirt_driver.LibvirtDriver(False) conn = libvirt_driver.LibvirtDriver(False)
class FakeNetworkInfo():
def fixed_ips(self):
return ["test_ip_addr"]
inst_ref = {'id': 'foo'}
c = context.get_admin_context()
nw_info = FakeNetworkInfo()
# Creating mocks # Creating mocks
self.mox.StubOutWithMock(driver, "block_device_info_get_mapping") self.mox.StubOutWithMock(driver, "block_device_info_get_mapping")
driver.block_device_info_get_mapping(vol driver.block_device_info_get_mapping(vol
@ -1552,10 +1722,12 @@ class LibvirtConnTestCase(test.TestCase):
conn.volume_driver_method('connect_volume', conn.volume_driver_method('connect_volume',
v['connection_info'], v['connection_info'],
v['mount_device'].rpartition("/")[2]) v['mount_device'].rpartition("/")[2])
self.mox.StubOutWithMock(conn, 'plug_vifs')
conn.plug_vifs(mox.IsA(inst_ref), nw_info)
# Starting test
self.mox.ReplayAll() self.mox.ReplayAll()
self.assertEqual(conn.pre_live_migration(vol), None) result = conn.pre_live_migration(c, inst_ref, vol, nw_info)
self.assertEqual(result, None)
def test_pre_block_migration_works_correctly(self): def test_pre_block_migration_works_correctly(self):
"""Confirms pre_block_migration works correctly.""" """Confirms pre_block_migration works correctly."""

View File

@ -455,32 +455,6 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
instance_ref, network_info = self._get_running_instance() instance_ref, network_info = self._get_running_instance()
self.connection.refresh_provider_fw_rules() self.connection.refresh_provider_fw_rules()
@catch_notimplementederror
def test_compare_cpu(self):
cpu_info = '''{ "topology": {
"sockets": 1,
"cores": 2,
"threads": 1 },
"features": [
"xtpr",
"tm2",
"est",
"vmx",
"ds_cpl",
"monitor",
"pbe",
"tm",
"ht",
"ss",
"acpi",
"ds",
"vme"],
"arch": "x86_64",
"model": "Penryn",
"vendor": "Intel" }'''
self.connection.compare_cpu(cpu_info)
@catch_notimplementederror @catch_notimplementederror
def test_ensure_filtering_for_instance(self): def test_ensure_filtering_for_instance(self):
instance_ref = test_utils.get_test_instance() instance_ref = test_utils.get_test_instance()