Use VM Roles in Windows Azure Pack with Java

 

Applies To: Windows Azure Pack

This guide demonstrates some basic tasks a tenant developer can do with virtual machine roles (VM roles), including creating, updating, and scaling a VM role instance. The code examples are written in Java and were created using the Eclipse IDE. Because the examples in this guide use the HTTP REST-based service of the Service Management API, you could modify these examples to work with any other language capable of sending HTTP operation requests. For a guide to all of the URLs that are available for VM roles, see the URL Cheat Sheet for VM Roles [SPFSDK][VMROLE].

VM roles can represent one or more virtual machines dedicated to a specific operation, such as a web server or web worker. Service providers can offer tenants a self-service experience for provisioning virtual machines through a curated gallery of virtual machine roles. Tenants can provision VM roles from the gallery by using the tenant portal UI or the HTTP REST-based service. VM roles differ from the traditional model of provisioning virtual machines because they provide a scale operation that enables you to adjust the number and version of virtual machines easily. For a guide to using virtual machines with WAP and Java with the traditional provisioning model, please see Virtual Machine Management with Java. The capabilities offered with VM roles can assist the fast provisioning and de-provisioning of your applications when you need to adjust the number and version of your virtual machines.

Service Provider Foundation and Windows Azure Pack for Windows Server expose an extensible service that enables service providers to build multi-tenant portals. A tenant is a self-service customer of the service provider. The service provider associates the tenant’s account with a subscription-id, and provides a public key to a security certificate used to verify the tenant. Prerequisite to running the examples in this guide you will need to have a subscription with a service provider offering a VM role gallery, a cloud service in the subscription to host the VM role, and a virtual network in the subscription to place virtual machines. If your service provider has given you a user name and password, you can log into the tenant portal UI and there find your subscription-id. While logged into the portal you can upload a certificate that enables the host to verify you as a trusted user and you can create a virtual network which you can use to place virtual machines.

After running the samples in this guide you should be able to do the following tasks with Java code.

  • Create a cloud service to host VM roles

  • Get a list of VM Roles from the gallery

  • Get a reference to a VM role gallery item

  • Create a new VM role instance

  • Scale a VM role

  • Start, stop, restart, shutdown, or delete a virtual machine

  • Update or delete a VM role

Create a cloud service to host VM roles

You must have a cloud service in your subscription to host VM roles. To list of all the cloud services, send a HTTP GET operation request to the following URL for CloudServices. Note that anytime you use an URL with the VM role gallery or cloud services, you must also append the api-version=2013-03 query string. The query string always starts with the ? character after the URL.

https://server:port/subscription-id/CloudServices?api-version=2013-03

The following Java code example, Get_list, can return all the cloud services in your subscription. The examples in this guide will represent your subscription-id by the string: 2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa. In general, you can set the x-ms-principal-id header to the email of the tenant associated with the current subscription.

public class Get_list 
{
public static void main(String[] args) throws Exception 
   {
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices?api-version=2013-03";       
   URL url = new URL(u);                       
   HttpURLConnection c = null;        
   c = (HttpsURLConnection)url.openConnection();
   c.setRequestMethod("GET");
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null){System.out.println(decodedString);}
   in.close();
   }
}

If the value field in the HTTP response is empty, this means you have no cloud services in your subscription and you’ll need to create one before provisioning a VM role. You can create a cloud service by sending a HTTP POST operation request to the same CloudServices URL, but in the request body you should specify a Name and Label for the new cloud service. For the examples in this guide, the OData added to the body of an HTTP request can be saved in a text file on your computer named odata.txt. For example, sending the following odata.txt can be used to create a cloud service named TestingCloudService799.

{
    "Name": "TestingCloudService799",
    "Label": "TestingCloudService799"
}

All the Java code examples read odata.txt using the following getpayload() method.

public class Data 
{
private String s;
public Data() 
   {
   String fileName = ("C:"+File.separator+"test"+File.separator+"odata.txt");
   File dataFile = new File(fileName);
   byte[] content = new byte[0];
   {      
   try {FileInputStream dataInputStream = new FileInputStream(dataFile);
      int bytesAvailable = dataInputStream.available();
      content = new byte[bytesAvailable];
      dataInputStream.read(content);
      dataInputStream.close();}       
   catch (FileNotFoundException fnfe) {System.out.println("Couldn't find a file called " + fileName);}       
   catch (IOException ioe) {System.out.println("Couldn't read from a file called " + fileName);}      
   this.s = new String(content);
   }
   }
   public String getpayload(){return s;}
 }

The Java code example, Create_cs, creates a new cloud service named TestingCloudService799. It reads odata.txt, streams this information into a HTTP body, sets the headers, and then sends a POST operation request to the Cloudservices endpoint.

public class Create_cs 
{
public static void main(String[] args) throws Exception 
   {
   Data s = new Data();
   String payload = s.getpayload();
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices?api-version=2013-03";       
   URL url = new URL(u);                        
   HttpURLConnection c = null;       
   c = (HttpsURLConnection)url.openConnection();
   c.setRequestMethod("POST");
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   c.setDoOutput(true);
   OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
   out.write(payload);
   out.close();
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null) 
      {System.out.println(decodedString);}
   in.close();
   }
}   

Service providers can offer tenants a self-service gallery of virtual machine roles. The tenant can then create a VM role from one of the VM Role gallery items. You can query for all the VM roles offered to your subscription by sending a HTTP GET operation request to the following URL for the VM role gallery. For example, you can use the following URL and Get_list to get the VM roles offered to your subscription.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03

Here is an example of the HTTP response containing the collection of VM role gallery items.

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 2148
Content-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
Content-Language: en-US
Server: Microsoft-IIS/8.5
X-Content-Type-Options: nosniff
DataServiceVersion: 3.0;
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Wed, 05 Feb 2014 20:11:29 GMT

{"odata.metadata":"https://server:port/SC2012R2/VMM/GalleryService.svc/$metadata#GalleryItems/MicrosoftCompute.VMRoleGalleryItem","value":[{"odata.type":"MicrosoftCompute.VMRoleGalleryItem","Name":"CentOS6LAMP","Publisher":"Microsoft","Version":"1.0.0.0","ContentUrl":"Gallery/GalleryItems(Name%3d%27CentOS6LAMP%27,Version%3d%271.0.0.0%27,Publisher%3d%27Microsoft%27)/Content","Description":"Deploy a CentOS 6 virtual machine role with Apache, MySQL and PHP installed.","IconUrl":null,"Label":"CentOS6 LAMP Role","PublishDate":"2014-01-21T19:09:11.163","PublisherLabel":"Microsoft","ResourceDefinition@odata.mediaContentType":"application/json","ResourceDefinitionUrl":"Gallery/GalleryItems(Name%3d%27CentOS6LAMP%27,Version%3d%271.0.0.0%27,Publisher%3d%27Microsoft%27)/MicrosoftCompute.ResourceDefinitionGalleryItem/ResourceDefinition","ViewDefinitionUrl":"Gallery/ViewDefinitions(Name%3d%27CentOS6LAMP%27,Version%3d%271.0.0.0%27,Publisher%3d%27Microsoft%27)/%24value"}]}

This response indicates there is one VM role offered by the service provider: a CentOS 6 virtual machine role with Apache, MySQL and PHP already installed. Other items may appear in the gallery depending upon what VM roles are offered to your subscription. Note the string in the response that gives the ContentUrl property for the item. You will need to use this value to get a reference to the specific item.

"ContentUrl":"Gallery/GalleryItems(Name%3d%27CentOS6LAMP%27,Version%3d%271.0.0.0%27,Publisher%3d%27Microsoft%27)"

After selecting a VM Role item from the gallery, get the resource definition for that item and determine what resource parameters you’ll need to provide. The resource definition is a JSON file that describes the virtual machine hardware and instantiation restrictions. For more information about the resource definition, see the ResourceDefinition [SPFSDK][VMROLE] section.

Use Get_list to send a GET operation request to the URL for the gallery item you have selected.

https://server:port/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/Gallery/GalleryItems(Name%3d%27CentOS6LAMP%27,Version%3d%271.0.0.0%27,Publisher%3d%27Microsoft%27)/MicrosoftCompute.ResourceDefinitionGalleryItem/ResourceDefinition?api-version=2013-03

For this example, this HTTP response includes the ResourceDefinition object for the CentOS VM role.

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 2009
Content-Type: application/json
Content-Language: en-US
Server: Microsoft-IIS/8.5
X-Content-Type-Options: nosniff
DataServiceVersion: 1.0;
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Thu, 06 Feb 2014 17:03:10 GMT

{"IntrinsicSettings":{"HardwareProfile":{"VMSize":"[Param.VMRoleVMSize]"},"NetworkProfile":{"NetworkAdapters":[{"IPAddresses":[{"AllocationMethod":"Dynamic","ConfigurationName":"IPV4Configuration","Type":"IPV4"}],"Name":"NIC1","NetworkRef":"[Param.VMRoleNetworkRef]"}]},"OperatingSystemProfile":{"AdminCredential":"[Param.VMRoleAdminCredential]","ComputerNamePattern":"[Param.VMRoleComputerNamePattern]","LinuxOperatingSystemProfile":{"DNSDomainName":"[Param.VMRoleDNSDomainName]","SSHPublicKey":"[Param.VMRoleSSHPublicKey]"},"TimeZone":"[Param.VMRoleTimeZone]","WindowsOperatingSystemProfile":null},"ScaleOutSettings":{"InitialInstanceCount":"1","MaximumInstanceCount":"5","MinimumInstanceCount":"1","UpgradeDomainCount":"1"},"StorageProfile":{"OSVirtualHardDiskImage":"[Param.VMRoleOSVirtualHardDiskImage]"}},"Name":"CentOS6LAMP","Publisher":"Microsoft","ResourceExtensionReferences":[{"Name":"CentOS6LAMP","Publisher":"Microsoft","ReferenceName":"CentOS6LAMP","ResourceExtensionParameterValues":"{\"MySQLRootPassword\":\"[Param.CentOS6LAMPMySQLRootPassword]\"}","Version":"1.0.0.0"}],"ResourceParameters":[{"Description":"Computer size","Name":"VMRoleVMSize","Type":"String"},{"Description":"Operating system disk","Name":"VMRoleOSVirtualHardDiskImage","Type":"String"},{"Description":"Network reference","Name":"VMRoleNetworkRef","Type":"String"},{"Description":"Resource Extension CentOS6LAMP. Parameter MySQLRootPassword. Run once command parameter","Name":"CentOS6LAMPMySQLRootPassword","Type":"SecureString"},{"Description":"Compute name pattern","Name":"VMRoleComputerNamePattern","Type":"String"},{"Description":"Time zone","Name":"VMRoleTimeZone","Type":"String"},{"Description":"Administrator credential","Name":"VMRoleAdminCredential","Type":"Credential"},{"Description":"DNS domain name","Name":"VMRoleDNSDomainName","Type":"String"},{"Description":"SSH public key","Name":"VMRoleSSHPublicKey","Type":"String"}],"SchemaVersion":"1.0","Type":"Microsoft.Compute\/VMRole\/1.0","Version":"1.0.0.0"}

Note that the ResourceParameters property lists parameters. Although not every VM role is required to have parameters, if any parameters are listed in the ResourceParameters property of the ResourceDefinition object, you must provide a value for each of these. You can provide the parameters and their values by packing them into a JSON-encoded string using the following format.

{ "parameter1 name" : "parameter1 value", "parameter2 name" : "parameter2 value", ... }

After you have gathered the ParameterValues, you can build a ResourceConfiguration object containing the ParameterValues and the version of the parameter values. In this guide, the example ResourceConfiguration object uses the following parameter values.

"ResourceConfiguration": 
{
"ParameterValues": "{\"VMRoleVMSize\" : \"ExtraSmall\",\"VMRoleOSVirtualHardDiskImage\" : \"CentOS Linux 6 (64-bit):1.0.0.0\",\"VMRoleNetworkRef\" : \"VMNetwork1\",\"CentOS6LAMPMySQLRootPassword\" : \"!!pass3abc12\",\"VMRoleComputerNamePattern\" : \"LAMP###\",\"VMRoleTimeZone\" : \"Pacific Standard Time\",\"VMRoleAdminCredential\" : \"root:!!pass3abc12\",\"VMRoleDNSDomainName\" : \"mydns\",\"VMRoleSSHPublicKey\" : \"key123\"}",
"Version": "1.0.0.0"
}

Note that the virtual network named VMNetwork1 must already exist in the tenant’s subscription. A virtual network must be specified to place virtual machines. You can create a virtual network by using the tenant UI portal of your subscription.

Create a new VM role instance

Build a new VirtualMachineRole object by combining the ResourceDefinition object retrieved from the VM role gallery and the ResourceConfiguration object you built in the previous step. Then send the entire VirtualMachineRole object as the body of an HTTP POST operation request to the URL for VMRoles.

https://server:port/subscription-id/CloudServices/cloudservice-name/Resources/MicrosoftCompute/VMRoles?api-version=2013-03

For example, the odata.txt can contain the following VitualMachineRole object.

{
    "InstanceView": null,
    "Label": "My VM Role Instance",
    "Name": "TestVMRole",
    "ProvisioningState": null,
    "ResourceConfiguration": {
        "ParameterValues": "{\"VMRoleVMSize\" : \"ExtraSmall\",\"VMRoleOSVirtualHardDiskImage\" : \"CentOS Linux 6 (64-bit):1.0.0.0\",\"VMRoleNetworkRef\" : \"VMNetwork1\",\"CentOS6LAMPMySQLRootPassword\" : \"!!pass3abc12\",\"VMRoleComputerNamePattern\" : \"LAMP###\",\"VMRoleTimeZone\" : \"Pacific Standard Time\",\"VMRoleAdminCredential\" : \"root:!!pass3abc12\",\"VMRoleDNSDomainName\" : \"mydns\",\"VMRoleSSHPublicKey\" : \"key123\"}",
        "Version": "1.0.0.0"
    },
    "ResourceDefinition": {
        "IntrinsicSettings": {
            "HardwareProfile": { "VMSize": "[Param.VMRoleVMSize]" },
            "NetworkProfile": {
                "NetworkAdapters": [{
                    "IPAddresses": [{
                        "AllocationMethod": "Dynamic",
                        "ConfigurationName": "IPV4Configuration",
                        "LoadBalancerConfigurations": [],
                        "Type": "IPV4"
                    }],
                    "Name": "NIC1",
                    "NetworkRef": "[Param.VMRoleNetworkRef]"
                }]
            },
            "OperatingSystemProfile": {
                "AdminCredential": "[Param.VMRoleAdminCredential]",
                "ComputerNamePattern": "[Param.VMRoleComputerNamePattern]",
                "LinuxOperatingSystemProfile": {
                    "DNSDomainName": "[Param.VMRoleDNSDomainName]",
                    "SSHPublicKey": "[Param.VMRoleSSHPublicKey]"
                },
                "TimeZone": "[Param.VMRoleTimeZone]",
                "WindowsOperatingSystemProfile": null
            },
            "ScaleOutSettings": {
                "InitialInstanceCount": "1",
                "MaximumInstanceCount": "5",
                "MinimumInstanceCount": "1",
                "UpgradeDomainCount": "1"
            },
            "StorageProfile": {
                "DataVirtualHardDisks": [],
                "OSVirtualHardDiskImage": "[Param.VMRoleOSVirtualHardDiskImage]"
            }
        },
        "Name": "CentOS6LAMP",
        "Publisher": "Microsoft",
        "ResourceExtensionReferences": [{
            "Name": "CentOS6LAMP",
            "Publisher": "Microsoft",
            "ReferenceName": "CentOS6LAMP",
            "ResourceExtensionParameterValues": "{\"MySQLRootPassword\":\"[Param.CentOS6LAMPMySQLRootPassword]\"}",
            "Version": "1.0.0.0"
        }],
        "ResourceParameters": [{
            "Description": "Computer size",
            "Name": "VMRoleVMSize",
            "Type": "String"
        },
            {
                "Description": "Operating system disk",
                "Name": "VMRoleOSVirtualHardDiskImage",
                "Type": "String"
            },
            {
                "Description": "Network reference",
                "Name": "VMRoleNetworkRef",
                "Type": "String"
            },
            {
                "Description": "Resource Extension CentOS6LAMP. Parameter MySQLRootPassword. Run conce command parameter",
                "Name": "CentOS6LAMPMySQLRootPassword",
                "Type": "SecureString"
            },
            {
                "Description": "Compute name pattern",
                "Name": "VMRoleComputerNamePattern",
                "Type": "String"
            },
            {
                "Description": "Time zone",
                "Name": "VMRoleTimeZone",
                "Type": "String"
            },
            {
                "Description": "Administrator credential",
                "Name": "VMRoleAdminCredential",
                "Type": "Credential"
            },
            {
                "Description": "DNS domain name",
                "Name": "VMRoleDNSDomainName",
                "Type": "String"
            },
            {
                "Description": "SSH public key",
                "Name": "VMRoleSSHPublicKey",
                "Type": "String"
            }
        ],
        "SchemaVersion": "1.0",
        "Type": "Microsoft.Compute/VMRole/1.0",
        "Version": "1.0.0.0"
    },
    "Substate": null
}

You can use the following Java code, Create_vmr, and the example VirtualMachine object, to create a new VM role named TestVMRole.

public class Create_vmr 
{
public static void main(String[] args) throws Exception 
   {
   Data s = new Data();
   String payload = s.getpayload();
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles?api-version=2013-03";       
   URL url = new URL(u);                        
   HttpURLConnection c = null;       
   c = (HttpsURLConnection)url.openConnection();
   c.setRequestMethod("POST");
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   c.setDoOutput(true);
   OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
   out.write(payload);
   out.close();
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null) {System.out.println(decodedString);}
   in.close();
   }
}  

Because the InitialInstanceCount is 1, one TestVMRole virtual machine, named LAMP0001, is place on VMNetwork1 and started. You can obtain the ID for this new virtual machine by sending a HTTP GET operation request to the URL for the VMs of TestVMRole.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs?api-version=2013-03

The unique ID for the vm is represented in this guide by the string 6e66ee6e-6e6e-6666-ee66-e666e666666e.

Scale a VM role

You can adjust how many virtual machines are running in a VM Role instance by sending a HTTP POST operation request to the URL for the VM role and Scale endpoint. The number of instances cannot be less than the minimum, or more than the maximum, number of instances that you have specified in the VitualMachineRole object. For example, you use the following URL to adjust the scale of the TestVMRole role.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/Scale?api-version=2013-03

The body of the POST operation request should specify the number of virtual machines to be instantiated for the VM role as the InstanceCount. Sending the following odata.txt increases the number of virtual machine running in TestVMRole to two.

{
    "InstanceCount": 2
}

To get a list of all the virtual machines currently in the TestVMRole role, send a HTTP GET operation request to the URL for the VMs.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs?api-version=2013-03

The example HTTP response looks as follows.

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 496
Content-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
Server: Microsoft-IIS/8.5
X-Content-Type-Options: nosniff
request-id: d3350337-10af-0000-897f-39d3af10cf01
DataServiceVersion: 3.0;
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Thu, 06 Feb 2014 21:52:56 GMT

{"odata.metadata":"https://server:8090/SC2012R2/VMM/Microsoft.Management.Odata.svc/$metadata#VM","value":[{"Id":"6e66ee6e-6e6e-6666-ee66-e666e666666e","ComputerName":"LAMP001.mydns","RuntimeState":"Running","ConnectToAddresses":[{"IPAddress":"10.0.0.4","NetworkName":"VMNetwork1","Port":3389}]},{"Id":"77ff7777-7777-7777-ff7f-f7f7f77777f7","ComputerName":"LAMP002","RuntimeState":"Running","ConnectToAddresses":[{"IPAddress":"10.0.0.5","NetworkName":"VMNetwork1","Port":3389}]}]}

The HTTP response shows that a second virtual machine of the TestVMRole role named LAMP0002 and represented by 77ff7777-7777-7777-ff7f-f7f7f77777f7 is now running.

Note that if the VM role is scaled to an Instance count that is less than the current number of virtual machines, some of the VMs get deleted whether or not they are running. If you want to delete a specific virtual machine in a VM role see the following section Start, stop, restart, shutdown, or delete a virtual machine.

Start, stop, restart, shutdown, or delete a virtual machine

You can stop the virtual machine by sending a HTTP POST operation request to the following URL with an empty body. For example, the following Java code example stops LAMP002, which has ID=77ff7777-7777-7777-ff7f-f7f7f77777f7.

public class Start_vmr 
{
public static void main(String[] args) throws Exception 
   {
   String payload ="";
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs/77ff7777-7777-7777-ff7f-f7f7f77777f7/Stop?api-version=2013-03";       
   URL url = new URL(u);                        
   HttpURLConnection c = null;       
   c = (HttpsURLConnection)url.openConnection();
   c.setRequestMethod("POST");
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   c.setDoOutput(true);
   OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
   out.write(payload);
   out.close();
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null) {System.out.println(decodedString);}
   in.close();
   }
}   

You can also use this example Java code to make a HTTP POST operation request to start, restart, or shutdown a VM. Use the following URL to start the stopped LAMP0002.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs/77ff7777-7777-7777-ff7f-f7f7f77777f7/Start?api-version=2013-03

Use the following URL to restart the running LAMP0002.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs/77ff7777-7777-7777-ff7f-f7f7f77777f7/Restart?api-version=2013-03

Use the following URL to shutdown the running LAMP0002.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs/77ff7777-7777-7777-ff7f-f7f7f77777f7/Shutdown?api-version=2013-03

You can delete a specific virtual machine by sending a HTTP DELETE operation request to the endpoint for the VM with an empty payload. You should stop the VM before deleting it. Note that the example uses the X-HTTP-Method header to override the POST operation with DELETE. For example, the following Java code, Delete_vm, deletes the VM which has ID=77ff7777-7777-7777-ff7f-f7f7f77777f7.

public class Delete_vm 
{
public static void main(String[] args) throws Exception 
   {
   String payload ="";
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole/VMs/77ff7777-7777-7777-ff7f-f7f7f77777f7?api-version=2013-03";       
   URL url = new URL(u);                       
   HttpURLConnection c = null;      
   c = (HttpsURLConnection)url.openConnection();
   TrustModifier.relaxHostChecking(c); // ignore host checking errors 
   c.setRequestMethod("POST");        
   c.setRequestProperty("X-HTTP-Method", "DELETE"); 
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   c.setDoOutput(true);        
   OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
   out.write(payload);
   out.close();
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null){System.out.println(decodedString);}
   in.close();
   }
}

Note that this deletes virtual machine LAMP0002 specifically. If the TestVMRole is scaled back from 2 to 1 instances, the virtual machine LAMP0001 gets deleted, even if LAMP0002 has been stopped previously.

Update or delete a VM role

You can update a VM Role instance to a new version while virtual machines of previous versions continue to run. If you add new virtual machines by scaling out the VM Role, the new virtual machines get the updated version of the VM role. Virtual machines based on both versions may run at the same time. You may need to stop or delete those specific virtual machines based on the earlier version.

You can update a VM role by sending an HTTP MERGE operation request to the URL for the VM role. The body contains the updated information to merge into the VirtualMachineRole.

https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole?api-version=2013-03

For example, the following odata.txt updates the TestVMRole role from version 1.0.0.0 to version 1.0.0.1. Whereas version 1.0.0.0 placed virtual machines on VMNetwork1, the example version 1.0.0.1 places virtual machines on VMNetwork2.

{
    "ResourceConfiguration": {
        "ParameterValues": "{\"VMRoleVMSize\" : \"ExtraSmall\",\"VMRoleOSVirtualHardDiskImage\" : \"CentOS Linux 6 (64-bit):1.0.0.0\",\"VMRoleNetworkRef\" : \"VMNetwork2\",\"CentOS6LAMPMySQLRootPassword\" : \"!!pass3abc12\",\"VMRoleComputerNamePattern\" : \"LAMP###\",\"VMRoleTimeZone\" : \"Pacific Standard Time\",\"VMRoleAdminCredential\" : \"root:!!pass3abc12\",\"VMRoleDNSDomainName\" : \"mydns\",\"VMRoleSSHPublicKey\" : \"key123\"}",
        "Version": "1.0.0.1"
    }
}  

The following Java code example can update the TestVMRole version. Note that the example uses the X-HTTP-Method header to override the POST operation with MERGE.

public class Update_vmr 
{
public static void main(String[] args) throws Exception 
   {
   Data s = new Data();
   String payload = s.getpayload();
   String u = "https://server:30006/2222aa22-22a2-2a22-2a22-2aaaaa2aaaaa/CloudServices/TestingCloudService799/Resources/MicrosoftCompute/VMRoles/TestVMRole?api-version=2013-03";       
   URL url = new URL(u);                        
   HttpURLConnection c = null;       
   c = (HttpsURLConnection)url.openConnection();
   c.setRequestMethod("POST");
   c.setRequestProperty("X-HTTP-Method", "MERGE");
   c.setRequestProperty("Content-Type", "text/plain; charset=\"utf8\"");
   c.setRequestProperty("DataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("MaxDataServiceVersion", "3.0;NetFx");
   c.setRequestProperty("Accept", "application/json;odata=minimalmetadata");
   c.setRequestProperty("Accept-Charset", "UTF-8");
   c.setRequestProperty("DataServiceUrlConventions", "KeyAsSegment");
   c.setRequestProperty("User-Agent", "Microsoft ADO.NET Data Services");
   c.setRequestProperty("x-ms-principal-id", "user@contoso.com");      
   c.setRequestProperty("Content-Type","application/json;odata=minimalmetadata");
   c.setRequestProperty(“Host”, “user@contoso.com”);
   c.setRequestProperty("Expect", "100-continue");
   c.setDoOutput(true);
   OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream());
   out.write(payload);
   out.close();
   BufferedReader in = new BufferedReader(new InputStreamReader(c.getInputStream()));
   String decodedString;
   while ((decodedString = in.readLine()) != null) {System.out.println(decodedString);}
   in.close();
   }
}  

After running this code, if any new TestVMRole VMs are created these will be version 1.0.0.1. Existing version 1.0.0.0 VMs continue run to run. For example, increase the scale of TestVMRole from 1 to 2. The new virtual machine uses the new version and runs on VMNetwork2. The virtual machine running on VMNetwork1 continues to run on VMNetwork1. You can reduce the number of instances, or delete the older virtual machine, to update all the instances of the previous VM Role version.

To delete a VM role, and all the virtual machines in the role, stop the virtual machines, and send a HTTP DELETE operation request to the URL for the VM role with an empty body. Use the X-HTTP-Method header to override the POST operation with DELETE.

See Also

Virtual Machine Management with Java
VM Roles Tenant Service [SPFSDK][VMROLE]
VM Role JSON Reference [SPFSDK][VMROLE]