def initialize(self, conf_reader, msgQlist, product): """initialize configuration reader and internal msg queues""" # Initialize ScheduledMonitorThread and InternalMsgQ super(SASPortSensor, self).initialize(conf_reader) super(SASPortSensor, self).initialize_msgQ(msgQlist) self._node_id = Conf.get(GLOBAL_CONF, NODE_ID_KEY,'SN01') # Get the sas port implementor from configuration sas_port_utility = Conf.get(SSPL_CONF, f"{self.name().capitalize()}>{self.PROBE}", "sysfs") self.polling_interval = int(Conf.get(SSPL_CONF, f"{self.SENSOR_NAME.upper()}>{self.POLLING_INTERVAL}", self.DEFAULT_POLLING_INTERVAL)) try: self.HOST_ID = SAS().get_host_list()[0].replace('host', '') except SASError as err: logger.error(f"Shutting Down the SASPort Sensor due to {err}") return False except Exception as err: logger.exception("Shutting Down the SASPort Sensor with error: %s", err) return False self.RESOURCE_ID = SAS_RESOURCE_ID + self.HOST_ID # eg. SASHBA-0 if host_id=0 # Creating the instance of ToolFactory class self.tool_factory = ToolFactory() cache_dir_path = os.path.join(DATA_PATH, self.CACHE_DIR_NAME) self.SAS_PORT_SENSOR_DATA = os.path.join(cache_dir_path, f'SAS_PORT_SENSOR_DATA_{self._node_id}') alert_type = None try: # Get the instance of the utility using ToolFactory self._utility_instance = self._utility_instance or \ self.tool_factory.get_instance(sas_port_utility) self._utility_instance.initialize() phy_status = None link_value_phy_status_collection = () # Call to sas phy dirctory which will return a dictionary # which has phy_name to negotiated link rate mapping # Ex: {"phy-0:0": "<12.0, Unknown>"} self.phy_dir_to_linkrate_mapping = \ self._utility_instance.get_phy_negotiated_link_rate() # Iterate over populated dictionary and restructure it # Ex: if phy-0:0 is 12.0/6.0/3.0, considered as UP. # {"phy-0:0": ("link_rate", <Up/Down>)} for phy, value in self.phy_dir_to_linkrate_mapping.items(): if 'Gbit'.lower() in value.strip().lower(): phy_status = 'up' # Increment global phy_link count for UP status self.phy_link_count += 1 else: phy_status = 'fault' link_value_phy_status_collection = (value, phy_status) self.phy_dir_to_linkrate_mapping[phy] = link_value_phy_status_collection # Get the stored previous alert info self.sas_phy_stored_alert = store.get(self.SAS_PORT_SENSOR_DATA) self.check_and_send_alert() except KeyError as key_error: logger.error( "Unable to get the instance of {} \ Utility. Hence shutting down the sensor".format(sas_port_utility)) self.shutdown() except Exception as e: if e == errno.ENOENT: logger.error( "Problem occured while reading from sas_phy \ directory. directory path doesn't directory. Hence \ shuting down the sensor") elif e == errno.EACCES: logger.error( "Problem occured while reading from sas_phy directory. \ Not enough permission to read from the directory. \ Hence shuting down the sensor") else: logger.error( "Problem occured while reading from sas_phy directory. \ {0}. Hence shuting down the sensor".format(e)) self.shutdown() return True
def run(self): """Run the sensor on its own thread""" alert_type = None status = None new_phy_up = 0 new_phy_down = 0 # Do not proceed if module is suspended if self._suspended == True: self._scheduler.enter(self.polling_interval, self._priority, self.run, ()) return # Check for debug mode being activated self._read_my_msgQ_noWait() try: phy_link_rate_dict = \ self._utility_instance.get_phy_negotiated_link_rate() if phy_link_rate_dict: for key, value in phy_link_rate_dict.items(): link_rate = value.strip() prev_linkrate_value = \ self.phy_dir_to_linkrate_mapping[key][0].strip() prev_alert_type = \ self.phy_dir_to_linkrate_mapping[key][1].strip() status = prev_alert_type # Compare local dict wrt global dictionary for change in the # negotiated link rate if link_rate.lower() != prev_linkrate_value.lower(): # If current link rate has no value like 12/6/3 Gbit # and previously it was up, then it's a fault condition if 'Gbit'.lower() not in link_rate.lower() and prev_alert_type.lower() == 'up': # Increment count for new phy down which were up previously new_phy_down +=1 # Make respective phy_status as fault status = 'fault' # Check if 12/6/3 Gbit is there in the current link rate and # the previous alert_type is fault. If so, means phy is Up again elif 'Gbit'.lower() in link_rate.lower() and prev_alert_type.lower() == 'fault': # Mark respective phy_status as Up status = 'up' # Increment count for new phy up new_phy_up +=1 # Finally update the global dict with current link rate # and respctive phy status self.phy_dir_to_linkrate_mapping[key] = (link_rate, status) # Get current phy status i.e number of Up phys new_phy_link_count = self.phy_link_count + new_phy_up - new_phy_down # Get the last sent alert info self.sas_phy_stored_alert = store.get(self.SAS_PORT_SENSOR_DATA) self.check_and_send_alert() # Update current active phy count for next iteration self.phy_link_count = new_phy_link_count except Exception as ae: logger.exception(ae) # Fire every 30 seconds to see if there's a change in the phy status self._scheduler.enter(self.polling_interval, self._priority, self.run, ())
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 # 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) self._producer.send([json.dumps(self._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._producer.send([json.dumps(self._jsonMsg)]) 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.info("inside egress, test actuator") self._add_signature() jsonMsg = json.dumps(self._jsonMsg) self._producer.send([jsonMsg]) else: self._add_signature() jsonMsg = json.dumps(self._jsonMsg) self._producer.send([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 _check_for_fan_module_fault(self): """Iterates over fan modules list. maintains a dictionary in order to keep track of previous health of the FRU in order to set alert_type""" self._fan_modules_list = self._get_fan_modules_list() alert_type = None if not self._fan_modules_list: return try: for fan_module in self._fan_modules_list: fru_status = fan_module.get("health").lower() durable_id = fan_module.get("durable-id").lower() health_reason = fan_module.get("health-reason").lower() if fru_status == self.rssencl.HEALTH_FAULT and \ self._check_if_fan_module_is_installed(health_reason): if durable_id not in self._faulty_fan_modules_list: alert_type = self.rssencl.FRU_MISSING self._faulty_fan_modules_list[durable_id] = alert_type else: prev_alert_type = self._faulty_fan_modules_list[ durable_id] if prev_alert_type != self.rssencl.FRU_MISSING: alert_type = self.rssencl.FRU_MISSING self._faulty_fan_modules_list[ durable_id] = alert_type elif fru_status == self.rssencl.HEALTH_FAULT or \ fru_status == self.rssencl.HEALTH_DEGRADED: if durable_id not in self._faulty_fan_modules_list: alert_type = self.rssencl.FRU_FAULT self._faulty_fan_modules_list[durable_id] = alert_type else: prev_alert_type = self._faulty_fan_modules_list[ durable_id] if prev_alert_type != self.rssencl.FRU_FAULT: alert_type = self.rssencl.FRU_FAULT self._faulty_fan_modules_list[ durable_id] = alert_type elif fru_status == self.rssencl.HEALTH_OK: if durable_id in self._faulty_fan_modules_list: prev_alert_type = \ self._faulty_fan_modules_list[durable_id] if prev_alert_type == self.rssencl.FRU_MISSING: alert_type = self.rssencl.FRU_INSERTION else: alert_type = self.rssencl.FRU_FAULT_RESOLVED del self._faulty_fan_modules_list[durable_id] # Persist faulty Fan Module list to file only if there is any # type of alert generated if alert_type: internal_json_message = \ self._create_internal_json_msg(fan_module, alert_type) self._send_json_message(internal_json_message) # Wait till msg is sent to rabbitmq or added in consul for resending. # If timed out, do not update cache and revert in-memory cache. # So, in next iteration change can be detectedcted if self._event.wait( self.rssencl.PERSISTENT_DATA_UPDATE_TIMEOUT): store.put(self._faulty_fan_modules_list,\ self._faulty_fan_file_path) else: self._faulty_fan_modules_list = store.get( self._faulty_fan_file_path) alert_type = None except Exception as e: logger.exception(e)
def _check_for_sideplane_expander_fault(self): """Iterates over sideplane expander list which has some fault. maintains a dictionary in order to keep track of previous health of the FRU, so that, alert_type can be set accordingly""" self.unhealthy_components = {} self._sideplane_expander_list = \ self._get_sideplane_expander_list() alert_type = None # Declaring the health_recommendation with default type NoneType. health_recommendation = None missing_health = " ".join( "Check that all I/O modules and power supplies in\ the enclosure are fully seated in their slots and that their latches are locked" .split()) if not self._sideplane_expander_list: return for sideplane_expander in self._sideplane_expander_list: try: self.unhealthy_components = \ sideplane_expander.get("unhealthy-component", []) fru_status = sideplane_expander.get("health").lower() durable_id = sideplane_expander.get("durable-id").lower() if self.unhealthy_components: health_recommendation = \ str(self.unhealthy_components[0] ["health-recommendation"]) # checking the health_recommendation not None if the fault response will be # theire it checks missing health. if fru_status == self.rssencl.HEALTH_FAULT and health_recommendation: if missing_health.strip(" ") in health_recommendation: if durable_id not in self._faulty_sideplane_expander_dict: alert_type = self.rssencl.FRU_MISSING self._faulty_sideplane_expander_dict[ durable_id] = alert_type elif fru_status == self.rssencl.HEALTH_FAULT: if durable_id not in self._faulty_sideplane_expander_dict: alert_type = self.rssencl.FRU_FAULT self._faulty_sideplane_expander_dict[ durable_id] = alert_type elif fru_status == self.rssencl.HEALTH_OK: if durable_id in self._faulty_sideplane_expander_dict: previous_alert_type = self._faulty_sideplane_expander_dict.\ get(durable_id) alert_type = self.rssencl.FRU_FAULT_RESOLVED if previous_alert_type == self.rssencl.FRU_MISSING: alert_type = self.rssencl.FRU_INSERTION del self._faulty_sideplane_expander_dict[durable_id] if alert_type: internal_json_message = \ self._create_internal_json_message( sideplane_expander, self.unhealthy_components, alert_type) self._send_json_message(internal_json_message) # Wait till msg is sent to rabbitmq or added in consul for resending. # If timed out, do not update cache and revert in-memory cache. # So, in next iteration change can be detected if self._event.wait( self.rssencl.PERSISTENT_DATA_UPDATE_TIMEOUT): store.put(\ self._faulty_sideplane_expander_dict,\ self._faulty_sideplane_expander_file_path) else: self._faulty_sideplane_expander_dict = store.get( self._faulty_sideplane_expander_file_path) alert_type = None except Exception as ae: logger.exception(ae)
def perform_request(self, jsonMsg): """Performs the PDU request @return: The response string from the PDU """ self._check_debug(jsonMsg) response = "" try: # Parse out the login request to perform node_request = jsonMsg.get("actuator_request_type").get( "node_controller").get("node_request") self._log_debug(f"perform_request, node_request: {node_request}") # Parse out the command to send to the PDU pdu_request = node_request[5:] self._log_debug(f"perform_request, pdu_request: {pdu_request}") # Create the serial port object and open the connection login_attempts = 0 try: self._connection = serial.Serial(self._comm_port, 115200, timeout=1) except Exception as ae: logger.info(f"Serial Port connection failure: {ae}") # Attempt network connection login_attempts = self._max_login_attempts # Send user/pass until max attempts has been reached while login_attempts < self._max_login_attempts: try: if self._login_PDU() is True: break except RuntimeError as re: self._log_debug( "Failed attempting to login to PDU via serial port: %s" % re) login_attempts += 1 # If we exceeded login attempts then try the network approach if login_attempts == self._max_login_attempts: try: self._log_debug("Attempting IP communications with PDU") client = paramiko.SSHClient() client.set_missing_host_key_policy( paramiko.AutoAddPolicy()) client.connect(self._ip_addr, port=22, username=self._user, password=self._pass) # Execute the command in pdu_request show outlets details (ssh_stdin, ssh_stdout, ssh_stderr) = client.exec_command(pdu_request + "\n", timeout=5) ssh_stdin.write(pdu_request + "\n") ssh_stdin.flush() # Read in the results from the command try: for output in iter(partial(ssh_stdout.readline), ''): #self._log_debug("output: %s" % str(output)) response += output except Exception as ea: self._log_debug("Reading from PDU completed") except Exception as e: self._log_debug( f"Warning: Attempted IP connection to PDU: {e}") return str(e) finally: client.close() # Otherwise use the serial port else: self._log_debug( "perform_request, Successfully logged into PDU") # Send the request and read the response via serial port response = self._send_request_read_response_serial(pdu_request) # Apply some validation to the response and retry as a safety net if self._validate_response(response) is False: response = self._send_request_read_response_serial( pdu_request) except Exception as e: logger.exception(e) response = str(e) finally: self._logout_PDU() return response
def _rss_check_disk_faults(self): """Retreive realstor system state info using cli api /show/system""" if not self.rssencl.check_system_faults_changed(): #logger.debug("System faults state _NOT_ changed !!! ") return try: # Extract new system faults faults = self.rssencl.latest_faults # TODO optimize to avoid nested 'for' loops. # Second 'for' loop in check_new_fault() self._event = Event() if faults: for fault in faults: #logger.debug("Faulty component-id {0}, IDENT {1}"\ # .format(fault["component-id"], self.DISK_IDENTIFIER)) # Check faulting component type if self.DISK_IDENTIFIER in fault["component-id"]: # If fault on disk, get disk full info including health if self.rssencl.check_new_fault(fault): # Extract slot from "component-id":"Disk 0.39" slot = fault["component-id"].split()[1].split( '.')[1] # Alert send only if disks_prcache updated with latest disk data if self.latest_disks[int(slot)]["health"] != "OK": #get drive data from disk cache disk_info = store.get( self.disks_prcache + "disk_{0}.json".format(slot)) # raise alert for disk fault self._rss_raise_disk_alert( self.rssencl.FRU_FAULT, disk_info) # To ensure all msg is sent to message bus or added in consul for resending. self._event_wait_results.add( self._event.wait( self.rssencl. PERSISTENT_DATA_UPDATE_TIMEOUT)) self._event.clear() # Check for resolved faults for cached in self.rssencl.memcache_faults: if not any(d.get("component-id", None) == cached["component-id"] \ for d in self.rssencl.latest_faults) and self.DISK_IDENTIFIER in cached["component-id"]: # Extract slot from "component-id":"Disk 0.39" logger.info( f"Found resolved disk fault for {cached['component-id']}" ) slot = cached["component-id"].split()[1].split('.')[1] # Alert send only if disks_prcache updated with latest disk data if self.latest_disks[int(slot)]["health"] == "OK": # get drive data from disk cache disk_info = store.get(self.disks_prcache + "disk_{0}.json".format(slot)) # raise alert for resolved disk fault self._rss_raise_disk_alert( self.rssencl.FRU_FAULT_RESOLVED, disk_info) # To ensure all msg is sent to message bus or added in consul for resending. self._event_wait_results.add( self._event.wait( self.rssencl.PERSISTENT_DATA_UPDATE_TIMEOUT)) self._event.clear() # If all messages are sent to message bus or added in consul for resending. # then only update cache if self._event_wait_results and all(self._event_wait_results): self.rssencl.update_memcache_faults() self._event_wait_results.clear() self._event = None except Exception as e: logger.exception(f"Error in _rss_check_disk_faults {e}")
def perform_request(self, jsonMsg): """Performs the HPI request @return: The response string from performing the request """ self._check_debug(jsonMsg) response = "N/A" try: # Parse the incoming json msg into usable fields error = self._parse_json(jsonMsg) if error != "None": return error # Find the ControlRecord id to use based on the requested ctrl state ctrlrec_name = self._get_ctrlrec_name() self._log_debug("ctrlrec_name: %s" % ctrlrec_name) if "Error" in ctrlrec_name: return ctrlrec_name # Create the HPI system info hpi_tree_root = self._get_sysinfo() if hpi_tree_root == os.EX_SOFTWARE: return "Error: Unable to parse fetch system information" # Search through the HPI tree for the desired ControlRecord system_inventory = SystemInventory(hpi_tree_root) for encl in system_inventory: # TODO: Match incoming enclosure s/n for multiple enclosures serial_number = encl.serial_number() self._log_debug("Enclosure[{}]:".format(serial_number)) self._log_debug(" Type: {}".format(encl.enclosure_type())) for item in encl.product_information(): self._log_debug(" {}: {}".format(item.name(), item.value())) # Retrieve the ControlRecord using python-hpi library control_record = self._get_ctrl_record("Disk", SubFruIterator(encl.disk_drives()), ctrlrec_name) if control_record is None: return "Error: Failed to find ControlRecord in HPI tree" # Used in returned response for get requests value = control_record.value() # Set the ControlRecord to the desired value if self._command_type == "set": response = self._set_control_record(control_record) if "Error" in response: return response value = self._control_state # Successful get/set on ControlRecord response = "Success, Name: {} Ctrl Num: {}, Mode: {}, Value: {}" \ .format(ctrlrec_name, control_record.record_number(), control_record.mode(), value) except Exception as e: logger.exception(e) response = "Error: {0}".format(str(e)) return response
def _transmit_msg_on_exchange(self): """Transmit json message onto RabbitMQ exchange""" try: if self._jsonMsg.get("actuator_request_type") is not None and \ self._jsonMsg.get("actuator_request_type").get("plane_controller") is not None: self._working_command = self._jsonMsg.get( "actuator_request_type").get("plane_controller").get( "command") self._working_uuid = self._jsonMsg.get( "sspl_ll_msg_header").get("uuid") logger.info("PlaneCntrlMsgHandler is currently working job task command: %s, uuid: %s" % \ (str(self._working_command ), str(self._working_uuid))) return # Check for a ack msg being sent and remove the currently working job uuid if job is completed elif self._jsonMsg.get("message") is not None and \ 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: uuid = self._jsonMsg.get("message").get( "sspl_ll_msg_header").get("uuid") ack_msg = self._jsonMsg.get("message").get( "actuator_response_type").get("ack").get("ack_msg") try: ack_type = json.loads( self._jsonMsg.get("message").get( "actuator_response_type").get("ack").get( "ack_type")) except Exception as exi: logger.info( "PlaneCntrlRMQegressProcessor, _transmit_msg_on_exchange no ack_type: %s" % str(self._jsonMsg)) return # If it's a job status request then parse out the uuid from args that we're looking for if ack_type.get("command") is not None and \ ack_type.get("command") == "job_status" and \ ack_type.get("arguments") is not None: uuid = ack_type.get("arguments") self._log_debug( "Processing ack msg: %s, ack type: %s, uuid: %s" % (ack_msg, ack_type, uuid)) # Check if the passing Ack msg has the same uuid as the one that was being worked on if self._working_uuid == uuid: # If the ack msg is Not Found then change it to In work if ack_msg == "Not Found": self._jsonMsg["message"]["actuator_response_type"][ "ack"]["ack_msg"] = "In Work" logger.info("PlaneCntrlMsgHandler is working on job task command: %s, uuid: %s, ack_msg: %s" % \ (str(self._working_command), str(uuid), "In Work")) else: # Task is no longer being worked on if ack_msg is None or \ len(ack_msg) == 0: ack_msg = "Completed" self._jsonMsg["message"]["actuator_response_type"][ "ack"]["ack_msg"] = ack_msg logger.info("PlaneCntrlMsgHandler has completed job task command: %s, uuid: %s, ack_msg: %s" % \ (str(self._working_command), str(uuid), str(ack_msg))) self._working_uuid = "N/A" msg_props = pika.BasicProperties() msg_props.content_type = "text/plain" self._add_signature() self._jsonMsg = json.dumps(self._jsonMsg).encode('utf8') self._connection.publish(exchange, routing_key, properties, body) # No exceptions thrown so success self._log_debug( "_transmit_msg_on_exchange, Successfully Sent: %s" % self._jsonMsg) # If event is added by sensors, set it if self._event: self._event.set() self._msg_sent_succesfull = True except Exception as ex: logger.exception( "PlaneCntrlRMQegressProcessor, _transmit_msg_on_exchange: %r" % ex) self._msg_sent_succesfull = False
def perform_request(self, jsonMsg): """Performs the RealStor enclosure request @return: The response string from performing the request """ response = "N/A" try: enclosure_request = jsonMsg.get("actuator_request_type").get("storage_enclosure").get("enclosure_request") enclosure_request_data = [ s.strip() for s in enclosure_request.split(":")] ctrl_action = "" ctrl_type = "" if enclosure_request_data[-1] == "shutdown": # "ENCL: enclosure:fru:controller:shutdown" (request_type, _, component, component_type, ctrl_action) = enclosure_request_data elif enclosure_request_data[-1] == "restart": # "ENCL: enclosure:fru:controller:sc:restart" # "ENCL: enclosure:fru:controller:mc:restart" (request_type, _, component, component_type, ctrl_type, ctrl_action) = enclosure_request_data else: # "ENCL: enclosure:fru:controller" (request_type, _, component, component_type) = \ enclosure_request_data resource = jsonMsg.get("actuator_request_type").get("storage_enclosure").get("resource") if ctrl_action in self.CTRL_ACTION_LST: response = self.make_response( self._put_enclosure_action(ctrl_action, ctrl_type, resource.strip(), enclosure_request), component, component_type, resource, ctrl_action = ctrl_action) elif component == "fru": response = self.make_response(self.request_fru_func[ request_type][component_type](resource), component, component_type, resource) elif component == "sensor": response = self.make_response( self._get_sensor_data(sensor_type=component_type, sensor_name=resource), component, component_type, resource) elif component == "interface": enclosure_type = enclosure_request.split(":")[2] if enclosure_type == ResourceTypes.INTERFACE.value: response = self._handle_ports_request(enclosure_request, resource) else: logger.error("Some unsupported interface passed, interface:{}".format(enclosure_type)) elif component == "system": if component_type == 'info': response = self.make_response( self._get_system_info(), component, component_type, resource) else: logger.error("Unsupported system request :{}".format(enclosure_request)) except Exception as e: logger.exception("Error while getting details for JSON: {}".format(jsonMsg)) response = {"Error": e} return response
def _process_msg(self, body): """Parses the incoming message and hands off to the appropriate module""" self._log_debug("_process_msg, body: %s" % body) ingressMsg = {} try: if isinstance(body, dict) is False: ingressMsg = json.loads(body) else: ingressMsg = body # Authenticate message using username and signature fields username = ingressMsg.get("username") signature = ingressMsg.get("signature") message = ingressMsg.get("message") assert (username is not None) assert (signature is not None) assert (message is not None) msg_len = len(message) + 1 if SSPL_SEC.sspl_verify_message(msg_len, str(message), username, signature) != 0: logger.error( "Authentication failed on message: %s" % ingressMsg) return # We're acting as HAlon so ignore actuator_requests # and sensor_requests messages if message.get("actuator_request_type") is not None or \ message.get("sensor_request_type") is not None: return # Get the message type msgType = message.get("actuator_response_type") # If it's an incoming actuator msg then validate against # Actuator Response schema if msgType is not None: validate(ingressMsg, self._actuator_schema) if msgType is None: msgType = message.get("sensor_response_type") validate(ingressMsg, self._sensor_schema) # Ignore drive status messages when thread starts up during tests if message.get("sensor_response_type").get( "disk_status_drivemanager") is not None: return # If the message comes from other SSPL hosts, do not pass that # message to internal queue. This happens as SSPL instances are # listening to common queues in a RabbitMQ cluster. if 'host_id' in msgType and socket.getfqdn() != msgType['host_id']: return # Write to the msg queue so the lettuce tests can # retrieve it and examine for accuracy during automated testing self._write_internal_msgQ("RabbitMQingressProcessorTests", message) except Exception as ex: logger.exception( "_process_msg unrecognized message: %r" % ingressMsg)