Skip to content

Commit 8b73c6c

Browse files
committed
Python script for Cloud Assets Cleanup
1 parent ae62d52 commit 8b73c6c

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

snippets/python/cloud/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### NetBackup API Code Samples for Python
2+
3+
This directory contains code samples to invoke NetBackup REST APIs using Python.
4+
5+
#### Disclaimer
6+
7+
These scripts are only meant to be used as a reference. If you intend to use them in production, use it at your own risk.
8+
9+
#### Pre-requisites:
10+
11+
- NetBackup 8.2 or higher
12+
- python 3.5 or higher
13+
- python modules: `requests, sys, argparse, ssl, json`
14+
15+
#### Executing the snippets in Python
16+
17+
Use the following commands to run the python samples.
18+
- `python cloud_assets_cleanup.py [-h] --nbu_master_host <hostname> --nbu_user_name <user name> --nbu_password <password>`
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/python
2+
import requests
3+
import sys
4+
import argparse
5+
import ssl
6+
import json
7+
from datetime import datetime, timedelta
8+
9+
requests.packages.urllib3.disable_warnings()
10+
11+
args = ()
12+
globals = {}
13+
CLEANUP_TIME = 48 # in hours
14+
15+
# NetBackup APIs
16+
URL_LOGIN = "/login"
17+
URL_NETBACKUP = "/netbackup"
18+
URL_GET_ASSETS = "/assets"
19+
URL_ASSET_CLEANUP = "/assets/asset-cleanup"
20+
CONTENT_TYPE4 = "application/vnd.netbackup+json;version=4.0"
21+
22+
# Build the URL to invoke
23+
def buildURL(url, filter = ""):
24+
retURL = "https://" + args.nbu_master_host + URL_NETBACKUP + url
25+
if (filter != ""):
26+
retURL += "?filter=" + filter
27+
return retURL
28+
29+
# RestClient
30+
def doRestCall(method, url, reqBody = {}):
31+
headers = {
32+
'Content-Type': CONTENT_TYPE4
33+
}
34+
if "token" in globals:
35+
headers["Authorization"] = globals["token"]
36+
37+
if (method == "POST"):
38+
response = requests.post (url, headers = headers, data = json.dumps(reqBody), verify = False)
39+
40+
if (method == "GET"):
41+
response = requests.get(url, headers=headers, data = json.dumps(reqBody), verify=False)
42+
return response
43+
44+
# Login to specified NetBackup master server
45+
def loginMaster():
46+
print ("** Logging in to the NetBackup master host...")
47+
if "token" in globals:
48+
return globals["token"]
49+
50+
reqBody = {
51+
"userName" : args.nbu_user_name,
52+
"password" : args.nbu_password
53+
}
54+
response = doRestCall("POST", buildURL(URL_LOGIN), reqBody)
55+
if response.status_code == 201:
56+
globals["token"] = response.json()["token"]
57+
return response.json()["token"]
58+
print(" -> Invalid user name or password")
59+
print("** Exiting")
60+
exit(1)
61+
62+
# Get assets using a filter
63+
def getAssets():
64+
token = loginMaster()
65+
66+
print ("** Retrieving assets to cleanup...")
67+
assets = []
68+
cleanupTime = str((datetime.utcnow() - timedelta(hours = CLEANUP_TIME)).isoformat()) + "Z"
69+
globals["cleanupTime"] = cleanupTime
70+
count = 0
71+
pageOffset = 0
72+
while True:
73+
queryFilter = "(lastDiscoveredTime lt " + cleanupTime \
74+
+ " and workloadType eq 'Cloud')"
75+
queryFilter += "&page[offset]=" + str(pageOffset) + "&page[limit]=100"
76+
response = doRestCall("GET", buildURL(URL_GET_ASSETS, queryFilter))
77+
if response.status_code == 200:
78+
if "data" not in response.json() or len(response.json()["data"]) == 0:
79+
break
80+
assets += response.json()["data"]
81+
pageOffset += 100
82+
if count == 0:
83+
try:
84+
count = response.json()["meta"]["pagination"]["count"]
85+
except:
86+
pass
87+
else:
88+
if len(assets) == 0:
89+
print (" -> No assets found")
90+
print ("** Exiting")
91+
exit(1)
92+
else:
93+
break
94+
msg = str(len(assets))
95+
if count != 0:
96+
msg = str(len(assets)) + " / " + str(count)
97+
print (" -> Received " + msg + " stale assets")
98+
globals["assets"] = assets
99+
100+
def cleanupAssets():
101+
assets = []
102+
if "assets" in globals:
103+
assets = globals["assets"]
104+
105+
if len(assets) == 0:
106+
print(" -> No assets to clean up")
107+
print("** Exiting")
108+
exit(1)
109+
110+
print ("** Cleaning up " + str(len(assets)) + " assets")
111+
112+
assetsCleanup = []
113+
for asset in assets:
114+
assetsCleanup.append(asset["id"])
115+
116+
reqBody = {"data": {
117+
"type": "assetCleanup",
118+
"id": "id",
119+
"attributes": {
120+
"cleanupTime": globals["cleanupTime"],
121+
"assetIds": assetsCleanup
122+
}
123+
}
124+
}
125+
response = doRestCall("POST", buildURL(URL_ASSET_CLEANUP), reqBody)
126+
if response.status_code == 204:
127+
print ("** Assets cleaned up successfully")
128+
else:
129+
print("** Unable to clean assets")
130+
print("** Exiting")
131+
132+
def parseArguments():
133+
global args
134+
parser = argparse.ArgumentParser()
135+
parser.add_argument('--nbu_master_host', metavar="<hostname>", \
136+
help='NetBackup Master Host', required = True)
137+
parser.add_argument('--nbu_user_name', metavar="<user name>",
138+
help='NetBackup Username', required = True)
139+
parser.add_argument('--nbu_password', metavar="<password>", \
140+
help='NetBackup Password', required = True)
141+
args = parser.parse_args()
142+
143+
def setup():
144+
try:
145+
_create_unverified_https_context = ssl._create_unverified_context
146+
except AttributeError:
147+
pass
148+
else:
149+
ssl._create_default_https_context = _create_unverified_https_context
150+
151+
if __name__ == "__main__":
152+
setup()
153+
parseArguments()
154+
getAssets()
155+
cleanupAssets()

0 commit comments

Comments
 (0)