From 42fd56895631aa00a60baa82ae9b8856b389ed5b Mon Sep 17 00:00:00 2001 From: Pavan-Mudunuri Date: Fri, 24 Mar 2023 16:10:27 +0530 Subject: [PATCH] Release 1.10.0 for PyPowerStore Python Library --- ChangeLog.md | 11 +- ProgrammersGuideExamples/info_examples.py | 5 + ProgrammersGuideExamples/vcenter_examples.py | 19 +++ PyPowerStore/__init__.py | 2 +- PyPowerStore/configuration.py | 114 +++++++++++++++--- PyPowerStore/provisioning.py | 72 +++++++++-- PyPowerStore/tests/unit_tests/base_test.py | 6 + .../tests/unit_tests/data/common_data.py | 23 +--- .../tests/unit_tests/data/file_system_data.py | 65 ++++++++++ .../tests/unit_tests/data/vcenter_data.py | 35 ++++++ .../unit_tests/data/virtual_volume_data.py | 35 ++++++ .../tests/unit_tests/entity/file_system.py | 4 +- .../tests/unit_tests/entity/vcenter.py | 20 ++- .../tests/unit_tests/entity/virtual_volume.py | 24 ++++ PyPowerStore/tests/unit_tests/myrequests.py | 2 + .../tests/unit_tests/test_file_system.py | 59 +++++---- PyPowerStore/tests/unit_tests/test_vcenter.py | 23 +++- .../tests/unit_tests/test_virtual_volume.py | 8 ++ PyPowerStore/tests/unit_tests/test_volume.py | 14 +++ PyPowerStore/utils/constants.py | 90 ++++++++++++-- PyPowerStore/utils/helpers.py | 16 ++- README.md | 2 +- docs/conf.py | 2 +- setup.py | 2 +- 24 files changed, 543 insertions(+), 110 deletions(-) create mode 100644 PyPowerStore/tests/unit_tests/data/file_system_data.py create mode 100644 PyPowerStore/tests/unit_tests/data/vcenter_data.py create mode 100644 PyPowerStore/tests/unit_tests/data/virtual_volume_data.py create mode 100644 PyPowerStore/tests/unit_tests/entity/virtual_volume.py create mode 100644 PyPowerStore/tests/unit_tests/test_virtual_volume.py diff --git a/ChangeLog.md b/ChangeLog.md index 7e6f00a..125ff1a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,6 +1,13 @@ # PyPowerStore Change Log -## Version 1.9.0 - released on 20/12/22 +## Version 1.10.0 - released on 31/03/23 +- Added configuration operations for vCenter. +- Added support for app_type and app_type_other to volume. +- Added support for config_type, is_async_MTime_enabled, + file_events_publishing_mode, flr_attributes and host_io_size + while creating and modifying a filesystem. + +## Version 1.9.0 - released on 21/12/22 - Added support for clone, restore, and refresh a volume. - Added support for metro sync to volume, host, host group and replication session. @@ -29,4 +36,4 @@ - Added file provisioning operations includes managing filesystem, filesystem snapshot, SMB shares, NFS exports, quotas and getting high level facts about all these entities. ## Version 1.1.0 - released on 06/05/20 -- Added block provisioning operations includes managing volume, volume group, host, host group, snapshot rule, protection policy, snapshots and getting high level facts about all these entities. \ No newline at end of file +- Added block provisioning operations includes managing volume, volume group, host, host group, snapshot rule, protection policy, snapshots and getting high level facts about all these entities. diff --git a/ProgrammersGuideExamples/info_examples.py b/ProgrammersGuideExamples/info_examples.py index 0c59aa0..70be5e9 100644 --- a/ProgrammersGuideExamples/info_examples.py +++ b/ProgrammersGuideExamples/info_examples.py @@ -136,3 +136,8 @@ # Get certificate list RESP = CONN.config_mgmt.get_certificates() print(RESP) + +# Get virtual volume list +RESP = CONN.config_mgmt.get_virtual_volume_list() +print(RESP) + diff --git a/ProgrammersGuideExamples/vcenter_examples.py b/ProgrammersGuideExamples/vcenter_examples.py index 0176ddd..f224f83 100644 --- a/ProgrammersGuideExamples/vcenter_examples.py +++ b/ProgrammersGuideExamples/vcenter_examples.py @@ -30,3 +30,22 @@ vcenter_details = CONN.config_mgmt.modify_vcenter(vcenter_id=vcenters_list[0]['id'], modify_param_dict=param_dict) print(vcenter_details) + +# Add vCenter +add_dict = { + 'address': 'vcenter IP/hostname', + 'username': 'vcenter username', + 'password': 'vcenter password', + 'vasa_provider_credentials': { + 'username': "<>", + 'password': "<>" + } +} + +vcenter_id = CONN.config_mgmt.add_vcenter(add_params=add_dict) +print(vcenter_id) + +# Remove a vCenter +remove_vasa = True +print(CONN.config_mgmt.remove_vcenter(vcenter_id=vcenters_list[0]['id'], + delete_vasa_provider=remove_vasa)) diff --git a/PyPowerStore/__init__.py b/PyPowerStore/__init__.py index 1f0c48c..24ff12f 100644 --- a/PyPowerStore/__init__.py +++ b/PyPowerStore/__init__.py @@ -2,6 +2,6 @@ """__init__.py.""" __title__ = 'PyPowerStore' -__version__ = '1.9.0.0' +__version__ = '1.10.0.0' __author__ = 'Dell Technologies or its subsidiaries' __copyright__ = 'Copyright 2019 Dell Technologies' diff --git a/PyPowerStore/configuration.py b/PyPowerStore/configuration.py index d429414..1ad9326 100644 --- a/PyPowerStore/configuration.py +++ b/PyPowerStore/configuration.py @@ -901,7 +901,6 @@ def get_ip_port_details(self, ip_port_id): # IP ports operations end # vCenter operations start - def get_vcenters(self, filter_dict=None, all_pages=False): """Get all vcenters. :param filter_dict: (optional) Filter details @@ -916,11 +915,18 @@ def get_vcenters(self, filter_dict=None, all_pages=False): querystring = helpers.prepare_querystring( constants.SELECT_ID, filter_dict) LOG.info("Querystring: '%s'" % querystring) - return self.config_client.request( - constants.GET, - constants.GET_VCENTER_LIST_URL.format(self.server_ip), - querystring=querystring, all_pages=all_pages - ) + vcenter_list = self.config_client.\ + request(constants.GET, + constants.GET_VCENTER_LIST_URL.format(self.server_ip), + querystring=querystring, all_pages=all_pages) + + if vcenter_list: + resp_list = [] + for vcenter in vcenter_list: + resp_dict = self.get_vcenter_details(vcenter['id']) + resp_list.append(resp_dict) + return resp_list + return vcenter_list def get_vcenter_details(self, vcenter_id): """Get vcenter details. @@ -931,12 +937,11 @@ def get_vcenter_details(self, vcenter_id): """ LOG.info("Getting vcenter details by ID: '%s'" % vcenter_id) querystring = constants.VCENTER_DETAILS_QUERY - if helpers.is_foot_hill_or_higher(): - querystring = { - 'select': 'id,instance_uuid,address,username,' - 'vendor_provider_status,' - 'vendor_provider_status_l10n' - } + if helpers.is_foot_hill_prime_or_higher(): + querystring = constants.FHP_VCENTER_QUERY + elif helpers.is_foot_hill_or_higher(): + querystring = constants.FHC_MALKA_VCENTER_QUERY + return self.config_client.request( constants.GET, constants.GET_VCENTER_DETAILS_URL.format(self.server_ip, @@ -945,20 +950,66 @@ def get_vcenter_details(self, vcenter_id): ) def modify_vcenter(self, vcenter_id, modify_param_dict): - """Register VASA provider. + """Modify vcenter attributes. :param vcenter_id: ID of the vcenter :type vcenter_id: str - :param modify_param_dict: Dict containing VASA provider credentials + :param modify_param_dict: Dict containing parameters for modification :type modify_param_dict: dict :return: Details of vcenter :rtype: dict """ - LOG.info("Registering VASA provider: '%s'" % vcenter_id) + LOG.info("Modifying vCenter attributes: '%s'" % vcenter_id) self.config_client.request(constants.PATCH, constants.MODIFY_VCENTER_URL.format( self.server_ip, vcenter_id), payload=modify_param_dict) return self.get_vcenter_details(vcenter_id) + + def add_vcenter(self, add_params): + """ + Add a vcenter to the unified PowerStore model. + vcenter can not be added to unified+ deployment + :param add_params: the parameters to add vcenter + :type add_params:dict + :return: ID of the vcenter if addition is successful + :rtype: dict + """ + LOG.info("Adding a vcenter.") + + payload = dict() + if add_params: + for key, values in add_params.items(): + payload[key] = values + + return self.config_client.\ + request(constants.POST, + constants.ADD_VCENTER_URL.format(self.server_ip), + payload=payload) + + def remove_vcenter(self, vcenter_id, delete_vasa_provider=None): + """ + Remove vcenter from Unified PowerStore model. + vcenter can not be removed from unified+ deployment + :param vcenter_id: ID of the vcenter + :type vcenter_id: str + :param delete_vasa_provider: whether to remove a VASA provider. + Removal will only happen if the provider + is not connected to any other PowerStore + system + :type delete_vasa_provider: bool + :return: None if success + :rtype: None + """ + LOG.info("Removing vcenter: {0}.".format(vcenter_id)) + payload = dict() + if delete_vasa_provider is not None: + payload['delete_vendor_provider'] = delete_vasa_provider + + return self.config_client.\ + request(constants.DELETE, + constants.REMOVE_VCENTER_URL.format(self.server_ip, + vcenter_id), + payload=payload) # vCenter operations end # Appliance operations start @@ -2044,7 +2095,38 @@ def delete_ldap_account(self, ldap_account_id): self.server_ip, ldap_account_id)) - # LDAP Account operations end + # LDAP Account operations end + + # Virtual volume operations begin + + def get_virtual_volume_list(self, filter_dict=None, all_pages=None): + """Get all virtual volumes available on array. + :param filter_dict: (optional) Filter details + :type filter_dict: dict + :param all_pages: (optional) Indicates whether to return all + virtual volumes or not + :type all_pages: bool + :return: List of virtual volumes on array + :rtype: list[dict] + """ + LOG.info("Getting volumes with filter: '%s' and all_pages: %s" + % (filter_dict, all_pages)) + querystring = helpers.prepare_querystring( + constants.VIRTUAL_VOLUME_DETAILS_QUERY, + filter_dict) + if helpers.is_foot_hill_prime_or_higher(): + querystring = helpers.prepare_querystring( + constants.VIRTUAL_VOLUME_FHP_DETAILS_QUERY, + filter_dict) + LOG.info("Querystring: '%s'" % querystring) + return self.config_client.request(constants.GET, + constants.GET_VIRTUAL_VOLUME_LIST_URL.format + (self.server_ip), payload=None, + querystring=querystring, + all_pages=all_pages) + + # Virtual volume operations end + @staticmethod def _prepare_local_user_payload(**kwargs): diff --git a/PyPowerStore/provisioning.py b/PyPowerStore/provisioning.py index 57d6cf4..d554ab3 100644 --- a/PyPowerStore/provisioning.py +++ b/PyPowerStore/provisioning.py @@ -64,7 +64,8 @@ def get_array_version(self): def create_volume(self, name, size, description=None, volume_group_id=None, protection_policy_id=None, - performance_policy_id=None): + performance_policy_id=None, app_type=None, + app_type_other=None): """Create a volume. :param name: The name of the volume @@ -73,13 +74,22 @@ def create_volume(self, name, size, description=None, :param volume_group_id: (optional) The volume group ID :param protection_policy_id: (optional) The protection policy ID :param performance_policy_id: (optional) The performance policy ID + :param app_type: (optional) The application type + :param app_type_other: (optional) Describes application type when + app_type is set to other """ + if app_type is not None and not helpers.is_malka_or_higher(): + raise Exception("'app_type' parameter is supported only from " + "Powerstore version 2.1.0.0 onwards") + LOG.info("Creating volume: '%s'" % name) payload = self._prepare_create_volume_payload(name, size, description, volume_group_id, protection_policy_id, - performance_policy_id) + performance_policy_id, + app_type, + app_type_other) self.client.request(constants.POST, constants.VOLUME_CREATE_URL.format( self.server_ip), payload) @@ -88,7 +98,9 @@ def _prepare_create_volume_payload(self, name, size, description, volume_group_id, protection_policy_id, - performance_policy_id): + performance_policy_id, + app_type, + app_type_other): create_volume_dict = dict() if name is not None: @@ -104,6 +116,10 @@ def _prepare_create_volume_payload(self, name, size, if performance_policy_id is not None: create_volume_dict['performance_policy_id'] = \ performance_policy_id + if app_type is not None: + create_volume_dict['app_type'] = app_type + if app_type_other is not None: + create_volume_dict['app_type_other'] = app_type_other return create_volume_dict @@ -122,8 +138,8 @@ def delete_volume(self, volume_id): payload=None) def modify_volume(self, volume_id, name=None, description=None, size=None, - protection_policy_id=None, - performance_policy_id=None): + protection_policy_id=None, performance_policy_id=None, + app_type=None, app_type_other=None): """Modify a volume. :param volume_id: The volume ID @@ -138,16 +154,26 @@ def modify_volume(self, volume_id, name=None, description=None, size=None, :type protection_policy_id: str :param performance_policy_id: The performance policy ID :type performance_policy_id: str + :param app_type: The application type + :type app_type: str + :param app_type_other: Describes application type when + app_type is set to other :return: None if success else raise exception :rtype: None """ + if app_type is not None and not helpers.is_malka_or_higher(): + raise Exception("'app_type' parameter is supported only from " + "Powerstore version 2.1.0.0 onwards") + LOG.info("Modifying volume: '%s'" % volume_id) payload = self.\ _prepare_modify_volume_payload(name, description, size, protection_policy_id, - performance_policy_id) + performance_policy_id, + app_type, + app_type_other) return self.client.request( constants.PATCH, constants.MODIFY_VOLUME_URL.format( self.server_ip, volume_id), @@ -156,7 +182,9 @@ def modify_volume(self, volume_id, name=None, description=None, size=None, def _prepare_modify_volume_payload(self, name=None, description=None, size=None, protection_policy_id=None, - performance_policy_id=None): + performance_policy_id=None, + app_type=None, + app_type_other=None): modify_volume_dict = dict() if name is not None: @@ -170,6 +198,10 @@ def _prepare_modify_volume_payload(self, name=None, description=None, if performance_policy_id is not None: modify_volume_dict['performance_policy_id'] = \ performance_policy_id + if app_type is not None: + modify_volume_dict['app_type'] = app_type + if app_type_other is not None: + modify_volume_dict['app_type_other'] = app_type_other return modify_volume_dict @@ -238,7 +270,7 @@ def _prepare_clone_volume_payload(self, name=None, description=None, host_id=Non performance_policy_id return clone_volume_dict - + def refresh_volume(self, volume_id, volume_id_to_refresh_from=None, create_backup_snap=None, backup_snap_name=None, @@ -303,7 +335,7 @@ def _prepare_refresh_volume_payload(self, volume_id_to_refresh_from=None, backup_snap_performance_policy_id return refresh_volume_dict - + def restore_volume(self, volume_id, snap_id_to_restore_from=None, create_backup_snap=None, backup_snap_name=None, @@ -1163,7 +1195,7 @@ def clone_volume_group(self, volume_group_id, name, description=None, protection :type name: str :param description: (optional) Description for the clone volume group. :type description: str - :param protection_policy_id: (optional) Unique identifier of the protection + :param protection_policy_id: (optional) Unique identifier of the protection policy to assign to the clone volume group :type protection_policy_id: str :return: Unique identifier of the new instance created if success else raise exception @@ -1493,7 +1525,7 @@ def get_host_volume_mapping(self, volume_id): ) # NAS Server methods - + def get_nas_servers(self, filter_dict=None, all_pages=False): """Get a list of nas servers. @@ -1620,12 +1652,15 @@ def get_filesystem_details(self, filesystem_id): :rtype: dict """ LOG.info("Getting filesystem details by ID: '%s'" % filesystem_id) + querystring=constants.SELECT_ALL_FILESYSTEM + if helpers.is_foot_hill_prime_or_higher(): + querystring=constants.SELECT_ALL_FILESYSTEM_PRIME return self.client.request( constants.GET, constants.GET_FILESYSTEM_DETAILS_URL.format(self.server_ip, filesystem_id), payload=None, - querystring=constants.SELECT_ALL_FILESYSTEM) + querystring=querystring) def get_filesystem_by_name(self, filesystem_name, nas_server_id): """Get details of a filesystem by name. @@ -1637,12 +1672,15 @@ def get_filesystem_by_name(self, filesystem_name, nas_server_id): """ LOG.info("Getting filesystem details by name: '%s' and NAS Server: " "'%s'" % (filesystem_name, nas_server_id)) + querystring=constants.SELECT_ALL_FILESYSTEM + if helpers.is_foot_hill_prime_or_higher(): + querystring=constants.SELECT_ALL_FILESYSTEM_PRIME return self.client.request( constants.GET, constants.GET_FILESYSTEM_DETAILS_BY_NAME_URL.format( self.server_ip), payload=None, querystring=helpers.prepare_querystring( - constants.SELECT_ALL_FILESYSTEM, + querystring, nas_server_id=constants.EQUALS + nas_server_id, name=constants.EQUALS + filesystem_name ) @@ -1671,6 +1709,10 @@ def create_filesystem(self, name, nas_server_id, size_total, if advance_parameters: for key, value in advance_parameters.items(): + if key in constants.FILESYSTEM_PRIME and \ + not helpers.is_foot_hill_prime_or_higher(): + raise Exception( key + " is supported for PowerStore" \ + " version 3.0.0.0 and above.") payload[key] = value return self.client.request(constants.POST, constants.CREATE_FILESYSTEM_URL.format( @@ -1722,6 +1764,10 @@ def modify_filesystem(self, filesystem_id, modify_parameters): if modify_parameters: payload = dict() for key, value in modify_parameters.items(): + if key in constants.FILESYSTEM_PRIME and \ + not helpers.is_foot_hill_prime_or_higher(): + raise Exception( key + " is supported for PowerStore" \ + " version 3.0.0.0 and above.") if value is not None: payload[key] = value diff --git a/PyPowerStore/tests/unit_tests/base_test.py b/PyPowerStore/tests/unit_tests/base_test.py index b8d392d..ab76427 100644 --- a/PyPowerStore/tests/unit_tests/base_test.py +++ b/PyPowerStore/tests/unit_tests/base_test.py @@ -15,6 +15,9 @@ from PyPowerStore.tests.unit_tests.data.remote_support_data import RemoteSupportData from PyPowerStore.tests.unit_tests.data.remote_support_contact_data import RemoteSupportContactData from PyPowerStore.tests.unit_tests.data.ldap_account_data import LdapAccountData +from PyPowerStore.tests.unit_tests.data.vcenter_data import VcenterData +from PyPowerStore.tests.unit_tests.data.virtual_volume_data import VirtualVolumeData +from PyPowerStore.tests.unit_tests.data.file_system_data import FileSystemData from unittest import mock class TestBase(TestCase): @@ -33,6 +36,9 @@ def setUp(self): self.remote_support_data = RemoteSupportData() self.remote_support_contact_data = RemoteSupportContactData() self.ldap_account_data = LdapAccountData() + self.vcenter_data = VcenterData() + self.virtual_volume_data = VirtualVolumeData() + self.file_system_data = FileSystemData() self.conf = PowerStoreConfig() self.mock_client = mock.patch('PyPowerStore.provisioning.Client', new=MockClient) diff --git a/PyPowerStore/tests/unit_tests/data/common_data.py b/PyPowerStore/tests/unit_tests/data/common_data.py index 5dafeca..b701eb9 100644 --- a/PyPowerStore/tests/unit_tests/data/common_data.py +++ b/PyPowerStore/tests/unit_tests/data/common_data.py @@ -11,6 +11,10 @@ class CommonData(object): vol_id2 = "00c2c300-cf6e-4cf0-9bf4-037173496913" vol_name2 = "my_vol2" + app_type1 = "Big_Data_Analytics_Spark" + app_type2 = "Healthcare_Other" + app_type_other = "Research Data" + volume_list = [{"id": vol_id1, "name": vol_name1}, {"id": vol_id2, "name": vol_name2}] @@ -800,25 +804,6 @@ class CommonData(object): } # job end - # vcenter start - - vcenter_id1 = '42d08c86-f958-4fbb-82f0-3ce1a5d99d1e' - vcenter_list = [{"id": '42d08c86-f958-4fbb-82f0-3ce1a5d99d1e'}] - vasa_provider_credentials = { - "username": "sample_vasa_user", - "password": "sample_vasa_password" - } - vcenter_details = { - "id": "42d08c86-f958-4fbb-82f0-3ce1a5d99d1e", - "instance_uuid": "3b33039f-908f-4d1a-a0ca-1d2fd050a09b", - "address": "vpi2197.pie.lab.emc.com", - "username": "administrator@vsphere.local", - "vendor_provider_status": "Online", - "vendor_provider_status_l10n": "Online" - } - - # vcenter end - # IP pool address start ip_pool_list = [ diff --git a/PyPowerStore/tests/unit_tests/data/file_system_data.py b/PyPowerStore/tests/unit_tests/data/file_system_data.py new file mode 100644 index 0000000..c1931a2 --- /dev/null +++ b/PyPowerStore/tests/unit_tests/data/file_system_data.py @@ -0,0 +1,65 @@ +class FileSystemData(object): + # FileSystem + fs_id1 = "5efc3ec5-ea0d-58d9-e21b-42079d64ae37" + fs_name1 = "my_fs1" + + fs_id2 = "5f293c02-4466-8e0b-14df-024f80ecffb0" + fs_name2 = "my_fs2" + + fs_list = [{"id": fs_id1, "name": fs_name1}, + {"id": fs_id2, "name": fs_name2}] + nas_id1 = "5ef3ade5-b532-27a5-1f2d-3286ff9e3ccf" + nas_name1 = "my_nas1" + size_used = 1623195648 + size_total = 5368709120 + size = 1048576 + create_filesystem = {'id': fs_id1} + fs_detail = {'access_policy': 'Native', 'access_policy_l10n': 'Native', + 'access_type': None, 'access_type_l10n': None, + 'creation_timestamp': None, 'creator_type': None, + 'creator_type_l10n': None, 'default_hard_limit': 0, + 'default_soft_limit': 0, 'description': None, + 'expiration_timestamp': None, 'filesystem_type': 'Primary', + 'filesystem_type_l10n': 'Primary File system', + 'folder_rename_policy': 'All_Forbidden', + 'folder_rename_policy_l10n': 'All Renames Forbidden', + 'grace_period': 604800, 'id': fs_id1, + 'is_async_MTime_enabled': False, 'is_modified': None, + 'is_quota_enabled': False, 'is_smb_no_notify_enabled': False, + 'is_smb_notify_on_access_enabled': False, + 'is_smb_notify_on_write_enabled': False, + 'is_smb_op_locks_enabled': True, + 'is_smb_sync_writes_enabled': False, + 'last_refresh_timestamp': None, 'parent_id': None, + 'last_writable_timestamp': None, + 'locking_policy': 'Advisory', 'name': fs_name1, + 'locking_policy_l10n': 'Advisory', + 'nas_server': {'id': nas_id1, 'name': nas_name1}, + 'protection_policy': None, 'size_total': size_total, + 'size_used': size_used, 'smb_notify_on_change_dir_depth': 512} + + fs_snap_id = "5efc3ec5-ea0d-58d9-e21b-42079d64ae37" + fs_snap_name = "my_fs_snap" + create_filesystem_snap = {'id': fs_snap_id} + fs_snap_detail = fs_detail + fs_snap_list = [{'id': fs_snap_id, 'name': fs_snap_name}] + + # fs which does not exists + invalid_fs_id = fs_id1[:len(fs_id1) - 3] + 'x' * 3 + # fs which has snapshot created on it + fs_id_with_snap = "5f488eb1-c75e-a704-e53a-c6f547282e76" + fs_error = { + 404: {'messages': [{'code': '0xE08010080001', + 'message_l10n': 'Operation failed because File ' + 'System ID is invalid. Enter a valid File System ' + 'ID and try again.', + 'severity': 'Error'}]}, + 422: {'messages': [{'arguments': ['[File system delete rejected due ' + 'to existing snap(s).]'], + 'code': '0xE08010080003', + 'message_l10n': 'Deletion of File System failed ' + 'as, [File system delete rejected ' + 'due to existing snap (s).]', + 'severity': 'Error'}]}} + + # FileSystem End diff --git a/PyPowerStore/tests/unit_tests/data/vcenter_data.py b/PyPowerStore/tests/unit_tests/data/vcenter_data.py new file mode 100644 index 0000000..ddf5864 --- /dev/null +++ b/PyPowerStore/tests/unit_tests/data/vcenter_data.py @@ -0,0 +1,35 @@ +class VcenterData: + vcenter_id = '42d08c86-f958-4fbb-82f0-3ce1a5d99d1e' + vcenter_list = [ + { + "id": "42d08c86-f958-4fbb-82f0-3ce1a5d99d1e", + "instance_uuid": "3b33039f-908f-4d1a-a0ca-1d2fd050a09b", + "address": "vpi7.lab.comp.com", + "username": "vcenter_admin", + "vendor_provider_status": "Online", + "vendor_provider_status_l10n": "Online" + } + ] + add_vcenter_params = { + "address": "dummy ip", + "username": "user", + "password": "vcenter_Password", + "vasa_provider_credentials": { + "username": "sample_vasa_user", + "password": "sample_vasa_password" + } + } + vasa_provider_credentials = { + "username": "sample_vasa_user", + "password": "sample_vasa_password" + } + vcenter_details = { + "id": "42d08c86-f958-4fbb-82f0-3ce1a5d99d1e", + "instance_uuid": "3b33039f-908f-4d1a-a0ca-1d2fd050a09b", + "address": "vpi7.lab.comp.com", + "username": "vcenter_admin", + "vendor_provider_status": "Online", + "vendor_provider_status_l10n": "Online" + } + + delete_vasa_provider = True diff --git a/PyPowerStore/tests/unit_tests/data/virtual_volume_data.py b/PyPowerStore/tests/unit_tests/data/virtual_volume_data.py new file mode 100644 index 0000000..02de44d --- /dev/null +++ b/PyPowerStore/tests/unit_tests/data/virtual_volume_data.py @@ -0,0 +1,35 @@ +class VirtualVolumeData: + virtual_volume_id = '42d08c86-f958-4fbb-82f0-3ce1a5d99d1e' + virtual_volume_list = [ + { + "id": "6c0b25ea-3f77-4f1f-93d1-e189df2385b9", + "name": "sample_vvol", + "size": 4294967296, + "type": "Primary", + "usage_type": "Config", + "appliance_id": "A1", + "storage_container_id": "a595ba82-06a7-4a7f-9956-6d54d233945c", + "io_priority": "Medium", + "profile_id": "f4e5bade-15a2-4805-bf8e-52318c4ce443", + "replication_group_id": None, + "creator_type": "User", + "is_readonly": False, + "migration_session_id": None, + "virtual_machine_uuid": "5030c9cf-12c4-654f-7658-da77bd65843f", + "family_id": "86cbc166-1a30-4bad-afa0-20698873f2c0", + "parent_id": None, + "source_id": None, + "source_timestamp": None, + "creation_timestamp": "2023-02-03T09:50:55.15+00:00", + "naa_name": "naa.68ccf098003756010d25481d597257d7", + "is_replication_destination": False, + "location_history": None, + "protection_policy_id": None, + "nsid": 1261, + "nguid": "nguid.3756010d25481d598ccf0968007257d7", + "type_l10n": "Primary", + "usage_type_l10n": "Config", + "io_priority_l10n": "Medium", + "creator_type_l10n": "User" + } + ] diff --git a/PyPowerStore/tests/unit_tests/entity/file_system.py b/PyPowerStore/tests/unit_tests/entity/file_system.py index e402336..fa91a82 100644 --- a/PyPowerStore/tests/unit_tests/entity/file_system.py +++ b/PyPowerStore/tests/unit_tests/entity/file_system.py @@ -1,6 +1,6 @@ from PyPowerStore.utils import constants from PyPowerStore.tests.unit_tests.entity.base_abstract import Entity -from PyPowerStore.tests.unit_tests.data.common_data import CommonData +from PyPowerStore.tests.unit_tests.data.file_system_data import FileSystemData class FileSystemResponse(Entity): @@ -9,7 +9,7 @@ def __init__(self, method, url, **kwargs): self.method = method self.url = url self.kwargs = kwargs - self.data = CommonData() + self.data = FileSystemData() self.status_code = 200 def get_api_name(self): diff --git a/PyPowerStore/tests/unit_tests/entity/vcenter.py b/PyPowerStore/tests/unit_tests/entity/vcenter.py index aa35e3b..ad5e3b9 100644 --- a/PyPowerStore/tests/unit_tests/entity/vcenter.py +++ b/PyPowerStore/tests/unit_tests/entity/vcenter.py @@ -1,5 +1,5 @@ from PyPowerStore.tests.unit_tests.entity.base_abstract import Entity -from PyPowerStore.tests.unit_tests.data.common_data import CommonData +from PyPowerStore.tests.unit_tests.data.vcenter_data import VcenterData class VcenterResponse(Entity): @@ -8,7 +8,7 @@ def __init__(self, method, url, **kwargs): self.method = method self.url = url self.kwargs = kwargs - self.data = CommonData() + self.vcenter_data = VcenterData() self.status_code = 200 def get_api_name(self): @@ -19,16 +19,26 @@ def get_api_name(self): return self.get_vcenter_details elif self.method == 'PATCH': return self.modify_vcenter + elif self.method == 'POST': + return self.add_vcenter + elif self.method == 'DELETE': + return self.remove_vcenter def execute_api(self, api_name): status_code, response = api_name() return status_code, response def get_vcenters(self): - return self.status_code, self.data.vcenter_list + return self.status_code, self.vcenter_data.vcenter_list def get_vcenter_details(self): - return self.status_code, self.data.vcenter_details + return self.status_code, self.vcenter_data.vcenter_details def modify_vcenter(self): - return self.status_code, self.data.vcenter_details \ No newline at end of file + return self.status_code, self.vcenter_data.vcenter_details + + def add_vcenter(self): + return 201, self.vcenter_data.vcenter_id + + def remove_vcenter(self): + return 204, None diff --git a/PyPowerStore/tests/unit_tests/entity/virtual_volume.py b/PyPowerStore/tests/unit_tests/entity/virtual_volume.py new file mode 100644 index 0000000..b5b915d --- /dev/null +++ b/PyPowerStore/tests/unit_tests/entity/virtual_volume.py @@ -0,0 +1,24 @@ +from PyPowerStore.tests.unit_tests.entity.base_abstract import Entity +from PyPowerStore.tests.unit_tests.data.virtual_volume_data import VirtualVolumeData + + +class VirtualVolumeResponse(Entity): + + def __init__(self, method, url, **kwargs): + self.method = method + self.url = url + self.kwargs = kwargs + self.virtual_volume_data = VirtualVolumeData() + self.status_code = 200 + + def get_api_name(self): + if self.method == 'GET': + if self.url.endswith('/virtual_volume'): + return self.get_virtual_volumes + + def execute_api(self, api_name): + status_code, response = api_name() + return status_code, response + + def get_virtual_volumes(self): + return self.status_code, self.virtual_volume_data.virtual_volume_list diff --git a/PyPowerStore/tests/unit_tests/myrequests.py b/PyPowerStore/tests/unit_tests/myrequests.py index 96f87ee..782ddf9 100644 --- a/PyPowerStore/tests/unit_tests/myrequests.py +++ b/PyPowerStore/tests/unit_tests/myrequests.py @@ -17,6 +17,7 @@ from PyPowerStore.tests.unit_tests.entity.software_installed import SoftwareResponse from PyPowerStore.tests.unit_tests.entity.job import JobResponse from PyPowerStore.tests.unit_tests.entity.vcenter import VcenterResponse +from PyPowerStore.tests.unit_tests.entity.virtual_volume import VirtualVolumeResponse from PyPowerStore.tests.unit_tests.entity.ip_pool_address import IPPoolAddressResponse from PyPowerStore.tests.unit_tests.entity.ip_port import IPPortResponse from PyPowerStore.tests.unit_tests.entity.local_user import LocalUserResponse @@ -62,6 +63,7 @@ 'software_installed': SoftwareResponse, 'job': JobResponse, 'vcenter': VcenterResponse, + 'virtual_volume': VirtualVolumeResponse, 'ip_pool_address': IPPoolAddressResponse, 'ip_port': IPPortResponse, 'local_user': LocalUserResponse, diff --git a/PyPowerStore/tests/unit_tests/test_file_system.py b/PyPowerStore/tests/unit_tests/test_file_system.py index 7324c39..0cd1ab3 100644 --- a/PyPowerStore/tests/unit_tests/test_file_system.py +++ b/PyPowerStore/tests/unit_tests/test_file_system.py @@ -1,7 +1,6 @@ from PyPowerStore.utils import constants, helpers from PyPowerStore.tests.unit_tests.base_test import TestBase from PyPowerStore.utils.exception import PowerStoreException - from unittest import mock @@ -9,7 +8,7 @@ class TestFileSystem(TestBase): def test_get_filesystems(self): fs_list = self.provisioning.get_file_systems() - self.assertListEqual(fs_list, self.data.fs_list) + self.assertListEqual(fs_list, self.file_system_data.fs_list) def test_get_filesystem_with_filter(self): querystring = {'get_file_systems': 'lt.10000'} @@ -27,45 +26,45 @@ def test_get_filesystem_with_filter(self): querystring=querystring) def test_create_filesystem(self): - param = {'is_smb_sync_writes_enabled': True} + param = {'is_smb_sync_writes_enabled': True, 'config_type': "General"} fs = self.provisioning.create_filesystem( - self.data.fs_name1, self.data.nas_id1, self.data.size, param) - self.assertEqual(fs, self.data.create_filesystem) + self.file_system_data.fs_name1, self.file_system_data.nas_id1, self.file_system_data.size, param) + self.assertEqual(fs, self.file_system_data.create_filesystem) def test_get_filesystem_details(self): - fs = self.provisioning.get_filesystem_details(self.data.fs_id1) - self.assertEqual(fs, self.data.fs_detail) + fs = self.provisioning.get_filesystem_details(self.file_system_data.fs_id1) + self.assertEqual(fs, self.file_system_data.fs_detail) def test_get_filesystem_by_name(self): fs = self.provisioning.get_filesystem_by_name( - self.data.fs_name1, self.data.nas_id1) - self.assertEqual(fs, self.data.fs_detail) + self.file_system_data.fs_name1, self.file_system_data.nas_id1) + self.assertEqual(fs, self.file_system_data.fs_detail) def test_create_filesystem_snapshot(self): fs_snap = self.protection.create_filesystem_snapshot( - self.data.fs_id1, is_smb_sync_writes_enabled=True) - self.assertEqual(fs_snap, self.data.create_filesystem_snap) + self.file_system_data.fs_id1, is_smb_sync_writes_enabled=True) + self.assertEqual(fs_snap, self.file_system_data.create_filesystem_snap) def test_get_filesystem_snapshot_details(self): fs_snap_detail = self.protection.get_filesystem_snapshot_details( - self.data.fs_snap_id) - self.assertEqual(fs_snap_detail, self.data.fs_snap_detail) + self.file_system_data.fs_snap_id) + self.assertEqual(fs_snap_detail, self.file_system_data.fs_snap_detail) def test_get_filesystem_snapshot_details_by_name_and_nas(self): fs_snap_detail = self.protection.\ get_filesystem_snapshot_details_by_name( - self.data.fs_snap_name, nas_server_id=self.data.nas_id1) - self.assertEqual(fs_snap_detail, self.data.fs_snap_detail) + self.file_system_data.fs_snap_name, nas_server_id=self.file_system_data.nas_id1) + self.assertEqual(fs_snap_detail, self.file_system_data.fs_snap_detail) def test_get_filesystem_snapshot_details_by_name_and_fs(self): querystring = helpers.prepare_querystring( constants.SELECT_ALL_FILESYSTEM, - name=constants.EQUALS + self.data.fs_snap_name, - parent_id=constants.EQUALS + self.data.fs_id1) + name=constants.EQUALS + self.file_system_data.fs_snap_name, + parent_id=constants.EQUALS + self.file_system_data.fs_id1) with mock.patch.object(self.protection.rest_client, 'request') as mock_request: self.protection.get_filesystem_snapshot_details_by_name( - self.data.fs_snap_name, filesystem_id=self.data.fs_id1) + self.file_system_data.fs_snap_name, filesystem_id=self.file_system_data.fs_id1) mock_request.assert_called_with( constants.GET, constants.GET_FILESYSTEM_DETAILS_BY_NAME_URL.format( @@ -76,42 +75,42 @@ def test_get_filesystem_snapshot_details_by_name_only(self): self.assertRaises( ValueError, self.protection.get_filesystem_snapshot_details_by_name, - self.data.fs_snap_name) + self.file_system_data.fs_snap_name) def test_get_filesystem_snapshot_details_by_name_fs_nas(self): self.assertRaises( ValueError, self.protection.get_filesystem_snapshot_details_by_name, - self.data.fs_snap_name, - filesystem_id=self.data.fs_id1, nas_server_id=self.data.nas_id1) + self.file_system_data.fs_snap_name, + filesystem_id=self.file_system_data.fs_id1, nas_server_id=self.file_system_data.nas_id1) def test_get_snapshots_filesystem(self): fs_snap_list = self.provisioning.get_snapshots_filesystem( - self.data.fs_id1) - self.assertEqual(fs_snap_list, self.data.fs_snap_list) + self.file_system_data.fs_id1) + self.assertEqual(fs_snap_list, self.file_system_data.fs_snap_list) def test_modify_filesystem_snapshot(self): resp = self.protection.modify_filesystem_snapshot( - self.data.fs_snap_id, description='My Desc') + self.file_system_data.fs_snap_id, description='My Desc') self.assertIsNone(resp) def test_modify_filesystem_with_empty_params(self): self.assertRaises( ValueError, self.provisioning.modify_filesystem, - self.data.fs_id1, {}) + self.file_system_data.fs_id1, {}) def test_modify_filesystem(self): param = {'folder_rename_policy': 'All_Allowed'} - resp = self.provisioning.modify_filesystem(self.data.fs_id1, param) + resp = self.provisioning.modify_filesystem(self.file_system_data.fs_id1, param) self.assertIsNone(resp) def test_delete_filesystem_snapshot(self): resp = self.protection.delete_filesystem_snapshot( - self.data.fs_snap_id) + self.file_system_data.fs_snap_id) self.assertIsNone(resp) def test_delete_filesystem(self): - resp = self.provisioning.delete_filesystem(self.data.fs_id1) + resp = self.provisioning.delete_filesystem(self.file_system_data.fs_id1) self.assertIsNone(resp) def test_delete_invalid_filesystem(self): @@ -119,11 +118,11 @@ def test_delete_invalid_filesystem(self): PowerStoreException, "HTTP code: 404, Not Found", self.provisioning.delete_filesystem, - self.data.invalid_fs_id) + self.file_system_data.invalid_fs_id) def test_delete_filesystem_with_snap(self): self.assertRaisesRegex( PowerStoreException, "HTTP code: 422, Unprocessable Entity", self.provisioning.delete_filesystem, - self.data.fs_id_with_snap) + self.file_system_data.fs_id_with_snap) diff --git a/PyPowerStore/tests/unit_tests/test_vcenter.py b/PyPowerStore/tests/unit_tests/test_vcenter.py index 8f6c85b..34bbb9b 100644 --- a/PyPowerStore/tests/unit_tests/test_vcenter.py +++ b/PyPowerStore/tests/unit_tests/test_vcenter.py @@ -5,13 +5,26 @@ class TestVcenter(TestBase): def test_modify_vcenter(self): vcenter_details = self.configuration.modify_vcenter( - self.data.vcenter_id1, self.data.vasa_provider_credentials) - self.assertEqual(vcenter_details, self.data.vcenter_details) + self.vcenter_data.vcenter_id, + self.vcenter_data.vasa_provider_credentials) + self.assertEqual(vcenter_details, self.vcenter_data.vcenter_details) def test_get_vcenters(self): vcenter_list = self.configuration.get_vcenters() - self.assertListEqual(vcenter_list, self.data.vcenter_list) + self.assertListEqual(vcenter_list, self.vcenter_data.vcenter_list) def test_get_vcenter_details(self): - vcenter_details = self.configuration.get_vcenter_details(self.data.vcenter_id1) - self.assertEqual(vcenter_details, self.data.vcenter_details) + vcenter_details = self.configuration.get_vcenter_details( + self.vcenter_data.vcenter_id) + self.assertEqual(vcenter_details, self.vcenter_data.vcenter_details) + + def test_add_vcenter(self): + vcenter_id = self.configuration.add_vcenter( + self.vcenter_data.add_vcenter_params) + self.assertEqual(vcenter_id, self.vcenter_data.vcenter_id) + + def test_remove_vcenter(self): + resp = self.configuration.\ + remove_vcenter(self.vcenter_data.vcenter_id, + self.vcenter_data.delete_vasa_provider) + self.assertIsNone(resp) diff --git a/PyPowerStore/tests/unit_tests/test_virtual_volume.py b/PyPowerStore/tests/unit_tests/test_virtual_volume.py new file mode 100644 index 0000000..4866857 --- /dev/null +++ b/PyPowerStore/tests/unit_tests/test_virtual_volume.py @@ -0,0 +1,8 @@ +from PyPowerStore.tests.unit_tests.base_test import TestBase + + +class TestVirtualVolume(TestBase): + + def test_get_virtual_volumes(self): + virtual_volume_list = self.configuration.get_virtual_volume_list() + self.assertListEqual(virtual_volume_list, self.virtual_volume_data.virtual_volume_list) diff --git a/PyPowerStore/tests/unit_tests/test_volume.py b/PyPowerStore/tests/unit_tests/test_volume.py index 38b67b1..30ae4b6 100644 --- a/PyPowerStore/tests/unit_tests/test_volume.py +++ b/PyPowerStore/tests/unit_tests/test_volume.py @@ -19,6 +19,20 @@ def test_create_volume(self): self.data.size) self.assertIsNone(vol) + def test_create_vol_with_app_type(self): + vol = self.provisioning.create_volume(self.data.vol_name1, + self.data.size, + app_type=self.data.app_type1) + self.assertIsNone(vol) + + def test_create_vol_with_app_type_and_with_app_type_other(self): + vol = self.provisioning.create_volume(self.data.vol_name1, + self.data.size, + app_type=self.data.app_type2, + app_type_other=self.data. + app_type_other) + self.assertIsNone(vol) + def test_modify_volume(self): vol = self.provisioning.modify_volume(self.data.vol_id1, self.data.vol_name1) diff --git a/PyPowerStore/utils/constants.py b/PyPowerStore/utils/constants.py index b2e5b6a..cf3e6f6 100644 --- a/PyPowerStore/utils/constants.py +++ b/PyPowerStore/utils/constants.py @@ -60,16 +60,19 @@ } # Host Query -SELECT_ALL_HOST = {"select": "id,name,description,os_type," - "host_group_id," - "host_initiators,os_type_l10n," - "mapped_hosts(id,logical_unit_number," - "host_group(id,name),volume(id,name))" +SELECT_ALL_HOST = { + "select": "id,name,description,os_type," + "host_group_id," + "host_initiators,os_type_l10n," + "mapped_hosts(id,logical_unit_number," + "host_group(id,name),volume(id,name))," + "host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)" } FHC_HOST_DETAILS_QUERY = { "select": "id,name,description,os_type,host_group_id,host_initiators," "os_type_l10n,mapped_hosts(id,logical_unit_number," - "host_group(id,name),volume(id,name)),type,type_l10n" + "host_group(id,name),volume(id,name)),type,type_l10n," + "host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)" } FHP_HOST_DETAILS_QUERY = { "select": "id,name,description,type,os_type,host_group_id," @@ -77,11 +80,13 @@ "mapped_hosts(id,logical_unit_number,host_group(id,name)," "volume(id,name)),type_l10n,host_connectivity_l10n," "initiators(id,port_name,port_type,chap_single_username," - "chap_mutual_username,active_sessions),host_initiators" + "chap_mutual_username,active_sessions),host_initiators," + "host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)" } SELECT_ALL_HOST_GROUP = {"select": "name,id,description,hosts(id,name)"} -FHP_HOST_GROUP_QUERY = {"select": "name,id,description,hosts(id,name)," +FHP_HOST_GROUP_QUERY = {"select": "name,id,description,hosts(id,name,host_virtual_volume_mappings(id," + "host_id,host_group_id,virtual_volume_id))," "host_connectivity,host_connectivity_l10n," "mapped_host_groups(id,volume_id," "logical_unit_number)"} @@ -136,6 +141,32 @@ "creator_type_l10n,nas_server(name,id)," "protection_policy(name,id)"} +SELECT_ALL_FILESYSTEM_PRIME = {"select": "id,name, description," + "parent_id, filesystem_type, size_total,size_used," + "access_policy,locking_policy," + "folder_rename_policy, is_smb_sync_writes_enabled," + "is_smb_op_locks_enabled, is_smb_no_notify_enabled," + "is_smb_notify_on_access_enabled," + "is_smb_notify_on_write_enabled," + "smb_notify_on_change_dir_depth," + "is_async_MTime_enabled, is_quota_enabled," + "grace_period, default_hard_limit," + "default_soft_limit, creation_timestamp," + "expiration_timestamp, last_refresh_timestamp," + "last_writable_timestamp, is_modified,access_type," + "creator_type, filesystem_type_l10n," + "access_policy_l10n, locking_policy_l10n," + "folder_rename_policy_l10n, access_type_l10n," + "creator_type_l10n,nas_server(name,id)," + "protection_policy(name,id)," + "file_events_publishing_mode," + "file_events_publishing_mode_l10n," + "config_type, config_type_l10n,flr_attributes," + "host_io_size,host_io_size_l10n"} + +FILESYSTEM_PRIME = ['config_type', 'is_async_MTime_enabled', + 'file_events_publishing_mode', 'flr_attributes', + 'host_io_size'] FHP_NAS_QUERYSTRING = {"select": "id,name, description, operational_status," "current_node_id,preferred_node_id," @@ -292,6 +323,20 @@ VCENTER_DETAILS_QUERY = { 'select': 'id,instance_uuid,address,username' } +FHC_MALKA_VCENTER_QUERY = { + 'select': 'id,instance_uuid,address,username,vendor_provider_status,' + 'vendor_provider_status_l10n,' + 'virtual_machines(id,name,instance_uuid,type,status,' + 'virtual_volumes,protection_policy_id)' +} +FHP_VCENTER_QUERY = { + 'select': 'id,instance_uuid,address,username,version,' + 'vendor_provider_status,vendor_provider_status_l10n,' + 'virtual_machines(id,name,instance_uuid,type,status,' + 'virtual_volumes,protection_policy_id),' + 'datastores(id,instance_uuid,name,type,' + 'storage_container_id),vsphere_hosts(id,name,version)' +} # Appliance details APPLIANCE_DETAILS_QUERY = { @@ -328,10 +373,10 @@ # Certificate details CERTIFICATE_DETAILS_QUERY = { 'select': 'id,type,type_l10n,service,service_l10n,scope,is_current,' - 'is_valid,members(subject,serial_number,signature_algorithm,' - 'issuer,valid_from,valid_to,public_key_algorithm,key_length,' - 'thumbprint_algorithm,thumbprint_algorithm_l10n,thumbprint,' - 'certificate,depth,subject_alternative_names)' + 'is_valid,members(subject,serial_number,signature_algorithm,' + 'issuer,valid_from,valid_to,public_key_algorithm,key_length,' + 'thumbprint_algorithm,thumbprint_algorithm_l10n,thumbprint,' + 'certificate,depth,subject_alternative_names)' } # Security config details @@ -378,6 +423,21 @@ 'group_name_attribute,group_member_attribute,group_object_class,' 'group_search_path,group_search_level,ldap_server_type_l10n,protocol_l10n' } +VIRTUAL_VOLUME_FHP_DETAILS_QUERY = { + 'select': 'id,name,size,type,usage_type,appliance_id,storage_container_id,io_priority,profile_id,' + 'replication_group_id,creator_type,is_readonly,migration_session_id,virtual_machine_uuid,' + 'family_id,parent_id,source_id,source_timestamp,creation_timestamp,naa_name,' + 'is_replication_destination,location_history,protection_policy_id,nsid,nguid,type_l10n,' + 'usage_type_l10n,io_priority_l10n,creator_type_l10n,' + 'host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)' +} +VIRTUAL_VOLUME_DETAILS_QUERY = { + 'select': 'id,name,size,type,usage_type,appliance_id,storage_container_id,io_priority,profile_id,' + 'creator_type,is_readonly,migration_session_id,virtual_machine_uuid,' + 'family_id,parent_id,source_id,source_timestamp,creation_timestamp,' + 'location_history,type_l10n,usage_type_l10n,io_priority_l10n,creator_type_l10n,' + 'host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)' +} # LDAP Account details LDAP_ACCOUNT_DETAILS_QUERY = { 'select': 'id,role_id,domain_id,name,type,type_l10n,dn' @@ -592,7 +652,9 @@ # vCenter endpoints GET_VCENTER_LIST_URL = 'https://{0}/api/rest/vcenter' GET_VCENTER_DETAILS_URL = 'https://{0}/api/rest/vcenter/{1}' +ADD_VCENTER_URL = GET_VCENTER_LIST_URL MODIFY_VCENTER_URL = GET_VCENTER_DETAILS_URL +REMOVE_VCENTER_URL = GET_VCENTER_DETAILS_URL # Appliance endpoints GET_APPLIANCE_LIST_URL = 'https://{0}/api/rest/appliance' @@ -667,3 +729,7 @@ CREATE_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_LIST_URL MODIFY_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_DETAILS_URL DELETE_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_DETAILS_URL + +# virtual volume endpoints +GET_VIRTUAL_VOLUME_LIST_URL = 'https://{0}/api/rest/virtual_volume' +GET_VIRTUAL_VOLUME_DETAILS_URL = 'https://{0}/api/rest/virtual_volume/{1}' diff --git a/PyPowerStore/utils/helpers.py b/PyPowerStore/utils/helpers.py index 65ece28..3546b9b 100644 --- a/PyPowerStore/utils/helpers.py +++ b/PyPowerStore/utils/helpers.py @@ -48,7 +48,7 @@ def get_logger(module_name, enable_log=False): def is_foot_hill_or_higher(): - """Return a true if the array version is foot hill or higher. + """Returns true if the array version is foot hill or higher. :return: True if foot hill or higher :rtype: bool @@ -60,9 +60,21 @@ def is_foot_hill_or_higher(): return True return False +def is_malka_or_higher(): + """Returns true if the array version is Malka or higher. + + :return: True if array version is Malka or higher + :rtype: bool + """ + malka_version = '2.1.0.0' + array_version = provisioning_obj.get_array_version() + if array_version and ( + parse_version(array_version[0:7]) >= parse_version(malka_version)): + return True + return False def is_foot_hill_prime_or_higher(): - """Return a true if the array version is foothill prime or higher. + """Returns true if the array version is foothill prime or higher. :return: True if foothill prime or higher :rtype: bool diff --git a/README.md b/README.md index 1bda1ec..575b5bf 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ The library docs are available under 'docs' folder. This library uses python's "requests" library. -PyPowerStore officially supports Python 3.8, 3.9 and 3.10. +PyPowerStore officially supports Python 3.9, 3.10 and 3.11. ## Support diff --git a/docs/conf.py b/docs/conf.py index 9ac2479..22d0124 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = 'Dell' # The full version, including alpha/beta/rc tags -release = '1.9.0' +release = '1.10.0' # -- General configuration --------------------------------------------------- diff --git a/setup.py b/setup.py index 0f23c9e..cc3620c 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup(name='PyPowerStore', - version='1.9.0.0', + version='1.10.0.0', description='Python Library for Dell PowerStore', author='Ansible Team at Dell', author_email='ansible.team@dell.com',