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, ())
Пример #3
0
    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
Пример #4
0
    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)
Пример #5
0
    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)
Пример #6
0
    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
Пример #7
0
    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}")
Пример #8
0
    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
Пример #9
0
    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
Пример #10
0
    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)