Beispiel #1
0
    def __init__(self):
        self.config = Config('giraffe.cfg')

        # configure RabbitMQ connector (and consumer)
        self.connector = Connector(username=self.config.get('rabbit', 'user'),
                                   password=self.config.get('rabbit', 'pass'),
                                   host=self.config.get('rabbit', 'host'),
                                   port=self.config.getint('rabbit', 'port'))
        self.queue = self.config.get('rabbit', 'queue')
        self.exchange = self.config.get('rabbit', 'exchange')
        self.routing_key = self.config.get('rabbit', 'routing_key')

        self.consumer = BasicConsumer(self.connector, self.queue,
                                      self.exchange, self._collector_callback)

        self.shared_secret = self.config.get('collector', 'shared_secret')

        # connect to giraffe database
        self.db = db.connect(
            '%s://%s:%s@%s/%s' %
            (self.config.get('db', 'vendor'), self.config.get('db', 'user'),
             self.config.get('db', 'pass'), self.config.get(
                 'db', 'host'), self.config.get('db', 'schema')))

        # prepare connection to nova-client
        self._credentials = dict(
            username=self.config.get('agent', 'user'),
            password=self.config.get('agent', 'pass'),
            #                        tenant_id=self.config.get('agent', 'tenant_id'),
            tenant_name=self.config.get('agent', 'tenant_name'),
            auth_url=self.config.get('auth', 'admin_url'),
            insecure=True)

        # known servers/instances
        self.known_instances = {}
Beispiel #2
0
    def __init__(self, agent):
        threading.Thread.__init__(self)

        self.agent = agent
        config = Config('giraffe.cfg')
        self.host_name = config.get('agent', 'host_name')

        self.flush_duration = config.getint('agent', 'duration')

        self.connector = Connector(username=config.get('rabbit', 'user'),
                                   password=config.get('rabbit', 'pass'),
                                   host=config.get('rabbit', 'host'),
                                   port=config.getint('rabbit', 'port'))
        self.queue = config.get('rabbit', 'queue')
        self.exchange = config.get('rabbit', 'exchange')
        self.routing_key = config.get('rabbit', 'routing_key')
        self.producer = BasicProducer(self.connector, self.exchange)

        self.shared_secret = config.get('agent', 'shared_secret')
        self.envelope = self._build_message()

        self.stopRequest = False
        self.lock = threading.Lock()
Beispiel #3
0
    def __init__(self, agent):
        threading.Thread.__init__(self)

        self.agent = agent
        config = Config('giraffe.cfg')
        self.host_name = config.get('agent', 'host_name')

        self.flush_duration = config.getint('agent', 'duration')

        self.connector = Connector(username=config.get('rabbit', 'user'),
                                   password=config.get('rabbit', 'pass'),
                                   host=config.get('rabbit', 'host'),
                                   port=config.getint('rabbit', 'port'))
        self.queue = config.get('rabbit', 'queue')
        self.exchange = config.get('rabbit', 'exchange')
        self.routing_key = config.get('rabbit', 'routing_key')
        self.producer = BasicProducer(self.connector, self.exchange)

        self.shared_secret = config.get('agent', 'shared_secret')
        self.envelope = self._build_message()

        self.stopRequest = False
        self.lock = threading.Lock()
Beispiel #4
0
    def __init__(self):
        self.config = Config('giraffe.cfg')

        # configure RabbitMQ connector (and consumer)
        self.connector = Connector(username=self.config.get('rabbit', 'user'),
                                   password=self.config.get('rabbit', 'pass'),
                                   host=self.config.get('rabbit', 'host'),
                                   port=self.config.getint('rabbit', 'port'))
        self.queue = self.config.get('rabbit', 'queue')
        self.exchange = self.config.get('rabbit', 'exchange')
        self.routing_key = self.config.get('rabbit', 'routing_key')

        self.consumer = BasicConsumer(self.connector,
                                      self.queue,
                                      self.exchange,
                                      self._collector_callback)

        self.shared_secret = self.config.get('collector', 'shared_secret')

        # connect to giraffe database
        self.db = db.connect('%s://%s:%s@%s/%s'
                             % (self.config.get('db', 'vendor'),
                                self.config.get('db', 'user'),
                                self.config.get('db', 'pass'),
                                self.config.get('db', 'host'),
                                self.config.get('db', 'schema')))

        # prepare connection to nova-client
        self._credentials = dict(username=self.config.get('agent', 'user'),
                                 password=self.config.get('agent', 'pass'),
        #                        tenant_id=self.config.get('agent', 'tenant_id'),
                                 tenant_name=self.config.get('agent', 'tenant_name'),
                                 auth_url=self.config.get('auth', 'admin_url'),
                                 insecure=True)

        # known servers/instances
        self.known_instances = {}
Beispiel #5
0
class AgentPublisher(threading.Thread):
    def __init__(self, agent):
        threading.Thread.__init__(self)

        self.agent = agent
        config = Config('giraffe.cfg')
        self.host_name = config.get('agent', 'host_name')

        self.flush_duration = config.getint('agent', 'duration')

        self.connector = Connector(username=config.get('rabbit', 'user'),
                                   password=config.get('rabbit', 'pass'),
                                   host=config.get('rabbit', 'host'),
                                   port=config.getint('rabbit', 'port'))
        self.queue = config.get('rabbit', 'queue')
        self.exchange = config.get('rabbit', 'exchange')
        self.routing_key = config.get('rabbit', 'routing_key')
        self.producer = BasicProducer(self.connector, self.exchange)

        self.shared_secret = config.get('agent', 'shared_secret')
        self.envelope = self._build_message()

        self.stopRequest = False
        self.lock = threading.Lock()

    def _timestamp_now(self, datetime_now=None):
        """
        Returns current system time as formatted string "%Y-%m-%d %H:%M:%S"
        """
        if not datetime_now:
            datetime_now = datetime.now()
        return datetime_now.strftime("%Y-%m-%d %H:%M:%S")

    def _build_message(self):
        """
        Returns a new MessageAdapter object with hostname and signature
        :rtype : MessageAdapter
        """
        envelope = EnvelopeAdapter()
        envelope.message.host_name = self.host_name
        #        message.signature = _SIGNATURE
        return envelope

    def add_meter_record(self, meter_name, meter_value, meter_duration):
        """
        Add new meter record to meter message
        Params: meter type [as string], value(s), and duration [in seconds]
        """
        logger.debug("Add meter record: %s=%s" % (meter_name, meter_value))

        if not self.lock.locked():
            self.lock.acquire()
            try:
                if meter_name.startswith('inst'):
                    for record in meter_value:
                        self.envelope.add_inst_record(
                            timestamp=self._timestamp_now(record[1]),
                            meter_name=meter_name,
                            value=record[2],
                            duration=meter_duration,
                            project_id='',
                            inst_id=record[0],
                            user_id='')
                else:  # .startswith('host'):
                    self.envelope.add_host_record(
                        self._timestamp_now(),
                        meter_name,
                        meter_value,
                        meter_duration)
            finally:
                self.lock.release()

    def flush(self):
        """
        Sends current state of agents message to the broker.
        """
        logger.debug("Flush meter message")

        if not self.lock.locked():
            self.lock.acquire()
            try:
                if self.envelope.len() > 0:
                    # flush message
                    self._send(self.envelope)

                    # build new message
                    self.envelope = self._build_message()

            # except Exception as e:
            #     logger.exception(e)

            finally:
                self.lock.release()

    def _send(self, envelope):
        """
        Create message signature and send envelop to broker
        """
        messageAdapter = MessageAdapter(envelope.message)
        sig = createSignature(str(messageAdapter), self.shared_secret)
        envelope.signature = sig
        self.producer.send(exchange=self.exchange,
                           routing_key=self.routing_key,
                           message=envelope.serialize_to_str())

    def run(self):
        self.connector.connect()
        while self.stopRequest is False:
            time.sleep(self.flush_duration)
            self.flush()

    def stop(self):
        self.stopRequest = True
        self._Thread__stop()
Beispiel #6
0
class Collector(object):
    def __init__(self):
        self.config = Config('giraffe.cfg')

        # configure RabbitMQ connector (and consumer)
        self.connector = Connector(username=self.config.get('rabbit', 'user'),
                                   password=self.config.get('rabbit', 'pass'),
                                   host=self.config.get('rabbit', 'host'),
                                   port=self.config.getint('rabbit', 'port'))
        self.queue = self.config.get('rabbit', 'queue')
        self.exchange = self.config.get('rabbit', 'exchange')
        self.routing_key = self.config.get('rabbit', 'routing_key')

        self.consumer = BasicConsumer(self.connector, self.queue,
                                      self.exchange, self._collector_callback)

        self.shared_secret = self.config.get('collector', 'shared_secret')

        # connect to giraffe database
        self.db = db.connect(
            '%s://%s:%s@%s/%s' %
            (self.config.get('db', 'vendor'), self.config.get('db', 'user'),
             self.config.get('db', 'pass'), self.config.get(
                 'db', 'host'), self.config.get('db', 'schema')))

        # prepare connection to nova-client
        self._credentials = dict(
            username=self.config.get('agent', 'user'),
            password=self.config.get('agent', 'pass'),
            #                        tenant_id=self.config.get('agent', 'tenant_id'),
            tenant_name=self.config.get('agent', 'tenant_name'),
            auth_url=self.config.get('auth', 'admin_url'),
            insecure=True)

        # known servers/instances
        self.known_instances = {}

    def launch(self):
        try:
            self.connector.connect()
            self.start_collecting()
        except KeyboardInterrupt:
            _logger.info("Ctrl-c received!")
        except:
            _logger.exception("Error: Unable to start collector service")
        finally:
            self.stop_collecting()
            _logger.info("Shutdown collector service")

    def start_collecting(self):
        _logger.debug("Start collecting from broker")
        self.consumer.consume()

    def stop_collecting(self):
        _logger.debug("Stop collecting from broker")
        self.consumer.stop_consuming()

    def _str_to_datetime(self, timestamp_str):
        return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')

    def _datetime_to_str(self, datetime_obj):
        return datetime_obj.strftime("%Y-%m-%d %H:%M:%S")

    def _collector_callback(self, params):
        envelope = EnvelopeAdapter()

        # check whether incorrectly formatted message
        try:
            envelope.deserialize_from_str(params)
        except:
            return

        message = MessageAdapter(envelope.message)
        # validate signature
        if not validateSignature(str(message), self.shared_secret,
                                 envelope.signature):
            return

        self.db.session_open()

        # load all meters now to avoid queries later
        meters = self.db.load(Meter)
        meter_dict = {}
        for meter in meters:
            meter_dict[meter.name] = meter

        # insert host if it does not exist yet
        hosts = self.db.load(Host, {'name': message.host_name}, limit=1)
        if not hosts:
            host = Host(name=message.host_name)
            self.db.save(host)
            self.db.commit()
        else:
            host = hosts[0]

        # insert all host records
        for r in message.host_records:
            if r.meter_name not in meter_dict:
                _logger.warning('Unknown meter_name "%s"' % r.meter_name)
                continue
            try:
                record = MeterRecord(meter_id=meter_dict[r.meter_name].id,
                                     host_id=host.id,
                                     user_id=None,
                                     resource_id=None,
                                     project_id=None,
                                     value=r.value,
                                     duration=r.duration,
                                     timestamp=r.timestamp)
                self.db.save(record)
                _logger.debug("New %s" % record)

                # update host activity
                record_timestamp = self._str_to_datetime(r.timestamp)
                if not host.activity or record_timestamp > host.activity:
                    host.activity = record_timestamp

            except Exception as e:
                _logger.exception(e)

        # insert all instance records
        for r in message.inst_records:
            if r.meter_name not in meter_dict:
                _logger.warning('Unknown meter_name "%s"' % r.meter_name)
                continue
            try:
                # @[fbahr] - TODO: `self.known_instances` grows over time
                #                  towards inf. - clean-up?
                if not r.inst_id in self.known_instances:
                    self.known_instances[r.inst_id] = self._metadata(
                        uuid=r.inst_id)

                r.project_id, r.user_id = self.known_instances[r.inst_id]

                # insert project if it does not exist yet
                projects = self.db.load(Project, {'uuid': r.project_id},
                                        limit=1)
                if not projects:
                    project = Project(uuid=r.project_id,
                                      created_at=self._str_to_datetime(
                                          r.timestamp))
                    self.db.save(project)
                    self.db.commit()
                else:
                    project = projects[0]

                record = MeterRecord(meter_id=meter_dict[r.meter_name].id,
                                     host_id=host.id,
                                     user_id=r.user_id,
                                     resource_id=r.inst_id,
                                     project_id=r.project_id,
                                     value=r.value,
                                     duration=r.duration,
                                     timestamp=r.timestamp)
                self.db.save(record)
                _logger.debug("New %s" % record)

                # update host and project activity
                record_timestamp = self._str_to_datetime(r.timestamp)
                if not host.activity or record_timestamp > host.activity:
                    host.activity = record_timestamp
                if not project.updated_at or record_timestamp > project.updated_at:
                    project.updated_at = record_timestamp

            except Exception as e:
                _logger.exception(e)

        try:
            self.db.commit()
        except Exception as e:
            self.db.rollback()
            _logger.exception(e)
        self.db.session_close()

    def _metadata(self, uuid):
        """
        Connect to nova database (by means of nova-client);
        fetches (project_id, user_id) information for a given instance uuid.
        """
        nova_client = NovaClient(username=self._credentials['username'],
                                 api_key=self._credentials['password'],
                                 project_id=self._credentials['tenant_name'],
                                 auth_url=self._credentials['auth_url'],
                                 service_type='compute',
                                 insecure=True)

        # self._credentials['auth_token'] = AuthProxy.get_token(**self._credentials)
        # nova_client.client.auth_token = self._credentials['auth_token']
        # nova_client.client.authenticate()

        # unfortunately, nova_client.servers.find(id=...) is restricted
        # to instances in an user's tentant (project) [can't tweek that,
        # hard-coded in find()] - but:
        search_opts = {'all_tenants': 1}
        server = next((s.user_id, s.tenant_id)
                      for s in nova_client.servers.list(True, search_opts)
                      if s.id == uuid)
        return map(str, server)
Beispiel #7
0
class Collector(object):
    def __init__(self):
        self.config = Config('giraffe.cfg')

        # configure RabbitMQ connector (and consumer)
        self.connector = Connector(username=self.config.get('rabbit', 'user'),
                                   password=self.config.get('rabbit', 'pass'),
                                   host=self.config.get('rabbit', 'host'),
                                   port=self.config.getint('rabbit', 'port'))
        self.queue = self.config.get('rabbit', 'queue')
        self.exchange = self.config.get('rabbit', 'exchange')
        self.routing_key = self.config.get('rabbit', 'routing_key')

        self.consumer = BasicConsumer(self.connector,
                                      self.queue,
                                      self.exchange,
                                      self._collector_callback)

        self.shared_secret = self.config.get('collector', 'shared_secret')

        # connect to giraffe database
        self.db = db.connect('%s://%s:%s@%s/%s'
                             % (self.config.get('db', 'vendor'),
                                self.config.get('db', 'user'),
                                self.config.get('db', 'pass'),
                                self.config.get('db', 'host'),
                                self.config.get('db', 'schema')))

        # prepare connection to nova-client
        self._credentials = dict(username=self.config.get('agent', 'user'),
                                 password=self.config.get('agent', 'pass'),
        #                        tenant_id=self.config.get('agent', 'tenant_id'),
                                 tenant_name=self.config.get('agent', 'tenant_name'),
                                 auth_url=self.config.get('auth', 'admin_url'),
                                 insecure=True)

        # known servers/instances
        self.known_instances = {}

    def launch(self):
        try:
            self.connector.connect()
            self.start_collecting()
        except KeyboardInterrupt:
            _logger.info("Ctrl-c received!")
        except:
            _logger.exception("Error: Unable to start collector service")
        finally:
            self.stop_collecting()
            _logger.info("Shutdown collector service")

    def start_collecting(self):
        _logger.debug("Start collecting from broker")
        self.consumer.consume()

    def stop_collecting(self):
        _logger.debug("Stop collecting from broker")
        self.consumer.stop_consuming()

    def _str_to_datetime(self, timestamp_str):
        return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')

    def _datetime_to_str(self, datetime_obj):
        return datetime_obj.strftime("%Y-%m-%d %H:%M:%S")

    def _collector_callback(self, params):
        envelope = EnvelopeAdapter()

        # check whether incorrectly formatted message
        try:
            envelope.deserialize_from_str(params)
        except:
            return

        message = MessageAdapter(envelope.message)
        # validate signature
        if not validateSignature(str(message), self.shared_secret,
                                 envelope.signature):
            return

        self.db.session_open()

        # load all meters now to avoid queries later
        meters = self.db.load(Meter)
        meter_dict = {}
        for meter in meters:
            meter_dict[meter.name] = meter

        # insert host if it does not exist yet
        hosts = self.db.load(Host, {'name': message.host_name}, limit=1)
        if not hosts:
            host = Host(name=message.host_name)
            self.db.save(host)
            self.db.commit()
        else:
            host = hosts[0]

        # insert all host records
        for r in message.host_records:
            if r.meter_name not in meter_dict:
                _logger.warning('Unknown meter_name "%s"' % r.meter_name)
                continue
            try:
                record = MeterRecord(meter_id=meter_dict[r.meter_name].id,
                                     host_id=host.id,
                                     user_id=None,
                                     resource_id=None,
                                     project_id=None,
                                     value=r.value,
                                     duration=r.duration,
                                     timestamp=r.timestamp)
                self.db.save(record)
                _logger.debug("New %s" % record)

                # update host activity
                record_timestamp = self._str_to_datetime(r.timestamp)
                if not host.activity or record_timestamp > host.activity:
                    host.activity = record_timestamp

            except Exception as e:
                _logger.exception(e)

        # insert all instance records
        for r in message.inst_records:
            if r.meter_name not in meter_dict:
                _logger.warning('Unknown meter_name "%s"' % r.meter_name)
                continue
            try:
                # @[fbahr] - TODO: `self.known_instances` grows over time
                #                  towards inf. - clean-up?
                if not r.inst_id in self.known_instances:
                    self.known_instances[r.inst_id] = self._metadata(uuid=r.inst_id)

                r.project_id, r.user_id = self.known_instances[r.inst_id]

                # insert project if it does not exist yet
                projects = self.db.load(Project,
                                        {'uuid': r.project_id},
                                        limit=1)
                if not projects:
                    project = Project(uuid=r.project_id,
                                      created_at=self._str_to_datetime(r.timestamp))
                    self.db.save(project)
                    self.db.commit()
                else:
                    project = projects[0]

                record = MeterRecord(meter_id=meter_dict[r.meter_name].id,
                                     host_id=host.id,
                                     user_id=r.user_id,
                                     resource_id=r.inst_id,
                                     project_id=r.project_id,
                                     value=r.value,
                                     duration=r.duration,
                                     timestamp=r.timestamp)
                self.db.save(record)
                _logger.debug("New %s" % record)

                # update host and project activity
                record_timestamp = self._str_to_datetime(r.timestamp)
                if not host.activity or record_timestamp > host.activity:
                    host.activity = record_timestamp
                if not project.updated_at or record_timestamp > project.updated_at:
                    project.updated_at = record_timestamp

            except Exception as e:
                _logger.exception(e)

        try:
            self.db.commit()
        except Exception as e:
            self.db.rollback()
            _logger.exception(e)
        self.db.session_close()

    def _metadata(self, uuid):
        """
        Connect to nova database (by means of nova-client);
        fetches (project_id, user_id) information for a given instance uuid.
        """
        nova_client = NovaClient(username=self._credentials['username'],
                                 api_key=self._credentials['password'],
                                 project_id=self._credentials['tenant_name'],
                                 auth_url=self._credentials['auth_url'],
                                 service_type='compute',
                                 insecure=True)

        # self._credentials['auth_token'] = AuthProxy.get_token(**self._credentials)
        # nova_client.client.auth_token = self._credentials['auth_token']
        # nova_client.client.authenticate()

        # unfortunately, nova_client.servers.find(id=...) is restricted
        # to instances in an user's tentant (project) [can't tweek that,
        # hard-coded in find()] - but:
        search_opts = {'all_tenants': 1}
        server = next((s.user_id,  s.tenant_id)
                          for s in nova_client.servers.list(True, search_opts)
                          if s.id == uuid)
        return map(str, server)
Beispiel #8
0
class AgentPublisher(threading.Thread):
    def __init__(self, agent):
        threading.Thread.__init__(self)

        self.agent = agent
        config = Config('giraffe.cfg')
        self.host_name = config.get('agent', 'host_name')

        self.flush_duration = config.getint('agent', 'duration')

        self.connector = Connector(username=config.get('rabbit', 'user'),
                                   password=config.get('rabbit', 'pass'),
                                   host=config.get('rabbit', 'host'),
                                   port=config.getint('rabbit', 'port'))
        self.queue = config.get('rabbit', 'queue')
        self.exchange = config.get('rabbit', 'exchange')
        self.routing_key = config.get('rabbit', 'routing_key')
        self.producer = BasicProducer(self.connector, self.exchange)

        self.shared_secret = config.get('agent', 'shared_secret')
        self.envelope = self._build_message()

        self.stopRequest = False
        self.lock = threading.Lock()

    def _timestamp_now(self, datetime_now=None):
        """
        Returns current system time as formatted string "%Y-%m-%d %H:%M:%S"
        """
        if not datetime_now:
            datetime_now = datetime.now()
        return datetime_now.strftime("%Y-%m-%d %H:%M:%S")

    def _build_message(self):
        """
        Returns a new MessageAdapter object with hostname and signature
        :rtype : MessageAdapter
        """
        envelope = EnvelopeAdapter()
        envelope.message.host_name = self.host_name
        #        message.signature = _SIGNATURE
        return envelope

    def add_meter_record(self, meter_name, meter_value, meter_duration):
        """
        Add new meter record to meter message
        Params: meter type [as string], value(s), and duration [in seconds]
        """
        logger.debug("Add meter record: %s=%s" % (meter_name, meter_value))

        if not self.lock.locked():
            self.lock.acquire()
            try:
                if meter_name.startswith('inst'):
                    for record in meter_value:
                        self.envelope.add_inst_record(
                            timestamp=self._timestamp_now(record[1]),
                            meter_name=meter_name,
                            value=record[2],
                            duration=meter_duration,
                            project_id='',
                            inst_id=record[0],
                            user_id='')
                else:  # .startswith('host'):
                    self.envelope.add_host_record(self._timestamp_now(),
                                                  meter_name, meter_value,
                                                  meter_duration)
            finally:
                self.lock.release()

    def flush(self):
        """
        Sends current state of agents message to the broker.
        """
        logger.debug("Flush meter message")

        if not self.lock.locked():
            self.lock.acquire()
            try:
                if self.envelope.len() > 0:
                    # flush message
                    self._send(self.envelope)

                    # build new message
                    self.envelope = self._build_message()

            # except Exception as e:
            #     logger.exception(e)

            finally:
                self.lock.release()

    def _send(self, envelope):
        """
        Create message signature and send envelop to broker
        """
        messageAdapter = MessageAdapter(envelope.message)
        sig = createSignature(str(messageAdapter), self.shared_secret)
        envelope.signature = sig
        self.producer.send(exchange=self.exchange,
                           routing_key=self.routing_key,
                           message=envelope.serialize_to_str())

    def run(self):
        self.connector.connect()
        while self.stopRequest is False:
            time.sleep(self.flush_duration)
            self.flush()

    def stop(self):
        self.stopRequest = True
        self._Thread__stop()