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.
@@ -1,45 +1,45 @@
1
- #
2
- # Author:: Jesse Campbell (<hikeit@gmail.com>)
3
- # License:: Apache License, Version 2.0
4
- #
5
- require 'chef/knife'
6
- require 'chef/knife/BaseVsphereCommand'
7
-
8
- # Lists all known pools in the configured datacenter
9
- class Chef::Knife::VspherePoolList < Chef::Knife::BaseVsphereCommand
10
-
11
- banner "knife vsphere pool list"
12
-
13
- get_common_options
14
-
15
- def traverse_folders(folder)
16
- puts "#{ui.color("#{folder.class}", :cyan)}: "+(folder.path[3..-1].map{|x| x[1]}.*'/')
17
- folders = find_all_in_folder(folder, RbVmomi::VIM::ManagedObject)
18
- unless folders.nil?
19
- folders.each do |child|
20
- traverse_folders(child)
21
- end
22
- end
23
- end
24
-
25
- def find_pool_folder(folderName)
26
- dcname = get_config(:vsphere_dc)
27
- dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
28
- baseEntity = dc.hostFolder
29
- entityArray = folderName.split('/')
30
- entityArray.each do |entityArrItem|
31
- if entityArrItem != ''
32
- baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::ManagedObject).find { |f| f.name == entityArrItem } or
33
- abort "no such folder #{folderName} while looking for #{entityArrItem}"
34
- end
35
- end
36
- baseEntity
37
- end
38
-
39
- def run
40
- $stdout.sync = true
41
- vim = get_vim_connection
42
- baseFolder = find_pool_folder(get_config(:folder));
43
- traverse_folders(baseFolder)
44
- end
45
- end
1
+ #
2
+ # Author:: Jesse Campbell (<hikeit@gmail.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ require 'chef/knife'
6
+ require 'chef/knife/base_vsphere_command'
7
+
8
+ # Lists all known pools in the configured datacenter
9
+ class Chef::Knife::VspherePoolList < Chef::Knife::BaseVsphereCommand
10
+
11
+ banner "knife vsphere pool list"
12
+
13
+ get_common_options
14
+
15
+ def traverse_folders(folder)
16
+ puts "#{ui.color("#{folder.class}", :cyan)}: "+(folder.path[3..-1].map { |x| x[1] }.* '/')
17
+ folders = find_all_in_folder(folder, RbVmomi::VIM::ManagedObject)
18
+ unless folders.nil?
19
+ folders.each do |child|
20
+ traverse_folders(child)
21
+ end
22
+ end
23
+ end
24
+
25
+ def find_pool_folder(folderName)
26
+ dcname = get_config(:vsphere_dc)
27
+ dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
28
+ baseEntity = dc.hostFolder
29
+ entityArray = folderName.split('/')
30
+ entityArray.each do |entityArrItem|
31
+ if entityArrItem != ''
32
+ baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::ManagedObject).find { |f| f.name == entityArrItem } or
33
+ abort "no such folder #{folderName} while looking for #{entityArrItem}"
34
+ end
35
+ end
36
+ baseEntity
37
+ end
38
+
39
+ def run
40
+ $stdout.sync = true
41
+ vim = get_vim_connection
42
+ baseFolder = find_pool_folder(get_config(:folder));
43
+ traverse_folders(baseFolder)
44
+ end
45
+ end
@@ -1,32 +1,32 @@
1
- #
2
- # Author:: Ezra Pagel (<ezra@cpan.org>)
3
- # License:: Apache License, Version 2.0
4
- #
5
-
6
- require 'chef/knife'
7
- require 'chef/knife/BaseVsphereCommand'
8
-
9
- # Lists all known VM templates in the configured datacenter
10
- class Chef::Knife::VsphereTemplateList < Chef::Knife::BaseVsphereCommand
11
-
12
- banner "knife vsphere template list"
13
-
14
- get_common_options
15
-
16
- def run
17
-
18
- $stdout.sync = true
19
- $stderr.sync = true
20
-
21
- vim = get_vim_connection
22
-
23
- baseFolder = find_folder(get_config(:folder));
24
-
25
- vms = find_all_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine).
26
- select {|v| !v.config.nil? && v.config.template == true }
27
-
28
- vms.each do |vm|
29
- puts "#{ui.color("Template Name", :cyan)}: #{vm.name}"
30
- end
31
- end
32
- end
1
+ #
2
+ # Author:: Ezra Pagel (<ezra@cpan.org>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+
6
+ require 'chef/knife'
7
+ require 'chef/knife/base_vsphere_command'
8
+
9
+ # Lists all known VM templates in the configured datacenter
10
+ class Chef::Knife::VsphereTemplateList < Chef::Knife::BaseVsphereCommand
11
+
12
+ banner "knife vsphere template list"
13
+
14
+ get_common_options
15
+
16
+ def run
17
+
18
+ $stdout.sync = true
19
+ $stderr.sync = true
20
+
21
+ vim = get_vim_connection
22
+
23
+ baseFolder = find_folder(get_config(:folder));
24
+
25
+ vms = find_all_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine).
26
+ select { |v| !v.config.nil? && v.config.template == true }
27
+
28
+ vms.each do |vm|
29
+ puts "#{ui.color("Template Name", :cyan)}: #{vm.name}"
30
+ end
31
+ end
32
+ end
@@ -1,37 +1,38 @@
1
- # Author: Jesse Campbell
2
- #
3
- # Permission to use, copy, modify, and/or distribute this software for
4
- # any purpose with or without fee is hereby granted, provided that the
5
- # above copyright notice and this permission notice appear in all
6
- # copies.
7
- #
8
- # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
9
- # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10
- # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
11
- # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
- # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
13
- # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14
- # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
- # PERFORMANCE OF THIS SOFTWARE
16
-
17
- require 'chef/knife'
18
- require 'chef/knife/BaseVsphereCommand'
19
-
20
- # Lists all known data stores in datacenter with sizes
21
- class Chef::Knife::VsphereVlanList < Chef::Knife::BaseVsphereCommand
22
-
23
- banner "knife vsphere vlan list"
24
-
25
- get_common_options
26
- def run
27
- $stdout.sync = true
28
-
29
- vim = get_vim_connection
30
- dcname = get_config(:vsphere_dc)
31
- dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
32
- dc.network.each do |network|
33
- puts "#{ui.color("VLAN", :cyan)}: #{network.name}"
34
- end
35
- end
36
- end
37
-
1
+ # Author: Jesse Campbell
2
+ #
3
+ # Permission to use, copy, modify, and/or distribute this software for
4
+ # any purpose with or without fee is hereby granted, provided that the
5
+ # above copyright notice and this permission notice appear in all
6
+ # copies.
7
+ #
8
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
9
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
11
+ # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
+ # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
13
+ # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14
+ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ # PERFORMANCE OF THIS SOFTWARE
16
+
17
+ require 'chef/knife'
18
+ require 'chef/knife/base_vsphere_command'
19
+
20
+ # Lists all known data stores in datacenter with sizes
21
+ class Chef::Knife::VsphereVlanList < Chef::Knife::BaseVsphereCommand
22
+
23
+ banner "knife vsphere vlan list"
24
+
25
+ get_common_options
26
+
27
+ def run
28
+ $stdout.sync = true
29
+
30
+ vim = get_vim_connection
31
+ dcname = get_config(:vsphere_dc)
32
+ dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
33
+ dc.network.each do |network|
34
+ puts "#{ui.color("VLAN", :cyan)}: #{network.name}"
35
+ end
36
+ end
37
+ end
38
+
@@ -7,7 +7,7 @@
7
7
  #
8
8
 
9
9
  require 'chef/knife'
10
- require 'chef/knife/BaseVsphereCommand'
10
+ require 'chef/knife/base_vsphere_command'
11
11
  require 'rbvmomi'
12
12
  require 'netaddr'
13
13
 
@@ -18,244 +18,244 @@ require 'netaddr'
18
18
  # --chostname NODENAME --cdomain NODEDOMAIN
19
19
  class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
20
20
 
21
- banner "knife vsphere vm clone VMNAME (options)"
21
+ banner "knife vsphere vm clone VMNAME (options)"
22
22
 
23
- get_common_options
23
+ get_common_options
24
24
 
25
- option :dest_folder,
26
- :long => "--dest-folder FOLDER",
27
- :description => "The folder into which to put the cloned VM"
25
+ option :dest_folder,
26
+ :long => "--dest-folder FOLDER",
27
+ :description => "The folder into which to put the cloned VM"
28
28
 
29
- option :datastore,
30
- :long => "--datastore STORE",
31
- :description => "The datastore into which to put the cloned VM"
32
-
33
- option :resource_pool,
34
- :long => "--resource-pool POOL",
35
- :description => "The resource pool into which to put the cloned VM"
36
-
37
- option :source_vm,
38
- :long => "--template TEMPLATE",
39
- :description => "The source VM / Template to clone from",
40
- :required => true
41
-
42
- option :annotation,
43
- :long => "--annotation TEXT",
44
- :description => "Add TEXT in Notes field from annotation"
45
-
46
- option :customization_spec,
47
- :long => "--cspec CUST_SPEC",
48
- :description => "The name of any customization specification to apply"
49
-
50
- option :customization_plugin,
51
- :long => "--cplugin CUST_PLUGIN_PATH",
52
- :description => "Path to plugin that implements KnifeVspherePlugin.customize_clone_spec and/or KnifeVspherePlugin.reconfig_vm"
53
-
54
- option :customization_plugin_data,
55
- :long => "--cplugin-data CUST_PLUGIN_DATA",
56
- :description => "String of data to pass to the plugin. Use any format you wish."
57
-
58
- option :customization_vlan,
59
- :long => "--cvlan CUST_VLAN",
60
- :description => "VLAN name for network adapter to join"
61
-
62
- option :customization_ips,
63
- :long => "--cips CUST_IPS",
64
- :description => "Comma-delimited list of CIDR IPs for customization"
65
-
66
- option :customization_dns_ips,
67
- :long => "--cdnsips CUST_DNS_IPS",
68
- :description => "Comma-delimited list of DNS IP addresses"
69
-
70
- option :customization_dns_suffixes,
71
- :long => "--cdnssuffix CUST_DNS_SUFFIXES",
72
- :description => "Comma-delimited list of DNS search suffixes"
73
-
74
- option :customization_gw,
75
- :long => "--cgw CUST_GW",
76
- :description => "CIDR IP of gateway for customization"
77
-
78
- option :customization_hostname,
79
- :long => "--chostname CUST_HOSTNAME",
80
- :description => "Unqualified hostname for customization"
81
-
82
- option :customization_domain,
83
- :long => "--cdomain CUST_DOMAIN",
84
- :description => "Domain name for customization"
85
-
86
- option :customization_tz,
87
- :long => "--ctz CUST_TIMEZONE",
88
- :description => "Timezone invalid 'Area/Location' format"
89
-
90
- option :customization_cpucount,
91
- :long => "--ccpu CUST_CPU_COUNT",
92
- :description => "Number of CPUs"
93
-
94
- option :customization_memory,
95
- :long => "--cram CUST_MEMORY_GB",
96
- :description => "Gigabytes of RAM"
97
-
98
- option :power,
99
- :long => "--start",
100
- :description => "Indicates whether to start the VM after a successful clone",
101
- :boolean => false
102
-
103
- option :bootstrap,
104
- :long => "--bootstrap",
105
- :description => "Indicates whether to bootstrap the VM",
106
- :boolean => false
107
-
108
- option :fqdn,
109
- :long => "--fqdn SERVER_FQDN",
110
- :description => "Fully qualified hostname for bootstrapping"
111
-
112
- option :ssh_user,
113
- :short => "-x USERNAME",
114
- :long => "--ssh-user USERNAME",
115
- :description => "The ssh username"
116
- $default[:ssh_user] = "root"
117
-
118
- option :ssh_password,
119
- :short => "-P PASSWORD",
120
- :long => "--ssh-password PASSWORD",
121
- :description => "The ssh password"
122
-
123
- option :ssh_port,
124
- :short => "-p PORT",
125
- :long => "--ssh-port PORT",
126
- :description => "The ssh port"
127
- $default[:ssh_port] = 22
128
-
129
- option :identity_file,
130
- :short => "-i IDENTITY_FILE",
131
- :long => "--identity-file IDENTITY_FILE",
132
- :description => "The SSH identity file used for authentication"
133
-
134
- option :chef_node_name,
135
- :short => "-N NAME",
136
- :long => "--node-name NAME",
137
- :description => "The Chef node name for your new node"
138
-
139
- option :prerelease,
140
- :long => "--prerelease",
141
- :description => "Install the pre-release chef gems",
142
- :boolean => false
143
-
144
- option :bootstrap_version,
145
- :long => "--bootstrap-version VERSION",
146
- :description => "The version of Chef to install",
147
- :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
148
-
149
- option :bootstrap_proxy,
150
- :long => "--bootstrap-proxy PROXY_URL",
151
- :description => "The proxy server for the node being bootstrapped",
152
- :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
153
-
154
- option :distro,
155
- :short => "-d DISTRO",
156
- :long => "--distro DISTRO",
157
- :description => "Bootstrap a distro using a template"
158
-
159
- option :template_file,
160
- :long => "--template-file TEMPLATE",
161
- :description => "Full path to location of template to use"
29
+ option :datastore,
30
+ :long => "--datastore STORE",
31
+ :description => "The datastore into which to put the cloned VM"
32
+
33
+ option :resource_pool,
34
+ :long => "--resource-pool POOL",
35
+ :description => "The resource pool into which to put the cloned VM"
36
+
37
+ option :source_vm,
38
+ :long => "--template TEMPLATE",
39
+ :description => "The source VM / Template to clone from",
40
+ :required => true
41
+
42
+ option :annotation,
43
+ :long => "--annotation TEXT",
44
+ :description => "Add TEXT in Notes field from annotation"
45
+
46
+ option :customization_spec,
47
+ :long => "--cspec CUST_SPEC",
48
+ :description => "The name of any customization specification to apply"
49
+
50
+ option :customization_plugin,
51
+ :long => "--cplugin CUST_PLUGIN_PATH",
52
+ :description => "Path to plugin that implements KnifeVspherePlugin.customize_clone_spec and/or KnifeVspherePlugin.reconfig_vm"
53
+
54
+ option :customization_plugin_data,
55
+ :long => "--cplugin-data CUST_PLUGIN_DATA",
56
+ :description => "String of data to pass to the plugin. Use any format you wish."
57
+
58
+ option :customization_vlan,
59
+ :long => "--cvlan CUST_VLAN",
60
+ :description => "VLAN name for network adapter to join"
61
+
62
+ option :customization_ips,
63
+ :long => "--cips CUST_IPS",
64
+ :description => "Comma-delimited list of CIDR IPs for customization"
65
+
66
+ option :customization_dns_ips,
67
+ :long => "--cdnsips CUST_DNS_IPS",
68
+ :description => "Comma-delimited list of DNS IP addresses"
69
+
70
+ option :customization_dns_suffixes,
71
+ :long => "--cdnssuffix CUST_DNS_SUFFIXES",
72
+ :description => "Comma-delimited list of DNS search suffixes"
73
+
74
+ option :customization_gw,
75
+ :long => "--cgw CUST_GW",
76
+ :description => "CIDR IP of gateway for customization"
77
+
78
+ option :customization_hostname,
79
+ :long => "--chostname CUST_HOSTNAME",
80
+ :description => "Unqualified hostname for customization"
81
+
82
+ option :customization_domain,
83
+ :long => "--cdomain CUST_DOMAIN",
84
+ :description => "Domain name for customization"
85
+
86
+ option :customization_tz,
87
+ :long => "--ctz CUST_TIMEZONE",
88
+ :description => "Timezone invalid 'Area/Location' format"
89
+
90
+ option :customization_cpucount,
91
+ :long => "--ccpu CUST_CPU_COUNT",
92
+ :description => "Number of CPUs"
93
+
94
+ option :customization_memory,
95
+ :long => "--cram CUST_MEMORY_GB",
96
+ :description => "Gigabytes of RAM"
97
+
98
+ option :power,
99
+ :long => "--start",
100
+ :description => "Indicates whether to start the VM after a successful clone",
101
+ :boolean => false
102
+
103
+ option :bootstrap,
104
+ :long => "--bootstrap",
105
+ :description => "Indicates whether to bootstrap the VM",
106
+ :boolean => false
107
+
108
+ option :fqdn,
109
+ :long => "--fqdn SERVER_FQDN",
110
+ :description => "Fully qualified hostname for bootstrapping"
111
+
112
+ option :ssh_user,
113
+ :short => "-x USERNAME",
114
+ :long => "--ssh-user USERNAME",
115
+ :description => "The ssh username"
116
+ $default[:ssh_user] = "root"
117
+
118
+ option :ssh_password,
119
+ :short => "-P PASSWORD",
120
+ :long => "--ssh-password PASSWORD",
121
+ :description => "The ssh password"
122
+
123
+ option :ssh_port,
124
+ :short => "-p PORT",
125
+ :long => "--ssh-port PORT",
126
+ :description => "The ssh port"
127
+ $default[:ssh_port] = 22
128
+
129
+ option :identity_file,
130
+ :short => "-i IDENTITY_FILE",
131
+ :long => "--identity-file IDENTITY_FILE",
132
+ :description => "The SSH identity file used for authentication"
133
+
134
+ option :chef_node_name,
135
+ :short => "-N NAME",
136
+ :long => "--node-name NAME",
137
+ :description => "The Chef node name for your new node"
138
+
139
+ option :prerelease,
140
+ :long => "--prerelease",
141
+ :description => "Install the pre-release chef gems",
142
+ :boolean => false
143
+
144
+ option :bootstrap_version,
145
+ :long => "--bootstrap-version VERSION",
146
+ :description => "The version of Chef to install",
147
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
148
+
149
+ option :bootstrap_proxy,
150
+ :long => "--bootstrap-proxy PROXY_URL",
151
+ :description => "The proxy server for the node being bootstrapped",
152
+ :proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
153
+
154
+ option :distro,
155
+ :short => "-d DISTRO",
156
+ :long => "--distro DISTRO",
157
+ :description => "Bootstrap a distro using a template"
158
+
159
+ option :template_file,
160
+ :long => "--template-file TEMPLATE",
161
+ :description => "Full path to location of template to use"
162
162
 
163
163
  option :run_list,
164
- :short => "-r RUN_LIST",
165
- :long => "--run-list RUN_LIST",
166
- :description => "Comma separated list of roles/recipes to apply"
164
+ :short => "-r RUN_LIST",
165
+ :long => "--run-list RUN_LIST",
166
+ :description => "Comma separated list of roles/recipes to apply"
167
167
  $default[:run_list] = ''
168
168
 
169
169
  option :secret_file,
170
- :long => "--secret-file SECRET_FILE",
171
- :description => "A file containing the secret key to use to encrypt data bag item values"
170
+ :long => "--secret-file SECRET_FILE",
171
+ :description => "A file containing the secret key to use to encrypt data bag item values"
172
172
  $default[:secret_file] = ''
173
173
 
174
- option :no_host_key_verify,
175
- :long => "--no-host-key-verify",
176
- :description => "Disable host key verification",
177
- :boolean => true
174
+ option :no_host_key_verify,
175
+ :long => "--no-host-key-verify",
176
+ :description => "Disable host key verification",
177
+ :boolean => true
178
178
 
179
179
  option :first_boot_attributes,
180
- :short => "-j JSON_ATTRIBS",
181
- :long => "--json-attributes",
182
- :description => "A JSON string to be added to the first run of chef-client",
183
- :proc => lambda { |o| JSON.parse(o) },
184
- :default => {}
185
-
186
- option :disable_customization,
187
- :long => "--disable-customization",
188
- :description => "Disable default customization",
189
- :boolean => true,
190
- :default => false
180
+ :short => "-j JSON_ATTRIBS",
181
+ :long => "--json-attributes",
182
+ :description => "A JSON string to be added to the first run of chef-client",
183
+ :proc => lambda { |o| JSON.parse(o) },
184
+ :default => {}
185
+
186
+ option :disable_customization,
187
+ :long => "--disable-customization",
188
+ :description => "Disable default customization",
189
+ :boolean => true,
190
+ :default => false
191
191
 
192
192
  option :log_level,
193
- :short => "-l LEVEL",
194
- :long => "--log_level",
195
- :description => "Set the log level (debug, info, warn, error, fatal) for chef-client",
196
- :proc => lambda { |l| l.to_sym }
197
-
198
- def run
199
- $stdout.sync = true
200
-
201
- vmname = @name_args[0]
202
- if vmname.nil?
203
- show_usage
204
- fatal_exit("You must specify a virtual machine name")
205
- end
206
- config[:chef_node_name] = vmname unless config[:chef_node_name]
207
- config[:vmname] = vmname
193
+ :short => "-l LEVEL",
194
+ :long => "--log_level",
195
+ :description => "Set the log level (debug, info, warn, error, fatal) for chef-client",
196
+ :proc => lambda { |l| l.to_sym }
197
+
198
+ def run
199
+ $stdout.sync = true
200
+
201
+ vmname = @name_args[0]
202
+ if vmname.nil?
203
+ show_usage
204
+ fatal_exit("You must specify a virtual machine name")
205
+ end
206
+ config[:chef_node_name] = vmname unless config[:chef_node_name]
207
+ config[:vmname] = vmname
208
208
 
209
- if get_config(:bootstrap) && get_config(:distro) && !@@chef_config_dir
210
- fatal_exit("Can't find .chef for bootstrap files. chdir to a location with a .chef directory and try again")
211
- end
209
+ if get_config(:bootstrap) && get_config(:distro) && !@@chef_config_dir
210
+ fatal_exit("Can't find .chef for bootstrap files. chdir to a location with a .chef directory and try again")
211
+ end
212
212
 
213
- vim = get_vim_connection
213
+ vim = get_vim_connection
214
214
 
215
215
  dcname = get_config(:vsphere_dc)
216
216
  dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
217
217
 
218
- src_folder = find_folder(get_config(:folder)) || dc.vmFolder
218
+ src_folder = find_folder(get_config(:folder)) || dc.vmFolder
219
219
 
220
- src_vm = find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, config[:source_vm]) or
221
- abort "VM/Template not found"
220
+ src_vm = find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, config[:source_vm]) or
221
+ abort "VM/Template not found"
222
222
 
223
- clone_spec = generate_clone_spec(src_vm.config)
223
+ clone_spec = generate_clone_spec(src_vm.config)
224
224
 
225
225
  cust_folder = config[:dest_folder] || get_config(:folder)
226
226
 
227
- dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder)
227
+ dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder)
228
228
 
229
- task = src_vm.CloneVM_Task(:folder => dest_folder, :name => vmname, :spec => clone_spec)
230
- puts "Cloning template #{config[:source_vm]} to new VM #{vmname}"
231
- task.wait_for_completion
232
- puts "Finished creating virtual machine #{vmname}"
229
+ task = src_vm.CloneVM_Task(:folder => dest_folder, :name => vmname, :spec => clone_spec)
230
+ puts "Cloning template #{config[:source_vm]} to new VM #{vmname}"
231
+ task.wait_for_completion
232
+ puts "Finished creating virtual machine #{vmname}"
233
233
 
234
- if customization_plugin && customization_plugin.respond_to?(:reconfig_vm)
235
- target_vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) or abort "VM could not be found in #{dest_folder}"
236
- customization_plugin.reconfig_vm(target_vm)
237
- end
234
+ if customization_plugin && customization_plugin.respond_to?(:reconfig_vm)
235
+ target_vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) or abort "VM could not be found in #{dest_folder}"
236
+ customization_plugin.reconfig_vm(target_vm)
237
+ end
238
238
 
239
- if get_config(:power) || get_config(:bootstrap)
240
- vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) or
241
- fatal_exit("VM #{vmname} not found")
242
- vm.PowerOnVM_Task.wait_for_completion
243
- puts "Powered on virtual machine #{vmname}"
244
- end
239
+ if get_config(:power) || get_config(:bootstrap)
240
+ vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) or
241
+ fatal_exit("VM #{vmname} not found")
242
+ vm.PowerOnVM_Task.wait_for_completion
243
+ puts "Powered on virtual machine #{vmname}"
244
+ end
245
245
 
246
- if get_config(:bootstrap)
247
- sleep 2 until vm.guest.ipAddress
248
- config[:fqdn] = vm.guest.ipAddress unless config[:fqdn]
249
- print "Waiting for sshd..."
250
- print "." until tcp_test_ssh(config[:fqdn])
251
- puts "done"
246
+ if get_config(:bootstrap)
247
+ sleep 2 until vm.guest.ipAddress
248
+ config[:fqdn] = vm.guest.ipAddress unless config[:fqdn]
249
+ print "Waiting for sshd..."
250
+ print "." until tcp_test_ssh(config[:fqdn])
251
+ puts "done"
252
252
 
253
- bootstrap_for_node.run
254
- end
255
- end
253
+ bootstrap_for_node.run
254
+ end
255
+ end
256
256
 
257
- # Builds a CloneSpec
258
- def generate_clone_spec (src_config)
257
+ # Builds a CloneSpec
258
+ def generate_clone_spec (src_config)
259
259
 
260
260
  rspec = nil
261
261
  if get_config(:resource_pool)
@@ -268,219 +268,219 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
268
268
  rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => rp)
269
269
  end
270
270
 
271
- if get_config(:datastore)
272
- rspec.datastore = find_datastore(get_config(:datastore))
273
- end
274
-
275
- clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec,
276
- :powerOn => false,
277
- :template => false)
278
-
279
- clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => Array.new)
280
-
281
- if get_config(:annotation)
282
- clone_spec.config.annotation = get_config(:annotation)
283
- end
284
-
285
- if get_config(:customization_cpucount)
286
- clone_spec.config.numCPUs = get_config(:customization_cpucount)
287
- end
288
-
289
- if get_config(:customization_memory)
290
- clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024
291
- end
292
-
293
- if get_config(:customization_vlan)
294
- network = find_network(get_config(:customization_vlan))
295
- card = src_config.hardware.device.find { |d| d.deviceInfo.label == "Network adapter 1" } or
296
- abort "Can't find source network card to customize"
297
- begin
298
- switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(:switchUuid => network.config.distributedVirtualSwitch.uuid ,:portgroupKey => network.key)
299
- card.backing.port = switch_port
300
- rescue
301
- # not connected to a distibuted switch?
302
- card.backing.deviceName = network.name
303
- end
304
- dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(:device => card, :operation => "edit")
305
- clone_spec.config.deviceChange.push dev_spec
306
- end
307
-
308
- if get_config(:customization_spec)
309
- csi = find_customization(get_config(:customization_spec)) or
310
- fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")
311
-
312
- if csi.info.type != "Linux"
313
- fatal_exit("Only Linux customization specifications are currently supported")
314
- end
315
- cust_spec = csi.spec
316
- else
317
- global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings
318
- cust_spec = RbVmomi::VIM.CustomizationSpec(:globalIPSettings => global_ipset)
319
- end
320
-
321
- if get_config(:customization_dns_ips)
322
- cust_spec.globalIPSettings.dnsServerList = get_config(:customization_dns_ips).split(',')
323
- end
324
-
325
- if get_config(:customization_dns_suffixes)
326
- cust_spec.globalIPSettings.dnsSuffixList = get_config(:customization_dns_suffixes).split(',')
327
- end
328
-
329
- if config[:customization_ips]
330
- if get_config(:customization_gw)
331
- cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i,get_config(:customization_gw)) }
332
- else
333
- cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i) }
334
- end
335
- end
271
+ if get_config(:datastore)
272
+ rspec.datastore = find_datastore(get_config(:datastore))
273
+ end
274
+
275
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec,
276
+ :powerOn => false,
277
+ :template => false)
278
+
279
+ clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => Array.new)
280
+
281
+ if get_config(:annotation)
282
+ clone_spec.config.annotation = get_config(:annotation)
283
+ end
284
+
285
+ if get_config(:customization_cpucount)
286
+ clone_spec.config.numCPUs = get_config(:customization_cpucount)
287
+ end
288
+
289
+ if get_config(:customization_memory)
290
+ clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024
291
+ end
292
+
293
+ if get_config(:customization_vlan)
294
+ network = find_network(get_config(:customization_vlan))
295
+ card = src_config.hardware.device.find { |d| d.deviceInfo.label == "Network adapter 1" } or
296
+ abort "Can't find source network card to customize"
297
+ begin
298
+ switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(:switchUuid => network.config.distributedVirtualSwitch.uuid, :portgroupKey => network.key)
299
+ card.backing.port = switch_port
300
+ rescue
301
+ # not connected to a distibuted switch?
302
+ card.backing.deviceName = network.name
303
+ end
304
+ dev_spec = RbVmomi::VIM.VirtualDeviceConfigSpec(:device => card, :operation => "edit")
305
+ clone_spec.config.deviceChange.push dev_spec
306
+ end
307
+
308
+ if get_config(:customization_spec)
309
+ csi = find_customization(get_config(:customization_spec)) or
310
+ fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")
311
+
312
+ if csi.info.type != "Linux"
313
+ fatal_exit("Only Linux customization specifications are currently supported")
314
+ end
315
+ cust_spec = csi.spec
316
+ else
317
+ global_ipset = RbVmomi::VIM.CustomizationGlobalIPSettings
318
+ cust_spec = RbVmomi::VIM.CustomizationSpec(:globalIPSettings => global_ipset)
319
+ end
320
+
321
+ if get_config(:customization_dns_ips)
322
+ cust_spec.globalIPSettings.dnsServerList = get_config(:customization_dns_ips).split(',')
323
+ end
324
+
325
+ if get_config(:customization_dns_suffixes)
326
+ cust_spec.globalIPSettings.dnsSuffixList = get_config(:customization_dns_suffixes).split(',')
327
+ end
328
+
329
+ if config[:customization_ips]
330
+ if get_config(:customization_gw)
331
+ cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i, get_config(:customization_gw)) }
332
+ else
333
+ cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i) }
334
+ end
335
+ end
336
336
 
337
337
  unless get_config(:disable_customization)
338
338
  use_ident = !config[:customization_hostname].nil? || !get_config(:customization_domain).nil? || cust_spec.identity.nil?
339
339
 
340
340
 
341
- if use_ident
342
- # TODO - verify that we're deploying a linux spec, at least warn
343
- ident = RbVmomi::VIM.CustomizationLinuxPrep
344
-
345
- ident.hostName = RbVmomi::VIM.CustomizationFixedName
346
- if config[:customization_hostname]
347
- ident.hostName.name = config[:customization_hostname]
348
- else
349
- ident.hostName.name = config[:vmname]
350
- end
351
-
352
- if get_config(:customization_domain)
353
- ident.domain = get_config(:customization_domain)
354
- else
355
- ident.domain = ''
356
- end
357
-
358
- cust_spec.identity = ident
359
- end
360
-
361
- if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec)
362
- clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec)
363
- end
364
-
365
- clone_spec.customization = cust_spec
366
- end
367
- clone_spec
368
- end
369
-
370
- # Loads the customization plugin if one was specified
371
- # @return [KnifeVspherePlugin] the loaded and initialized plugin or nil
372
- def customization_plugin
373
- if @customization_plugin.nil?
374
- if cplugin_path = get_config(:customization_plugin)
375
- if File.exists? cplugin_path
376
- require cplugin_path
377
- else
378
- abort "Customization plugin could not be found at #{cplugin_path}"
379
- end
380
-
381
- if Object.const_defined? 'KnifeVspherePlugin'
382
- @customization_plugin = Object.const_get('KnifeVspherePlugin').new
383
- if cplugin_data = get_config(:customization_plugin_data)
384
- if @customization_plugin.respond_to?(:data=)
385
- @customization_plugin.data = cplugin_data
386
- else
387
- abort "Customization plugin has no :data= accessor to receive the --cplugin-data argument. Define both or neither."
388
- end
389
- end
390
- else
391
- abort "KnifeVspherePlugin class is not defined in #{cplugin_path}"
392
- end
393
- end
394
- end
395
-
396
- @customization_plugin
397
- end
398
-
399
- # Retrieves a CustomizationSpecItem that matches the supplied name
400
- # @param vim [Connection] VI Connection to use
401
- # @param name [String] name of customization
402
- # @return [RbVmomi::VIM::CustomizationSpecItem]
403
- def find_customization(name)
404
- csm = config[:vim].serviceContent.customizationSpecManager
405
- csm.GetCustomizationSpec(:name => name)
406
- end
407
-
408
- # Generates a CustomizationAdapterMapping (currently only single IPv4 address) object
409
- # @param ip [String] Any static IP address to use, otherwise DHCP
410
- # @param gw [String] If static, the gateway for the interface, otherwise network address + 1 will be used
411
- # @return [RbVmomi::VIM::CustomizationIPSettings]
412
- def generate_adapter_map (ip=nil, gw=nil, dns1=nil, dns2=nil, domain=nil)
413
-
414
- settings = RbVmomi::VIM.CustomizationIPSettings
415
-
416
- if ip.nil?
417
- settings.ip = RbVmomi::VIM::CustomizationDhcpIpGenerator
418
- else
419
- cidr_ip = NetAddr::CIDR.create(ip)
420
- settings.ip = RbVmomi::VIM::CustomizationFixedIp(:ipAddress => cidr_ip.ip)
421
- settings.subnetMask = cidr_ip.netmask_ext
422
-
423
- # TODO - want to confirm gw/ip are in same subnet?
424
- # Only set gateway on first IP.
425
- if config[:customization_ips].split(',').first == ip
426
- if gw.nil?
427
- settings.gateway = [cidr_ip.network(:Objectify => true).next_ip]
428
- else
429
- gw_cidr = NetAddr::CIDR.create(gw)
430
- settings.gateway = [gw_cidr.ip]
431
- end
432
- end
433
- end
434
-
435
- adapter_map = RbVmomi::VIM.CustomizationAdapterMapping
436
- adapter_map.adapter = settings
437
- adapter_map
438
- end
439
-
440
- def bootstrap_for_node()
441
- Chef::Knife::Bootstrap.load_deps
442
- bootstrap = Chef::Knife::Bootstrap.new
443
- bootstrap.name_args = [config[:fqdn]]
444
- bootstrap.config[:run_list] = get_config(:run_list).split(/[\s,]+/)
341
+ if use_ident
342
+ # TODO - verify that we're deploying a linux spec, at least warn
343
+ ident = RbVmomi::VIM.CustomizationLinuxPrep
344
+
345
+ ident.hostName = RbVmomi::VIM.CustomizationFixedName
346
+ if config[:customization_hostname]
347
+ ident.hostName.name = config[:customization_hostname]
348
+ else
349
+ ident.hostName.name = config[:vmname]
350
+ end
351
+
352
+ if get_config(:customization_domain)
353
+ ident.domain = get_config(:customization_domain)
354
+ else
355
+ ident.domain = ''
356
+ end
357
+
358
+ cust_spec.identity = ident
359
+ end
360
+
361
+ if customization_plugin && customization_plugin.respond_to?(:customize_clone_spec)
362
+ clone_spec = customization_plugin.customize_clone_spec(src_config, clone_spec)
363
+ end
364
+
365
+ clone_spec.customization = cust_spec
366
+ end
367
+ clone_spec
368
+ end
369
+
370
+ # Loads the customization plugin if one was specified
371
+ # @return [KnifeVspherePlugin] the loaded and initialized plugin or nil
372
+ def customization_plugin
373
+ if @customization_plugin.nil?
374
+ if cplugin_path = get_config(:customization_plugin)
375
+ if File.exists? cplugin_path
376
+ require cplugin_path
377
+ else
378
+ abort "Customization plugin could not be found at #{cplugin_path}"
379
+ end
380
+
381
+ if Object.const_defined? 'KnifeVspherePlugin'
382
+ @customization_plugin = Object.const_get('KnifeVspherePlugin').new
383
+ if cplugin_data = get_config(:customization_plugin_data)
384
+ if @customization_plugin.respond_to?(:data=)
385
+ @customization_plugin.data = cplugin_data
386
+ else
387
+ abort "Customization plugin has no :data= accessor to receive the --cplugin-data argument. Define both or neither."
388
+ end
389
+ end
390
+ else
391
+ abort "KnifeVspherePlugin class is not defined in #{cplugin_path}"
392
+ end
393
+ end
394
+ end
395
+
396
+ @customization_plugin
397
+ end
398
+
399
+ # Retrieves a CustomizationSpecItem that matches the supplied name
400
+ # @param vim [Connection] VI Connection to use
401
+ # @param name [String] name of customization
402
+ # @return [RbVmomi::VIM::CustomizationSpecItem]
403
+ def find_customization(name)
404
+ csm = config[:vim].serviceContent.customizationSpecManager
405
+ csm.GetCustomizationSpec(:name => name)
406
+ end
407
+
408
+ # Generates a CustomizationAdapterMapping (currently only single IPv4 address) object
409
+ # @param ip [String] Any static IP address to use, otherwise DHCP
410
+ # @param gw [String] If static, the gateway for the interface, otherwise network address + 1 will be used
411
+ # @return [RbVmomi::VIM::CustomizationIPSettings]
412
+ def generate_adapter_map (ip=nil, gw=nil, dns1=nil, dns2=nil, domain=nil)
413
+
414
+ settings = RbVmomi::VIM.CustomizationIPSettings
415
+
416
+ if ip.nil?
417
+ settings.ip = RbVmomi::VIM::CustomizationDhcpIpGenerator
418
+ else
419
+ cidr_ip = NetAddr::CIDR.create(ip)
420
+ settings.ip = RbVmomi::VIM::CustomizationFixedIp(:ipAddress => cidr_ip.ip)
421
+ settings.subnetMask = cidr_ip.netmask_ext
422
+
423
+ # TODO - want to confirm gw/ip are in same subnet?
424
+ # Only set gateway on first IP.
425
+ if config[:customization_ips].split(',').first == ip
426
+ if gw.nil?
427
+ settings.gateway = [cidr_ip.network(:Objectify => true).next_ip]
428
+ else
429
+ gw_cidr = NetAddr::CIDR.create(gw)
430
+ settings.gateway = [gw_cidr.ip]
431
+ end
432
+ end
433
+ end
434
+
435
+ adapter_map = RbVmomi::VIM.CustomizationAdapterMapping
436
+ adapter_map.adapter = settings
437
+ adapter_map
438
+ end
439
+
440
+ def bootstrap_for_node()
441
+ Chef::Knife::Bootstrap.load_deps
442
+ bootstrap = Chef::Knife::Bootstrap.new
443
+ bootstrap.name_args = [config[:fqdn]]
444
+ bootstrap.config[:run_list] = get_config(:run_list).split(/[\s,]+/)
445
445
  bootstrap.config[:secret_file] = get_config(:secret_file)
446
446
  bootstrap.config[:ssh_user] = get_config(:ssh_user)
447
- bootstrap.config[:ssh_password] = get_config(:ssh_password)
448
- bootstrap.config[:ssh_port] = get_config(:ssh_port)
449
- bootstrap.config[:identity_file] = get_config(:identity_file)
450
- bootstrap.config[:chef_node_name] = get_config(:chef_node_name)
451
- bootstrap.config[:prerelease] = get_config(:prerelease)
452
- bootstrap.config[:bootstrap_version] = get_config(:bootstrap_version)
453
- bootstrap.config[:distro] = get_config(:distro)
454
- bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
455
- bootstrap.config[:template_file] = get_config(:template_file)
456
- bootstrap.config[:environment] = get_config(:environment)
447
+ bootstrap.config[:ssh_password] = get_config(:ssh_password)
448
+ bootstrap.config[:ssh_port] = get_config(:ssh_port)
449
+ bootstrap.config[:identity_file] = get_config(:identity_file)
450
+ bootstrap.config[:chef_node_name] = get_config(:chef_node_name)
451
+ bootstrap.config[:prerelease] = get_config(:prerelease)
452
+ bootstrap.config[:bootstrap_version] = get_config(:bootstrap_version)
453
+ bootstrap.config[:distro] = get_config(:distro)
454
+ bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
455
+ bootstrap.config[:template_file] = get_config(:template_file)
456
+ bootstrap.config[:environment] = get_config(:environment)
457
457
  bootstrap.config[:first_boot_attributes] = get_config(:first_boot_attributes)
458
458
  bootstrap.config[:log_level] = get_config(:log_level)
459
- # may be needed for vpc_mode
460
- bootstrap.config[:no_host_key_verify] = get_config(:no_host_key_verify)
461
- bootstrap
462
- end
463
-
464
- def tcp_test_ssh(hostname)
465
- tcp_socket = TCPSocket.new(hostname, get_config(:ssh_port))
466
- readable = IO.select([tcp_socket], nil, nil, 5)
467
- if readable
468
- Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
469
- true
470
- else
471
- false
472
- end
473
- rescue Errno::ETIMEDOUT
474
- false
475
- rescue Errno::EPERM
476
- false
477
- rescue Errno::ECONNREFUSED
478
- sleep 2
479
- false
480
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
481
- sleep 2
482
- false
483
- ensure
484
- tcp_socket && tcp_socket.close
485
- end
459
+ # may be needed for vpc_mode
460
+ bootstrap.config[:no_host_key_verify] = get_config(:no_host_key_verify)
461
+ bootstrap
462
+ end
463
+
464
+ def tcp_test_ssh(hostname)
465
+ tcp_socket = TCPSocket.new(hostname, get_config(:ssh_port))
466
+ readable = IO.select([tcp_socket], nil, nil, 5)
467
+ if readable
468
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
469
+ true
470
+ else
471
+ false
472
+ end
473
+ rescue Errno::ETIMEDOUT
474
+ false
475
+ rescue Errno::EPERM
476
+ false
477
+ rescue Errno::ECONNREFUSED
478
+ sleep 2
479
+ false
480
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
481
+ sleep 2
482
+ false
483
+ ensure
484
+ tcp_socket && tcp_socket.close
485
+ end
486
486
  end