How to use the Windows Azure Service Management API from cURL to create Virtual Machines

Recently a partner asked me for some simples examples of using the Windows Azure Management API from that most universal Swiss army knife of HTTP debug tools, namely the infamous cURL. Specifically, he was looking for an example of how to create a Linux machine from the command line using just cURL.

There is already a blog post out there showing you how to access the Management API using cURL (https://blog.toddysm.com/2012/01/accessing-windows-azure-rest-apis-with-curl.html) however it doesn't cover the creation of VMs, so here are a few more samples.

First, the blob post above shows you how to create a new certificate and upload it to the Windows Azure management portal. But there is a simpler way, using a "Publish Settings" profile, that you use for example with the cross-platform Command Line Tools.

Here is the article that will explain you how to download this publishing profile: https://www.windowsazure.com/en-us/manage/linux/common-tasks/manage-certificates/

As explained in the article, you can extract from the profile the Base64-encoded certificate necessary to authenticate your calls to the Management API.

Let's say you saved the Base64 version in a file called cert.base64; here's how I decoded it:

 python -c 'print open("cert.base64", "rb").read().decode("base64")' > cert.pfx

Then I checked it using OpenSSL: (password is empty)

 openssl pkcs12 -info -in cert.pfx

And finally you can convert it to PEM format: (again, password is empty)

 openssl pkcs12 -in cert.pfx -out cert.pem -nodes

Now you can used this certificate with the -E option in cURL! You should also extract from the Publish Settings file your Subscription ID, that you will use to construct the URLs below.

Here are some examples... Again, the goal is to create a Linux virtual machine; in order to do that, we must first create a Hosted Service, and then "deploy" a Linux VM inside this Hosted Service. Here are the steps using cURL. All the URLs begin with your subscription ID, that you can find in the publishing profile as well.

Create a Hosted Service:

 curl -v -d @CreateHostedService.xml \
-H 'Content-Type: application/xml' \
-H 'x-ms-version: 2010-10-28' \
-E cert.pem: \
https://management.core.windows.net/(subscription-id)/services/hostedservices

The CreateHostedService.xml file contains the parameters for the Hosted Service:

 <?xml version="1.0" encoding="utf-8"?>
<CreateHostedService xmlns="https://schemas.microsoft.com/windowsazure">
  <ServiceName>testfromapi</ServiceName>
  <Label>VGVzdCBmcm9tIEFQSQ==</Label>
  <Description></Description>
  <Location>West Europe</Location>
</CreateHostedService>

The most important part in this file are the Location element, in which you indicate the data center you want to create this Hosted Service in (I chose West Europe), and the ServiceName element, that will be used later to deploy a VM.

List the Hosted Service:

 curl -H 'Content-Type: application/xml' \
-H 'x-ms-version: 2010-10-28' \
-E cert.pem: \
https://management.core.windows.net/(subscription-id)/services/hostedservices/testfromapi

This should return your newly created Hosted Service.

List OS images:

 curl -H 'Content-Type: application/xml' \
-H 'x-ms-version: 2012-03-01' \
-E cert.pem: \
https://management.core.windows.net/(subscription-id)/services/images

This will return a list of all available OS images. Let's use Ubuntu: CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd

Now the last step, create the VM:

 curl -v -d @TestLinuxVM.xml \
-H 'Content-Type: application/xml' \
-H 'x-ms-version: 2012-03-01' \
-E cert.pem: \
https://management.core.windows.net/(subscription-id)/services/hostedservices/testfromapi/deployments

Please note the URL references the name of the Hosted Service we created earlier ("testfromapi" in my example).

Now let's look at the XML file:

 <Deployment xmlns:i="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/windowsazure">
  <Name>testlinux</Name>
  <DeploymentSlot>Production</DeploymentSlot>
  <Label>testlinux</Label>
  <RoleList>
    <Role i:type="PersistentVMRole">
      <RoleName>testlinux</RoleName>
      <OsVersion i:nil="true" />
      <RoleType>PersistentVMRole</RoleType>
      <ConfigurationSets>
        <ConfigurationSet i:type="LinuxProvisioningConfigurationSet">
          <ConfigurationSetType>LinuxProvisioningConfiguration</ConfigurationSetType>
          <HostName>testlinux</HostName>
          <UserName>azure</UserName>
          <UserPassword>P@ssw0rd!</UserPassword>
          <DisableSshPasswordAuthentication>false</DisableSshPasswordAuthentication>
        </ConfigurationSet>
        <ConfigurationSet i:type="NetworkConfigurationSet">
          <ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
          <InputEndpoints>
            <InputEndpoint>
              <LocalPort>22</LocalPort>
              <Name>SSH</Name>
              <Protocol>tcp</Protocol>
            </InputEndpoint>
          </InputEndpoints>
        </ConfigurationSet>
      </ConfigurationSets>
      <DataVirtualHardDisks />
      <Label>dGVzdGF0b3Rv</Label>
      <OSVirtualHardDisk>
        <MediaLink>https://portalvhdsfxcplfk8zny2r.blob.core.windows.net/vhds/testfromapi-testlinux-2012-11-29-593.vhd</MediaLink>
        <SourceImageName>CANONICAL__Canonical-Ubuntu-12.04-amd64-server-20120924-en-us-30GB.vhd</SourceImageName>
      </OSVirtualHardDisk>
      <RoleSize>Small</RoleSize>
    </Role>
  </RoleList>
</Deployment>

This one is more complicated! There are good articles on Michael Washam's blog if you want to dig into the details, but here are the important parts:

  • In the LinuxProvisioningConfigurationSet, enter the login and password for the user that will be created on the machine.
  • The InputEndpoint definition opens port 22 (SSH).
  • In the OSVirtualHardDisk section, you must indicate the URL of the blob that will contain the new OS Disk for the machine; you can choose any name for the VHD, as long as it is unique! Also make sure the URL points to a Storage Account located in the same data center as the Hosted Service you created above, otherwise the call will fail (you cannot boot a machine in Dublin with an OS Disk in Singapore :)

This should give you a running Linux VM.

You can retrieve the details of the VM once it's created:

 curl -H 'Content-Type: application/xml' \
-H 'x-ms-version: 2012-08-01' \
-E cert.pem: \
https://management.core.windows.net/(subscription-id)/services/hostedservices/testfromapi/deployments/testlinux

You will get an XML response including, among other details, the status of the instance (Running, Stopped, etc.) and, most importantly, the public port that was assigned for SSH when the VM was created (look for the PublicPort element). This should let you connect to your new VM via SSH.

Enjoy!