Passing arrays into dialog_parser


#1

If I provision an OpenStack instance by going to Clouds > Instances > Lifecycle > Provision Instances and watch the log file with object_walker active, I see that the value of the cloud_tenant drop-down box is an array:

[----] I, [2016-03-23T16:08:16.986533 #2655:276d354] INFO -- : Q-task_id([miq_provision_249]) <AEMethod object_walker> object_walker#C56B6536:[2] $evm.root['miq_provision'].options[:cloud_tenant] = [2, "demo"] (type: Array)

However, if I create and request a service with a service dialog that contains a drop down list with various OpenStack tenants, object_walker reports the value as being an integer instead of an array. For example, instead of [2, “demo”], it is just the value 2, which causes the provision to fail since I guess something further along expects it to be an array. To get around this I go into dialog_parser and make the following changes.

In the case statement I get the value of dialog_cloud_tenant, use it to find the CloudTenant’s name and building an array:

def parse_dialog_entries(dialog_options)
  options_hash        = Hash.new { |h, k| h[k] = {} }
  tags_hash           = Hash.new { |h, k| h[k] = {} }
dialog_options.each do |key, value|
    
    case key
    when 'dialog_cloud_tenant'
      $evm.log(:info, "dialog_parser: Changing #{key} value")
      cloud_tenant_name = $evm.vmdb('CloudTenant').find(value).name
      value = [value, cloud_tenant_name]
    when 'dialog_cloud_network'
      $evm.log(:info, "dialog_parser: Changing #{key} value")
      cloud_network_name = $evm.vmdb('CloudNetwork').find(value).name
      value = [value, cloud_network_name]
    end
    
    $evm.log(:info, "dialog_parser: key: #{key}, value: #{value}")
    next if value.blank?
    set_dialog_value(key, value, options_hash, tags_hash)
  end
  return options_hash, tags_hash
end

This happens if I use the Service Dialog interface to create static values in the drop down list or create my own values by enabling the drop down list to be dynamic using a script like this:

tenant_list = {}
tenant_list[1] = "demo"
tenant_list[2] = "admin"
list_values	= {
    'sort_by'   => :value,
    'required'  =>  true,
    'data_type' => :integer, 
    'values'    =>  tenant_list,
  }
list_values.each { |key, value| $evm.object[key] = value }

I’ve tried setting the ‘data_type’ key to array, hash and leaving it out.

All I’m trying to do is build a simple service dialog that has the options similar to what is displayed when you go to Clouds > Instances > Lifecycle > Provision Instances > Environment tab:

I’d like to just use the same functionality in this form in my service dialogs, but I can’t figure it out. This form is nice because if a user selects a cloud tenant, it automatically refreshes all the other elements.

So if anyone knows how I can make service dialogs that I create pass in arrays instead of integers and/or make form on the Clouds > Instances > Lifecycle > Provision Instances > Environments tab work in a service dialog that I create, I/'d be great full. Thanks.


Provisioning vm with host and datastore
#2

The :cloud_tenant options hash key has its own ‘set’ method that formats the array for you. Use prov.set_cloud_tenant(object).

See https://pemcg.gitbooks.io/introduction-to-cloudforms-automation/content/chapter15/options_hash.html for an example.

pemcg


#3

OK thanks. I was able to set it that way but I thought I was doing it wrong. I thought passing in the array/hash from the dialog options would be good enough. It seems weird that I build the drop down list using the cloud tenant/network values from vmdb and then during the provisioning process I have to get query vmdb again to get the tenant/network name. I guess it’s a layer of validation in case the user does something not through the GUI like makes an API call with the wrong info. I also did it using the method you described here:
https://pemcg.gitbooks.io/introduction-to-cloudforms-automation/content/chapter17/state_machine.html

Anyways, thanks again. I’m not a programmer so this doesn’t come easy and your book is indispensable.


#4

Thanks sg_chris.

What’s confusing is the multiple generations of object, each with their options hash, and the various methods that can be used to insert entries into each.

If we start with the top level object parent service_template_provision_task, this has an options hash with a useful key called :dialog. This parent options hash key contains the values that the input supplied from the service dialog.

Sometimes it’s useful to propagate the contents of this :dialog options hash key to the child miq_request_task so that it also has visibility of the dialog values supplied by the user. To do this the parent service_template_provision_task calls the .set_dialog_option method (note the ‘dialog’ in the name).

Now we also somehow have to set the options hash keys in the grandchild miq_provision object that is handling the provisioning of the actual VM (in your case this was :cloud_tenant). For this we use the .set_option method (note no ‘dialog’ in the name), or the specific ‘set’ methods that some of the keys have. As it happens :cloud_tenant has its own method that we should use, .set_cloud_tenant, but this takes an MiqAeServiceCloudTenant object as its parameter, so we need to perform a VMDB lookup on the cloud tenant ID passed from the dialog, to find its object.

Hope this helps,

pemcg


#5

That makes sense. Thanks for information.