# Use vCenter APIs

> Reach vCenter directly from plugin code through its vSphere Web Services API or its vSphere Automation API

---

Site [llms.txt](/llms.txt)

---

Cloud Management Platform (CMP) already manages the resources in a vCenter, but when you need something it does not expose, both vCenter APIs are reachable from a resource handler without setting up your own connection or credentials.

## vSphere Web Services API

The vSphere Web Services API is stable, changes infrequently, and keeps backward compatibility with earlier versions. It is based on SOAP and XML, which makes it complex to call directly.

CMP ships the `pyvmomi` Python bindings to mitigate the complexity. They are not especially Pythonic and take more effort than bindings such as `Boto3`, but they are supported by CMP.

See VMware's [vSphere Web Services API reference](https://developer.broadcom.com/xapis/vsphere-web-services-api/latest/).

## ServiceInstance: the root of the vCenter and ESXi API

`ServiceInstance` is the vCenter `ManagedObject` that serves as the singleton root of the API inventory on vSphere and ESXi servers.

1. Get the singleton from a connected vCenter server. CMP exposes it through the `VsphereResourceHandler` model.

   ```python
   # Assuming the variable rh is a VsphereResourceHandler
   wrapper = rh.get_api_wrapper()
   si = wrapper._get_connection()
   ```

1. With a reference to the `ServiceInstance` for your resource handler, call the API on that vCenter directly. This example retrieves a virtual machine's summary.

   ```python
   RH_ID = 1          # The ID for a vSphere ResourceHandler
   SERVER_ID = 1000   # A Server ID for a server in the above ResourceHandler

   server = Server.objects.get(id=SERVER_ID)
   rh = VsphereResourceHandler.objects.get(id=RH_ID)
   wrapper = rh.get_api_wrapper()
   si = wrapper._get_connection()
   index = si.content.searchIndex

   vm = index.FindByUuid(
     uuid=server.resource_handler_svr_id,
     vmSearch=True)

   print(vm.summary if vm else "VM Not Found.")
   ```

The `ServiceInstance` gives you a `ServiceContent` object, which exposes the vCenter managed objects used to retrieve content in various ways. The example uses the `SearchIndex` singleton and its `FindByUuid` method, passing the UUID held on the CMP server record along with a flag indicating to search for a virtual machine.

Common pyvmomi gotchas:

- The capitalization is not conventional Python. Method names are CamelCase because the bindings are generated from the vSphere Web Services API.
- Calls and properties are dispatched dynamically, so an IDE cannot autocomplete them. The API reference is the way to find what is available.

## vSphere Automation API

The vSphere Automation API, added in vSphere 6.5, is a REST API that is easier to work with than the Web Services API and more consistent with other vendors' APIs.

See VMware's [vSphere Automation API reference](https://developer.broadcom.com/xapis/vsphere-automation-api/latest/).

### Use the Automation API with a vCenter resource handler

CMP provides `resourcehandlers.vmware.vapi_wrapper.VsphereRESTClient` for calling this API with an existing vCenter resource handler. Build one from the handler's own connection details.

```python
client = VsphereRESTClient(
    host=rh.ip,
    port=rh.port,
    username=rh.serviceaccount,
    password=rh.servicepasswd,
    protocol="https",
    ssl_verification=rh.get_ssl_verification()
)
```

The client exposes some methods of its own, and all other operations are performed via HTTP POST or GET, depending on the API function. This example uses POST to list the objects a given vCenter tag is applied to.

```python
# The following ID corresponds to an existing tag in our vCenter
TAG_ID = "urn:vmomi:InventoryServiceTag:0c43707b-39bd-4f69-8e16-4a2e7bff3755:GLOBAL"

client = VsphereRESTClient(
    host=rh.ip,
    port=rh.port,
    username=rh.serviceaccount,
    password=rh.servicepasswd,
    protocol='https',
    ssl_verification=rh.get_ssl_verification()
)

# Get objects in vCenter that are tagged with TAG_ID
response = client.post(
    uri=f"/rest/com/vmware/cis/tagging/tag-association"
        f"/id:{TAG_ID}?~action=list-attached-objects", data={})
client.close_session()

# Let's iterate thru the JSON returned to print tagged VMs
for moid in [value.get('id') for value in response.get('value')
             if value.get('type') == 'VirtualMachine']:
  print(moid)
```

<div class="alert alert-info" role="alert">


The call invokes the `list-attached-objects` action on the tag URI `/rest/com/vmware/cis/tagging/tag-association/id:{TAG_ID}`. Note also that `VsphereRESTClient.post` returns a `dict`, having already unmarshalled the JSON response, rather than the `requests.Response` object that `requests.post` returns.
</div>


## Related

- [VMware vCenter](/docs/cmp/configure/infrastructure/resource-handlers/vmware-vcenter/): the resource handler these examples run against.
- [Minimum required permissions in vCenter/VMware](/docs/cmp/configure/infrastructure/resource-handlers/vmware-vcenter/minimum-permissions/): the privileges the account making these calls holds.
- [Developer guide](/docs/cmp/developer-resources/guide/): where plugin code lives and how it runs.
