Skip to content

Commit

Permalink
Merge pull request #632 from pkomanek/openstack_customizerequest_refa…
Browse files Browse the repository at this point in the history
…ctoring

Refactor openstack_customizerequest method for VM Provisioning.
  • Loading branch information
tinaafitz authored Mar 24, 2020
2 parents cbe5517 + 4a9f0f7 commit 49dc304
Show file tree
Hide file tree
Showing 2 changed files with 295 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,99 +2,166 @@
# Description: This method is used to Customize the Openstack Provisioning Request
#

# process_customization - mapping instance_types, key pairs, security groups and cloud-init templates
def process_customization(mapping, prov, template, product, provider )
log(:info, "Processing Openstack customizations...", true)
case mapping
when 0
# No mapping
when 1
ws_values = prov.options.fetch(:ws_values, {})

if prov.get_option(:instance_type).nil? && ws_values.has_key?(:instance_type)
provider.flavors.each do |flavor|
if flavor.name.downcase == ws_values[:instance_type].downcase
prov.set_option(:instance_type, [flavor.id, "#{flavor.name}':'#{flavor.description}"])
log(:info, "Provisioning object updated {:instance_type => #{prov.get_option(:instance_type).inspect}}")
end
end
end
module ManageIQ
module Automate
module Cloud
module VM
module Provisioning
module StateMachines
module Methods
class OpenstackCustomizeRequest
def initialize(handle = $evm)
@handle = handle
@mapping = false
end

if prov.get_option(:guest_access_key_pair).nil? && ws_values.has_key?(:guest_access_key_pair)
provider.key_pairs.each do |keypair|
if keypair.name == ws_values[:guest_access_key_pair]
prov.set_option(:guest_access_key_pair, [keypair.id,keypair.name])
log(:info, "Provisioning object updated {:guest_access_key_pair => #{prov.get_option(:guest_access_key_pair).inspect}}")
end
end
end
def main
log(:info, "Provision:<#{prov.id}> Request:<#{prov.miq_provision_request.id}> Type:<#{prov.type}>")
log(:info, "Template: #{template.name} Provider: #{provider.name} Vendor: #{template.vendor} Product: #{product}")
log(:info, "Processing Openstack customizations...", true)
process_customization if @mapping
log(:info, "Processing Openstack customizations...Complete", true)
end

if prov.get_option(:security_groups).blank? && ws_values.has_key?(:security_groups)
provider.security_groups.each do |securitygroup|
if securitygroup.name == ws_values[:security_groups]
prov.set_option(:security_groups, [securitygroup.id])
log(:info, "Provisioning object updated {:security_groups => #{prov.get_option(:security_groups).inspect}}")
end
end
end
private

if prov.get_option(:customization_template_id).nil?
customization_template_search_by_function = "#{prov.type}_#{prov.get_tags[:function]}" rescue nil
customization_template_search_by_template_name = template.name
customization_template_search_by_ws_values = ws_values[:customization_template] rescue nil
log(:info, "prov.eligible_customization_templates: #{prov.eligible_customization_templates.inspect}")
customization_template = nil

unless customization_template_search_by_function.nil?
# Search for customization templates enabled for Cloud-Init that equal MiqProvisionOpenstack_prov.get_tags[:function]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_function}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_function)==0 }
end
end
unless customization_template_search_by_template_name.nil?
# Search for customization templates enabled for Cloud-Init that match the template/image name
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_template_name}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_template_name)==0 }
end
end
unless customization_template_search_by_ws_values.nil?
# Search for customization templates enabled for Cloud-Init that match ws_values[:customization_template]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: #{customization_template_search_by_ws_values}")
customization_template = prov.eligible_customization_templates.detect { |ct| ct.name.casecmp(customization_template_search_by_ws_values)==0 }
end
end
if customization_template.blank?
log(:warn, "Failed to find matching Customization Template", true)
else
log(:info, "Found Customization Template ID: #{customization_template.id} Name: #{customization_template.name} Description: #{customization_template.description}")
prov.set_customization_template(customization_template) rescue nil
log(:info, "Provisioning object updated {:customization_template_id => #{prov.get_option(:customization_template_id).inspect}}")
log(:info, "Provisioning object updated {:customization_template_script => #{prov.get_option(:customization_template_script).inspect}}")
end
else
log(:info, "Customization Template selected from dialog ID: #{prov.get_option(:customization_template_id).inspect}} Script: #{prov.get_option(:customization_template_script).inspect}")
end
end # case mapping
log(:info, "Processing Openstack customizations...Complete", true)
end
def prov
@prov ||= @handle.root["miq_provision"].tap do |req|
raise 'miq_provision not specified' if req.nil?
end
end

def log(level, msg, update_message=false)
$evm.log(level, "#{msg}")
$evm.root['miq_provision'].message = "#{msg}" if $evm.root['miq_provision'] && update_message
end
def template
@template ||= prov.vm_template.tap do |req|
raise 'vm_template not specified' if req.nil?
end
end

def provider
@provider ||= template.ext_management_system.tap do |ems|
raise 'ext_management_system not specified' if ems.nil?
end
end

def product
@product ||= template.operating_system&.product_name&.downcase
end

def ws_values
@ws_values ||= prov.options.fetch(:ws_values, {})
end

def process_customization
set_options
set_customization_template
end

def set_options
if prov.get_option(:instance_type).nil? && ws_values.key?(:instance_type)
provider.flavors.each do |flavor|
if flavor.name.downcase == ws_values[:instance_type].downcase
prov.set_option(:instance_type, [flavor.id, "#{flavor.name}':'#{flavor.description}"])
log(:info, "Provisioning object updated {:instance_type => #{prov.get_option(:instance_type).inspect}}")
end
end
end

# Get provisioning object
prov = $evm.root["miq_provision"]
if prov.get_option(:guest_access_key_pair).nil? && ws_values.key?(:guest_access_key_pair)
provider.key_pairs.each do |keypair|
if keypair.name == ws_values[:guest_access_key_pair]
prov.set_option(:guest_access_key_pair, [keypair.id, keypair.name])
log(:info, "Provisioning object updated {:guest_access_key_pair => #{prov.get_option(:guest_access_key_pair).inspect}}")
end
end
end

log(:info, "Provision:<#{prov.id}> Request:<#{prov.miq_provision_request.id}> Type:<#{prov.type}>")
if prov.get_option(:security_groups).blank? && ws_values.key?(:security_groups)
provider.security_groups.each do |securitygroup|
if securitygroup.name == ws_values[:security_groups]
prov.set_option(:security_groups, [securitygroup.id])
log(:info, "Provisioning object updated {:security_groups => #{prov.get_option(:security_groups).inspect}}")
end
end
end
end

template = prov.vm_template
provider = template.ext_management_system
product = template.operating_system['product_name'].downcase rescue nil
log(:info, "Template: #{template.name} Provider: #{provider.name} Vendor: #{template.vendor} Product: #{product}")
def set_customization_template
if prov.get_option(:customization_template_id).present?
log(:info, "Customization Template selected from dialog ID: %{id} Script: %{script}" % {
:id => prov.get_option(:customization_template_id).inspect,
:script => prov.get_option(:customization_template_script).inspect
})
return
end

customization_template_search_by_function = "#{prov.type}_#{prov.get_tags[:function]}"
customization_template_search_by_template_name = template.name
customization_template_search_by_ws_values = ws_values[:customization_template]
log(:info, "prov.eligible_customization_templates: #{prov.eligible_customization_templates.inspect}")
customization_template = nil

unless customization_template_search_by_function.nil?
# Search for customization templates enabled for Cloud-Init that equal MiqProvisionAmazon_prov.get_tags[:function]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{function}" % {
:function => customization_template_search_by_function
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_function) == 0
end
end
end
unless customization_template_search_by_template_name.nil?
# Search for customization templates enabled for Cloud-Init that match the template/image name
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{name}" % {
:name => customization_template_search_by_template_name
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_template_name) == 0
end
end
end
unless customization_template_search_by_ws_values.nil?
# Search for customization templates enabled for Cloud-Init that match ws_values[:customization_template]
if customization_template.blank?
log(:info, "Searching for customization templates (Cloud-Init) enabled that are named: %{ws_value}" % {
:ws_value => customization_template_search_by_ws_values
})
customization_template = prov.eligible_customization_templates.detect do |ct|
ct.name.casecmp(customization_template_search_by_ws_values) == 0
end
end
end
if customization_template.blank?
log(:warn, "Failed to find matching Customization Template", true)
else
log(:info, "Found Customization Template ID: %{id} Name: %{name} Description: %{desc}" % {
:id => customization_template.id,
:name => customization_template.name,
:desc => customization_template.description
})
prov.set_customization_template(customization_template) rescue nil
log(:info, "Provisioning object updated {:customization_template_id => %{id}}" % {
:id => prov.get_option(:customization_template_id).inspect
})
log(:info, "Provisioning object updated {:customization_template_script => %{script}}" % {
:script => prov.get_option(:customization_template_script).inspect
})
end
end

def log(level, msg, update_message = false)
@handle.log(level, msg)
@handle.root['miq_provision'].message = msg if @handle.root['miq_provision'] && update_message
end
end
end
end
end
end
end
end
end

mapping = 0
process_customization(mapping, prov, template, product, provider)
ManageIQ::Automate::Cloud::VM::Provisioning::StateMachines::Methods::OpenstackCustomizeRequest.new.main
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
require_domain_file

describe ManageIQ::Automate::Cloud::VM::Provisioning::StateMachines::Methods::OpenstackCustomizeRequest do
let(:ems) { FactoryBot.create(:ems_openstack_with_authentication) }
let(:template) { FactoryBot.create(:miq_template, :ext_management_system => ems) }
let(:prov_req) { FactoryBot.create(:miq_provision_request, :options => {:src_vm_id => template.id}) }
let(:prov) { FactoryBot.create(:miq_provision, :miq_provision_request => prov_req, :options => {:src_vm_id => template.id}) }
let(:svc_prov) { MiqAeMethodService::MiqAeServiceMiqProvision.find(prov.id) }
let(:root_hash) { {'miq_provision' => svc_prov} }
let(:root_object) { Spec::Support::MiqAeMockObject.new(root_hash) }
let(:ae_service) do
Spec::Support::MiqAeMockService.new(root_object).tap do |service|
current_object = Spec::Support::MiqAeMockObject.new
current_object.parent = root_object
service.object = current_object
end
end

it "process customization without mapping" do
described_class.new(ae_service).main
expect(svc_prov.message).to eq("Processing Openstack customizations...Complete")
end

context 'customization with mapping' do
let(:customization_template) { FactoryBot.create(:customization_template) }

after(:each) { expect(svc_prov.message).to eq("Processing Openstack customizations...Complete") }

def options_with_template(ws_values)
ae_service.root["miq_provision"].options[:ws_values] = ws_values
ae_service.root["miq_provision"].options[:customization_template_id] = customization_template.id
ae_service.root["miq_provision"].options[:customization_template_script] = customization_template.script
end

context '#instance_type' do
let(:ems) { FactoryBot.create(:ems_openstack_with_authentication, :flavors => [flavor]) }
let(:flavor) { FactoryBot.create(:flavor, :description => 'desc') }

it "sets flavor as an instance_type" do
options_with_template(:instance_type => flavor.name)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:instance_type]).to eq([flavor.id, "#{flavor.name}':'#{flavor.description}"])
end
end

context '#guest_access_key_pair' do
let(:keypair) { FactoryBot.create(:auth_key_pair_cloud, :name => "test_auth_key_pair_cloud") }
let(:ems) { FactoryBot.create(:ems_openstack_with_authentication, :key_pairs => [keypair]) }

it "sets keypair as a guest_access_key_pair" do
options_with_template(:guest_access_key_pair => keypair.name)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:guest_access_key_pair]).to eq([keypair.id, keypair.name])
end
end

context '#security_groups' do
let(:sec_group) { FactoryBot.create(:security_group_openstack) }

it "sets security_groups for network_manager" do
options_with_template(:security_groups => sec_group.name)
ems.network_manager.security_groups = [sec_group]

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
expect(svc_prov.options[:security_groups]).to eq([sec_group.id])
end
end

context '#customization_templates' do
it "fails to find template" do
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([])
expect(ae_service.root["miq_provision"]).not_to receive(:set_customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by name" do
customization_template.name = template.name
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by ws_values" do
ae_service.root["miq_provision"].options[:ws_values] = {:customization_template => customization_template.name}
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end

it "finds a template by functions" do
customization_template.name = "#{svc_prov.type}_#{svc_prov.get_tags[:function]}"
allow(ae_service.root["miq_provision"]).to receive(:eligible_customization_templates).and_return([customization_template])
expect(ae_service.root["miq_provision"]).to receive(:set_customization_template).with(customization_template)

described_class.new(ae_service).instance_eval do
@mapping = true
main
end
end
end
end

it 'raises error for missing miq_provision' do
ae_service.root["miq_provision"] = nil
expect { described_class.new(ae_service).main }.to raise_error('miq_provision not specified')
end

it 'raises error for missing vm_template' do
allow(ae_service.root["miq_provision"]).to receive(:vm_template).and_return(nil)
expect { described_class.new(ae_service).main }.to raise_error('vm_template not specified')
end

it 'raises error for missing ext_management_system' do
allow_any_instance_of(MiqAeMethodService::MiqAeServiceMiqTemplate).to receive(:ext_management_system).and_return(nil)
expect { described_class.new(ae_service).main }.to raise_error('ext_management_system not specified')
end
end

0 comments on commit 49dc304

Please sign in to comment.