I had a power outage recently that took out my entire lab in a very ungraceful manner - everything, well mostly everything, came back up without a hitch - but NSX was acting a bit weird, so I decided to redeploy the NSX Controllers.

I removed all 3 controllers and tried redeploying but ended up with the error “No IPs left in pool NSX-Controllers”. If you’re familiar with NSX, then you know when creating both controllers and VTEPs you’re required to configure IP Pools in NSX Manager to allocate IP addresses from.

What has happened in this instance is, I removed the controllers, but for some reason, NSX Manager was not made aware of these changes and now the IPs are showing as used when in fact they’re free - hence, orphaned.

I went API diving and found this could be resolved with a few calls in POSTman - if you don’t fancy the API PDF ↗ in its 450-page glory, I recommend running Platypus ↗ in Docker on your workstation, or you can access a hosted version here ↗.

It provides a Swagger instance for a nice overview of the available APIs and their responses:

Swagger API

So, let’s get down to it - you want to query the IPPool IDs on your instance:

GET https://{{nsxmanagerIP}}/api/2.0/services/ipam/pools/scope/globalroot-0

Then from the response body, we want the objectId associated with the NSX-Controllers IP Pool object:

<ipamAddressPools>
    <ipamAddressPool>
        <objectId>ipaddresspool-1</objectId>
        <objectTypeName>IpAddressPool</objectTypeName>
        <vsmUuid>421190C6-9A73-BBBC-B646-11767FC2B08D</vsmUuid>
        <nodeId>532eeed7-4e72-419b-84a2-6e9c212e1810</nodeId>
        <revision>1</revision>
        <type>
            <typeName>IpAddressPool</typeName>
        </type>
        <name>NSX-Controllers</name>
        ......

From this, we can query the “active” IP addresses in the pool (though you probably know these already):

GET https://{{nsxmanagerIP}}/api/2.0/services/ipam/pools/ipaddresspool-1/ipaddresses

And then we can delete each offending IP:

DELETE https://{{nsxmanagerIP}}/api/2.0/services/ipam/pools/ipaddresspool-1/ipaddresses/10.0.3.170

If successful you should now be able to re-deploy your controllers with the IP Pool as before and see the following output in POSTman for each DELETE:

<?xml version="1.0" encoding="UTF-8"?>
<boolean>true</boolean>

Why not follow @mylesagray on Twitter ↗ for more like this!