Saturday, May 30, 2020

vRealize Operations API and Identity Manager Authentication

My vRealize Operations' posts prior to this one, have  shown local user authentication.  This post will demonstrate how to use VMware Identity Manager within a Python script that authenticates to vRealize Operations.

I'm going to assume that vIDM is already running and configured within vRealize Operations.  If you view the authentication sources in vRealize Operations, at a minimum you should see something like the following if vIDM is configured:



In the screen capture above, the 'Source Display Name' will be used during the authentication configuration later.

In the script below, I'm using configparser to read a file named 'config.ini'.  In the example below, I'm showing the local authentication as well as the vIDM authentication.  The local stuff is commented out.  For the vIDM user, I could have combined the user name and user domain into a single parameter.  I opted to leave them separated here and combine them in the Python script.

<--- Begin config.ini --->


[vrops user]

#usrName=vrops-adm

#usrPass=adminpassword

#authSource=Local

usrName=idm-user

usrPass=idm-user-password

authSource=VM-IDM

usrDomain=thewhiteshouse.net


[vrops server]

srvName=vm-vrops.thewhiteshouse.net

<--- End config.ini --->

For my environment, I'm only considering a local authentication or a vIDM authentication.  For vIDM, I need to use the 'Source Display Name' that we viewed in the screen capture above.  Now that we have the necessary parameters in the config.ini, we can look at the authentication process in the script.  

In the 'Authenticate' routine below, I grab the server name, user name, password and authentication source from the INI file.  If the authentication source is not 'Local', I grab the domain parameter and append that to the user name.  I can now acquire the token and run the rest of the script.

The script results are basic.  It will show the authenticated user's permissions and the configured authentication sources in vROps.  I show the results of the script at the bottom of this blog.

Here is the script:

<--- Begin opstest.py --->

#!/usr/bin/python3


#imports

import getopt, sys, json, requests, configparser

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


def Authenticate():

# Read Config parameters

config = configparser.ConfigParser()

config.read('config.ini')


#Your vROps environment parameters

srvName = config['vrops server']['srvName']

usrName = config['vrops user']['usrName']

usrPass = config['vrops user']['usrPass']

authSource = config['vrops user']['authSource']


if authSource.lower() != "local":

usrDom = config['vrops user']['usrDomain']

usrName = usrName+"@"+usrDom


global baseURL

baseURL = "https://" + srvName


apiURL = baseURL + "/suite-api/api/auth/token/acquire"

apiData = {"username": usrName,"authSource": authSource,"password": usrPass,"others": [],"otherAttributes": {}}

apiHeaders = {"Content-Type":"application/json","Accept":"application/json"}

apiReq = requests.post(apiURL,data=json.dumps(apiData),headers=apiHeaders,verify=False)

if (apiReq.status_code != 200):

print('probably invalid credentials')

print('Returned Status Code: ' + str(apiReq.status_code))

sys.exit(2)

else:

token = "vRealizeOpsToken " + apiReq.json()['token']

return token


# Get Current Users Permissions

def GetPermissions(token):

apiURL = baseURL + "/suite-api/api/auth/currentuser/permissions"

apiHeaders = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

apiReq = requests.get(apiURL,headers=apiHeaders,verify=False)

# print(json.dumps(apiReq.json(),indent=4))

print("Current User Permissions:")

for x in range(len(apiReq.json()['permissions'])):

print(" Role Name: "+apiReq.json()['permissions'][x]['roleName'])

print(" Allow All Objects: "+str(apiReq.json()['permissions'][x]['allowAllObjects']))


# Get Auth Sources

def GetAuthSources(token):

apiURL = baseURL + "/suite-api/api/auth/sources"

apiHeaders = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

apiReq = requests.get(apiURL,headers=apiHeaders,verify=False)

# print(json.dumps(apiReq.json(),indent=4))

if (apiReq.status_code == 200):

for x in range(len(apiReq.json()['sources'])):

msg = "\nAuthorization Source: "+ str(x+1)

msg += "\n\tname: "+apiReq.json()['sources'][x]['name']

msg += "\n\tid: "+apiReq.json()['sources'][x]['id']

msg += "\n\tsource type name: "+apiReq.json()['sources'][x]['sourceType']['name']

print(msg)

GetAuthSourcesType(token, apiReq.json()['sources'][x]['id'])


# Get Auth Source Type

def GetAuthSourcesType(token, id):

apiURL = baseURL + "/suite-api/api/auth/sources/"+id

apiHeaders = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

apiReq = requests.get(apiURL,headers=apiHeaders,verify=False)

# print(json.dumps(apiReq.json(),indent=4))

if (apiReq.status_code == 200):

msg = " Propterties about the source:"

# msg += "\n\t\tid: "+apiReq.json()['id']

# msg += "\n\t\tname: "+apiReq.json()['name']

for x in range(len(apiReq.json()['property'])):

if 'value' in apiReq.json()['property'][x]:

msg += "\n\t\tprop: "+apiReq.json()['property'][x]['name']

msg += "\n\t\tvalue: "+apiReq.json()['property'][x]['value']

else:

msg += "\n\t\tprop: "+apiReq.json()['property'][x]['name']

msg += "\n\t\tvalue: "


print(msg)


def Logout(token):

releaseURL = baseURL + "/suite-api/api/auth/token/release"

apiHeaders = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

authResponse = requests.post(releaseURL,headers=apiHeaders,verify=False)


def main():

token = Authenticate()

GetPermissions(token)

GetAuthSources(token)

Logout(token)


if __name__ == "__main__":

main()


<--- End opstest.py --->


These are the results of the script above:

<--- Script Results --->

jwhite@vm-linux:~/bin$ ./opstest.py 

Current User Permissions:

Role Name: Administrator

Allow All Objects: True


Authorization Source: 1

name: All vCenter Servers

id: d082d766-b28b-43e9-85cf-030ff82dcff1

source type name: VC_GROUP

Propterties about the source:


Authorization Source: 2

name: VM-IDM

id: acca9a62-4869-4404-b8b7-3a702a63df3f

source type name: VIDM

Propterties about the source:

prop: redirect-host

value: https://vm-idm.thewhiteshouse.net/ui/vidmClient/vidm/

prop: display-name

value: VM-IDM

prop: port

value: 443

prop: host

value: vm-idm.thewhiteshouse.net

prop: tenant

value: default-tenant

prop: certificate-thumprint

value: 7007a6e4811bbc4657846fe9b6c2f56193a76f25


Authorization Source: 3

name: vCenter

id: 894a97aa-c2b7-4022-8e87-298b952f6afa

source type name: VC

Propterties about the source:

prop: vc-guid

value: 335c8073-3c15-48ae-b291-0c29af38f896


Thanks for taking a look at this blog.

Tuesday, May 26, 2020

vRealize Operations Export the Latest Metrics for VM(s)

In a response to a customer asking about exporting VM metrics via the REST API, I put together the following post.  The REST API for vRealize Operations Manager provides a few methods for exporting metrics.  For this exercise, I'm showing a method to get the latest stats for a selected resource: 

"/suite-api/api/resources/stats/latest/query"

To use this method, the script requires the ID for the resource we will query.  To get the ID, I'll copy the code from one of my earlier posts to search for a VM based on the name entered and use that as the base for the script below.  The script is written in Python.

The script has the ability to return selected stats (metrics) or all the stats for virtual machines.  Once you run the script to return all of the metrics, you can modify the statKey parameters in vropsGetResIdStats to return selected metrics.  The script will return results for Virtual Machines that are not templates, powered on and currently providing data to vRealize Operations.

You can also return all the properties for the searched VMs.  At the end of the script, you'll see where that is commented out by default.  Remove the hashtag to enable that process.

To execute the script, enter the script name like this:

"python3 getstats.py -n vm-name"

or to return all virtual machines:

"python3 getstats.py -a"

The script is currently configured to display the results to the screen in JSON format.  I've included the parameters to return XML or CSV.  Those lines are commented out.

Like the other Python scripts in my blog, I'm using configparser to store and read the configuration parameters for username, password and server address.  The script is written to authenticate to vROps as a local user.

<--- Begin getstats.py --->

#!/usr/bin/python3


#imports

import getopt, sys, json, requests, configparser

from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


# Authenticate (vROps local user - consider updating script to allow for IDM)

def Authenticate():

    #Read Config parameters

    config = configparser.ConfigParser()

    config.read('config.ini')


    #Your vROps environment parameters

    usrName = config['vrops user']['usrName']

    usrPass = config['vrops user']['usrPass']

    srvName = config['vrops server']['srvName']


    global baseURL

    baseURL = "https://" + srvName


    tokenURL = baseURL + "/suite-api/api/auth/token/acquire"

    authJSON = {"username": usrName,"authSource": "Local","password": usrPass,"others": [],"otherAttributes": {}}

    authHeaders = {"Content-Type":"application/json","Accept":"application/json"}

    authResponse = requests.post(tokenURL,data=json.dumps(authJSON),headers=authHeaders,verify=False)

    if (authResponse.status_code != 200):

        print('probably invalid credentials')

        print('Returned Status Code: ' + authResponse.status_code)

        sys.exit(2)

    else:

        authToken = "vRealizeOpsToken " + authResponse.json()['token']

        return authToken


# Get all VMs in the vROps database

# Return only VMs that are not templates and are receiving data from vCenter

def vropsGetAllVms(token):

    vmList=[]

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    vropsURL = baseURL+"/suite-api/api/resources?resourceKind=virtualmachine"

    response = requests.get(vropsURL,headers=Headers,verify=False)

    data = response.json()

    AddVmToList(token,data,vmList)

    return(vmList)


# Search vROps database for the VM Name

# Return only VMs that are not templates and are receiving data from vCenter

def vropsSearchName(token, vm_name):

    vmList = []

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    vropsURL = baseURL+"/suite-api/api/adapterkinds/VMWARE/resourcekinds/virtualmachine/resources?name="+vm_name

    response = requests.get(vropsURL,headers=Headers,verify=False)

    if (response.status_code == 200):

        data = response.json()

        if data['pageInfo']['totalCount'] == '0':

            return ('Searched term not found')

        else:

            AddVmToList(token,data,vmList)

    return (vmList)


# Add VM to the VM List only if it exists, is not a template and is Powered On

def AddVmToList(token,data,vmList):

    for x in range(int(data['pageInfo']['totalCount'])):

        for y in range(len(data['resourceList'][x]['resourceStatusStates'])):

            adapterKey = vropsGetAdapterKind(token,data['resourceList'][x]['resourceStatusStates'][y]['adapterInstanceId'])

            resState = data['resourceList'][x]['resourceStatusStates'][y]['resourceState'] 

            if (adapterKey == 'VMWARE'):

                if (resState == 'NOT_EXISTING'):

                    break

                else:

                    msg = vropsVmStatus(token,data['resourceList'][x]['identifier'])

                    if (msg[0]=='false' and msg[1]=='Powered On'):

                        vmList.append(data['resourceList'][x]['identifier'])

                        msg = data['resourceList'][x]['resourceKey']['name']+": "

                        msg += data['resourceList'][x]['identifier']+" "

#                        msg += data['resourceList'][x]['resourceKey']['resourceIdentifiers'][2]['value']

                        print(msg)

    return(vmList)


def vropsVmStatus(token,vmId):

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    Data = {

        "resourceIds":[vmId],

        "propertyKeys": ["summary|config|isTemplate","summary|runtime|powerState"],

        "other": [],

        "otherAttributes": {}

    }

    vropsURL = baseURL+"/suite-api/api/resources/properties/latest/query"

    response = requests.post(vropsURL,headers=Headers,data=json.dumps(Data),verify=False)

    resp = response.json()

    isTemplate = resp['values'][0]['property-contents']['property-content'][0]['values'][0]

    powerState = resp['values'][0]['property-contents']['property-content'][1]['values'][0]

    msg = [isTemplate,powerState]

    return(msg)


# Get the metrics for the VM

# Change the statKey parameter to select metrics.  An empty list will return all metrics

# Change maxSamples to return X past values for each metric.  1 returns the latest metric

def vropsGetResIdStats(token, vmId):

#    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"text/csv"}

#    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/xml"}

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    Data = {

     "resourceId" : [vmId],

     "statKey" : ["cpu|workload","cpu|demandPct"],

#     "statKey" : [],

     "metrics" : False,

     "currentOnly" : False,

     "maxSamples" : 1

    }

    vropsURL = baseURL+"/suite-api/api/resources/stats/latest/query"

    response = requests.post(vropsURL,headers=Headers,data=json.dumps(Data),verify=False)

    newstr=(response.text).replace("\n",",").strip()

    print(newstr)


# Get all the properties for the VM

def vropsGetResIdProps(token, vmId):

#    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"text/csv"}

#    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/xml"}

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    vropsURL = baseURL+"/suite-api/api/resources/"+vmId+"/properties"

    response = requests.get(vropsURL,headers=Headers,verify=False)

    newstr=(response.text).replace("\n",",").strip()

    print(newstr)


def vropsGetAdapterKind(token,adapterId):

    Headers = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    vropsURL = baseURL+"/suite-api/api/adapters/"+adapterId

    response = requests.get(vropsURL,headers=Headers,verify=False)

    if response.status_code == 200:

        return(response.json()['resourceKey']['adapterKindKey'])

    else:

        print("There is a problem searching for the adapter")

        sys.exit(2)


def Logout(token):

    releaseURL = baseURL + "/suite-api/api/auth/token/release"

    authHeaders = {"Content-Type":"application/json","Authorization":token,"Accept":"application/json"}

    authResponse = requests.post(releaseURL,headers=authHeaders,verify=False)


def Usage():

    print("We need:")

    print(" -a or --all")

    print(" -n <VM Name>")

    print("for parameters")


def main():

# Check for passed arguments

    if len(sys.argv)==1:

        Usage()

        sys.exit()


    try:

        opts, args = getopt.getopt(sys.argv[1:], "han:",["help","all","name="])

    except getopt.GetoptError as err:

        print(err)

        Usage()

        sys.exit(2)

    authToken = Authenticate()

    vmList = []

    for key,value in opts:

        if key == ("-h", "--help"):

            Usage()

            sys.exit()

        elif key in ("-a", "--all"):

            vmList = vropsGetAllVms(authToken)

        elif key in ("-n", "--name"):

            vmList = vropsSearchName(authToken, value)

        else:

            Usage()


        for x in range(len(vmList)):

            vropsGetResIdStats(authToken,vmList[x])

#            vropsGetResIdProps(authToken,vmList[x])


    Logout(authToken)


if __name__ == "__main__":

    main()


<--- End getstats.py --->

Thanks for checking out the blog.