class SensorWrapper(object): def __init__(self, pack, file_path, class_name, trigger_types, poll_interval=None, parent_args=None): """ :param pack: Name of the pack this sensor belongs to. :type pack: ``str`` :param file_path: Path to the sensor module file. :type file_path: ``str`` :param class_name: Sensor class name. :type class_name: ``str`` :param trigger_types: A list of references to trigger types which belong to this sensor. :type trigger_types: ``list`` of ``str`` :param poll_interval: Sensor poll interval (in seconds). :type poll_interval: ``int`` or ``None`` :param parent_args: Command line arguments passed to the parent process. :type parse_args: ``list`` """ self._pack = pack self._file_path = file_path self._class_name = class_name self._trigger_types = trigger_types or [] self._poll_interval = poll_interval self._parent_args = parent_args or [] self._trigger_names = {} # 1. Parse the config with inherited parent args try: config.parse_args(args=self._parent_args) except Exception: pass # 2. Establish DB connection username = cfg.CONF.database.username if hasattr( cfg.CONF.database, 'username') else None password = cfg.CONF.database.password if hasattr( cfg.CONF.database, 'password') else None db_setup_with_retry(cfg.CONF.database.db_name, cfg.CONF.database.host, cfg.CONF.database.port, username=username, password=password) # 3. Instantiate the watcher self._trigger_watcher = TriggerWatcher( create_handler=self._handle_create_trigger, update_handler=self._handle_update_trigger, delete_handler=self._handle_delete_trigger, trigger_types=self._trigger_types, queue_suffix='sensorwrapper_%s_%s' % (self._pack, self._class_name), exclusive=True) # 4. Set up logging self._logger = logging.getLogger('SensorWrapper.%s' % (self._class_name)) logging.setup(cfg.CONF.sensorcontainer.logging) if '--debug' in parent_args: set_log_level_for_all_loggers() self._sensor_instance = self._get_sensor_instance() def run(self): atexit.register(self.stop) self._trigger_watcher.start() self._logger.info('Watcher started') self._logger.info('Running sensor initialization code') self._sensor_instance.setup() if self._poll_interval: message = ('Running sensor in active mode (poll interval=%ss)' % (self._poll_interval)) else: message = 'Running sensor in passive mode' self._logger.info(message) try: self._sensor_instance.run() except Exception as e: # Include traceback msg = ('Sensor "%s" run method raised an exception: %s.' % (self._class_name, str(e))) self._logger.warn(msg, exc_info=True) raise Exception(msg) def stop(self): # Stop watcher self._logger.info('Stopping trigger watcher') self._trigger_watcher.stop() # Run sensor cleanup code self._logger.info('Invoking cleanup on sensor') self._sensor_instance.cleanup() ############################################## # Event handler methods for the trigger events ############################################## def _handle_create_trigger(self, trigger): self._logger.debug( 'Calling sensor "add_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.add_trigger(trigger=trigger) def _handle_update_trigger(self, trigger): self._logger.debug( 'Calling sensor "update_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.update_trigger(trigger=trigger) def _handle_delete_trigger(self, trigger): trigger_id = str(trigger.id) if trigger_id not in self._trigger_names: return self._logger.debug( 'Calling sensor "remove_trigger" method (trigger.type=%s)' % (trigger.type)) del self._trigger_names[trigger_id] trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.remove_trigger(trigger=trigger) def _get_sensor_instance(self): """ Retrieve instance of a sensor class. """ _, filename = os.path.split(self._file_path) module_name, _ = os.path.splitext(filename) sensor_class = loader.register_plugin_class( base_class=Sensor, file_path=self._file_path, class_name=self._class_name) if not sensor_class: raise ValueError( 'Sensor module is missing a class with name "%s"' % (self._class_name)) sensor_class_kwargs = {} sensor_class_kwargs['sensor_service'] = SensorService( sensor_wrapper=self) sensor_config = self._get_sensor_config() sensor_class_kwargs['config'] = sensor_config if self._poll_interval and issubclass(sensor_class, PollingSensor): sensor_class_kwargs['poll_interval'] = self._poll_interval try: sensor_instance = sensor_class(**sensor_class_kwargs) except Exception: self._logger.exception('Failed to instantiate "%s" sensor class' % (self._class_name)) raise Exception('Failed to instantiate "%s" sensor class' % (self._class_name)) return sensor_instance def _get_sensor_config(self): config_parser = ContentPackConfigParser(pack_name=self._pack) config = config_parser.get_sensor_config( sensor_file_path=self._file_path) if config: self._logger.info('Using config "%s" for sensor "%s"' % (config.file_path, self._class_name)) return config.config else: self._logger.info('No config found for sensor "%s"' % (self._class_name)) return {} def _sanitize_trigger(self, trigger): sanitized = trigger._data if 'id' in sanitized: # Friendly objectid rather than the MongoEngine representation. sanitized['id'] = str(sanitized['id']) return sanitized
class SensorWrapper(object): def __init__(self, pack, file_path, class_name, trigger_types, poll_interval=None, parent_args=None): """ :param pack: Name of the pack this sensor belongs to. :type pack: ``str`` :param file_path: Path to the sensor module file. :type file_path: ``str`` :param class_name: Sensor class name. :type class_name: ``str`` :param trigger_types: A list of references to trigger types which belong to this sensor. :type trigger_types: ``list`` of ``str`` :param poll_interval: Sensor poll interval (in seconds). :type poll_interval: ``int`` or ``None`` :param parent_args: Command line arguments passed to the parent process. :type parse_args: ``list`` """ self._pack = pack self._file_path = file_path self._class_name = class_name self._trigger_types = trigger_types or [] self._poll_interval = poll_interval self._parent_args = parent_args or [] self._trigger_names = {} # 1. Parse the config with inherited parent args try: config.parse_args(args=self._parent_args) except Exception: pass # 2. Establish DB connection username = cfg.CONF.database.username if hasattr(cfg.CONF.database, 'username') else None password = cfg.CONF.database.password if hasattr(cfg.CONF.database, 'password') else None db_setup(cfg.CONF.database.db_name, cfg.CONF.database.host, cfg.CONF.database.port, username=username, password=password) # 3. Instantiate the watcher self._trigger_watcher = TriggerWatcher(create_handler=self._handle_create_trigger, update_handler=self._handle_update_trigger, delete_handler=self._handle_delete_trigger, trigger_types=self._trigger_types, queue_suffix='sensorwrapper') # 4. Set up logging self._logger = logging.getLogger('SensorWrapper.%s' % (self._class_name)) logging.setup(cfg.CONF.sensorcontainer.logging) self._sensor_instance = self._get_sensor_instance() def run(self): atexit.register(self.stop) self._trigger_watcher.start() self._logger.info('Watcher started') self._logger.info('Running sensor initialization code') self._sensor_instance.setup() if self._poll_interval: message = ('Running sensor in active mode (poll interval=%ss)' % (self._poll_interval)) else: message = 'Running sensor in passive mode' self._logger.info(message) try: self._sensor_instance.run() except Exception as e: # Include traceback msg = ('Sensor "%s" run method raised an exception: %s.' % (self._class_name, str(e))) self._logger.warn(msg, exc_info=True) raise Exception(msg) def stop(self): # Stop watcher self._logger.info('Stopping trigger watcher') self._trigger_watcher.stop() # Run sensor cleanup code self._logger.info('Invoking cleanup on sensor') self._sensor_instance.cleanup() ############################################## # Event handler methods for the trigger events ############################################## def _handle_create_trigger(self, trigger): self._logger.debug('Calling sensor "add_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.add_trigger(trigger=trigger) def _handle_update_trigger(self, trigger): self._logger.debug('Calling sensor "update_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.update_trigger(trigger=trigger) def _handle_delete_trigger(self, trigger): trigger_id = str(trigger.id) if trigger_id not in self._trigger_names: return self._logger.debug('Calling sensor "remove_trigger" method (trigger.type=%s)' % (trigger.type)) del self._trigger_names[trigger_id] trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.remove_trigger(trigger=trigger) def _get_sensor_instance(self): """ Retrieve instance of a sensor class. """ _, filename = os.path.split(self._file_path) module_name, _ = os.path.splitext(filename) sensor_class = loader.register_plugin_class(base_class=Sensor, file_path=self._file_path, class_name=self._class_name) if not sensor_class: raise ValueError('Sensor module is missing a class with name "%s"' % (self._class_name)) sensor_class_kwargs = {} sensor_class_kwargs['sensor_service'] = SensorService(sensor_wrapper=self) sensor_config = self._get_sensor_config() if self._pack not in SYSTEM_PACK_NAMES: sensor_class_kwargs['config'] = sensor_config if self._poll_interval and issubclass(sensor_class, PollingSensor): sensor_class_kwargs['poll_interval'] = self._poll_interval try: sensor_instance = sensor_class(**sensor_class_kwargs) except Exception as e: raise Exception('Failed to instantiate "%s" sensor class: %s' % (self._class_name, str(e))) return sensor_instance def _get_sensor_config(self): config_parser = ContentPackConfigParser(pack_name=self._pack) config = config_parser.get_sensor_config(sensor_file_path=self._file_path) if config: self._logger.info('Using config "%s" for sensor "%s"' % (config.file_path, self._class_name)) return config.config else: self._logger.info('No config found for sensor "%s"' % (self._class_name)) return {} def _sanitize_trigger(self, trigger): sanitized = trigger._data if 'id' in sanitized: # Friendly objectid rather than the MongoEngine representation. sanitized['id'] = str(sanitized['id']) return sanitized
class SensorWrapper(object): def __init__(self, pack, file_path, class_name, trigger_types, poll_interval=None, parent_args=None): """ :param pack: Name of the pack this sensor belongs to. :type pack: ``str`` :param file_path: Path to the sensor module file. :type file_path: ``str`` :param class_name: Sensor class name. :type class_name: ``str`` :param trigger_types: A list of references to trigger types which belong to this sensor. :type trigger_types: ``list`` of ``str`` :param poll_interval: Sensor poll interval (in seconds). :type poll_interval: ``int`` or ``None`` :param parent_args: Command line arguments passed to the parent process. :type parse_args: ``list`` """ self._pack = pack self._file_path = file_path self._class_name = class_name self._trigger_types = trigger_types or [] self._poll_interval = poll_interval self._parent_args = parent_args or [] self._trigger_names = {} # 1. Parse the config with inherited parent args try: config.parse_args(args=self._parent_args) except Exception: pass # 2. Establish DB connection username = cfg.CONF.database.username if hasattr( cfg.CONF.database, 'username') else None password = cfg.CONF.database.password if hasattr( cfg.CONF.database, 'password') else None db_setup_with_retry( cfg.CONF.database.db_name, cfg.CONF.database.host, cfg.CONF.database.port, username=username, password=password, ssl=cfg.CONF.database.ssl, ssl_keyfile=cfg.CONF.database.ssl_keyfile, ssl_certfile=cfg.CONF.database.ssl_certfile, ssl_cert_reqs=cfg.CONF.database.ssl_cert_reqs, ssl_ca_certs=cfg.CONF.database.ssl_ca_certs, authentication_mechanism=cfg.CONF.database. authentication_mechanism, ssl_match_hostname=cfg.CONF.database.ssl_match_hostname) # 3. Instantiate the watcher self._trigger_watcher = TriggerWatcher( create_handler=self._handle_create_trigger, update_handler=self._handle_update_trigger, delete_handler=self._handle_delete_trigger, trigger_types=self._trigger_types, queue_suffix='sensorwrapper_%s_%s' % (self._pack, self._class_name), exclusive=True) # 4. Set up logging self._logger = logging.getLogger('SensorWrapper.%s.%s' % (self._pack, self._class_name)) logging.setup(cfg.CONF.sensorcontainer.logging) if '--debug' in parent_args: set_log_level_for_all_loggers() else: # NOTE: statsd logger logs everything by default under INFO so we ignore those log # messages unless verbose / debug mode is used logging.ignore_statsd_log_messages() self._sensor_instance = self._get_sensor_instance() def run(self): atexit.register(self.stop) self._trigger_watcher.start() self._logger.info('Watcher started') self._logger.info('Running sensor initialization code') self._sensor_instance.setup() if self._poll_interval: message = ('Running sensor in active mode (poll interval=%ss)' % (self._poll_interval)) else: message = 'Running sensor in passive mode' self._logger.info(message) try: self._sensor_instance.run() except Exception as e: # Include traceback msg = ('Sensor "%s" run method raised an exception: %s.' % (self._class_name, six.text_type(e))) self._logger.warn(msg, exc_info=True) raise Exception(msg) def stop(self): # Stop watcher self._logger.info('Stopping trigger watcher') self._trigger_watcher.stop() # Run sensor cleanup code self._logger.info('Invoking cleanup on sensor') self._sensor_instance.cleanup() ############################################## # Event handler methods for the trigger events ############################################## def _handle_create_trigger(self, trigger): self._logger.debug( 'Calling sensor "add_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.add_trigger(trigger=trigger) def _handle_update_trigger(self, trigger): self._logger.debug( 'Calling sensor "update_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.update_trigger(trigger=trigger) def _handle_delete_trigger(self, trigger): trigger_id = str(trigger.id) if trigger_id not in self._trigger_names: return self._logger.debug( 'Calling sensor "remove_trigger" method (trigger.type=%s)' % (trigger.type)) del self._trigger_names[trigger_id] trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.remove_trigger(trigger=trigger) def _get_sensor_instance(self): """ Retrieve instance of a sensor class. """ _, filename = os.path.split(self._file_path) module_name, _ = os.path.splitext(filename) try: sensor_class = loader.register_plugin_class( base_class=Sensor, file_path=self._file_path, class_name=self._class_name) except Exception as e: tb_msg = traceback.format_exc() msg = ( 'Failed to load sensor class from file "%s" (sensor file most likely doesn\'t ' 'exist or contains invalid syntax): %s' % (self._file_path, six.text_type(e))) msg += '\n\n' + tb_msg exc_cls = type(e) raise exc_cls(msg) if not sensor_class: raise ValueError( 'Sensor module is missing a class with name "%s"' % (self._class_name)) sensor_class_kwargs = {} sensor_class_kwargs['sensor_service'] = SensorService( sensor_wrapper=self) sensor_config = self._get_sensor_config() sensor_class_kwargs['config'] = sensor_config if self._poll_interval and issubclass(sensor_class, PollingSensor): sensor_class_kwargs['poll_interval'] = self._poll_interval try: sensor_instance = sensor_class(**sensor_class_kwargs) except Exception: self._logger.exception('Failed to instantiate "%s" sensor class' % (self._class_name)) raise Exception('Failed to instantiate "%s" sensor class' % (self._class_name)) return sensor_instance def _get_sensor_config(self): config_loader = ContentPackConfigLoader(pack_name=self._pack) config = config_loader.get_config() if config: self._logger.info('Found config for sensor "%s"' % (self._class_name)) else: self._logger.info('No config found for sensor "%s"' % (self._class_name)) return config def _sanitize_trigger(self, trigger): sanitized = TriggerAPI.from_model(trigger).to_dict() return sanitized
class SensorWrapper(object): def __init__(self, pack, file_path, class_name, trigger_types, poll_interval=None, parent_args=None): """ :param pack: Name of the pack this sensor belongs to. :type pack: ``str`` :param file_path: Path to the sensor module file. :type file_path: ``str`` :param class_name: Sensor class name. :type class_name: ``str`` :param trigger_types: A list of references to trigger types which belong to this sensor. :type trigger_types: ``list`` of ``str`` :param poll_interval: Sensor poll interval (in seconds). :type poll_interval: ``int`` or ``None`` :param parent_args: Command line arguments passed to the parent process. :type parse_args: ``list`` """ self._pack = pack self._file_path = file_path self._class_name = class_name self._trigger_types = trigger_types or [] self._poll_interval = poll_interval self._parent_args = parent_args or [] self._trigger_names = {} # 1. Parse the config with inherited parent args try: config.parse_args(args=self._parent_args) except Exception: pass # 2. Establish DB connection username = cfg.CONF.database.username if hasattr(cfg.CONF.database, 'username') else None password = cfg.CONF.database.password if hasattr(cfg.CONF.database, 'password') else None db_setup_with_retry(cfg.CONF.database.db_name, cfg.CONF.database.host, cfg.CONF.database.port, username=username, password=password, ssl=cfg.CONF.database.ssl, ssl_keyfile=cfg.CONF.database.ssl_keyfile, ssl_certfile=cfg.CONF.database.ssl_certfile, ssl_cert_reqs=cfg.CONF.database.ssl_cert_reqs, ssl_ca_certs=cfg.CONF.database.ssl_ca_certs, ssl_match_hostname=cfg.CONF.database.ssl_match_hostname) # 3. Instantiate the watcher self._trigger_watcher = TriggerWatcher(create_handler=self._handle_create_trigger, update_handler=self._handle_update_trigger, delete_handler=self._handle_delete_trigger, trigger_types=self._trigger_types, queue_suffix='sensorwrapper_%s_%s' % (self._pack, self._class_name), exclusive=True) # 4. Set up logging self._logger = logging.getLogger('SensorWrapper.%s.%s' % (self._pack, self._class_name)) logging.setup(cfg.CONF.sensorcontainer.logging) if '--debug' in parent_args: set_log_level_for_all_loggers() self._sensor_instance = self._get_sensor_instance() def run(self): atexit.register(self.stop) self._trigger_watcher.start() self._logger.info('Watcher started') self._logger.info('Running sensor initialization code') self._sensor_instance.setup() if self._poll_interval: message = ('Running sensor in active mode (poll interval=%ss)' % (self._poll_interval)) else: message = 'Running sensor in passive mode' self._logger.info(message) try: self._sensor_instance.run() except Exception as e: # Include traceback msg = ('Sensor "%s" run method raised an exception: %s.' % (self._class_name, str(e))) self._logger.warn(msg, exc_info=True) raise Exception(msg) def stop(self): # Stop watcher self._logger.info('Stopping trigger watcher') self._trigger_watcher.stop() # Run sensor cleanup code self._logger.info('Invoking cleanup on sensor') self._sensor_instance.cleanup() ############################################## # Event handler methods for the trigger events ############################################## def _handle_create_trigger(self, trigger): self._logger.debug('Calling sensor "add_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.add_trigger(trigger=trigger) def _handle_update_trigger(self, trigger): self._logger.debug('Calling sensor "update_trigger" method (trigger.type=%s)' % (trigger.type)) self._trigger_names[str(trigger.id)] = trigger trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.update_trigger(trigger=trigger) def _handle_delete_trigger(self, trigger): trigger_id = str(trigger.id) if trigger_id not in self._trigger_names: return self._logger.debug('Calling sensor "remove_trigger" method (trigger.type=%s)' % (trigger.type)) del self._trigger_names[trigger_id] trigger = self._sanitize_trigger(trigger=trigger) self._sensor_instance.remove_trigger(trigger=trigger) def _get_sensor_instance(self): """ Retrieve instance of a sensor class. """ _, filename = os.path.split(self._file_path) module_name, _ = os.path.splitext(filename) try: sensor_class = loader.register_plugin_class(base_class=Sensor, file_path=self._file_path, class_name=self._class_name) except Exception as e: tb_msg = traceback.format_exc() msg = ('Failed to load sensor class from file "%s" (sensor file most likely doesn\'t ' 'exist or contains invalid syntax): %s' % (self._file_path, str(e))) msg += '\n\n' + tb_msg exc_cls = type(e) raise exc_cls(msg) if not sensor_class: raise ValueError('Sensor module is missing a class with name "%s"' % (self._class_name)) sensor_class_kwargs = {} sensor_class_kwargs['sensor_service'] = SensorService(sensor_wrapper=self) sensor_config = self._get_sensor_config() sensor_class_kwargs['config'] = sensor_config if self._poll_interval and issubclass(sensor_class, PollingSensor): sensor_class_kwargs['poll_interval'] = self._poll_interval try: sensor_instance = sensor_class(**sensor_class_kwargs) except Exception: self._logger.exception('Failed to instantiate "%s" sensor class' % (self._class_name)) raise Exception('Failed to instantiate "%s" sensor class' % (self._class_name)) return sensor_instance def _get_sensor_config(self): config_loader = ContentPackConfigLoader(pack_name=self._pack) config = config_loader.get_config() if config: self._logger.info('Found config for sensor "%s"' % (self._class_name)) else: self._logger.info('No config found for sensor "%s"' % (self._class_name)) return config def _sanitize_trigger(self, trigger): sanitized = TriggerAPI.from_model(trigger).to_dict() return sanitized