text: """Validation for RabbitMQ"""
  
  import time
  
  from alarmageddon.validations.validation import Validation, Priority
  
  from pika import ConnectionParameters
  from pika.adapters import BlockingConnection
  from pika.credentials import PlainCredentials
  from pika.exceptions import AMQPError
  
  import logging
  
  logger = logging.getLogger(__name__)
  
  class RabbitMqContext(object):
      """information needed to connect and interact with RabbitMQ"""
      def __init__(self, host, port, user_name, password):
          self.host = host
          self.port = port
          self.user_name = user_name
          self.password = password
  
      def get_credentials(self):
          """get "plain" credentials based on this object's user name and
          password
  
          """
          return PlainCredentials(self.user_name, self.password)
  
      def get_connection(self, timeout=None):
          """Connects to RabbitMQ and returns the connection object
  
          Third Party (pika) Bug: https://github.com/pika/pika/issues/354 - Once
          this bug is fixed we can take out our own retrying logic and use pika's
          retry logic.  In the mean time, connection failure messages will be
          inaccurate; they'll say that only one connection attempt was made.
  
          """
          return BlockingConnection(
              ConnectionParameters(host=self.host,
                                   credentials=self.get_credentials(),
                                   connection_attempts=1,
                                   retry_delay=0,
                                   socket_timeout=timeout))
  
  
  class RabbitMqValidation(Validation):
      """A Validation that can be held against a RabbitMQ server"""
      def __init__(self, rabbitmq_context, name, queue_name, max_queue_size,
                   priority=Priority.NORMAL, timeout=None, num_attempts=4,
                   seconds_between_attempts=2, group=None,
                   ignore_connection_failure=False):
          """Creates a RabbitMqValidation object."""
          Validation.__init__(self,
              ("queue '{0}' should have less than {1} messages in in " +
              "it on RabbitMQ host: '{2}' ({3})")
              .format(queue_name, max_queue_size, rabbitmq_context.host, name),
              priority=priority, timeout=timeout, group=group)
  
          self.rabbitmq_context = rabbitmq_context
          self.max_queue_size = max_queue_size
          self.queue_name = queue_name
          self.num_attempts = num_attempts
          self.seconds_between_attempts = seconds_between_attempts
          self.ignore_connection_failure = ignore_connection_failure
  
      def perform(self, group_failures):
          """Perform the validation.  If the validation fails, call self.fail
          passing it the reason for the failure.
  
          """
          try:
              (conn, chan) = self._connect()
          except AMQPError, ex:
              #if we're here we're intentionally ignoring the failure
              return
  
          try:
              queue = chan.queue_declare(self.queue_name, passive=True)
              message_count = queue.method.message_count
  
              if message_count > self.max_queue_size:
                  self.fail("Too many messages in queue ({0} messages)."
                            .format(message_count))
  
          except AMQPError, ex:
              self.fail("RabbitMQ exception throw from host: {0}.  {1}"
                        .format(self.rabbitmq_context.host, repr(ex)))
  
          finally:
              if conn:
                  conn.close()
  
      def _connect(self):
          """connect to the RabbitMQ server"""
          for attempt in range(1, self.num_attempts + 1):
              try:
                  conn = self.rabbitmq_context.get_connection(self.timeout)
                  chan = conn.channel()
                  return (conn, chan)
              except AMQPError, ex:
                  if attempt >= self.num_attempts:
                      if self.ignore_connection_failure:
                          raise ex
                      else:
                          self.fail(
                              "Could not access RabbitMQ host {0} because {1}"
                              .format(self.rabbitmq_context.host, repr(ex)))
                  else:
                      time.sleep(self.seconds_between_attempts)
  