design summit - intro to state machines - john hardy
TRANSCRIPT
State Machines
A big look at them from all angles!
John HardyProduct Manager
Fall 2014
Agenda
• What is a state machine?
• Real Life State Machines
• What is the difference between a State Machine and WorkFlow?
• Cyclic Graphs
• Acyclic Graphs
• The StateMachine
• Our StateMachine
• Fisher Price My First StateMachine
• Review : Why Are we talking statemachines?
• Wanna play? How to invoke statemachines.
• Q&A
What is a State Machine?
1. A state machine is simply a number of states.
2. A state is a process, something happening.
3. Only one state can be current at any one time.
4. The state of a state can be changed.
5. The initial entrance is event triggered, could be conditionally based.
6. Every change to a state is a transition.
Real Life State Machines
Traffic Lights – That change their sequence based on the cars waiting.
Turn Stile
Current
StateInput Next State Output
Lockedcoin Unlocked Release turnstile so customer can push through
push Locked None
Unlocked
coin Unlocked None
push LockedWhen customer has pushed through lock
turnstile.
What is the difference?
The shortest answer is that StateMachines are Cyclic and Workflows are Acyclic.
Workflows tend to be human representations to how a job is done, therefore ends, directive and event driven are
common place.
StateMachines are a map of states with transitions between them, sometimes allowing for loops.
Between a StateMachine and a WorkFlow
Cyclic Graphs
BA C
ED F
Cyclic graphs have CYCLES, as you can see here B,C,E,D.
At point E the graph decides to go F or to D and into a cycle.
Acyclic Graphs
BA
C E
D
F
aCyclic graphs are directive, shown here no point starts a cycle, only
completion to end.
Action
System/request
familycarClick Button
Instance
cfnow/fisherprice/myfir
ststatemachine
familycar
Attribute
number of
doors = 4
Value
cfnow/fisherprice/met
hods
Validate_car
On Entry Exit States
cfnow/fisherprice/met
hods
Validate_error
cfnow/fisherprice/met
hods
Build_car
cfnow/fisherprice/met
hods
build_error
cfnow/fisherprice/met
hods
Test_car
cfnow/fisherprice/met
hods
Test_error
cfnow/fisherprice/met
hods
Test_Complet
ed
$evm.root['ae_result'] = 'retry'
$evm.root['ae_result'] = 'retry'
$evm.root['ae_retry_interval'] =
'10.seconds'
$evm.root['ae_retry_interval'] =
'10.seconds'
The State Machine
Action
System/request
familycarClick Button
Instance
cfnow/fisherprice/myfir
ststatemachine
familycar
Attribute
number of
doors = 4
Value
cfnow/fisherprice/met
hods
Validate_car
On Entry Exit States
cfnow/fisherprice/met
hods
Validate_error
cfnow/fisherprice/met
hods
Build_car
cfnow/fisherprice/met
hods
build_error
cfnow/fisherprice/met
hods
Test_car
cfnow/fisherprice/met
hods
Test_error
cfnow/fisherprice/met
hods
Test_Complet
ed
$evm.root['ae_result'] = 'retry'
$evm.root['ae_result'] = 'retry'
$evm.root['ae_retry_interval'] =
'10.seconds'
$evm.root['ae_retry_interval'] =
'10.seconds'
The State Machine
State Machine
ae_result
• retry
• ok
• error
Our State Machines
Many state machines exist already in ManageIQ/CF
• Provisioning Hosts
• Provisioning Virtual Machines
• Provisioning Instances
• Retirement Hosts
• Retirement Virtual Machines
• Retirement Instances
• Provisioning Services
• Retirement Services
• Migration Virtual Machines
These can be copied and amended as you see fit.
So its not about creating state machine from new all the time.
Our State Machines – Provisioning VM
Our State Machines – Provisioning VM
Starting with the basics
My First State Machine
My First State Machine
StateMachine
Goal – To teach the concepts of state machine
Give you some best practices, why?
Good State-Machines = Re-usable and Portable
Not to mention easier to debug too!
– My First StateMachine!
Skipping HelloWorld – That was My First Method!
Car Example – We are going to build a car, that during manufacturing we shall
up date the manufacturing cycle too. First steps will be;
1. Specify how many doors our car should have.
2. Validate the number of doors defined.
3. Error out if the doors are too many.
4. Build the car.
• The doors will be set on the StateMachine itself, and pulled into it as a
variable
• The validation will simply check to see if #Doors > 4, if so then it will error
out.
• If the validation succeeds then we shall go on and build the car.
– My First StateMachine!
Step 1 – Create a NameSpace
Why ? – We want to create out own working area within the model.
– My First StateMachine!
Step 2 – Create a Class
Why ? – We are going to create a class so we can instantiate multiple copies of
the same StateMachine.
Think, that the first car we will build is a family car, but later we may wish to
build a sports car. We do not want to rebuild the entire process just because of
a new car. A class allows us to have repeatability and also allows us to inherit
schema from other classes too.
• Create a new class within the MyFirstStateMachine namespace.
– My First StateMachine!
Step 3 – Create the Schema
Why ? – We need to lay out the instructions/flow of the StateMachine.
This is very much about planning, thinking about what you want from your
statemachine. Schema – Our schema will be;
• Attribute – Number of Doors
• State – Validate Doors – This will have an On Entry that will perform the validation,
but if the validation fails then it will also have an On Error condition called Error
Doors.
• State – Build the Car, this will execute when the previous state (Validate Doors)
succeeds.
– My First StateMachine!
Step 4 – Create the States
There were 3 states in our StateMachine example as follows;
Validate
Doors
On
Error
BuildCar
Error
Doors
Simple Method that outputs to log “Building Car”
Simple Method that outputs to log “Error with
Car”
Method that grabs the Attribute (Number of Doors), checks it is less than <
5, if true then it exits MIQ_OK, otherwise it exits MIQ_ERROR
– My First StateMachine!
Check point
To re-cap, you should have a tree view to your StateMachine something like this;
The code behind build_car and error_doors should be something like;
– My First StateMachine!
Check point
The code behind validate_doors is slightly more complex and should be something
like;
– My First StateMachine!
Step 5 – Create the Instance
The instance will be the object that gets instantiated, here is the instance we will
create, this first time we will call it family car.
Later we are going to create other car types, and extend our use of this
StateMachine, showing how easy, reusable and extensible it can be.
– My First StateMachine!
Running the StateMachine
Executing the StateMachine can be done in numerous ways;
Policies – Raise Automation Event
Events – Raise Automation Event
Custom Buttons – Link direct to an Automation Request
Web Services – SOAP call to Automation Request
For this example we shall use a custom button.
– My First StateMachine!
Custom Button
Configuration
We will link the button to an
instance in the /System/Request
class called “car”.
Notice that the button Text we
are setting to “Family Car”
Don’t forget to wire your
/System/Request/car instance
to your
/MyFirstStateMachine/Car/fam
ilyCar instance.
– My First StateMachine!
Executing the StateMachine!
When the instance was created called “Family Car” the default for Number of Doors
was used, this should have been set to 4 in the schema. Therefore when the Validate
Doors state runs, we will pass with no error.
[----] I, [2013-09-10T12:19:38.351213 #11411:9919ffc] INFO -- : Following Relationship [miqaedb:/MyFirstStateMachine/car/familyCar#create]
[----] I, [2013-09-10T12:19:38.360325 #11411:9919ffc] INFO -- : In State=[validate_doors], invoking [on_entry] method=[validate_doors]
[----] I, [2013-09-10T12:19:38.362838 #11411:9919ffc] INFO -- : Invoking [inline] method [MyFirstStateMachine/car/validate_doors] with inputs
[{}]
[----] I, [2013-09-10T12:19:38.611718 #11411:d7fa0b4] INFO -- : <User-Defined Method> Automate Method Started
[----] I, [2013-09-10T12:19:38.612049 #11411:d7fa0b4] INFO -- : <User-Defined Method> ********* VALIDATE DOORS ***********
[----] I, [2013-09-10T12:19:38.612908 #11411:d7fa0b4] INFO -- : <User-Defined Method> Number of Doors = 4
[----] I, [2013-09-10T12:19:38.613257 #11411:d7fa0b4] INFO -- : <User-Defined Method> Automate Method Ended
[----] I, [2013-09-10T12:19:38.618829 #11411:9919ffc] INFO -- : Method exited with rc=MIQ_OK
[----] I, [2013-09-10T12:19:38.619363 #11411:9919ffc] INFO -- : Next State=[build_car]
[----] I, [2013-09-10T12:19:38.619714 #11411:9919ffc] INFO -- : In State=[build_car], invoking [on_entry] method=[build_car]
[----] I, [2013-09-10T12:19:38.622929 #11411:9919ffc] INFO -- : Invoking [inline] method [MyFirstStateMachine/car/build_car] with inputs [{}]
[----] I, [2013-09-10T12:19:38.911154 #11411:d82b8d0] INFO -- : <User-Defined Method> Automate Method Started
[----] I, [2013-09-10T12:19:38.911524 #11411:d82b8d0] INFO -- : <User-Defined Method> ******* BUILD THE CAR *******
[----] I, [2013-09-10T12:19:38.911843 #11411:d82b8d0] INFO -- : <User-Defined Method> Automate Method Ended
[----] I, [2013-09-10T12:19:38.919020 #11411:9919ffc] INFO -- : Method exited with rc=MIQ_OK
[----] I, [2013-09-10T12:19:38.919520 #11411:9919ffc] INFO -- : Next State=[]
[----] I, [2013-09-10T12:19:38.919667 #11411:9919ffc] INFO -- : Followed Relationship [miqaedb:/MyFirstStateMachine/car/familyCar#create]
– My First StateMachine!
Seeing the StateMachine Error outTo cause the StateMachine to error out to the “error_doors” state we simply just increase the
“number_of_doors” attribute to a figure equal to/greater than 5.
[----] I, [2013-09-10T12:51:35.789525 #11411:9919ffc] INFO -- : Following Relationship [miqaedb:/MyFirstStateMachine/car/familyCar#create]
[----] I, [2013-09-10T12:51:35.864078 #11411:9919ffc] INFO -- : In State=[validate_doors], invoking [on_entry] method=[validate_doors]
[----] I, [2013-09-10T12:51:35.866869 #11411:9919ffc] INFO -- : Invoking [inline] method [MyFirstStateMachine/car/validate_doors] with inputs [{}]
[----] I, [2013-09-10T12:51:35.926245 #12128:a922804] INFO -- : Following Relationship [miqaedb:/System/Event/ems_auth_unreachable#create]
[----] I, [2013-09-10T12:51:35.926752 #12128:a922804] INFO -- : Instance [/System/Event/ems_auth_unreachable] not found in MiqAeDatastore - trying
[.missing]
[----] I, [2013-09-10T12:51:35.932561 #12128:a922804] INFO -- : Followed Relationship [miqaedb:/System/Event/ems_auth_unreachable#create]
[----] I, [2013-09-10T12:51:36.290497 #11411:d29a4ac] INFO -- : <User-Defined Method> Automate Method Started
[----] I, [2013-09-10T12:51:36.290871 #11411:d29a4ac] INFO -- : <User-Defined Method> ********* VALIDATE DOORS ***********
[----] I, [2013-09-10T12:51:36.291846 #11411:d29a4ac] INFO -- : <User-Defined Method> Number of Doors = 10
[----] I, [2013-09-10T12:51:36.292288 #11411:d29a4ac] INFO -- : <User-Defined Method> Number of Doors has exceeded the maximum allowed of 4
[----] E, [2013-09-10T12:51:36.389610 #11411:9919ffc] ERROR -- : State=<validate_doors> running on_entry raised exception: <Method exited with
rc=MIQ_STOP>
[----] W, [2013-09-10T12:51:36.389870 #11411:9919ffc] WARN -- : Error in State=[validate_doors]
[----] I, [2013-09-10T12:51:36.390052 #11411:9919ffc] INFO -- : In State=[validate_doors], invoking [on_error] method=[error_doors]
[----] I, [2013-09-10T12:51:36.393388 #11411:9919ffc] INFO -- : Invoking [inline] method [MyFirstStateMachine/car/error_doors] with inputs [{}]
[----] I, [2013-09-10T12:51:36.945727 #11411:d2e3e04] INFO -- : <User-Defined Method> Automate Method Started
[----] I, [2013-09-10T12:51:36.946097 #11411:d2e3e04] INFO -- : <User-Defined Method> ******** ERROR DOORS ********
[----] I, [2013-09-10T12:51:36.946466 #11411:d2e3e04] INFO -- : <User-Defined Method> Automate Method Ended
[----] I, [2013-09-10T12:51:37.073448 #11411:9919ffc] INFO -- : Method exited with rc=MIQ_OK
[----] I, [2013-09-10T12:51:37.073905 #11411:9919ffc] INFO -- : Followed Relationship [miqaedb:/MyFirstStateMachine/car/familyCar#create]
– My First StateMachine!
Summary
We created;
Namespace, Class and set the schema.
Wrote the state methods for validate_doors, error_doors & build_car.
Created the instance that a custom button with initiate.
We had two runs of the StateMachine,
Run 1 – Everything succeeded due to the “number_of_doors” < 5
Run 2 – Failure occurred in validate_doors because number_of_doors was > 4, we
observed error_doors was executed.
– My First StateMachine!
What Next…?
We will now extend the custom button so we can execute a Family Car or a Sports
Car.
When we select
– Example 2
Step 1 – Create a new Custom Button
Create a new custom bottom with very similar
values to that of your first Custom Button.
Notice that we have added Attribute/Value Pairs.
This will allow the button to pass the attribute
“carType” with the value “sportsCar” to the
Request instance.
Update your previous button “Family Car” with
the Attribute/Value combination, with value as
“familyCar”
– Example 2
Step 2 – Using Variables in Relationships
Using variables to connect two instances together gives us huge flexibility in how we
can fork and control the path of a StateMachine.
Adjust your /System/Request/car instance, so that the relationship to the
/MyFirstStateMachine/familyCar is changed to find an instance that is “${/#carType}”
– Example 2
Step 3 – Create the Sport Car Instance
Create the new instance Sports Car in your /MyFirstStateMachine/Car class.
Set the number of doors to 2.
– Example 2
Try it out
You should now have two buttons configured, Sports Car and Family Car. There is
only one StateMachine setup, but with two instances for the Sports Car and Family
Car executions.
When the Sports Car StateMachine executes, you will see Validate_Doors report only
2 doors, and when Family Car is instantiated you will get 10 doors reported and it
errors out.
Summary – Multiple buttons, single
StateMachine, variablized relationships to
multiple instances.
Why are we here?
Real Cloud Based State Machines
Real Cloud Use-Cases
What sort of automation is possible?
Inbound or Outbound?
First question is
Real Cloud Use-Cases - InboundFrom What?
HelpDesk – We return Insight data back via an agreed standard.
HelpDesk – We are initiated to perform a SmartState scan, to update the
information that they are displaying.
HelpDesk – We are initiated to retire a VM.
HelpDesk – We are initiated to evacuate a host of its VMs
CMDB – The CMDB calls into us for specific data sets that we format and return.
CMDB – The CMDB has raised an event on a failed network, it notifies CF/MIQ to
tag all VMs associated with the failure.
Real Cloud Use-Cases - InboundFrom What?
ServiceCatalog – The catalog reads from us values to populate its dialogs, then
upon submission of the item we are initiated to provision the requested item.
Real Cloud Use-Cases - OutboundTo What?
CMDB– We the CMP deliver inventory data that we are collecting to the webservice
of the CMDB.
HelpDesk – Tickets are automatically opened and closed by the CMP upon tasks
like provisioning, retirement etc..
Placement – Use external systems to provide value to virtual machine placement in
the environment during provisioning.
Quota – Look up in financial systems or other Cloud Costing products for further
data to aid quota evaluation.
IPAM – During provisioning goto an IPAM system to retrieve an IP address for the
instance or virtual machine.
Real Cloud Use-Cases - OutboundTo What?
IPAM – During retirement goto an IPAM system to release an IP address from the
instance or virtual machine back to the pool.
CIP – Work with the Cloud Infrastructure Platform to provision storage, switches or
further hosts.
Not to mention some of the others like;
• DNS (create/delete records),
• DHCP (create/delete reservations),
• Active Directory (domain membership management)
• Foreman/Cobbler/Satellite 5/6 (OS build/assignments)
• Puppet/Radia/SCCM Software Management
Invocation
How to make things happen!
Choices
• Alerts
• Policies
• SoapAPI
• RestAPI
• Buttons
You can also use Simulation to invoke;
• Policies
• Automation Directly
Buttons
Button Groups, group Buttons.
• A button may have a dialog.
• A button must have an image.
• A button can pass messages.
• Attributes/Values can be passed.
The last item is nice as one method can
be called with different attribute/values
from different buttons. Eg, Clone2MS,
Clone2EC2, Clone2vAIR = 1 method,
with a case select.
Policies
Policies can call automation in two
different ways.
1. Invoke a Custom Automation
2. Raise Automation Event
Policies – Invoke a Custom Automation
Policies – Raise an Automation Event
[miqaedb:/System/Event/assigned_company_tag#create]
The raise an automation event, depending on the event you choose to monitor is
raised, first example is “assigned_company_tag” because I selected;
Policies – Raise an Automation EventOther examples…
[miqaedb:/System/Event/PowerOnVM_Task#create]
Or
[miqaedb:/System/Event/PowerOffVM_Task#create]
Policies – Raise an Automation EventFrom your miqaedb:/System/Event/……
You can configure routes to anything you want!
Policies – Invoke a Custom AutomationThis is a lot easier, once you have created your ACTION, with a valid message and
request URI, you are free to create what you specified.
Best Practice – Always set your request to /System/Request
Whilst you can point anywhere, most OOTB functions will look in /System/Request
for the start of an automation task.
Alerts – Management EventVery much the same as Invoke a Custom Automation,
Set the Event Name in the Event.
The create an instance by the same name in the /System/Event class
soapAPI - 1The soapAPI has been superseded in most by the newly added restAPI as found
in ManageIQ Anand and Cloudforms 3.1.
When should I use soapAPI?
When restAPI is NOT available!
About the API
• Read the Integration guide (great info with examples)
• Broken down into 3 different sections
• Insight web services – performs queries against vmdb items
• Control web services – query control related information and perform basic tasks like tagging
• Automate web services – create/query automation and provisioning requests
• Simple Object Access Protocol (SOAP) based Extensible Markup Language (XML)
• Ruby, PowerShell, Perl, JScript, etc…
WSDL Review
• https://<cloudforms-appliance>/vmdbws/wsdl
• There are 3 types of calls
• Query – calls that query CFME for data (I.e. GetEmsList - returns all Management Systems as list objects)
• Action – calls that perform an action (I.e. VmSetTag -applies a tag to a VM by specifying the tag category and name
• Request – calls that create automation and provision requests
Query Example
Query EMS – Ruby#!/usr/bin/env ruby
# CFME Automate Method: GetEmsList.rb
# Require necessary gems
require 'savon'
# Set up Savon client
client = Savon::Client.new do |wsdl, http|
wsdl.document = "https://cloudforms.cloudelicious.com/vmdbws/wsdl"
http.auth.basic 'admin', ‘’smartvm'
http.auth.ssl.verify_mode = :none
end
# Query CFME web-service
response = client.request 'GetEmsList'
# Convert response to hash
response_hash = response.to_hash[:get_ems_list_response][:return]
puts "CFME web-service returned: #{response_hash.inspect}"
# Loop through each management system in the array and log the name and guid
response_hash[:item].each { |key| puts "Found Management System: #{key[:name].inspect} GUID:
#{key[:guid].inspect}" }
Query EMS – Ruby Output
CFME web-service returned: {:item=>[{:guid=>"9f41086a-f488-11e2-9677-001a4a0ba4f3", :name=>"RHEVM-001"},
{:guid=>"035f424e-f48e-11e2-9677-001a4a0ba4f3", :name=>"VMware-001"}],
:"@xmlns:n2"=>"http://schemas.xmlsoap.org/soap/encoding/", :"@n2:array_type"=>"n1:VmdbwsSupport..EmsList[2]",
:"@xsi:type"=>"n2:Array"}
Found Management System: "RHEVM-001" GUID: "9f41086a-f488-11e2-9677-001a4a0ba4f3"
Found Management System: "VMware-001" GUID: "035f424e-f48e-11e2-9677-001a4a0ba4f3"
Action Example
VM Set Tag - Ruby#!/usr/bin/env ruby
# CFME Automate Method: VMSetTag.rb
# Require necessary gems
require 'savon'
# Set up Savon client
client = Savon::Client.new do |wsdl, http|
wsdl.document = "https://cloudforms.cloudelicious.com/vmdbws/wsdl"
http.auth.basic 'admin', ‘smartvm'
http.auth.ssl.verify_mode = :none
end
# Query CFME web-service
response = client.request :vm_set_tag do
soap.body = { 'vmGuid'=>'9badadc8-fe2b-11e2-a507-005056a231cb', 'category'=>'function',
'name'=>'database' }
end
# Convert response to hash
response_hash = response.to_hash[:vm_set_tag_response]
puts "CFME web-service hash returned: #{response_hash.inspect}"
# Loop through each management system in the array and log the name and guid
puts "CFME Returned: #{response_hash[:return].inspect}"}
VM Set Tag – Ruby Output<?xml version="1.0" encoding="UTF-8" ?>
<env:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:VmSetTagResponse env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:n1="urn:ActionWebService">
<return xsi:type="xsd:boolean">true</return>
</n1:VmSetTagResponse>
</env:Body>
</env:Envelope>
CFME web-service hash returned: {:return=>true,
:"@env:encoding_style"=>"http://schemas.xmlsoap.org/soap/encoding/",
:"@xmlns:n1"=>"urn:ActionWebService"}
CFME Returned: true
Request Example -Automation
Create Automation Request
• This method initiates an automation request. It can be
used to drive an automation workflow and provide
feedback to the requester.
• Execute any instance or SateMachine you want!
• Input parameters• version
• uri_parts
• Parameters – these guys show up in $evm.root
• requester
Create Automation Request - Ruby
#!/usr/bin/env ruby
# CreateAutomationRequest.rb
# Require necessary gems
require 'savon'
# Set up Savon client
client = Savon::Client.new do |wsdl, http|
wsdl.document = "https://cloudforms.cloudelicious.com/vmdbws/wsdl"
http.auth.basic 'admin', 'smartvm'
http.auth.ssl.verify_mode = :none
end
# Build has of paramters
body_hash = {}
body_hash['version'] = '1.1'
body_hash['uri_parts'] = "namespace=Sample|class=Methods|instance=InspectMe|message=create"
body_hash['parameters'] = 'parm1=parameter1|parm2=parameter2'
body_hash['requester'] = "auto_approve=true"
response = client.request :create_automation_request do |soap|
soap.body = body_hash
end
request_hash = response.to_hash
puts "Request Returned: #{request_hash.inspect}"
puts "Automation Request Id: #{request_hash[:create_automation_request_response][:return].inspect}"
exit
Create Automation Request – Ruby Output
<?xml version="1.0" encoding="UTF-8" ?>
<env:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<n1:CreateAutomationRequestResponse
env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:n1="urn:ActionWebService">
<return xsi:type="xsd:string">919000000000071</return>
</n1:CreateAutomationRequestResponse>
</env:Body>
</env:Envelope>
Request Returned: {:create_automation_request_response=>{:return=>"919000000000071",
:"@env:encoding_style"=>"http://schemas.xmlsoap.org/soap/encoding/",
:"@xmlns:n1"=>"urn:ActionWebService"}}
Automation Request Id: "919000000000071"
Request Example -Provisioning
VM Provision Request
• VmProvisionRequest – This initiates a VM provision
request and returns an request id object that provides
feedback
• EVMProvisionRequestEx – This initiates a VM provision
request and returns true|false with no added feedback
• VmProvisionRequest Input parameters• version
• templateFields
• vmFields
• requester
• tags
• Options
• Dialogs are the keys to success
VM Provision Request - Ruby#!/usr/bin/env ruby
# VMProvisionRequest.rb
# Require necessary gems
require 'savon'
# Set up Savon client
client = Savon::Client.new do |wsdl, http|
wsdl.document = "https://cloudforms.cloudelicious.com/vmdbws/wsdl"
http.auth.basic 'admin', ‘smartvm'
http.auth.ssl.verify_mode = :none
end
# Build hash of paramters
body_hash = {}
body_hash['version'] = '1.1'
body_hash['templateFields'] = "name=rhel63|request_type=template|guid=cb73axb8-f46f-11e2-ba2d-005056a231cb"
body_hash['vmFields'] = 'vm_name=changeme|cores_per_socket=1|vm_memory=1024|vm_auto_start=true'
body_hash['requester'] = "user_name=admin|owner_last_name=Lastname|owner_first_name=Firstname"
body_hash['tags'] = "environment=dev|function=database"
body_hash['options'] = { 'values' => 'parm1=parameter1|parm2=parameter2', 'miq_custom_attributes' => "", 'ems_custom_attributes'
=> "" }
response = client.request :vm_provision_request do |soap|
soap.body = body_hash
end
request_hash = response.to_hash
puts "Request Returned: #{request_hash.inspect}"
puts "Provision Request Id: #{request_hash[:vm_provision_request_response][:return][:id].inspect}”
VM Provision Request – Ruby Output
VM Request Returned: {:vm_provision_request_response=>{:return=>{:id=>"919000000000074",
:description=>"Provision from [rhel63] to [cfmedev###]", :approval_state=>"pending_approval"….(Output is too
large to show all of it)
VM Provision Request Id: "919000000000074"
Q & A