merge trunk, fixed conflicts

This commit is contained in:
Salvatore Orlando
2011-03-28 15:58:06 +01:00
3 changed files with 150 additions and 31 deletions

View File

@@ -1,4 +1,5 @@
Andy Smith <code@term.ie> Andy Smith <code@term.ie>
Andy Southgate <andy.southgate@citrix.com>
Anne Gentle <anne@openstack.org> Anne Gentle <anne@openstack.org>
Anthony Young <sleepsonthefloor@gmail.com> Anthony Young <sleepsonthefloor@gmail.com>
Antony Messerli <ant@openstack.org> Antony Messerli <ant@openstack.org>
@@ -21,6 +22,7 @@ Eldar Nugaev <enugaev@griddynamics.com>
Eric Day <eday@oddments.org> Eric Day <eday@oddments.org>
Eric Windisch <eric@cloudscaling.com> Eric Windisch <eric@cloudscaling.com>
Ewan Mellor <ewan.mellor@citrix.com> Ewan Mellor <ewan.mellor@citrix.com>
Gabe Westmaas <gabe.westmaas@rackspace.com>
Hisaharu Ishii <ishii.hisaharu@lab.ntt.co.jp> Hisaharu Ishii <ishii.hisaharu@lab.ntt.co.jp>
Hisaki Ohara <hisaki.ohara@intel.com> Hisaki Ohara <hisaki.ohara@intel.com>
Ilya Alekseyev <ialekseev@griddynamics.com> Ilya Alekseyev <ialekseev@griddynamics.com>

View File

@@ -19,11 +19,15 @@ Test suite for XenAPI
""" """
import functools import functools
import os
import re
import stubout import stubout
import ast
from nova import db from nova import db
from nova import context from nova import context
from nova import flags from nova import flags
from nova import log as logging
from nova import test from nova import test
from nova import utils from nova import utils
from nova.auth import manager from nova.auth import manager
@@ -38,6 +42,9 @@ from nova.virt.xenapi.vmops import VMOps
from nova.tests.db import fakes as db_fakes from nova.tests.db import fakes as db_fakes
from nova.tests.xenapi import stubs from nova.tests.xenapi import stubs
from nova.tests.glance import stubs as glance_stubs from nova.tests.glance import stubs as glance_stubs
from nova.tests import fake_utils
LOG = logging.getLogger('nova.tests.test_xenapi')
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
@@ -64,13 +71,14 @@ class XenAPIVolumeTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(XenAPIVolumeTestCase, self).setUp() super(XenAPIVolumeTestCase, self).setUp()
self.stubs = stubout.StubOutForTesting() self.stubs = stubout.StubOutForTesting()
self.context = context.RequestContext('fake', 'fake', False)
FLAGS.target_host = '127.0.0.1' FLAGS.target_host = '127.0.0.1'
FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_url = 'test_url'
FLAGS.xenapi_connection_password = 'test_pass' FLAGS.xenapi_connection_password = 'test_pass'
db_fakes.stub_out_db_instance_api(self.stubs) db_fakes.stub_out_db_instance_api(self.stubs)
stubs.stub_out_get_target(self.stubs) stubs.stub_out_get_target(self.stubs)
xenapi_fake.reset() xenapi_fake.reset()
self.values = {'name': 1, 'id': 1, self.values = {'id': 1,
'project_id': 'fake', 'project_id': 'fake',
'user_id': 'fake', 'user_id': 'fake',
'image_id': 1, 'image_id': 1,
@@ -90,7 +98,7 @@ class XenAPIVolumeTestCase(test.TestCase):
vol['availability_zone'] = FLAGS.storage_availability_zone vol['availability_zone'] = FLAGS.storage_availability_zone
vol['status'] = "creating" vol['status'] = "creating"
vol['attach_status'] = "detached" vol['attach_status'] = "detached"
return db.volume_create(context.get_admin_context(), vol) return db.volume_create(self.context, vol)
def test_create_iscsi_storage(self): def test_create_iscsi_storage(self):
""" This shows how to test helper classes' methods """ """ This shows how to test helper classes' methods """
@@ -126,7 +134,7 @@ class XenAPIVolumeTestCase(test.TestCase):
stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests) stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests)
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
volume = self._create_volume() volume = self._create_volume()
instance = db.instance_create(self.values) instance = db.instance_create(self.context, self.values)
vm = xenapi_fake.create_vm(instance.name, 'Running') vm = xenapi_fake.create_vm(instance.name, 'Running')
result = conn.attach_volume(instance.name, volume['id'], '/dev/sdc') result = conn.attach_volume(instance.name, volume['id'], '/dev/sdc')
@@ -146,7 +154,7 @@ class XenAPIVolumeTestCase(test.TestCase):
stubs.FakeSessionForVolumeFailedTests) stubs.FakeSessionForVolumeFailedTests)
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
volume = self._create_volume() volume = self._create_volume()
instance = db.instance_create(self.values) instance = db.instance_create(self.context, self.values)
xenapi_fake.create_vm(instance.name, 'Running') xenapi_fake.create_vm(instance.name, 'Running')
self.assertRaises(Exception, self.assertRaises(Exception,
conn.attach_volume, conn.attach_volume,
@@ -175,8 +183,9 @@ class XenAPIVMTestCase(test.TestCase):
self.project = self.manager.create_project('fake', 'fake', 'fake') self.project = self.manager.create_project('fake', 'fake', 'fake')
self.network = utils.import_object(FLAGS.network_manager) self.network = utils.import_object(FLAGS.network_manager)
self.stubs = stubout.StubOutForTesting() self.stubs = stubout.StubOutForTesting()
FLAGS.xenapi_connection_url = 'test_url' self.flags(xenapi_connection_url='test_url',
FLAGS.xenapi_connection_password = 'test_pass' xenapi_connection_password='test_pass',
instance_name_template='%d')
xenapi_fake.reset() xenapi_fake.reset()
xenapi_fake.create_local_srs() xenapi_fake.create_local_srs()
db_fakes.stub_out_db_instance_api(self.stubs) db_fakes.stub_out_db_instance_api(self.stubs)
@@ -189,6 +198,8 @@ class XenAPIVMTestCase(test.TestCase):
stubs.stub_out_vm_methods(self.stubs) stubs.stub_out_vm_methods(self.stubs)
glance_stubs.stubout_glance_client(self.stubs, glance_stubs.stubout_glance_client(self.stubs,
glance_stubs.FakeGlance) glance_stubs.FakeGlance)
fake_utils.stub_out_utils_execute(self.stubs)
self.context = context.RequestContext('fake', 'fake', False)
self.conn = xenapi_conn.get_connection(False) self.conn = xenapi_conn.get_connection(False)
def test_list_instances_0(self): def test_list_instances_0(self):
@@ -213,7 +224,7 @@ class XenAPIVMTestCase(test.TestCase):
if not vm_rec["is_control_domain"]: if not vm_rec["is_control_domain"]:
vm_labels.append(vm_rec["name_label"]) vm_labels.append(vm_rec["name_label"])
self.assertEquals(vm_labels, [1]) self.assertEquals(vm_labels, ['1'])
def ensure_vbd_was_torn_down(): def ensure_vbd_was_torn_down():
vbd_labels = [] vbd_labels = []
@@ -221,7 +232,7 @@ class XenAPIVMTestCase(test.TestCase):
vbd_rec = xenapi_fake.get_record('VBD', vbd_ref) vbd_rec = xenapi_fake.get_record('VBD', vbd_ref)
vbd_labels.append(vbd_rec["vm_name_label"]) vbd_labels.append(vbd_rec["vm_name_label"])
self.assertEquals(vbd_labels, [1]) self.assertEquals(vbd_labels, ['1'])
def ensure_vdi_was_torn_down(): def ensure_vdi_was_torn_down():
for vdi_ref in xenapi_fake.get_all('VDI'): for vdi_ref in xenapi_fake.get_all('VDI'):
@@ -238,11 +249,10 @@ class XenAPIVMTestCase(test.TestCase):
def create_vm_record(self, conn, os_type): def create_vm_record(self, conn, os_type):
instances = conn.list_instances() instances = conn.list_instances()
self.assertEquals(instances, [1]) self.assertEquals(instances, ['1'])
# Get Nova record for VM # Get Nova record for VM
vm_info = conn.get_info(1) vm_info = conn.get_info(1)
# Get XenAPI record for VM # Get XenAPI record for VM
vms = [rec for ref, rec vms = [rec for ref, rec
in xenapi_fake.get_all_records('VM').iteritems() in xenapi_fake.get_all_records('VM').iteritems()
@@ -251,7 +261,7 @@ class XenAPIVMTestCase(test.TestCase):
self.vm_info = vm_info self.vm_info = vm_info
self.vm = vm self.vm = vm
def check_vm_record(self, conn): def check_vm_record(self, conn, check_injection=False):
# Check that m1.large above turned into the right thing. # Check that m1.large above turned into the right thing.
instance_type = db.instance_type_get_by_name(conn, 'm1.large') instance_type = db.instance_type_get_by_name(conn, 'm1.large')
mem_kib = long(instance_type['memory_mb']) << 10 mem_kib = long(instance_type['memory_mb']) << 10
@@ -271,6 +281,25 @@ class XenAPIVMTestCase(test.TestCase):
# Check that the VM is running according to XenAPI. # Check that the VM is running according to XenAPI.
self.assertEquals(self.vm['power_state'], 'Running') self.assertEquals(self.vm['power_state'], 'Running')
if check_injection:
xenstore_data = self.vm['xenstore_data']
key = 'vm-data/networking/aabbccddeeff'
xenstore_value = xenstore_data[key]
tcpip_data = ast.literal_eval(xenstore_value)
self.assertEquals(tcpip_data, {
'label': 'test_network',
'broadcast': '10.0.0.255',
'ips': [{'ip': '10.0.0.3',
'netmask':'255.255.255.0',
'enabled':'1'}],
'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff',
'netmask': '120',
'enabled': '1',
'gateway': 'fe80::a00:1'}],
'mac': 'aa:bb:cc:dd:ee:ff',
'dns': ['10.0.0.2'],
'gateway': '10.0.0.1'})
def check_vm_params_for_windows(self): def check_vm_params_for_windows(self):
self.assertEquals(self.vm['platform']['nx'], 'true') self.assertEquals(self.vm['platform']['nx'], 'true')
self.assertEquals(self.vm['HVM_boot_params'], {'order': 'dc'}) self.assertEquals(self.vm['HVM_boot_params'], {'order': 'dc'})
@@ -317,10 +346,10 @@ class XenAPIVMTestCase(test.TestCase):
self.fail('Found unexpected unbound VDI:%s' % vdi_rec['uuid']) self.fail('Found unexpected unbound VDI:%s' % vdi_rec['uuid'])
def _test_spawn(self, image_id, kernel_id, ramdisk_id, def _test_spawn(self, image_id, kernel_id, ramdisk_id,
instance_type="m1.large", os_type="linux"): instance_type="m1.large", os_type="linux",
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) check_injection=False):
values = {'name': 1, stubs.stubout_loopingcall_start(self.stubs)
'id': 1, values = {'id': 1,
'project_id': self.project.id, 'project_id': self.project.id,
'user_id': self.user.id, 'user_id': self.user.id,
'image_id': image_id, 'image_id': image_id,
@@ -329,12 +358,10 @@ class XenAPIVMTestCase(test.TestCase):
'instance_type': instance_type, 'instance_type': instance_type,
'mac_address': 'aa:bb:cc:dd:ee:ff', 'mac_address': 'aa:bb:cc:dd:ee:ff',
'os_type': os_type} 'os_type': os_type}
instance = db.instance_create(self.context, values)
conn = xenapi_conn.get_connection(False) self.conn.spawn(instance)
instance = db.instance_create(values) self.create_vm_record(self.conn, os_type)
conn.spawn(instance) self.check_vm_record(self.conn, check_injection)
self.create_vm_record(conn, os_type)
self.check_vm_record(conn)
def test_spawn_not_enough_memory(self): def test_spawn_not_enough_memory(self):
FLAGS.xenapi_image_service = 'glance' FLAGS.xenapi_image_service = 'glance'
@@ -399,6 +426,85 @@ class XenAPIVMTestCase(test.TestCase):
glance_stubs.FakeGlance.IMAGE_RAMDISK) glance_stubs.FakeGlance.IMAGE_RAMDISK)
self.check_vm_params_for_linux_with_external_kernel() self.check_vm_params_for_linux_with_external_kernel()
def test_spawn_netinject_file(self):
FLAGS.xenapi_image_service = 'glance'
db_fakes.stub_out_db_instance_api(self.stubs, injected=True)
self._tee_executed = False
def _tee_handler(cmd, **kwargs):
input = kwargs.get('process_input', None)
self.assertNotEqual(input, None)
config = [line.strip() for line in input.split("\n")]
# Find the start of eth0 configuration and check it
index = config.index('auto eth0')
self.assertEquals(config[index + 1:index + 8], [
'iface eth0 inet static',
'address 10.0.0.3',
'netmask 255.255.255.0',
'broadcast 10.0.0.255',
'gateway 10.0.0.1',
'dns-nameservers 10.0.0.2',
''])
self._tee_executed = True
return '', ''
fake_utils.fake_execute_set_repliers([
# Capture the sudo tee .../etc/network/interfaces command
(r'(sudo\s+)?tee.*interfaces', _tee_handler),
])
FLAGS.xenapi_image_service = 'glance'
self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE,
glance_stubs.FakeGlance.IMAGE_KERNEL,
glance_stubs.FakeGlance.IMAGE_RAMDISK,
check_injection=True)
self.assertTrue(self._tee_executed)
def test_spawn_netinject_xenstore(self):
FLAGS.xenapi_image_service = 'glance'
db_fakes.stub_out_db_instance_api(self.stubs, injected=True)
self._tee_executed = False
def _mount_handler(cmd, *ignore_args, **ignore_kwargs):
# When mounting, create real files under the mountpoint to simulate
# files in the mounted filesystem
# mount point will be the last item of the command list
self._tmpdir = cmd[len(cmd) - 1]
LOG.debug(_('Creating files in %s to simulate guest agent' %
self._tmpdir))
os.makedirs(os.path.join(self._tmpdir, 'usr', 'sbin'))
# Touch the file using open
open(os.path.join(self._tmpdir, 'usr', 'sbin',
'xe-update-networking'), 'w').close()
return '', ''
def _umount_handler(cmd, *ignore_args, **ignore_kwargs):
# Umount would normall make files in the m,ounted filesystem
# disappear, so do that here
LOG.debug(_('Removing simulated guest agent files in %s' %
self._tmpdir))
os.remove(os.path.join(self._tmpdir, 'usr', 'sbin',
'xe-update-networking'))
os.rmdir(os.path.join(self._tmpdir, 'usr', 'sbin'))
os.rmdir(os.path.join(self._tmpdir, 'usr'))
return '', ''
def _tee_handler(cmd, *ignore_args, **ignore_kwargs):
self._tee_executed = True
return '', ''
fake_utils.fake_execute_set_repliers([
(r'(sudo\s+)?mount', _mount_handler),
(r'(sudo\s+)?umount', _umount_handler),
(r'(sudo\s+)?tee.*interfaces', _tee_handler)])
self._test_spawn(1, 2, 3, check_injection=True)
# tee must not run in this case, where an injection-capable
# guest agent is detected
self.assertFalse(self._tee_executed)
def test_spawn_with_network_qos(self): def test_spawn_with_network_qos(self):
self._create_instance() self._create_instance()
for vif_ref in xenapi_fake.get_all('VIF'): for vif_ref in xenapi_fake.get_all('VIF'):
@@ -408,6 +514,7 @@ class XenAPIVMTestCase(test.TestCase):
str(4 * 1024)) str(4 * 1024))
def test_rescue(self): def test_rescue(self):
self.flags(xenapi_inject_image=False)
instance = self._create_instance() instance = self._create_instance()
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
conn.rescue(instance, None) conn.rescue(instance, None)
@@ -428,8 +535,8 @@ class XenAPIVMTestCase(test.TestCase):
def _create_instance(self): def _create_instance(self):
"""Creates and spawns a test instance.""" """Creates and spawns a test instance."""
values = {'name': 1, stubs.stubout_loopingcall_start(self.stubs)
'id': 1, values = {'id': 1,
'project_id': self.project.id, 'project_id': self.project.id,
'user_id': self.user.id, 'user_id': self.user.id,
'image_id': 1, 'image_id': 1,
@@ -438,7 +545,7 @@ class XenAPIVMTestCase(test.TestCase):
'instance_type': 'm1.large', 'instance_type': 'm1.large',
'mac_address': 'aa:bb:cc:dd:ee:ff', 'mac_address': 'aa:bb:cc:dd:ee:ff',
'os_type': 'linux'} 'os_type': 'linux'}
instance = db.instance_create(values) instance = db.instance_create(self.context, values)
self.conn.spawn(instance) self.conn.spawn(instance)
return instance return instance
@@ -483,21 +590,26 @@ class XenAPIMigrateInstance(test.TestCase):
db_fakes.stub_out_db_instance_api(self.stubs) db_fakes.stub_out_db_instance_api(self.stubs)
stubs.stub_out_get_target(self.stubs) stubs.stub_out_get_target(self.stubs)
xenapi_fake.reset() xenapi_fake.reset()
xenapi_fake.create_network('fake', FLAGS.flat_network_bridge)
self.manager = manager.AuthManager() self.manager = manager.AuthManager()
self.user = self.manager.create_user('fake', 'fake', 'fake', self.user = self.manager.create_user('fake', 'fake', 'fake',
admin=True) admin=True)
self.project = self.manager.create_project('fake', 'fake', 'fake') self.project = self.manager.create_project('fake', 'fake', 'fake')
self.values = {'name': 1, 'id': 1, self.context = context.RequestContext('fake', 'fake', False)
self.values = {'id': 1,
'project_id': self.project.id, 'project_id': self.project.id,
'user_id': self.user.id, 'user_id': self.user.id,
'image_id': 1, 'image_id': 1,
'kernel_id': None, 'kernel_id': None,
'ramdisk_id': None, 'ramdisk_id': None,
'local_gb': 5,
'instance_type': 'm1.large', 'instance_type': 'm1.large',
'mac_address': 'aa:bb:cc:dd:ee:ff', 'mac_address': 'aa:bb:cc:dd:ee:ff',
'os_type': 'linux'} 'os_type': 'linux'}
fake_utils.stub_out_utils_execute(self.stubs)
stubs.stub_out_migration_methods(self.stubs) stubs.stub_out_migration_methods(self.stubs)
stubs.stubout_get_this_vm_uuid(self.stubs)
glance_stubs.stubout_glance_client(self.stubs, glance_stubs.stubout_glance_client(self.stubs,
glance_stubs.FakeGlance) glance_stubs.FakeGlance)
@@ -508,14 +620,15 @@ class XenAPIMigrateInstance(test.TestCase):
self.stubs.UnsetAll() self.stubs.UnsetAll()
def test_migrate_disk_and_power_off(self): def test_migrate_disk_and_power_off(self):
instance = db.instance_create(self.values) instance = db.instance_create(self.context, self.values)
stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
conn.migrate_disk_and_power_off(instance, '127.0.0.1') conn.migrate_disk_and_power_off(instance, '127.0.0.1')
def test_finish_resize(self): def test_finish_resize(self):
instance = db.instance_create(self.values) instance = db.instance_create(self.context, self.values)
stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests)
stubs.stubout_loopingcall_start(self.stubs)
conn = xenapi_conn.get_connection(False) conn = xenapi_conn.get_connection(False)
conn.finish_resize(instance, dict(base_copy='hurr', cow='durr')) conn.finish_resize(instance, dict(base_copy='hurr', cow='durr'))

View File

@@ -21,6 +21,7 @@ from nova.virt.xenapi import fake
from nova.virt.xenapi import volume_utils from nova.virt.xenapi import volume_utils
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
from nova.virt.xenapi import vmops from nova.virt.xenapi import vmops
from nova import utils
def stubout_instance_snapshot(stubs): def stubout_instance_snapshot(stubs):
@@ -164,14 +165,17 @@ def stubout_create_vm(stubs):
stubs.Set(vm_utils.VMHelper, 'create_vm', f) stubs.Set(vm_utils.VMHelper, 'create_vm', f)
def stubout_loopingcall_start(stubs):
def fake_start(self, interval, now=True):
self.f(*self.args, **self.kw)
stubs.Set(utils.LoopingCall, 'start', fake_start)
class FakeSessionForVMTests(fake.SessionBase): class FakeSessionForVMTests(fake.SessionBase):
""" Stubs out a XenAPISession for VM tests """ """ Stubs out a XenAPISession for VM tests """
def __init__(self, uri): def __init__(self, uri):
super(FakeSessionForVMTests, self).__init__(uri) super(FakeSessionForVMTests, self).__init__(uri)
def network_get_all_records_where(self, _1, _2):
return self.xenapi.network.get_all_records()
def host_call_plugin(self, _1, _2, _3, _4, _5): def host_call_plugin(self, _1, _2, _3, _4, _5):
sr_ref = fake.get_all('SR')[0] sr_ref = fake.get_all('SR')[0]
vdi_ref = fake.create_vdi('', False, sr_ref, False) vdi_ref = fake.create_vdi('', False, sr_ref, False)
@@ -223,7 +227,7 @@ def stub_out_vm_methods(stubs):
pass pass
def fake_spawn_rescue(self, inst): def fake_spawn_rescue(self, inst):
pass inst._rescue = False
stubs.Set(vmops.VMOps, "_shutdown", fake_shutdown) stubs.Set(vmops.VMOps, "_shutdown", fake_shutdown)
stubs.Set(vmops.VMOps, "_acquire_bootlock", fake_acquire_bootlock) stubs.Set(vmops.VMOps, "_acquire_bootlock", fake_acquire_bootlock)