Review changes and merge from trunk

This commit is contained in:
Cerberus
2011-05-16 10:54:02 -05:00
10 changed files with 78 additions and 50 deletions

View File

@@ -29,6 +29,7 @@
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local> <matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
<matt.dietz@rackspace.com> <mdietz@openstack> <matt.dietz@rackspace.com> <mdietz@openstack>
<mordred@inaugust.com> <mordred@hudson> <mordred@inaugust.com> <mordred@hudson>
<naveedm9@gmail.com> <naveed.massjouni@rackspace.com>
<nirmal.ranganathan@rackspace.com> <nirmal.ranganathan@rackspace.coom> <nirmal.ranganathan@rackspace.com> <nirmal.ranganathan@rackspace.coom>
<paul@openstack.org> <paul.voccio@rackspace.com> <paul@openstack.org> <paul.voccio@rackspace.com>
<paul@openstack.org> <pvoccio@castor.local> <paul@openstack.org> <pvoccio@castor.local>
@@ -36,6 +37,7 @@
<rlane@wikimedia.org> <laner@controller> <rlane@wikimedia.org> <laner@controller>
<sleepsonthefloor@gmail.com> <root@tonbuntu> <sleepsonthefloor@gmail.com> <root@tonbuntu>
<soren.hansen@rackspace.com> <soren@linux2go.dk> <soren.hansen@rackspace.com> <soren@linux2go.dk>
<throughnothing@gmail.com> <will.wolf@rackspace.com>
<todd@ansolabs.com> <todd@lapex> <todd@ansolabs.com> <todd@lapex>
<todd@ansolabs.com> <todd@rubidine.com> <todd@ansolabs.com> <todd@rubidine.com>
<tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in> <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
@@ -44,5 +46,4 @@
<ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp> <ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp>
<vishvananda@gmail.com> <root@mirror.nasanebula.net> <vishvananda@gmail.com> <root@mirror.nasanebula.net>
<vishvananda@gmail.com> <root@ubuntu> <vishvananda@gmail.com> <root@ubuntu>
<naveedm9@gmail.com> <naveed.massjouni@rackspace.com>
<vishvananda@gmail.com> <vishvananda@yahoo.com> <vishvananda@gmail.com> <vishvananda@yahoo.com>

View File

@@ -80,7 +80,7 @@ Trey Morris <trey.morris@rackspace.com>
Tushar Patil <tushar.vitthal.patil@gmail.com> Tushar Patil <tushar.vitthal.patil@gmail.com>
Vasiliy Shlykov <vash@vasiliyshlykov.org> Vasiliy Shlykov <vash@vasiliyshlykov.org>
Vishvananda Ishaya <vishvananda@gmail.com> Vishvananda Ishaya <vishvananda@gmail.com>
William Wolf <will.wolf@rackspace.com> William Wolf <throughnothing@gmail.com>
Yoshiaki Tamura <yoshi@midokura.jp> Yoshiaki Tamura <yoshi@midokura.jp>
Youcef Laribi <Youcef.Laribi@eu.citrix.com> Youcef Laribi <Youcef.Laribi@eu.citrix.com>
Yuriy Taraday <yorik.sar@gmail.com> Yuriy Taraday <yorik.sar@gmail.com>

View File

@@ -37,7 +37,7 @@ class BadPriorityException(Exception):
pass pass
def notify(event_name, publisher_id, event_type, priority, payload): def notify(event_name, publisher_id, event_type, priority, message):
""" """
Sends a notification using the specified driver Sends a notification using the specified driver
@@ -49,11 +49,11 @@ def notify(event_name, publisher_id, event_type, priority, payload):
event_type - the literal type of event (ex. Instance Creation) event_type - the literal type of event (ex. Instance Creation)
priority - patterned after the enumeration of Python logging levels in priority - patterned after the enumeration of Python logging levels in
the set (DEBUG, WARN, INFO, ERROR, CRITICAL) the set (DEBUG, WARN, INFO, ERROR, CRITICAL)
payload - A python dictionary of attributes message - A python dictionary of attributes
The message body will be constructed as a dictionary of the above The message payload will be constructed as a dictionary of the above
attributes, and converted into a JSON dump, which will then be sent attributes, which will then be sent via the transport mechanism defined
via the transport mechanism defined by the driver. by the driver.
Message example: Message example:
@@ -62,16 +62,17 @@ def notify(event_name, publisher_id, event_type, priority, payload):
'timestamp': datetime.datetime.utcnow(), 'timestamp': datetime.datetime.utcnow(),
'priority': 'WARN', 'priority': 'WARN',
'event_type': 'compute.create_instance', 'event_type': 'compute.create_instance',
'payload': {'instance_id': 12, ... }} 'message': {'instance_id': 12, ... }}
""" """
if priority not in log_levels: if priority not in log_levels:
raise BadPriorityException('%s not in valid priorities' % priority) raise BadPriorityException(
_('%s not in valid priorities' % priority))
driver = utils.import_class(FLAGS.notification_driver)() driver = utils.import_class(FLAGS.notification_driver)()
message = dict(message_id=str(uuid.uuid4()), msg = dict(message_id=str(uuid.uuid4()),
publisher_id=publisher_id, publisher_id=publisher_id,
event_type=event_type, event_type=event_type,
priority=priority, priority=priority,
payload=payload, message=message,
timestamp=str(datetime.datetime.utcnow())) timestamp=str(datetime.datetime.utcnow()))
driver.notify(message) driver.notify(msg)

View File

@@ -22,13 +22,13 @@ FLAGS = flags.FLAGS
class LogNotifier(object): class LogNotifier(object):
""" log notifications using nova's default logging system """ """Log notifications using nova's default logging system"""
def notify(self, payload): def notify(self, message):
"""Notifies the recipient of the desired event given the model""" """Notifies the recipient of the desired event given the model"""
priority = payload.get('priority', priority = message.get('priority',
FLAGS.default_notification_level) FLAGS.default_notification_level)
priority = priority.lower() priority = priority.lower()
logger = logging.getLogger( logger = logging.getLogger(
'nova.notification.%s' % payload['event_type']) 'nova.notification.%s' % message['event_type'])
getattr(logger, priority)(json.dumps(payload)) getattr(logger, priority)(json.dumps(message))

View File

@@ -17,6 +17,6 @@
class NoopNotifier(object): class NoopNotifier(object):
"""A notifier that doesn't actually do anything. Simply a placeholder""" """A notifier that doesn't actually do anything. Simply a placeholder"""
def notify(self, payload): def notify(self, message):
"""Notifies the recipient of the desired event given the model""" """Notifies the recipient of the desired event given the model"""
pass pass

View File

@@ -28,11 +28,11 @@ flags.DEFINE_string('notification_topic', 'notifications',
class RabbitNotifier(object): class RabbitNotifier(object):
"""Sends notifications to a specific RabbitMQ server and topic""" """Sends notifications to a specific RabbitMQ server and topic"""
def notify(self, payload): def notify(self, message):
"""Sends a notification to the RabbitMQ""" """Sends a notification to the RabbitMQ"""
context = nova.context.get_admin_context() context = nova.context.get_admin_context()
priority = payload.get('priority', priority = message.get('priority',
FLAGS.default_notification_level) FLAGS.default_notification_level)
priority = priority.lower() priority = priority.lower()
topic = '%s.%s' % (FLAGS.notification_topic, priority) topic = '%s.%s' % (FLAGS.notification_topic, priority)
rpc.cast(context, topic, payload) rpc.cast(context, topic, message)

View File

@@ -279,6 +279,26 @@ class CloudTestCase(test.TestCase):
user_group=['all']) user_group=['all'])
self.assertEqual(True, result['is_public']) self.assertEqual(True, result['is_public'])
def test_deregister_image(self):
deregister_image = self.cloud.deregister_image
def fake_delete(self, context, id):
return None
self.stubs.Set(local.LocalImageService, 'delete', fake_delete)
# valid image
result = deregister_image(self.context, 'ami-00000001')
self.assertEqual(result['imageId'], 'ami-00000001')
# invalid image
self.stubs.UnsetAll()
def fake_detail_empty(self, context):
return []
self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty)
self.assertRaises(exception.ImageNotFound, deregister_image,
self.context, 'ami-bad001')
def test_console_output(self): def test_console_output(self):
instance_type = FLAGS.default_instance_type instance_type = FLAGS.default_instance_type
max_count = 1 max_count = 1

View File

@@ -60,7 +60,7 @@ class NotifierTestCase(test.TestCase):
fields = [('publisher_id', 'publisher_id'), fields = [('publisher_id', 'publisher_id'),
('event_type', 'event_type'), ('event_type', 'event_type'),
('priority', 'WARN'), ('priority', 'WARN'),
('payload', dict(a=3))] ('message', dict(a=3))]
for k, v in fields: for k, v in fields:
self.assertEqual(message[k], v) self.assertEqual(message[k], v)
self.assertTrue(len(message['message_id']) > 0) self.assertTrue(len(message['message_id']) > 0)

View File

@@ -16,6 +16,7 @@
"""Test suite for XenAPI.""" """Test suite for XenAPI."""
import eventlet
import functools import functools
import json import json
import os import os
@@ -198,6 +199,28 @@ class XenAPIVMTestCase(test.TestCase):
self.context = context.RequestContext('fake', 'fake', False) self.context = context.RequestContext('fake', 'fake', False)
self.conn = xenapi_conn.get_connection(False) self.conn = xenapi_conn.get_connection(False)
def test_parallel_builds(self):
stubs.stubout_loopingcall_delay(self.stubs)
def _do_build(id, proj, user, *args):
values = {
'id': id,
'project_id': proj,
'user_id': user,
'image_id': 1,
'kernel_id': 2,
'ramdisk_id': 3,
'instance_type_id': '3', # m1.large
'mac_address': 'aa:bb:cc:dd:ee:ff',
'os_type': 'linux'}
instance = db.instance_create(self.context, values)
self.conn.spawn(instance)
gt1 = eventlet.spawn(_do_build, 1, self.project.id, self.user.id)
gt2 = eventlet.spawn(_do_build, 2, self.project.id, self.user.id)
gt1.wait()
gt2.wait()
def test_list_instances_0(self): def test_list_instances_0(self):
instances = self.conn.list_instances() instances = self.conn.list_instances()
self.assertEquals(instances, []) self.assertEquals(instances, [])

View File

@@ -16,6 +16,7 @@
"""Stubouts, mocks and fixtures for the test suite""" """Stubouts, mocks and fixtures for the test suite"""
import eventlet
from nova.virt import xenapi_conn from nova.virt import xenapi_conn
from nova.virt.xenapi import fake from nova.virt.xenapi import fake
from nova.virt.xenapi import volume_utils from nova.virt.xenapi import volume_utils
@@ -28,29 +29,6 @@ def stubout_instance_snapshot(stubs):
@classmethod @classmethod
def fake_fetch_image(cls, session, instance_id, image, user, project, def fake_fetch_image(cls, session, instance_id, image, user, project,
type): type):
# Stubout wait_for_task
def fake_wait_for_task(self, task, id):
class FakeEvent:
def send(self, value):
self.rv = value
def wait(self):
return self.rv
done = FakeEvent()
self._poll_task(id, task, done)
rv = done.wait()
return rv
def fake_loop(self):
pass
stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task',
fake_wait_for_task)
stubs.Set(xenapi_conn.XenAPISession, '_stop_loop', fake_loop)
from nova.virt.xenapi.fake import create_vdi from nova.virt.xenapi.fake import create_vdi
name_label = "instance-%s" % instance_id name_label = "instance-%s" % instance_id
#TODO: create fake SR record #TODO: create fake SR record
@@ -63,11 +41,6 @@ def stubout_instance_snapshot(stubs):
stubs.Set(vm_utils.VMHelper, 'fetch_image', fake_fetch_image) stubs.Set(vm_utils.VMHelper, 'fetch_image', fake_fetch_image)
def fake_parse_xmlrpc_value(val):
return val
stubs.Set(xenapi_conn, '_parse_xmlrpc_value', fake_parse_xmlrpc_value)
def fake_wait_for_vhd_coalesce(session, instance_id, sr_ref, vdi_ref, def fake_wait_for_vhd_coalesce(session, instance_id, sr_ref, vdi_ref,
original_parent_uuid): original_parent_uuid):
from nova.virt.xenapi.fake import create_vdi from nova.virt.xenapi.fake import create_vdi
@@ -144,6 +117,16 @@ def stubout_loopingcall_start(stubs):
stubs.Set(utils.LoopingCall, 'start', fake_start) stubs.Set(utils.LoopingCall, 'start', fake_start)
def stubout_loopingcall_delay(stubs):
def fake_start(self, interval, now=True):
self._running = True
eventlet.sleep(1)
self.f(*self.args, **self.kw)
# This would fail before parallel xenapi calls were fixed
assert self._running == False
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):