Skip to content

Commit

Permalink
Service for VMware content library item deployment.
Browse files Browse the repository at this point in the history
  • Loading branch information
lfu committed Sep 21, 2020
1 parent d324862 commit def351f
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 1 deletion.
2 changes: 1 addition & 1 deletion app/models/manageiq/providers/vmware/infra_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def supports_authentication?(authtype)
end

def self.catalog_types
{"vmware" => N_("VMware")}
{"vmware" => N_("VMware"), "generic_ovf_template" => N_("VMware Content Libary OVF Template")}
end

def streaming_refresh_enabled?
Expand Down
150 changes: 150 additions & 0 deletions app/models/manageiq/providers/vmware/infra_manager/ovf_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
class ManageIQ::Providers::Vmware::InfraManager::OvfService < ServiceGeneric
delegate :template, :manager, :to => :service_template, :allow_nil => true

# A chance for taking options from automate script to override options from a service dialog
def preprocess(action, new_options = {})
return unless action == ResourceAction::PROVISION

if new_options.present?
_log.info("Override with new options:")
$log.log_hashes(new_options)
end

save_action_options(action, new_options)
end

def execute(action)
return unless action == ResourceAction::PROVISION

library_item_deploy_queue
end

def library_item_deploy_queue
task_options = {:action => "Deploying VMware Content Library Item", :userid => "system"}
queue_options = {
:class_name => self.class.name,
:instance_id => id,
:method_name => "library_item_deploy",
:args => {},
:role => "ems_operations",
#:queue_name => manager.queue_name_for_ems_operations,
:zone => manager.my_zone
}

task_id = MiqTask.generic_action_with_callback(task_options, queue_options)
task = MiqTask.wait_for_taskid(task_id)
raise task.message unless task.status_ok?
end

def library_item_deploy(_options)
_log.info("OVF template provisioning with template ID: [#{template.id}] name:[#{template.name}] was initiated.")
opts = provision_options
_log.info("VMware Content Library OVF Tempalte provisioning with options:")
$log.log_hashes(opts)

@deploy_response = template.deploy(opts).to_hash
_log.info("Content Library request response: #{@deploy_response}")
update(:options => options.merge(:deploy_response => @deploy_response))
rescue VSphereAutomation::ApiError => e
_log.error("Failed to deploy content library template(#{template.name}), error: #{e}")
raise MiqException::MiqOrchestrationProvisionError, "Content library OVF template deployment failed: #{e}"
end

def check_completed(action)
return [true, 'not supported'] unless action == ResourceAction::PROVISION
return [false, nil] if deploy_response.blank?

message = deploy_response.dig(:value, :succeeded) ? nil : deploy_response.dig(:value, :error).to_json || deploy_response.to_json
[true, message]
end

def refresh(_action)
EmsRefresh.queue_refresh(refresh_target) if deploy_response.dig(:value, :succeeded)
end

def check_refreshed(action)
return [true, nil] unless deploy_response.dig(:value, :succeeded)

dest = find_destination_in_vmdb
if dest
add_resource!(dest, :name => action)

if dest.kind_of?(ResourcePool)
dest.vms.each { |vm| add_resource!(vm, :name => action) }
end

[true, nil]
else
[false, nil]
end
end

def refresh_target
target_folder || target_host || target_resource_pool
end

private

def deploy_response
@deploy_response ||= options[:deploy_response]
end

def find_destination_in_vmdb
target_model_class.find_by(:ems_id => manager.id, :ems_ref => deploy_response.dig(:value, :resource_id, :id))
end

def target_model_class
case deploy_response.dig(:value, :resource_id, :type)
when "VirtualMachine"
manager.class::Vm
when "VirtualApp"
manager.class::ResourcePool
end
end

def target_folder
@target_folder ||= EmsFolder.find_by(:id => provision_options[:ems_folder_id])
end

def target_host
@target_host ||= Host.find_by(:id => provision_options[:host_id])
end

def target_resource_pool
@target_resource_pool ||= ResourcePool.find_by(:id => provision_options[:resource_pool_id])
end

def get_action_options(action)
options[action_option_key(action)]
end

def provision_options
@provision_options ||= get_action_options(ResourceAction::PROVISION)
end

def save_action_options(action, overrides)
return unless action == ResourceAction::PROVISION

action_options = options.fetch_path(:config_info, action.downcase.to_sym).with_indifferent_access
action_options.deep_merge!(parse_dialog_options)
action_options.deep_merge!(overrides)

options[action_option_key(action)] = action_options
save!
end

def parse_dialog_options
dialog_options = options[:dialog] || {}
options = {:vm_name => dialog_options['dialog_vm_name']}
options[:accept_all_EULA] = dialog_options['dialog_accept_all_EULA'] == 't'

%w[resource_pool ems_folder host].each do |r|
options["#{r}_id".to_sym] = dialog_options["dialog_#{r}"].split.first.to_i if dialog_options["dialog_#{r}"].present?
end
options
end

def action_option_key(action)
"#{action.downcase}_options".to_sym
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
class ManageIQ::Providers::Vmware::InfraManager::OvfServiceTemplate < ServiceTemplateGeneric
def self.default_provisioning_entry_point(_service_type)
'/Service/Generic/StateMachines/GenericLifecycle/provision'
end

# create ServiceTemplate and supporting ServiceResources and ResourceActions
# options
# :name
# :description
# :service_template_catalog_id
# :config_info
# :provision
# :dialog_id or :dialog
# :template_id or :template
#
def self.create_catalog_item(options, _auth_user)
options = options.merge(:service_type => 'atomic', :prov_type => 'generic_ovf_template')
config_info = validate_config_info(options[:config_info])
enhanced_config = config_info.deep_merge(
:provision => {
:configuration_template => template_from_config_info(config_info)
}
)

transaction do
create_from_options(options).tap do |service_template|
service_template.create_resource_actions(enhanced_config)
end
end
end

def self.validate_config_info(info)
info[:provision][:fqname] ||= default_provisioning_entry_point(SERVICE_TYPE_ATOMIC) if info.key?(:provision)

# TODO: Add more validation for required fields
info
end
private_class_method :validate_config_info

def self.template_from_config_info(info)
template_id = info[:provision][:template_id]
template_id ? OrchestrationTemplate.find(template_id) : info[:provision][:template]
end
private_class_method :template_from_config_info

def template
@template ||= resource_actions.find_by(:action => "Provision").try(:configuration_template)
end

def manager
@manager ||= template.try(:ext_management_system)
end

def update_catalog_item(options)
config_info = validate_update_config_info(options)
config_info[:provision][:configuration_template] ||= template_from_config_info(config_info) if config_info.key?(:provision)
options[:config_info] = config_info

super
end

private

def template_from_config_info(info)
self.class.send(:template_from_config_info, info)
end

def validate_update_config_info(options)
opts = super
self.class.send(:validate_config_info, opts)
end

def update_service_resources(_config_info, _auth_user = nil)
# do nothing since no service resources for this template
end

def update_from_options(params)
options[:config_info] = Hash[params[:config_info].collect { |k, v| [k, v.except(:configuration_template)] }]
update!(params.except(:config_info))
end
end

0 comments on commit def351f

Please sign in to comment.