forked from vmware-archive/rbvmomi
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CachedOvfDeployer, AdmissionControlledResourceScheduler,
LeaseTool classes and example scripts to use them. The three classes automate common deployment and management tasks in a large scale and highly automated vSphere environment, especially in Test/Dev.
- Loading branch information
administrator
committed
Aug 15, 2012
1 parent
5dc0ca3
commit 2109d27
Showing
6 changed files
with
1,088 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
#!/usr/bin/env ruby | ||
require 'trollop' | ||
require 'rbvmomi' | ||
require 'rbvmomi/trollop' | ||
require 'rbvmomi/utils/deploy' | ||
require 'rbvmomi/utils/admission_control' | ||
require 'yaml' | ||
|
||
VIM = RbVmomi::VIM | ||
|
||
opts = Trollop.options do | ||
banner <<-EOS | ||
Deploy an OVF to a cluster, using a cached template if available. | ||
Usage: | ||
cached_ovf_deploy.rb [options] <vmname> <ovfurl> | ||
VIM connection options: | ||
EOS | ||
|
||
rbvmomi_connection_opts | ||
|
||
text <<-EOS | ||
VM location options: | ||
EOS | ||
|
||
rbvmomi_datacenter_opt | ||
rbvmomi_datastore_opt | ||
|
||
text <<-EOS | ||
Other options: | ||
EOS | ||
|
||
opt :template_name, "Name to give to the (cached) template", :type => :string | ||
opt :template_path, "Path where templates are stored", :default => 'templates', :type => :string | ||
opt :computer_path, "Path to the cluster to deploy into", :type => :string | ||
opt :network, "Name of the network to attach template to", :type => :string | ||
opt :vm_folder_path, "Path to VM folder to deploy VM into", :type => :string | ||
opt :lease, "Lease in days", :type => :int, :default => 3 | ||
end | ||
|
||
Trollop.die("must specify host") unless opts[:host] | ||
Trollop.die("no cluster path given") unless opts[:computer_path] | ||
template_folder_path = opts[:template_path] | ||
template_name = opts[:template_name] or Trollop.die("no template name given") | ||
vm_name = ARGV[0] or Trollop.die("no VM name given") | ||
ovf_url = ARGV[1] or Trollop.die("No OVF URL given") | ||
|
||
vim = VIM.connect opts | ||
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found" | ||
|
||
root_vm_folder = dc.vmFolder | ||
vm_folder = root_vm_folder | ||
if opts[:vm_folder_path] | ||
vm_folder = root_vm_folder.traverse(opts[:vm_folder_path], VIM::Folder) | ||
end | ||
template_folder = root_vm_folder.traverse!(template_folder_path, VIM::Folder) | ||
|
||
scheduler = AdmissionControlledResourceScheduler.new( | ||
vim, | ||
:datacenter => dc, | ||
:computer_names => [opts[:computer_path]], | ||
:vm_folder => vm_folder, | ||
:rp_path => '/', | ||
:datastore_paths => [opts[:datastore]], | ||
:max_vms_per_pod => nil, # No limits | ||
:min_ds_free => nil, # No limits | ||
) | ||
scheduler.make_placement_decision | ||
|
||
datastore = scheduler.datastore | ||
computer = scheduler.pick_computer | ||
# XXX: Do this properly | ||
if opts[:network] | ||
network = computer.network.find{|x| x.name == opts[:network]} | ||
else | ||
network = computer.network[0] | ||
end | ||
|
||
lease_tool = LeaseTool.new | ||
lease = opts[:lease] * 24 * 60 * 60 | ||
deployer = CachedOvfDeployer.new( | ||
vim, network, computer, template_folder, vm_folder, datastore | ||
) | ||
template = deployer.lookup_template template_name | ||
|
||
if !template | ||
puts "#{Time.now}: Uploading/Preparing OVF template ..." | ||
|
||
template = deployer.upload_ovf_as_template( | ||
ovf_url, template_name, | ||
:run_without_interruptions => true, | ||
:config => lease_tool.set_lease_in_vm_config({}, lease) | ||
) | ||
end | ||
|
||
puts "#{Time.now}: Cloning template ..." | ||
config = { | ||
:numCPUs => opts[:cpus], | ||
:memoryMB => opts[:memory], | ||
} | ||
config = lease_tool.set_lease_in_vm_config(config, lease) | ||
vm = deployer.linked_clone template, vm_name, config | ||
|
||
puts "#{Time.now}: Powering On VM ..." | ||
# XXX: Add a retrying version? | ||
vm.PowerOnVM_Task.wait_for_completion | ||
|
||
puts "#{Time.now}: Waiting for VM to be up ..." | ||
ip = nil | ||
while !(ip = vm.guest_ip) | ||
sleep 5 | ||
end | ||
|
||
puts "#{Time.now}: VM got IP: #{ip}" | ||
|
||
puts "#{Time.now}: Done" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#!/usr/bin/env ruby | ||
require 'trollop' | ||
require 'rbvmomi' | ||
require 'rbvmomi/trollop' | ||
require 'rbvmomi/utils/leases' | ||
require 'yaml' | ||
|
||
VIM = RbVmomi::VIM | ||
CMDS = ['set_lease_on_leaseless_vms', 'show_expired_vms', | ||
'show_soon_expired_vms', 'kill_expired_vms'] | ||
|
||
opts = Trollop.options do | ||
banner <<-EOS | ||
Tool for managing leases on VMs where leases are stored in YAML on VM annotations. | ||
Usage: | ||
lease_tool.rb [options] <cmd> | ||
Commands: #{CMDS * ' '} | ||
VIM connection options: | ||
EOS | ||
|
||
rbvmomi_connection_opts | ||
|
||
text <<-EOS | ||
VM location options: | ||
EOS | ||
|
||
rbvmomi_datacenter_opt | ||
|
||
text <<-EOS | ||
Other options: | ||
EOS | ||
|
||
opt :vm_folder_path, "Path to VM folder to deploy VM into", :type => :string | ||
opt :force, "Really perform VMs. Used with kill_expired_vms" | ||
|
||
stop_on CMDS | ||
end | ||
|
||
Trollop.die("must specify host") unless opts[:host] | ||
cmd = ARGV[0] or Trollop.die("no command given") | ||
Trollop.die("no vm folder path given") unless opts[:vm_folder_path] | ||
|
||
vim = VIM.connect opts | ||
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found" | ||
|
||
root_vm_folder = dc.vmFolder | ||
vm_folder = root_vm_folder.traverse(opts[:vm_folder_path], VIM::Folder) | ||
|
||
lease_tool = LeaseTool.new | ||
vms_props_list = (['runtime.powerState'] + lease_tool.vms_props_list).uniq | ||
inventory = vm_folder.inventory_flat('VirtualMachine' => vms_props_list) | ||
inventory = inventory.select{|obj, props| obj.is_a?(VIM::VirtualMachine)} | ||
case cmd | ||
when 'set_lease_on_leaseless_vms' | ||
lease_tool.set_lease_on_leaseless_vms( | ||
inventory.keys, inventory, | ||
:lease_minutes => 3 * 24 * 60 * 60 # 3 days | ||
) | ||
when 'show_expired_vms' | ||
vms = lease_tool.filter_expired_vms inventory.keys, inventory | ||
vms.each do |vm, time_to_expiration| | ||
puts "VM '#{inventory[vm]['name']}' is expired" | ||
end | ||
when 'kill_expired_vms' | ||
vms = lease_tool.filter_expired_vms inventory.keys, inventory | ||
vms.each do |vm, time_to_expiration| | ||
puts "VM '#{inventory[vm]['name']}' is expired" | ||
if !opts[:force] | ||
puts "NOT killing VM '#{inventory[vm]['name']}' because --force not set" | ||
else | ||
puts "Killing expired VM '#{inventory[vm]['name']}'" | ||
# Destroying VMs is very stressful for vCenter, and we aren't in a rush | ||
# so do one VM at a time | ||
if inventory[vm]['runtime.powerState'] == 'poweredOn' | ||
vm.PowerOffVM_Task.wait_for_completion | ||
end | ||
vm.Destroy_Task.wait_for_completion | ||
end | ||
end | ||
when 'show_soon_expired_vms' | ||
vms = lease_tool.filter_expired_vms( | ||
inventory.keys, inventory, | ||
:time_delta => 3.5 * 24 * 60 * 60, # 3.5 days | ||
) | ||
# We could send the user emails here, but for this example, just print the | ||
# VMs that will expire within the next 3.5 days | ||
vms.each do |vm, time_to_expiration| | ||
if time_to_expiration > 0 | ||
hours_to_expiration = time_to_expiration / (60.0 * 60.0) | ||
puts "VM '%s' expires in %.2fh" % [inventory[vm]['name'], hours_to_expiration] | ||
else | ||
puts "VM '#{inventory[vm]['name']}' is expired" | ||
end | ||
end | ||
else | ||
abort "invalid command" | ||
end |
Oops, something went wrong.