vCHS APIs 102
In the vCHS API 101 blog post I have walked you through how to find out your vCHS API end-point(s) as well as how to navigate the structure with the RESTClient browser plug-in. This was more or less a read-only tour of the structure of the objects in the virtual data center.
In this post I’d like to show you how to instantiate a VM in vCHS and customize it. Particularly we are going to instantiate a VM from a catalog. In this case the vCHS public catalog.
At this point you should be able to login into your virtual data center, and locate a vApp template in a catalog available to you. As a refresh, the steps are:
login per the instruction in the vCHS API 101
query your organization
query your catalog
query your catalog item
The catalog item I have chosen is the
CentOS64-64bit. A 64 bit version of a CentOS 6.4 image. This is the result of that query:
The name and href of the entity inside the catalog item is what I will need to reference when I deploy this template. In other words, the href above represents the actual vApp template.
Now, how do you instantiate this template? To instantiate a template you need to move into the context of your virtual datacenter and there you will find the href of the instantiateVAppTemplate action.
For me the virtual data center href to query is
Note: this is what I am using in my REST calls below. Your virtual data center URL will obviously be different so you will have to adjust it.
Inside that virtual data center, when you query it with the GET, you should find something along the lines of:
<Link rel=”add” type=”application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml” href= “https://p1v14-vcd.vchs.vmware.com:443/api/vdc/1c10eda5-5b99-44b9-85f8-a6c54e8f13d6/action/instantiateVAppTemplate” />
This will give you the href (or URL) you need to call and also the type of the call.
Note: when you instantiate (or modify) something, you need to pass parameters that describe the change you are making. These parameters need to be passed in XML format. The type describes the layout of these XML parameters and their structure. The structure with the parameters will need to be pasted into the so called Body of the request.
This isn’t required when you query (GET …) objects but it is required when you instantiate or change (POST or PUT …) them.
Enough for the theory. In the next few sessions I am going to demonstrate how to create a vApp from the catalog and change its configuration settings.
But before we start, this picture shows you where, in the RESTClient, you should use the information provided in the sections below. In particular notice the location of the Method, the URL, the Content-Type (in the Header Name section) and the Body:
How to deploy a vApp
The vApp I have decided to deploy from the catalog (see above) is a fairly simple vApp that only contains one Linux CentOS VM.
By following the example provided above this is what you should be calling (I am also providing the page of the manual that describes the action and the sample code I used as a basis)
Manual page: http://pubs.vmware.com/vcd-51/index.jsp#com.vmware.vcloud.api.doc_51/GUID-EBA7704F-0D94-4AA1-815F-C3352FE89766.html Method: POST URL: https://p1v14-vcd.vchs.vmware.com:443/api/vdc/1c10eda5-5b99-44b9-85f8-a6c54e8f13d6/action/instantiateVAppTemplate Content-Type: application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml Body: <?xml version=”1.0″ encoding=”UTF-8″?> <InstantiateVAppTemplateParams xmlns=”http://www.vmware.com/vcloud/v1.5” name=”vApp-API” deploy=”false” powerOn=”false” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:ovf=”http://schemas.dmtf.org/ovf/envelope/1″> <Description>vApp API</Description> <InstantiationParams> <NetworkConfigSection> <ovf:Info>Configuration parameters for logical networks</ovf:Info> <NetworkConfig networkName=”TechServices-GW-default-routed“> <Configuration> <ParentNetwork href=”https://p1v14-vcd.vchs.vmware.com:443/api/network/58b97c77-451c-4da5-8a92-ad682c4559f3” /> <FenceMode>bridged</FenceMode> </Configuration> </NetworkConfig> </NetworkConfigSection> <LeaseSettingsSection type=”application/vnd.vmware.vcloud.leaseSettingsSection+xml”> <ovf:Info>Lease Settings</ovf:Info> <StorageLeaseInSeconds>172800</StorageLeaseInSeconds> <StorageLeaseExpiration>2010-04-11T08:08:16.438-07:00</StorageLeaseExpiration> </LeaseSettingsSection> </InstantiationParams> <Source href=”https://p1v14-vcd.vchs.vmware.com:443/api/vAppTemplate/vappTemplate-83b9b5bc-3508-49ce-9b42-9bb531087852” /> <AllEULAsAccepted>true</AllEULAsAccepted> </InstantiateVAppTemplateParams>
Notice in red the fields I customized that deviates from the code sample in the documentation. Some of them are cosmetic and totally up to you (e.g. the Name and the Description of the vApp).
Others needs to be depicted from your actual configuration such as, for example, the Source (which is the href of the template you are trying to deploy from) and the ParentNetwork (which is the href of the virtual data center network you are going to connect the VM to).
Note that dealing with the APIs you get full visibility into the rich (but more complex) vApp construct. The way you connect a VM to an Org Network is by declaring a vApp Network that is directly connected to the organization virtual data center network. You do so by setting the FenceMode to bridged. All this happens behind the scenes if you deploy from the vCHS portal.
By the way, when you configure the vApp Network to direct connect (bridged) to the organization network, the networkName parameter in the XML body gets ignored. The vApp Network in this case will automatically inherit the name of the organization network you are connecting to (which in my case is called TechServices-GW-default-routed and its described by the href in the ParentNetwork).
If you run the call above you should receive a
201 Created Status Code at the bottom of the RESTClient and this is what you see in the vCHS interface:
Note the name of the vApp, the fact that it’s powered off and that the name of the VM in the vApp is still the default name of the VM template.
If you click on the properties of the VM you will also find that the VM isn’t connected to any network. In fact we have made available in the vApp the TechServices-GW-default-routed network but we haven’t configured (yet) the VM to connect to that network:
Last but not least the computer name (guest OS name) of this VM is still the computer name as found in the template.
How to connect the VM vNIC to the network
Now you need to navigate the vApp we just deployed and locate the VM inside it. The VM section will have a bunch of parameters one of which relates to the VM network configuration. The URL below will need to be adapted to your own vApp / VM instantiation. Note also that the type points to the structure that describes the actual content we are passing in the body.
Straight into the code now.
Manual page: http://pubs.vmware.com/vcd-51/index.jsp#com.vmware.vcloud.api.doc_51/GUID-2F5C3326-4A6B-4784-BE36-99066B8CEE8A.html Method: PUT URL: https://p1v14-vcd.vchs.vmware.com:443/api/vApp/vm-c7f064e4-4ce6-43d4-a34f-fdbd6e29d8b5/networkConnectionSection/ Content-Type: application/vnd.vmware.vcloud.networkConnectionSection+xml Body: <?xml version=”1.0″ encoding=”UTF-8″?> <NetworkConnectionSection type=”application/vnd.vmware.vcloud.networkConnectionSection+xml” xmlns=”http://www.vmware.com/vcloud/v1.5” xmlns:ovf=”http://schemas.dmtf.org/ovf/envelope/1″> <ovf:Info>Firewall allows access to this address.</ovf:Info> <PrimaryNetworkConnectionIndex>0</PrimaryNetworkConnectionIndex> <NetworkConnection network=”TechServices-GW-default-routed“> <NetworkConnectionIndex>0</NetworkConnectionIndex> <IpAddress /> <IsConnected>true</IsConnected> <MACAddress>00:50:56:01:01:49</MACAddress> <IpAddressAllocationMode>POOL</IpAddressAllocationMode> </NetworkConnection> </NetworkConnectionSection>
Now it is critical that we set the name of the network to the actual name of the network we have configured in the previous API call above. When we have done that we will let vCD to assign an IP coming from a pool that is already configured on that network (via the IpAddressAllocationMode section).
Now the VM is connected to the proper network and vCD assigned the 192.168.109.5 IP automatically from the pool defined on that network:
How to change the computer name of the VM
I am particularly interested in this API call because, at the time of this writing, you cannot do that in the vCHS portal. The VM will keep the computer name as defined in the template.
With this simple REST API call you can set your computer name of choice. Notice we have just changed the URL to point to the guest customization section for the VM (and obviously we had to change the type to match the proper structure we are passing in the body).
Manual page: http://pubs.vmware.com/vcd-51/index.jsp#com.vmware.vcloud.api.doc_51/GUID-1BA3B7C5-B46C-48F7-8704-945BC47A940D.html Method: PUT URL: https://p1v14-vcd.vchs.vmware.com:443/api/vApp/vm-c7f064e4-4ce6-43d4-a34f-fdbd6e29d8b5/guestCustomizationSection/ Content-Type: application/vnd.vmware.vcloud.guestcustomizationsection+xml Body: <?xml version=”1.0″ encoding=”UTF-8″?> <GuestCustomizationSection xmlns=”http://www.vmware.com/vcloud/v1.5” xmlns:ovf=”http://schemas.dmtf.org/ovf/envelope/1” ovf:required=”false”> <ovf:Info>Specifies Guest OS Customization Settings</ovf:Info> <Enabled>true</Enabled> <ChangeSid>false</ChangeSid> <VirtualMachineId /> <JoinDomainEnabled>false</JoinDomainEnabled> <UseOrgSettings>false</UseOrgSettings> <AdminPasswordEnabled>true</AdminPasswordEnabled> <AdminPasswordAuto>true</AdminPasswordAuto> <AdminPassword /> <ResetPasswordRequired>false</ResetPasswordRequired> <CustomizationScript /> <ComputerName>VMAPI</ComputerName> </GuestCustomizationSection>
We don’t want to change the SID of the VM (it’s actually a Linux VM so it will not even apply). The other thing you want to do is to change the ComputerName which is what actually changes the Linux guest OS name.
Note that, in my tests, I have also had to remove the sections DomainName, DomainUser and DomainPassword from the suggested code sample in the documentation. The API call was complaining that, with JoinDomainEnabled = false, there should not be any domain related parameter.
If you power on the VM in the vCHS portal (yes you can do that from the APIs as well but I didn’t bother to), you can see that the OS name has been customized properly (VMAPI) as set in the body of the call above:
How to change the VM name, the computer name and the network of the VM in one single API call
So far we have seen how to instantiate a vApp (first API call), how to change the network of the VM (second API call) and how to change the computer name of the VM (third API call).
In this section we are going to rewind this movie back to right after the first API call. For the purpose of this exercise I am going to delete the VM I have created above and I am going to deploy a brand new one from the catalog with the instantiateVAppTemplate call. Notice that the href of the VM I will be using is different (because this is a new vApp and a new VM).
The following API call does the network, OS name as well as the VM name changes in one single call.
Manual page: http://pubs.vmware.com/vcd-51/index.jsp#com.vmware.vcloud.api.doc_51/GUID-4759B018-86C2-4C91-8176-3EC73CD7122B.html Method: POST URL: https://p1v14-vcd.vchs.vmware.com:443/api/vApp/vm-0d251e1f-7b3f-4ee3-aca9-517388a83acc/action/reconfigureVm Content-Type: application/vnd.vmware.vcloud.vm+xml Body: <?xml version=”1.0″ encoding=”UTF-8″?> <Vm xmlns=”http://www.vmware.com/vcloud/v1.5″ nestedHypervisorEnabled=”false” needsCustomization=”true” deployed=”true” status=”8″ name=”VM-API” id=”urn:vcloud:vm:0d251e1f-7b3f-4ee3-aca9-517388a83acc” type=”application/vnd.vmware.vcloud.vm+xml” href= “https://p1v14-vcd.vchs.vmware.com:443/api/vApp/vm-0d251e1f-7b3f-4ee3-aca9-517388a83acc”> <NetworkConnectionSection type=”application/vnd.vmware.vcloud.networkConnectionSection+xml” xmlns=”http://www.vmware.com/vcloud/v1.5” xmlns:ovf=”http://schemas.dmtf.org/ovf/envelope/1″> <ovf:Info>Firewall allows access to this address.</ovf:Info> <PrimaryNetworkConnectionIndex>0</PrimaryNetworkConnectionIndex> <NetworkConnection network=”TechServices-GW-default-routed“> <NetworkConnectionIndex>0</NetworkConnectionIndex> <IpAddress /> <IsConnected>true</IsConnected> <MACAddress>00:50:56:01:01:49</MACAddress> <IpAddressAllocationMode>POOL</IpAddressAllocationMode> </NetworkConnection> </NetworkConnectionSection> <GuestCustomizationSection xmlns=”http://www.vmware.com/vcloud/v1.5” xmlns:ovf=”http://schemas.dmtf.org/ovf/envelope/1” ovf:required=”false”> <ovf:Info>Specifies Guest OS Customization Settings</ovf:Info> <Enabled>true</Enabled> <ChangeSid>false</ChangeSid> <VirtualMachineId /> <JoinDomainEnabled>false</JoinDomainEnabled> <UseOrgSettings>false</UseOrgSettings> <AdminPasswordEnabled>true</AdminPasswordEnabled> <AdminPasswordAuto>true</AdminPasswordAuto> <ResetPasswordRequired>false</ResetPasswordRequired> <CustomizationScript /> <ComputerName>VM-API-OS</ComputerName> </GuestCustomizationSection> </Vm>
Again, the red text in the body represents the customizations and deviations from the sample code found in the documentation. The initial part needs to be customized a bit and it needs to include he id and href of the VM against which you are running the reconfigureVm action.
Note this is no longer a PUT method where we “override” some parameters but it’s rather a real POST where we run the action above (reconfigureVm).
In the opening of the body is where we set the VM name (I set it to VM-API). Below that I set the network (TechServices-GW-default-routed) and the computer name (VM-API-OS). I have copied that string from the VM description when I queried the vApp.
Other than having to remove all domain related XML entries, I had also to remove the AdminPassword entry as it complained it was in there. For some reasons the syntax I used in one of the bodies above didn’t work here. I had to remove the entry entirely from this body.
I am not showing screenshot of the network connection as well as the customized computer name. You have to trust me it worked.
However the following screenshot shows the new VM name in the vCHS portal:
I am not suggesting the code and sequence of API calls I have used above is the best ever. Perhaps there are shortcuts to do similar things. However it’s a good exercise to learn how the basic works. In particular I am dealing with these types and actions and schema in a very mechanical way, if you will. Copying and pasting code samples from the documentation, instinctively trying to understand how it works and where to change things.
What fascinates me about this whole REST thing is that there is a very logical and clear correlation between the result you get from the queries, the schema you have to set in the Content-Type and all that.
I haven’t grasped 100% of it but I am working towards that.
I don’t think anyone, in a proper state of mind, would ever broadly use raw REST calls as part of a complex development project. As I suggested in the vCHS API 101 blog post you may want to use language bindings for doing serious programming work against the vCHS APIs. Having that said I think it’s always good to understand how the mechanic in the back works before you move to the next level of abstraction.