Skip to content

Commit

Permalink
Merge pull request #645 from pkomanek/vmware_preprovision_clone_to_te…
Browse files Browse the repository at this point in the history
…mplate_method_refactoring

Refactor vmware_preprovision_clone_to_template method for VM Provisioning.
  • Loading branch information
tinaafitz authored Aug 17, 2020
2 parents 2c82071 + 085856f commit 2a1b7b7
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,115 @@
# 2. Target VC Folder
# 3. Tag Inheritance

set_folder = true
set_notes = true
set_tags = true

# Get provisioning object
prov = $evm.root["miq_provision"]

# Get Provision Type
prov_type = prov.provision_type
$evm.log("info", "Provision Type: <#{prov_type}>")

# Get template
template = prov.vm_template

# Get OS Type from the template platform
product = template.operating_system['product_name'] rescue ''
$evm.log("info", "Source Product: <#{product}>")

if set_notes
###################################
# Set the VM Description and VM Annotations as follows:
# The example would allow user input in provisioning dialog "vm_description"
# to be added to the VM notes
###################################
# Stamp VM with custom description
unless prov.get_option(:vm_description).nil?
vmdescription = prov.get_option(:vm_description)
prov.set_option(:vm_description, vmdescription)
$evm.log("info", "Provisioning object <:vmdescription> updated with <#{vmdescription}>")
end

# Setup VM Annotations
vm_notes = "Owner: #{prov.get_option(:owner_first_name)} #{prov.get_option(:owner_last_name)}"
vm_notes += "\nEmail: #{prov.get_option(:owner_email)}"
vm_notes += "\nSource Template: #{prov.vm_template.name}"
vm_notes += "\nCustom Description: #{vmdescription}" unless vmdescription.nil?
prov.set_vm_notes(vm_notes)
$evm.log("info", "Provisioning object <:vm_notes> updated with <#{vm_notes}>")
end
module ManageIQ
module Automate
module Infrastructure
module VM
module Provisioning
module StateMachines
module Methods
class VmwarePreprovisionCloneToTemplate
def initialize(handle = $evm)
@handle = handle
@folder = true
@notes = true
@tags = true
end

if set_folder
###################################
# Drop the VM in the targeted folder if no folder was chosen in the dialog
# The VC folder must exist for the VM to be placed correctly,
# Otherwise the VM will be placed at the Data Center level.
###################################
datacenter = template.v_owning_datacenter

if prov.get_option(:placement_folder_name).nil?
prov.set_folder(datacenter)
$evm.log("info", "Provisioning object <:placement_folder_name> updated with <#{prov.options[:placement_folder_name].inspect}>")
else
$evm.log("info", "Placing VM in folder: <#{prov.get_option(:placement_folder_name)}>")
end
end
def main
@handle.log("info", "Provision Type: <#{prov_type}>")
@handle.log("info", "Source Product: <#{product}>")

set_notes if @notes
set_folder if @folder
set_tags if @tags
end

private

def set_notes
vmdescription = prov.get_option(:vm_description)

# Setup VM Annotations
vm_notes = "Owner: #{prov.get_option(:owner_first_name)} #{prov.get_option(:owner_last_name)}"
vm_notes += "\nEmail: #{prov.get_option(:owner_email)}"
vm_notes += "\nSource Template: #{prov.vm_template.name}"
vm_notes += "\nCustom Description: #{vmdescription}" unless vmdescription.nil?
prov.set_vm_notes(vm_notes)
@handle.log("info", "Provisioning object <:vm_notes> updated with <#{vm_notes}>")
end

def set_folder
###################################
# Drop the VM in the targeted folder if no folder was chosen in the dialog
# The VC folder must exist for the VM to be placed correctly,
# Otherwise the VM will be placed at the Data Center level.
###################################
datacenter = template.v_owning_datacenter

if prov.get_option(:placement_folder_name).nil?
prov.set_folder(datacenter)
@handle.log("info", "Provisioning object <:placement_folder_name> updated with <#{prov.options[:placement_folder_name].inspect}>")
else
@handle.log("info", "Placing VM in folder: <#{prov.get_option(:placement_folder_name)}>")
end
end

if set_tags
###################################
#
# Inherit parent VM's tags and apply
# them to the published template
#
###################################

# List of tag categories to carry over
tag_categories_to_migrate = %w(environment department location function)

# Assign variables
prov_tags = prov.get_tags
$evm.log("info", "Inspecting Provisioning Tags: <#{prov_tags.inspect}>")
template_tags = template.tags
$evm.log("info", "Inspecting Template Tags: <#{template_tags.inspect}>")

# Loop through each source tag for matching categories
template_tags.each do |cat_tagname|
category, tag_value = cat_tagname.split('/')
$evm.log("info", "Processing Tag Category: <#{category}> Value: <#{tag_value}>")
next unless tag_categories_to_migrate.include?(category)
prov.add_tag(category, tag_value)
$evm.log("info", "Updating Provisioning Tags with Category: <#{category}> Value: <#{tag_value}>")
def set_tags
###################################
#
# Inherit parent VM's tags and apply
# them to the published template
#
###################################

# List of tag categories to carry over
tag_categories_to_migrate = %w[environment department location function]

# Assign variables
prov_tags = prov.get_tags
@handle.log("info", "Inspecting Provisioning Tags: <#{prov_tags.inspect}>")
template_tags = template.tags
@handle.log("info", "Inspecting Template Tags: <#{template_tags.inspect}>")

# Loop through each source tag for matching categories
template_tags.each do |cat_tagname|
category, tag_value = cat_tagname.split('/')
@handle.log("info", "Processing Tag Category: <#{category}> Value: <#{tag_value}>")
next unless tag_categories_to_migrate.include?(category)

prov.add_tag(category, tag_value)
@handle.log("info", "Updating Provisioning Tags with Category: <#{category}> Value: <#{tag_value}>")
end
end

def prov
@prov ||= @handle.root["miq_provision"].tap do |req|
raise 'miq_provision not specified' if req.nil?
end
end

def prov_type
@prov_type ||= prov.provision_type
end

def template
@template ||= prov.vm_template.tap do |req|
raise 'vm_template not specified' if req.nil?
end
end

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

ManageIQ::Automate::Infrastructure::VM::Provisioning::StateMachines::Methods::VmwarePreprovisionCloneToTemplate.new.main
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
require_domain_file

describe ManageIQ::Automate::Infrastructure::VM::Provisioning::StateMachines::Methods::VmwarePreprovisionCloneToTemplate do
let(:prov_type) { :miq_provision_redhat }
let(:ems) { FactoryBot.create(:ems_redhat_with_authentication) }
let(:os) { FactoryBot.create(:operating_system, :product_name => 'Fedora') }
let(:template) { FactoryBot.create(:miq_template, :ext_management_system => ems, :operating_system => os) }
let(:prov_req) { FactoryBot.create(:miq_provision_request, :options => prov_opt) }
let(:prov) { FactoryBot.create(prov_type, :miq_provision_request => prov_req, :options => prov_opt) }
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(:category) { FactoryBot.create(:classification_department_with_tags) }
let(:prov_opt) do
{
:src_vm_id => template.id,
:owner_first_name => 'owner_first_name',
:owner_last_name => 'owner_last_name',
:owner_email => 'owner_email@owner_email.com',
:vm_description => 'vm_description'
}
end
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

def build_notes
res = "Owner: #{prov_opt[:owner_first_name]} #{prov_opt[:owner_last_name]}\n"\
"Email: #{prov_opt[:owner_email]}\n"\
"Source Template: #{template.name}"

if ae_service.root["miq_provision"].get_option(:vm_description)
res += "\nCustom Description: #{prov_opt[:vm_description]}"
end

res
end

def validate_notes
described_class.new(ae_service).instance_eval do
@set_notes = true
main
end

expect(ae_service.root["miq_provision"].get_option(:vm_notes)).to eq(build_notes)
end

it 'sets the notes with description' do
validate_notes
end

it 'sets the notes without description' do
prov_opt[:vm_description] = nil
validate_notes
end

it 'sets the folder' do
v_owning_datacenter = "v_owning_datacenter"
svc_template = MiqAeMethodService::MiqAeServiceMiqTemplate.find(template.id)
allow(ae_service.root["miq_provision"]).to receive(:vm_template).and_return(svc_template)
allow(svc_template).to receive(:v_owning_datacenter).and_return(v_owning_datacenter)
expect(ae_service.root["miq_provision"]).to receive(:set_folder).with(v_owning_datacenter)
described_class.new(ae_service).main
end

it 'skips folder set' do
prov_opt[:placement_folder_name] = 'placement_folder_name'
expect(ae_service.root["miq_provision"]).not_to receive(:set_folder)
described_class.new(ae_service).main
end

it 'sets the tags' do
tag = category.children.first
svc_template = MiqAeMethodService::MiqAeServiceMiqTemplate.find(template.id)
allow(ae_service.root["miq_provision"]).to receive(:vm_template).and_return(svc_template)
allow(svc_template).to receive(:tags).and_return(["#{category.name}/#{tag.name}"])

expect(ae_service.root["miq_provision"]).to receive(:add_tag).with(category.name, tag.name)
described_class.new(ae_service).main
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
end

0 comments on commit 2a1b7b7

Please sign in to comment.