merge trunk
addressing Trey's comments
This commit is contained in:
1
Authors
1
Authors
@@ -1,4 +1,5 @@
|
||||
Andy Smith <code@term.ie>
|
||||
Andy Southgate <andy.southgate@citrix.com>
|
||||
Anne Gentle <anne@openstack.org>
|
||||
Anthony Young <sleepsonthefloor@gmail.com>
|
||||
Antony Messerli <ant@openstack.org>
|
||||
|
106
nova/tests/fake_utils.py.moved
Normal file
106
nova/tests/fake_utils.py.moved
Normal file
@@ -0,0 +1,106 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2011 Citrix Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""This modules stubs out functions in nova.utils
|
||||
"""
|
||||
|
||||
import re
|
||||
import types
|
||||
|
||||
from eventlet import greenthread
|
||||
|
||||
from nova import exception
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
|
||||
LOG = logging.getLogger('nova.tests.fake_utils')
|
||||
|
||||
_fake_execute_repliers = []
|
||||
_fake_execute_log = []
|
||||
|
||||
|
||||
def fake_execute_get_log():
|
||||
global _fake_execute_log
|
||||
return _fake_execute_log
|
||||
|
||||
|
||||
def fake_execute_clear_log():
|
||||
global _fake_execute_log
|
||||
_fake_execute_log = []
|
||||
|
||||
|
||||
def fake_execute_set_repliers(repliers):
|
||||
"""Allows the client to configure replies to commands"""
|
||||
global _fake_execute_repliers
|
||||
_fake_execute_repliers = repliers
|
||||
|
||||
|
||||
def fake_execute_default_reply_handler(*ignore_args, **ignore_kwargs):
|
||||
"""A reply handler for commands that haven't been added to the reply
|
||||
list. Returns empty strings for stdout and stderr
|
||||
"""
|
||||
return '', ''
|
||||
|
||||
|
||||
def fake_execute(*cmd, **kwargs):
|
||||
"""This function stubs out execute, optionally executing
|
||||
a preconfigued function to return expected data
|
||||
"""
|
||||
global _fake_execute_repliers
|
||||
|
||||
process_input = kwargs.get('process_input', None)
|
||||
addl_env = kwargs.get('addl_env', None)
|
||||
check_exit_code = kwargs.get('check_exit_code', 0)
|
||||
cmd_map = map(str, cmd)
|
||||
cmd_str = ' '.join(cmd_map)
|
||||
|
||||
LOG.debug(_("Faking execution of cmd (subprocess): %s"), cmd_str)
|
||||
_fake_execute_log.append(cmd_str)
|
||||
|
||||
reply_handler = fake_execute_default_reply_handler
|
||||
|
||||
for fake_replier in _fake_execute_repliers:
|
||||
if re.match(fake_replier[0], cmd_str):
|
||||
reply_handler = fake_replier[1]
|
||||
LOG.debug(_('Faked command matched %s') % fake_replier[0])
|
||||
break
|
||||
|
||||
if isinstance(reply_handler, types.StringTypes):
|
||||
# If the reply handler is a string, return it as stdout
|
||||
reply = reply_handler, ''
|
||||
else:
|
||||
try:
|
||||
# Alternative is a function, so call it
|
||||
reply = reply_handler(cmd,
|
||||
process_input=process_input,
|
||||
addl_env=addl_env,
|
||||
check_exit_code=check_exit_code)
|
||||
except exception.ProcessExecutionError as e:
|
||||
LOG.debug(_('Faked command raised an exception %s' % str(e)))
|
||||
raise
|
||||
|
||||
LOG.debug(_("Reply to faked command is stdout='%(0)s' stderr='%(1)s'") %
|
||||
{'0': reply[0], '1': reply[1]})
|
||||
|
||||
# Replicate the sleep call in the real function
|
||||
greenthread.sleep(0)
|
||||
return reply
|
||||
|
||||
|
||||
def stub_out_utils_execute(stubs):
|
||||
fake_execute_set_repliers([])
|
||||
fake_execute_clear_log()
|
||||
stubs.Set(utils, 'execute', fake_execute)
|
@@ -19,11 +19,15 @@ Test suite for XenAPI
|
||||
"""
|
||||
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import stubout
|
||||
import ast
|
||||
|
||||
from nova import db
|
||||
from nova import context
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova import test
|
||||
from nova import utils
|
||||
from nova.auth import manager
|
||||
@@ -40,7 +44,7 @@ from nova.tests.xenapi import stubs
|
||||
from nova.tests.glance import stubs as glance_stubs
|
||||
from nova.tests import fake_utils
|
||||
|
||||
from nova import log as LOG
|
||||
LOG = logging.getLogger('nova.tests.test_xenapi')
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
@@ -95,7 +99,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
vol['availability_zone'] = FLAGS.storage_availability_zone
|
||||
vol['status'] = "creating"
|
||||
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):
|
||||
""" This shows how to test helper classes' methods """
|
||||
@@ -251,7 +255,6 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
|
||||
# Get Nova record for VM
|
||||
vm_info = conn.get_info(instance_id)
|
||||
|
||||
# Get XenAPI record for VM
|
||||
vms = [rec for ref, rec
|
||||
in xenapi_fake.get_all_records('VM').iteritems()
|
||||
@@ -260,7 +263,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
self.vm_info = vm_info
|
||||
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.
|
||||
instance_type = db.instance_type_get_by_name(conn, 'm1.large')
|
||||
mem_kib = long(instance_type['memory_mb']) << 10
|
||||
@@ -280,6 +283,25 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
# Check that the VM is running according to XenAPI.
|
||||
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': 'fake_flat_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):
|
||||
self.assertEquals(self.vm['platform']['nx'], 'true')
|
||||
self.assertEquals(self.vm['HVM_boot_params'], {'order': 'dc'})
|
||||
@@ -313,7 +335,8 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
self.assertEquals(self.vm['HVM_boot_policy'], '')
|
||||
|
||||
def _test_spawn(self, image_id, kernel_id, ramdisk_id,
|
||||
instance_type="m1.large", os_type="linux", instance_id=1):
|
||||
instance_type="m1.large", os_type="linux",
|
||||
instance_id=1, check_injection=False):
|
||||
stubs.stubout_loopingcall_start(self.stubs)
|
||||
values = {'id': instance_id,
|
||||
'project_id': self.project.id,
|
||||
@@ -327,7 +350,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
instance = db.instance_create(self.context, values)
|
||||
self.conn.spawn(instance)
|
||||
self.create_vm_record(self.conn, os_type, instance_id)
|
||||
self.check_vm_record(self.conn)
|
||||
self.check_vm_record(self.conn, check_injection)
|
||||
|
||||
def test_spawn_not_enough_memory(self):
|
||||
FLAGS.xenapi_image_service = 'glance'
|
||||
@@ -368,6 +391,85 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
glance_stubs.FakeGlance.IMAGE_RAMDISK)
|
||||
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_vlanmanager(self):
|
||||
self.flags(xenapi_image_service='glance',
|
||||
network_manager='nova.network.manager.VlanManager',
|
||||
@@ -399,6 +501,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
str(4 * 1024))
|
||||
|
||||
def test_rescue(self):
|
||||
self.flags(xenapi_inject_image=False)
|
||||
instance = self._create_instance()
|
||||
conn = xenapi_conn.get_connection(False)
|
||||
conn.rescue(instance, None)
|
||||
@@ -492,6 +595,7 @@ class XenAPIMigrateInstance(test.TestCase):
|
||||
'mac_address': 'aa:bb:cc:dd:ee:ff',
|
||||
'os_type': 'linux'}
|
||||
|
||||
fake_utils.stub_out_utils_execute(self.stubs)
|
||||
stubs.stub_out_migration_methods(self.stubs)
|
||||
stubs.stubout_get_this_vm_uuid(self.stubs)
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
|
@@ -139,9 +139,9 @@ def stubout_is_vdi_pv(stubs):
|
||||
|
||||
|
||||
def stubout_loopingcall_start(stubs):
|
||||
def f_1(self, interval, now=True):
|
||||
def fake_start(self, interval, now=True):
|
||||
self.f(*self.args, **self.kw)
|
||||
stubs.Set(utils.LoopingCall, 'start', f_1)
|
||||
stubs.Set(utils.LoopingCall, 'start', fake_start)
|
||||
|
||||
|
||||
class FakeSessionForVMTests(fake.SessionBase):
|
||||
|
Reference in New Issue
Block a user