From 9039c2cc59904a72fc71255a3a31ec2b17018963 Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Fri, 21 Jan 2011 16:06:32 +0000 Subject: OS-55: Added unit test for network injection via xenstore --- nova/tests/db/fakes.py | 54 ++++++++++++++++++++++++++++++---------------- nova/tests/test_xenapi.py | 46 +++++++++++++++++++++++++++++++++------ nova/tests/xenapi/stubs.py | 15 +++++++++++++ nova/virt/xenapi/fake.py | 12 +++++++++-- 4 files changed, 100 insertions(+), 27 deletions(-) diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 72e093f99..e92efbedd 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -23,23 +23,22 @@ from nova import db from nova import utils from nova.compute import instance_types +class FakeModel(object): + """ Stubs out for model """ + def __init__(self, values): + self.values = values -def stub_out_db_instance_api(stubs): - """ Stubs out the db API for creating Instances """ + def __getattr__(self, name): + return self.values[name] - class FakeModel(object): - """ Stubs out for model """ - def __init__(self, values): - self.values = values + def __getitem__(self, key): + if key in self.values: + return self.values[key] + else: + raise NotImplementedError() - def __getattr__(self, name): - return self.values[name] - - def __getitem__(self, key): - if key in self.values: - return self.values[key] - else: - raise NotImplementedError() +def stub_out_db_instance_api(stubs): + """ Stubs out the db API for creating Instances """ def fake_instance_create(values): """ Stubs out the db.instance_create method """ @@ -66,12 +65,29 @@ def stub_out_db_instance_api(stubs): } return FakeModel(base_options) - def fake_network_get_by_instance(context, instance_id): - fields = { + stubs.Set(db, 'instance_create', fake_instance_create) + +def stub_out_db_network_api(stubs, injected = False): + """Stubs out the db API for retrieving networks""" + network_fields = { 'bridge': 'xenbr0', - 'injected': False + 'injected': injected } - return FakeModel(fields) - stubs.Set(db, 'instance_create', fake_instance_create) + if injected: + network_fields.update({ + 'netmask': '255.255.255.0', + 'gateway': '10.0.0.1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2' + }) + + def fake_network_get_by_instance(context, instance_id): + return FakeModel(network_fields) + + def fake_instance_get_fixed_address(context, instance_id): + return '10.0.0.3' + stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) + stubs.Set(db, 'instance_get_fixed_address', fake_instance_get_fixed_address) + diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 9f5b266f3..2a32845d3 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -50,6 +50,7 @@ class XenAPIVolumeTestCase(test.TestCase): FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_password = 'test_pass' db_fakes.stub_out_db_instance_api(self.stubs) + db_fakes.stub_out_db_network_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() self.values = {'name': 1, 'id': 1, @@ -158,6 +159,7 @@ class XenAPIVMTestCase(test.TestCase): xenapi_fake.reset() xenapi_fake.create_local_srs() db_fakes.stub_out_db_instance_api(self.stubs) + db_fakes.stub_out_db_network_api(self.stubs) xenapi_fake.create_network('fake', FLAGS.flat_network_bridge) stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) @@ -211,7 +213,7 @@ class XenAPIVMTestCase(test.TestCase): check() - def check_vm_record(self, conn): + def check_vm_record(self, conn, check_injection = False): instances = conn.list_instances() self.assertEquals(instances, [1]) @@ -219,10 +221,10 @@ class XenAPIVMTestCase(test.TestCase): vm_info = conn.get_info(1) # Get XenAPI record for VM - vms = [rec for ref, rec + vms = [(ref, rec) for ref, rec in xenapi_fake.get_all_records('VM').iteritems() if not rec['is_control_domain']] - vm = vms[0] + vm_ref, vm = vms[0] # Check that m1.large above turned into the right thing. instance_type = instance_types.INSTANCE_TYPES['m1.large'] @@ -242,8 +244,35 @@ class XenAPIVMTestCase(test.TestCase): # Check that the VM is running according to XenAPI. self.assertEquals(vm['power_state'], 'Running') - - def _test_spawn(self, image_id, kernel_id, ramdisk_id): + + if check_injection: + xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) + key_prefix = 'vm-data/vif/22_33_2A_B3_CC_DD/tcpip/' + tcpip_data = dict([(k.replace(key_prefix, ''), v) + for k, v in xenstore_data.iteritems() if k.startswith(key_prefix) ]) + + self.assertEquals(tcpip_data, { + 'BroadcastAddress/data/0': '10.0.0.255', + 'BroadcastAddress/name': 'BroadcastAddress', + 'BroadcastAddress/type': 'multi_sz', + 'DefaultGateway/data/0': '10.0.0.1', + 'DefaultGateway/name': 'DefaultGateway', + 'DefaultGateway/type': 'multi_sz', + 'EnableDhcp/data': '0', + 'EnableDhcp/name': 'EnableDhcp', + 'EnableDhcp/type': 'dword', + 'IPAddress/data/0': '10.0.0.3', + 'IPAddress/name': 'IPAddress', + 'IPAddress/type': 'multi_sz', + 'NameServer/data': '10.0.0.2', + 'NameServer/name': 'NameServer', + 'NameServer/type': 'string', + 'SubnetMask/data/0': '255.255.255.0', + 'SubnetMask/name': 'SubnetMask', + 'SubnetMask/type': 'multi_sz' + }) + + def _test_spawn(self, image_id, kernel_id, ramdisk_id, check_injection = False): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) values = {'name': 1, 'id': 1, @@ -258,7 +287,7 @@ class XenAPIVMTestCase(test.TestCase): conn = xenapi_conn.get_connection(False) instance = db.instance_create(values) conn.spawn(instance) - self.check_vm_record(conn) + self.check_vm_record(conn, check_injection = check_injection) def test_spawn_raw_objectstore(self): FLAGS.xenapi_image_service = 'objectstore' @@ -276,6 +305,11 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_image_service = 'glance' self._test_spawn(1, 2, 3) + def test_spawn_netinject(self): + FLAGS.xenapi_image_service = 'glance' + db_fakes.stub_out_db_network_api(self.stubs, injected = True) + self._test_spawn(1, 2, 3, check_injection = True) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 624995ada..3cfc8e5f9 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -171,6 +171,21 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_destroy(self, session_ref, vm_ref): fake.destroy_vm(vm_ref) + def VM_get_VIFs(self, session_ref, vm_ref): + return (['0', '1', '2']) + + def VIF_get_device(self, session_ref, vif_ref): + return ('1', '0', '2')[int(vif_ref)] + + def VIF_get_MAC(self, session_ref, vif_ref): + return ( + '11:22:2a:b3:CC:dd', + '22:33:2a:b3:CC:dd', + '44:44:2a:b3:CC:dd' + )[int(vif_ref)] + + def VM_add_to_xenstore_data(self, session_ref, vm_ref, key, value): + fake.VM_add_to_xenstore_data(vm_ref, key, value) class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py index 836252730..f9ae8766a 100644 --- a/nova/virt/xenapi/fake.py +++ b/nova/virt/xenapi/fake.py @@ -148,7 +148,15 @@ def create_vbd(vm_ref, vdi_ref): after_VBD_create(vbd_ref, vbd_rec) return vbd_ref - +def VM_get_xenstore_data(vm_ref): + return _db_content['VM'][vm_ref].get('xenstore_data', '') + +def VM_add_to_xenstore_data(vm_ref, key, value): + db_ref = _db_content['VM'][vm_ref] + if not 'xenstore_data' in db_ref: + db_ref['xenstore_data'] = {} + db_ref['xenstore_data'][key] = value + def after_VBD_create(vbd_ref, vbd_rec): """Create read-only fields and backref from VM to VBD when VBD is created.""" @@ -401,7 +409,7 @@ class SessionBase(object): field in _db_content[cls][ref]): return _db_content[cls][ref][field] - LOG.debuug(_('Raising NotImplemented')) + LOG.debug(_('Raising NotImplemented')) raise NotImplementedError( _('xenapi.fake does not have an implementation for %s or it has ' 'been called with the wrong number of arguments') % name) -- cgit