def log(level, msg, update_message=false)
$evm.log(level,"#{msg}")
@task.message = msg if @task.respond_to?('message') && update_message
end
def dump_root()
$evm.log(:info, "Begin $evm.root.attributes")
$evm.root.attributes.sort.each { |k, v| log(:info, "\t Attribute: #{k} = #{v}")}
$evm.log(:info, "End $evm.root.attributes")
$evm.log(:info, "")
end
def add_security_groups()
# ensure that the security group is set
log(:info, "Processing add_security_groups...", true)
ws_values = @task.options.fetch(:ws_values, {})
if @task.get_option(:security_groups).blank?
security_group_id = @task.get_option(:security_groups) || ws_values[:security_groups] rescue nil
security_group_id ||= @task.get_option(:security_groups_id) || ws_values[:security_groups_id] rescue nil
unless security_group_id.nil?
security_group = $evm.vmdb(:security_group).find_by_id(security_group_id)
end
if security_group
log(:info, "Using security_group: #{security_group.name} id: #{security_group.id} ems_ref: #{security_group.ems_ref}")
@task.set_option(:security_groups, [security_group.id, security_group.name])
log(:info, "Provisioning object updated {:security_group => #{@task.options[:security_groups].inspect}}")
end
end
log(:info, "Processing add_security_groups...Complete", true)
end
def add_key_pair()
# ensure that the key_pair is set
log(:info, "Processing add_key_pair...", true)
ws_values = @task.options.fetch(:ws_values, {})
if @task.get_option(:guest_access_key_pair).blank?
key_pair_id = @task.get_option(:guest_access_key_pair) || ws_values[:guest_access_key_pair] rescue nil
key_pair_id ||= @task.get_option(:guest_access_key_pair_id) || ws_values[:guest_access_key_pair_id] rescue nil
key_pair_id ||= @task.get_option(:key_pair) || ws_values[:key_pair_id] rescue nil
unless key_pair_id.nil?
key_pair = $evm.vmdb(:auth_key_pair_amazon).find_by_id(key_pair_id) || $evm.vmdb(:auth_key_pair_amazon).find_by_name(key_pair_id)
end
if key_pair
log(:info, "Using key_pair: #{key_pair.name} id: #{key_pair.id} ems_ref: #{key_pair.ems_ref}")
@task.set_option(:guest_access_key_pair, [key_pair.id, key_pair.name])
log(:info, "Provisioning object updated {:guest_access_key_pair => #{@task.options[:guest_access_key_pair].inspect}}")
end
end
log(:info, "Processing add_key_pair...Complete", true)
end
def parse_market_urn(urn)
keys = %w(publisher offer sku version)
Hash[keys.zip(urn.split(':'))]
end
def parse_storage_type(size)
if size =~ /\w[Ss]\d{1,2}|\w\d{1,2}[Ss]/
'Premium_LRS'
else
'Standard_LRS'
end
end
def set_market_image(options)
log(:info, "Processing set_market_image...", true)
ws_values = @task.get_option(:ws_values)
unless ws_values[:market_image].blank?
image_ref = parse_market_urn(ws_values[:market_image])
options[:properties][:storageProfile][:imageReference] = image_ref
options[:properties][:storageProfile][:osDisk][:managedDisk] = {
:storageAccountType => parse_storage_type(options[:properties][:hardwareProfile][:vmSize])
}
log(:info, "Clone options object updated {:imageReference => #{options[:properties][:storageProfile][:imageReference]}")
log(:info, "Clone options object updated {:managedDisk => #{options[:properties][:storageProfile][:osDisk][:managedDisk]}")
end
log(:info, "Processing set_market_image...Complete", true)
end
def set_availability_set(options)
log(:info, "Processing set_availability_set...", true)
ws_values = @task.get_option(:ws_values)
unless ws_values[:availability_set].blank?
options[:properties][:availabilitySet] = {
:id => "#{ws_values[:availability_set]}"
}
log(:info, "Clone options object updated {:availabilitySet => #{options[:properties][:availabilitySet]}")
end
log(:info, "Processing set_availability_set...Complete", true)
end
def add_nics(options)
log(:info, "Processing add_nics...", true)
nis = Azure::Armrest::Network::NetworkInterfaceService.new(@azure)
rg = $evm.vmdb(:resource_group).find_by_id(@task.get_option(:resource_group))
nic_options = {
:name => "#{@task.get_option(:vm_name)}_nic0",
:location => @provider.provider_region,
:properties => {
:ipConfigurations => [
{
:name => @task.get_option(:vm_name),
:properties => {
:subnet => { :id => $evm.vmdb(:cloud_subnet).find_by_id(@task.get_option(:cloud_subnet)).ems_ref }
}
}
]
}
}
nic = nis.create("#{@task.get_option(:vm_name)}_nic0", rg.name, nic_options)
options[:properties][:networkProfile][:networkInterfaces] << {:id => nic.id}
log(:info, "Clone options object updated {:dataDisks => #{options[:properties][:networkProfile][:networkInterfaces]}")
log(:info, "Processing add_nics...Complete", true)
end
def set_tags(options)
log(:info, "Processing set_tags...", true)
options[:tags] = {
'ApplicationName' => '',
'BuildDate' => Time.now.utc.strftime('%Y-%m-%d'),
'BusinessFunction' => '',
'BusinessOwner' => '',
'Creator' => @request.requester.email,
'Supervisor' => '',
'Manager' => ''
}
log(:info, "Processing set_tags...Complete", true)
end
def add_disks(options)
log(:info, "Processing add_disks...", true)
ws_disks = []
if @task.options.has_key?(:ws_values)
ws_values = @task.options[:ws_values]
# :ws_values=>{:add_disk1 => '20', :add_disk2=>'50'}
ws_values.each {|k,v| ws_disks[$1.to_i] = v.to_i if k.to_s =~ /add_disk(\d*)/}
ws_disks.compact!
end
if ws_disks.blank?
# @task.options=>{:add_disk1 => '20', :add_disk2=>'50'}
@task.options.each {|k,v| ws_disks[$1.to_i] = v.to_i if k.to_s =~ /add_disk(\d*)/}
ws_disks.compact!
end
unless ws_disks.blank?
lun_start_idx = 1
ws_disks.each_with_index do |size_in_gb, idx|
next if size_in_gb.zero?
options[:properties][:storageProfile][:dataDisks] << {
:name => "#{@task.get_option(:vm_name)}_dataDisk#{idx}",
:lun => lun_start_idx + idx,
:diskSizeGB => size_in_gb,
:createOption => 'empty',
:managedDisk => {
:storageAccountType => parse_storage_type(options[:properties][:hardwareProfile][:vmSize])
}
}
end
log(:info, "Clone options object updated {:dataDisks => #{options[:properties][:storageProfile][:dataDisks]}")
end
log(:info, "Processing add_disks...Complete", true)
end
def set_license_type(options)
log(:info, "Processing set_license_type...", true)
ws_values = @task.get_option(:ws_values)
if ws_values[:market_image].downcase.include? 'windows'
license_type = 'Windows_Server'
options[:properties][:licenseType] = license_type
log(:info, "Clone options object updated {:licenseType => #{options[:properties][:licenseType]}")
else
# This is here against the day we need to set Windows_Client
license_type = nil
end
log(:info, "Processing set_license_type...Complete", true)
end
def set_os_profile(options)
log(:info, 'Processing set_os_profile...', true)
ws_values = @task.get_option(:ws_values)
if ws_values[:market_image].downcase.include? 'windows'
options[:properties][:osProfile][:windowsConfiguration] = {
:provisionVMAgent => true,
:winRM => {
:listeners => [
{
:protocol => 'http'
}
]
}
}
else
options[:properties][:osProfile][:linuxConfiguration] = {
:disablePasswordAuthentication => false
}
end
log(:info, "Clone object updated {:osProfile => #{options[:properties][:osProfile]}}")
log(:info, 'Processing set_os_profile...Complete', true)
end
def generate_clone_options()
credentials = $evm.instantiate('/Configuration/MachineCredentials/Azure/Credentials/admin_account')
log(:info, 'Processing generate_clone_options...', true)
clone_options = {
:properties => {
:hardwareProfile => {
:vmSize => $evm.vmdb(:flavor).find_by_id(@task.get_option(:instance_type)).name
},
:osProfile => {
:adminUserName => @task.get_option(:root_username),
:adminPassword => credentials.decrypt('password'),
:computerName => @task.get_option(:vm_name)
},
:storageProfile => {
:osDisk => {
:name => "#{@task.get_option(:vm_name)}_osDisk",
:createOption => 'fromImage',
:caching => 'ReadWrite',
:diskSizeGB => 128
},
:dataDisks => []
},
:networkProfile => {
:networkInterfaces => []
}
}
}
set_os_profile(clone_options)
set_availability_set(clone_options)
set_market_image(clone_options)
add_nics(clone_options)
add_disks(clone_options)
log(:info, 'Processing generate_clone_options...Complete', true)
clone_options
end
begin
require 'azure-armrest'
require 'pp'
###############
# Start Method
###############
log(:info, "ManageIQ Automate Method Started", true)
dump_root()
# Get provisioning object
@task = $evm.root['miq_provision']
@request = @task.miq_request
log(:info, "Provisioning ID:<#{@task.id}> Provision Request ID:<#{@task.miq_provision_request.id}> Provision Type: <#{@task.provision_type}>")
@template = @task.vm_template
@provider = @template.ext_management_system
@azure = Azure::Armrest::Configuration.new(
:client_id => @provider.authentication_userid,
:client_key => @provider.authentication_password,
:tenant_id => @provider.uid_ems,
:subscription_id => @provider.subscription
)
clone_options = generate_clone_options
@task.set_option(:clone_options, clone_options)
# Log all of the options to the automation.log
@task.options.each { |k,v| log(:info, "Provisioning Option Key(#{k.class}): #{k.inspect} Value: #{v.inspect}") }
log(:info, "Task Options: #{@task.options.pretty_inspect}")
###############
# Exit Method
###############
log(:info, "ManageIQ Automate Method Ended", true)
exit MIQ_OK
# Set Ruby rescue behavior
rescue => err
log(:error, "[(#{err.class})#{err}]\n#{err.backtrace.join("\n")}")
@task.finished("#{err}") if @task && @task.respond_to?('finished')
exit MIQ_ABORT
end