Moves the ip allocation requests to the from the api host into calls to the network host made from the compute host.

This commit is contained in:
Vishvananda Ishaya
2010-12-22 22:04:30 +00:00
committed by Tarmac
8 changed files with 106 additions and 94 deletions

View File

@@ -25,6 +25,10 @@ from carrot.backends import base
from eventlet import greenthread from eventlet import greenthread
EXCHANGES = {}
QUEUES = {}
class Message(base.BaseMessage): class Message(base.BaseMessage):
pass pass
@@ -68,81 +72,63 @@ class Queue(object):
return self._queue.get() return self._queue.get()
class Backend(object): class Backend(base.BaseBackend):
""" Singleton backend for testing """ def queue_declare(self, queue, **kwargs):
class __impl(base.BaseBackend): global QUEUES
def __init__(self, *args, **kwargs): if queue not in QUEUES:
#super(__impl, self).__init__(*args, **kwargs) logging.debug(_('Declaring queue %s'), queue)
self._exchanges = {} QUEUES[queue] = Queue(queue)
self._queues = {}
def _reset_all(self): def exchange_declare(self, exchange, type, *args, **kwargs):
self._exchanges = {} global EXCHANGES
self._queues = {} if exchange not in EXCHANGES:
logging.debug(_('Declaring exchange %s'), exchange)
EXCHANGES[exchange] = Exchange(exchange, type)
def queue_declare(self, queue, **kwargs): def queue_bind(self, queue, exchange, routing_key, **kwargs):
if queue not in self._queues: global EXCHANGES
logging.debug(_('Declaring queue %s'), queue) global QUEUES
self._queues[queue] = Queue(queue) logging.debug(_('Binding %s to %s with key %s'),
queue, exchange, routing_key)
EXCHANGES[exchange].bind(QUEUES[queue].push, routing_key)
def exchange_declare(self, exchange, type, *args, **kwargs): def declare_consumer(self, queue, callback, *args, **kwargs):
if exchange not in self._exchanges: self.current_queue = queue
logging.debug(_('Declaring exchange %s'), exchange) self.current_callback = callback
self._exchanges[exchange] = Exchange(exchange, type)
def queue_bind(self, queue, exchange, routing_key, **kwargs): def consume(self, limit=None):
logging.debug(_('Binding %s to %s with key %s'), while True:
queue, exchange, routing_key) item = self.get(self.current_queue)
self._exchanges[exchange].bind(self._queues[queue].push, if item:
routing_key) self.current_callback(item)
raise StopIteration()
greenthread.sleep(0)
def declare_consumer(self, queue, callback, *args, **kwargs): def get(self, queue, no_ack=False):
self.current_queue = queue global QUEUES
self.current_callback = callback if not queue in QUEUES or not QUEUES[queue].size():
return None
(message_data, content_type, content_encoding) = QUEUES[queue].pop()
message = Message(backend=self, body=message_data,
content_type=content_type,
content_encoding=content_encoding)
message.result = True
logging.debug(_('Getting from %s: %s'), queue, message)
return message
def consume(self, *args, **kwargs): def prepare_message(self, message_data, delivery_mode,
while True: content_type, content_encoding, **kwargs):
item = self.get(self.current_queue) """Prepare message for sending."""
if item: return (message_data, content_type, content_encoding)
self.current_callback(item)
raise StopIteration()
greenthread.sleep(0)
def get(self, queue, no_ack=False): def publish(self, message, exchange, routing_key, **kwargs):
if not queue in self._queues or not self._queues[queue].size(): global EXCHANGES
return None if exchange in EXCHANGES:
(message_data, content_type, content_encoding) = \ EXCHANGES[exchange].publish(message, routing_key=routing_key)
self._queues[queue].pop()
message = Message(backend=self, body=message_data,
content_type=content_type,
content_encoding=content_encoding)
message.result = True
logging.debug(_('Getting from %s: %s'), queue, message)
return message
def prepare_message(self, message_data, delivery_mode,
content_type, content_encoding, **kwargs):
"""Prepare message for sending."""
return (message_data, content_type, content_encoding)
def publish(self, message, exchange, routing_key, **kwargs):
if exchange in self._exchanges:
self._exchanges[exchange].publish(
message, routing_key=routing_key)
__instance = None
def __init__(self, *args, **kwargs):
if Backend.__instance is None:
Backend.__instance = Backend.__impl(*args, **kwargs)
self.__dict__['_Backend__instance'] = Backend.__instance
def __getattr__(self, attr):
return getattr(self.__instance, attr)
def __setattr__(self, attr, value):
return setattr(self.__instance, attr, value)
def reset_all(): def reset_all():
Backend()._reset_all() global EXCHANGES
global QUEUES
EXCHANGES = {}
QUEUES = {}

View File

@@ -245,7 +245,7 @@ def msg_reply(msg_id, reply=None, failure=None):
logging.error(_("Returning exception %s to caller"), message) logging.error(_("Returning exception %s to caller"), message)
logging.error(tb) logging.error(tb)
failure = (failure[0].__name__, str(failure[1]), tb) failure = (failure[0].__name__, str(failure[1]), tb)
conn = Connection.instance() conn = Connection.instance(True)
publisher = DirectPublisher(connection=conn, msg_id=msg_id) publisher = DirectPublisher(connection=conn, msg_id=msg_id)
try: try:
publisher.send({'result': reply, 'failure': failure}) publisher.send({'result': reply, 'failure': failure})

View File

@@ -22,20 +22,18 @@ import logging
from M2Crypto import BIO from M2Crypto import BIO
from M2Crypto import RSA from M2Crypto import RSA
import os import os
import StringIO
import tempfile import tempfile
import time import time
from eventlet import greenthread from eventlet import greenthread
from xml.etree import ElementTree
from nova import context from nova import context
from nova import crypto from nova import crypto
from nova import db from nova import db
from nova import flags from nova import flags
from nova import rpc from nova import rpc
from nova import service
from nova import test from nova import test
from nova import utils
from nova.auth import manager from nova.auth import manager
from nova.compute import power_state from nova.compute import power_state
from nova.api.ec2 import cloud from nova.api.ec2 import cloud
@@ -54,7 +52,8 @@ os.makedirs(IMAGES_PATH)
class CloudTestCase(test.TestCase): class CloudTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(CloudTestCase, self).setUp() super(CloudTestCase, self).setUp()
self.flags(connection_type='fake', images_path=IMAGES_PATH) self.flags(connection_type='fake',
images_path=IMAGES_PATH)
self.conn = rpc.Connection.instance() self.conn = rpc.Connection.instance()
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
@@ -62,27 +61,23 @@ class CloudTestCase(test.TestCase):
# set up our cloud # set up our cloud
self.cloud = cloud.CloudController() self.cloud = cloud.CloudController()
# set up a service # set up services
self.compute = utils.import_object(FLAGS.compute_manager) self.compute = service.Service.create(binary='nova-compute')
self.compute_consumer = rpc.AdapterConsumer(connection=self.conn, self.compute.start()
topic=FLAGS.compute_topic, self.network = service.Service.create(binary='nova-network')
proxy=self.compute) self.network.start()
self.compute_consumer.attach_to_eventlet()
self.network = utils.import_object(FLAGS.network_manager)
self.network_consumer = rpc.AdapterConsumer(connection=self.conn,
topic=FLAGS.network_topic,
proxy=self.network)
self.network_consumer.attach_to_eventlet()
self.manager = manager.AuthManager() self.manager = manager.AuthManager()
self.user = self.manager.create_user('admin', 'admin', 'admin', True) self.user = self.manager.create_user('admin', 'admin', 'admin', True)
self.project = self.manager.create_project('proj', 'admin', 'proj') self.project = self.manager.create_project('proj', 'admin', 'proj')
self.context = context.RequestContext(user=self.user, self.context = context.RequestContext(user=self.user,
project=self.project) project=self.project)
def tearDown(self): def tearDown(self):
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
self.compute.kill()
self.network.kill()
super(CloudTestCase, self).tearDown() super(CloudTestCase, self).tearDown()
def _create_key(self, name): def _create_key(self, name):
@@ -109,12 +104,13 @@ class CloudTestCase(test.TestCase):
{'address': address, {'address': address,
'host': FLAGS.host}) 'host': FLAGS.host})
self.cloud.allocate_address(self.context) self.cloud.allocate_address(self.context)
inst = db.instance_create(self.context, {}) inst = db.instance_create(self.context, {'host': FLAGS.host})
fixed = self.network.allocate_fixed_ip(self.context, inst['id']) fixed = self.network.allocate_fixed_ip(self.context, inst['id'])
ec2_id = cloud.internal_id_to_ec2_id(inst['internal_id']) ec2_id = cloud.internal_id_to_ec2_id(inst['internal_id'])
self.cloud.associate_address(self.context, self.cloud.associate_address(self.context,
instance_id=ec2_id, instance_id=ec2_id,
public_ip=address) public_ip=address)
greenthread.sleep(0.3)
self.cloud.disassociate_address(self.context, self.cloud.disassociate_address(self.context,
public_ip=address) public_ip=address)
self.cloud.release_address(self.context, self.cloud.release_address(self.context,

View File

@@ -41,6 +41,7 @@ class ComputeTestCase(test.TestCase):
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
super(ComputeTestCase, self).setUp() super(ComputeTestCase, self).setUp()
self.flags(connection_type='fake', self.flags(connection_type='fake',
stub_network=True,
network_manager='nova.network.manager.FlatManager') network_manager='nova.network.manager.FlatManager')
self.compute = utils.import_object(FLAGS.compute_manager) self.compute = utils.import_object(FLAGS.compute_manager)
self.compute_api = compute_api.ComputeAPI() self.compute_api = compute_api.ComputeAPI()

View File

@@ -26,6 +26,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 service
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
@@ -40,6 +41,7 @@ class NetworkTestCase(test.TestCase):
# NOTE(vish): if you change these flags, make sure to change the # NOTE(vish): if you change these flags, make sure to change the
# flags in the corresponding section in nova-dhcpbridge # flags in the corresponding section in nova-dhcpbridge
self.flags(connection_type='fake', self.flags(connection_type='fake',
fake_call=True,
fake_network=True, fake_network=True,
network_size=16, network_size=16,
num_networks=5) num_networks=5)
@@ -56,16 +58,13 @@ class NetworkTestCase(test.TestCase):
# create the necessary network data for the project # create the necessary network data for the project
user_context = context.RequestContext(project=self.projects[i], user_context = context.RequestContext(project=self.projects[i],
user=self.user) user=self.user)
network_ref = self.network.get_network(user_context) host = self.network.get_network_host(user_context.elevated())
self.network.set_network_host(context.get_admin_context(),
network_ref['id'])
instance_ref = self._create_instance(0) instance_ref = self._create_instance(0)
self.instance_id = instance_ref['id'] self.instance_id = instance_ref['id']
instance_ref = self._create_instance(1) instance_ref = self._create_instance(1)
self.instance2_id = instance_ref['id'] self.instance2_id = instance_ref['id']
def tearDown(self): def tearDown(self):
super(NetworkTestCase, self).tearDown()
# TODO(termie): this should really be instantiating clean datastores # TODO(termie): this should really be instantiating clean datastores
# in between runs, one failure kills all the tests # in between runs, one failure kills all the tests
db.instance_destroy(context.get_admin_context(), self.instance_id) db.instance_destroy(context.get_admin_context(), self.instance_id)
@@ -73,6 +72,7 @@ class NetworkTestCase(test.TestCase):
for project in self.projects: for project in self.projects:
self.manager.delete_project(project) self.manager.delete_project(project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
super(NetworkTestCase, self).tearDown()
def _create_instance(self, project_num, mac=None): def _create_instance(self, project_num, mac=None):
if not mac: if not mac:

View File

@@ -33,7 +33,7 @@ class RpcTestCase(test.TestCase):
"""Test cases for rpc""" """Test cases for rpc"""
def setUp(self): def setUp(self):
super(RpcTestCase, self).setUp() super(RpcTestCase, self).setUp()
self.conn = rpc.Connection.instance() self.conn = rpc.Connection.instance(True)
self.receiver = TestReceiver() self.receiver = TestReceiver()
self.consumer = rpc.AdapterConsumer(connection=self.conn, self.consumer = rpc.AdapterConsumer(connection=self.conn,
topic='test', topic='test',
@@ -79,6 +79,33 @@ class RpcTestCase(test.TestCase):
except rpc.RemoteError as exc: except rpc.RemoteError as exc:
self.assertEqual(int(exc.value), value) self.assertEqual(int(exc.value), value)
def test_nested_calls(self):
"""Test that we can do an rpc.call inside another call"""
class Nested(object):
@staticmethod
def echo(context, queue, value):
"""Calls echo in the passed queue"""
logging.debug("Nested received %s, %s", queue, value)
ret = rpc.call(context,
queue,
{"method": "echo",
"args": {"value": value}})
logging.debug("Nested return %s", ret)
return value
nested = Nested()
conn = rpc.Connection.instance(True)
consumer = rpc.AdapterConsumer(connection=conn,
topic='nested',
proxy=nested)
consumer.attach_to_eventlet()
value = 42
result = rpc.call(self.context,
'nested', {"method": "echo",
"args": {"queue": "test",
"value": value}})
self.assertEqual(value, result)
class TestReceiver(object): class TestReceiver(object):
"""Simple Proxy class so the consumer has methods to call """Simple Proxy class so the consumer has methods to call

View File

@@ -78,6 +78,7 @@ class SimpleDriverTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(SimpleDriverTestCase, self).setUp() super(SimpleDriverTestCase, self).setUp()
self.flags(connection_type='fake', self.flags(connection_type='fake',
stub_network=True,
max_cores=4, max_cores=4,
max_gigabytes=4, max_gigabytes=4,
network_manager='nova.network.manager.FlatManager', network_manager='nova.network.manager.FlatManager',

View File

@@ -33,6 +33,7 @@ flags.DECLARE('instances_path', 'nova.compute.manager')
class LibvirtConnTestCase(test.TestCase): class LibvirtConnTestCase(test.TestCase):
def setUp(self): def setUp(self):
super(LibvirtConnTestCase, self).setUp() super(LibvirtConnTestCase, self).setUp()
self.flags(fake_call=True)
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)
@@ -88,9 +89,9 @@ class LibvirtConnTestCase(test.TestCase):
user_context = context.RequestContext(project=self.project, user_context = context.RequestContext(project=self.project,
user=self.user) user=self.user)
instance_ref = db.instance_create(user_context, instance) instance_ref = db.instance_create(user_context, instance)
network_ref = self.network.get_network(user_context) host = self.network.get_network_host(user_context.elevated())
self.network.set_network_host(context.get_admin_context(), network_ref = db.project_get_network(context.get_admin_context(),
network_ref['id']) self.project.id)
fixed_ip = {'address': self.test_ip, fixed_ip = {'address': self.test_ip,
'network_id': network_ref['id']} 'network_id': network_ref['id']}