Desabilitando redes sem IP disponível automaticamente no vRealize Automation 8.x

Desabilitando redes sem IP disponível automaticamente no vRealize Automation 8.x

As escolhas do vRA são basedas em tags e muitas vezes podemos ter multiplas opções de escolha, por exemplo, o match das tags pode encontrar multiplas redes, clusters, datastores, etc. A ideia geral aqui é demonstrar como o vRA pode desabilitar algum recurso automaticamente evitando assim a utilização do mesmo. Isso poderia se aplicar para um cluster quando alcança uma porcentagem especifica de consumo de memória ou CPU, valeria também para datastores que chegam em uma utilização pré-definida e até mesmo para as redes, onde seriam desabilitadas no caso da quantidade de endereços IP disponíveis serem inferior a 5%, por exemplo. E é exatamente este exemplo das redes que veremos aqui.

No meu ambiente possuo duas redes de produção que são usadas para serviços de web server. No momento da escolha da rede, qualquer uma das duas pode ser selecionada como uma opção válida. A parte de rede do blueprint ficaria assim:

Network:
    type: Cloud.vSphere.Network
    properties:
      networkType: existing
      constraints:
        - tag: environment:${input.cavAmbiente}
        - tag: service:${input.cavService}

Se fizermos um teste rápido e escolhermos o ambiente de produção + serviço web server, então veremos a VMnet_113 e VMnet_114 como opções.

Porém, a VMnet_113 está com poucos endereços IP livres e dependendo da quantidade de máquinas que será solicitada este deploy irá falhar. O que eu gostaria de fazer é desabilitar a rede para o vRA quando a mesma atingir uma porcentagem especifica de endereços IP livres, ou seja, eu quero que o vRA não considere mais aquela rede como uma opção quando tiver apenas 5% de IP livres. Para isso, vamos utilizar uma nova tag no blueprint, desta vez, ao invés de buscar o match como de costume, iremos fazer o oposto. Neste caso, não quero aquilo que está associado com esta tag e para isso utilizamos a exclamação (!) na frente da tag: !network-status:disabled

Exemplificando:

bebida:cerveja = procure algum match com isso (quero isso)
!bebida:cerveja = evite um match com isso (não quero isso)

Network:
    type: Cloud.vSphere.Network
    properties:
      networkType: existing
      constraints:
        - tag: environment:${input.cavAmbiente}
        - tag: service:${input.cavService}
        - tag: '!network-status:disabled'

Bastou adicionar a tag network-status:disabled na rede VMnet_113 e agora o vRA não a considera mais uma opção (Obs: a exclamação ! só é adiconada no blueprint, não vai na tag do objeto). Desta forma, estou falando para o vRA que eu busco uma rede que seja de produção (environment:prod), que seja de web servers (service:web) e que NÃO esteja com o status desabilitado (!network-status:disabled).

Importante: se você remover todas as tags da rede o vRA não irá considerar uma opção, porém, muitos clientes entendem que esta condição é temporaria e por isso esta rede voltaria a funcionar quando tivesse os endereços IP liberados, por isso optamos por adiconar uma nova tag para desabilitar a rede ao invés de remover as tags existentes.

Então é isso, super fácil e rápido, basta usar a tag. MMMAAASSS (sempre tem um mas, não é mesmo?!) alguns clientes possuem muitas redes e talvez a administração delas não seja tão boa e por isso estes clientes gostariam que o vRA identificasse quando esta rede está com poucos endereços IP e desabilitasse automaticamente, da pra fazer? Claro que da! Vamos ver como seria isso.

Primeiramente precisamos validar quem está gerenciando os endereços IP: vRA ou software externo. Como é mais comum os clientes optarem por gerenciamento externo, neste exemplo irei demonstrar com fazer com o phpIPAM. Neste caso, precisamos conectar no phpIPAM e obter a utilização de todas as redes. Após, vamos conectar no vRA e adicionar a tag network-status:disabled para que a rede que esteja com menos de 5% de endereços IP disponíveis seja desabilitada no vRA.

Como já era de se imaginar, vamos utilizar o Orchestrator em conjunto com o uso de APIs e Python. Primeiramente crie um novo workflow em Orchestrator > Library > Workflows > new workflow. Configure as variáveis para as conexões via API e não esqueça de adiciona-las no input da scriptable task na aba schema.

O código em Python é este:

import requests
import json

def handler(context, inputs):
    baseurl = inputs['ipamServer'] + "/api/" + inputs['ipamAppid']
    
    # get token phpIPAM
    res = requests.post(baseurl + '/user/', verify=False, auth=(inputs['ipamUser'], inputs['ipamPass']))
    tokenipam = json.loads(res.content)['data']['token']

    # get subnets
    res2 = requests.get(baseurl + '/subnets', verify=False, headers={'token': tokenipam})
    subnets = json.loads(res2.content)['data']

    result = []
    i = 0
    while (len(subnets) > i):
        cidr = subnets[i]['subnet'] + '/' + subnets[i]['mask']
        res3 = requests.get(baseurl + '/subnets/' + subnets[i]['id'] + '/usage', verify=False, headers={'token': tokenipam})
        iplivre = json.loads(res3.content)['data']
        
        if iplivre['freehosts_percent'] <= 5.00:
            print('### Network: ' + cidr + ' | Free IP: ' + iplivre['freehosts'] + ' (' + str(iplivre['freehosts_percent']) + '%)') # log
            
            # new tag
            newtag = {'key': 'network-status', 'value': 'disabled'}

            # get vRA fresh token
            res4 = requests.post(inputs['vraServer'] + '/csp/gateway/am/api/login?access_token', verify=False, headers={'Content-Type': 'application/json'}, json={'username': inputs['vraUser'], 'password': inputs['vraPass']})
            tokenvra = json.loads(res4.content)['refresh_token'] 

            # get vRA bearer token
            res5 = requests.post(inputs['vraServer'] + '/iaas/api/login', verify=False, headers={'Content-Type': 'application/json'}, json={'refreshToken': tokenvra })
            token2 = json.loads(res5.content)
            bearer = token2["tokenType"] + " " + token2["token"]
           
            # get fabric network ID
            res6 = requests.get(inputs['vraServer'] + "/iaas/api/fabric-networks?$filter=cidr%20eq%20'" + cidr + "'", verify=False, headers={'Content-Type': 'application/json', 'Authorization': bearer})
            networkid = json.loads(res6.content)['content'][0]['id']
            
            # get existing tags
            res7 = requests.get(inputs['vraServer'] + '/iaas/api/fabric-networks/' + str(networkid), verify=False, headers={'Content-Type': 'application/json', 'Authorization': bearer})
            tags = json.loads(res7.content)
            tags['tags'].append(newtag)
            
            # update fabric network tags
            res8 = requests.patch(inputs['vraServer'] + '/iaas/api/fabric-networks/' + str(networkid), verify=False, json=tags, headers={'Content-Type': 'application/json', 'Authorization': bearer})
            patchnetwork = json.loads(res8.content)
            print(patchnetwork) # log
        i = i+1

Salve e feche o workflow. Nas actions do workflow que acabou de criar selecione schedule. Vamos criar um agendamento para que este workflow seja executado em um horário especifico e com recorrência.

Obviamente isso pode variar em cada ambiente, então basta ajustar conforme a sua necessidade. Para testar coloquei para rodar a cada minuto (exagero haha).

Cada vez que o workflow for executado, ele irá conectar no phpIPAM e validar se alguma das redes está com 5% (ou menos) de endereços IP livres, se encontrar algum caso irá identificar a rede no vRA e adicionar a tag desabilitando-a. Caso a rede libere mais endereços IP e você queira disponibiliza-la novamente para o vRA, basta remover a tag e pronto.

É isso aí, pessoal. Até a próxima!

Apenas para esclarecer: VMware Aria Automation é o novo nome do vRealize Automation. Aqui, para fins didáticos, continuo utilizando o termo vRA.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *