Skip to content

Commit e6c7f03

Browse files
committed
Removed the FlexGroup support since it wasn't complete.
1 parent cfbda2f commit e6c7f03

File tree

2 files changed

+5
-160
lines changed

2 files changed

+5
-160
lines changed

Management-Utilities/auto_create_sm_relationships/README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ This script is used to ensure that all your volumes, in all your FSxN file syste
1010
- If it is set to false, then it checks from the AWS side to see if there is a "protect_volume" tag set to "skip".
1111
- If there isn't one, then it uses the ONTAP SnapMirror API to create the SnapMirror relationship. This API will create a destination volume if it does not already exist.
1212

13-
While there is some logic in the script to attempt to handle FlexGroup volumes, there are issues with it, so that part of the script has been disabled. The issues I encountered trying to support FlexGroups:
14-
**NOTE:** All of the below is based on ONTAP version 9.13.1.
15-
- The SnapMirror API does not work with FlexGroups (even though the documentation implies that it does). Because of this I attempted to use the CLI "pass-through" API to create the SnapMirror relationship the "old fashioned way" by:
16-
- Create the destination volume if it doesn't already exist.
17-
- Create the SnapMirror relationship.
18-
- Initialize the SnapMirror relationship.
19-
- When creating the destination volume, it just creates with the default parameters, so it might not match the configuration of the source volume. Specially, the number of constituents could be different.
20-
- The "snapmirror.destinations.is_ontap" field is not maintained by ONTAP for FlexGroup volumes. So, the script will attempt to create a SM relationship every time it is run. It will fail, and probably not harm anything, but it isn't clean. A "To Do" is the leverage the SnapMirror API to obtain the list of SnapMirror relationships and figure out if the volume already has a relationship reviewing that list. Note that "snapmirror list-destinations" also doesn't work for FlexGroup volumes.
13+
**NOTE:** This script only creates SnapMirror relationships for FlexVol volumes. It does not create SnapMirror relationships for FlexGroup volumes.
2114

2215
## Set Up
2316
There are a few things you need to do in order to get this script to run properly:

Management-Utilities/auto_create_sm_relationships/auto_create_sm_relationships.py

Lines changed: 4 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -161,41 +161,6 @@ def getVolumeARN(awsVolumes, volumeUUID):
161161
logger.warning(f'Failed to get ARN for volume with UUID={volumeUUID}.')
162162
return("")
163163

164-
################################################################################
165-
# This function waits for an ONTAP job to complete.
166-
# NOTE: This function is only needed for creating SM relationships for
167-
# FlexGroup volumes. It returns 'True' if the job completed successfully,
168-
# otherwise it returns False.
169-
################################################################################
170-
def waitForJobToComplete(fsxnIp, headers, jobUUID):
171-
172-
global logger
173-
174-
count = 0
175-
logger.debug(f'Waiting for {jobUUID} to finish.')
176-
while count < 10:
177-
try:
178-
endpoint = f'https://{fsxnIp}/api/cluster/jobs/{jobUUID}'
179-
logger.debug(f'Trying {endpoint}.')
180-
response = http.request('GET', endpoint, headers=headers, timeout=5.0)
181-
if response.status == 200:
182-
data = json.loads(response.data)
183-
jobState = data['state'].lower()
184-
if jobState == "success":
185-
return True
186-
if jobState in ["failure", "error", "quit", "dead", "unknown", "dormant"]:
187-
return False
188-
else:
189-
logger.error(f'API call to {endpoint} failed. HTTP status code: {response.status}.')
190-
return False
191-
except Exception as err:
192-
logger.critical(f'Failed to issue API against {fsxnIp}. Endpoint={endpoint}, The error messages received: "{err}".')
193-
return False
194-
time.sleep(2)
195-
count += 1
196-
logger.error(f'Timed out waiting for a job with a UUID of "{jobUUID}" to complete on {fsxnIp}.')
197-
return False
198-
199164
################################################################################
200165
# This function is used to obtain the username and password from AWS's Secrets
201166
# Manager for the fsxnId passed in. It returns empty strings if it can't
@@ -215,128 +180,15 @@ def getCredentials(fsxnId):
215180
return ("", "")
216181

217182
################################################################################
218-
# This function is used to attempt to set up a snapmirror relationship for a
219-
# flexgroup volume. Since I was unable to get the regular API to create
220-
# SnapMirror relationshipsto work, at least when dealing with flexgroups, this
221-
# function does it the old fashioned way of creating a DP volume if it doesn't
222-
# already exist. creating the SM relationship, then initializing it.
223-
#
224-
# It assumes that the destination SVM exist and has already been peered.
183+
# Since the ONTAP SnapMirror API does not work with FlexGroups, this function
184+
# was created as a place holder for coming up with an alternative way to
185+
# protect them.
225186
################################################################################
226187
def protectFlexGroup(fsxId, svmName, volumeName):
227188

228189
global logger, http, numSnapMirrorRelationships
229190

230-
logger.info(f'Unfortunately, creating snapmirror relationships for FlexGroups has not be thoroughly tested and therefore is disabled.')
231-
return
232-
#
233-
# find the partner fsx cluster, and svmName
234-
partnerIp = ""
235-
for fsx in partnerTable:
236-
if fsx['fsxId'] == fsxId and fsx['svmName'] == svmName:
237-
partnerIp = fsx['partnerFsxnIp']
238-
partnerSvmName = fsx['partnerSvmName']
239-
partnerSvmSourceName = fsx['partnerSvmSourceName']
240-
break
241-
242-
if partnerIp == "":
243-
logger.error(f'No partner found for fsxId: {fsxId} and svmName: {svmName}.')
244-
return
245-
246-
(username, password) = getCredentials(fsxId)
247-
if username == "" or password == "":
248-
logger.error(f'No credentials for FSxN ID: {fsxId}.')
249-
return
250-
251-
auth = urllib3.make_headers(basic_auth=f'{username}:{password}')
252-
headers = { **auth }
253-
#
254-
# Check to see if the destination volume already exist.
255-
try:
256-
endpoint = f'https://{partnerIp}/api/storage/volumes?name={volumeName}{destinationVolumeSuffix}&svm.name={partnerSvmName}&fields=type,style'
257-
logger.debug(f'Trying {endpoint}.')
258-
response = http.request('GET', endpoint, headers=headers, timeout=5.0)
259-
if response.status == 200:
260-
data = json.loads(response.data)
261-
else:
262-
logger.error(f'API call to {endpoint} failed. HTTP status code: {response.status}.')
263-
return
264-
except Exception as err:
265-
logger.critical(f'Failed to issue API against {partnerIp}. Cluster could be down. The error messages received: "{err}".')
266-
return
267-
268-
if data['num_records'] < 1: # If the number of records is 0, then the volume doesn't exist, so try to create it,
269-
try:
270-
endpoint = f'https://{partnerIp}/api/storage/volumes'
271-
data = {
272-
"name": f'{volumeName}{destinationVolumeSuffix}',
273-
"svm": partnerSvmName,
274-
"aggregates": ["aggr1"],
275-
"style": "flexgroup",
276-
"type": "dp"
277-
}
278-
logger.debug(f'Trying {endpoint} with {data}.')
279-
if not dryRun:
280-
response = http.request('POST', endpoint, headers=headers, body=json.dumps(data), timeout=5.0)
281-
if response.status >= 200 or response.status <= 299:
282-
data = json.loads(response.data)
283-
jobUUID = data['job']['uuid']
284-
if waitForJobToComplete(partnerIp, headers, jobUUID):
285-
logger.error(f'Failed to create destination flexgroup volume {partnerIp}::{partnerSvmName}:{volumeName}{destinationVolumeSuffix}.')
286-
return
287-
else:
288-
logger.error(f'API call to {endpoint} failed. HTTP status code: {response.status}.')
289-
return
290-
except Exception as err:
291-
logger.critical(f'Failed to issue API against {partnerIp}. Cluster could be down. The error messages received: "{err}".')
292-
return
293-
else: # The volume already exist. Make sure it is the correct type and style.
294-
if data['records'][0]['type'].lower() != "dp" or data['records'][0]['style'].lower() != "flexgroup":
295-
logger.error(f'Destination volume "{partnerIp}::{partnerSvmName}:{volumeName}{destinationVolumeSuffix}" already exist but is not of type "DP", or is not a flexgroup type volume.')
296-
return
297-
#
298-
# At this point we have the destination volume. Time to create the snapmirror relationship.
299-
try:
300-
endpoint = f'https://{partnerIp}/api/private/cli/snapmirror'
301-
data = {
302-
"source-path": f'{partnerSvmSourceName}:{volumeName}',
303-
"destination-path": f'{partnerSvmName}:{volumeName}{destinationVolumeSuffix}'
304-
}
305-
logger.debug(f'Trying {endpoint} with {data}.')
306-
if not dryRun:
307-
response = http.request('POST', endpoint, headers=headers, body=json.dumps(data), timeout=5.0)
308-
if response.status >= 200 or response.status <= 299:
309-
data = json.loads(response.data)
310-
if data['cli_output'][0:len('Operation succeeded:')] != 'Operation succeeded:':
311-
logger.error(f'Failed to create the SnapMirror relationship for volume {partnerIp}::{svmName}:{volumeName}. Message={data["cli_output"]}')
312-
return
313-
else:
314-
logger.error(f'API call to {endpoint} failed. HTTP status code: {response.status}.')
315-
return
316-
except Exception as err:
317-
logger.critical(f'Failed to issue API against {partnerIp}. Cluster could be down. The error messages received: "{err}".')
318-
return
319-
#
320-
# Last step is to do the initialize.
321-
try:
322-
endpoint = f'https://{partnerIp}/api/private/cli/snapmirror/initialize'
323-
data = {
324-
"source-path": f'{partnerSvmSourceName}:{volumeName}',
325-
"destination-path": f'{partnerSvmName}:{volumeName}{destinationVolumeSuffix}'
326-
}
327-
logger.debug(f'Trying {endpoint} with {data}.')
328-
if not dryRun:
329-
response = http.request('POST', endpoint, headers=headers, body=json.dumps(data), timeout=5.0)
330-
if response.status < 200 or response.status > 299:
331-
logger.error(f'API call to {endpoint} failed. HTTP status code: {response.status}.')
332-
return
333-
logger.info(f'Path {fsxId}::{svmName}:{volumeName} is being SnapMirrored to {partnerIp}::{partnerSvmName}:{volumeName}{destinationVolumeSuffix}')
334-
else:
335-
logger.info(f'Path {fsxId}::{svmName}:{volumeName} would have been SnapMirrored to {partnerIp}::{partnerSvmName}:{volumeName}{destinationVolumeSuffix}')
336-
numSnapMirrorRelationships += 1 # pylint: disable=E0602
337-
except Exception as err:
338-
logger.critical(f'Failed to issue API against {partnerIp}. Cluster could be down. The error messages received: "{err}".')
339-
return
191+
logger.warning(f'Unfortunately, creating snapmirror relationships for FlexGroups is currently not supported.')
340192
return
341193

342194
################################################################################

0 commit comments

Comments
 (0)