Beispiel #1
0
class Main(object):
    def __init__(self):
        self.client = None
        self.server = None
        self.datastore = None
        self.hdf = None
        self.hdf_group = None
        self.config = None
        self.event_queue = collections.deque()
        self.event_lock = RLock()
        self.logger = logging.getLogger('statd')
        self.data_sources = {}

    def init_datastore(self):
        try:
            self.datastore = get_datastore(self.config)
        except DatastoreException as err:
            self.logger.error('Cannot initialize datastore: %s', str(err))
            sys.exit(1)

    def init_database(self):
        # adding this try/except till system-dataset plugin is added back in in full fidelity
        # just a hack (since that directory's data will not persist)
        # Please remove this when system-dataset plugin is added back in
        try:
            directory = self.client.call_sync(
                'system_dataset.request_directory', 'statd')
        except RpcException:
            directory = '/var/tmp/statd'
            if not os.path.exists(directory):
                os.makedirs(directory)
        self.hdf = tables.open_file(os.path.join(directory, DEFAULT_DBFILE),
                                    mode='a')
        if not hasattr(self.hdf.root, 'stats'):
            self.hdf.create_group('/', 'stats')

        self.hdf_group = self.hdf.root.stats

    def request_table(self, name):
        try:
            if hasattr(self.hdf_group, name):
                return getattr(self.hdf_group, name)

            return self.hdf.create_table(self.hdf_group, name, DataPoint, name)
        except Exception as e:
            self.logger.error(str(e))

    def init_alert_config(self, name):
        config_name = name if self.datastore.exists('statd.alerts',
                                                    ('id', '=',
                                                     name)) else 'default'
        alert_config = self.datastore.get_by_id('statd.alerts', config_name)
        return alert_config

    def get_data_source(self, name):
        try:
            return self.data_sources[name]
        except KeyError:
            config = DataSourceConfig(self.datastore, name)
            alert_config = self.init_alert_config(name)
            ds = DataSource(self, name, config, alert_config)
            self.data_sources[name] = ds
            self.client.call_sync('plugin.register_event_type', 'statd.output',
                                  'statd.{0}.pulse'.format(name))
            return ds

    def register_schemas(self):
        self.client.register_schema(
            'GetStatsParams', {
                'type': 'object',
                'additionalProperties': False,
                'properties': {
                    'start': {
                        'type': 'datetime'
                    },
                    'end': {
                        'type': 'datetime'
                    },
                    'timespan': {
                        'type': 'integer'
                    },
                    'frequency': {
                        'type': 'string'
                    }
                }
            })

        self.client.register_schema(
            'GetStatsResult', {
                'type': 'object',
                'additionalProperties': False,
                'properties': {
                    'data': {
                        'type': 'array',
                    }
                }
            })

    def connect(self):
        while True:
            try:
                self.client.connect('unix:')
                self.client.login_service('statd')
                self.client.enable_server()
                self.register_schemas()
                self.client.register_service('statd.output',
                                             OutputService(self))
                self.client.register_service('statd.alert', AlertService(self))
                self.client.register_service('statd.debug',
                                             DebugService(gevent=True))
                self.client.resume_service('statd.output')
                self.client.resume_service('statd.alert')
                self.client.resume_service('statd.debug')
                for i in list(self.data_sources.keys()):
                    self.client.call_sync('plugin.register_event_type',
                                          'statd.output',
                                          'statd.{0}.pulse'.format(i))

                return
            except (OSError, RpcException) as err:
                self.logger.warning(
                    'Cannot connect to dispatcher: {0}, retrying in 1 second'.
                    format(str(err)))
                time.sleep(1)

    def init_dispatcher(self):
        def on_error(reason, **kwargs):
            if reason in (ClientError.CONNECTION_CLOSED, ClientError.LOGOUT):
                self.logger.warning('Connection to dispatcher lost')
                self.connect()

        self.client = Client()
        self.client.on_error(on_error)
        self.connect()

    def die(self):
        self.logger.warning('Exiting')
        self.server.stop()
        self.client.disconnect()
        sys.exit(0)

    def push_event(self, name, args):
        with self.event_lock:
            self.event_queue.append({'name': name, 'args': args})

    def event_worker(self):
        while True:
            time.sleep(1)
            with self.event_lock:
                if self.event_queue and self.client.connected:
                    self.client.send_event_burst(list(self.event_queue))
                    self.event_queue.clear()

    def checkin(self):
        checkin()

    def main(self):
        parser = argparse.ArgumentParser()
        parser.add_argument('-c',
                            metavar='CONFIG',
                            default=DEFAULT_CONFIGFILE,
                            help='Middleware config file')
        args = parser.parse_args()
        configure_logging('fnstatd', 'DEBUG')
        setproctitle('fnstatd')

        # Signal handlers
        gevent.signal(signal.SIGQUIT, self.die)
        gevent.signal(signal.SIGTERM, self.die)
        gevent.signal(signal.SIGINT, self.die)
        gevent.spawn(self.event_worker)

        self.server = InputServer(self)
        self.config = args.c
        self.init_datastore()
        self.init_dispatcher()
        self.init_database()
        self.server.start()
        self.logger.info('Started')
        self.checkin()
        self.client.wait_forever()