require 'tmpdir' require 'fileutils' require 'ruby_vcloud_sdk' module VmShepherd class VcloudManager def initialize(login_info, vdc_name, logger) @login_info = login_info @vdc_name = vdc_name @logger = logger end def deploy(vapp_template_tar_path, vapp_config) tmpdir = Dir.mktmpdir check_vapp_status(vapp_config) untar_vapp_template_tar(File.expand_path(vapp_template_tar_path), tmpdir) vapp = deploy_vapp(tmpdir, vapp_config) reconfigure_vm(vapp, vapp_config) vapp.power_on ensure FileUtils.remove_entry_secure(tmpdir, force: true) end def destroy(vapp_names, catalog) delete_vapps(vapp_names) delete_catalog(catalog) end def clean_environment(vapp_names, catalog) destroy(vapp_names, catalog) end private def check_vapp_status(vapp_config) log('Checking for existing VM') do ip = vapp_config[:ip] raise "VM exists at #{ip}" if system("ping -c 5 #{ip}") end end def untar_vapp_template_tar(vapp_template_tar_path, dir) log("Untarring #{vapp_template_tar_path}") do system_or_exit("cd #{dir} && tar xfv '#{vapp_template_tar_path}'") end end def client @client ||= VCloudSdk::Client.new( @login_info[:url], "#{@login_info[:user]}@#{@login_info[:organization]}", @login_info[:password], {}, @logger, ) end def deploy_vapp(ovf_dir, vapp_config) # setup the catalog client.delete_catalog_by_name(vapp_config[:catalog]) if client.catalog_exists?(vapp_config[:catalog]) catalog = client.create_catalog(vapp_config[:catalog]) # upload template and instantiate vapp catalog.upload_vapp_template(@vdc_name, vapp_config[:name], ovf_dir) # instantiate template network_config = VCloudSdk::NetworkConfig.new(vapp_config[:network], 'Network 1') catalog.instantiate_vapp_template( vapp_config[:name], @vdc_name, vapp_config[:name], nil, nil, network_config) rescue => e @logger.error(e.http_body) if e.respond_to?(:http_body) raise e end def reconfigure_vm(vapp, vapp_config) vm = vapp.find_vm_by_name(vapp_config[:name]) vm.product_section_properties = build_properties(vapp_config) vm end def build_properties(vapp_config) [ { 'type' => 'string', 'key' => 'gateway', 'value' => vapp_config[:gateway], 'password' => 'false', 'userConfigurable' => 'true', 'Label' => 'Default Gateway', 'Description' => 'The default gateway address for the VM network. Leave blank if DHCP is desired.' }, { 'type' => 'string', 'key' => 'DNS', 'value' => vapp_config[:dns], 'password' => 'false', 'userConfigurable' => 'true', 'Label' => 'DNS', 'Description' => 'The domain name servers for the VM (comma separated). Leave blank if DHCP is desired.', }, { 'type' => 'string', 'key' => 'ntp_servers', 'value' => vapp_config[:ntp], 'password' => 'false', 'userConfigurable' => 'true', 'Label' => 'NTP Servers', 'Description' => 'Comma-delimited list of NTP servers' }, { 'type' => 'string', 'key' => 'admin_password', 'value' => 'tempest', 'password' => 'true', 'userConfigurable' => 'true', 'Label' => 'Admin Password', 'Description' => 'This password is used to SSH into the VM. The username is "tempest".', }, { 'type' => 'string', 'key' => 'ip0', 'value' => vapp_config[:ip], 'password' => 'false', 'userConfigurable' => 'true', 'Label' => 'IP Address', 'Description' => 'The IP address for the VM. Leave blank if DHCP is desired.', }, { 'type' => 'string', 'key' => 'netmask0', 'value' => vapp_config[:netmask], 'password' => 'false', 'userConfigurable' => 'true', 'Label' => 'Netmask', 'Description' => 'The netmask for the VM network. Leave blank if DHCP is desired.' } ] end def log(title, &blk) @logger.debug "--- Begin: #{title.inspect} @ #{DateTime.now}" blk.call @logger.debug "--- End: #{title.inspect} @ #{DateTime.now}" end def system_or_exit(command) log(command) do system(command) || raise("Error executing: #{command.inspect}") end end def vdc @vdc ||= client.find_vdc_by_name(@vdc_name) end def delete_vapps(vapp_names) vapp_names.each do |vapp_name| begin vapp = vdc.find_vapp_by_name(vapp_name) vapp.power_off vapp.delete rescue VCloudSdk::ObjectNotFoundError => e @logger.debug "Could not delete vapp '#{vapp_name}': #{e.inspect}" end end end def delete_catalog(catalog) client.delete_catalog_by_name(catalog) if client.catalog_exists?(catalog) end end end