From d526e5c3edaa90ca6bdff224e6f63e712447e146 Mon Sep 17 00:00:00 2001 From: Rounak Adhikary Date: Tue, 17 Mar 2026 05:58:58 -0400 Subject: [PATCH 1/2] Fix: Add missing comma --- PyPowerStore/utils/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PyPowerStore/utils/constants.py b/PyPowerStore/utils/constants.py index 245bc3a..73b8f17 100644 --- a/PyPowerStore/utils/constants.py +++ b/PyPowerStore/utils/constants.py @@ -220,7 +220,7 @@ "current_unix_directory_service_l10n," "file_interfaces(name,id,ip_address)," "nfs_servers,smb_servers," - "file_ldaps,file_nises,file_systems(id,name)" + "file_ldaps,file_nises,file_systems(id,name)," "file_events_publishing_mode," "is_replication_destination," "is_production_mode_enabled," From b6e9c8b1e5cdf32bb59c75dcab25da8363e214b8 Mon Sep 17 00:00:00 2001 From: Rounak Adhikary Date: Tue, 17 Mar 2026 07:01:55 -0400 Subject: [PATCH 2/2] Unit tests and lint fixes --- ProgrammersGuideExamples/host_examples.py | 14 ++-- ProgrammersGuideExamples/metrics_examples.py | 1 + PyPowerStore/metrics.py | 47 +++++++---- PyPowerStore/tests/unit_tests/base_test.py | 13 +++ .../tests/unit_tests/entity/metrics.py | 84 +++++++++++++++++++ PyPowerStore/tests/unit_tests/myrequests.py | 2 + .../tests/unit_tests/test_auth_manager.py | 2 + PyPowerStore/tests/unit_tests/test_metrics.py | 6 +- PyPowerStore/utils/__init__.py | 5 ++ PyPowerStore/utils/constants.py | 6 +- setup.py | 7 +- 11 files changed, 152 insertions(+), 35 deletions(-) create mode 100644 PyPowerStore/tests/unit_tests/entity/metrics.py diff --git a/ProgrammersGuideExamples/host_examples.py b/ProgrammersGuideExamples/host_examples.py index 891d950..948e16a 100644 --- a/ProgrammersGuideExamples/host_examples.py +++ b/ProgrammersGuideExamples/host_examples.py @@ -6,9 +6,9 @@ from PyPowerStore import powerstore_conn -REMOVE_INITIATORS = ["iqn.1998-01.com.vmware:lgloc187-4cfa37b6"] +remove_initiators = ["iqn.1998-01.com.vmware:lgloc187-4cfa37b6"] -INITIATORS = [ +initiators = [ { "port_name": "iqn.1998-01.com.vmware:lgloc187-4cfa37b6", "port_type": "iSCSI", @@ -20,7 +20,7 @@ ] -MODIFY_INITIATORS = [ +modify_initiators = [ { "port_name": "iqn.1998-01.com.vmware:lgloc187-4cfa37b6", "chap_single_username": "prashantrakheja", @@ -30,8 +30,6 @@ }, ] -REMOVE_INITIATORS = ["iqn.1998-01.com.vmware:lgloc187-4cfa37b6"] - CONN = powerstore_conn.PowerStoreConn( username="", password="", @@ -47,7 +45,7 @@ # Register a new Host RESP = CONN.provisioning.create_host( - name="pr-sdk-host", os_type="Linux", initiators=INITIATORS, + name="pr-sdk-host", os_type="Linux", initiators=initiators, ) print(RESP) @@ -67,13 +65,13 @@ # Remove Initiators from Host HOST_REMOVE_INITIATOR = CONN.provisioning.remove_initiators_from_host( - host_id=RESP["id"], remove_initiators=REMOVE_INITIATORS, + host_id=RESP["id"], remove_initiators=remove_initiators, ) print(HOST_REMOVE_INITIATOR) # Add initiators to Host HOST_ADD_INITIATOR = CONN.provisioning.add_initiators_to_host( - host_id=RESP["id"], add_initiators=INITIATORS, + host_id=RESP["id"], add_initiators=initiators, ) print(HOST_ADD_INITIATOR) diff --git a/ProgrammersGuideExamples/metrics_examples.py b/ProgrammersGuideExamples/metrics_examples.py index 20b5535..a5f0ce4 100644 --- a/ProgrammersGuideExamples/metrics_examples.py +++ b/ProgrammersGuideExamples/metrics_examples.py @@ -4,6 +4,7 @@ # pylint: disable=invalid-name,assignment-from-none,duplicate-code +from pprint import pprint from PyPowerStore import powerstore_conn CONN = powerstore_conn.PowerStoreConn( diff --git a/PyPowerStore/metrics.py b/PyPowerStore/metrics.py index 6cc4f8c..ec4276a 100644 --- a/PyPowerStore/metrics.py +++ b/PyPowerStore/metrics.py @@ -1,5 +1,4 @@ - -from collections import namedtuple +"""PowerStore metrics module for performance monitoring.""" from PyPowerStore.utils import constants, helpers @@ -7,9 +6,13 @@ class MetricsFunctions: - """Metric related functionality for PowerStore.""" + """Metric related functionality for PowerStore. + + This class provides methods to retrieve performance metrics + from PowerStore appliances. + """ def __init__(self, provisioning, enable_log=False): - """Initializes ProtectionFunctions Class + """Initializes MetricsFunctions Class :param provisioning: Provisioning class object :type provisioning: Provisioning @@ -19,20 +22,24 @@ def __init__(self, provisioning, enable_log=False): self.provisioning = provisioning self.server_ip = provisioning.server_ip self.rest_client = provisioning.client - global LOG # Reset LOG based on param - LOG = helpers.get_logger(__name__, enable_log=enable_log) + self._enable_log = enable_log + self._log = helpers.get_logger(__name__, enable_log=enable_log) def get_performance_metrics(self, entity, entity_id, interval): """Get performance metrics for the given entity. - entity: The entity to get metrics for see documentation for Entity + :param entity: The entity to get metrics for see documentation for Entity class https://developer.dell.com/apis/3898/versions/{ version}/reference/openapi.json/paths/~1metrics~1generate/post - entity_id: The ID of the entity - str - entity_id: The ID of the entity - str - interval: The interval to get metrics for, Best_Available - Five_Sec, Twenty_Sec, Five_Mins, One_Hour, One_Day - str + :type entity: str + :param entity_id: The ID of the entity + :type entity_id: str + :param interval: The interval to get metrics for, Best_Available + Five_Sec, Twenty_Sec, Five_Mins, One_Hour, One_Day + :type interval: str + :return: Performance metrics data + :rtype: dict """ payload = { "entity": entity, @@ -40,8 +47,16 @@ class https://developer.dell.com/apis/3898/versions/{ "interval": interval } return self.rest_client.request( - constants.POST, - constants.GET_PERFORMANCE_METRICS_URL.format( - self.server_ip), - payload=payload - ) + constants.POST, + constants.GET_PERFORMANCE_METRICS_URL.format( + self.server_ip), + payload=payload + ) + + def is_logging_enabled(self): + """Check if logging is enabled for this instance. + + :return: True if logging is enabled, False otherwise + :rtype: bool + """ + return self._enable_log diff --git a/PyPowerStore/tests/unit_tests/base_test.py b/PyPowerStore/tests/unit_tests/base_test.py index 5942d4c..ddadccb 100644 --- a/PyPowerStore/tests/unit_tests/base_test.py +++ b/PyPowerStore/tests/unit_tests/base_test.py @@ -4,6 +4,8 @@ from unittest import mock +# testtools is a test framework dependency, will be available in test environment +# pylint: disable=import-error from testtools import TestCase from PyPowerStore.powerstore_conn import PowerStoreConn @@ -54,6 +56,8 @@ class TestBase(TestCase): This class provides a common setup for all test cases, including the creation of a PowerStore connection and the initialization of various data objects. """ + # setUp is the standard unittest method name, pylint disable for naming convention + # pylint: disable=invalid-name def setUp(self): """ Setup method to initialize objects and connections for testing. @@ -116,3 +120,12 @@ def setUp(self): self.smb_server = self.conn.smb_server self.nfs_server = self.conn.nfs_server self.snmp_server = self.conn.snmp_server + self.metrics = self.conn.metrics + + def get_test_config(self): + """Get the test configuration. + + :return: Test configuration object + :rtype: PowerStoreConfig + """ + return self.conf diff --git a/PyPowerStore/tests/unit_tests/entity/metrics.py b/PyPowerStore/tests/unit_tests/entity/metrics.py new file mode 100644 index 0000000..55602bf --- /dev/null +++ b/PyPowerStore/tests/unit_tests/entity/metrics.py @@ -0,0 +1,84 @@ +"""Mock metrics Api for Metrics Unit Tests""" + +from PyPowerStore.tests.unit_tests.entity.base_abstract import Entity + + +class MetricsResponse(Entity): + """ + This class is used to handle metrics related responses. + + It provides methods to get performance metrics. + """ + + def __init__(self, method, url, **kwargs): + """ + Initializes the MetricsResponse object. + + Args: + method (str): The HTTP method. + url (str): The URL of the request. + **kwargs: Additional keyword arguments. + """ + self.method = method + self.url = url + self.kwargs = kwargs + self.status_code = 200 + + def get_post_api_name(self): + """ + Returns the API function name based on the POST request URL. + + Returns: + function: The API function. + """ + if self.url.endswith("/generate"): + return self.get_performance_metrics + return None + + def get_performance_metrics(self): + """ + Mock performance metrics response. + + Returns: + dict: Mock performance metrics data. + """ + return { + "metrics": [ + { + "timestamp": "2023-01-01T00:00:00Z", + "entity_id": "A1", + "entity_type": "appliance", + "values": { + "cpu_usage": 50.0, + "memory_usage": 60.0, + "disk_usage": 40.0 + } + } + ] + } + + def get_api_name(self): + """ + Returns the API function name based on the HTTP method and URL. + + Returns: + function: The API function. + """ + if self.method == "POST": + return self.get_post_api_name() + return None + + def execute_api(self, api_name): + """ + Executes the API function and returns the result. + + Args: + api_name (function): The API function to execute. + + Returns: + tuple: A tuple containing the status code and the response. + """ + if api_name: + response = api_name() + return self.status_code, response + return 400, None diff --git a/PyPowerStore/tests/unit_tests/myrequests.py b/PyPowerStore/tests/unit_tests/myrequests.py index 8352a8c..278731b 100644 --- a/PyPowerStore/tests/unit_tests/myrequests.py +++ b/PyPowerStore/tests/unit_tests/myrequests.py @@ -63,6 +63,7 @@ from PyPowerStore.tests.unit_tests.entity.virtual_volume import VirtualVolumeResponse from PyPowerStore.tests.unit_tests.entity.volume import VolumeResponse from PyPowerStore.tests.unit_tests.entity.volume_group import VolumeGroupResponse +from PyPowerStore.tests.unit_tests.entity.metrics import MetricsResponse # map the entity class name with the url resource name ENTITY_CLASS_MAPPING = { @@ -97,6 +98,7 @@ "chap_config": ChapConfigResponse, "x509_certificate": CertificateResponse, "security_config": SecurityConfigResponse, + "generate": MetricsResponse, "remote_system": RemoteSystemResponse, "file_ftp": AdsResponse, "file_ldap": LdapResponse, diff --git a/PyPowerStore/tests/unit_tests/test_auth_manager.py b/PyPowerStore/tests/unit_tests/test_auth_manager.py index 6ce1fe5..07aa1fe 100644 --- a/PyPowerStore/tests/unit_tests/test_auth_manager.py +++ b/PyPowerStore/tests/unit_tests/test_auth_manager.py @@ -3,6 +3,8 @@ import time from unittest.mock import MagicMock, patch +# pytest is a test framework dependency, will be available in test environment +# pylint: disable=import-error import pytest import requests diff --git a/PyPowerStore/tests/unit_tests/test_metrics.py b/PyPowerStore/tests/unit_tests/test_metrics.py index a0d134f..d7cca01 100644 --- a/PyPowerStore/tests/unit_tests/test_metrics.py +++ b/PyPowerStore/tests/unit_tests/test_metrics.py @@ -1,10 +1,6 @@ """Unit Tests for Host""" -from unittest import mock - from PyPowerStore.tests.unit_tests.base_test import TestBase -from PyPowerStore.utils import constants -from PyPowerStore.utils.exception import PowerStoreException class TestMetrics(TestBase): @@ -15,4 +11,4 @@ def test_metrics(self): metric_result = self.metrics.get_performance_metrics( entity="performance_metrics_by_appliance", entity_id="A1", interval="Five_Sec") - self.asssertIsNotNone(metric_result) + self.assertIsNotNone(metric_result) diff --git a/PyPowerStore/utils/__init__.py b/PyPowerStore/utils/__init__.py index e69de29..c4b9984 100644 --- a/PyPowerStore/utils/__init__.py +++ b/PyPowerStore/utils/__init__.py @@ -0,0 +1,5 @@ +"""PyPowerStore utility modules. + +This package contains utility modules for PowerStore operations including +constants, helpers, and other supporting functionality. +""" diff --git a/PyPowerStore/utils/constants.py b/PyPowerStore/utils/constants.py index 73b8f17..935fd5f 100644 --- a/PyPowerStore/utils/constants.py +++ b/PyPowerStore/utils/constants.py @@ -697,9 +697,6 @@ # Login session endpoint LOGIN_SESSION = "https://{0}/api/rest/login_session" -# Local_user endpoints -GET_LOCAL_USER_LIST_URL = "https://{0}/api/rest/local_user" - # IP Pool Address endpoint GET_IP_POOL_LIST_URL = "https://{0}/api/rest/ip_pool_address" @@ -847,5 +844,4 @@ CREATE_STORAGE_CONTAINER_DESTINATION_URL = GET_STORAGE_CONTAINER_DESTINATION_LIST_URL DELETE_STORAGE_CONTAINER_DESTINATION_URL = GET_STORAGE_CONTAINER_DESTINATION_DETAILS_URL -GET_PERFORMANCE_METRICS_URL = ( - "https://{""0}/api/rest/metrics/generate") +GET_PERFORMANCE_METRICS_URL = "https://{0}/api/rest/metrics/generate" diff --git a/setup.py b/setup.py index b045e7a..f2c4763 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,12 @@ description="Python Library for Dell PowerStore", author="Ansible Team at Dell", author_email="ansible.team@dell.com", - install_requires=["urllib3>=1.26.7", "requests>=2.23.0", "packaging>=26.0", "setuptools>=80.10.2"], + install_requires=[ + "urllib3>=1.26.7", + "requests>=2.23.0", + "packaging>=26.0", + "setuptools>=80.10.2" + ], license_files=("LICENSE",), classifiers=["License :: OSI Approved :: Apache Software License"], url="https://github.com/dell/python-powerstore",