1- ## The library contain common functions which are used for both single and group VM backup and restore.
1+ """ The library contain common functions which are used for both single and group VM backup and restore. """
22
3- ## The script can be run with Python 3.5 or higher version.
3+ ## The script can be run with Python 3.6 or higher version.
44
5- ## The script requires 'requests' library to make the API calls. The library can be installed using the command: pip install requests.
5+ ## The script requires 'requests' library to make the API calls.
66
77import json
88import os
1212
1313headers = {"Content-Type" : "application/vnd.netbackup+json;version=4.0" }
1414
15- # Get the base netbackup url
15+ # Get the base NetBackup url
1616def get_nbu_base_url (host , port ):
17+ """ This function return NetBackup base url """
1718 port = f":{ str (port )} " if port else ''
1819 baseurl = f"https://{ host } { port } /netbackup/"
1920 return baseurl
2021
21- # Login to the netbackup and get the authorization token
22+ # Login to the NetBackup and get the authorization token
2223def get_authenticate_token (baseurl , username , password ):
24+ """ This function return token of NB master server """
2325 creds = {'userName' :username , 'password' :password }
24- url = baseurl + ' login'
26+ url = f" { baseurl } login"
2527 status_code , response_text = rest_request ('POST' , url , headers , data = creds )
2628 validate_response (status_code , 201 , response_text )
2729 token = response_text ['token' ]
2830 return token
2931
3032# Add vCenter credential
3133def add_vcenter_credential (baseurl , token , vcenter_server , vcenter_username , vcenter_password , vcenter_port , vcenter_server_type ):
32- print (f"Add the vcenter credential:[{ vcenter_server } ]" )
33- headers .update ({'Authorization' : token })
34- url = baseurl + 'config/servers/vmservers'
35- payload = {'serverName' :vcenter_server , 'vmType' :vcenter_server_type , 'userId' :vcenter_username , 'password' :vcenter_password , 'port' :vcenter_port }
34+ """ This function add the vCenter into NBU master server """
35+ print (f"Add the vCenter credential:[{ vcenter_server } ]" )
36+ headers .update ({'Authorization' : token })
37+ url = f"{ baseurl } config/servers/vmservers"
38+ payload = {'serverName' :vcenter_server , 'vmType' :vcenter_server_type , 'userId' :vcenter_username ,\
39+ 'password' :vcenter_password , 'port' :vcenter_port }
3640 status_code , response_text = rest_request ('POST' , url , headers , data = payload )
3741 validate_response (status_code , 201 , response_text )
38- print (f"Vcenter credentials added successfully:[{ vcenter_server } ]" )
42+ print (f"vCenter credentials added successfully:[{ vcenter_server } ]" )
3943
4044# Get Vmware server discovery status
4145def get_vmware_discovery_status (baseurl , token , workload_type , vcenter_server ):
46+ """ This function return the discovery status of vCenter server """
4247 headers .update ({'Authorization' : token })
43- url = baseurl + "admin/discovery/workloads/" + workload_type + "/status?filter=serverName eq '" + vcenter_server + "'"
48+ url = f"{ baseurl } admin/discovery/workloads/{ workload_type } /status?" \
49+ f"filter=serverName eq '{ vcenter_server } '"
4450 status_code , response_text = rest_request ('GET' , url , headers )
4551 validate_response (status_code , 200 , response_text )
4652 discovery_status = response_text ['data' ][0 ]['attributes' ]['discoveryStatus' ]
4753 return discovery_status
4854
49- # Get Vmware server discovery status
55+ # Verify Vmware server discovery status
5056def verify_vmware_discovery_status (baseurl , token , workload_type , vcenter_server , timeout = 600 ):
51- print (f"Wait for Vcenter Discovery :[{ vcenter_server } ]" )
57+ """ This function verify the 'SUCESS' discovery status of vCenter """
58+ print (f"Wait for vCenter Discovery :[{ vcenter_server } ]" )
5259 discovery_status = ''
5360 end_time = time .time () + timeout
5461 while time .time () < end_time :
5562 time .sleep (30 )
5663 discovery_status = get_vmware_discovery_status (baseurl , token , workload_type , vcenter_server )
5764 if discovery_status == 'SUCCESS' :
58- print (f"Vcenter added successfully:[{ vcenter_server } ]" )
65+ print (f"vCenter added successfully:[{ vcenter_server } ]" )
5966 break
6067 else :
61- print (f"Failed to verify VCenter :[{ vcenter_server } ] discovery with status:[{ discovery_status } ]" )
68+ print (f"Failed to verify vCenter :[{ vcenter_server } ] discovery with status:[{ discovery_status } ]" )
6269 sys .exit (1 )
63- print (f"Vcenter discovery successful:[{ vcenter_server } ] with status:[{ discovery_status } ]" )
70+ print (f"vCenter discovery successful:[{ vcenter_server } ] with status:[{ discovery_status } ]" )
6471
6572# Get asset info
6673def get_asset_info (baseurl , token , workload_type , client ):
74+ """ This function return the asset info """
6775 print (f"Get client asset info:[{ client } ]" )
6876 headers .update ({'Authorization' : token })
69- url = baseurl + "asset-service/workloads/" + workload_type + "/assets?filter=commonAssetAttributes/displayName eq '" + client + "'"
77+ url = f"{ baseurl } asset-service/workloads/{ workload_type } /assets?" \
78+ f"filter=commonAssetAttributes/displayName eq '{ client } '"
7079 status_code , response_text = rest_request ('GET' , url , headers )
7180 validate_response (status_code , 200 , response_text )
81+
7282 asset_id = response_text ['data' ][0 ]['id' ]
7383 uuid = response_text ['data' ][0 ]['attributes' ]['instanceUuid' ]
7484 exsi_host = response_text ['data' ][0 ]['attributes' ]['host' ]
85+
7586 print (f"Client asset Id:[{ asset_id } ]" )
7687 print (f"Client uuid Id:[{ uuid } ]" )
7788 print (f"Client exsi host:[{ exsi_host } ]" )
7889 return asset_id , uuid , exsi_host
7990
8091# Get StorageUnits
8192def get_storage_units (baseurl , token ):
93+ """ This function return the storage unit name """
8294 headers .update ({'Authorization' : token })
83- url = baseurl + " storage/storage-units"
95+ url = f" { baseurl } storage/storage-units"
8496 status_code , response_text = rest_request ('GET' , url , headers )
8597 validate_response (status_code , 200 , response_text )
8698 storage_unit_name = response_text ['data' ][0 ]['id' ]
8799 is_instant_access_enable = response_text ['data' ][0 ]['attributes' ]['instantAccessEnabled' ]
100+
88101 if is_instant_access_enable :
89102 print (f"Storage unit:[{ storage_unit_name } ] enabled for instant access" )
90- return storage_unit_name
91103 else :
92104 print (f"Storage unit:[{ storage_unit_name } ] disable for instant access" )
93105 raise Exception (f"Storage unit:[{ storage_unit_name } ] disabled for instant access" )
106+ return storage_unit_name
94107
95108# Create protection plan
96109def create_protection_plan (baseurl , token , protection_plan_name , storage_unit_name ):
110+ """ This function create the protection plan """
97111 print (f"Create protection plan:[{ protection_plan_name } ]" )
98112 headers .update ({'Authorization' : token })
99- payload = {}
100- url = baseurl + 'servicecatalog/slos?meta=accessControlId'
113+ url = f"{ baseurl } servicecatalog/slos?meta=accessControlId"
101114
102115 cur_dir = os .path .dirname (os .path .abspath (__file__ ))
103116 file_name = os .path .join (cur_dir , "create_protection_plan_template.json" )
104- f = open (file_name )
105- data = json .load (f )
117+ file_handle = open (file_name )
118+ data = json .load (file_handle )
106119 data ['data' ]['attributes' ]['name' ] = protection_plan_name
107120 data ['data' ]['attributes' ]['policyNamePrefix' ] = protection_plan_name
108121 data ['data' ]['attributes' ]['schedules' ][0 ]['backupStorageUnit' ] = storage_unit_name
@@ -115,12 +128,14 @@ def create_protection_plan(baseurl, token, protection_plan_name, storage_unit_na
115128 return protection_plan_id
116129
117130# Subscription asset to SLO
118- def subscription_asset_to_slo (baseurl , token , protection_plan_id , asset_id , is_vm_group = 0 ):
131+ def subscription_asset_to_slo (baseurl , token , protection_plan_id , asset_id , is_vm_group = 0 ):
132+ """ This function subscribe the asset/group asset to protection plan """
119133 print (f"Subscribe client to protection plan id: [{ protection_plan_id } ]" )
120134 headers .update ({'Authorization' : token })
121- url = baseurl + " servicecatalog/slos/" + protection_plan_id + " /subscriptions"
135+ url = f" { baseurl } servicecatalog/slos/{ protection_plan_id } /subscriptions"
122136 selection_type = "ASSETGROUP" if is_vm_group else "ASSET"
123- payload = {"data" : {"type" : "subscription" ,"attributes" : {"selectionType" : selection_type ,"selectionId" : asset_id }}}
137+ payload = {"data" : {"type" : "subscription" , "attributes" : \
138+ {"selectionType" : selection_type , "selectionId" : asset_id }}}
124139 status_code , response_text = rest_request ('POST' , url , headers , data = payload )
125140 validate_response (status_code , 201 , response_text )
126141 subscription_id = response_text ['data' ]['id' ]
@@ -130,22 +145,25 @@ def subscription_asset_to_slo(baseurl, token, protection_plan_id, asset_id, is_v
130145
131146# Get subscription
132147def get_subscription (baseurl , token , protection_plan_id , subscription_id ):
148+ """ This function return the subscription info """
133149 headers .update ({'Authorization' : token })
134- url = baseurl + " servicecatalog/slos/" + protection_plan_id + " /subscriptions/" + subscription_id
150+ url = f" { baseurl } servicecatalog/slos/{ protection_plan_id } /subscriptions/{ subscription_id } "
135151 status_code , response_text = rest_request ('GET' , url , headers )
136152 validate_response (status_code , 200 , response_text )
137153 print (f"Sucessfully fetched the subscription:[{ subscription_id } ] details." )
138-
154+
139155# Get job details
140156def get_job_details (baseurl , token , jobid ):
157+ """ This function return the job details """
141158 headers .update ({'Authorization' : token })
142- url = baseurl + " admin/jobs/" + str (jobid )
159+ url = f" { baseurl } admin/jobs/{ str (jobid )} "
143160 status_code , response_text = rest_request ('GET' , url , headers )
144161 validate_response (status_code , 200 , response_text )
145162 return response_text
146163
147164# Verify given job state and status
148165def verify_job_state (baseurl , token , jobid , expected_state , expected_status = 0 , timeout = 1200 ):
166+ """ This function verify the job status and state with expected status and state """
149167 if jobid :
150168 print (f"Wait for backup job to complete. Backup jobid:[{ jobid } ]" )
151169 # Verify backup job status
@@ -158,7 +176,7 @@ def verify_job_state(baseurl, token, jobid, expected_state, expected_status=0, t
158176 print (f"Job:[{ jobid } ] completed with expected state:[{ expected_state } ]" )
159177 status = response_text ['data' ]['attributes' ]['status' ]
160178 print (f"Actual status:[{ status } ] and expected status:[{ expected_status } ]" )
161- if status == expected_status or status == 1 :
179+ if status == expected_status :
162180 print (f"Job:[{ jobid } ] completed with expected status:[{ expected_status } ]" )
163181 break
164182 else :
@@ -168,37 +186,40 @@ def verify_job_state(baseurl, token, jobid, expected_state, expected_status=0, t
168186 print (f"Failed backup jobid:[{ jobid } ] with state:[{ state } ]" )
169187 raise Exception (f"Failed backup jobid:[{ jobid } ] with state:[{ state } ]" )
170188
171-
172-
173189# Remove protection plan
174190def remove_protectionplan (baseurl , token , protection_plan_id ):
191+ """ This function remove the given protection plan """
175192 if protection_plan_id :
176193 headers .update ({'Authorization' : token })
177- url = baseurl + ' servicecatalog/slos/' + protection_plan_id
194+ url = f" { baseurl } servicecatalog/slos/{ protection_plan_id } "
178195 status_code , response_text = rest_request ('DELETE' , url , headers )
179- validate_response (status_code , 204 , response_text )
196+ validate_response (status_code , 204 , response_text )
180197 print (f"Successfully removed protection plan:[{ protection_plan_id } ]" )
181198
182199# Remove vm subscription from protection plan
183200def remove_subscription (baseurl , token , protection_plan_id , subscription_id ):
201+ """ This function remove subscription from protection plan """
184202 if protection_plan_id and subscription_id :
185203 headers .update ({'Authorization' : token })
186- url = baseurl + ' servicecatalog/slos/' + protection_plan_id + ' /subscriptions/' + subscription_id
204+ url = f" { baseurl } servicecatalog/slos/{ protection_plan_id } /subscriptions/{ subscription_id } "
187205 status_code , response_text = rest_request ('DELETE' , url , headers )
188- validate_response (status_code , 204 , response_text )
189- print (f"Successfully removed asset subscription:[{ subscription_id } ] from protection plan:[{ protection_plan_id } ]" )
206+ validate_response (status_code , 204 , response_text )
207+ print (f"Successfully removed asset subscription:[{ subscription_id } ] " \
208+ f"from protection plan:[{ protection_plan_id } ]" )
190209
191- # Remove vcenter creds from netbackup master
210+ # Remove vCenter creds from NetBackup master
192211def remove_vcenter_creds (baseurl , token , vcenter_name ):
212+ """ This function remove the vCenter from NBU master """
193213 if vcenter_name :
194214 headers .update ({'Authorization' : token })
195- url = baseurl + ' config/servers/vmservers/' + vcenter_name
215+ url = f" { baseurl } config/servers/vmservers/{ vcenter_name } "
196216 status_code , response_text = rest_request ('DELETE' , url , headers )
197217 validate_response (status_code , 204 , response_text )
198- print (f"Successfully removed vcenter :[{ vcenter_name } ] credential " )
218+ print (f"Successfully removed vCenter :[{ vcenter_name } ] from NBU master " )
199219
200220# Execute REST API request
201221def rest_request (request_type , uri , header = None , ** kwargs ):
222+ """ This function make call to the REST API """
202223 session = requests .session ()
203224 payload = kwargs .get ('data' )
204225 if request_type == 'POST' :
@@ -233,17 +254,18 @@ def rest_request(request_type, uri, header=None, **kwargs):
233254 except json .decoder .JSONDecodeError :
234255 print (f"Could not parse json from [{ response_text } ]" )
235256
236- print (f"Sucessfully sent REST request:[{ uri } ]" )
257+ print (f"Successfully sent REST request:[{ uri } ]" )
237258 print (f"Status code:[{ response .status_code } ]" )
238259 print (f"Response text:[{ response .text } ]" )
239260 return response .status_code , response_text
240261
262+ # Validate the response code of the request
241263def validate_response (actual_status_code , expected_status_code , response_text ):
242- # Validate the response code of the request
243- if (actual_status_code == expected_status_code ):
244- print (f"Sucessfully validate the response status code:[{ expected_status_code } ]" )
245- return True
264+ """ This function validate the response status code with expected response code """
265+ if actual_status_code == expected_status_code :
266+ print (f"Successfully validate the response status code:[{ expected_status_code } ]" )
246267 else :
247- print (f"Actual status code:[{ actual_status_code } ] not match with expected status code:[{ expected_status_code } ]" )
248- raise Exception (f"Response Error:[{ response_text ['errorMessage' ]} ] and details:[{ response_text ['errorDetails' ]} ]" )
249- return False
268+ print (f"Actual status code:[{ actual_status_code } ] not match " \
269+ f"with expected status code:[{ expected_status_code } ]" )
270+ raise Exception (f"Response Error:[{ response_text ['errorMessage' ]} ] and " \
271+ f"details:[{ response_text ['errorDetails' ]} ]" )
0 commit comments