Over the preceding chapters we have discovered several ways of calling Automate instances. In some cases we need to pass arguments into the instance’s method, but the way that we pass arguments into methods, and receive them from inside the method, varies depending on how the instance is called. We need to consider this if we’re writing code that can be called in several ways, such as from a button and/or from an API call.
In this chapter we’ll look at how we pass arguments into instances and how we retrieve them from inside the method. We will call the same instance (ObjectWalker) four ways, passing two arguments each time: lunch
and dinner
. We can use object_walker_reader to show us where the arguments can be read from inside our called method.
For this first case we call ObjectWalker (via /System/Process/Request/Call_Instance) from a button. We create a button dialog that prompts for two text box fields (see Figure 46-1).
We then add the button to a button group anywhere.
If we click on the button and enter the values salad
and pasta
into the dialog boxes, we see the dialog values appear in $evm.root
in the receiving method, indexed by the key name prefixed by dialog_
:
~/object_walker_reader.rb | grep -P "lunch|dinner" | $evm.root['dialog_dinner'] = salad (type: String) | $evm.root['dialog_lunch'] = pasta (type: String)
For this use case we have an external Ruby script that calls our internal CloudForms instance via the REST API:
url
=
"https://
#{
server
}
"
post_params
=
{
:version
=>
'1.1'
,
:uri_parts
=>
{
:namespace
=>
'Stuff'
,
:class
=>
'Methods'
,
:instance
=>
'ObjectWalker'
},
:parameters
=>
{
:lunch
=>
"sandwich"
,
:dinner
=>
"steak"
},
:requester
=>
{
:auto_approve
=>
true
}
}
.
to_json
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
)
In the called method we see the arguments visible in several places: in the task’s options hash as the attrs
key, under $evm.root
because this is the Instance that we launched when entering Automate, and under $evm.object
because this is also our current object:
~/object_walker_reader.rb | grep -P "lunch|dinner" | object_walker: $evm.root['automation_task'].options[:attrs] = {:lunch=>"sandwich", :dinner=>"steak", :userid=>"admin"} (type: Hash) object_walker: $evm.root['dinner'] = steak (type: String) object_walker: $evm.root['lunch'] = sandwich (type: String) object_walker: $evm.object['dinner'] = steak (type: String) object_walker: $evm.object['lunch'] = sandwich (type: String)
When we call instances via a relationship (such as from a state machine), we specify the full URI of the instance. We can append arguments to this URI using standard web form query string syntax.
For this use case, we’ll call ObjectWalker from an already running automation script, using $evm.instantiate
. The argument to $evm.instantiate
is the full URI of the instance to be launched, as follows:
$evm
.
instantiate
(
"/Stuff/Methods/ObjectWalker?lunch=salad&dinner=spaghetti"
)
When instantiated in this way, the receiving method retrieves the arguments from $evm.object
(one of our [grand]parent instances is $evm.root
; our immediate caller is $evm.parent
):
~/object_walker_reader.rb | grep -P "lunch|dinner" object_walker: $evm.object['dinner'] = spaghetti (type: String) object_walker: $evm.object['lunch'] = salad (type: String)
We can pass our own custom values into the virtual machine provisioning process so that they can be interpreted by any method in the Provision VM from Template
state machine.
The facility to do this is provided by the additional_values
field in an /api/provision_requests REST call (additionalValues
in the original SOAP EVMProvisionRequestEx
call) or from the sixth element in the argument list to an $evm.execute('create_provision_request',…)
call (see Chapter 27).
For this use case we’ve edited the Provision VM from Template
state machine to add a few extra stages (see Figure 46-2).
These stages could modify the provisioning process if required based on the custom values passed in. An example of this might be to specify the disk size for an additional disk to be added by the AddDisk
stage.
For this example we’re using a simple automation method to call $evm.execute('create_provision_request',…)
to provision a new virtual machine. We specify the custom values in arg6
:
# arg1 = version
args
=
[
'1.1'
]
# arg2 = templateFields
args
<<
{
'name'
=>
'rhel7-generic'
,
'request_type'
=>
'template'
}
# arg3 = vmFields
args
<<
{
'vm_name'
=>
'test10'
,
'vlan'
=>
'rhevm'
}
# arg4 = requester
args
<<
{
'owner_email'
=>
'[email protected]'
,
'owner_first_name'
=>
'Peter'
,
'owner_last_name'
=>
'McGowan'
}
# arg5 = tags
args
<<
nil
# arg6 = Web Service Values (ws_values)
args
<<
{
'lunch'
=>
'soup'
,
'dinner'
=>
'chicken'
}
# arg7 = emsCustomAttributes
args
<<
nil
# arg8 = miqCustomAttributes
args
<<
nil
request_id
=
$evm
.
execute
(
'create_provision_request'
,
*
args
)
When we call this method and the virtual machine provisioning process begins, we can retrieve the custom values at any stage from the miq_provision_request
or miq_provision
options hash using the ws_values
key:
~/object_walker_reader.rb | grep -P "lunch|dinner" | $evm.root['miq_provision'].options[:ws_values] = {:lunch=>"soup", :dinner=>"chicken"} (type: Hash) | | miq_provision_request.options[:ws_values] = {:lunch=>"soup", :dinner=>"chicken"} (type: Hash)
When an instance (such as a state machine) calls a method in the same class as itself, it can pass key/value argument pairs in parentheses as input parameters with the call. We see the VMProvision_VM state machine do this when it calls update_provision_status during the processing of the On Entry, On Exit, and On Error (see Figure 46-3).
When we create a method that accepts input parameters in this way, we need to specify the name and data type of each parameter in the method definition (see Figure 46-4).
The method then reads the parameters from $evm.inputs
:
update_provision_status
(
status
=>
'pre1'
,
status_state
=>
'on_entry'
)
# Get status from input field status
status
=
$evm
.
inputs
[
'status'
]
# Get status_state ['on_entry', 'on_exit', 'on_error'] from input field
status_state
=
$evm
.
inputs
[
'status_state'
]
This chapter shows how we can send arguments when we call instances and how we process them inside the method. The way that a method retrieves an argument depends on how the instance has been called, but we can use $evm.root['vmdb_object_type']
as before to determine this, and access the argument in an appropriate manner.
18.118.12.157