Our first look at the integration capabilities of CloudForms examines how external systems can make inbound calls to CloudForms to run Automate instances using the RESTful API.1
Being able to call automation in this way enables our workflows to be utilized by other enterprise tools in a number of ways. For example, organizations may wish to use a help-desk ticketing system as their starting point for new virtual machine provisioning requests. The ticketing system can make a RESTful call to CloudForms Automate to initiate the workflow.
We can call any Automate instance from the RESTful API, by issuing a POST
call to /api/automation_requests and enclosing a JSON-encoded parameter hash such as the following:
post_params
=
{
:version
=>
'1.1'
,
:uri_parts
=>
{
:namespace
=>
'ACME/General'
,
:class
=>
'Methods'
,
:instance
=>
'HelloWorld'
},
:requester
=>
{
:auto_approve
=>
true
}
}
.
to_json
We can call the RESTful API from an external Ruby script by using the rest-client
gem:
url
=
'https://cloudforms_server'
query
=
'/api/automation_requests'
rest_return
=
RestClient
:
:Request
.
execute
(
method
:
:post
,
url
:
url
+
query
,
:user
=>
username
,
:password
=>
password
,
:headers
=>
{
:accept
=>
:json
},
:payload
=>
post_params
,
verify_ssl
:
false
)
result
=
JSON
.
parse
(
rest_return
)
The request ID is returned to us in the result from the initial call:
request_id
=
result
[
'results'
][
0
][
'id'
]
We call poll this to check on status:
query
=
"/api/automation_requests/
#{
request_id
}
"
rest_return
=
RestClient
:
:Request
.
execute
(
method
:
:get
,
url
:
url
+
query
,
:user
=>
username
,
:password
=>
password
,
:headers
=>
{
:accept
=>
:json
},
verify_ssl
:
false
)
result
=
JSON
.
parse
(
rest_return
)
request_state
=
result
[
'request_state'
]
until
request_state
==
"finished"
puts
"Checking completion state..."
rest_return
=
RestClient
:
:Request
.
execute
(
method
:
:get
,
url
:
url
+
query
,
:user
=>
username
,
:password
=>
password
,
:headers
=>
{
:accept
=>
:json
},
verify_ssl
:
false
)
result
=
JSON
.
parse
(
rest_return
)
request_state
=
result
[
'request_state'
]
sleep
3
end
The automation request’s options hash is included in the return from the RestClient::Request
call, and we can use this to our advantage, by using set_option
to add return data in the form of key/value pairs to the options hash from our called automation method.
For example, from the called (Automate) method, we can include the following:
automation_request
=
$evm
.
root
[
'automation_task'
].
automation_request
automation_request
.
set_option
(
:return
,
JSON
.
generate
({
:status
=>
'success'
,
:return
=>
some_data
}))
From the calling (external) method, we can then parse the return
key from the returned options hash and print the contents, as follows:
result
=
JSON
.
parse
(
rest_return
)
puts
"Results:
#{
result
[
'options'
][
'return'
].
inspect
}
"
Using this technique, we can write our own pseudo-API calls for CloudForms to handle anything that the standard RESTful API doesn’t support. We implement the “API” using a standard Automate method and call it using the RESTful automate call; and we can pass parameters to, and retrieve result back from, the called method.
When we make a RESTful call, we must authenticate using a valid username and password. This user must be an admin or equivalent, however, if we wish to specify an :auto_approve
value of true
in our calling arguments (only admins can auto-approve automation requests).
If we try making a RESTful call as a nonadmin user, the automation request will be blocked, pending approval (as expected). If we want to submit an auto-approved automation request as a nonadmin user, we would need to write our own approval workflow (see Chapter 43).
When we submit an automation request via the API, by default the Automate task is queued on the same appliance that the web service is running on. This will be dequeued to run by any appliance with the Automation Engine role set in the same zone. If we have separated out our UI/web service appliances into a different zone, this may not necessarily be our desired behavior.
We can add the parameter :miq_zone
to the automation request to override this:
:requester
=>
{
:auto_approve
=>
true
},
:parameters
=>
{
:miq_zone
=>
'Zone Name'
}
The behavior of this parameter is as follows:
If the parameter is not passed, the request should use the zone of the server that receives the request.
If passed but empty (e.g., parameters => "miq_zone="
), the zone should be set to nil
and any appliance can process the request.
Passing a valid zone name parameter (e.g., parameters => "miq_zone=Test"
) should process the work in the Test zone.
Passing an invalid zone name should raise an error of unknown zone Zone_name
back to the caller.
The accompanying code on GitHub contains an example script called run_via_api.rb that can be used to call any Automate instance, using arguments to pass server name, credentials, and URI parameters to the instance to be called. Its usage is as follows:
Usage: run_via_api.rb [options] -s, --server server CloudForms server to connect to -u, --username username Username to connect as -p, --password password Password -d, --domain Domain -n, --namespace Namespace -c, --class Class -i, --instance Instance -P, --parameter <key,value> Parameter (key => value pair) for the instance -h, --help
Edit the default values for server, username, and password if required. Run the script as:
./run_via_api.rb -s 192.168.1.1 -u cfadmin -p password -d ACME -n General -c Methods -i AddNIC2VM -P vm_id,1000000000195 -P nic_name,nic1 -P nic_network,vlan_712
This chapter has examined how we can make RESTful API calls into Automate and, if necessary, return results back to the caller. This is a very powerful feature that lets us harness the power of CloudForms Automate from external systems.
We can implement bidirectional workflows, for example, whereby CloudForms makes outgoing calls to integrate with some other enterprise tool, perhaps to initiate an asynchronous action that may take some time to complete. We can implement callback routines as REST-callable Automate instances that can be called to signal that the external processing has finished.
https:http://bit.ly/1szXHpL[API Reference—Automation Requests]
1 We need to enable the Web Services server role on any of our CloudForms appliances to which we wish to make RESTful calls.
18.191.215.96