bring back commits lost in merge
This commit is contained in:
107
nova/rpc.py
107
nova/rpc.py
@@ -35,6 +35,7 @@ from carrot import connection as carrot_connection
|
|||||||
from carrot import messaging
|
from carrot import messaging
|
||||||
import eventlet
|
import eventlet
|
||||||
from eventlet import greenpool
|
from eventlet import greenpool
|
||||||
|
from eventlet import greenthread
|
||||||
from eventlet import pools
|
from eventlet import pools
|
||||||
from eventlet import queue
|
from eventlet import queue
|
||||||
|
|
||||||
@@ -140,30 +141,30 @@ class Consumer(messaging.Consumer):
|
|||||||
FLAGS.rabbit_max_retries)
|
FLAGS.rabbit_max_retries)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False):
|
#def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False):
|
||||||
"""Wraps the parent fetch with some logic for failed connection."""
|
# """Wraps the parent fetch with some logic for failed connection."""
|
||||||
# TODO(vish): the logic for failed connections and logging should be
|
# # TODO(vish): the logic for failed connections and logging should be
|
||||||
# refactored into some sort of connection manager object
|
# # refactored into some sort of connection manager object
|
||||||
try:
|
# try:
|
||||||
if self.failed_connection:
|
# if self.failed_connection:
|
||||||
# NOTE(vish): connection is defined in the parent class, we can
|
# # NOTE(vish): connection is defined in the parent class, we can
|
||||||
# recreate it as long as we create the backend too
|
# # recreate it as long as we create the backend too
|
||||||
# pylint: disable=W0201
|
# # pylint: disable=W0201
|
||||||
self.connection = Connection.recreate()
|
# self.connection = Connection.recreate()
|
||||||
self.backend = self.connection.create_backend()
|
# self.backend = self.connection.create_backend()
|
||||||
self.declare()
|
# self.declare()
|
||||||
return super(Consumer, self).fetch(
|
# return super(Consumer, self).fetch(
|
||||||
no_ack, auto_ack, enable_callbacks)
|
# no_ack, auto_ack, enable_callbacks)
|
||||||
if self.failed_connection:
|
# if self.failed_connection:
|
||||||
LOG.error(_('Reconnected to queue'))
|
# LOG.error(_('Reconnected to queue'))
|
||||||
self.failed_connection = False
|
# self.failed_connection = False
|
||||||
# NOTE(vish): This is catching all errors because we really don't
|
# # NOTE(vish): This is catching all errors because we really don't
|
||||||
# want exceptions to be logged 10 times a second if some
|
# # want exceptions to be logged 10 times a second if some
|
||||||
# persistent failure occurs.
|
# # persistent failure occurs.
|
||||||
except Exception, e: # pylint: disable=W0703
|
# except Exception, e: # pylint: disable=W0703
|
||||||
if not self.failed_connection:
|
# if not self.failed_connection:
|
||||||
LOG.exception(_('Failed to fetch message from queue: %s' % e))
|
# LOG.exception(_('Failed to fetch message from queue: %s' % e))
|
||||||
self.failed_connection = True
|
# self.failed_connection = True
|
||||||
|
|
||||||
def attach_to_eventlet(self):
|
def attach_to_eventlet(self):
|
||||||
"""Only needed for unit tests!"""
|
"""Only needed for unit tests!"""
|
||||||
@@ -195,7 +196,7 @@ class AdapterConsumer(Consumer):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
LOG.debug(_('received %s') % message_data)
|
LOG.debug(_('received %s') % message_data)
|
||||||
msg_id = message_data.pop('_msg_id', None)
|
msg_id = message_data.get('_msg_id', None)
|
||||||
|
|
||||||
ctxt = _unpack_context(message_data)
|
ctxt = _unpack_context(message_data)
|
||||||
|
|
||||||
@@ -225,11 +226,14 @@ class AdapterConsumer(Consumer):
|
|||||||
rval = node_func(context=ctxt, **node_args)
|
rval = node_func(context=ctxt, **node_args)
|
||||||
if msg_id:
|
if msg_id:
|
||||||
# TODO(termie): re-enable when fix the yielding issue
|
# TODO(termie): re-enable when fix the yielding issue
|
||||||
#if hasattr(rval, 'send'):
|
if hasattr(rval, 'send'):
|
||||||
# logging.error('rval! %s', rval)
|
logging.error('rval! %s', rval)
|
||||||
# for x in rval:
|
for x in rval:
|
||||||
# msg_reply(msg_id, x, None)
|
msg_reply(msg_id, x, None)
|
||||||
msg_reply(msg_id, rval, None)
|
msg_reply(msg_id, None, None)
|
||||||
|
else:
|
||||||
|
msg_reply(msg_id, rval, None)
|
||||||
|
#msg_reply(msg_id, rval, None)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.exception('Exception during message handling')
|
logging.exception('Exception during message handling')
|
||||||
if msg_id:
|
if msg_id:
|
||||||
@@ -355,7 +359,7 @@ class DirectConsumer(Consumer):
|
|||||||
self.routing_key = msg_id
|
self.routing_key = msg_id
|
||||||
self.exchange = msg_id
|
self.exchange = msg_id
|
||||||
self.auto_delete = True
|
self.auto_delete = True
|
||||||
self.exclusive = True
|
self.exclusive = False
|
||||||
super(DirectConsumer, self).__init__(connection=connection)
|
super(DirectConsumer, self).__init__(connection=connection)
|
||||||
|
|
||||||
|
|
||||||
@@ -387,7 +391,9 @@ def msg_reply(msg_id, reply=None, failure=None):
|
|||||||
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})
|
||||||
|
LOG.error('MSG REPLY SUCCESS')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
LOG.error('MSG REPLY FAILURE')
|
||||||
publisher.send(
|
publisher.send(
|
||||||
{'result': dict((k, repr(v))
|
{'result': dict((k, repr(v))
|
||||||
for k, v in reply.__dict__.iteritems()),
|
for k, v in reply.__dict__.iteritems()),
|
||||||
@@ -440,9 +446,9 @@ def _pack_context(msg, context):
|
|||||||
for args at some point.
|
for args at some point.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
context = dict([('_context_%s' % key, value)
|
context_d = dict([('_context_%s' % key, value)
|
||||||
for (key, value) in context.to_dict().iteritems()])
|
for (key, value) in context.to_dict().iteritems()])
|
||||||
msg.update(context)
|
msg.update(context_d)
|
||||||
|
|
||||||
|
|
||||||
class RpcContext(context.RequestContext):
|
class RpcContext(context.RequestContext):
|
||||||
@@ -463,12 +469,13 @@ def multicall(context, topic, msg):
|
|||||||
LOG.debug(_('MSG_ID is %s') % (msg_id))
|
LOG.debug(_('MSG_ID is %s') % (msg_id))
|
||||||
_pack_context(msg, context)
|
_pack_context(msg, context)
|
||||||
|
|
||||||
conn = ConnectionPool.get()
|
con_conn = ConnectionPool.get()
|
||||||
consumer = DirectConsumer(connection=conn, msg_id=msg_id)
|
consumer = DirectConsumer(connection=con_conn, msg_id=msg_id)
|
||||||
wait_msg = MulticallWaiter(consumer)
|
wait_msg = MulticallWaiter(consumer)
|
||||||
consumer.register_callback(wait_msg)
|
consumer.register_callback(wait_msg)
|
||||||
|
|
||||||
publisher = TopicPublisher(connection=conn, topic=topic)
|
pub_conn = ConnectionPool.get()
|
||||||
|
publisher = TopicPublisher(connection=pub_conn, topic=topic)
|
||||||
publisher.send(msg)
|
publisher.send(msg)
|
||||||
publisher.close()
|
publisher.close()
|
||||||
|
|
||||||
@@ -484,6 +491,7 @@ class MulticallWaiter(object):
|
|||||||
def close(self):
|
def close(self):
|
||||||
self._closed = True
|
self._closed = True
|
||||||
self._consumer.close()
|
self._consumer.close()
|
||||||
|
ConnectionPool.put(self._consumer.connection)
|
||||||
|
|
||||||
def __call__(self, data, message):
|
def __call__(self, data, message):
|
||||||
"""Acks message and sets result."""
|
"""Acks message and sets result."""
|
||||||
@@ -501,15 +509,26 @@ class MulticallWaiter(object):
|
|||||||
# trying to solve the problem quickly. This works but
|
# trying to solve the problem quickly. This works but
|
||||||
# I'd prefer to dig in and do it the best way later on.
|
# I'd prefer to dig in and do it the best way later on.
|
||||||
|
|
||||||
def _waiter():
|
#def _waiter():
|
||||||
while not self._closed:
|
# i = 0
|
||||||
try:
|
# while not self._closed:
|
||||||
self._consumer.wait(limit=1)
|
# LOG.error('Iteration #%s (%s)', i, self._consumer.consumer_tag)
|
||||||
except StopIteration:
|
# i += 1
|
||||||
pass
|
# try:
|
||||||
eventlet.spawn(_waiter)
|
# self._consumer.wait(limit=1)
|
||||||
|
# except StopIteration:
|
||||||
|
# pass
|
||||||
|
# self._consumer.close()
|
||||||
|
# ConnectionPool.put(self._consumer.connection)
|
||||||
|
#eventlet.spawn(_waiter)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
rv = None
|
||||||
|
while rv is None and not self._closed:
|
||||||
|
rv = self._consumer.fetch(enable_callbacks=True)
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
LOG.error('RV %s', rv)
|
||||||
result = self._results.get()
|
result = self._results.get()
|
||||||
if isinstance(result, Exception):
|
if isinstance(result, Exception):
|
||||||
raise result
|
raise result
|
||||||
|
|||||||
@@ -61,6 +61,18 @@ class RpcTestCase(test.TestCase):
|
|||||||
self.assertEqual(value + i, x)
|
self.assertEqual(value + i, x)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
|
def test_multicall_succeed_three_times_yield(self):
|
||||||
|
"""Get a value through rpc call"""
|
||||||
|
value = 42
|
||||||
|
result = rpc.multicall(self.context,
|
||||||
|
'test',
|
||||||
|
{"method": "echo_three_times_yield",
|
||||||
|
"args": {"value": value}})
|
||||||
|
i = 0
|
||||||
|
for x in result:
|
||||||
|
self.assertEqual(value + i, x)
|
||||||
|
i += 1
|
||||||
|
|
||||||
def test_context_passed(self):
|
def test_context_passed(self):
|
||||||
"""Makes sure a context is passed through rpc call"""
|
"""Makes sure a context is passed through rpc call"""
|
||||||
value = 42
|
value = 42
|
||||||
@@ -83,6 +95,7 @@ class RpcTestCase(test.TestCase):
|
|||||||
'test',
|
'test',
|
||||||
{"method": "fail",
|
{"method": "fail",
|
||||||
"args": {"value": value}})
|
"args": {"value": value}})
|
||||||
|
LOG.error('INNNNNNN BETTTWWWWWWWWWWEEEEEEEEEEN')
|
||||||
try:
|
try:
|
||||||
rpc.call(self.context,
|
rpc.call(self.context,
|
||||||
'test',
|
'test',
|
||||||
@@ -186,6 +199,12 @@ class TestReceiver(object):
|
|||||||
context.reply(value + 1)
|
context.reply(value + 1)
|
||||||
context.reply(value + 2)
|
context.reply(value + 2)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def echo_three_times_yield(context, value):
|
||||||
|
yield value
|
||||||
|
yield value + 1
|
||||||
|
yield value + 2
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fail(context, value):
|
def fail(context, value):
|
||||||
"""Raises an exception with the value sent in"""
|
"""Raises an exception with the value sent in"""
|
||||||
|
|||||||
Reference in New Issue
Block a user