diff --git a/ansible/devutils b/ansible/devutils index de54b047073..4692e222991 100755 --- a/ansible/devutils +++ b/ansible/devutils @@ -16,7 +16,7 @@ from devutil.task_runner import TaskRunner import sys sys.path.append("..") from tests.common.connections import ConsoleHost -from tests.common.plugins.psu_controller.snmp_psu_controllers import get_psu_controller +from tests.common.plugins.pdu_controller.snmp_pdu_controllers import get_pdu_controller g_inv_mgr = None g_task_runner = None @@ -156,21 +156,21 @@ def pdu_action_on_dut(host, attrs, action): rec = { 'PDU' : p_name, 'PDU_IP' : pdu_host, 'status' : [] } ret['PDU status'].append(rec) - controller = get_psu_controller(pdu_host, host, pdu_info) + controller = get_pdu_controller(pdu_host, host, pdu_info) if not controller: ret['Summary'].append('Failed to communicate with controller {}'.format(p_name)) continue - rec['status'] = controller.get_psu_status() + rec['status'] = controller.get_outlet_status() if action == 'off': for outlet in rec['status']: - controller.turn_off_psu(outlet['psu_id']) - rec['status'] = controller.get_psu_status() + controller.turn_off_outlet(outlet['outlet_id']) + rec['status'] = controller.get_outlet_status() elif action == 'on': for outlet in rec['status']: - controller.turn_on_psu(outlet['psu_id']) - rec['status'] = controller.get_psu_status() + controller.turn_on_outlet(outlet['outlet_id']) + rec['status'] = controller.get_outlet_status() elif action != 'status': ret['Summary'].append('Unsupported action {}.'.format(action)) continue diff --git a/docs/tests/README.md b/docs/tests/README.md index ba825e08a82..d13a97758d7 100644 --- a/docs/tests/README.md +++ b/docs/tests/README.md @@ -10,7 +10,7 @@ Plugins: - [ptfadapter](/tests/common/ptfadapter/README.md) - [DUT monitor](/tests/common/dut_monitor/README.md) - [Log Analyzer](/tests/common/loganalyzer/README.md) -- [PSU Controller](/tests/common/psu_controller/README.md) +- [PSU Controller](/tests/common/pdu_controller/README.md) - [Sanity Check](/tests/common/sanity_check/README.md) - [Test Completeness](/tests/common/test_completeness/README.md) diff --git a/tests/common/plugins/psu_controller/README.md b/tests/common/plugins/pdu_controller/README.md similarity index 93% rename from tests/common/plugins/psu_controller/README.md rename to tests/common/plugins/pdu_controller/README.md index 20bf443e359..2c0fb40af05 100644 --- a/tests/common/plugins/psu_controller/README.md +++ b/tests/common/plugins/pdu_controller/README.md @@ -1,12 +1,12 @@ -# psu_controller fixture user guide +# pdu_controller fixture user guide PSU controller is usually a PDU device which can supply power to PSUs of SONiC switch. The PDU devices usually provide management interface like SNMP, web GUI, telnet, SSH, etc. -This plugin defined a fixture named psu_controller. It returns a python object implements the interface of PsuControllerBase defined in controller_base.py. +This plugin defined a fixture named pdu_controller. It returns a python object implements the interface of PsuControllerBase defined in controller_base.py. ## Add PDU information in inventory file -To get a psu_controller object using the psu_controller fixture, PDU host information must be known. +To get a pdu_controller object using the pdu_controller fixture, PDU host information must be known. PDU information of each DUT device need to be added to the inventory file. The minimum required information information of PDU host is: * IP address of the PDU host diff --git a/tests/common/plugins/psu_controller/__init__.py b/tests/common/plugins/pdu_controller/__init__.py similarity index 57% rename from tests/common/plugins/psu_controller/__init__.py rename to tests/common/plugins/pdu_controller/__init__.py index 827701e7697..6a2cc651557 100644 --- a/tests/common/plugins/psu_controller/__init__.py +++ b/tests/common/plugins/pdu_controller/__init__.py @@ -3,34 +3,34 @@ import pytest -def psu_controller_factory(controller_ip, controller_protocol, dut_hostname, pdu): +def pdu_controller_factory(controller_ip, controller_protocol, dut_hostname, pdu): """ - @summary: Factory function for creating PSU controller according to different management protocol. - @param controller_ip: IP address of the PSU controller host. - @param controller_protocol: Management protocol supported by the PSU controller host. - @param dut_hostname: Hostname of the DUT to be controlled by the PSU controller. + @summary: Factory function for creating PDU controller according to different management protocol. + @param controller_ip: IP address of the PDU controller host. + @param controller_protocol: Management protocol supported by the PDU controller host. + @param dut_hostname: Hostname of the DUT to be controlled by the PDU controller. """ - logging.info("Creating psu controller object") + logging.info("Creating pdu controller object") if controller_protocol == "snmp": - import snmp_psu_controllers - return snmp_psu_controllers.get_psu_controller(controller_ip, dut_hostname, pdu) + import snmp_pdu_controllers + return snmp_pdu_controllers.get_pdu_controller(controller_ip, dut_hostname, pdu) @pytest.fixture(scope="module") -def psu_controller(duthosts, rand_one_dut_hostname, pdu): +def pdu_controller(duthosts, rand_one_dut_hostname, pdu): """ @summary: Fixture for controlling power supply to PSUs of DUT @param duthost: Fixture duthost defined in sonic-mgmt/tests/conftest.py - @returns: Returns a psu controller object implementing the BasePsuController interface defined in + @returns: Returns a pdu controller object implementing the BasePduController interface defined in controller_base.py. """ duthost = duthosts[rand_one_dut_hostname] - logging.info("Creating psu_controller fixture") + logging.info("Creating pdu_controller fixture") inv_mgr = duthost.host.options["inventory_manager"] pdu_host = inv_mgr.get_host(duthost.hostname).get_vars().get("pdu_host") if not pdu_host: - logging.info("No 'pdu_host' is defined in inventory file for '%s'. Unable to create psu_controller" % + logging.info("No 'pdu_host' is defined in inventory file for '%s'. Unable to create pdu_controller" % duthost.hostname) yield None return @@ -40,7 +40,7 @@ def psu_controller(duthosts, rand_one_dut_hostname, pdu): controller_ip = controller_vars.get("ansible_host") if not controller_ip: logging.info("No 'ansible_host' is defined in inventory file for '%s'" % pdu_host) - logging.info("Unable to create psu_controller for %s" % duthost.hostname) + logging.info("Unable to create pdu_controller for %s" % duthost.hostname) yield None return @@ -49,15 +49,15 @@ def psu_controller(duthosts, rand_one_dut_hostname, pdu): logging.info("No protocol is defined in inventory file for '%s'. Try to use default 'snmp'" % pdu_host) controller_protocol = "snmp" - controller = psu_controller_factory(controller_ip, controller_protocol, duthost.hostname, pdu) + controller = pdu_controller_factory(controller_ip, controller_protocol, duthost.hostname, pdu) yield controller - logging.info("psu_controller fixture teardown, ensure that all PSUs are turned on after test") + logging.info("pdu_controller fixture teardown, ensure that all PDU outlets are turned on after test") if controller: - psu_status = controller.get_psu_status() - if psu_status: - for psu in psu_status: - if not psu["psu_on"]: - controller.turn_on_psu(psu["psu_id"]) + outlet_status = controller.get_outlet_status() + if outlet_status: + for outlet in outlet_status: + if not outlet["outlet_on"]: + controller.turn_on_outlet(outlet["outlet_id"]) controller.close() diff --git a/tests/common/plugins/psu_controller/controller_base.py b/tests/common/plugins/pdu_controller/controller_base.py similarity index 56% rename from tests/common/plugins/psu_controller/controller_base.py rename to tests/common/plugins/pdu_controller/controller_base.py index e0ae4bdc49f..d26b669dd16 100644 --- a/tests/common/plugins/psu_controller/controller_base.py +++ b/tests/common/plugins/pdu_controller/controller_base.py @@ -1,56 +1,54 @@ """ -Base class for controlling PSUs of DUT +Base class for controlling PDU(s) connected to DUT power supplies -This file defines the base class for controlling PSUs of DUT. The base class defined the basic interface of -PSU controllers. +This file defines the base class for controlling PDU outlets. The base class defined the basic interface of +PDU controllers. -The PSU controller for actually controlling PSUs must be a subclass of the PsuControllerBase class and must +The PDU controller for PDUs must be a subclass of the PduControllerBase class and must implement the methods defined in the base class. """ -import os -import sys import subprocess -class PsuControllerBase(): +class PduControllerBase(): """ - @summary: Base class for PSU controller + @summary: Base class for PDU controller - This base class defines the basic interface to be provided by PSU controller. + This base class defines the basic interface to be provided by PDU controller. - The PSU controller for actually controlling PSUs must be a subclass of the PsuControllerBase class and must + The PDU controller for PDUs must be a subclass of the PduControllerBase class and must implement the methods defined in the base class. """ def __init__(self): pass - def turn_on_psu(self, psu_id): + def turn_on_outlet(self, outlet): """ - @summary: Turn on power for specified PSU. + @summary: Turn on power for specified PDU. - @param psu_id: PSU ID, it could be integer of string digit. For example: 0 or '1' + @param outlet: PDU ID, it could be integer of string digit. For example: 0 or '1' @return: Returns True if operation is successful. Otherwise, returns False """ raise NotImplementedError - def turn_off_psu(self, psu_id): + def turn_off_outlet(self, outlet): """ - @summary: Turn off power for specified PSU. + @summary: Turn off power for specified PDU. - @param psu_id: PSU ID, it could be integer of string digit. For example: 0 or '1' + @param outlet: PDU ID, it could be integer of string digit. For example: 0 or '1' @return: Returns True if operation is successful. Otherwise, returns False """ raise NotImplementedError - def get_psu_status(self, psu_id=None): + def get_outlet_status(self, outlet=None): """ - @summary: Get current power status of PSUs + @summary: Get current power status of PDU outlets - @param psu_id: Optional PSU ID, it could be integer or string digit. If no psu_id is specified, power status of - all PSUs should be returned + @param outlet: Optional outlet ID, it could be integer or string digit. If no outlet is specified, power status of + all PDU outlets should be returned @return: Returns a list of dictionaries. For example: - [{"psu_id": 0, "psu_on": True}, {"psu_id": 1, "psu_on": True}] - If getting PSU status failed, an empty list should be returned. + [{"outlet_id": 0, "outlet_on": True}, {"outlet_id": 1, "outlet_on": True}] + If getting outlet(s) status failed, an empty list should be returned. """ raise NotImplementedError diff --git a/tests/common/plugins/psu_controller/snmp_psu_controllers.py b/tests/common/plugins/pdu_controller/snmp_pdu_controllers.py similarity index 70% rename from tests/common/plugins/psu_controller/snmp_psu_controllers.py rename to tests/common/plugins/pdu_controller/snmp_pdu_controllers.py index 5f5d7a8cac6..56d437ba604 100644 --- a/tests/common/plugins/psu_controller/snmp_psu_controllers.py +++ b/tests/common/plugins/pdu_controller/snmp_pdu_controllers.py @@ -1,32 +1,32 @@ """ -This module contains classes for PSU controllers that supports the SNMP management protocol. +This module contains classes for PDU controllers that supports the SNMP management protocol. -The classes must implement the PsuControllerBase interface defined in controller_base.py. +The classes must implement the PduControllerBase interface defined in controller_base.py. """ import logging -from controller_base import PsuControllerBase +from controller_base import PduControllerBase from pysnmp.proto import rfc1902 from pysnmp.entity.rfc3413.oneliner import cmdgen -class snmpPsuController(PsuControllerBase): +class snmpPduController(PduControllerBase): """ - PSU Controller class for SNMP conrolled PSUs - 'Sentry Switched CDU' and 'APC Web/SNMP Management Card' + PDU Controller class for SNMP conrolled PDUs - 'Sentry Switched CDU' and 'APC Web/SNMP Management Card' - This class implements the interface defined in PsuControllerBase class for SNMP conrtolled PDU type + This class implements the interface defined in PduControllerBase class for SNMP conrtolled PDU type 'Sentry Switched CDU' and 'APC Web/SNMP Management Card' """ - def get_psu_controller_type(self): + def get_pdu_controller_type(self): """ - @summary: Use SNMP to get the type of PSU controller host - @param psu_controller_host: IP address of PSU controller host - @return: Returns type string of the specified PSU controller host + @summary: Use SNMP to get the type of PDU controller host + @param pdu_controller_host: IP address of PDU controller host + @return: Returns type string of the specified PDU controller host """ pSYSDESCR = ".1.3.6.1.2.1.1.1.0" SYSDESCR = "1.3.6.1.2.1.1.1.0" - psu = None + pdu = None cmdGen = cmdgen.CommandGenerator() snmp_auth = cmdgen.CommunityData(self.snmp_rocommunity) errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( @@ -35,30 +35,30 @@ def get_psu_controller_type(self): cmdgen.MibVariable(pSYSDESCR,), ) if errorIndication: - logging.info("Failed to get psu controller type, exception: " + str(errorIndication)) + logging.info("Failed to get pdu controller type, exception: " + str(errorIndication)) for oid, val in varBinds: current_oid = oid.prettyPrint() current_val = val.prettyPrint() if current_oid == SYSDESCR: - psu = current_val - if psu is None: - self.psuType = None + pdu = current_val + if pdu is None: + self.pduType = None return - if 'Sentry Switched PDU' in psu: - self.psuType = "SENTRY4" - if 'Sentry Switched CDU' in psu: - self.psuType = "SENTRY" - if 'APC Web/SNMP Management Card' in psu: - self.psuType = "APC" - if 'Emerson' in psu: - self.psuType = 'Emerson' + if 'Sentry Switched PDU' in pdu: + self.pduType = "SENTRY4" + if 'Sentry Switched CDU' in pdu: + self.pduType = "SENTRY" + if 'APC Web/SNMP Management Card' in pdu: + self.pduType = "APC" + if 'Emerson' in pdu: + self.pduType = 'Emerson' return - def psuCntrlOid(self): + def pduCntrlOid(self): """ - Define Oids based on the PSU Type + Define Oids based on the PDU Type """ - # MIB OIDs for 'APC Web/SNMP Management PSU' + # MIB OIDs for 'APC Web/SNMP Management PDU' APC_PORT_NAME_BASE_OID = "1.3.6.1.4.1.318.1.1.4.4.2.1.4" APC_PORT_STATUS_BASE_OID = "1.3.6.1.4.1.318.1.1.12.3.5.1.1.4" APC_PORT_CONTROL_BASE_OID = "1.3.6.1.4.1.318.1.1.12.3.3.1.1.4" @@ -78,28 +78,28 @@ def psuCntrlOid(self): self.STATUS_OFF = "0" self.CONTROL_ON = "1" self.CONTROL_OFF = "2" - if self.psuType == "APC": + if self.pduType == "APC": self.pPORT_NAME_BASE_OID = '.'+APC_PORT_NAME_BASE_OID self.pPORT_STATUS_BASE_OID = '.'+APC_PORT_STATUS_BASE_OID self.pPORT_CONTROL_BASE_OID = '.'+APC_PORT_CONTROL_BASE_OID self.PORT_NAME_BASE_OID = APC_PORT_NAME_BASE_OID self.PORT_STATUS_BASE_OID = APC_PORT_STATUS_BASE_OID self.PORT_CONTROL_BASE_OID = APC_PORT_CONTROL_BASE_OID - elif self.psuType == "SENTRY": + elif self.pduType == "SENTRY": self.pPORT_NAME_BASE_OID = '.'+SENTRY_PORT_NAME_BASE_OID self.pPORT_STATUS_BASE_OID = '.'+SENTRY_PORT_STATUS_BASE_OID self.pPORT_CONTROL_BASE_OID = '.'+SENTRY_PORT_CONTROL_BASE_OID self.PORT_NAME_BASE_OID = SENTRY_PORT_NAME_BASE_OID self.PORT_STATUS_BASE_OID = SENTRY_PORT_STATUS_BASE_OID self.PORT_CONTROL_BASE_OID = SENTRY_PORT_CONTROL_BASE_OID - elif self.psuType == "Emerson": + elif self.pduType == "Emerson": self.pPORT_NAME_BASE_OID = '.'+EMERSON_PORT_NAME_BASE_OID self.pPORT_STATUS_BASE_OID = '.'+EMERSON_PORT_STATUS_BASE_OID self.pPORT_CONTROL_BASE_OID = '.'+EMERSON_PORT_CONTROL_BASE_OID self.PORT_NAME_BASE_OID = EMERSON_PORT_NAME_BASE_OID self.PORT_STATUS_BASE_OID = EMERSON_PORT_STATUS_BASE_OID self.PORT_CONTROL_BASE_OID = EMERSON_PORT_CONTROL_BASE_OID - elif self.psuType == "SENTRY4": + elif self.pduType == "SENTRY4": self.pPORT_NAME_BASE_OID = '.'+SENTRY4_PORT_NAME_BASE_OID self.pPORT_STATUS_BASE_OID = '.'+SENTRY4_PORT_STATUS_BASE_OID self.pPORT_CONTROL_BASE_OID = '.'+SENTRY4_PORT_CONTROL_BASE_OID @@ -117,8 +117,8 @@ def _get_pdu_ports(self): The PDU ports connected to DUT must have hostname of DUT configured in port name/description. This method depends on this configuration to find out the PDU ports connected to PSUs of specific DUT. """ - if not self.psuType: - logging.info('PSU type is unknown') + if not self.pduType: + logging.info('PDU type is unknown') return max_lane = 5 @@ -155,7 +155,7 @@ def map_host_to_lane(self, lane_id): """ Dynamically update Oids based on the PDU lane ID """ - if self.psuType == "SENTRY4": + if self.pduType == "SENTRY4": # No need to update lane for SENTRY4 return @@ -168,40 +168,40 @@ def map_host_to_lane(self, lane_id): def __init__(self, hostname, controller, pdu): logging.info("Initializing " + self.__class__.__name__) - PsuControllerBase.__init__(self) + PduControllerBase.__init__(self) self.hostname = hostname self.controller = controller self.snmp_rocommunity = pdu['snmp_rocommunity'] self.snmp_rwcommunity = pdu['snmp_rwcommunity'] self.pdu_ports = [] - self.psuType = None - self.get_psu_controller_type() - self.psuCntrlOid() + self.pduType = None + self.get_pdu_controller_type() + self.pduCntrlOid() self._get_pdu_ports() logging.info("Initialized " + self.__class__.__name__) - def turn_on_psu(self, psu_id): + def turn_on_outlet(self, outlet): """ - @summary: Use SNMP to turn on power to PSU of DUT specified by psu_id + @summary: Use SNMP to turn on power to PDU of DUT specified by outlet DUT hostname must be configured in PDU port name/description. But it is hard to specify which PDU port is - connected to the first PSU of DUT and which port is connected to the second PSU. + connected to the first PDU of DUT and which port is connected to the second PDU. Because of this, currently we just find out which PDU ports are connected to PSUs of which DUT. We cannot find out the exact mapping between PDU ports and PSUs of DUT. - To overcome this limitation, the trick is to convert the specified psu_id to integer, then calculate the mode + To overcome this limitation, the trick is to convert the specified outlet to integer, then calculate the mode upon the number of PSUs on DUT. The calculated mode is used as an index to get PDU ports ID stored in - self.pdu_ports. But still, we cannot gurante that psu_id 0 is first PSU of DUT, and so on. + self.pdu_ports. But still, we cannot gurante that outlet 0 is first PDU of DUT, and so on. - @param psu_id: ID of the PSU on SONiC DUT + @param outlet: ID of the PDU on SONiC DUT @return: Return true if successfully execute the command for turning on power. Otherwise return False. """ - if not self.psuType: - logging.error('Unable to turn on: PSU type is unknown') + if not self.pduType: + logging.error('Unable to turn on: PDU type is unknown') return False - port_oid = self.pPORT_CONTROL_BASE_OID + self.pdu_ports[rfc1902.Integer(psu_id)] + port_oid = self.pPORT_CONTROL_BASE_OID + self.pdu_ports[rfc1902.Integer(outlet)] errorIndication, errorStatus, _, _ = \ cmdgen.CommandGenerator().setCmd( cmdgen.CommunityData(self.snmp_rwcommunity), @@ -209,32 +209,32 @@ def turn_on_psu(self, psu_id): (port_oid, rfc1902.Integer(self.CONTROL_ON)), ) if errorIndication or errorStatus != 0: - logging.debug("Failed to turn on PSU %s, exception: %s" % (str(psu_id), str(errorStatus))) + logging.debug("Failed to turn on outlet %s, exception: %s" % (str(outlet), str(errorStatus))) return False return True - def turn_off_psu(self, psu_id): + def turn_off_outlet(self, outlet): """ - @summary: Use SNMP to turn off power to PSU of DUT specified by psu_id + @summary: Use SNMP to turn off power to PDU outlet of DUT specified by outlet DUT hostname must be configured in PDU port name/description. But it is hard to specify which PDU port is connected to the first PSU of DUT and which port is connected to the second PSU. - Because of this, currently we just find out which PDU ports are connected to PSUs of which DUT. We cannot - find out the exact mapping between PDU ports and PSUs of DUT. + Because of this, currently we just find out which PDU outlets are connected to PSUs of which DUT. We cannot + find out the exact mapping between PDU outlets and PSUs of DUT. - To overcome this limitation, the trick is to convert the specified psu_id to integer, then calculate the mode + To overcome this limitation, the trick is to convert the specified outlet to integer, then calculate the mode upon the number of PSUs on DUT. The calculated mode is used as an index to get PDU ports ID stored in - self.pdu_ports. But still, we cannot gurante that psu_id 0 is first PSU of DUT, and so on. + self.pdu_ports. But still, we cannot guarantee that outlet 0 is first PSU of DUT, and so on. - @param psu_id: ID of the PSU on SONiC DUT + @param outlet: ID of the outlet on PDU @return: Return true if successfully execute the command for turning off power. Otherwise return False. """ - if not self.psuType: - logging.error('Unable to turn off: PSU type is unknown') + if not self.pduType: + logging.error('Unable to turn off: PDU type is unknown') return False - port_oid = self.pPORT_CONTROL_BASE_OID + self.pdu_ports[rfc1902.Integer(psu_id)] + port_oid = self.pPORT_CONTROL_BASE_OID + self.pdu_ports[rfc1902.Integer(outlet)] errorIndication, errorStatus, _, _ = \ cmdgen.CommandGenerator().setCmd( cmdgen.CommunityData(self.snmp_rwcommunity), @@ -242,11 +242,11 @@ def turn_off_psu(self, psu_id): (port_oid, rfc1902.Integer(self.CONTROL_OFF)), ) if errorIndication or errorStatus != 0: - logging.debug("Failed to turn on PSU %s, exception: %s" % (str(psu_id), str(errorStatus))) + logging.debug("Failed to turn on outlet %s, exception: %s" % (str(outlet), str(errorStatus))) return False return True - def get_psu_status(self, psu_id=None): + def get_outlet_status(self, outlet=None): """ @summary: Use SNMP to get status of PDU ports supplying power to PSUs of DUT @@ -254,21 +254,21 @@ def get_psu_status(self, psu_id=None): connected to the first PSU of DUT and which port is connected to the second PSU. Because of this, currently we just find out which PDU ports are connected to PSUs of which DUT. We cannot - find out the exact mapping between PDU ports and PSUs of DUT. + find out the exact mapping between PDU outlets and PSUs of DUT. - To overcome this limitation, the trick is to convert the specified psu_id to integer, then calculate the mode - upon the number of PSUs on DUT. The calculated mode is used as an index to get PDU ports ID stored in - self.pdu_ports. But still, we cannot gurante that psu_id 0 is first PSU of DUT, and so on. + To overcome this limitation, the trick is to convert the specified outlet to integer, then calculate the mode + upon the number of PSUs on DUT. The calculated mode is used as an index to get PDU outlet ID stored in + self.pdu_ports. But still, we cannot guarantee that outlet 0 is first PSU of DUT, and so on. - @param psu_id: Optional. If specified, only return status of PDU port connected to specified PSU of DUT. If - omitted, return status of all PDU ports connected to PSUs of DUT. - @return: Return status of PDU ports connected to PSUs of DUT in a list of dictionary. Example result: - [{"psu_id": 0, "psu_on": True}, {"psu_id": 1, "psu_on": True}] - The psu_id in returned result is integer starts from 0. + @param outlet: Optional. If specified, only return status of PDU outlet connected to specified PSU of DUT. If + omitted, return status of all PDU outlets connected to PSUs of DUT. + @return: Return status of PDU outlets connected to PSUs of DUT in a list of dictionary. Example result: + [{"outlet_id": 0, "outlet_on": True}, {"outlet_id": 1, "outlet_on": True}] + The outlet in returned result is integer starts from 0. """ results = [] - if not self.psuType: - logging.error('Unable to retrieve status: PSU type is unknown') + if not self.pduType: + logging.error('Unable to retrieve status: PDU type is unknown') return results cmdGen = cmdgen.CommandGenerator() @@ -287,21 +287,21 @@ def get_psu_status(self, psu_id=None): for idx, port in enumerate(self.pdu_ports): port_oid = self.PORT_STATUS_BASE_OID + port if current_oid == port_oid: - status = {"psu_id": idx, "psu_on": True if current_val == self.STATUS_ON else False} + status = {"outlet_id": idx, "outlet_on": True if current_val == self.STATUS_ON else False} results.append(status) - if psu_id is not None: - idx = int(psu_id) % len(self.pdu_ports) + if outlet is not None: + idx = int(outlet) % len(self.pdu_ports) results = results[idx:idx+1] - logging.info("Got PSU status: %s" % str(results)) + logging.info("Got outlet status: %s" % str(results)) return results def close(self): pass -def get_psu_controller(controller_ip, dut_hostname, pdu): +def get_pdu_controller(controller_ip, dut_hostname, pdu): """ - @summary: Factory function to create the actual PSU controller object. - @return: The actual PSU controller object. Returns None if something went wrong. + @summary: Factory function to create the actual PDU controller object. + @return: The actual PDU controller object. Returns None if something went wrong. """ - return snmpPsuController(dut_hostname, controller_ip, pdu) + return snmpPduController(dut_hostname, controller_ip, pdu) diff --git a/tests/conftest.py b/tests/conftest.py index 69f337d9460..739bf6be6d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,7 +35,7 @@ 'tests.common.plugins.dut_monitor', 'tests.common.plugins.tacacs', 'tests.common.plugins.loganalyzer', - 'tests.common.plugins.psu_controller', + 'tests.common.plugins.pdu_controller', 'tests.common.plugins.sanity_check', 'tests.common.plugins.custom_markers', 'tests.common.plugins.test_completeness', diff --git a/tests/platform_tests/test_platform_info.py b/tests/platform_tests/test_platform_info.py index a462d0b2350..aaa0d755536 100644 --- a/tests/platform_tests/test_platform_info.py +++ b/tests/platform_tests/test_platform_info.py @@ -153,12 +153,12 @@ def check_vendor_specific_psustatus(dut, psu_status_line): check_psu_sysfs(dut, psu_id, psu_status) -def turn_all_psu_on(psu_ctrl): - all_psu_status = psu_ctrl.get_psu_status() - pytest_require(all_psu_status and len(all_psu_status) >= 2, 'Skip the test, cannot to get at least 2 PSU status: {}'.format(all_psu_status)) - for psu in all_psu_status: - if not psu["psu_on"]: - psu_ctrl.turn_on_psu(psu["psu_id"]) +def turn_all_outlets_on(pdu_ctrl): + all_outlet_status = pdu_ctrl.get_outlet_status() + pytest_require(all_outlet_status and len(all_outlet_status) >= 2, 'Skip the test, cannot to get at least 2 outlet status: {}'.format(all_outlet_status)) + for outlet in all_outlet_status: + if not outlet["outlet_on"]: + pdu_ctrl.turn_on_outlet(outlet["outlet_id"]) time.sleep(5) @@ -179,7 +179,7 @@ def check_all_psu_on(dut, psu_test_results): @pytest.mark.disable_loganalyzer @pytest.mark.parametrize('ignore_particular_error_log', [SKIP_ERROR_LOG_PSU_ABSENCE], indirect=True) -def test_turn_on_off_psu_and_check_psustatus(duthosts, rand_one_dut_hostname, psu_controller, ignore_particular_error_log): +def test_turn_on_off_psu_and_check_psustatus(duthosts, rand_one_dut_hostname, pdu_controller, ignore_particular_error_log): """ @summary: Turn off/on PSU and check PSU status using 'show platform psustatus' """ @@ -191,11 +191,11 @@ def test_turn_on_off_psu_and_check_psustatus(duthosts, rand_one_dut_hostname, ps pytest_require(psu_num >= 2, "At least 2 PSUs required for rest of the testing in this case") logging.info("Create PSU controller for testing") - psu_ctrl = psu_controller - pytest_require(psu_ctrl, "No PSU controller for %s, skip rest of the testing in this case" % duthost.hostname) + pdu_ctrl = pdu_controller + pytest_require(pdu_ctrl, "No PSU controller for %s, skip rest of the testing in this case" % duthost.hostname) logging.info("To avoid DUT being shutdown, need to turn on PSUs that are not powered") - turn_all_psu_on(psu_ctrl) + turn_all_outlets_on(pdu_ctrl) logging.info("Initialize test results") psu_test_results = {} @@ -205,13 +205,13 @@ def test_turn_on_off_psu_and_check_psustatus(duthosts, rand_one_dut_hostname, ps "In consistent PSU number output by '%s' and '%s'" % (CMD_PLATFORM_PSUSTATUS, "sudo psuutil numpsus")) logging.info("Start testing turn off/on PSUs") - all_psu_status = psu_ctrl.get_psu_status() - pytest_require(all_psu_status and len(all_psu_status) >= 2, 'Skip the test, cannot get at least 2 PSU status: {}'.format(all_psu_status)) - for psu in all_psu_status: + all_outlet_status = pdu_ctrl.get_outlet_status() + pytest_require(all_outlet_status and len(all_outlet_status) >= 2, 'Skip the test, cannot get at least 2 outlet status: {}'.format(all_outlet_status)) + for outlet in all_outlet_status: psu_under_test = None - logging.info("Turn off PSU %s" % str(psu["psu_id"])) - psu_ctrl.turn_off_psu(psu["psu_id"]) + logging.info("Turn off outlet %s" % str(outlet["outlet_id"])) + pdu_ctrl.turn_off_outlet(outlet["outlet_id"]) time.sleep(5) cli_psu_status = duthost.command(CMD_PLATFORM_PSUSTATUS) @@ -223,8 +223,8 @@ def test_turn_on_off_psu_and_check_psustatus(duthosts, rand_one_dut_hostname, ps check_vendor_specific_psustatus(duthost, line) pytest_assert(psu_under_test is not None, "No PSU is turned off") - logging.info("Turn on PSU %s" % str(psu["psu_id"])) - psu_ctrl.turn_on_psu(psu["psu_id"]) + logging.info("Turn on outlet %s" % str(outlet["outlet_id"])) + pdu_ctrl.turn_on_outlet(outlet["outlet_id"]) time.sleep(5) cli_psu_status = duthost.command(CMD_PLATFORM_PSUSTATUS) @@ -317,7 +317,7 @@ def check_thermal_control_load_invalid_file(duthost, file_name): @pytest.mark.disable_loganalyzer @pytest.mark.parametrize('ignore_particular_error_log', [SKIP_ERROR_LOG_PSU_ABSENCE], indirect=True) -def test_thermal_control_psu_absence(duthosts, rand_one_dut_hostname, psu_controller, mocker_factory, ignore_particular_error_log): +def test_thermal_control_psu_absence(duthosts, rand_one_dut_hostname, pdu_controller, mocker_factory, ignore_particular_error_log): """ @summary: Turn off/on PSUs, check thermal control is working as expect. """ @@ -326,13 +326,13 @@ def test_thermal_control_psu_absence(duthosts, rand_one_dut_hostname, psu_contro pytest_require(psu_num >= 2, "At least 2 PSUs required for rest of the testing in this case") - logging.info("Create PSU controller for testing") - psu_ctrl = psu_controller + logging.info("Create PDU controller for testing") + pdu_ctrl = pdu_controller - pytest_require(psu_ctrl, "No PSU controller for %s, skip rest of the testing in this case" % duthost.hostname) + pytest_require(pdu_ctrl, "No PDU controller for %s, skip rest of the testing in this case" % duthost.hostname) logging.info("To avoid DUT being shutdown, need to turn on PSUs that are not powered") - turn_all_psu_on(psu_ctrl) + turn_all_outlets_on(pdu_ctrl) logging.info("Initialize test results") psu_test_results = {} @@ -353,17 +353,17 @@ def test_thermal_control_psu_absence(duthosts, rand_one_dut_hostname, psu_contro check_thermal_algorithm_status(duthost, mocker_factory, False) - logging.info('Shutdown first PSU and check thermal control result...') - all_psu_status = psu_ctrl.get_psu_status() - pytest_require(all_psu_status and len(all_psu_status) >= 2, 'Skip the test, cannot get at least 2 PSU status: {}'.format(all_psu_status)) - psu = all_psu_status[0] - turn_off_psu_and_check_thermal_control(duthost, psu_ctrl, psu, fan_mocker) + logging.info('Shutdown first PDU outlet and check thermal control result...') + all_outlet_status = pdu_ctrl.get_outlet_status() + pytest_require(all_outlet_status and len(all_outlet_status) >= 2, 'Skip the test, cannot get at least 2 outlet status: {}'.format(all_outlet_status)) + outlet = all_outlet_status[0] + turn_off_outlet_and_check_thermal_control(duthost, pdu_ctrl, outlet, fan_mocker) psu_test_results.clear() pytest_require(check_all_psu_on(duthost, psu_test_results), "Some PSU are still down, skip rest of the testing in this case") - logging.info('Shutdown second PSU and check thermal control result...') - psu = all_psu_status[1] - turn_off_psu_and_check_thermal_control(duthost, psu_ctrl, psu, fan_mocker) + logging.info('Shutdown second PDU outlet and check thermal control result...') + outlet = all_outlet_status[1] + turn_off_outlet_and_check_thermal_control(duthost, pdu_ctrl, outlet, fan_mocker) psu_test_results.clear() pytest_require(check_all_psu_on(duthost, psu_test_results), "Some PSU are still down, skip rest of the testing in this case") @@ -374,13 +374,13 @@ def test_thermal_control_psu_absence(duthosts, rand_one_dut_hostname, psu_contro 65), 'FAN speed not change to 65% according to policy') -def turn_off_psu_and_check_thermal_control(dut, psu_ctrl, psu, mocker): +def turn_off_outlet_and_check_thermal_control(dut, pdu_ctrl, outlet, mocker): """ @summary: Turn off PSUs, check all FAN speed are set to 100% according to thermal control policy file. """ - logging.info("Turn off PSU %s" % str(psu["psu_id"])) - psu_ctrl.turn_off_psu(psu["psu_id"]) + logging.info("Turn off outlet %s" % str(outlet["psu_id"])) + pdu_ctrl.turn_off_outlet(outlet["outlet_id"]) time.sleep(5) psu_under_test = None @@ -399,7 +399,7 @@ def turn_off_psu_and_check_thermal_control(dut, psu_ctrl, psu, mocker): mocker.check_all_fan_speed, 100), 'FAN speed not turn to 100% after PSU off') - psu_ctrl.turn_on_psu(psu["psu_id"]) + pdu_ctrl.turn_on_outlet(outlet["outlet_id"]) time.sleep(5) diff --git a/tests/platform_tests/test_reboot.py b/tests/platform_tests/test_reboot.py index 7b497afbc66..6deebc2b9f0 100644 --- a/tests/platform_tests/test_reboot.py +++ b/tests/platform_tests/test_reboot.py @@ -154,37 +154,37 @@ def _power_off_reboot_helper(kwargs): @summary: used to parametrized test cases on power_off_delay @param kwargs: the delay time between turning off and on the PSU """ - psu_ctrl = kwargs["psu_ctrl"] - all_psu = kwargs["all_psu"] + pdu_ctrl = kwargs["pdu_ctrl"] + all_outlets = kwargs["all_outlets"] power_on_seq = kwargs["power_on_seq"] delay_time = kwargs["delay_time"] - for psu in all_psu: - logging.debug("turning off {}".format(psu)) - psu_ctrl.turn_off_psu(psu["psu_id"]) + for outlet in all_outlets: + logging.debug("turning off {}".format(outlet)) + pdu_ctrl.turn_off_outlet(outlet["outlet_id"]) time.sleep(delay_time) logging.info("Power on {}".format(power_on_seq)) - for psu in power_on_seq: - logging.debug("turning on {}".format(psu)) - psu_ctrl.turn_on_psu(psu["psu_id"]) + for outlet in power_on_seq: + logging.debug("turning on {}".format(outlet)) + pdu_ctrl.turn_on_outlet(outlet["outlet_id"]) -def test_power_off_reboot(duthosts, rand_one_dut_hostname, localhost, conn_graph_facts, xcvr_skip_list, psu_controller, power_off_delay): +def test_power_off_reboot(duthosts, rand_one_dut_hostname, localhost, conn_graph_facts, xcvr_skip_list, pdu_controller, power_off_delay): """ @summary: This test case is to perform reboot via powercycle and check platform status @param duthost: Fixture for DUT AnsibleHost object @param localhost: Fixture for interacting with localhost through ansible @param conn_graph_facts: Fixture parse and return lab connection graph @param xcvr_skip_list: list of DUT's interfaces for which transeiver checks are skipped - @param psu_controller: The python object of psu controller + @param pdu_controller: The python object of psu controller @param power_off_delay: Pytest parameter. The delay between turning off and on the PSU """ duthost = duthosts[rand_one_dut_hostname] - psu_ctrl = psu_controller - if psu_ctrl is None: + pdu_ctrl = pdu_controller + if pdu_ctrl is None: pytest.skip("No PSU controller for %s, skip rest of the testing in this case" % duthost.hostname) - all_psu = psu_ctrl.get_psu_status() + all_outlets = pdu_ctrl.get_outlet_status() # Purpose of this list is to control sequence of turning on PSUs in power off testing. # If there are 2 PSUs, then 3 scenarios would be covered: @@ -192,17 +192,17 @@ def test_power_off_reboot(duthosts, rand_one_dut_hostname, localhost, conn_graph # 2. Turn off all PSUs, turn on PSU2, then check. # 3. Turn off all PSUs, turn on one of the PSU, then turn on the other PSU, then check. power_on_seq_list = [] - if all_psu: - power_on_seq_list = [[item] for item in all_psu] - power_on_seq_list.append(all_psu) + if all_outlets: + power_on_seq_list = [[item] for item in all_outlets] + power_on_seq_list.append(all_outlets) logging.info("Got all power on sequences {}".format(power_on_seq_list)) poweroff_reboot_kwargs = {"dut": duthost} for power_on_seq in power_on_seq_list: - poweroff_reboot_kwargs["psu_ctrl"] = psu_ctrl - poweroff_reboot_kwargs["all_psu"] = all_psu + poweroff_reboot_kwargs["pdu_ctrl"] = pdu_ctrl + poweroff_reboot_kwargs["all_outlets"] = all_outlets poweroff_reboot_kwargs["power_on_seq"] = power_on_seq poweroff_reboot_kwargs["delay_time"] = power_off_delay reboot_and_check(localhost, duthost, conn_graph_facts["device_conn"][duthost.hostname], xcvr_skip_list, REBOOT_TYPE_POWEROFF, diff --git a/tests/snmp/test_snmp_phy_entity.py b/tests/snmp/test_snmp_phy_entity.py index 3f32550885d..7a88d62bf28 100644 --- a/tests/snmp/test_snmp_phy_entity.py +++ b/tests/snmp/test_snmp_phy_entity.py @@ -428,36 +428,36 @@ def _get_transceiver_sensor_data(duthost, name): @pytest.mark.disable_loganalyzer -def test_turn_off_psu_and_check_psu_info(duthost, localhost, creds, psu_controller): +def test_turn_off_pdu_and_check_psu_info(duthost, localhost, creds, pdu_controller): """ Turn off one PSU and check all PSU sensor entity being removed because it can no longer get any value :param duthost: DUT host object :param localhost: localhost object :param creds: Credential for snmp - :param psu_controller: PSU controller + :param pdu_controller: PDU controller :return: """ - if not psu_controller: - pytest.skip('psu_controller is None, skipping this test') - psu_status = psu_controller.get_psu_status() - if len(psu_status) < 2: - pytest.skip('At least 2 PSUs required for rest of the testing in this case') + if not pdu_controller: + pytest.skip('pdu_controller is None, skipping this test') + outlet_status = pdu_controller.get_outlet_status() + if len(outlet_status) < 2: + pytest.skip('At least 2 outlets required for rest of the testing in this case') # turn on all PSU - for item in psu_status: - if not item['psu_on']: - psu_controller.turn_on_psu(item["psu_id"]) + for item in outlet_status: + if not item['outlet_on']: + pdu_controller.turn_on_outlet(item["outlet_id"]) time.sleep(5) - psu_status = psu_controller.get_psu_status() - for item in psu_status: - if not item['psu_on']: - pytest.skip('Not all PSU are powered on, skip rest of the testing in this case') + outlet_status = pdu_controller.get_outlet_status() + for item in outlet_status: + if not item['outlet_on']: + pytest.skip('Not all outlet are powered on, skip rest of the testing in this case') # turn off the first PSU - first_psu_id = psu_status[0]['psu_id'] - psu_controller.turn_off_psu(first_psu_id) - assert wait_until(30, 5, check_psu_status, psu_controller, first_psu_id, False) + first_outlet_id = outlet_status[0]['outlet_id'] + pdu_controller.turn_off_outlet(first_outlet_id) + assert wait_until(30, 5, check_outlet_status, pdu_controller, first_outlet_id, False) # wait for psud update the database assert wait_until(120, 20, _check_psu_status_after_power_off, duthost, localhost, creds) @@ -581,13 +581,13 @@ def is_null_str(value): return not value or value == str(None) or value == 'N/A' -def check_psu_status(psu_controller, psu_id, expect_status): +def check_outlet_status(pdu_controller, outlet_id, expect_status): """ Check if a given PSU is at expect status - :param psu_controller: PSU controller - :param psu_id: PSU id + :param pdu_controller: PDU controller + :param outlet_id: outlet id :param expect_status: Expect bool status, True means on, False means off :return: True if a given PSU is at expect status """ - status = psu_controller.get_psu_status(psu_id) - return 'psu_on' in status[0] and status[0]['psu_on'] == expect_status + status = pdu_controller.get_outlet_status(outlet_id) + return 'outlet_on' in status[0] and status[0]['outlet_on'] == expect_status