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()