Using the CloudForms Web Services API

The web services API provided by CloudForms Management Engine allows users to integrate external systems with CloudForms. For example, if you wanted an existing change control system to request services from a virtualization provider or public cloud you could call the CloudForms SOAP API to initiate the virtual machine provisioning request method. Keep in mind that automate methods within CloudForms can be used to do just about anything from opening a new incident in a change management system to checking the weather in your favorite city. In this post, however, I’ll provide a simple example of how the Savon soap client and Ruby can be used to make a request to CloudForms to launch a virtual machine.

First you’ll need to install a few ruby gems on your system if you don’t already have them.

# gem install savon
....
# gem install httpclient
....
# gem install openssl
....
# gem install httpi
....
# gem install pp
....
# vi myscript.rb

The first section of the script will specify the interpreter and import the gems we installed via require.

#!/usr/bin/ruby

require 'savon'
require 'httpi'
require 'httpclient'
require 'openssl'
require 'pp'

The next section will define a ruby module named DCA which contains a class named Worker, or a collection of methods and constants. The module will help provide a namespace so the class name doesn’t clash with an already existing class that may have a similar name if you include this code in a larger body of ruby. We will also define two methods. The build_automation_request method will handle executing the request against the CloudForms Management Engine Web Services API. It accepts a hash that it will pass to the web services API. The deploy_vm method will accept some arguments, provide others within it’s body and then instantiate the build_automation_request with body of the request. This includes things such as the template_name, vlan, vm_name, etc.


module DCA
  class Worker

    def build_automation_request(body_hash)
       # We will populate this with the request
    end

    def deploy_vm(template_name, vlan, ip, subnet, gateway, vm_name, domain_name, memory, cpus, add_disk, owner_email, customization_spec = 'linux')
       # We will build the request here, then pass it to build_automation_request

    end

  end
end

With the structure in place we can add the following to the build_automation_request method. Replace YOURUSER with your username, YOURPASSWORD with your password and CFMEIPADDRESS with the IP address of the CloudForms Management Engine running with the web services role enabled.


    def build_automation_request(body_hash)
      client = Savon.client(basic_auth: ["YOURUSER", "YOURPASSWORD"], ssl_verify_mode: :none, ssl_version: :TLSv1, wsdl: "https://CFMEIPADDRESS/vmdbws/wsdl")
      evm_response = client.call(:vm_provision_request, message: body_hash)
    end

Next we will populate the deploy_vm method. The contents of the method will build several arrays and then combine them into a hash which will be passed to the build_automation_request hash we created previously.


    def deploy_vm(template_name, vlan, ip, subnet, gateway, vm_name, domain_name, memory, cpus, add_disk, owner_email, customization_spec = 'linux')
      templateFields = []
      templateFields << "name=#{template_name}"
      templateFields << "request_type=template"
      vmFields = []
      vmFields << "vm_name=#{vm_name}"
      vmFields << "number_of_vms=1"
      vmFields << "vm_memory=#{memory}"
      vmFields << "number_of_cpus=#{cpus}"
#      The options below are useful for windows systems
#      options = []
#      options << "sysprep_custom_spec=#{customization_spec}"
#      options << "sysprep_spec_override=true"
#      options << "sysprep_domain_name=#{domain_name}"
      vmFields << "addr_mode=static"
      vmFields << "ip_addr=#{ip}"
      vmFields << "subnet_mask=#{subnet}"
      vmFields << "gateway=#{gateway}"
      vmFields << "vlan=#{vlan}"
      vmFields << "provision_type=PXE"
      requester = []
      #requester << "user_name=#{user_id}"
      requester << "owner_email=#{owner_email}"
      tags = []
      #options << "add_vdisk1=#{add_disk}"
      input =  {
          'version'        =>        '1.1',
          'templateFields'        =>        templateFields.join('|'),
          'vmFields'        =>        vmFields.join('|'),
          'requester'        =>        requester.join('|'),
          'tags'        =>        tags.join('|'),
          #'options'        =>        options
      }
      pp input
      response = build_automation_request(input)
      pp response
    end

Finally, we will create a new worker object by invoking the worker class and we will call the deploy_vm method associated with the worker object overriding the arguments that we wish to use.

w = DCA::Worker.new
r = w.deploy_vm("win2k8tmpl", "VM Network", "172.28.158.125", "255.255.255.128", "172.28.158.1",
                "VMNAME", "sys.mycustomer.net", 2048, 2, 15, "yourname@yourdomain.com", "linux")
puts "Guess what! I built me a vm! #{r}"

That’s it. When this script is executed it should print out the output of your hash along with a bunch of output from the result of the request. If all goes well you should end up with a virtual machine running on your provider!

# chmod 755 myscript.rb
# ./myscript.rb
.... 
Guess what! I built me a vm!"

Keep in mind you should utilize more robust error handling if you are serious and also use something more secure for authentication between remote systems.

You can download the entire script here.

One thought on “Using the CloudForms Web Services API

  1. simon pole says:

    Hi, Great post! Is there a cloudforms WSDL I can explore?

Leave a comment