Service Catalog drop-down shows script error

Hello,

I am trying to create a customized service catalog for our operations team to use to provision VMs on certain templates, datastores and networks. There are quite a lot of templates, datastores and networks and going the conventional way of using lifecycle isn’t practical. Within the lifecycle screen it takes a lot of time to select each item under Environment tab (i.e. Datacenter, Cluster, Folder, and Datastore).

In order to shorten the process I would like to create service catalog where I provide a drop down of templates, datastores and networks to choose from. I got the template drop down to work, but not the datastores. on the datastores drop down I get Script Error message when I run the service catalog

Here is the code:

# list_datastores.rb
#
# Description: List the datastores associated with a provider
#

# Get vm object from root
vm = $evm.root['vm']
raise "Missing $evm.root['vm'] object" if vm.nil?

provider = vm.ext_management_system.name
$evm.log(:info, "Detected Provider: #{provider.name}")

datastores_hash = {}

provider.storages.each do |storage|
  #next unless template.tagged_with?('prov_scope', 'all')
  #next unless template.vendor.downcase == 'vmware'
  if vm.storage.ems_ref == storage.ems_ref
    datastores_hash[storage[:ems_ref]] = "<current> #{storage[:name]}"
  else
  	datastores_hash[storage[:ems_ref]] = storage[:name]
  end
end

$evm.object['values'] = datastores_hash
$evm.log(:info, "Dialog Values: #{$evm.object['values'].inspect}")

Can someone guide me on how to troubleshoot this? also what am I doing wrong here?

Hi

The automation.log file should give an idea of what the specific error is in your script, but at first glance it’s probably that you won’t have a $evm.root['vm'] object if the script is run from a service dialog fronting a service catalog order. What may be confusing is that you would have this object if the same dialog is run from a button on the VM object.

If you’re looking to match against the datastore that the selected template uses, then I’d suggest performing a $evm.vmdb lookup of the template ID that was returned from the previous ‘Template’ drop-down, for example something like:

vm = $evm.vmdb(:vm_or_template, dialog_template_id)

Hope this helps,
pemcg

Thank you pemcg. That makes sense. I gotta confess I am new to manageiq and ruby language and my next question might be obvious but I replaced #evm.root[‘vm’] with

and when I look at the log, I see these errors. From the error below I think I needed to change dialog_template_id or define it somehow. Can someone point me on what I am doing wrong? Also if there are examples on how to link between different dialogs, that would be appreciated.

[----] E, [2019-12-17T11:53:50.596340 #3265:93ebf80] ERROR -- : <AEMethod list_datastores> The following error occurred during method evaluation:
[----] E, [2019-12-17T11:53:50.596735 #3265:93ebf80] ERROR -- : <AEMethod list_datastores>   NameError: undefined local variable or method `dialog_template_id' for main:Object
[----] E, [2019-12-17T11:53:50.597827 #3265:93ebf80] ERROR -- : <AEMethod list_datastores>
[----] E, [2019-12-17T11:53:50.600320 #3265:93ebf80] ERROR -- : Method STDERR: /Mydomain/Integration/VMware/DynamicDropDowns/list_datastores:8:in `<main>': undefined local variable or method `dialog_template_id' for main:Object (NameError)
[----] I, [2019-12-17T11:53:50.617639 #3265:4ffea5c]  INFO -- : <AEMethod [/Mydomain/Integration/VMware/DynamicDropDowns/list_datastores]> Ending
[----] E, [2019-12-17T11:53:50.618377 #3265:4ffea5c] ERROR -- : Aborting instantiation (unknown method return code) because [Method exited with rc=Unknown RC: [1]]

Below is the template dropdown method which I got from one of Kevin Morey scripts. (I still need to modify it to check for specific template name pattern but I want to get the basics working first then attempt to tweak the script.)

def get_user
  user_search = $evm.root['dialog_userid'] || $evm.root['dialog_evm_owner_id']
  user = $evm.vmdb('user').find_by_id(user_search) || $evm.vmdb('user').find_by_userid(user_search) ||
    $evm.root['user']
  user
end

def get_current_group_rbac_array(user, rbac_array=[])
  unless user.current_group.filters.blank?
    user.current_group.filters['managed'].flatten.each do |filter|
      next unless /(?<category>\w*)\/(?<tag>\w*)$/i =~ filter
      rbac_array << {category=>tag}
    end
  end
  $evm.log(:info, "rbac filters: #{rbac_array}")
  rbac_array
end

def template_eligible?(rbac_array, template)
  return false if template.archived || template.orphaned
  rbac_array.each do |rbac_hash|
    rbac_hash.each {|category, tag| return false unless template.tagged_with?(category, tag)}
  end
  $evm.log(:info, "template: #{template.name} is eligible")
  true
end

user = get_user
rbac_array = get_current_group_rbac_array(user)

dialog_hash = {}
$evm.vmdb(:template_vmware).all.each do |template|
  if template_eligible?(rbac_array, template)
    dialog_hash[template[:guid]] = "#{template.name} on #{template.ext_management_system.name}"
  end
end

if dialog_hash.blank?
  log(:info, "No Templates found")
  dialog_hash[''] = "< No Templates found >"
else
  dialog_hash[''] = '< choose a template >'
end

$evm.object["values"] = dialog_hash
$evm.log(:info, "$evm.object['values']: #{$evm.object['values'].inspect}")

This needs to be the name of the “Template” element in your service dialog, prefixed by “dialog_”. I was assuming that your element was called “template_id”, but you need to use whatever your specific element is called in the service dialog editor.

pemcg