PyPowerStore 1.9.0.0__tar.gz → 2.0.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PKG-INFO +3 -2
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/__init__.py +1 -1
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/client.py +4 -1
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/configuration.py +271 -19
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/protection.py +55 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/provisioning.py +64 -13
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/utils/constants.py +119 -13
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/utils/helpers.py +14 -2
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore.egg-info/PKG-INFO +3 -2
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore.egg-info/SOURCES.txt +0 -1
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/README.md +1 -1
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/setup.py +3 -1
- PyPowerStore-1.9.0.0/LICENSE +0 -201
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/powerstore_conn.py +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/utils/__init__.py +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore/utils/exception.py +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore.egg-info/dependency_links.txt +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore.egg-info/requires.txt +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/PyPowerStore.egg-info/top_level.txt +0 -0
- {PyPowerStore-1.9.0.0 → PyPowerStore-2.0.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 1.
|
|
1
|
+
Metadata-Version: 1.1
|
|
2
2
|
Name: PyPowerStore
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0.0
|
|
4
4
|
Summary: Python Library for Dell PowerStore
|
|
5
5
|
Home-page: https://github.com/dell/python-powerstore
|
|
6
6
|
Author: Ansible Team at Dell
|
|
@@ -8,3 +8,4 @@ Author-email: ansible.team@dell.com
|
|
|
8
8
|
License: UNKNOWN
|
|
9
9
|
Description: UNKNOWN
|
|
10
10
|
Platform: UNKNOWN
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -247,7 +247,10 @@ class Client():
|
|
|
247
247
|
if self.is_valid_response(response):
|
|
248
248
|
response_json = None
|
|
249
249
|
if response.status_code != 204:
|
|
250
|
-
|
|
250
|
+
if response.status_code == 201 and response.content == b'':
|
|
251
|
+
pass
|
|
252
|
+
else:
|
|
253
|
+
response_json = response.json()
|
|
251
254
|
# check 'all_pages' required, response received is
|
|
252
255
|
# partial(code 206) and contains info about total size of
|
|
253
256
|
# the collection
|
|
@@ -901,7 +901,6 @@ class Configuration:
|
|
|
901
901
|
# IP ports operations end
|
|
902
902
|
|
|
903
903
|
# vCenter operations start
|
|
904
|
-
|
|
905
904
|
def get_vcenters(self, filter_dict=None, all_pages=False):
|
|
906
905
|
"""Get all vcenters.
|
|
907
906
|
:param filter_dict: (optional) Filter details
|
|
@@ -916,11 +915,18 @@ class Configuration:
|
|
|
916
915
|
querystring = helpers.prepare_querystring(
|
|
917
916
|
constants.SELECT_ID, filter_dict)
|
|
918
917
|
LOG.info("Querystring: '%s'" % querystring)
|
|
919
|
-
|
|
920
|
-
constants.GET,
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
918
|
+
vcenter_list = self.config_client.\
|
|
919
|
+
request(constants.GET,
|
|
920
|
+
constants.GET_VCENTER_LIST_URL.format(self.server_ip),
|
|
921
|
+
querystring=querystring, all_pages=all_pages)
|
|
922
|
+
|
|
923
|
+
if vcenter_list:
|
|
924
|
+
resp_list = []
|
|
925
|
+
for vcenter in vcenter_list:
|
|
926
|
+
resp_dict = self.get_vcenter_details(vcenter['id'])
|
|
927
|
+
resp_list.append(resp_dict)
|
|
928
|
+
return resp_list
|
|
929
|
+
return vcenter_list
|
|
924
930
|
|
|
925
931
|
def get_vcenter_details(self, vcenter_id):
|
|
926
932
|
"""Get vcenter details.
|
|
@@ -931,12 +937,11 @@ class Configuration:
|
|
|
931
937
|
"""
|
|
932
938
|
LOG.info("Getting vcenter details by ID: '%s'" % vcenter_id)
|
|
933
939
|
querystring = constants.VCENTER_DETAILS_QUERY
|
|
934
|
-
if helpers.
|
|
935
|
-
querystring =
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
}
|
|
940
|
+
if helpers.is_foot_hill_prime_or_higher():
|
|
941
|
+
querystring = constants.FHP_VCENTER_QUERY
|
|
942
|
+
elif helpers.is_foot_hill_or_higher():
|
|
943
|
+
querystring = constants.FHC_MALKA_VCENTER_QUERY
|
|
944
|
+
|
|
940
945
|
return self.config_client.request(
|
|
941
946
|
constants.GET,
|
|
942
947
|
constants.GET_VCENTER_DETAILS_URL.format(self.server_ip,
|
|
@@ -945,20 +950,66 @@ class Configuration:
|
|
|
945
950
|
)
|
|
946
951
|
|
|
947
952
|
def modify_vcenter(self, vcenter_id, modify_param_dict):
|
|
948
|
-
"""
|
|
953
|
+
"""Modify vcenter attributes.
|
|
949
954
|
:param vcenter_id: ID of the vcenter
|
|
950
955
|
:type vcenter_id: str
|
|
951
|
-
:param modify_param_dict: Dict containing
|
|
956
|
+
:param modify_param_dict: Dict containing parameters for modification
|
|
952
957
|
:type modify_param_dict: dict
|
|
953
958
|
:return: Details of vcenter
|
|
954
959
|
:rtype: dict
|
|
955
960
|
"""
|
|
956
|
-
LOG.info("
|
|
961
|
+
LOG.info("Modifying vCenter attributes: '%s'" % vcenter_id)
|
|
957
962
|
self.config_client.request(constants.PATCH,
|
|
958
963
|
constants.MODIFY_VCENTER_URL.format(
|
|
959
964
|
self.server_ip, vcenter_id),
|
|
960
965
|
payload=modify_param_dict)
|
|
961
966
|
return self.get_vcenter_details(vcenter_id)
|
|
967
|
+
|
|
968
|
+
def add_vcenter(self, add_params):
|
|
969
|
+
"""
|
|
970
|
+
Add a vcenter to the unified PowerStore model.
|
|
971
|
+
vcenter can not be added to unified+ deployment
|
|
972
|
+
:param add_params: the parameters to add vcenter
|
|
973
|
+
:type add_params:dict
|
|
974
|
+
:return: ID of the vcenter if addition is successful
|
|
975
|
+
:rtype: dict
|
|
976
|
+
"""
|
|
977
|
+
LOG.info("Adding a vcenter.")
|
|
978
|
+
|
|
979
|
+
payload = dict()
|
|
980
|
+
if add_params:
|
|
981
|
+
for key, values in add_params.items():
|
|
982
|
+
payload[key] = values
|
|
983
|
+
|
|
984
|
+
return self.config_client.\
|
|
985
|
+
request(constants.POST,
|
|
986
|
+
constants.ADD_VCENTER_URL.format(self.server_ip),
|
|
987
|
+
payload=payload)
|
|
988
|
+
|
|
989
|
+
def remove_vcenter(self, vcenter_id, delete_vasa_provider=None):
|
|
990
|
+
"""
|
|
991
|
+
Remove vcenter from Unified PowerStore model.
|
|
992
|
+
vcenter can not be removed from unified+ deployment
|
|
993
|
+
:param vcenter_id: ID of the vcenter
|
|
994
|
+
:type vcenter_id: str
|
|
995
|
+
:param delete_vasa_provider: whether to remove a VASA provider.
|
|
996
|
+
Removal will only happen if the provider
|
|
997
|
+
is not connected to any other PowerStore
|
|
998
|
+
system
|
|
999
|
+
:type delete_vasa_provider: bool
|
|
1000
|
+
:return: None if success
|
|
1001
|
+
:rtype: None
|
|
1002
|
+
"""
|
|
1003
|
+
LOG.info("Removing vcenter: {0}.".format(vcenter_id))
|
|
1004
|
+
payload = dict()
|
|
1005
|
+
if delete_vasa_provider is not None:
|
|
1006
|
+
payload['delete_vendor_provider'] = delete_vasa_provider
|
|
1007
|
+
|
|
1008
|
+
return self.config_client.\
|
|
1009
|
+
request(constants.DELETE,
|
|
1010
|
+
constants.REMOVE_VCENTER_URL.format(self.server_ip,
|
|
1011
|
+
vcenter_id),
|
|
1012
|
+
payload=payload)
|
|
962
1013
|
# vCenter operations end
|
|
963
1014
|
|
|
964
1015
|
# Appliance operations start
|
|
@@ -1761,7 +1812,6 @@ class Configuration:
|
|
|
1761
1812
|
"""
|
|
1762
1813
|
LOG.info("Modifying remote support contact : '%s' with params '%s'" % (
|
|
1763
1814
|
remote_support_contact_id, modify_parameters))
|
|
1764
|
-
print(remote_support_contact_id)
|
|
1765
1815
|
if helpers.is_foot_hill_or_higher():
|
|
1766
1816
|
remote_support_contact_url = constants.MODIFY_REMOTE_SUPPORT_CONTACT_URL
|
|
1767
1817
|
return self.config_client.request(
|
|
@@ -1843,10 +1893,10 @@ class Configuration:
|
|
|
1843
1893
|
resp = self.config_client.request(
|
|
1844
1894
|
constants.GET,
|
|
1845
1895
|
constants.GET_LDAP_DOMAIN_LIST_URL.format(
|
|
1846
|
-
self.server_ip
|
|
1896
|
+
self.server_ip),
|
|
1847
1897
|
querystring=helpers.prepare_querystring(
|
|
1848
1898
|
constants.LDAP_DOMAIN_DETAILS_QUERY,
|
|
1849
|
-
|
|
1899
|
+
domain_name=constants.EQUALS + ldap_domain_name)
|
|
1850
1900
|
)
|
|
1851
1901
|
|
|
1852
1902
|
filterable_keys = ['domain_name', 'id', 'protocol', 'ldap_server_type']
|
|
@@ -2044,7 +2094,209 @@ class Configuration:
|
|
|
2044
2094
|
self.server_ip, ldap_account_id))
|
|
2045
2095
|
|
|
2046
2096
|
|
|
2047
|
-
# LDAP Account operations end
|
|
2097
|
+
# LDAP Account operations end
|
|
2098
|
+
|
|
2099
|
+
# Virtual volume operations begin
|
|
2100
|
+
|
|
2101
|
+
def get_virtual_volume_list(self, filter_dict=None, all_pages=None):
|
|
2102
|
+
"""Get all virtual volumes available on array.
|
|
2103
|
+
:param filter_dict: (optional) Filter details
|
|
2104
|
+
:type filter_dict: dict
|
|
2105
|
+
:param all_pages: (optional) Indicates whether to return all
|
|
2106
|
+
virtual volumes or not
|
|
2107
|
+
:type all_pages: bool
|
|
2108
|
+
:return: List of virtual volumes on array
|
|
2109
|
+
:rtype: list[dict]
|
|
2110
|
+
"""
|
|
2111
|
+
LOG.info("Getting volumes with filter: '%s' and all_pages: %s"
|
|
2112
|
+
% (filter_dict, all_pages))
|
|
2113
|
+
querystring = helpers.prepare_querystring(
|
|
2114
|
+
constants.VIRTUAL_VOLUME_DETAILS_QUERY,
|
|
2115
|
+
filter_dict)
|
|
2116
|
+
if helpers.is_foot_hill_prime_or_higher():
|
|
2117
|
+
querystring = helpers.prepare_querystring(
|
|
2118
|
+
constants.VIRTUAL_VOLUME_FHP_DETAILS_QUERY,
|
|
2119
|
+
filter_dict)
|
|
2120
|
+
LOG.info("Querystring: '%s'" % querystring)
|
|
2121
|
+
return self.config_client.request(constants.GET,
|
|
2122
|
+
constants.GET_VIRTUAL_VOLUME_LIST_URL.format
|
|
2123
|
+
(self.server_ip), payload=None,
|
|
2124
|
+
querystring=querystring,
|
|
2125
|
+
all_pages=all_pages)
|
|
2126
|
+
|
|
2127
|
+
# Virtual volume operations end
|
|
2128
|
+
|
|
2129
|
+
# Storage container operations begin
|
|
2130
|
+
|
|
2131
|
+
def get_storage_container_list(self, filter_dict=None, all_pages=None):
|
|
2132
|
+
"""Get all storage container available on array.
|
|
2133
|
+
:param filter_dict: (optional) Filter details
|
|
2134
|
+
:type filter_dict: dict
|
|
2135
|
+
:param all_pages: (optional) Indicates whether to return all
|
|
2136
|
+
Storage containers or not
|
|
2137
|
+
:type all_pages: bool
|
|
2138
|
+
:return: List of storage containers on array
|
|
2139
|
+
:rtype: list[dict]
|
|
2140
|
+
"""
|
|
2141
|
+
LOG.info("Getting storage containers with filter: '%s' and all_pages: %s"
|
|
2142
|
+
% (filter_dict, all_pages))
|
|
2143
|
+
querystring = helpers.prepare_querystring(
|
|
2144
|
+
constants.STORAGE_CONTAINER_DETAILS_QUERY,
|
|
2145
|
+
filter_dict)
|
|
2146
|
+
LOG.info("Querystring: '%s'" % querystring)
|
|
2147
|
+
return self.config_client.request(constants.GET,
|
|
2148
|
+
constants.GET_STORAGE_CONTAINER_LIST_URL.format
|
|
2149
|
+
(self.server_ip), payload=None,
|
|
2150
|
+
querystring=querystring,
|
|
2151
|
+
all_pages=all_pages)
|
|
2152
|
+
|
|
2153
|
+
def get_storage_container_details(self, storage_container_id):
|
|
2154
|
+
""" Get details of a storage container instance.
|
|
2155
|
+
|
|
2156
|
+
:param storage_container_id: Unique identifier of the storage_container
|
|
2157
|
+
:type storage_container_id: str
|
|
2158
|
+
:return: storage container details
|
|
2159
|
+
:rtype: dict
|
|
2160
|
+
"""
|
|
2161
|
+
LOG.info("Getting storage container details by ID: '%s'" % storage_container_id)
|
|
2162
|
+
|
|
2163
|
+
return self.config_client.request(
|
|
2164
|
+
constants.GET,
|
|
2165
|
+
constants.GET_STORAGE_CONTAINER_DETAILS_URL.format(
|
|
2166
|
+
self.server_ip, storage_container_id),
|
|
2167
|
+
querystring=constants.STORAGE_CONTAINER_DETAILS_QUERY)
|
|
2168
|
+
|
|
2169
|
+
def get_storage_container_details_by_name(self, storage_container_name):
|
|
2170
|
+
""" Get details of a storage container instance.
|
|
2171
|
+
|
|
2172
|
+
:param storage_container_name: storage container name
|
|
2173
|
+
:type storage_container_name: str
|
|
2174
|
+
:return: storage container details
|
|
2175
|
+
:rtype: dict
|
|
2176
|
+
"""
|
|
2177
|
+
LOG.info("Getting storage container details by name: '%s'" % storage_container_name)
|
|
2178
|
+
resp = self.get_storage_container_list()
|
|
2179
|
+
|
|
2180
|
+
for container in resp:
|
|
2181
|
+
if container['name'] == storage_container_name:
|
|
2182
|
+
return self.get_storage_container_details(container['id'])
|
|
2183
|
+
|
|
2184
|
+
def create_storage_container(self, create_parameters):
|
|
2185
|
+
""" Create a storage_container.
|
|
2186
|
+
|
|
2187
|
+
:param create_parameters: Parameters for creating a storage_container
|
|
2188
|
+
:type create_parameters: dict
|
|
2189
|
+
:return: Unique identifier of the new storage container instance created
|
|
2190
|
+
:rtype: dict
|
|
2191
|
+
"""
|
|
2192
|
+
LOG.info("creating storage container")
|
|
2193
|
+
|
|
2194
|
+
return self.config_client.request(
|
|
2195
|
+
constants.POST,
|
|
2196
|
+
constants.CREATE_STORAGE_CONTAINER_URL.format(
|
|
2197
|
+
self.server_ip), payload=create_parameters)
|
|
2198
|
+
|
|
2199
|
+
def modify_storage_container_details(self, storage_container_id, modify_parameters):
|
|
2200
|
+
""" Modifying storage container configuration.
|
|
2201
|
+
|
|
2202
|
+
:param storage_container_id: Unique ID of the storage container instance
|
|
2203
|
+
:type storage_container_id: str
|
|
2204
|
+
:param modify_parameters: Parameters for modifying storage container
|
|
2205
|
+
:type modify_parameters: dict
|
|
2206
|
+
:return: None
|
|
2207
|
+
:rtype: None
|
|
2208
|
+
"""
|
|
2209
|
+
LOG.info("Modifying storage containert id: '%s'" % storage_container_id)
|
|
2210
|
+
|
|
2211
|
+
return self.config_client.request(
|
|
2212
|
+
constants.PATCH,
|
|
2213
|
+
constants.MODIFY_STORAGE_CONTAINER_URL.format(
|
|
2214
|
+
self.server_ip, storage_container_id), payload=modify_parameters)
|
|
2215
|
+
|
|
2216
|
+
def delete_storage_container(self, storage_container_id, delete_parameters):
|
|
2217
|
+
""" Delete a storage container.
|
|
2218
|
+
|
|
2219
|
+
:param storage_container_id: Unique ID of the storage container instance
|
|
2220
|
+
:type storage_container_id: str
|
|
2221
|
+
:return: None
|
|
2222
|
+
:rtype: None
|
|
2223
|
+
"""
|
|
2224
|
+
LOG.info("Deleting storage container with id: '%s'" % storage_container_id)
|
|
2225
|
+
|
|
2226
|
+
return self.config_client.request(
|
|
2227
|
+
constants.DELETE,
|
|
2228
|
+
constants.DELETE_STORAGE_CONTAINER_URL.format(
|
|
2229
|
+
self.server_ip, storage_container_id), payload=delete_parameters)
|
|
2230
|
+
# Storage container operations end
|
|
2231
|
+
|
|
2232
|
+
# Storage container destination operations start
|
|
2233
|
+
def get_storage_container_destination_list(self, filter_dict=None, all_pages=None):
|
|
2234
|
+
"""Get all storage container destination.
|
|
2235
|
+
:param filter_dict: (optional) Filter details
|
|
2236
|
+
:type filter_dict: dict
|
|
2237
|
+
:param all_pages: (optional) Indicates whether to return all
|
|
2238
|
+
Storage containers destination or not
|
|
2239
|
+
:type all_pages: bool
|
|
2240
|
+
:return: List of storage containers destination
|
|
2241
|
+
:rtype: list[dict]
|
|
2242
|
+
"""
|
|
2243
|
+
LOG.info("Getting storage containers destination with filter: '%s' "
|
|
2244
|
+
"and all_pages: %s" % (filter_dict, all_pages))
|
|
2245
|
+
querystring = helpers.prepare_querystring(
|
|
2246
|
+
constants.STORAGE_CONTAINER_DETAILS_DESTINATION_QUERY, filter_dict)
|
|
2247
|
+
LOG.info("Querystring: '%s'" % querystring)
|
|
2248
|
+
return self.config_client.request(
|
|
2249
|
+
constants.GET,
|
|
2250
|
+
constants.GET_STORAGE_CONTAINER_DESTINATION_LIST_URL.format(
|
|
2251
|
+
self.server_ip),
|
|
2252
|
+
payload=None, querystring=querystring, all_pages=all_pages)
|
|
2253
|
+
|
|
2254
|
+
def get_storage_container_destination_details(self, storage_container_destination_id):
|
|
2255
|
+
""" Get details of a storage container destination instance.
|
|
2256
|
+
|
|
2257
|
+
:param storage_container_destination_id: Unique identifier of the
|
|
2258
|
+
storage container destination
|
|
2259
|
+
:type storage_container_destination_id: str
|
|
2260
|
+
:return: storage container destination details
|
|
2261
|
+
:rtype: dict
|
|
2262
|
+
"""
|
|
2263
|
+
LOG.info("Getting storage container destination details by "
|
|
2264
|
+
"ID: '%s'" % storage_container_destination_id)
|
|
2265
|
+
|
|
2266
|
+
return self.config_client.request(
|
|
2267
|
+
constants.GET,
|
|
2268
|
+
constants.GET_STORAGE_CONTAINER_DESTINATION_DETAILS_URL.format(
|
|
2269
|
+
self.server_ip, storage_container_destination_id),
|
|
2270
|
+
querystring=constants.STORAGE_CONTAINER_DETAILS_DESTINATION_QUERY)
|
|
2271
|
+
|
|
2272
|
+
def create_storage_container_destination(self, create_destination_params):
|
|
2273
|
+
"""Create a Storage Container Destination
|
|
2274
|
+
:param create_destination_params: parameter to create storage container
|
|
2275
|
+
destination
|
|
2276
|
+
:type create_destination_params: dict
|
|
2277
|
+
:return: Unique identifier of newly created storage container destination
|
|
2278
|
+
:rtype: dict
|
|
2279
|
+
"""
|
|
2280
|
+
LOG.info("Creating storage container destination.")
|
|
2281
|
+
return self.config_client.request(
|
|
2282
|
+
constants.POST,
|
|
2283
|
+
constants.CREATE_STORAGE_CONTAINER_DESTINATION_URL.format(
|
|
2284
|
+
self.server_ip), payload=create_destination_params)
|
|
2285
|
+
|
|
2286
|
+
def delete_storage_container_destination(self, storage_container_destination_id):
|
|
2287
|
+
"""Delete a storage container destination
|
|
2288
|
+
:param storage_container_destination_id: ID of storage container destination
|
|
2289
|
+
:type storage_container_destination_id: str
|
|
2290
|
+
:rtype: None
|
|
2291
|
+
"""
|
|
2292
|
+
LOG.info("Deleting storage container destination with "
|
|
2293
|
+
"id: '%s'" % storage_container_destination_id)
|
|
2294
|
+
return self.config_client.request(
|
|
2295
|
+
constants.DELETE,
|
|
2296
|
+
constants.DELETE_STORAGE_CONTAINER_DESTINATION_URL.format(
|
|
2297
|
+
self.server_ip, storage_container_destination_id))
|
|
2298
|
+
|
|
2299
|
+
# Storage container destination operations end
|
|
2048
2300
|
|
|
2049
2301
|
@staticmethod
|
|
2050
2302
|
def _prepare_local_user_payload(**kwargs):
|
|
@@ -1142,6 +1142,61 @@ class ProtectionFunctions:
|
|
|
1142
1142
|
|
|
1143
1143
|
# Replication Session end
|
|
1144
1144
|
|
|
1145
|
+
# Replication group start
|
|
1146
|
+
def get_replication_groups(self, filter_dict=None, all_pages=False):
|
|
1147
|
+
"""Get all the replication groups
|
|
1148
|
+
:param filter_dict: (optional) Filter details
|
|
1149
|
+
:type filter_dict: dict
|
|
1150
|
+
:param all_pages: (optional) Indicates whether to return all elements
|
|
1151
|
+
or not
|
|
1152
|
+
:type all_pages: bool
|
|
1153
|
+
:return: replication groups.
|
|
1154
|
+
:rtype: list[dict]
|
|
1155
|
+
"""
|
|
1156
|
+
LOG.info("Getting replication groups with filter: '%s' and "
|
|
1157
|
+
"all_pages: %s" % (filter_dict, all_pages))
|
|
1158
|
+
querystring = helpers.prepare_querystring(
|
|
1159
|
+
constants.REPLICATION_GROUP_QUERY, filter_dict)
|
|
1160
|
+
LOG.info("Querystring: '%s'" % querystring)
|
|
1161
|
+
return self.rest_client.request(
|
|
1162
|
+
constants.GET, constants.REPLICATION_GROUP_DETAILS_LIST_URL.format(
|
|
1163
|
+
self.server_ip), payload=None, querystring=querystring,
|
|
1164
|
+
all_pages=all_pages)
|
|
1165
|
+
|
|
1166
|
+
def get_replication_group_details(self, replication_group_id):
|
|
1167
|
+
"""Getting the details of a replication group using ID
|
|
1168
|
+
:param replication_group_id: ID of the replication group
|
|
1169
|
+
:type replication_group_id: str
|
|
1170
|
+
:return: replication session details
|
|
1171
|
+
:rtype: dict
|
|
1172
|
+
"""
|
|
1173
|
+
LOG.info("Getting replication session details by ID:"
|
|
1174
|
+
" '%s'" % replication_group_id)
|
|
1175
|
+
|
|
1176
|
+
return self.rest_client.request(
|
|
1177
|
+
constants.GET,
|
|
1178
|
+
constants.REPLICATION_GROUP_DETAILS_URL.format(
|
|
1179
|
+
self.server_ip, replication_group_id),
|
|
1180
|
+
querystring=constants.REPLICATION_GROUP_QUERY)
|
|
1181
|
+
|
|
1182
|
+
def get_replication_group_details_by_name(self, replication_group_name):
|
|
1183
|
+
"""Get details of the replication group details using name
|
|
1184
|
+
:param replication_group_name: Name of the replication group
|
|
1185
|
+
:type replication_group_name: str
|
|
1186
|
+
:return: replication session details
|
|
1187
|
+
:rtype: list of dict
|
|
1188
|
+
"""
|
|
1189
|
+
LOG.info("Getting replication group details by name:"
|
|
1190
|
+
" '%s'" % replication_group_name)
|
|
1191
|
+
return self.rest_client.request(
|
|
1192
|
+
constants.GET,
|
|
1193
|
+
constants.REPLICATION_GROUP_DETAILS_LIST_URL.format(
|
|
1194
|
+
self.server_ip),
|
|
1195
|
+
querystring=helpers.prepare_querystring(
|
|
1196
|
+
constants.REPLICATION_GROUP_QUERY,
|
|
1197
|
+
name=constants.EQUALS + replication_group_name))
|
|
1198
|
+
# Replication group end
|
|
1199
|
+
|
|
1145
1200
|
# Remote System start
|
|
1146
1201
|
def get_remote_systems(self, filter_dict=None, all_pages=False):
|
|
1147
1202
|
"""Get all remote systems.
|
|
@@ -64,7 +64,8 @@ class Provisioning:
|
|
|
64
64
|
|
|
65
65
|
def create_volume(self, name, size, description=None,
|
|
66
66
|
volume_group_id=None, protection_policy_id=None,
|
|
67
|
-
performance_policy_id=None
|
|
67
|
+
performance_policy_id=None, app_type=None,
|
|
68
|
+
app_type_other=None, appliance_id=None):
|
|
68
69
|
"""Create a volume.
|
|
69
70
|
|
|
70
71
|
:param name: The name of the volume
|
|
@@ -73,13 +74,24 @@ class Provisioning:
|
|
|
73
74
|
:param volume_group_id: (optional) The volume group ID
|
|
74
75
|
:param protection_policy_id: (optional) The protection policy ID
|
|
75
76
|
:param performance_policy_id: (optional) The performance policy ID
|
|
77
|
+
:param app_type: (optional) The application type
|
|
78
|
+
:param app_type_other: (optional) Describes application type when
|
|
79
|
+
app_type is set to other
|
|
80
|
+
:param appliance_id: (optional) The appliance ID
|
|
76
81
|
"""
|
|
82
|
+
if app_type is not None and not helpers.is_malka_or_higher():
|
|
83
|
+
raise Exception("'app_type' parameter is supported only from "
|
|
84
|
+
"Powerstore version 2.1.0.0 onwards")
|
|
85
|
+
|
|
77
86
|
LOG.info("Creating volume: '%s'" % name)
|
|
78
87
|
payload = self._prepare_create_volume_payload(name, size,
|
|
79
88
|
description,
|
|
80
89
|
volume_group_id,
|
|
81
90
|
protection_policy_id,
|
|
82
|
-
performance_policy_id
|
|
91
|
+
performance_policy_id,
|
|
92
|
+
app_type,
|
|
93
|
+
app_type_other,
|
|
94
|
+
appliance_id)
|
|
83
95
|
self.client.request(constants.POST,
|
|
84
96
|
constants.VOLUME_CREATE_URL.format(
|
|
85
97
|
self.server_ip), payload)
|
|
@@ -88,7 +100,10 @@ class Provisioning:
|
|
|
88
100
|
description,
|
|
89
101
|
volume_group_id,
|
|
90
102
|
protection_policy_id,
|
|
91
|
-
performance_policy_id
|
|
103
|
+
performance_policy_id,
|
|
104
|
+
app_type,
|
|
105
|
+
app_type_other,
|
|
106
|
+
appliance_id):
|
|
92
107
|
|
|
93
108
|
create_volume_dict = dict()
|
|
94
109
|
if name is not None:
|
|
@@ -104,6 +119,12 @@ class Provisioning:
|
|
|
104
119
|
if performance_policy_id is not None:
|
|
105
120
|
create_volume_dict['performance_policy_id'] = \
|
|
106
121
|
performance_policy_id
|
|
122
|
+
if app_type is not None:
|
|
123
|
+
create_volume_dict['app_type'] = app_type
|
|
124
|
+
if app_type_other is not None:
|
|
125
|
+
create_volume_dict['app_type_other'] = app_type_other
|
|
126
|
+
if appliance_id is not None:
|
|
127
|
+
create_volume_dict['appliance_id'] = appliance_id
|
|
107
128
|
|
|
108
129
|
return create_volume_dict
|
|
109
130
|
|
|
@@ -122,8 +143,8 @@ class Provisioning:
|
|
|
122
143
|
payload=None)
|
|
123
144
|
|
|
124
145
|
def modify_volume(self, volume_id, name=None, description=None, size=None,
|
|
125
|
-
protection_policy_id=None,
|
|
126
|
-
|
|
146
|
+
protection_policy_id=None, performance_policy_id=None,
|
|
147
|
+
app_type=None, app_type_other=None):
|
|
127
148
|
"""Modify a volume.
|
|
128
149
|
|
|
129
150
|
:param volume_id: The volume ID
|
|
@@ -138,16 +159,26 @@ class Provisioning:
|
|
|
138
159
|
:type protection_policy_id: str
|
|
139
160
|
:param performance_policy_id: The performance policy ID
|
|
140
161
|
:type performance_policy_id: str
|
|
162
|
+
:param app_type: The application type
|
|
163
|
+
:type app_type: str
|
|
164
|
+
:param app_type_other: Describes application type when
|
|
165
|
+
app_type is set to other
|
|
141
166
|
:return: None if success else raise exception
|
|
142
167
|
:rtype: None
|
|
143
168
|
"""
|
|
169
|
+
if app_type is not None and not helpers.is_malka_or_higher():
|
|
170
|
+
raise Exception("'app_type' parameter is supported only from "
|
|
171
|
+
"Powerstore version 2.1.0.0 onwards")
|
|
172
|
+
|
|
144
173
|
LOG.info("Modifying volume: '%s'" % volume_id)
|
|
145
174
|
payload = self.\
|
|
146
175
|
_prepare_modify_volume_payload(name,
|
|
147
176
|
description,
|
|
148
177
|
size,
|
|
149
178
|
protection_policy_id,
|
|
150
|
-
performance_policy_id
|
|
179
|
+
performance_policy_id,
|
|
180
|
+
app_type,
|
|
181
|
+
app_type_other)
|
|
151
182
|
return self.client.request(
|
|
152
183
|
constants.PATCH, constants.MODIFY_VOLUME_URL.format(
|
|
153
184
|
self.server_ip, volume_id),
|
|
@@ -156,7 +187,9 @@ class Provisioning:
|
|
|
156
187
|
def _prepare_modify_volume_payload(self, name=None, description=None,
|
|
157
188
|
size=None,
|
|
158
189
|
protection_policy_id=None,
|
|
159
|
-
performance_policy_id=None
|
|
190
|
+
performance_policy_id=None,
|
|
191
|
+
app_type=None,
|
|
192
|
+
app_type_other=None):
|
|
160
193
|
|
|
161
194
|
modify_volume_dict = dict()
|
|
162
195
|
if name is not None:
|
|
@@ -170,6 +203,10 @@ class Provisioning:
|
|
|
170
203
|
if performance_policy_id is not None:
|
|
171
204
|
modify_volume_dict['performance_policy_id'] = \
|
|
172
205
|
performance_policy_id
|
|
206
|
+
if app_type is not None:
|
|
207
|
+
modify_volume_dict['app_type'] = app_type
|
|
208
|
+
if app_type_other is not None:
|
|
209
|
+
modify_volume_dict['app_type_other'] = app_type_other
|
|
173
210
|
|
|
174
211
|
return modify_volume_dict
|
|
175
212
|
|
|
@@ -238,7 +275,7 @@ class Provisioning:
|
|
|
238
275
|
performance_policy_id
|
|
239
276
|
|
|
240
277
|
return clone_volume_dict
|
|
241
|
-
|
|
278
|
+
|
|
242
279
|
def refresh_volume(self, volume_id, volume_id_to_refresh_from=None,
|
|
243
280
|
create_backup_snap=None,
|
|
244
281
|
backup_snap_name=None,
|
|
@@ -303,7 +340,7 @@ class Provisioning:
|
|
|
303
340
|
backup_snap_performance_policy_id
|
|
304
341
|
|
|
305
342
|
return refresh_volume_dict
|
|
306
|
-
|
|
343
|
+
|
|
307
344
|
def restore_volume(self, volume_id, snap_id_to_restore_from=None,
|
|
308
345
|
create_backup_snap=None,
|
|
309
346
|
backup_snap_name=None,
|
|
@@ -1163,7 +1200,7 @@ class Provisioning:
|
|
|
1163
1200
|
:type name: str
|
|
1164
1201
|
:param description: (optional) Description for the clone volume group.
|
|
1165
1202
|
:type description: str
|
|
1166
|
-
:param protection_policy_id: (optional) Unique identifier of the protection
|
|
1203
|
+
:param protection_policy_id: (optional) Unique identifier of the protection
|
|
1167
1204
|
policy to assign to the clone volume group
|
|
1168
1205
|
:type protection_policy_id: str
|
|
1169
1206
|
:return: Unique identifier of the new instance created if success else raise exception
|
|
@@ -1493,7 +1530,7 @@ class Provisioning:
|
|
|
1493
1530
|
)
|
|
1494
1531
|
|
|
1495
1532
|
# NAS Server methods
|
|
1496
|
-
|
|
1533
|
+
|
|
1497
1534
|
def get_nas_servers(self, filter_dict=None, all_pages=False):
|
|
1498
1535
|
"""Get a list of nas servers.
|
|
1499
1536
|
|
|
@@ -1620,12 +1657,15 @@ class Provisioning:
|
|
|
1620
1657
|
:rtype: dict
|
|
1621
1658
|
"""
|
|
1622
1659
|
LOG.info("Getting filesystem details by ID: '%s'" % filesystem_id)
|
|
1660
|
+
querystring=constants.SELECT_ALL_FILESYSTEM
|
|
1661
|
+
if helpers.is_foot_hill_prime_or_higher():
|
|
1662
|
+
querystring=constants.SELECT_ALL_FILESYSTEM_PRIME
|
|
1623
1663
|
return self.client.request(
|
|
1624
1664
|
constants.GET,
|
|
1625
1665
|
constants.GET_FILESYSTEM_DETAILS_URL.format(self.server_ip,
|
|
1626
1666
|
filesystem_id),
|
|
1627
1667
|
payload=None,
|
|
1628
|
-
querystring=
|
|
1668
|
+
querystring=querystring)
|
|
1629
1669
|
|
|
1630
1670
|
def get_filesystem_by_name(self, filesystem_name, nas_server_id):
|
|
1631
1671
|
"""Get details of a filesystem by name.
|
|
@@ -1637,12 +1677,15 @@ class Provisioning:
|
|
|
1637
1677
|
"""
|
|
1638
1678
|
LOG.info("Getting filesystem details by name: '%s' and NAS Server: "
|
|
1639
1679
|
"'%s'" % (filesystem_name, nas_server_id))
|
|
1680
|
+
querystring=constants.SELECT_ALL_FILESYSTEM
|
|
1681
|
+
if helpers.is_foot_hill_prime_or_higher():
|
|
1682
|
+
querystring=constants.SELECT_ALL_FILESYSTEM_PRIME
|
|
1640
1683
|
return self.client.request(
|
|
1641
1684
|
constants.GET,
|
|
1642
1685
|
constants.GET_FILESYSTEM_DETAILS_BY_NAME_URL.format(
|
|
1643
1686
|
self.server_ip),
|
|
1644
1687
|
payload=None, querystring=helpers.prepare_querystring(
|
|
1645
|
-
|
|
1688
|
+
querystring,
|
|
1646
1689
|
nas_server_id=constants.EQUALS + nas_server_id,
|
|
1647
1690
|
name=constants.EQUALS + filesystem_name
|
|
1648
1691
|
)
|
|
@@ -1671,6 +1714,10 @@ class Provisioning:
|
|
|
1671
1714
|
|
|
1672
1715
|
if advance_parameters:
|
|
1673
1716
|
for key, value in advance_parameters.items():
|
|
1717
|
+
if key in constants.FILESYSTEM_PRIME and \
|
|
1718
|
+
not helpers.is_foot_hill_prime_or_higher():
|
|
1719
|
+
raise Exception( key + " is supported for PowerStore" \
|
|
1720
|
+
" version 3.0.0.0 and above.")
|
|
1674
1721
|
payload[key] = value
|
|
1675
1722
|
return self.client.request(constants.POST,
|
|
1676
1723
|
constants.CREATE_FILESYSTEM_URL.format(
|
|
@@ -1722,6 +1769,10 @@ class Provisioning:
|
|
|
1722
1769
|
if modify_parameters:
|
|
1723
1770
|
payload = dict()
|
|
1724
1771
|
for key, value in modify_parameters.items():
|
|
1772
|
+
if key in constants.FILESYSTEM_PRIME and \
|
|
1773
|
+
not helpers.is_foot_hill_prime_or_higher():
|
|
1774
|
+
raise Exception( key + " is supported for PowerStore" \
|
|
1775
|
+
" version 3.0.0.0 and above.")
|
|
1725
1776
|
if value is not None:
|
|
1726
1777
|
payload[key] = value
|
|
1727
1778
|
|
|
@@ -60,16 +60,19 @@ FHP_VOLUME_DETAILS_QUERY = {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
# Host Query
|
|
63
|
-
SELECT_ALL_HOST = {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
SELECT_ALL_HOST = {
|
|
64
|
+
"select": "id,name,description,os_type,"
|
|
65
|
+
"host_group_id,"
|
|
66
|
+
"host_initiators,os_type_l10n,"
|
|
67
|
+
"mapped_hosts(id,logical_unit_number,"
|
|
68
|
+
"host_group(id,name),volume(id,name)),"
|
|
69
|
+
"host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)"
|
|
68
70
|
}
|
|
69
71
|
FHC_HOST_DETAILS_QUERY = {
|
|
70
72
|
"select": "id,name,description,os_type,host_group_id,host_initiators,"
|
|
71
73
|
"os_type_l10n,mapped_hosts(id,logical_unit_number,"
|
|
72
|
-
"host_group(id,name),volume(id,name)),type,type_l10n"
|
|
74
|
+
"host_group(id,name),volume(id,name)),type,type_l10n,"
|
|
75
|
+
"host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)"
|
|
73
76
|
}
|
|
74
77
|
FHP_HOST_DETAILS_QUERY = {
|
|
75
78
|
"select": "id,name,description,type,os_type,host_group_id,"
|
|
@@ -77,11 +80,13 @@ FHP_HOST_DETAILS_QUERY = {
|
|
|
77
80
|
"mapped_hosts(id,logical_unit_number,host_group(id,name),"
|
|
78
81
|
"volume(id,name)),type_l10n,host_connectivity_l10n,"
|
|
79
82
|
"initiators(id,port_name,port_type,chap_single_username,"
|
|
80
|
-
"chap_mutual_username,active_sessions),host_initiators"
|
|
83
|
+
"chap_mutual_username,active_sessions),host_initiators,"
|
|
84
|
+
"host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)"
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
SELECT_ALL_HOST_GROUP = {"select": "name,id,description,hosts(id,name)"}
|
|
84
|
-
FHP_HOST_GROUP_QUERY = {"select": "name,id,description,hosts(id,name
|
|
88
|
+
FHP_HOST_GROUP_QUERY = {"select": "name,id,description,hosts(id,name,host_virtual_volume_mappings(id,"
|
|
89
|
+
"host_id,host_group_id,virtual_volume_id)),"
|
|
85
90
|
"host_connectivity,host_connectivity_l10n,"
|
|
86
91
|
"mapped_host_groups(id,volume_id,"
|
|
87
92
|
"logical_unit_number)"}
|
|
@@ -136,6 +141,32 @@ SELECT_ALL_FILESYSTEM = {"select": "id,name, description,"
|
|
|
136
141
|
"creator_type_l10n,nas_server(name,id),"
|
|
137
142
|
"protection_policy(name,id)"}
|
|
138
143
|
|
|
144
|
+
SELECT_ALL_FILESYSTEM_PRIME = {"select": "id,name, description,"
|
|
145
|
+
"parent_id, filesystem_type, size_total,size_used,"
|
|
146
|
+
"access_policy,locking_policy,"
|
|
147
|
+
"folder_rename_policy, is_smb_sync_writes_enabled,"
|
|
148
|
+
"is_smb_op_locks_enabled, is_smb_no_notify_enabled,"
|
|
149
|
+
"is_smb_notify_on_access_enabled,"
|
|
150
|
+
"is_smb_notify_on_write_enabled,"
|
|
151
|
+
"smb_notify_on_change_dir_depth,"
|
|
152
|
+
"is_async_MTime_enabled, is_quota_enabled,"
|
|
153
|
+
"grace_period, default_hard_limit,"
|
|
154
|
+
"default_soft_limit, creation_timestamp,"
|
|
155
|
+
"expiration_timestamp, last_refresh_timestamp,"
|
|
156
|
+
"last_writable_timestamp, is_modified,access_type,"
|
|
157
|
+
"creator_type, filesystem_type_l10n,"
|
|
158
|
+
"access_policy_l10n, locking_policy_l10n,"
|
|
159
|
+
"folder_rename_policy_l10n, access_type_l10n,"
|
|
160
|
+
"creator_type_l10n,nas_server(name,id),"
|
|
161
|
+
"protection_policy(name,id),"
|
|
162
|
+
"file_events_publishing_mode,"
|
|
163
|
+
"file_events_publishing_mode_l10n,"
|
|
164
|
+
"config_type, config_type_l10n,flr_attributes,"
|
|
165
|
+
"host_io_size,host_io_size_l10n"}
|
|
166
|
+
|
|
167
|
+
FILESYSTEM_PRIME = ['config_type', 'is_async_MTime_enabled',
|
|
168
|
+
'file_events_publishing_mode', 'flr_attributes',
|
|
169
|
+
'host_io_size']
|
|
139
170
|
|
|
140
171
|
FHP_NAS_QUERYSTRING = {"select": "id,name, description, operational_status,"
|
|
141
172
|
"current_node_id,preferred_node_id,"
|
|
@@ -292,6 +323,20 @@ IP_PORT_DETAILS_QUERY = {
|
|
|
292
323
|
VCENTER_DETAILS_QUERY = {
|
|
293
324
|
'select': 'id,instance_uuid,address,username'
|
|
294
325
|
}
|
|
326
|
+
FHC_MALKA_VCENTER_QUERY = {
|
|
327
|
+
'select': 'id,instance_uuid,address,username,vendor_provider_status,'
|
|
328
|
+
'vendor_provider_status_l10n,'
|
|
329
|
+
'virtual_machines(id,name,instance_uuid,type,status,'
|
|
330
|
+
'virtual_volumes,protection_policy_id)'
|
|
331
|
+
}
|
|
332
|
+
FHP_VCENTER_QUERY = {
|
|
333
|
+
'select': 'id,instance_uuid,address,username,version,'
|
|
334
|
+
'vendor_provider_status,vendor_provider_status_l10n,'
|
|
335
|
+
'virtual_machines(id,name,instance_uuid,type,status,'
|
|
336
|
+
'virtual_volumes,protection_policy_id),'
|
|
337
|
+
'datastores(id,instance_uuid,name,type,'
|
|
338
|
+
'storage_container_id),vsphere_hosts(id,name,version)'
|
|
339
|
+
}
|
|
295
340
|
|
|
296
341
|
# Appliance details
|
|
297
342
|
APPLIANCE_DETAILS_QUERY = {
|
|
@@ -322,16 +367,18 @@ REMOTE_SYSTEM_FHP_DETAILS_QUERY = {
|
|
|
322
367
|
'state_l10n,data_connection_type_l10n,file_connection_state_l10n,'
|
|
323
368
|
'data_connection_state_l10n,discovery_chap_mode_l10n,'
|
|
324
369
|
'session_chap_mode_l10n,data_network_latency_l10n,'
|
|
325
|
-
'capabilities_l10n,storage_container_destinations'
|
|
370
|
+
'capabilities_l10n,storage_container_destinations(id,'
|
|
371
|
+
'storage_container_id,remote_system_id,remote_storage_container_id,'
|
|
372
|
+
'storage_container(id,name))'
|
|
326
373
|
}
|
|
327
374
|
|
|
328
375
|
# Certificate details
|
|
329
376
|
CERTIFICATE_DETAILS_QUERY = {
|
|
330
377
|
'select': 'id,type,type_l10n,service,service_l10n,scope,is_current,'
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
378
|
+
'is_valid,members(subject,serial_number,signature_algorithm,'
|
|
379
|
+
'issuer,valid_from,valid_to,public_key_algorithm,key_length,'
|
|
380
|
+
'thumbprint_algorithm,thumbprint_algorithm_l10n,thumbprint,'
|
|
381
|
+
'certificate,depth,subject_alternative_names)'
|
|
335
382
|
}
|
|
336
383
|
|
|
337
384
|
# Security config details
|
|
@@ -378,6 +425,42 @@ LDAP_DOMAIN_DETAILS_QUERY = {
|
|
|
378
425
|
'group_name_attribute,group_member_attribute,group_object_class,'
|
|
379
426
|
'group_search_path,group_search_level,ldap_server_type_l10n,protocol_l10n'
|
|
380
427
|
}
|
|
428
|
+
VIRTUAL_VOLUME_FHP_DETAILS_QUERY = {
|
|
429
|
+
'select': 'id,name,size,type,usage_type,appliance_id,storage_container_id,io_priority,profile_id,'
|
|
430
|
+
'replication_group_id,creator_type,is_readonly,migration_session_id,virtual_machine_uuid,'
|
|
431
|
+
'family_id,parent_id,source_id,source_timestamp,creation_timestamp,naa_name,'
|
|
432
|
+
'is_replication_destination,location_history,protection_policy_id,nsid,nguid,type_l10n,'
|
|
433
|
+
'usage_type_l10n,io_priority_l10n,creator_type_l10n,'
|
|
434
|
+
'host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)'
|
|
435
|
+
}
|
|
436
|
+
VIRTUAL_VOLUME_DETAILS_QUERY = {
|
|
437
|
+
'select': 'id,name,size,type,usage_type,appliance_id,storage_container_id,io_priority,profile_id,'
|
|
438
|
+
'creator_type,is_readonly,migration_session_id,virtual_machine_uuid,'
|
|
439
|
+
'family_id,parent_id,source_id,source_timestamp,creation_timestamp,'
|
|
440
|
+
'location_history,type_l10n,usage_type_l10n,io_priority_l10n,creator_type_l10n,'
|
|
441
|
+
'host_virtual_volume_mappings(id,host_id,host_group_id,virtual_volume_id)'
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
STORAGE_CONTAINER_DETAILS_QUERY = {
|
|
445
|
+
'select': 'id,name,quota,storage_protocol,storage_protocol_l10n,'
|
|
446
|
+
'virtual_volumes(id,name),replication_groups(id,name),datastores(id,name),'
|
|
447
|
+
'destinations(id,remote_system_id,remote_storage_container_id)'
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
STORAGE_CONTAINER_DETAILS_DESTINATION_QUERY = {
|
|
451
|
+
'select': 'id,remote_system_id,storage_container_id,'
|
|
452
|
+
'storage_container(id,name),remote_storage_container_id,'
|
|
453
|
+
'remote_system(id,name,management_address)'
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
REPLICATION_GROUP_QUERY = {
|
|
457
|
+
'select': 'id,name,storage_container_id,description,creator_type,'
|
|
458
|
+
'creation_timestamp,is_replication_destination,creator_type_l10n'
|
|
459
|
+
',virtual_volumes,storage_container,parent,source,'
|
|
460
|
+
'child_replication_groups,target_replication_groups,'
|
|
461
|
+
'virtual_machines'
|
|
462
|
+
}
|
|
463
|
+
|
|
381
464
|
# LDAP Account details
|
|
382
465
|
LDAP_ACCOUNT_DETAILS_QUERY = {
|
|
383
466
|
'select': 'id,role_id,domain_id,name,type,type_l10n,dn'
|
|
@@ -470,6 +553,10 @@ REPLICATION_SESSION_FAILOVER_URL = 'https://{0}/api/rest/replication_session/{1}
|
|
|
470
553
|
REPLICATION_SESSION_REPROTECT_URL = 'https://{0}/api/rest/replication_session/{1}/reprotect'
|
|
471
554
|
MODIFY_REPLICATION_SESSION_URL = REPLICATION_SESSION_OBJECT_URL
|
|
472
555
|
|
|
556
|
+
# Replication Group endpoints
|
|
557
|
+
REPLICATION_GROUP_DETAILS_LIST_URL = 'https://{0}/api/rest/replication_group'
|
|
558
|
+
REPLICATION_GROUP_DETAILS_URL = 'https://{0}/api/rest/replication_group/{1}'
|
|
559
|
+
|
|
473
560
|
# Remote system endpoints
|
|
474
561
|
GET_REMOTE_SYSTEM_LIST_URL = 'https://{0}/api/rest/remote_system'
|
|
475
562
|
GET_REMOTE_SYSTEM_DETAILS_URL = 'https://{0}/api/rest/remote_system/{1}'
|
|
@@ -592,7 +679,9 @@ GET_JOB_DETAILS_URL = 'https://{0}/api/rest/job/{1}'
|
|
|
592
679
|
# vCenter endpoints
|
|
593
680
|
GET_VCENTER_LIST_URL = 'https://{0}/api/rest/vcenter'
|
|
594
681
|
GET_VCENTER_DETAILS_URL = 'https://{0}/api/rest/vcenter/{1}'
|
|
682
|
+
ADD_VCENTER_URL = GET_VCENTER_LIST_URL
|
|
595
683
|
MODIFY_VCENTER_URL = GET_VCENTER_DETAILS_URL
|
|
684
|
+
REMOVE_VCENTER_URL = GET_VCENTER_DETAILS_URL
|
|
596
685
|
|
|
597
686
|
# Appliance endpoints
|
|
598
687
|
GET_APPLIANCE_LIST_URL = 'https://{0}/api/rest/appliance'
|
|
@@ -667,3 +756,20 @@ GET_LDAP_ACCOUNT_DETAILS_URL = 'https://{0}/api/rest/ldap_account/{1}'
|
|
|
667
756
|
CREATE_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_LIST_URL
|
|
668
757
|
MODIFY_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_DETAILS_URL
|
|
669
758
|
DELETE_LDAP_ACCOUNT_URL = GET_LDAP_ACCOUNT_DETAILS_URL
|
|
759
|
+
|
|
760
|
+
# virtual volume endpoints
|
|
761
|
+
GET_VIRTUAL_VOLUME_LIST_URL = 'https://{0}/api/rest/virtual_volume'
|
|
762
|
+
GET_VIRTUAL_VOLUME_DETAILS_URL = 'https://{0}/api/rest/virtual_volume/{1}'
|
|
763
|
+
|
|
764
|
+
# Storage container endpoints
|
|
765
|
+
GET_STORAGE_CONTAINER_LIST_URL = 'https://{0}/api/rest/storage_container'
|
|
766
|
+
GET_STORAGE_CONTAINER_DETAILS_URL = 'https://{0}/api/rest/storage_container/{1}'
|
|
767
|
+
CREATE_STORAGE_CONTAINER_URL = GET_STORAGE_CONTAINER_LIST_URL
|
|
768
|
+
MODIFY_STORAGE_CONTAINER_URL = GET_STORAGE_CONTAINER_DETAILS_URL
|
|
769
|
+
DELETE_STORAGE_CONTAINER_URL = GET_STORAGE_CONTAINER_DETAILS_URL
|
|
770
|
+
|
|
771
|
+
# Storage container Destination endpoints
|
|
772
|
+
GET_STORAGE_CONTAINER_DESTINATION_LIST_URL = "https://{0}/api/rest/storage_container_destination"
|
|
773
|
+
GET_STORAGE_CONTAINER_DESTINATION_DETAILS_URL = "https://{0}/api/rest/storage_container_destination/{1}"
|
|
774
|
+
CREATE_STORAGE_CONTAINER_DESTINATION_URL = GET_STORAGE_CONTAINER_DESTINATION_LIST_URL
|
|
775
|
+
DELETE_STORAGE_CONTAINER_DESTINATION_URL = GET_STORAGE_CONTAINER_DESTINATION_DETAILS_URL
|
|
@@ -48,7 +48,7 @@ def get_logger(module_name, enable_log=False):
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def is_foot_hill_or_higher():
|
|
51
|
-
"""
|
|
51
|
+
"""Returns true if the array version is foot hill or higher.
|
|
52
52
|
|
|
53
53
|
:return: True if foot hill or higher
|
|
54
54
|
:rtype: bool
|
|
@@ -60,9 +60,21 @@ def is_foot_hill_or_higher():
|
|
|
60
60
|
return True
|
|
61
61
|
return False
|
|
62
62
|
|
|
63
|
+
def is_malka_or_higher():
|
|
64
|
+
"""Returns true if the array version is Malka or higher.
|
|
65
|
+
|
|
66
|
+
:return: True if array version is Malka or higher
|
|
67
|
+
:rtype: bool
|
|
68
|
+
"""
|
|
69
|
+
malka_version = '2.1.0.0'
|
|
70
|
+
array_version = provisioning_obj.get_array_version()
|
|
71
|
+
if array_version and (
|
|
72
|
+
parse_version(array_version[0:7]) >= parse_version(malka_version)):
|
|
73
|
+
return True
|
|
74
|
+
return False
|
|
63
75
|
|
|
64
76
|
def is_foot_hill_prime_or_higher():
|
|
65
|
-
"""
|
|
77
|
+
"""Returns true if the array version is foothill prime or higher.
|
|
66
78
|
|
|
67
79
|
:return: True if foothill prime or higher
|
|
68
80
|
:rtype: bool
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 1.
|
|
1
|
+
Metadata-Version: 1.1
|
|
2
2
|
Name: PyPowerStore
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0.0
|
|
4
4
|
Summary: Python Library for Dell PowerStore
|
|
5
5
|
Home-page: https://github.com/dell/python-powerstore
|
|
6
6
|
Author: Ansible Team at Dell
|
|
@@ -8,3 +8,4 @@ Author-email: ansible.team@dell.com
|
|
|
8
8
|
License: UNKNOWN
|
|
9
9
|
Description: UNKNOWN
|
|
10
10
|
Platform: UNKNOWN
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -10,7 +10,7 @@ except ImportError:
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
setup(name='PyPowerStore',
|
|
13
|
-
version='
|
|
13
|
+
version='2.0.0.0',
|
|
14
14
|
description='Python Library for Dell PowerStore',
|
|
15
15
|
author='Ansible Team at Dell',
|
|
16
16
|
author_email='ansible.team@dell.com',
|
|
@@ -18,6 +18,8 @@ setup(name='PyPowerStore',
|
|
|
18
18
|
'urllib3>=1.26.7',
|
|
19
19
|
'requests>=2.23.0'
|
|
20
20
|
],
|
|
21
|
+
license_files = ('LICENSE',),
|
|
22
|
+
classifiers=['License :: OSI Approved :: Apache Software License'],
|
|
21
23
|
url='https://github.com/dell/python-powerstore',
|
|
22
24
|
packages=['PyPowerStore', 'PyPowerStore.utils'],
|
|
23
25
|
)
|
PyPowerStore-1.9.0.0/LICENSE
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
Apache License
|
|
2
|
-
Version 2.0, January 2004
|
|
3
|
-
http://www.apache.org/licenses/
|
|
4
|
-
|
|
5
|
-
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
-
|
|
7
|
-
1. Definitions.
|
|
8
|
-
|
|
9
|
-
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
-
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
-
|
|
12
|
-
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
-
the copyright owner that is granting the License.
|
|
14
|
-
|
|
15
|
-
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
-
other entities that control, are controlled by, or are under common
|
|
17
|
-
control with that entity. For the purposes of this definition,
|
|
18
|
-
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
-
direction or management of such entity, whether by contract or
|
|
20
|
-
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
-
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
-
|
|
23
|
-
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
-
exercising permissions granted by this License.
|
|
25
|
-
|
|
26
|
-
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
-
including but not limited to software source code, documentation
|
|
28
|
-
source, and configuration files.
|
|
29
|
-
|
|
30
|
-
"Object" form shall mean any form resulting from mechanical
|
|
31
|
-
transformation or translation of a Source form, including but
|
|
32
|
-
not limited to compiled object code, generated documentation,
|
|
33
|
-
and conversions to other media types.
|
|
34
|
-
|
|
35
|
-
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
-
Object form, made available under the License, as indicated by a
|
|
37
|
-
copyright notice that is included in or attached to the work
|
|
38
|
-
(an example is provided in the Appendix below).
|
|
39
|
-
|
|
40
|
-
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
-
form, that is based on (or derived from) the Work and for which the
|
|
42
|
-
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
-
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
-
of this License, Derivative Works shall not include works that remain
|
|
45
|
-
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
-
the Work and Derivative Works thereof.
|
|
47
|
-
|
|
48
|
-
"Contribution" shall mean any work of authorship, including
|
|
49
|
-
the original version of the Work and any modifications or additions
|
|
50
|
-
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
-
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
-
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
-
means any form of electronic, verbal, or written communication sent
|
|
55
|
-
to the Licensor or its representatives, including but not limited to
|
|
56
|
-
communication on electronic mailing lists, source code control systems,
|
|
57
|
-
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
-
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
-
excluding communication that is conspicuously marked or otherwise
|
|
60
|
-
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
-
|
|
62
|
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
-
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
-
subsequently incorporated within the Work.
|
|
65
|
-
|
|
66
|
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
-
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
-
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
-
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
-
Work and such Derivative Works in Source or Object form.
|
|
72
|
-
|
|
73
|
-
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
-
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
-
(except as stated in this section) patent license to make, have made,
|
|
77
|
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
-
where such license applies only to those patent claims licensable
|
|
79
|
-
by such Contributor that are necessarily infringed by their
|
|
80
|
-
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
-
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
-
institute patent litigation against any entity (including a
|
|
83
|
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
-
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
-
or contributory patent infringement, then any patent licenses
|
|
86
|
-
granted to You under this License for that Work shall terminate
|
|
87
|
-
as of the date such litigation is filed.
|
|
88
|
-
|
|
89
|
-
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
-
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
-
modifications, and in Source or Object form, provided that You
|
|
92
|
-
meet the following conditions:
|
|
93
|
-
|
|
94
|
-
(a) You must give any other recipients of the Work or
|
|
95
|
-
Derivative Works a copy of this License; and
|
|
96
|
-
|
|
97
|
-
(b) You must cause any modified files to carry prominent notices
|
|
98
|
-
stating that You changed the files; and
|
|
99
|
-
|
|
100
|
-
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
-
that You distribute, all copyright, patent, trademark, and
|
|
102
|
-
attribution notices from the Source form of the Work,
|
|
103
|
-
excluding those notices that do not pertain to any part of
|
|
104
|
-
the Derivative Works; and
|
|
105
|
-
|
|
106
|
-
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
-
distribution, then any Derivative Works that You distribute must
|
|
108
|
-
include a readable copy of the attribution notices contained
|
|
109
|
-
within such NOTICE file, excluding those notices that do not
|
|
110
|
-
pertain to any part of the Derivative Works, in at least one
|
|
111
|
-
of the following places: within a NOTICE text file distributed
|
|
112
|
-
as part of the Derivative Works; within the Source form or
|
|
113
|
-
documentation, if provided along with the Derivative Works; or,
|
|
114
|
-
within a display generated by the Derivative Works, if and
|
|
115
|
-
wherever such third-party notices normally appear. The contents
|
|
116
|
-
of the NOTICE file are for informational purposes only and
|
|
117
|
-
do not modify the License. You may add Your own attribution
|
|
118
|
-
notices within Derivative Works that You distribute, alongside
|
|
119
|
-
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
-
that such additional attribution notices cannot be construed
|
|
121
|
-
as modifying the License.
|
|
122
|
-
|
|
123
|
-
You may add Your own copyright statement to Your modifications and
|
|
124
|
-
may provide additional or different license terms and conditions
|
|
125
|
-
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
-
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
-
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
-
the conditions stated in this License.
|
|
129
|
-
|
|
130
|
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
-
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
-
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
-
this License, without any additional terms or conditions.
|
|
134
|
-
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
-
the terms of any separate license agreement you may have executed
|
|
136
|
-
with Licensor regarding such Contributions.
|
|
137
|
-
|
|
138
|
-
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
-
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
-
except as required for reasonable and customary use in describing the
|
|
141
|
-
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
-
|
|
143
|
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
-
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
-
implied, including, without limitation, any warranties or conditions
|
|
148
|
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
-
appropriateness of using or redistributing the Work and assume any
|
|
151
|
-
risks associated with Your exercise of permissions under this License.
|
|
152
|
-
|
|
153
|
-
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
-
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
-
unless required by applicable law (such as deliberate and grossly
|
|
156
|
-
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
-
liable to You for damages, including any direct, indirect, special,
|
|
158
|
-
incidental, or consequential damages of any character arising as a
|
|
159
|
-
result of this License or out of the use or inability to use the
|
|
160
|
-
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
-
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
-
other commercial damages or losses), even if such Contributor
|
|
163
|
-
has been advised of the possibility of such damages.
|
|
164
|
-
|
|
165
|
-
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
-
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
-
or other liability obligations and/or rights consistent with this
|
|
169
|
-
License. However, in accepting such obligations, You may act only
|
|
170
|
-
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
-
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
-
defend, and hold each Contributor harmless for any liability
|
|
173
|
-
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
-
of your accepting any such warranty or additional liability.
|
|
175
|
-
|
|
176
|
-
END OF TERMS AND CONDITIONS
|
|
177
|
-
|
|
178
|
-
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
-
|
|
180
|
-
To apply the Apache License to your work, attach the following
|
|
181
|
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
-
replaced with your own identifying information. (Don't include
|
|
183
|
-
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
-
comment syntax for the file format. We also recommend that a
|
|
185
|
-
file or class name and description of purpose be included on the
|
|
186
|
-
same "printed page" as the copyright notice for easier
|
|
187
|
-
identification within third-party archives.
|
|
188
|
-
|
|
189
|
-
Copyright [yyyy] [name of copyright owner]
|
|
190
|
-
|
|
191
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
-
you may not use this file except in compliance with the License.
|
|
193
|
-
You may obtain a copy of the License at
|
|
194
|
-
|
|
195
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
-
|
|
197
|
-
Unless required by applicable law or agreed to in writing, software
|
|
198
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
-
See the License for the specific language governing permissions and
|
|
201
|
-
limitations under the License.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|