Enthusiast
Enthusiast

Manually set IP in VRA 8.1

What I am trying to do is to set the IP address of the VM manually so I do not have to use an IP Range. My company has a bluecat IPAM, and I have a powershell script that will get an available ip for the network from bluecat. We do not have the bluecat intetgration for vra and are not purchasing it. In vra 7.6 with vro I used virtualMachineAddOrUpdateProperties to set the IP and it worked fine.

I am now trying to get the same using VRA 8.1, on-prem, with powershell and an ABX. I have a VRA network profile with 1 network 10.7.127.0/24 and it has 1 IP range in VRA of .5-.10. When I deploy a blueprint and the YAML has assignment:static for my network resource the vm deploys and it obtains 1 of the addresses from the IP Range (example .6) no problem. When I deploy a blueprint and the YAML has assignment:static for my network resource the VM deploys but it keeps it's original IP (.252).

How do I set a static IP in 8.1? I have an ABX subscribed to compute.provision.pre and compute.provision.post. These both have a place in JSON for addresses.

I use the ABX and inject into addresses, the 1st addres out of my range, 10.7.127.11

Outputs

{

  "tags": {},

  "target": "World",

  "zoneId": "5ad9740d-6829-4739-8a92-46c297c90ffc",

  "addresses": [

    [

      "10.7.127.11"

    ]

  ],....

Even with this output, if assignment:static is set in YAML, I get an address from the IP range, not the manually specified IP address .11

What am  I doing wrong? It was much easier in 7.6 I must be missing something simple.

thanks,

ds

0 Kudos
10 Replies
Enthusiast
Enthusiast

As a note, it also works in in the blueprint I have

formatVersion: 1

inputs:

  vmName:

    type: string

resources:

  Cloud_vSphere_Network_1:

    type: Cloud.vSphere.Network

    properties:

      networkType: existing

  Cloud_vSphere_Machine_1:

    type: Cloud.vSphere.Machine

    properties:

      image: MD2016

      flavor: Small

      networks:

        - network: '${resource.Cloud_vSphere_Network_1.id}'

          assignment: static

          address: 10.7.127.13

      userDefinedName: '${input.vmName}'

As long as IP falls in my IP Range, it will honor the address. I THINK if I can find where address: gets set, I will be good.

0 Kudos
Contributor
Contributor

I would recommend taking a look at Vmware‘s IPAM SDK for vRA8. I takes a little bit of coding, but you end up with a nice integration in vRA:

VMware vRealize Automation Third-Party IPAM SDK - VMware {code}

It will be more effort in first place, but it will be worth it when it comes to multi vm, multi nic deployments as all this gets handled out of the box.

0 Kudos
Enthusiast
Enthusiast

I looked at that, seems a little extreme for something as simple as setting an IP on a VM. There has to be some point in the build process where something fires and assigns the IP to the vm. Also, what is the addresses array in the JSON for anyway?

0 Kudos
Contributor
Contributor

If you want to code it as ABX actions you have to subscribe at "network configure".  At this point you have the selected network available to get an IP address from your IPAM and shoot the array back to vRA. It is an array to cover the occasion of multiple IP addresses in the same subnet.

Note: At "network configure" you don't have the VM name in the payload if you need to use this for your IPAM entry. It will be in the payload at "compute provision" in case you wan't to grab that and update your IPAM (At least in vRO it's like that)

0 Kudos
Enthusiast
Enthusiast

Thank you. But what array in network configure? And I am not married to doing this in ABX, orchestrator is fine too.

I see the address come across in compute.provision.pre like this:

"eventTopicId": "compute.provision.pre"

Inputs

{

  "tags": {},

  "target": "World",

  "zoneId": "5ad9740d-6829-4739-8a92-46c297c90ffc",

  "addresses": [

    [

      "10.7.127.13"

    ]

  ],...

"eventTopicId": "compute.provision.pre"

Inputs

{

  "tags": {},

  "target": "World",

  "zoneId": "5ad9740d-6829-4739-8a92-46c297c90ffc",

  "addresses": [

    [

      "10.7.127.13"

    ]

  ],...

----------------------------

-------------------------

NETWORK CONFIGURE

Inputs

{

  "tags": {},

  "target": "World",

  "zoneId": "5ad9740d-6829-4739-8a92-46c297c90ffc",

  "projectId": "f1a58110-e3b2-4e8e-b516-76c5d86e82bf",

  "requestId": "21359875-a60f-4b19-acf3-8da24f50318f",

  "__metadata": {

    "orgId": "b3288c09-4f8f-4bb0-b454-d76df922ee89",

    "headers": {

      "tokenId": "WK5yxiTlywCE6Q7sRthCbN32Eamu6F8LZyruLGwgXdU=",

      "blocking": "false",

      "runnableId": "8a7480a7742b94320174b75eb7ab011d",

      "runnableType": "extensibility.abx",

      "uber-trace-id": "757b12c8092b4185b360de1f331a322a:8a8e1b1a05df45a49aa60966f65403a0:57bb1ba8-53d9-4883-bf28-0b8fcd03df46:1",

      "uberctx-org-id": "b3288c09-4f8f-4bb0-b454-d76df922ee89",

      "uberctx-user-id": "provisioning-aAIfSaQTCsPeW014",

      "eventTraceEntryId": "393a5c22-e6f0-4855-ab6d-bd5bf9643518",

      "sampling-decision": "true",

      "uberctx-parent-id": "57bb1ba8-53d9-4883-bf28-0b8fcd03df46",

      "provisioning-callback-uri": "/provisioning/config/extensibility-callbacks/0b5b6428-155d-4292-a960-652c84f15807"

    },

    "targetId": "929e95d4-6271-4fbe-8faa-3eee87d9ff15",

    "userName": "infra_admin",

    "eventType": "EVENT",

    "timeStamp": 1600895144498,

    "sourceType": "provisioning",

    "targetType": "ComputeAllocationTaskState",

    "eventTopicId": "network.configure",

    "correlationId": "f23fb13c-5ead-417f-9949-601ed7fd6444--21359875-a60f-4b19-acf3-8da24f50318f",

    "sourceIdentity": "50305e4e-67fe-4262-b712-330da0cec4af",

    "correlationType": "contextId"

  },

  "endpointId": "16203e85-87ab-403c-9e92-72b6f51ddf94",

  "blueprintId": "541471c8-d22e-46bf-a077-376eac567ac9",

  "componentId": "Cloud_vSphere_Machine_1",

  "externalIds": [

    "testVM020"

  ],

  "resourceIds": [

    "b289b480-e81b-495e-95db-575137e5becf"

  ],

  "deploymentId": "f23fb13c-5ead-417f-9949-601ed7fd6444",

  "componentTypeId": "Cloud.vSphere.Machine",

  "customProperties": {

    "image": "MD2016",

    "flavor": "Small",

    "userDefinedName": "testVM020"

  },

  "networkProfileIds": [

    "e301361b-a2a2-4239-8116-973952e889f9"

  ],

  "networkSelectionIds": [

    [

      [

        "d20385a3-ebfc-405e-80c3-9817adebf535"

      ]

    ]

  ]

}

Outputs

{

  "tags": {},

  "target": "World",

  "zoneId": "5ad9740d-6829-4739-8a92-46c297c90ffc",

  "projectId": "f1a58110-e3b2-4e8e-b516-76c5d86e82bf",

  "requestId": "21359875-a60f-4b19-acf3-8da24f50318f",

  "endpointId": "16203e85-87ab-403c-9e92-72b6f51ddf94",

  "blueprintId": "541471c8-d22e-46bf-a077-376eac567ac9",

  "componentId": "Cloud_vSphere_Machine_1",

  "externalIds": [

    "testVM020"

  ],

  "resourceIds": [

    "b289b480-e81b-495e-95db-575137e5becf"

  ],

  "deploymentId": "f23fb13c-5ead-417f-9949-601ed7fd6444",

  "componentTypeId": "Cloud.vSphere.Machine",

  "customProperties": {

    "image": "MD2016",

    "flavor": "Small",

    "userDefinedName": "testVM020"

  },

  "networkProfileIds": [

    "e301361b-a2a2-4239-8116-973952e889f9"

  ],

  "networkSelectionIds": [

    [

      [

        "d20385a3-ebfc-405e-80c3-9817adebf535"

      ]

    ]

  ]

}

0 Kudos
Enthusiast
Enthusiast

If you look at the schema for the Network Configure event under the Extensibility tab in Cloud Assembly, you'll see a few network related arrays in there. 

Specifically, I believe the addresses array is what you need to populate.  That field is a 2-dimensional array.  The first dimension represents the machine you're configuring.  If you only have one machine on your blueprint, it will always be 0.  The second dimension represents the Nic on that machine.  So for example, addresses[0][0] would be nic0 on the first machine (which is probably what you need to set).  And addresses[2][1] would be the second nic on the 3rd machine in the blueprint/deployment.

I'm not familiar with ABX, but with workflows those values are set as output variables.  So in our case, we have a workflow that subscribes to Network Configure.  In that workflow, we have Output variables for all of the network fields we need to set, including the addresses array.  We go through our process of getting IPs and then we populate the Output addresses array.  Since it's an output, it gets sent back to vRA and then it's used for actually configuring the nics during os customization.

One thing to note, the fields that come out of a workflow (and ABX I'm assuming) need to match exactly what is defined in the schema for that event.

Hope that helps.

0 Kudos
Contributor
Contributor

It's exactly as emacintosh described. That's also how we used to handle things in orchestrator before we moved to coding our own plugin.

Also thanks for mentioning that addresses is a two dimensional array, I forgot about that.

Btw, in this article you can see how "addresses" gets handled in the workflow output:

https://cloudbrokers.blog/IPAM-Integration-with-VMware-Cloud-Assembly

0 Kudos
Enthusiast
Enthusiast

Got it figured out. Thanks for the help!

Using the suggested links etc, this is what I got:

In the blueprint, do not use assignment: static. VRA will look for an assigned IP Range and will give an error if it can't find one, which in my case it would not as I do not want to create one.

Using assignment:dynamic (or not specifying it at all), setting addresses will result in the IP being assigned along with the rest of the network information from the network (gateway, dns, etc).

I did see 'skipIPAllocation' in the network.configure event, but did not explore it, could not find any documentation.

Also as a note, setting IPs leverages vmware tools. A customization spec is sent. So, VM will reboot several times and then show IP.

Also, as I was looking to do this in powershell in an ABX,

set at blocking

here is the code:

function handler($context, $payload) {

     #full JSON   

     Write-host "** Start JSON Payload***"

    $payloadjson = $payload | ConvertTo-Json -Compress   

    Write-host  $payloadjson

    Write-host "** END JSON Payload"

     # dump properties    

     Write-host "*** Start Property dump"

    $payload.psobject.properties | ForEach-Object {

            Write-host $_.Name

            Write-host "  "$_.Value

        }

    Write-Host "*** END Propety dump"

    $returnObj = $payload

    $returnObj | Add-Member -membertype noteproperty -name addresses -value $null

     #Can get address from IP here, or retrieve it from a custom property from blueprint etc, just using dummy address on subnet here

     #note how the array is set using unary array construction operator (or comma operator), so you get an array nested in another array

    $returnObj.addresses = ,@("10.7.129.12")

     #verify properties set correctly   

     Write-host "*** Property dump after setting returnObj"

    $returnObj.psobject.properties | ForEach-Object {

            Write-host $_.Name

            Write-host "  "$_.Value

        }

    Write-Host "*** END Propety dump"

    return $returnObj

}

0 Kudos
Contributor
Contributor

Glad you figured it out. Just to let you know: It will work with static assignment, but only if you are on 8.1 P2.

Ending up with "Could not find Range" was a bug introduced in 8.1 that I reported and got fixed in 8.1 P2.

You can find it here under attachments:

https://kb.vmware.com/s/article/79170

"(fix) IP Range required when deploying with a static IP using extensibility IPAM event"

0 Kudos
Enthusiast
Enthusiast

glad I found this post!

networkSelectionIds appears to be the networks associated with a network profile rather than whats tied to the machine in the blueprint.

My blueprint has just one network configured; 

Cloud_vSphere_Machine_1:
type: Cloud.vSphere.Machine
attachedDisks: []
properties:
...
networks:
- network: '${resource.Cloud_Network_1.id}'

assignment: static
...
Cloud_Network_1:
type: Cloud.Network
properties:
networkType: existing
name: dsVlan255

When there's only one network defined in Network Profiles the payload contains only one entry for networkSelectionIds, but when there are one or more networks defined in Network Profiles, the payload contains networkSelectionIds for all of the networks even though the blueprint only has one.

network profile - one network.png

networkSelectionId's workflow run;
2020-11-25 16:18:22.550 +00:00INFOcd906a44-a02e-4335-b3dd-b6a83ed6f327
2020-11-25 16:18:22.645 +00:00INFOCloud Network No: 0 {"isDefault":true,"cidr":...

network profile - two networks.png

networkSelectionId's workflow run;

2020-11-25 16:41:17.682 +00:00INFOExtracting network selection IDs from payload
2020-11-25 16:41:17.683 +00:00INFOcc81cffd-c8bf-4e18-9237-a66cf999dde2,cd906a44-a02e-4335-b3dd-b6a83ed6f327
2020-11-25 16:41:17.756 +00:00INFOCloud Network No: 0 {"cidr"....
2020-11-25 16:41:17.783 +00:00INFOCloud Network No: 1 {"isDefault":true,"cidr"....

I was expecting the networkselectionId's for the network the deployed vm is associated with and expecting an ip address from, unless I'm missing something here?

Any help most welcome on this!

0 Kudos