knife-vsphere 0.9.0 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|