Example #1
0
    def _process_data(self, msg_id, ctxt, method, args):
        """Thread that maigcally looks for a method on the proxy
        object and calls it.
        """

        node_func = getattr(self.proxy, str(method))
        node_args = dict((str(k), v) for k, v in args.iteritems())
        # NOTE(vish): magic is fun!
        try:
            rval = node_func(context=ctxt, **node_args)
            if msg_id:
                # Check if the result was a generator
                if isinstance(rval, types.GeneratorType):
                    for x in rval:
                        msg_reply(msg_id, x, None)
                else:
                    msg_reply(msg_id, rval, None)

                # This final None tells multicall that it is done.
                msg_reply(msg_id, None, None)
            elif isinstance(rval, types.GeneratorType):
                # NOTE(vish): this iterates through the generator
                list(rval)
        except Exception as e:
            LOG.exception('Exception during message handling')
            if msg_id:
                msg_reply(msg_id, None, sys.exc_info())
        return
Example #2
0
    def reconnect(self):
        """Handles reconnecting and re-estblishing queues"""
        if self.connection:
            try:
                self.connection.close()
            except self.connection.connection_errors:
                pass
            time.sleep(1)
        self.connection = kombu.connection.BrokerConnection(**self.params)
        if self.memory_transport:
            # Kludge to speed up tests.
            self.connection.transport.polling_interval = 0.0
        self.consumer_num = itertools.count(1)

        try:
            self.connection.ensure_connection(
                errback=self.connect_error,
                max_retries=self.max_retries,
                interval_start=self.interval_start,
                interval_step=self.interval_stepping,
                interval_max=self.interval_max)
        except self.connection.connection_errors, e:
            # We should only get here if max_retries is set.  We'll go
            # ahead and exit in this case.
            err_str = str(e)
            max_retries = self.max_retries
            LOG.error(
                _('Unable to connect to AMQP server '
                  'after %(max_retries)d tries: %(err_str)s') % locals())
            sys.exit(1)
Example #3
0
    def _process_data(self, msg_id, ctxt, method, args):
        """Thread that maigcally looks for a method on the proxy
        object and calls it.
        """

        node_func = getattr(self.proxy, str(method))
        node_args = dict((str(k), v) for k, v in args.iteritems())
        # NOTE(vish): magic is fun!
        try:
            rval = node_func(context=ctxt, **node_args)
            if msg_id:
                # Check if the result was a generator
                if isinstance(rval, types.GeneratorType):
                    for x in rval:
                        msg_reply(msg_id, x, None)
                else:
                    msg_reply(msg_id, rval, None)

                # This final None tells multicall that it is done.
                msg_reply(msg_id, None, None)
            elif isinstance(rval, types.GeneratorType):
                # NOTE(vish): this iterates through the generator
                list(rval)
        except Exception as e:
            LOG.exception('Exception during message handling')
            if msg_id:
                msg_reply(msg_id, None, sys.exc_info())
        return
Example #4
0
File: amqp.py Project: Jaesang/nova
    def __call__(self, message_data):
        """Consumer callback to call a method on a proxy object.

        Parses the message for validity and fires off a thread to call the
        proxy object method.

        Message data should be a dictionary with two keys:
            method: string representing the method to call
            args: dictionary of arg: value

        Example: {'method': 'echo', 'args': {'value': 42}}

        """
        # It is important to clear the context here, because at this point
        # the previous context is stored in local.store.context
        if hasattr(local.store, "context"):
            del local.store.context
        rpc_common._safe_log(LOG.debug, _("received %s"), message_data)
        ctxt = unpack_context(message_data)
        method = message_data.get("method")
        args = message_data.get("args", {})
        if not method:
            LOG.warn(_("no method for message: %s") % message_data)
            ctxt.reply(_("No method for message: %s") % message_data)
            return
        self.pool.spawn_n(self._process_data, ctxt, method, args)
Example #5
0
def send_message(topic, message, wait=True):
    """Sends a message for testing."""
    msg_id = uuid.uuid4().hex
    message.update({'_msg_id': msg_id})
    LOG.debug(_('topic is %s'), topic)
    LOG.debug(_('message %s'), message)

    if wait:
        consumer = messaging.Consumer(connection=Connection.instance(),
                                      queue=msg_id,
                                      exchange=msg_id,
                                      auto_delete=True,
                                      exchange_type='direct',
                                      routing_key=msg_id)
        consumer.register_callback(generic_response)

    publisher = messaging.Publisher(connection=Connection.instance(),
                                    exchange=FLAGS.control_exchange,
                                    durable=FLAGS.rabbit_durable_queues,
                                    exchange_type='topic',
                                    routing_key=topic)
    publisher.send(message)
    publisher.close()

    if wait:
        consumer.wait()
        consumer.close()
Example #6
0
def msg_reply(msg_id, connection_pool, reply=None, failure=None, ending=False):
    """Sends a reply or an error on the channel signified by msg_id.

    Failure should be a sys.exc_info() tuple.

    """
    with ConnectionContext(connection_pool) as conn:
        if failure:
            message = str(failure[1])
            tb = traceback.format_exception(*failure)
            LOG.error(_("Returning exception %s to caller"), message)
            LOG.error(tb)
            failure = (failure[0].__name__, str(failure[1]), tb)

        try:
            msg = {'result': reply, 'failure': failure}
        except TypeError:
            msg = {
                'result': dict(
                    (k, repr(v)) for k, v in reply.__dict__.iteritems()),
                'failure': failure
            }
        if ending:
            msg['ending'] = True
        conn.direct_send(msg_id, msg)
Example #7
0
 def __init__(self, topic, connection=None):
     self.exchange = "%s_fanout" % topic
     self.queue = "%s_fanout" % topic
     self.durable = False
     self.auto_delete = True
     LOG.info(_('Creating "%(exchange)s" fanout exchange'), dict(exchange=self.exchange))
     super(FanoutPublisher, self).__init__(connection=connection)
Example #8
0
 def fetch(self, no_ack=None, auto_ack=None, enable_callbacks=False):
     """Wraps the parent fetch with some logic for failed connection."""
     # TODO(vish): the logic for failed connections and logging should be
     #             refactored into some sort of connection manager object
     try:
         if self.failed_connection:
             # NOTE(vish): connection is defined in the parent class, we can
             #             recreate it as long as we create the backend too
             # pylint: disable=W0201
             self.connection = Connection.recreate()
             self.backend = self.connection.create_backend()
             self.declare()
         return super(Consumer, self).fetch(no_ack,
                                            auto_ack,
                                            enable_callbacks)
         if self.failed_connection:
             LOG.error(_('Reconnected to queue'))
             self.failed_connection = False
     # NOTE(vish): This is catching all errors because we really don't
     #             want exceptions to be logged 10 times a second if some
     #             persistent failure occurs.
     except Exception, e:  # pylint: disable=W0703
         if not self.failed_connection:
             LOG.exception(_('Failed to fetch message from queue: %s' % e))
             self.failed_connection = True
Example #9
0
 def __init__(self, connection=None, topic='broadcast', proxy=None):
     LOG.debug(_('Initing the Adapter Consumer for %s') % topic)
     self.proxy = proxy
     self.pool = greenpool.GreenPool(FLAGS.rpc_thread_pool_size)
     super(AdapterConsumer, self).__init__(connection=connection,
                                           topic=topic)
     self.register_callback(self.process_data)
Example #10
0
    def process_data(self, message_data, message):
        """Consumer callback to call a method on a proxy object.

        Parses the message for validity and fires off a thread to call the
        proxy object method.

        Message data should be a dictionary with two keys:
            method: string representing the method to call
            args: dictionary of arg: value

        Example: {'method': 'echo', 'args': {'value': 42}}

        """
        # It is important to clear the context here, because at this point
        # the previous context is stored in local.store.context
        if hasattr(local.store, 'context'):
            del local.store.context
        LOG.debug(_('received %s') % message_data)
        # This will be popped off in _unpack_context
        msg_id = message_data.get('_msg_id', None)
        ctxt = _unpack_context(message_data)

        method = message_data.get('method')
        args = message_data.get('args', {})
        message.ack()
        if not method:
            # NOTE(vish): we may not want to ack here, but that means that bad
            #             messages stay in the queue indefinitely, so for now
            #             we just log the message and send an error string
            #             back to the caller
            LOG.warn(_('no method for message: %s') % message_data)
            ctxt.reply(msg_id,
                    _('No method for message: %s') % message_data)
            return
        self.pool.spawn_n(self._process_data, ctxt, method, args)
Example #11
0
    def reconnect(self):
        """Handles reconnecting and re-establishing queues"""
        if self.connection:
            try:
                self.connection.close()
            except self.connection.connection_errors:
                pass
            time.sleep(1)
        self.connection = kombu.connection.BrokerConnection(**self.params)
        if self.memory_transport:
            # Kludge to speed up tests.
            self.connection.transport.polling_interval = 0.0
        self.consumer_num = itertools.count(1)

        try:
            self.connection.ensure_connection(errback=self.connect_error,
                    max_retries=self.max_retries,
                    interval_start=self.interval_start,
                    interval_step=self.interval_stepping,
                    interval_max=self.interval_max)
        except self.connection.connection_errors, e:
            # We should only get here if max_retries is set.  We'll go
            # ahead and exit in this case.
            err_str = str(e)
            max_retries = self.max_retries
            LOG.error(_('Unable to connect to AMQP server '
                    'after %(max_retries)d tries: %(err_str)s') % locals())
            sys.exit(1)
Example #12
0
File: amqp.py Project: xtoddx/nova
    def __call__(self, message_data):
        """Consumer callback to call a method on a proxy object.

        Parses the message for validity and fires off a thread to call the
        proxy object method.

        Message data should be a dictionary with two keys:
            method: string representing the method to call
            args: dictionary of arg: value

        Example: {'method': 'echo', 'args': {'value': 42}}

        """
        # It is important to clear the context here, because at this point
        # the previous context is stored in local.store.context
        if hasattr(local.store, 'context'):
            del local.store.context
        rpc_common._safe_log(LOG.debug, _('received %s'), message_data)
        ctxt = unpack_context(message_data)
        method = message_data.get('method')
        args = message_data.get('args', {})
        if not method:
            LOG.warn(_('no method for message: %s') % message_data)
            ctxt.reply(_('No method for message: %s') % message_data)
            return
        self.pool.spawn_n(self._process_data, ctxt, method, args)
Example #13
0
 def __init__(self, *args, **kwargs):
     max_retries = FLAGS.rabbit_max_retries
     sleep_time = FLAGS.rabbit_retry_interval
     tries = 0
     while True:
         tries += 1
         if tries > 1:
             time.sleep(sleep_time)
             # backoff for next retry attempt.. if there is one
             sleep_time += FLAGS.rabbit_retry_backoff
             if sleep_time > 30:
                 sleep_time = 30
         try:
             super(Consumer, self).__init__(*args, **kwargs)
             self.failed_connection = False
             break
         except Exception as e:  # Catching all because carrot sucks
             self.failed_connection = True
             if max_retries > 0 and tries == max_retries:
                 break
             fl_host = FLAGS.rabbit_host
             fl_port = FLAGS.rabbit_port
             fl_intv = sleep_time
             LOG.error(_('AMQP server on %(fl_host)s:%(fl_port)d is'
                         ' unreachable: %(e)s. Trying again in %(fl_intv)d'
                         ' seconds.') % locals())
     if self.failed_connection:
         LOG.error(_('Unable to connect to AMQP server '
                     'after %(tries)d tries. Shutting down.') % locals())
         sys.exit(1)
Example #14
0
    def process_data(self, message_data, message):
        """Consumer callback to call a method on a proxy object.

        Parses the message for validity and fires off a thread to call the
        proxy object method.

        Message data should be a dictionary with two keys:
            method: string representing the method to call
            args: dictionary of arg: value

        Example: {'method': 'echo', 'args': {'value': 42}}

        """
        LOG.debug(_("received %s") % message_data)
        # This will be popped off in _unpack_context
        msg_id = message_data.get("_msg_id", None)
        ctxt = _unpack_context(message_data)

        method = message_data.get("method")
        args = message_data.get("args", {})
        message.ack()
        if not method:
            # NOTE(vish): we may not want to ack here, but that means that bad
            #             messages stay in the queue indefinitely, so for now
            #             we just log the message and send an error string
            #             back to the caller
            LOG.warn(_("no method for message: %s") % message_data)
            if msg_id:
                msg_reply(msg_id, _("No method for message: %s") % message_data)
            return
        self.pool.spawn_n(self._process_data, msg_id, ctxt, method, args)
Example #15
0
def msg_reply(msg_id, reply=None, failure=None, ending=False):
    """Sends a reply or an error on the channel signified by msg_id.

    Failure should be a sys.exc_info() tuple.

    """
    if failure:
        message = str(failure[1])
        tb = traceback.format_exception(*failure)
        LOG.error(_("Returning exception %s to caller"), message)
        LOG.error(tb)
        failure = (failure[0].__name__, str(failure[1]), tb)

    with ConnectionPool.item() as conn:
        publisher = DirectPublisher(connection=conn, msg_id=msg_id)
        try:
            msg = {'result': reply, 'failure': failure}
            if ending:
                msg['ending'] = True
            publisher.send(msg)
        except TypeError:
            msg = {'result': dict((k, repr(v))
                            for k, v in reply.__dict__.iteritems()),
                    'failure': failure}
            if ending:
                msg['ending'] = True
            publisher.send(msg)

        publisher.close()
Example #16
0
 def _error_callback(exc):
     if isinstance(exc, qpid.messaging.exceptions.Empty):
         LOG.exception(_('Timed out waiting for RPC response: %s') %
                 str(exc))
         raise rpc_common.Timeout()
     else:
         LOG.exception(_('Failed to consume message from queue: %s') %
                 str(exc))
Example #17
0
 def connect_error(self, exc, interval):
     """Callback when there are connection re-tries by kombu"""
     info = self.params.copy()
     info['intv'] = interval
     info['e'] = exc
     LOG.error(_('AMQP server on %(hostname)s:%(port)d is'
             ' unreachable: %(e)s. Trying again in %(intv)d'
             ' seconds.') % info)
Example #18
0
 def __init__(self, topic, connection=None):
     self.exchange = '%s_fanout' % topic
     self.queue = '%s_fanout' % topic
     self.durable = False
     self.auto_delete = True
     LOG.info(_('Creating "%(exchange)s" fanout exchange'),
              dict(exchange=self.exchange))
     super(FanoutPublisher, self).__init__(connection=connection)
Example #19
0
 def _error_callback(exc):
     if isinstance(exc, qpid.messaging.exceptions.Empty):
         LOG.exception(
             _('Timed out waiting for RPC response: %s') % str(exc))
         raise rpc_common.Timeout()
     else:
         LOG.exception(
             _('Failed to consume message from queue: %s') % str(exc))
Example #20
0
def cast(context, topic, msg):
    """Sends a message on a topic without waiting for a response."""
    LOG.debug(_('Making asynchronous cast on %s...'), topic)
    _pack_context(msg, context)
    with ConnectionPool.item() as conn:
        publisher = TopicPublisher(connection=conn, topic=topic)
        publisher.send(msg)
        publisher.close()
Example #21
0
 def connect_error(self, exc, interval):
     """Callback when there are connection re-tries by kombu"""
     info = self.params.copy()
     info['intv'] = interval
     info['e'] = exc
     LOG.error(_('AMQP server on %(hostname)s:%(port)d is'
             ' unreachable: %(e)s. Trying again in %(intv)d'
             ' seconds.') % info)
Example #22
0
def notify(context, topic, msg):
    """Sends a notification event on a topic."""
    LOG.debug(_('Sending notification on %s...'), topic)
    _pack_context(msg, context)
    with ConnectionPool.item() as conn:
        publisher = TopicPublisher(connection=conn, topic=topic, durable=True)
        publisher.send(msg)
        publisher.close()
Example #23
0
def fanout_cast(context, topic, msg):
    """Sends a message on a fanout exchange without waiting for a response."""
    LOG.debug(_('Making asynchronous fanout cast...'))
    _pack_context(msg, context)
    with ConnectionPool.item() as conn:
        publisher = FanoutPublisher(topic, connection=conn)
        publisher.send(msg)
        publisher.close()
Example #24
0
def notify(context, topic, msg):
    """Sends a notification event on a topic."""
    LOG.debug(_('Sending notification on %s...'), topic)
    _pack_context(msg, context)
    with ConnectionPool.item() as conn:
        publisher = TopicPublisher(connection=conn, topic=topic,
                                   durable=True)
        publisher.send(msg)
        publisher.close()
Example #25
0
 def __call__(self, data):
     """The consume() callback will call this.  Store the result."""
     LOG.debug("Receive response %s", data)
     if data['failure']:
         self._result = RemoteError(*data['failure'])
     elif data.get('ending', False):
         self._got_ending = True
     else:
         self._result = data['result']
Example #26
0
 def publisher_send(self, cls, topic, msg, **kwargs):
     """Send to a publisher based on the publisher class"""
     while True:
         try:
             publisher = cls(self.channel, topic, **kwargs)
             publisher.send(msg)
             return
         except self.connection.connection_errors, e:
             LOG.exception(_('Failed to publish message %s' % str(e)))
             try:
                 self.reconnect()
             except self.connection.connection_errors, e:
                 pass
Example #27
0
def _unpack_context(msg):
    """Unpack context from msg."""
    context_dict = {}
    for key in list(msg.keys()):
        # NOTE(vish): Some versions of python don't like unicode keys
        #             in kwargs.
        key = str(key)
        if key.startswith('_context_'):
            value = msg.pop(key)
            context_dict[key[9:]] = value
    context_dict['msg_id'] = msg.pop('_msg_id', None)
    LOG.debug(_('unpacked context: %s'), context_dict)
    return RpcContext.from_dict(context_dict)
Example #28
0
 def publisher_send(self, cls, topic, msg, **kwargs):
     """Send to a publisher based on the publisher class"""
     while True:
         try:
             publisher = cls(self.channel, topic, **kwargs)
             publisher.send(msg)
             return
         except self.connection.connection_errors, e:
             LOG.exception(_('Failed to publish message %s' % str(e)))
             try:
                 self.reconnect()
             except self.connection.connection_errors, e:
                 pass
Example #29
0
def _unpack_context(msg):
    """Unpack context from msg."""
    context_dict = {}
    for key in list(msg.keys()):
        # NOTE(vish): Some versions of python don't like unicode keys
        #             in kwargs.
        key = str(key)
        if key.startswith("_context_"):
            value = msg.pop(key)
            context_dict[key[9:]] = value
    context_dict["msg_id"] = msg.pop("_msg_id", None)
    LOG.debug(_("unpacked context: %s"), context_dict)
    return RpcContext.from_dict(context_dict)
Example #30
0
def _unpack_context(msg):
    """Unpack context from msg."""
    context_dict = {}
    for key in list(msg.keys()):
        # NOTE(vish): Some versions of python don't like unicode keys
        #             in kwargs.
        key = str(key)
        if key.startswith('_context_'):
            value = msg.pop(key)
            context_dict[key[9:]] = value
    context_dict['msg_id'] = msg.pop('_msg_id', None)
    ctx = RpcContext.from_dict(context_dict)
    LOG.debug(_('unpacked context: %s'), ctx.to_dict())
    return ctx
Example #31
0
    def reconnect(self):
        """Handles reconnecting and re-establishing sessions and queues"""
        if self.connection.opened():
            try:
                self.connection.close()
            except qpid.messaging.exceptions.ConnectionError:
                pass

        while True:
            try:
                self.connection.open()
            except qpid.messaging.exceptions.ConnectionError, e:
                LOG.error(_('Unable to connect to AMQP server: %s ' % str(e)))
                time.sleep(FLAGS.qpid_reconnect_interval or 1)
            else:
                break
Example #32
0
    def reconnect(self):
        """Handles reconnecting and re-establishing sessions and queues"""
        if self.connection.opened():
            try:
                self.connection.close()
            except qpid.messaging.exceptions.ConnectionError:
                pass

        while True:
            try:
                self.connection.open()
            except qpid.messaging.exceptions.ConnectionError, e:
                LOG.error(_('Unable to connect to AMQP server: %s ' % str(e)))
                time.sleep(FLAGS.qpid_reconnect_interval or 1)
            else:
                break
Example #33
0
 def __init__(self, connection=None, topic='broadcast', proxy=None):
     self.exchange = '%s_fanout' % topic
     self.routing_key = topic
     unique = uuid.uuid4().hex
     self.queue = '%s_fanout_%s' % (topic, unique)
     self.durable = False
     # Fanout creates unique queue names, so we should auto-remove
     # them when done, so they're not left around on restart.
     # Also, we're the only one that should be consuming.  exclusive
     # implies auto_delete, so we'll just set that..
     self.exclusive = True
     LOG.info(_('Created "%(exchange)s" fanout exchange '
                'with "%(key)s" routing key'),
              dict(exchange=self.exchange, key=self.routing_key))
     super(FanoutAdapterConsumer, self).__init__(connection=connection,
                                 topic=topic, proxy=proxy)
Example #34
0
def multicall(context, topic, msg):
    """Make a call that returns multiple times."""
    # Can't use 'with' for multicall, as it returns an iterator
    # that will continue to use the connection.  When it's done,
    # connection.close() will get called which will put it back into
    # the pool
    LOG.debug(_('Making asynchronous call on %s ...'), topic)
    msg_id = uuid.uuid4().hex
    msg.update({'_msg_id': msg_id})
    LOG.debug(_('MSG_ID is %s') % (msg_id))
    _pack_context(msg, context)

    conn = ConnectionContext()
    wait_msg = MulticallWaiter(conn)
    conn.declare_direct_consumer(msg_id, wait_msg)
    conn.topic_send(topic, msg)
    return wait_msg
Example #35
0
File: amqp.py Project: Jaesang/nova
def multicall(context, topic, msg):
    """Make a call that returns multiple times."""
    # Can't use 'with' for multicall, as it returns an iterator
    # that will continue to use the connection.  When it's done,
    # connection.close() will get called which will put it back into
    # the pool
    LOG.debug(_("Making asynchronous call on %s ..."), topic)
    msg_id = uuid.uuid4().hex
    msg.update({"_msg_id": msg_id})
    LOG.debug(_("MSG_ID is %s") % (msg_id))
    pack_context(msg, context)

    conn = ConnectionContext()
    wait_msg = MulticallWaiter(conn)
    conn.declare_direct_consumer(msg_id, wait_msg)
    conn.topic_send(topic, msg)
    return wait_msg
Example #36
0
    def iterconsume(self, limit=None):
        """Return an iterator that will consume from all queues/consumers"""
        while True:
            try:
                queues_head = self.consumers[:-1]
                queues_tail = self.consumers[-1]
                for queue in queues_head:
                    queue.consume(nowait=True)
                queues_tail.consume(nowait=False)

                for iteration in itertools.count(0):
                    if limit and iteration >= limit:
                        raise StopIteration
                    yield self.connection.drain_events()
            except self.connection.connection_errors, e:
                LOG.exception(_("Failed to consume message from queue: " "%s" % str(e)))
                self.reconnect()
Example #37
0
def multicall(context, topic, msg):
    """Make a call that returns multiple times."""
    LOG.debug(_('Making asynchronous call on %s ...'), topic)
    msg_id = uuid.uuid4().hex
    msg.update({'_msg_id': msg_id})
    LOG.debug(_('MSG_ID is %s') % (msg_id))
    _pack_context(msg, context)

    con_conn = ConnectionPool.get()
    consumer = DirectConsumer(connection=con_conn, msg_id=msg_id)
    wait_msg = MulticallWaiter(consumer)
    consumer.register_callback(wait_msg)

    publisher = TopicPublisher(connection=con_conn, topic=topic)
    publisher.send(msg)
    publisher.close()

    return wait_msg
Example #38
0
    def iterconsume(self, limit=None):
        """Return an iterator that will consume from all queues/consumers"""
        while True:
            try:
                queues_head = self.consumers[:-1]
                queues_tail = self.consumers[-1]
                for queue in queues_head:
                    queue.consume(nowait=True)
                queues_tail.consume(nowait=False)

                for iteration in itertools.count(0):
                    if limit and iteration >= limit:
                        raise StopIteration
                    yield self.connection.drain_events()
            except self.connection.connection_errors, e:
                LOG.exception(_('Failed to consume message from queue: '
                        '%s' % str(e)))
                self.reconnect()
Example #39
0
 def wait(self, limit=None):
     running = True
     while running:
         it = self.consumer_set.iterconsume(limit=limit)
         if not it:
             break
         while True:
             try:
                 it.next()
             except StopIteration:
                 return
             except greenlet.GreenletExit:
                 running = False
                 break
             except Exception as e:
                 LOG.exception(_("Exception while processing consumer"))
                 self.reconnect()
                 # Break to outer loop
                 break
Example #40
0
def call(context, topic, msg):
    """Sends a message on a topic and wait for a response."""
    LOG.debug("Do rpc call with %s message on %s topic", msg, topic)
    rv = multicall(context, topic, msg)
    # NOTE(vish): return the last result from the multicall
    rv = list(rv)
    LOG.debug('rpc.call results: %s', rv)
    if not rv:
        LOG.debug('rpc.call return to caller: None')
        return
    LOG.debug('rpc.call return to caller: %s', rv[-1])
    return rv[-1]
Example #41
0
File: amqp.py Project: Jaesang/nova
def msg_reply(msg_id, reply=None, failure=None, ending=False):
    """Sends a reply or an error on the channel signified by msg_id.

    Failure should be a sys.exc_info() tuple.

    """
    with ConnectionContext() as conn:
        if failure:
            message = str(failure[1])
            tb = traceback.format_exception(*failure)
            LOG.error(_("Returning exception %s to caller"), message)
            LOG.error(tb)
            failure = (failure[0].__name__, str(failure[1]), tb)

        try:
            msg = {"result": reply, "failure": failure}
        except TypeError:
            msg = {"result": dict((k, repr(v)) for k, v in reply.__dict__.iteritems()), "failure": failure}
        if ending:
            msg["ending"] = True
        conn.direct_send(msg_id, msg)
Example #42
0
 def __init__(self, *args, **kwargs):
     for i in xrange(FLAGS.rabbit_max_retries):
         if i > 0:
             time.sleep(FLAGS.rabbit_retry_interval)
         try:
             super(Consumer, self).__init__(*args, **kwargs)
             self.failed_connection = False
             break
         except Exception as e:  # Catching all because carrot sucks
             fl_host = FLAGS.rabbit_host
             fl_port = FLAGS.rabbit_port
             fl_intv = FLAGS.rabbit_retry_interval
             LOG.error(_('AMQP server on %(fl_host)s:%(fl_port)d is'
                         ' unreachable: %(e)s. Trying again in %(fl_intv)d'
                         ' seconds.') % locals())
             self.failed_connection = True
     if self.failed_connection:
         LOG.error(_('Unable to connect to AMQP server '
                     'after %d tries. Shutting down.'),
                   FLAGS.rabbit_max_retries)
         sys.exit(1)
Example #43
0
File: amqp.py Project: Jaesang/nova
    def _process_data(self, ctxt, method, args):
        """Thread that magically looks for a method on the proxy
        object and calls it.
        """

        try:
            node_func = getattr(self.proxy, str(method))
            node_args = dict((str(k), v) for k, v in args.iteritems())
            # NOTE(vish): magic is fun!
            rval = node_func(context=ctxt, **node_args)
            # Check if the result was a generator
            if inspect.isgenerator(rval):
                for x in rval:
                    ctxt.reply(x, None)
            else:
                ctxt.reply(rval, None)
            # This final None tells multicall that it is done.
            ctxt.reply(ending=True)
        except Exception as e:
            LOG.exception("Exception during message handling")
            ctxt.reply(None, sys.exc_info())
        return
Example #44
0
    def __call__(self, message_data):
        """Consumer callback to call a method on a proxy object.

        Parses the message for validity and fires off a thread to call the
        proxy object method.

        Message data should be a dictionary with two keys:
            method: string representing the method to call
            args: dictionary of arg: value

        Example: {'method': 'echo', 'args': {'value': 42}}

        """
        LOG.debug(_('received %s') % message_data)
        ctxt = _unpack_context(message_data)
        method = message_data.get('method')
        args = message_data.get('args', {})
        if not method:
            LOG.warn(_('no method for message: %s') % message_data)
            ctxt.reply(_('No method for message: %s') % message_data)
            return
        self.pool.spawn_n(self._process_data, ctxt, method, args)
Example #45
0
 def __init__(self, *args, **kwargs):
     for i in xrange(FLAGS.rabbit_max_retries):
         if i > 0:
             time.sleep(FLAGS.rabbit_retry_interval)
         try:
             super(Consumer, self).__init__(*args, **kwargs)
             self.failed_connection = False
             break
         except Exception as e:  # Catching all because carrot sucks
             fl_host = FLAGS.rabbit_host
             fl_port = FLAGS.rabbit_port
             fl_intv = FLAGS.rabbit_retry_interval
             LOG.error(
                 _('AMQP server on %(fl_host)s:%(fl_port)d is'
                   ' unreachable: %(e)s. Trying again in %(fl_intv)d'
                   ' seconds.') % locals())
             self.failed_connection = True
     if self.failed_connection:
         LOG.error(
             _('Unable to connect to AMQP server '
               'after %d tries. Shutting down.'), FLAGS.rabbit_max_retries)
         sys.exit(1)
Example #46
0
    def _process_data(self, ctxt, method, args):
        """Thread that magically looks for a method on the proxy
        object and calls it.
        """

        node_func = getattr(self.proxy, str(method))
        node_args = dict((str(k), v) for k, v in args.iteritems())
        # NOTE(vish): magic is fun!
        try:
            rval = node_func(context=ctxt, **node_args)
            # Check if the result was a generator
            if inspect.isgenerator(rval):
                for x in rval:
                    ctxt.reply(x, None)
            else:
                ctxt.reply(rval, None)
            # This final None tells multicall that it is done.
            ctxt.reply(ending=True)
        except Exception as e:
            LOG.exception('Exception during message handling')
            ctxt.reply(None, sys.exc_info())
        return
Example #47
0
def generic_response(message_data, message):
    """Logs a result and exits."""
    LOG.debug(_('response %s'), message_data)
    message.ack()
    sys.exit(0)
Example #48
0
 def create(self):
     LOG.debug('Pool creating new connection')
     return Connection.instance(new=True)
Example #49
0
def fanout_cast(context, topic, msg):
    """Sends a message on a fanout exchange without waiting for a response."""
    LOG.debug(_('Making asynchronous fanout cast...'))
    _pack_context(msg, context)
    with ConnectionContext() as conn:
        conn.fanout_send(topic, msg)