def init_rabbitMQ_msg_processors(): """The main bootstrap for sspl automated tests""" # Initialize logging try: init_logging("SSPL-Tests", "DEBUG") except Exception as err: # We don't have logger since it threw an exception, use generic 'print' print("[ Error ] when initializing logging :") print(err) print("Exiting ...") exit(os.EX_USAGE) # Modules to be used for testing conf_modules = Conf.get(SSPL_TEST_CONF, f"{SSPL_SETTING}>{MODULES}") # Create a map of references to all the module's message queues. Each module # is passed this mapping so that it can send messages to other modules. msgQlist = {} # Create a mapping of all the instantiated modules to their names world.sspl_modules = {} # Read in product value from configuration file product = Conf.get(GLOBAL_CONF, f"release>{PRODUCT_NAME}") logger.info("sspl-ll Bootstrap: product name supported: %s" % product) # Use reflection to instantiate the class based upon its class name in config file for conf_thread in conf_modules: klass = globals()[conf_thread] # Create mappings of modules and their message queues world.sspl_modules[klass.name()] = klass() msgQlist[klass.name()] = queue.Queue() # Convert to a dict # TODO: Check use of this world.diskmonitor_file = json.loads("{}") try: # Loop through the list of instanced modules and start them on threads threads = [] for name, curr_module in list(world.sspl_modules.items()): logger.info("SSPL-Tests Starting %s" % curr_module.name()) curr_module._set_debug(True) thread = Thread(target=_run_thread_capture_errors, args=(curr_module, msgQlist, conf_reader, product)) thread.start() threads.append(thread) # Allow threads to startup before running tests time.sleep(2) # Clear the message queue buffer out from msgs sent at startup while not world.sspl_modules[ RabbitMQingressProcessorTests.name()]._is_my_msgQ_empty(): world.sspl_modules[ RabbitMQingressProcessorTests.name()]._read_my_msgQ() except Exception as ex: logger.exception(ex)
def _log_debug(self, message): """Logging messages""" if self._debug: log_msg = self.name() + ", " + message if use_journal: journal.send(log_msg, PRIORITY=7, SYSLOG_IDENTIFIER="sspl-ll") else: logger.info(log_msg)
def _debug_off_globally(self): """Turns debug mode off on all threads""" jsonMsg = {'sspl_ll_debug': {'debug_component':'all', 'debug_enabled' : False}} for _msgQ in self._msgQlist: if _msgQ != "ThreadController": logger.info("_debug_off_globally, notifying: %s" % _msgQ) self._write_internal_msgQ(_msgQ, jsonMsg) # Notify the ThreadController to bounce all threads so that blocking ones switch debug mode jsonMsg = {'sspl_ll_debug': {'debug_component':'all'}} self._write_internal_msgQ("ThreadController", jsonMsg)
def shutdown(self): """Clean up scheduler queue and gracefully shutdown thread""" super(RabbitMQingressProcessorTests, self).shutdown() time.sleep(4) try: self._connection.cleanup() except pika.exceptions.ConnectionClosed: logger.info( "RabbitMQingressProcessorTests, shutdown, RabbitMQ ConnectionClosed" ) except Exception as err: logger.info( "RabbitMQingressProcessorTests, shutdown, RabbitMQ {}".format( str(err)))
def _retry_connection(self): """Retries to establish the connection until a connection is made with RabbitMQ a node in the cluster. """ while True: try: self._establish_connection() logger.info('Connection established with RabbitMQ...') break except connection_exceptions as e: logger.error(connection_error_msg.format(repr(e))) time.sleep(self.wait_time) except Exception: raise
def run(self): """Run the module periodically on its own thread. """ self._log_debug("Start accepting requests") try: self._connection.consume(callback=self._process_msg) except Exception: if self.is_running() == True: logger.info( "RabbitMQingressProcessorTests ungracefully breaking out of run loop, restarting." ) # Configure RabbitMQ Exchange to receive messages self._configure_exchange() self._scheduler.enter(1, self._priority, self.run, ()) else: logger.info( "RabbitMQingressProcessorTests gracefully breaking out of run Loop, not restarting." ) self._log_debug("Finished processing successfully")
def _transmit_msg_on_exchange(self): """Transmit json message onto RabbitMQ exchange""" self._log_debug("_transmit_msg_on_exchange, jsonMsg: %s" % self._jsonMsg) try: # Check for shut down message from sspl_ll_d and set a flag to shutdown # once our message queue is empty if self._jsonMsg.get("message").get("actuator_response_type") is not None and \ self._jsonMsg.get("message").get("actuator_response_type").get("thread_controller") is not None and \ self._jsonMsg.get("message").get("actuator_response_type").get("thread_controller").get("thread_response") == \ "SSPL-LL is shutting down": logger.info("RabbitMQegressProcessor, _transmit_msg_on_exchange, received" \ "global shutdown message from sspl_ll_d") self._request_shutdown = True msg_props = pika.BasicProperties() msg_props.content_type = "text/plain" # Publish json message to the correct channel # NOTE: We need to route ThreadController messages to ACK channel. # We can't modify schema as it will affect other modules too. As a # temporary solution we have added a extra check to see if actuator_response_type # is "thread_controller". # TODO: Find a proper way to solve this issue. Avoid changing # core egress processor code if self._jsonMsg.get("message").get("actuator_response_type") is not None and \ (self._jsonMsg.get("message").get("actuator_response_type").get("ack") is not None or \ self._jsonMsg.get("message").get("actuator_response_type").get("thread_controller") is not None): self._add_signature() jsonMsg = json.dumps(self._jsonMsg).encode('utf8') self._ack_connection.publish(exchange=self._exchange_name, routing_key=self._ack_routing_key, properties=msg_props, body=jsonMsg) # Routing requests for IEM msgs sent from the LoggingMsgHandler elif self._jsonMsg.get("message").get("IEM_routing") is not None: log_msg = self._jsonMsg.get("message").get("IEM_routing").get("log_msg") self._log_debug("Routing IEM: %s" % log_msg) if self._iem_route_addr != "": self._iem_connection.publish(exchange=self._iem_route_exchange_name, routing_key=self._routing_key, properties=msg_props, body=str(log_msg)) else: logger.warn("RabbitMQegressProcessor, Attempted to route IEM without a valid 'iem_route_addr' set.") elif self._jsonMsg.get("message") is not None: message = self._jsonMsg.get("message") if message.get("actuator_request_type") or \ message.get("sensor_request_type") is not None: logger.error("inside egress, test actuator") unique_routing_key = f'{self._routing_key}_node{self._node_id}' logger.info(f"Connecting using routing key: {unique_routing_key}") logger.error(f"Connecting using routing key: {unique_routing_key}") self._add_signature() jsonMsg = json.dumps(self._jsonMsg).encode('utf8') self._connection.publish(exchange=self._exchange_name, routing_key=unique_routing_key, properties=msg_props, body=jsonMsg) else: self._add_signature() jsonMsg = json.dumps(self._jsonMsg).encode('utf8') self._connection.publish(exchange=self._exchange_name, routing_key=self._routing_key, properties=msg_props, body=jsonMsg) # No exceptions thrown so success self._log_debug("_transmit_msg_on_exchange, Successfully Sent: %s" % self._jsonMsg) self._msg_sent_succesfull = True except Exception as ex: logger.exception("RabbitMQegressProcessor, _transmit_msg_on_exchange: %r" % ex) self._msg_sent_succesfull = False
def _read_config(self): """Configure the RabbitMQ exchange with defaults available""" try: self._virtual_host = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.VIRT_HOST, 'SSPL') # Read common RabbitMQ configuration self._primary_rabbitmq_host = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.PRIMARY_RABBITMQ_HOST, 'localhost') # Read RabbitMQ configuration for sensor messages self._queue_name = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.QUEUE_NAME, 'sensor-queue') self._exchange_name = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.EXCHANGE_NAME, 'sspl-out') self._routing_key = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.ROUTING_KEY, 'sensor-key') # Read RabbitMQ configuration for Ack messages self._ack_queue_name = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.ACK_QUEUE_NAME, 'sensor-queue') self._ack_routing_key = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.ACK_ROUTING_KEY, 'sensor-key') self._username = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.USER_NAME, 'sspluser') self._password = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.PASSWORD, 'sspl4ever') self._signature_user = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.SIGNATURE_USERNAME, 'sspl-ll') self._signature_token = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.SIGNATURE_TOKEN, 'FAKETOKEN1234') self._signature_expires = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.SIGNATURE_EXPIRES, "3600") self._iem_route_addr = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.IEM_ROUTE_ADDR, '') self._iem_route_exchange_name = self._conf_reader._get_value_with_default(self.RABBITMQPROCESSOR, self.IEM_ROUTE_EXCHANGE_NAME, 'sspl-in') self._rack_id = self._conf_reader._get_value_with_default( self.SYSTEM_INFORMATION, self.RACK_ID, '') self._node_id = self._conf_reader._get_value_with_default( self.SYSTEM_INFORMATION, self.NODE_ID, '') self._cluster_id = self._conf_reader._get_value_with_default( self.SYSTEM_INFORMATION, self.CLUSTER_ID, '') self._site_id = self._conf_reader._get_value_with_default( self.SYSTEM_INFORMATION, self.SITE_ID, '') if self._iem_route_addr != "": logger.info(" Routing IEMs to host: %s" % self._iem_route_addr) logger.info(" Using IEM exchange: %s" % self._iem_route_exchange_name) except Exception as ex: logger.exception("RabbitMQegressProcessor, _read_config: %r" % ex)
import json import pika import os import time from sspl_test.framework.base.module_thread import ScheduledModuleThread from sspl_test.framework.base.internal_msgQ import InternalMsgQ from sspl_test.framework.utils.service_logging import logger from .rabbitmq_sspl_test_connector import RabbitMQSafeConnection import ctypes try: use_security_lib=True SSPL_SEC = ctypes.cdll.LoadLibrary('libsspl_sec.so.0') except Exception as ae: logger.info("RabbitMQegressProcessor, libsspl_sec not found, disabling authentication on egress msgs") use_security_lib=False class RabbitMQegressProcessor(ScheduledModuleThread, InternalMsgQ): """Handles outgoing messages via rabbitMQ over localhost""" MODULE_NAME = "RabbitMQegressProcessor" PRIORITY = 1 # Section and keys in configuration file SYSTEM_INFORMATION = "SYSTEM_INFORMATION" RACK_ID = "rack_id" NODE_ID = "node_id" CLUSTER_ID = "cluster_id" SITE_ID = "site_id"
def _read_config(self): """Configure the RabbitMQ exchange with defaults available""" try: self._virtual_host = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.VIRT_HOST}", 'SSPL') # Read common RabbitMQ configuration self._primary_rabbitmq_host = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.PRIMARY_RABBITMQ_HOST}", 'localhost') # Read RabbitMQ configuration for sensor messages self._queue_name = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.QUEUE_NAME}", 'sensor-queue') self._exchange_name = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.EXCHANGE_NAME}", 'sspl-out') self._routing_key = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.ROUTING_KEY}", 'sensor-key') # Read RabbitMQ configuration for Ack messages self._ack_queue_name = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.ACK_QUEUE_NAME}", 'sensor-queue') self._ack_routing_key = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.ACK_ROUTING_KEY}", 'sensor-key') self._username = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.USER_NAME}", 'sspluser') self._password = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.PASSWORD}", '') self._signature_user = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.SIGNATURE_USERNAME}", 'sspl-ll') self._signature_token = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.SIGNATURE_TOKEN}", 'FAKETOKEN1234') self._signature_expires = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.SIGNATURE_EXPIRES}", "3600") self._iem_route_addr = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.IEM_ROUTE_ADDR}", '') self._iem_route_exchange_name = Conf.get( SSPL_TEST_CONF, f"{self.RABBITMQPROCESSOR}>{self.IEM_ROUTE_EXCHANGE_NAME}", 'sspl-in') self._node_id = Conf.get( SSPL_TEST_CONF, f"{self.SYSTEM_INFORMATION}>{self.NODE_ID}", 'SN01') cluster_id = Conf.get( SSPL_TEST_CONF, f"{self.SYSTEM_INFORMATION}>{self.CLUSTER_ID}", 'CC01') # Decrypt RabbitMQ Password decryption_key = encryptor.gen_key(cluster_id, ServiceTypes.RABBITMQ.value) self._password = encryptor.decrypt(decryption_key, self._password.encode('ascii'), "RabbitMQegressProcessor") if self._iem_route_addr != "": logger.info(" Routing IEMs to host: %s" % self._iem_route_addr) logger.info(" Using IEM exchange: %s" % self._iem_route_exchange_name) except Exception as ex: print(ex) logger.error("RabbitMQegressProcessor, _read_config: %r" % ex)