Hello my readers
I’m sorry that my articles are published so rarely, but I am still so fascinated by the world of vmware that it’s hard for me to break away and write something.
Recently, I had the task of looking at the monitoring of Aria Automation infrastructures, previously known as vRealie Automation, or more precisely, Aria Automation Assembler, previously known as VMware Cloud Assembly
after digging through various possibilities, a script in PowerShell was created that monitors ABX, CAS and Cloud Account along with all the possibilities that are
unfortunately I can’t share this script so I went the other way and started learning two things by the way. Mianowice is Python and tkinter, its library for GUI programming and I started to create the script again, a lot ahead of me, but the stub I want to share with you and briefly describe what will happen
The script will be a welcome window in which we will have a choice of Cloud or OnPrem instances
from the code point of view it looks like this
#main buttons
cloudButton = tkinter.Button(mainWindow, text ="Cloud", command = openCloudWindow)
onpremButton = tkinter.Button(mainWindow, text ="OnPrem", command = openOnpremmWindow)
cloudButton.pack()
onpremButton.pack()
mainWindow.title("Aria Automation Health Check")
mainWindow.geometry("500x100")
at the moment I started to create versions for the cloud because I already have questions, so I will describe the versions from the cloud here
after selecting cloud, our main window disappears and a window appears on which the health check will be built, but before this happens, we have to provide data. These can either be entered manually or a configuration file can be selected
def openCloudWindow():
cloudWindow = Toplevel(mainWindow)
mainWindow.withdraw()
cloudWindow.protocol("WM_DELETE_WINDOW", onClose)
cloudWindow.geometry("500x500")
cloudWindow.state("zoomed")
#cloudWindow.columnconfigure(2, weight=5)
cloudWindow.title("Aria Automation Health Check")
questionButton = tkinter.messagebox.askquestion('Coonfig File', 'Do you wanna use Config File')
if questionButton == 'yes':
print("choose file")
OpenFile()
requestBearer(url, refreshToken,cloudWindow)
else:
print("fields with inputs")
createValues(cloudWindow)
here we have a normal function that creates a window and asks for a file. The configuration file has the following structure at present
if we choose the option without a configuration file we will have to enter the URL and our Refresh Token
Bearer;
def requestBearer(url, refreshToken,cloudWindow):
global bearerToken, clockLabel
headers = {"Accept": "application/json", "Content-Type": "application/json"}
payload = {"refreshToken": refreshToken}
payload = json.dumps(payload)
apiUrl = url+"/iaas/api/login"
print(url)
print(refreshToken)
response = requests.request("POST",apiUrl,headers=headers,data=payload)
bearerToken = response.json()['token']
print(bearerToken)
#return bearerToken
if(bearerToken):
bearerLabel = tkinter.Label(cloudWindow, text="Bearer Token time for refresh: ").grid(column=1,row=5)
frame = tkinter.Frame(cloudWindow,relief='solid',width=100,height=20)
frame.grid(column=2,row=5)
stop_event = Event()
th = threading.Thread(target=print_numbers, args=(1800,frame,stop_event))
th.daemon = True
th.start()
the next element is to save the values that have been entered and download the Bearer Token, after downloading it, we will get a counter counting 30 minutes after which we will have to re-download the token
Counter:
def print_numbers(end,frame,stop_event):
while not stop_event.is_set():
clockCounter = tkinter.Label(frame)
clockCounter.grid(column=2,row=5)
clockCounter.configure(text=" ")
clockCounter.update()
frame.update()
for i in reversed(range(end)):
if(i<60):
clockCounter.configure(text=str(i),fg='#FF0000')
else:
clockCounter.configure(text=str(i))
time.sleep(1)
stop_event.set()
As we already have bearer, we can finally download our endpoints and then display the values that interest us.
Endpoints will be displayed as Radio Button
Endpinds Code:
def getEndpoints(bearerToken, cloudWindow,url):
global abxArray, radio
abxArray = []
radio = IntVar(value=0)
authHeaders = {"Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer "+bearerToken}
apiUrl=url+"def getEndpoints(bearerToken, cloudWindow,url):
global abxArray, radio
abxArray = []
radio = IntVar(value=0)
authHeaders = {"Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer "+bearerToken}
apiUrl=url+"/iaas/api/integrations?apiVersion=2021-07-15"
response = requests.request("GET",apiUrl,headers=authHeaders)
results = response.json()
for item in results['content']:
abxArray.append(item)
print(len(abxArray))
if(abxArray):
endpointLabel = tkinter.Label(cloudWindow, text="Endponts: ").grid(column=1,row=6)
for i in range(len(abxArray)):
Radiobutton(cloudWindow, text=abxArray[i]['name'], value=i,tristatevalue=i,variable=radio,command=lambda: showDetails(cloudWindow) ).grid(sticky="W",column=1, row=7+i)
"
response = requests.request("GET",apiUrl,headers=authHeaders)
results = response.json()
for item in results['content']:
abxArray.append(item)
print(len(abxArray))
if(abxArray):
endpointLabel = tkinter.Label(cloudWindow, text="Endponts: ").grid(column=1,row=6)
for i in range(len(abxArray)):
Radiobutton(cloudWindow, text=abxArray[i]['name'], value=i,tristatevalue=i,variable=radio,command=lambda: showDetails(cloudWindow) ).grid(sticky="W",column=1, row=7+i)
As you can see I’m using the calla na API here
“/ iaas / api / integrations? apiVersion = 2021-07-15”
from the documentation, we can read what is in this answer.https://www.mgmt.cloud.vmware.com/iaas/api/swagger/ui/#/Integration/getIntegrations
for this solution i get name and dcId from integrationProperties
The solution at the moment informs about the status of the endpoint itself and the containers present on it
Endpint Details:
def abxDetails(abx,cloudWindow):
#print(abx)
if(abx['integrationProperties']['dcId']):
authHeaders = {"Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer "+bearerToken}
apiUrl=url+"/api/data-collector-v2/"+abx['integrationProperties']['dcId']
response = requests.request("GET",apiUrl,headers=authHeaders)
results = response.json()
responseheaders = response.headers['Date']
unixTime = int(time.mktime(email.utils.parsedate(responseheaders)))
lastSync = int(results['lastSyncTime']/1000000)
lastSynTime = math.floor((unixTime - lastSync)/60000)
tableResult = ttk.Treeview(cloudWindow)
tableResult.grid(column=3,row=5)
tableResult['columns']=('id','value')
tableResult.tag_configure(tagname="red", background='#FF0000')
tableResult.tag_configure(tagname="green", background='#008000')
tableResult.insert(parent="",index="end",iid=0,text="",values=("name",results['name']))
tableResult.insert(parent="",index="end",iid=1,text="",values=("ip",results['ipAddress']))
if(results['status'] == "INACTIVE"):
tableResult.insert(parent="",index="end",iid=2,text="",values=("status",results['status']), tags="red")
else:
tableResult.insert(parent="",index="end",iid=2,text="",values=("status",results['status']), tags="green")
tableResult.insert(parent="",index="end",iid=3,text="",values=("LastSyncMinutesAgo",lastSynTime))
contUrl = url+"/stargate/api/v1/rdc/"+abx['integrationProperties']['dcId']+"/container/status/"
response_1 = requests.request("GET",contUrl,headers=authHeaders)
results_1 = response_1.json()
tableResultContainer = ttk.Treeview(cloudWindow)
tableResultContainer.grid(column=3,row=6)
tableResultContainer['columns']=('id','value')
counter = 0
for c in results_1:
tableResultContainer.insert(parent="",index="end",iid=0+counter,text="",values=("containerName",c['name']))
tableResultContainer.insert(parent="",index="end",iid=1+counter,text="",values=("containerStatus",c['status']))
tableResultContainer.insert(parent="",index="end",iid=2+counter,text="",values=("containerStatusMessage",c['statusMessage']))
counter += 3
In this case, it uses an API that is no longer described, but we can easily use it by performing reverse engineering
/ api / data-collector-v2 / “+ abx [‘integrationProperties’] [‘dcId’]
“/ stargate / api / v1 / rdc /” + abx [‘integrationProperties’] [‘dcId’] + “/ container / status /”
The first query returns information about ABX itself and the global status
The second one informs about the status of the containers
The next elements will be information about Cloud Accounts and CASs, so be patient, and it will not be long for full functionality, additionally it will be generating a report and sending an e-mail.
I’m working on something big for you, but that’s another story