bin/esx in esx-0.4.1 vs bin/esx in esx-0.4.2
- old
+ new
@@ -3,16 +3,18 @@
require 'esx'
require 'terminal-table/import'
require 'clamp'
require 'net/http'
require 'fileutils'
+require 'json'
class BaseCommand < Clamp::Command
parameter "ADDRESS", "ESX host address"
option "--user", "USER", "Username", :default => "root"
option "--password", "PASSWORD", "Password", :default => ""
option "--debug", :flag, "Print debugging info"
+ option "--free-license", :flag, "If your Hypervisor have a free license", :default => false
end
class InfoCommand < BaseCommand
parameter "ADDRESS", "ESX host address"
@@ -20,11 +22,11 @@
option "--password", "PASSWORD", "Password", :default => ""
def execute
begin
- host = ESX::Host.connect(address, user, password)
+ host = ESX::Host.connect(address, user, password, true, {:free_license=>free_license?})
puts
name = host.name.upcase
puts "*" * name.size
puts name
@@ -76,13 +78,13 @@
parameter "ADDRESS", "ESX host address"
option "--vm-name", "VM_NAME", "Virtual Machine to destroy"
def execute
begin
- host = ESX::Host.connect address, user, password
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
host.virtual_machines.each do |vm|
- if vm.name == vm_name
+ if vm.name == vm_name
print "Destroying Virtual Machine '#{vm.name}'..."
vm.power_off unless vm.power_state == 'poweredOff'
vm.destroy
puts "Done."
end
@@ -103,11 +105,11 @@
parameter "ADDRESS", "ESX host address"
option "--vm-name", "VM_NAME", "Virtual Machine to Power Off"
def execute
begin
- host = ESX::Host.connect address, user, password
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
host.virtual_machines.each do |vm|
if vm.name == vm_name and vm.power_state == 'poweredOn'
print "Powering Off VM #{vm_name}... "
vm.power_off
puts "Done."
@@ -129,11 +131,11 @@
parameter "ADDRESS", "ESX host address"
option "--vm-name", "VM_NAME", "Virtual Machine to Power On"
def execute
begin
- host = ESX::Host.connect address, user, password
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
host.virtual_machines.each do |vm|
if vm.name == vm_name and vm.power_state != 'poweredOn'
print "Powering On VM #{vm_name}... "
vm.power_on
puts "Done."
@@ -148,11 +150,140 @@
end
end
end
+class DeleteNICCommand < BaseCommand
+ parameter "ADDRESS", "ESX host address"
+ option "--vm-name", "VM_NAME", "Virtual Machine"
+ option "--mac-address", "MAC_ADDRESS", "MAC address to remove"
+ option "--force", :flag, "Force reboot"
+ def execute
+ begin
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
+
+ vm = host.virtual_machines.find{|x| x.name.eql? vm_name}
+ if vm
+ hd=vm.vm_object.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).find{|nic| nic.props[:macAddress].eql?mac_address}
+ if hd
+ spec = RbVmomi::VIM.VirtualMachineConfigSpec({:deviceChange => [{:operation => :remove,:device => hd}]})
+ unless free_license?
+ vm.vm_object.ReconfigVM_Task(:spec => spec).wait_for_completion
+ else
+ #TODO: This is horrible! Find a way to reconfigure the VM without downtime
+ key = hd.key
+ vmx_file = vm.vm_object.config.files.vmPathName.gsub("[","/vmfs/volumes/").gsub(/]\s*/,"/")
+ puts "VMX file: #{vmx_file}" if debug?
+ eth_name = host.remote_command("fgrep #{mac_address} #{vmx_file} | cut -d. -f1")
+ if eth_name
+ eth_name.strip!
+ puts "#{eth_name} found!" if debug?
+ host.remote_command "sed -i -e '/.*#{eth_name}\..*/d' #{vmx_file}"
+ end
+ if force?
+ vm.power_off
+ host.remote_command "vim-cmd vmsvc/unregister #{vm.vmid}"
+ id = host.remote_command "vim-cmd solo/registervm #{vmx_file}"
+ host.remote_command "vim-cmd vmsvc/power.on #{id}"
+ else
+ puts "You have to power-off the vm unregister it and register it agin."
+ end
+ end
+ puts "Done."
+ else
+ puts "No NIC with #{mac_address} mac address was found!"
+ end
+ else
+ puts "No Virtual Machine found!"
+ end
+ rescue Exception => e
+ $stderr.puts "Can't connect to the host #{address}."
+ if debug?
+ $stderr.puts e.message
+ end
+ exit 1
+ end
+ end
+end
+
+
+class AddNICCommand < BaseCommand
+ parameter "ADDRESS", "ESX host address"
+ option "--vm-name", "VM_NAME", "Virtual Machine"
+ option "--mac-address", "MAC_ADDRESS", "MAC address to add", :default => nil
+ option "--network", "NETWORK", "Network name for new interface"
+ option "--force", :flag, "Force reboot"
+
+ def execute
+ begin
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
+ vm = host.virtual_machines.find{|x| x.name.eql? vm_name}
+ if vm
+ hd = vm.vm_object.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).find{|nic| nic.props[:macAddress].eql?mac_address}
+ s = vm.vm_object.config.hardware.device.grep(RbVmomi::VIM::VirtualEthernetCard).size
+ if hd
+ puts "NIC with #{mac_address} mac address already exists!"
+ else
+ if mac_address
+ nics = {:macAddress => mac_address, :addressType => 'manual'}
+ else
+ nics = {:addressType => 'generated'}
+ end
+ spec = RbVmomi::VIM.VirtualMachineConfigSpec({:deviceChange => [{
+ :operation => :add,
+ :device => RbVmomi::VIM.VirtualE1000({
+ :key => s,
+ :deviceInfo => {
+ :label => "Network Adapter #{s}",
+ :summary => network || 'VM Network'
+ },
+ :backing => RbVmomi::VIM.VirtualEthernetCardNetworkBackingInfo(
+ :deviceName => network || 'VM Network'
+ )
+ }.merge(nics))
+ }]})
+ unless free_license?
+ vm.vm_object.ReconfigVM_Task(:spec => spec).wait_for_completion
+ else
+ #TODO: This is horrible! Find a way to reconfigure the VM without downtime
+ vmx_file = vm.vm_object.config.files.vmPathName.gsub("[","/vmfs/volumes/").gsub(/]\s*/,"/")
+ puts "VMX file: #{vmx_file}" if debug?
+ host.remote_command " echo 'ethernet#{s}.present = \"true\"' >> #{vmx_file}"
+ host.remote_command " echo 'ethernet#{s}.virtualDev = \"e1000\"' >> #{vmx_file}"
+ host.remote_command " echo 'ethernet#{s}.wakeOnPcktRcv = \"false\"' >> #{vmx_file}"
+ host.remote_command " echo 'ethernet#{s}.networkName = \"#{network || 'VM Network'}\"' >> #{vmx_file}"
+ if mac_address
+ host.remote_command " echo 'ethernet#{s}.addressType = \"static\"' >> #{vmx_file}"
+ host.remote_command " echo 'ethernet#{s}.address = \"#{mac_address}\"' >> #{vmx_file}"
+ else
+ host.remote_command " echo 'ethernet#{s}.addressType = \"generated\"' >> #{vmx_file}"
+ end
+ if force?
+ vm.power_off
+ host.remote_command "vim-cmd vmsvc/unregister #{vm.vmid}"
+ id = host.remote_command "vim-cmd solo/registervm #{vmx_file}"
+ host.remote_command "vim-cmd vmsvc/power.on #{id}"
+ else
+ puts "You have to power-off the vm unregister it and register it agin."
+ end
+ end
+ puts "Done."
+ end
+ else
+ puts "No Virtual Machine found!"
+ end
+ rescue Exception => e
+ $stderr.puts "Can't connect to the host #{address}."
+ if debug?
+ $stderr.puts e.message
+ end
+ exit 1
+ end
+ end
+end
+
class CreateVMCommand < BaseCommand
parameter "ADDRESS", "ESX host address"
option "--disk-file", "DISK_FILE", "VMDK file to import", :attribute_name => :disk_file
option "--disk-size", "DISK_SIZE", "VM Disk size in MB", :attribute_name => :disk_size, :default => 8192
@@ -165,11 +296,11 @@
option "--datastore", "DATASTORE", "Datastore used to host the disk", :default => "datastore1"
option "--poweron", :flag, "Power on the VM after creation"
def execute
begin
- host = ESX::Host.connect address, user, password
+ host = ESX::Host.connect address, user, password, true, {:free_license=>free_license?}
rescue Exception => e
$stderr.puts "Can't connect to the host #{address}."
if debug?
$stderr.puts e.message
end
@@ -179,11 +310,11 @@
$stderr.puts "Both --disk-file and --disk-size specified. --disk-size will be ignored."
end
downloaded_file = nil
if disk_file.nil?
# if --disk-file nil? create the VM without disk
- vm = host.create_vm :vm_name => name,
+ vm = host.create_vm :vm_name => name,
:datastore => datastore, :disk_type => :flat, :memory => memory,
:disk_size => disk_size,
:guest_id => guest_id, :nics => [{:mac_address => mac_address, :network => vm_network}]
else
df = disk_file.dup
@@ -194,11 +325,11 @@
puts "Downloading file... (#{tmpfile})"
download! downloaded_file, tmpfile
puts
df = tmpfile
rescue Exception => e
- FileUtils.rm_f(tmpfile)
+ FileUtils.rm_f(tmpfile)
$stderr.puts "Error downloading file from #{downloaded_file}."
$stderr.puts e.message if debug?
exit 1
end
end
@@ -218,24 +349,24 @@
exit 1
end
if not downloaded_file.nil?
puts "Deleting tmp file #{df}" if debug?
- FileUtils.rm_f(df)
+ FileUtils.rm_f(df)
end
- vm = host.create_vm :vm_name => name,
- :disk_file => "#{name}/#{name}.vmdk",
+ vm = host.create_vm :vm_name => name,
+ :disk_file => "#{name}/#{name}.vmdk",
:datastore => datastore, :disk_type => :flat, :memory => memory,
:guest_id => guest_id, :nics => [{mac_address => mac_address, :network => vm_network}]
end
if poweron?
vm.power_on
end
end
def report_progress(progress, total, show_parts=true)
- line_reset = "\r\e[0K"
+ line_reset = "\r\e[0K"
percent = (progress.to_f / total.to_f) * 100
line = "Progress: #{percent.to_i}%"
line << " (#{progress} / #{total})" if show_parts
line = "#{line_reset}#{line}"
$stdout.sync = true
@@ -282,14 +413,17 @@
end
end
class DefaultCommand < Clamp::Command
- default_subcommand "info", "Display host info", InfoCommand
+ self.default_subcommand="info"
+ subcommand "info", "Display host info", InfoCommand
subcommand "create-vm", "Create a VM", CreateVMCommand
subcommand "poweron-vm", "Power On a VM", PowerOnVMCommand
subcommand "poweroff-vm", "Power Off a VM", PowerOffVMCommand
subcommand "destroy-vm", "Destroy VM", DestroyVMCommand
+ subcommand "add-nic", "Add NIC to a VM", AddNICCommand
+ subcommand "delete-nic", "Delete NIC from a VM", DeleteNICCommand
end
begin
DefaultCommand.run
rescue Exception => e