Skip to content

Commit 5fe555d

Browse files
authored
Merge pull request #5 from dell/release_1.4.0
Release version 1.4.0 for PyPowerFlex
2 parents 29b26e0 + b14bbd9 commit 5fe555d

File tree

7 files changed

+411
-6
lines changed

7 files changed

+411
-6
lines changed

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# PyPowerFlex Change Log
22

3+
## Version 1.4.0 - released on 28/06/22
4+
- Added configuration operations includes adding/removing of standby MDM, change cluster ownership, change cluster mode, modify performance profile, rename MDM, modify MDM's virtual interface and getting details of MDM cluster entities.
5+
36
## Version 1.3.0 - released on 25/03/22
47
- Added block provisioning operations includes managing protection domain and getting high level facts about this entity.
58

PyPowerFlex/base_client.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,27 @@ def send_post_request(self, url, params=None, **url_params):
8484
self._logout()
8585
return r, response
8686

87+
def send_mdm_cluster_post_request(self, url, params=None, **url_params):
88+
if params is None:
89+
params = dict()
90+
response = None
91+
self._login()
92+
request_url = self.base_url + url.format(**url_params)
93+
r = requests.post(request_url,
94+
auth=(
95+
self.configuration.username,
96+
self.token.get()
97+
),
98+
headers=self.headers,
99+
data=utils.prepare_params(params),
100+
verify=self.verify_certificate,
101+
timeout=self.configuration.timeout)
102+
103+
if r.content != b'':
104+
response = r.json()
105+
self._logout()
106+
return r, response
107+
87108
def _login(self):
88109
request_url = self.base_url + '/login'
89110

@@ -125,6 +146,8 @@ class EntityRequest(Request):
125146
base_entity_url = '/instances/{entity}::{entity_id}'
126147
base_entity_list_or_create_url = '/types/{entity}/instances'
127148
base_relationship_url = base_entity_url + '/relationships/{related}'
149+
base_object_url = '/instances/{entity}/action/{action}'
150+
query_mdm_cluster_url = '/instances/{entity}/queryMdmCluster'
128151
entity_name = None
129152

130153
@property
@@ -196,7 +219,8 @@ def get(self, entity_id=None, filter_fields=None, fields=None):
196219
response = utils.query_response_fields(response, fields)
197220
return response
198221

199-
def get_related(self, entity_id, related, filter_fields=None, fields=None):
222+
def get_related(self, entity_id, related, filter_fields=None,
223+
fields=None):
200224
url_params = dict(
201225
entity=self.entity,
202226
entity_id=entity_id,

PyPowerFlex/objects/sdc.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ def set_performance_profile(self, sdc_id, perf_profile):
7272
perfProfile=perf_profile
7373
)
7474

75-
r, response = self.send_post_request(self.base_action_url, action, sdc_id, params)
75+
r, response = self.send_post_request(self.base_action_url, action,
76+
sdc_id, params)
7677

7778
if r.status_code != requests.codes.ok:
7879
msg = ('Failed to set Performance Profile on '
@@ -83,4 +84,4 @@ def set_performance_profile(self, sdc_id, perf_profile):
8384
LOG.error(msg)
8485
raise exceptions.PowerFlexClientException(msg)
8586

86-
return self.get(entity_id=sdc_id)
87+
return self.get(entity_id=sdc_id)

PyPowerFlex/objects/system.py

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,263 @@ def snapshot_volumes(self,
154154
raise exceptions.PowerFlexClientException(msg)
155155

156156
return response
157+
158+
def add_standby_mdm(self, mdm_ips, role, management_ips=None, port=None,
159+
mdm_name=None, allow_multiple_ips=None, clean=None,
160+
virtual_interface=None):
161+
"""
162+
Add a standby MDM to the system.
163+
:param mdm_ips: List of ip addresses assigned to new MDM. It can
164+
contain IPv4 addresses.
165+
:type mdm_ips: list[str]
166+
:param role: Role of the new MDM.
167+
:type role: str
168+
:param management_ips: List of IP addresses used to manage the MDM.
169+
It can contain IPv4 addresses.
170+
:type management_ips: list[str]
171+
:param port: Port of new MDM. Default: 9011
172+
:type port: str
173+
:param mdm_name: Name of the new MDM.
174+
:type mdm_name: str
175+
:param allow_multiple_ips: Allow the added node to have a different
176+
number of IPs from the primary node.
177+
:type allow_multiple_ips: str
178+
:param clean: Clean a previous MDM configuration.
179+
:type clean: str
180+
:param virtual_interface: List of NIC interfaces that will be used
181+
for virtual IP address.
182+
:type virtual_interface: list[str]
183+
:return: ID of new standby MDM.
184+
:rtype: dict
185+
"""
186+
action = 'addStandbyMdm'
187+
params = dict(
188+
ips=mdm_ips,
189+
role=role,
190+
managementIps=management_ips,
191+
name=mdm_name,
192+
port=port,
193+
allowAsymmetricIps=allow_multiple_ips,
194+
forceClean=clean,
195+
virtIpIntfs=virtual_interface
196+
)
197+
198+
r, response = self.send_post_request(self.base_object_url,
199+
action=action,
200+
entity=self.entity,
201+
params=params)
202+
if r.status_code != requests.codes.ok:
203+
msg = ('Failed to add standBy MDM on PowerFlex {entity}. '
204+
'Error: {response}'.format(entity=self.entity,
205+
response=response))
206+
LOG.error(msg)
207+
raise exceptions.PowerFlexClientException(msg)
208+
209+
return response
210+
211+
def remove_standby_mdm(self, mdm_id):
212+
"""
213+
Remove a standby MDM from the system.
214+
:param mdm_id: ID of MDM to be removed.
215+
:type mdm_id: str
216+
:return: None
217+
"""
218+
action = 'removeStandbyMdm'
219+
params = dict(
220+
id=mdm_id
221+
)
222+
223+
r, response = self.send_mdm_cluster_post_request(self.base_object_url,
224+
action=action,
225+
entity=self.entity,
226+
params=params)
227+
if r.status_code != requests.codes.ok and response is not None:
228+
msg = ('Failed to remove standBy MDM from PowerFlex {entity}. '
229+
'Error: {response}.'.format(entity=self.entity,
230+
response=response))
231+
LOG.error(msg)
232+
raise exceptions.PowerFlexClientException(msg)
233+
234+
return True
235+
236+
def get_mdm_cluster_details(self):
237+
"""
238+
Get the MDM cluster details
239+
:return: MDM cluster details
240+
:rtype: dict
241+
"""
242+
243+
r, response = self.send_post_request(self.query_mdm_cluster_url,
244+
entity=self.entity)
245+
if r.status_code != requests.codes.ok:
246+
msg = ('Failed to get MDM cluster details on PowerFlex {entity}. '
247+
'Error: {response}'.format(entity=self.entity,
248+
response=response))
249+
LOG.error(msg)
250+
raise exceptions.PowerFlexClientException(msg)
251+
252+
return response
253+
254+
def change_mdm_ownership(self, mdm_id):
255+
"""
256+
Change MDM cluster ownership from current master MDM to different MDM.
257+
258+
:param mdm_id: ID of New Manager MDM
259+
:type mdm_id: str
260+
:return: None
261+
:rtype: dict
262+
"""
263+
action = 'changeMdmOwnership'
264+
params = dict(
265+
id=mdm_id
266+
)
267+
268+
r, response = self.send_post_request(self.base_object_url,
269+
action=action,
270+
entity=self.entity,
271+
params=params)
272+
if r.status_code != requests.codes.ok:
273+
msg = ('Failed to change ownership on PowerFlex {entity}. '
274+
'Error: {response}'.format(entity=self.entity,
275+
response=response))
276+
LOG.error(msg)
277+
raise exceptions.PowerFlexClientException(msg)
278+
279+
def set_cluster_mdm_performance_profile(self, performance_profile):
280+
"""
281+
Set the Cluster MDMs performance profile.
282+
283+
:param performance_profile: Define the performance profile of MDMs.
284+
:type performance_profile: str
285+
:return: None
286+
:rtype: dict
287+
"""
288+
action = 'setMdmPerformanceParameters'
289+
params = dict(
290+
perfProfile=performance_profile
291+
)
292+
293+
r, response = self.send_post_request(self.base_object_url,
294+
action=action,
295+
entity=self.entity,
296+
params=params)
297+
if r.status_code != requests.codes.ok:
298+
msg = ('Failed to set performance profile of MDMs on PowerFlex '
299+
'{entity}. Error: {response}'.format(entity=self.entity,
300+
response=response))
301+
LOG.error(msg)
302+
raise exceptions.PowerFlexClientException(msg)
303+
304+
return response
305+
306+
def rename_mdm(self, mdm_id, mdm_new_name):
307+
"""
308+
Set the Cluster MDMs performance profile.
309+
310+
:param mdm_id: ID of MDM.
311+
:type mdm_id: str
312+
:param mdm_new_name: new name of MDM.
313+
:type mdm_new_name: str
314+
:return: None
315+
:rtype: dict
316+
"""
317+
action = 'renameMdm'
318+
params = dict(
319+
id=mdm_id,
320+
newName=mdm_new_name
321+
)
322+
323+
r, response = self.send_post_request(self.base_object_url,
324+
action=action,
325+
entity=self.entity,
326+
params=params)
327+
if r.status_code != requests.codes.ok:
328+
msg = ('Failed to rename the MDM on PowerFlex {entity}. Error: '
329+
'{response}'.format(entity=self.entity, response=response))
330+
LOG.error(msg)
331+
raise exceptions.PowerFlexClientException(msg)
332+
333+
return response
334+
335+
def modify_virtual_ip_interface(self, mdm_id, virtual_ip_interfaces=None,
336+
clear_interfaces=None):
337+
"""
338+
Set the Cluster MDMs performance profile.
339+
340+
:param mdm_id: ID of MDM.
341+
:type mdm_id: str
342+
:param virtual_ip_interfaces: List of interface names to be used for
343+
the MDM virtual IPs.
344+
:type virtual_ip_interfaces: list[str]
345+
:param clear_interfaces: Clear all virtual IP interfaces.
346+
:type mdm_id: str
347+
:return: None
348+
:rtype: dict
349+
"""
350+
action = 'modifyVirtualIpInterfaces'
351+
if virtual_ip_interfaces is not None:
352+
params = dict(
353+
id=mdm_id,
354+
virtIpIntfs=virtual_ip_interfaces
355+
)
356+
else:
357+
params = dict(
358+
id=mdm_id,
359+
clear=clear_interfaces
360+
)
361+
362+
r, response = self.send_post_request(self.base_object_url,
363+
action=action,
364+
entity=self.entity,
365+
params=params)
366+
if r.status_code != requests.codes.ok:
367+
msg = ('Failed to modify virtual IP interface on PowerFlex '
368+
'{entity}. Error: {response}'.format(entity=self.entity,
369+
response=response))
370+
LOG.error(msg)
371+
raise exceptions.PowerFlexClientException(msg)
372+
373+
return response
374+
375+
def switch_cluster_mode(self, cluster_mode, add_secondary=None,
376+
remove_secondary=None, add_tb=None, remove_tb=None):
377+
"""
378+
Switch cluster mode.
379+
380+
:param cluster_mode: New mode of MDM cluster
381+
:type cluster_mode: str
382+
:param add_secondary: List of secondary MDM IDs that will be part of
383+
the cluster. A maximum of two IDs are allowed.
384+
:type add_secondary: list[str]
385+
:param remove_secondary: List of secondary MDM IDs that will be removed
386+
from the cluster.
387+
:type remove_secondary: list[str]
388+
:param add_tb: List of TieBreaker MDM IDs that will be part of the
389+
cluster.
390+
:type add_tb: list[str]
391+
:param remove_tb: List of TieBreaker MDM IDs that will be removed
392+
from the cluster.
393+
:type remove_tb: list[str]
394+
:return: None
395+
"""
396+
action = 'switchClusterMode'
397+
params = dict(
398+
mode=cluster_mode,
399+
addSlaveMdmIdList=add_secondary,
400+
addTBIdList=add_tb,
401+
removeSlaveMdmIdList=remove_secondary,
402+
removeTBIdList=remove_tb
403+
)
404+
405+
r, response = self.send_mdm_cluster_post_request(self.base_object_url,
406+
action=action,
407+
entity=self.entity,
408+
params=params)
409+
if r.status_code != requests.codes.ok and response is not None:
410+
msg = ('Failed to switch MDM cluster mode PowerFlex {entity}. '
411+
'Error: {response}.'.format(entity=self.entity,
412+
response=response))
413+
LOG.error(msg)
414+
raise exceptions.PowerFlexClientException(msg)
415+
416+
return True

PyPowerFlex/objects/volume.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ def set_retention_period(self, snap_id, retention_period):
455455
:type retention_period: str
456456
:return: dict
457457
"""
458-
458+
459459
action = 'setSnapshotSecurity'
460460

461461
params = dict(
@@ -478,7 +478,6 @@ def set_retention_period(self, snap_id, retention_period):
478478

479479
return self.get(entity_id=snap_id)
480480

481-
482481
def set_volume_access_mode_limit(self, volume_id, access_mode_limit):
483482
"""
484483
Set the highest mapping access mode allowed for a volume.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
setup(
1919
name='PyPowerFlex',
20-
version='1.3.0',
20+
version='1.4.0',
2121
description='Python library for Dell PowerFlex',
2222
author='Ansible Team at Dell',
2323
author_email='[email protected]',

0 commit comments

Comments
 (0)