knife-vsphere 0.9.0 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/chef/knife/base_vsphere_command.rb +304 -0
- data/lib/chef/knife/vsphere_customization_list.rb +29 -29
- data/lib/chef/knife/vsphere_datastore_list.rb +59 -58
- data/lib/chef/knife/vsphere_pool_list.rb +45 -45
- data/lib/chef/knife/vsphere_template_list.rb +32 -32
- data/lib/chef/knife/vsphere_vlan_list.rb +38 -37
- data/lib/chef/knife/vsphere_vm_clone.rb +414 -414
- data/lib/chef/knife/vsphere_vm_config.rb +48 -0
- data/lib/chef/knife/vsphere_vm_delete.rb +39 -39
- data/lib/chef/knife/vsphere_vm_execute.rb +67 -68
- data/lib/chef/knife/vsphere_vm_list.rb +46 -46
- data/lib/chef/knife/vsphere_vm_query.rb +3 -4
- data/lib/chef/knife/vsphere_vm_snapshot.rb +56 -56
- data/lib/chef/knife/vsphere_vm_state.rb +46 -46
- data/lib/chef/knife/vsphere_vm_vmdk_add.rb +67 -67
- data/lib/knife-vsphere/version.rb +1 -1
- metadata +4 -3
- data/lib/chef/knife/BaseVsphereCommand.rb +0 -304
@@ -0,0 +1,48 @@
|
|
1
|
+
# Author:: Brian Dupras (<bdupras@rallydev.com>)
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'chef/knife'
|
5
|
+
require 'chef/knife/base_vsphere_command'
|
6
|
+
require 'rbvmomi'
|
7
|
+
require 'netaddr'
|
8
|
+
|
9
|
+
class Chef::Knife::VsphereVmConfig < Chef::Knife::BaseVsphereCommand
|
10
|
+
banner "knife vsphere vm config VMNAME PROPERTY VALUE. See \"http://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.ConfigSpec.html\" for allowed ATTRIBUTE values (any property of type xs:string is supported)."
|
11
|
+
|
12
|
+
get_common_options
|
13
|
+
|
14
|
+
def run
|
15
|
+
$stdout.sync = true
|
16
|
+
vmname = @name_args[0]
|
17
|
+
if vmname.nil?
|
18
|
+
show_usage
|
19
|
+
fatal_exit("You must specify a virtual machine name")
|
20
|
+
end
|
21
|
+
|
22
|
+
property_name = @name_args[1]
|
23
|
+
if property_name.nil?
|
24
|
+
show_usage
|
25
|
+
fatal_exit("You must specify a PROPERTY name (e.g. annotation)")
|
26
|
+
end
|
27
|
+
property_name = property_name.to_sym
|
28
|
+
|
29
|
+
property_value = @name_args[2]
|
30
|
+
if property_value.nil?
|
31
|
+
show_usage
|
32
|
+
fatal_exit("You must specify a PROPERTY value")
|
33
|
+
end
|
34
|
+
|
35
|
+
vim = get_vim_connection
|
36
|
+
|
37
|
+
dcname = get_config(:vsphere_dc)
|
38
|
+
dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
|
39
|
+
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
40
|
+
|
41
|
+
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
42
|
+
abort "VM #{vmname} not found"
|
43
|
+
|
44
|
+
properties = {}
|
45
|
+
properties[property_name] = property_value
|
46
|
+
vm.ReconfigVM_Task(:spec => RbVmomi::VIM.VirtualMachineConfigSpec(properties)).wait_for_completion
|
47
|
+
end
|
48
|
+
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
require 'chef/knife'
|
7
|
-
require 'chef/knife/
|
7
|
+
require 'chef/knife/base_vsphere_command'
|
8
8
|
require 'rbvmomi'
|
9
9
|
|
10
10
|
# These two are needed for the '--purge' deletion case
|
@@ -14,53 +14,53 @@ require 'chef/api_client'
|
|
14
14
|
# Delete a virtual machine from vCenter
|
15
15
|
class Chef::Knife::VsphereVmDelete < Chef::Knife::BaseVsphereCommand
|
16
16
|
|
17
|
-
|
17
|
+
banner "knife vsphere vm delete VMNAME"
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
option :purge,
|
20
|
+
:short => "-P",
|
21
|
+
:long => "--purge",
|
22
|
+
:boolean => true,
|
23
|
+
:description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the VM itself."
|
24
24
|
|
25
|
-
|
25
|
+
get_common_options
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
27
|
+
# Extracted from Chef::Knife.delete_object, because it has a
|
28
|
+
# confirmation step built in... By specifying the '--purge'
|
29
|
+
# flag (and also explicitly confirming the server destruction!)
|
30
|
+
# the user is already making their intent known. It is not
|
31
|
+
# necessary to make them confirm two more times.
|
32
|
+
def destroy_item(itemClass, name, type_name)
|
33
|
+
object = itemClass.load(name)
|
34
|
+
object.destroy
|
35
|
+
puts "Deleted #{type_name} #{name}"
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
38
|
+
def run
|
39
|
+
$stdout.sync = true
|
40
40
|
|
41
|
-
|
41
|
+
vmname = @name_args[0]
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
if vmname.nil?
|
44
|
+
show_usage
|
45
|
+
fatal_exit("You must specify a virtual machine name")
|
46
|
+
end
|
47
47
|
|
48
|
-
|
48
|
+
vim = get_vim_connection
|
49
49
|
|
50
|
-
|
50
|
+
baseFolder = find_folder(get_config(:folder));
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
vm = find_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine, vmname) or
|
53
|
+
fatal_exit("VM #{vmname} not found")
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
vm.PowerOffVM_Task.wait_for_completion unless vm.runtime.powerState == "poweredOff"
|
56
|
+
vm.Destroy_Task
|
57
|
+
puts "Deleted virtual machine #{vmname}"
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
59
|
+
if config[:purge]
|
60
|
+
destroy_item(Chef::Node, vmname, "node")
|
61
|
+
destroy_item(Chef::ApiClient, vmname, "client")
|
62
|
+
else
|
63
|
+
puts "Corresponding node and client for the #{vmname} server were not deleted and remain registered with the Chef Server"
|
64
|
+
end
|
65
|
+
end
|
66
66
|
end
|
@@ -1,68 +1,67 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
require 'chef/knife'
|
6
|
-
require '
|
7
|
-
require '
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
vmname
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
command
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
args
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
:
|
60
|
-
|
61
|
-
|
62
|
-
:
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
end
|
1
|
+
# Author:: Ian Delahorne (<ian@delahorne.com>)
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'chef/knife'
|
5
|
+
require 'chef/knife/base_vsphere_command'
|
6
|
+
require 'rbvmomi'
|
7
|
+
require 'netaddr'
|
8
|
+
|
9
|
+
class Chef::Knife::VsphereVmExecute < Chef::Knife::BaseVsphereCommand
|
10
|
+
banner "knife vsphere vm execute VMNAME COMMAND ARGS"
|
11
|
+
|
12
|
+
option :exec_user,
|
13
|
+
:long => "--exec-user USER",
|
14
|
+
:description => "User to execute as",
|
15
|
+
:required => true
|
16
|
+
|
17
|
+
option :exec_passwd,
|
18
|
+
:long => "--exec-passwd PASSWORD",
|
19
|
+
:description => "Password for execute user",
|
20
|
+
:required => true
|
21
|
+
|
22
|
+
option :exec_dir,
|
23
|
+
:long => "--exec-dir DIRECTORY",
|
24
|
+
:description => "Working directory to execute in"
|
25
|
+
|
26
|
+
get_common_options
|
27
|
+
|
28
|
+
def run
|
29
|
+
$stdout.sync = true
|
30
|
+
vmname = @name_args[0]
|
31
|
+
if vmname.nil?
|
32
|
+
show_usage
|
33
|
+
fatal_exit("You must specify a virtual machine name")
|
34
|
+
end
|
35
|
+
command = @name_args[1]
|
36
|
+
if command.nil?
|
37
|
+
show_usage
|
38
|
+
fatal_exit("You must specify a command to execute")
|
39
|
+
end
|
40
|
+
|
41
|
+
args = @name_args[2]
|
42
|
+
if args.nil?
|
43
|
+
args = ""
|
44
|
+
end
|
45
|
+
|
46
|
+
vim = get_vim_connection
|
47
|
+
|
48
|
+
dcname = get_config(:vsphere_dc)
|
49
|
+
dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
|
50
|
+
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
51
|
+
|
52
|
+
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
53
|
+
abort "VM #{vmname} not found"
|
54
|
+
|
55
|
+
gom = vim.serviceContent.guestOperationsManager
|
56
|
+
|
57
|
+
guest_auth = RbVmomi::VIM::NamePasswordAuthentication(:interactiveSession => false,
|
58
|
+
:username => config[:exec_user],
|
59
|
+
:password => config[:exec_passwd])
|
60
|
+
prog_spec = RbVmomi::VIM::GuestProgramSpec(:programPath => command,
|
61
|
+
:arguments => args,
|
62
|
+
:workingDirectory => get_config(:exec_dir))
|
63
|
+
|
64
|
+
gom.processManager.StartProgramInGuest(:vm => vm, :auth => guest_auth, :spec => prog_spec)
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -3,64 +3,64 @@
|
|
3
3
|
# License:: Apache License, Version 2.0
|
4
4
|
#
|
5
5
|
require 'chef/knife'
|
6
|
-
require 'chef/knife/
|
6
|
+
require 'chef/knife/base_vsphere_command'
|
7
7
|
|
8
8
|
# Lists all known virtual machines in the configured datacenter
|
9
9
|
class Chef::Knife::VsphereVmList < Chef::Knife::BaseVsphereCommand
|
10
10
|
|
11
|
-
|
11
|
+
banner "knife vsphere vm list"
|
12
12
|
|
13
|
-
|
13
|
+
get_common_options
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
option :recursive,
|
16
|
+
:long => "--recursive",
|
17
|
+
:short => "-r",
|
18
|
+
:description => "Recurse down through sub-folders"
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
option :only_folders,
|
21
|
+
:long => "--only-folders",
|
22
|
+
:description => "Print only sub-folders"
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
def traverse_folders(folder)
|
25
|
+
puts "#{ui.color("Folder", :cyan)}: "+(folder.path[3..-1].map { |x| x[1] }.* '/')
|
26
|
+
print_vms_in_folder(folder) unless get_config(:only_folders)
|
27
|
+
folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
|
28
|
+
folders.each do |child|
|
29
|
+
traverse_folders(child)
|
30
|
+
end
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
def print_vms_in_folder(folder)
|
34
|
+
vms = find_all_in_folder(folder, RbVmomi::VIM::VirtualMachine)
|
35
|
+
vms.each do |vm|
|
36
|
+
state = case vm.runtime.powerState
|
37
|
+
when PsOn
|
38
|
+
ui.color("on", :green)
|
39
|
+
when PsOff
|
40
|
+
ui.color("off", :red)
|
41
|
+
when PsSuspended
|
42
|
+
ui.color("suspended", :yellow)
|
43
|
+
end
|
44
|
+
puts "#{ui.color("VM Name:", :cyan)} #{vm.name}\t#{ui.color("IP:", :magenta)} #{vm.guest.ipAddress}\t#{ui.color("RAM:", :magenta)} #{vm.summary.config.memorySizeMB}\t#{ui.color("State:", :cyan)} #{state}"
|
45
|
+
end
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
def print_subfolders(folder)
|
49
|
+
folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
|
50
50
|
folders.each do |subfolder|
|
51
51
|
puts "#{ui.color("Folder Name", :cyan)}: #{subfolder.name}"
|
52
52
|
end
|
53
|
-
|
53
|
+
end
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
def run
|
56
|
+
$stdout.sync = true
|
57
|
+
vim = get_vim_connection
|
58
|
+
baseFolder = find_folder(get_config(:folder));
|
59
|
+
if get_config(:recursive)
|
60
|
+
traverse_folders(baseFolder)
|
61
|
+
else
|
62
|
+
print_subfolders(baseFolder)
|
63
|
+
print_vms_in_folder(baseFolder)
|
64
|
+
end
|
65
|
+
end
|
66
66
|
end
|
@@ -1,9 +1,8 @@
|
|
1
|
-
|
2
|
-
# Author:: Ian Delahorne (<ian@delahorne.com>)
|
1
|
+
# Author:: Brian Dupras (<bdupras@rallydev.com>)
|
3
2
|
# License:: Apache License, Version 2.0
|
4
3
|
|
5
4
|
require 'chef/knife'
|
6
|
-
require 'chef/knife/
|
5
|
+
require 'chef/knife/base_vsphere_command'
|
7
6
|
require 'rbvmomi'
|
8
7
|
require 'netaddr'
|
9
8
|
|
@@ -33,7 +32,7 @@ class Chef::Knife::VsphereVmQuery < Chef::Knife::BaseVsphereCommand
|
|
33
32
|
folder = find_folder(get_config(:folder)) || dc.vmFolder
|
34
33
|
|
35
34
|
vm = find_in_folder(folder, RbVmomi::VIM::VirtualMachine, vmname) or
|
36
|
-
|
35
|
+
abort "VM #{vmname} not found"
|
37
36
|
|
38
37
|
# split QUERY by dots, and walk the object model
|
39
38
|
query = query_string.split '.'
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
|
5
5
|
require 'chef/knife'
|
6
|
-
require 'chef/knife/
|
6
|
+
require 'chef/knife/base_vsphere_command'
|
7
7
|
require 'rbvmomi'
|
8
8
|
require 'netaddr'
|
9
9
|
|
@@ -16,33 +16,33 @@ class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand
|
|
16
16
|
get_common_options
|
17
17
|
|
18
18
|
option :list,
|
19
|
-
|
20
|
-
|
19
|
+
:long => "--list",
|
20
|
+
:description => "The current tree of snapshots"
|
21
21
|
|
22
22
|
option :create_new_snapshot,
|
23
|
-
|
24
|
-
|
23
|
+
:long => "--create SNAPSHOT",
|
24
|
+
:description => "Create a new snapshot off of the current snapshot."
|
25
25
|
|
26
26
|
option :remove_named_snapshot,
|
27
|
-
|
28
|
-
|
27
|
+
:long => "--remove SNAPSHOT",
|
28
|
+
:description => "Remove a named snapshot."
|
29
29
|
|
30
30
|
option :revert_snapshot,
|
31
|
-
|
32
|
-
|
31
|
+
:long => "--revert SNAPSHOT",
|
32
|
+
:description => "Revert to a named snapshot."
|
33
33
|
|
34
34
|
option :revert_current_snapshot,
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
:long => "--revert-current",
|
36
|
+
:description => "Revert to current snapshot.",
|
37
|
+
:boolean => false
|
38
38
|
|
39
39
|
option :power,
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
:long => "--start",
|
41
|
+
:description => "Indicates whether to start the VM after a successful revert",
|
42
|
+
:boolean => false
|
43
43
|
|
44
44
|
def run
|
45
|
-
|
45
|
+
|
46
46
|
$stdout.sync = true
|
47
47
|
|
48
48
|
vmname = @name_args[0]
|
@@ -51,13 +51,13 @@ class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand
|
|
51
51
|
ui.fatal("You must specify a virtual machine name")
|
52
52
|
exit 1
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
vim = get_vim_connection
|
56
56
|
|
57
57
|
baseFolder = find_folder(get_config(:folder));
|
58
58
|
|
59
59
|
vm = find_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine, vmname) or
|
60
|
-
|
60
|
+
abort "VM #{vmname} not found"
|
61
61
|
|
62
62
|
if vm.snapshot
|
63
63
|
snapshot_list = vm.snapshot.rootSnapshotList
|
@@ -67,7 +67,7 @@ class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand
|
|
67
67
|
if config[:list] && vm.snapshot
|
68
68
|
puts "Current snapshot tree: "
|
69
69
|
puts "#{vmname}"
|
70
|
-
snapshot_list.each{|i| puts display_node(i,current_snapshot)}
|
70
|
+
snapshot_list.each { |i| puts display_node(i, current_snapshot) }
|
71
71
|
end
|
72
72
|
|
73
73
|
if config[:create_new_snapshot]
|
@@ -75,55 +75,55 @@ class Chef::Knife::VsphereVmSnapshot < Chef::Knife::BaseVsphereCommand
|
|
75
75
|
end
|
76
76
|
|
77
77
|
if config[:remove_named_snapshot]
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
ss_name = config[:remove_named_snapshot]
|
79
|
+
snapshot = find_node(snapshot_list, ss_name)
|
80
|
+
puts "Found snapshot #{ss_name} removing."
|
81
|
+
snapshot.RemoveSnapshot_Task(:removeChildren => false)
|
82
82
|
end
|
83
83
|
|
84
84
|
if config[:revert_current_snapshot]
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
puts "Reverting to Current Snapshot"
|
86
|
+
vm.RevertToCurrentSnapshot_Task(:suppressPowerOn => false).wait_for_completion
|
87
|
+
if get_config(:power)
|
88
|
+
vm.PowerOnVM_Task.wait_for_completion
|
89
|
+
puts "Powered on virtual machine #{vmname}"
|
90
|
+
end
|
91
91
|
end
|
92
92
|
|
93
93
|
if config[:revert_snapshot]
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
94
|
+
ss_name = config[:revert_snapshot]
|
95
|
+
snapshot = find_node(snapshot_list, ss_name)
|
96
|
+
snapshot.RevertToSnapshot_Task(:suppressPowerOn => false).wait_for_completion
|
97
|
+
if get_config(:power)
|
98
|
+
vm.PowerOnVM_Task.wait_for_completion
|
99
|
+
puts "Powered on virtual machine #{vmname}"
|
100
|
+
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
def find_node(tree,name)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
104
|
+
def find_node(tree, name)
|
105
|
+
snapshot = nil
|
106
|
+
tree.each do |node|
|
107
|
+
if node.name == name
|
108
|
+
snapshot = node.snapshot
|
109
|
+
elsif !node.childSnapshotList.empty?
|
110
|
+
snapshot = find_node(node.childSnapshotList, name)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
return snapshot
|
114
114
|
end
|
115
115
|
|
116
|
-
def display_node(node,current,shift=1)
|
116
|
+
def display_node(node, current, shift=1)
|
117
117
|
out = ""
|
118
|
-
out << "+--"*shift
|
118
|
+
out << "+--"*shift
|
119
119
|
if node.snapshot == current
|
120
|
-
|
121
|
-
else
|
122
|
-
|
120
|
+
out << "#{ui.color(node.name, :cyan)}" << "\n"
|
121
|
+
else
|
122
|
+
out << "#{node.name}" << "\n"
|
123
123
|
end
|
124
|
-
if !
|
125
|
-
|
126
|
-
end
|
127
|
-
out
|
128
|
-
end
|
124
|
+
if !node.childSnapshotList.empty?
|
125
|
+
node.childSnapshotList.each { |item| out << display_node(item, current, shift+1) }
|
126
|
+
end
|
127
|
+
out
|
128
|
+
end
|
129
129
|
end
|