Skip to content

Instantly share code, notes, and snippets.

@nohtyp
Created January 29, 2014 21:34
Show Gist options
  • Save nohtyp/8697699 to your computer and use it in GitHub Desktop.
Save nohtyp/8697699 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
#!/opt/puppet/bin/ruby
require 'trollop'
require 'rbvmomi'
require 'rbvmomi/trollop'
################
# Parse Args #
################
SUB_CMDS = %w(on off reset suspend destroy revert list_snapshots create_snapshot remove_snapshot help)
opts = Trollop.options do
banner <<-EOS
Perform VM power operations.
Usage:
vm_manage.rb [options] cmd VM
Commands: #{SUB_CMDS * ' '}
VIM connection options:
EOS
# same as rbvmomi_connection_opts, but modifying it to hide passwords
opt :host, "host", :type => :string, :short => 'o', :default => ENV['RBVMOMI_HOST']
opt :port, "port", :type => :int, :short => :none, :default => (ENV.member?('RBVMOMI_PORT') ? ENV['RBVMOMI_PORT'].to_i : 443)
opt :"no-ssl", "don't use ssl", :short => :none, :default => (ENV['RBVMOMI_SSL'] == '0')
opt :insecure, "don't verify ssl certificate", :short => 'k', :default => (ENV['RBVMOMI_INSECURE'] == '1')
opt :user, "username", :short => 'u', :default => (ENV['RBVMOMI_USER'] || 'root')
opt :password, "password", :short => 'p', :default => ('')
opt :path, "SOAP endpoint path", :short => :none, :default => (ENV['RBVMOMI_PATH'] || '/sdk')
opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
text <<-EOS
VM location options:
EOS
rbvmomi_datacenter_opt
rbvmomi_folder_opt
text <<-EOS
Other options:
EOS
stop_on SUB_CMDS
end
# Handle extra defaults
opts[:password] = ENV['RBVMOMI_PASSWORD'] if opts[:password].empty?
cmd = ARGV.shift
cmd_parser = {}
cmd_parser['create_snapshot'] = Trollop::Parser.new do
banner <<-EOS
create_snapshot options:
EOS
opt :name, "Snapshot name", :type => :string, :short => 'n', :required => true
opt :description, "Snapshot description", :type => :string, :short => 'd'
opt :memory, "Snapshot memory", :type => :flag, :default => true
opt :quiesce, "Quiesce the guest file system", :type => :flag, :default => true
end
cmd_parser['remove_snapshot'] = Trollop::Parser.new do
banner <<-EOS
remove_snapshot options:
EOS
opt :name, "Snapshot name", :type => :string, :short => 'n', :required => true
end
cmd_opts = case cmd
when "on", "off", "reset", "suspend", "destroy", "revert", "list_snapshots"
when "create_snapshot"
p = cmd_parser['create_snapshot']
Trollop::with_standard_exception_handling p do
raise Trollop::HelpNeeded if ARGV.empty?
p.parse ARGV
end
when "remove_snapshot"
p = cmd_parser['remove_snapshot']
Trollop::with_standard_exception_handling p do
raise Trollop::HelpNeeded if ARGV.empty?
p.parse ARGV
end
when "help"
cmd = ARGV[0]
puts "Usage: vm_manage.rb [options] #{cmd} <vm_name>\n\n"
if p = cmd_parser.fetch(cmd, nil)
p.educate
end
exit
else
Trollop::die "unknown subcommand #{cmd.inspect}"
end
vm_name = ARGV[0] or Trollop.die("no VM name given")
Trollop.die("must specify host") unless opts[:host]
###############
# Functions #
###############
def get_snapshots(vm)
snapshots = []
if ! vm.snapshot
return snapshots
end
vm.snapshot.rootSnapshotList.each do |root_snapshot|
snapshots << root_snapshot
snapshots += get_child_snapshots(root_snapshot)
end
snapshots
end
def get_child_snapshots(root_snapshot)
snapshots = []
root_snapshot.childSnapshotList.each do |childSnapshot|
snapshots << childSnapshot
if child_snapshots = get_child_snapshots(childSnapshot)
snapshots += child_snapshots
end
end
snapshots
end
##########
# Main #
##########
VIM = RbVmomi::VIM
vim = VIM.connect opts
begin
dc = vim.serviceInstance.find_datacenter(opts[:datacenter]) or abort "datacenter not found"
rescue RbVmomi::VIM::NoPermission
dc = vim.serviceInstance.content.rootFolder.childEntity.grep(VIM::Datacenter).find {|x| x.name == opts[:datacenter]} or abort "datacenter not found"
end
begin
vm = dc.vmFolder.findByDnsName(vm_name) or abort "VM not found"
rescue RbVmomi::VIM::NoPermission
vm_folder = dc.vmFolder.childEntity.grep(VIM::Folder).find{|x| x.name == opts[:folder]} or abort "VM folder not found"
vm = vm_folder.childEntity.grep(VIM::VirtualMachine).find{|x| x.name == vm_name} or abort "VM not found"
end
case cmd
when 'on'
vm.PowerOnVM_Task.wait_for_completion
when 'off'
vm.PowerOffVM_Task.wait_for_completion
when 'reset'
vm.ResetVM_Task.wait_for_completion
when 'suspend'
vm.SuspendVM_Task.wait_for_completion
when 'destroy'
vm.Destroy_Task.wait_for_completion
when 'revert'
vm.RevertToCurrentSnapshot_Task.wait_for_completion
when "list_snapshots"
puts "Snapshots: " + get_snapshots(vm).map(&:name).inspect
when "create_snapshot"
vm.CreateSnapshot_Task(:name => cmd_opts[:name],
:description => cmd_opts[:description],
:memory => cmd_opts[:memory],
:quiesce => cmd_opts[:quiesce]).wait_for_completion
when "remove_snapshot"
if snapshot_tree = get_snapshots(vm).find {|x| x.name == cmd_opts[:name]}
snapshot = snapshot_tree.snapshot
snapshot.RemoveSnapshot_Task(:removeChildren => false).wait_for_completion
else
abort "No snapshot found by name #{cmd_opts[:name].inspect}"
end
else
abort "invalid command"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment