knife-cloudstack-fog 0.5.2 → 0.6.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cabd0497918fc2d74a07bf227823c06843871e11
4
- data.tar.gz: 040fd195030f8066160240c34b4dcaa123ff1184
3
+ metadata.gz: 9783b50b32ad22099bd01c21caa5cceca1717a28
4
+ data.tar.gz: e40480ac878ead9a2606bbe1e2f189d2347acc70
5
5
  SHA512:
6
- metadata.gz: 5ba61637614a9af0a1a4f707a0d6345117924daf03bd5ca31e92099db48cd0a95604785bbedb2089fcffaeb84787c04e0d8ff8aae6b3b84c49052c859f72aaf6
7
- data.tar.gz: ec4edf39407225b490845590148436e51c293490b928f6c6ed94f3d38780f63d604d69a70b00531f8111822fa7cc3e69982019c240987511a80bfbdcb9e2b4f1
6
+ metadata.gz: 42e5db01915d4693be9301d05b6ec80c6d2a337526ad2af145b7366ea9bb7caf2e51bd447cd38eafe3fd95a82ac08c8069201ab7a9fcbd39754af0f38820954c
7
+ data.tar.gz: cf73a2525989a2dc5a16a6706f694c83f42e6d81f6a0be9d45b443ae2dd4f627513b4843c219458299ba4cf5b3677ac35c356d33f7700ad3cf1dbb6ab2feea66
@@ -13,10 +13,6 @@ This is the unofficial Opscode Knife plugin for Apache CloudStack / Citrix Cloud
13
13
  Be sure you are running the latest version Chef. Versions earlier than 0.10.0 don't support plugins:
14
14
 
15
15
  $ gem install chef
16
-
17
- Also ensure you are running the latest version of Fog. Versions earlier than 1.3.1 don't fully support Cloudstack Cloud:
18
-
19
- $ gem update fog
20
16
 
21
17
  This plugin is distributed as a Ruby Gem. To install it, run:
22
18
 
@@ -62,7 +62,7 @@ class Chef
62
62
 
63
63
  case mode
64
64
  when 'register'
65
- response = connection.register_ssh_key_pair(options)
65
+ response = connection.register_ssh_key_pair(options['publickey'], options['name'])
66
66
  sshkeypair = response['registersshkeypairresponse']['keypair']
67
67
 
68
68
  sshkeypair_list = [
@@ -78,13 +78,14 @@ class Chef
78
78
  validate!
79
79
 
80
80
  netoptions = {}
81
+ mandatoryoptions = {}
81
82
 
82
83
  if (locate_config_value(:name).nil? || locate_config_value(:networkoffering).nil? || locate_config_value(:zone).nil?)
83
84
  puts "Name (-n), Service Offering ID (-o), and Zone ID (-z) are required."
84
85
  else
85
- netoptions['name'] = locate_config_value(:name)
86
- netoptions['networkofferingid'] = locate_config_value(:networkoffering)
87
- netoptions['zoneid'] = locate_config_value(:zone)
86
+ mandatoryoptions['name'] = locate_config_value(:name)
87
+ mandatoryoptions['networkofferingid'] = locate_config_value(:networkoffering)
88
+ mandatoryoptions['zoneid'] = locate_config_value(:zone)
88
89
 
89
90
  if locate_config_value(:startip) != nil
90
91
  netoptions['startip'] = locate_config_value(:startip)
@@ -107,14 +108,14 @@ class Chef
107
108
  end
108
109
 
109
110
  if locate_config_value(:displaytext) != nil
110
- netoptions['displaytext'] = locate_config_value(:displaytext)
111
+ mandatoryoptions['displaytext'] = locate_config_value(:displaytext)
111
112
  else
112
- netoptions['displaytext'] = locate_config_value(:name)
113
+ mandatoryoptions['displaytext'] = locate_config_value(:name)
113
114
  end
114
115
 
115
116
  Chef::Log.debug("Options: #{netoptions}")
116
117
 
117
- response = connection.create_network(netoptions)
118
+ response = connection.create_network(mandatoryoptions['displaytext'], mandatoryoptions['name'], mandatoryoptions['networkofferingid'], mandatoryoptions['zoneid'], netoptions)
118
119
 
119
120
  Chef::Log.debug("API Response: #{response}")
120
121
 
@@ -23,491 +23,516 @@ require 'chef/json_compat'
23
23
  require 'chef/knife/cloudstack_base'
24
24
  require 'chef/knife/ssh'
25
25
  Chef::Knife::Ssh.load_deps
26
+ # require 'pry'
26
27
 
27
28
  class Chef
28
- class Knife
29
- class CloudstackServerCreate < Knife
30
-
31
- include Knife::CloudstackBase
32
-
33
- banner "knife cloudstack server create -s SERVICEID -t TEMPLATEID -z ZONEID (options)"
34
-
35
- option :cloudstack_serviceid,
36
- :short => "-s SERVICEID",
37
- :long => "--serviceid SERVICEID",
38
- :description => "The CloudStack service offering ID."
39
-
40
- option :cloudstack_templateid,
41
- :short => "-t TEMPLATEID",
42
- :long => "--templateid TEMPLATEID",
43
- :description => "The CloudStack template ID for the server."
44
-
45
- option :cloudstack_zoneid,
46
- :short => "-Z ZONEID",
47
- :long => "--zoneid ZONE",
48
- :description => "The CloudStack zone ID for the server."
49
-
50
- option :cloudstack_networkids,
51
- :short => "-w NETWORKIDS",
52
- :long => "--networkids NETWORKIDS",
53
- :description => "Comma separated list of CloudStack network IDs.",
54
- :proc => lambda { |n| n.split(/[\s,]+/) },
55
- :default => []
56
-
57
- option :cloudstack_groupids,
58
- :short => "-g SECURITYGROUPIDS",
59
- :long => "--groupids SECURITYGROUPIDS",
60
- :description => "Comma separated list of CloudStack Security Group IDs.",
61
- :proc => lambda { |n| n.split(/[\s,]+/) },
62
- :default => []
63
-
64
- option :cloudstack_groupnames,
65
- :short => "-G SECURITYGROUPNAMES",
66
- :long => "--groupnames SECURITYGROUPNAMES",
67
- :description => "Comma separated list of CloudStack Security Group names. Each group name must be encapuslated in quotes if it contains whitespace.",
68
- :proc => lambda { |n| n.split(/[\s,]+/) },
69
- :default => []
70
-
71
- option :distro,
72
- :short => "-d DISTRO",
73
- :long => "--distro DISTRO",
74
- :description => "Bootstrap a distro using a template; default is 'chef-full'",
75
- :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
76
- :default => "chef-full"
77
-
78
- option :template_file,
79
- :long => "--template-file TEMPLATE",
80
- :description => "Full path to location of template to use",
81
- :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
82
- :default => false
83
-
84
- option :run_list,
85
- :short => "-r RUN_LIST",
86
- :long => "--run-list RUN_LIST",
87
- :description => "Comma separated list of roles/recipes to apply",
88
- :proc => lambda { |o| o.split(/[\s,]+/) },
89
- :default => []
90
-
91
- option :ssh_user,
92
- :short => "-x USERNAME",
93
- :long => "--ssh-user USERNAME",
94
- :description => "The ssh username",
95
- :default => 'root'
96
-
97
- option :ssh_password,
98
- :short => "-P PASSWORD",
99
- :long => "--ssh-password PASSWORD",
100
- :description => "The ssh password"
101
-
102
- option :identity_file,
103
- :short => "-i PRIVATE_KEY_FILE",
104
- :long => "--identity-file PRIVATE_KEY_FILE",
105
- :description => "The Private key file for authenticating SSH session. --keypair option is also needed."
106
-
107
- option :ssh_port,
108
- :short => "-p PORT",
109
- :long => "--ssh-port PORT",
110
- :description => "The port which SSH should be listening on. If unspecified, will default to 22."
111
-
112
- option :server_display_name,
113
- :short => "-N NAME",
114
- :long => "--display-name NAME",
115
- :description => "The instance display name"
116
-
117
- option :host_name,
118
- :short => "-H NAME",
119
- :long => "--hostname NAME",
120
- :description => "The instance host name"
121
-
122
- option :keypair,
123
- :short => "-k KEYPAIR",
124
- :long => "--keypair KEYPAIR",
125
- :description => "The CloudStack Key Pair to use for SSH key authentication."
126
-
127
- option :diskoffering,
128
- :short => "-D DISKOFFERINGID",
129
- :long => "--diskoffering DISKOFFERINGID",
130
- :description => "Specifies either the Disk Offering ID for the ROOT disk for an ISO template, or a DATA disk."
131
-
132
- option :size,
133
- :long => "--size SIZE",
134
- :description => "Specifies the arbitrary Disk Size for DATADISK volume in GB. Must be passed with custom size Disk Offering ID."
135
-
136
- option :random_ssh_port,
137
- :long => "--random-ssh-port",
138
- :description => "Map a random, unused high-level port to 22 for SSH and creates a port forward for this mapping. For Isolated Networking and VPC only."
139
-
140
- option :ssh_gateway,
141
- :short => "-W GATEWAY",
142
- :long => "--ssh-gateway GATEWAY",
143
- :description => "The ssh gateway server. Connection is defined as USERNAME@HOST:PORT",
144
- :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
145
-
146
- # def bootstrap_for_node(host, user, password)
147
- def bootstrap_for_node(server, ssh_host)
148
- host = server["name"]
149
- user = config[:ssh_user]
150
- password = server["password"]
151
- Chef::Log.debug("Bootstrap host: #{host}")
152
- Chef::Log.debug("Bootstrap user: #{user}")
153
- Chef::Log.debug("Bootstrap pass: #{password}")
154
- bootstrap = Chef::Knife::Bootstrap.new
155
- bootstrap.name_args = [ssh_host]
156
- bootstrap.config[:run_list] = config[:run_list]
157
- bootstrap.config[:ssh_user] = user
158
- bootstrap.config[:ssh_password] = password
159
- bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
160
- bootstrap.config[:identity_file] = locate_config_value(:identity_file)
161
- bootstrap.config[:chef_node_name] = config[:server_display_name] if config[:server_display_name]
162
- bootstrap.config[:prerelease] = config[:prerelease]
163
- bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
164
- bootstrap.config[:distro] = locate_config_value(:distro)
165
- bootstrap.config[:use_sudo] = true
166
- bootstrap.config[:template_file] = locate_config_value(:template_file)
167
- bootstrap.config[:environment] = config[:environment]
168
- # may be needed for vpc_mode
169
- bootstrap.config[:no_host_key_verify] = config[:no_host_key_verify]
170
- begin
171
- bootstrap
172
- rescue
173
- sleep @initial_sleep_delay
174
- retry
175
- end
176
- end
177
-
178
- def check_port_available(public_port, ipaddressid)
179
- Chef::Log.debug("Checking if port #{public_port} is available.")
180
- pubport = public_port.to_i
181
- port_forward_rules_query = connection.list_port_forwarding_rules({'ipaddressid' => ipaddressid })
182
- port_rules = port_forward_rules_query['listportforwardingrulesresponse']['portforwardingrule']
183
- is_available = true
184
- some_possible_rules = port_rules.select { |rule| rule['publicport'].to_i <= pubport }
185
- possible_rules = some_possible_rules.select { |rule| rule['publicendport'].to_i >= pubport }
186
- possible_rules.each do |rule|
187
- startport = rule['publicport'].to_i
188
- endport = rule['publicendport'].to_i
189
- Chef::Log.debug("Determining if #{pubport} is between #{startport} and #{endport}.")
190
- if (endport != startport)
191
- if pubport.between?(startport, endport)
192
- is_available = false
193
- else
194
- is_available = true
195
- end
196
- else
197
- if (pubport == startport)
198
- is_available = false
199
- else
200
- is_available = true
201
- end
202
- end
203
- end
204
- return is_available
205
- end
206
-
207
- def add_port_forward(public_start_port, public_end_port, server_id, ipaddressid, privateport)
208
- pfwdops = {}
209
- pfwdops['ipaddressid'] = ipaddressid
210
- pfwdops['privateport'] = privateport
211
- pfwdops['protocol'] = "TCP"
212
- pfwdops['virtualmachineid'] = server_id
213
- pfwdops['openfirewall'] = "true"
214
- pfwdops['publicport'] = public_start_port
215
- pfwdops['publicendport'] = public_end_port
216
- rule_create_job = connection.create_port_forwarding_rule(pfwdops)
217
- print "#{ui.color("Creating port forwarding rule.", :cyan)}"
218
- while (@connection.query_async_job_result({'jobid' => rule_create_job['createportforwardingruleresponse']['jobid']})['queryasyncjobresultresponse'].fetch('jobstatus') == 0)
219
- print("#{ui.color(".", :cyan)}")
220
- sleep 2
221
- end
222
- print("\n")
223
- end
224
-
225
- def create_server_def
226
- server_def = {
227
- "templateid" => locate_config_value(:cloudstack_templateid),
228
- "serviceofferingid" => locate_config_value(:cloudstack_serviceid),
229
- "zoneid" => locate_config_value(:cloudstack_zoneid)
230
- }
231
-
232
- if locate_config_value(:server_display_name) != nil
233
- server_def["displayname"] = locate_config_value(:server_display_name)
234
- end
235
-
236
- if locate_config_value(:host_name) != nil
237
- server_def["name"] = locate_config_value(:host_name)
238
- end
239
-
240
- network_ids = []
241
- if locate_config_value(:cloudstack_networkids) != []
242
- cs_networkids = locate_config_value(:cloudstack_networkids)
243
- cs_networkids.each do |id|
244
- network_ids.push(id)
245
- end
246
- server_def["networkids"] = network_ids
247
- end
248
-
249
- security_groups = []
250
- if locate_config_value(:cloudstack_groupids) != []
251
- cs_groupids = locate_config_value(:cloudstack_groupids)
252
- cs_groupids.each do |id|
253
- security_groups.push(id)
254
- end
255
- server_def["securitygroupids"] = security_groups
256
- elsif locate_config_value(:cloudstack_groupnames) != []
257
- cs_groupnames = locate_config_value(:cloudstack_groupnames)
258
- cs_groupnames.each do |name|
259
- security_groups.push(name)
260
- end
261
- server_def["securitygroupnames"] = security_groups
262
- end
263
-
264
- if locate_config_value(:keypair) != nil
265
- server_def["keypair"] = locate_config_value(:keypair)
266
- end
267
-
268
- if locate_config_value(:diskoffering) != nil
269
- server_def["diskofferingid"] = locate_config_value(:diskoffering)
270
- end
271
-
272
- if locate_config_value(:size) != nil
273
- server_def["size"] = locate_config_value(:size)
274
- end
275
-
276
- server_def
277
- end
278
-
279
- def knife_ssh
280
- ssh = Chef::Knife::Ssh.new
281
- ssh.ui = ui
282
- ssh.name_args = [ @primary_ip, ssh_command ]
283
- ssh.config[:ssh_user] = Chef::Config[:knife][:ssh_user] || config[:ssh_user]
284
- ssh.config[:ssh_password] = config[:ssh_password]
285
- ssh.config[:ssh_port] = Chef::Config[:knife][:ssh_port] || config[:ssh_port]
286
- ssh.config[:ssh_gateway] = Chef::Config[:knife][:ssh_gateway] || config[:ssh_gateway]
287
- ssh.config[:forward_agent] = Chef::Config[:knife][:forward_agent] || config[:forward_agent]
288
- ssh.config[:identity_file] = Chef::Config[:knife][:identity_file] || config[:identity_file]
289
- ssh.config[:manual] = true
290
- ssh.config[:host_key_verify] = Chef::Config[:knife][:host_key_verify] || config[:host_key_verify]
291
- ssh.config[:on_error] = :raise
292
- Chef::Log.debug("SSH User: #{ssh.config[:ssh_user]}")
293
- Chef::Log.debug("SSH Password: #{ssh.config[:ssh_password]}")
294
- Chef::Log.debug("SSH Port: #{ssh.config[:ssh_port]}")
295
- Chef::Log.debug("SSH Gateway: #{ssh.config[:ssh_gateway]}")
296
- Chef::Log.debug("SSH Identity File: #{ssh.config[:identity_file]}")
297
- ssh
298
- end
299
-
300
- def find_template(template=nil)
301
- # Are we bootstrapping using an already shipped template?
302
- if config[:template_file]
303
- bootstrap_files = config[:template_file]
304
- else
305
- bootstrap_files = []
306
- bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
307
- bootstrap_files << File.join(Knife.chef_config_dir, "bootstrap", "#{config[:distro]}.erb") if Knife.chef_config_dir
308
- bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb") if ENV['HOME']
309
- bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
310
- bootstrap_files.flatten!
311
- end
312
-
313
- template = Array(bootstrap_files).find do |bootstrap_template|
314
- Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
315
- File.exists?(bootstrap_template)
316
- end
317
-
318
- unless template
319
- ui.info("Can not find bootstrap definition for #{config[:distro]}")
320
- raise Errno::ENOENT
321
- end
322
-
323
- Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
324
-
325
- template
326
- end
327
-
328
- def render_template(template=nil)
329
- context = Knife::Core::BootstrapContext.new(config, config[:run_list], Chef::Config)
330
- Erubis::Eruby.new(template).evaluate(context)
331
- end
332
-
333
- def read_template
334
- IO.read(@template_file).chomp
335
- end
336
-
337
- def knife_ssh_with_password_auth
338
- ssh = knife_ssh
339
- ssh.config[:identity_file] = nil
340
- Chef::Log.debug("Private Key failed or not specified. Trying password of #{ssh.get_password}")
341
- ssh.config[:ssh_password] = ssh.get_password
342
- ssh
343
- end
344
-
345
- def ssh_command
346
- command = render_template(read_template)
347
-
348
- if config[:use_sudo]
349
- command = config[:use_sudo_password] ? "echo #{config[:ssh_password]} | sudo -S #{command}" : "sudo #{command}"
350
- end
351
-
352
- command
353
- end
354
-
355
- def run
356
- $stdout.sync = true
357
- options = create_server_def
358
- Chef::Log.debug("Options: #{options} \n")
359
-
360
- @initial_sleep_delay = 10
361
- @sshport = 22
362
-
363
- config[:host_key_verify] = false
364
-
365
- if locate_config_value(:ssh_port) != nil
366
- @sshport = locate_config_value(:ssh_port).to_i
367
- end
368
-
369
- serverdeploy = connection.deploy_virtual_machine(options)
370
- jobid = serverdeploy['deployvirtualmachineresponse'].fetch('jobid')
371
-
372
- server_start = connection.query_async_job_result('jobid'=>jobid)
373
-
374
- Chef::Log.debug("Job ID: #{jobid} \n")
375
-
376
- print "#{ui.color("Waiting for server", :magenta)}"
377
- while server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 0
378
- print "#{ui.color(".", :magenta)}"
379
- sleep @initial_sleep_delay
380
- server_start = connection.query_async_job_result('jobid'=>jobid)
381
- Chef::Log.debug("Server_Start: #{server_start} \n")
382
- end
383
- puts "\n\n"
384
-
385
- if server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 2
386
- errortext = server_start['queryasyncjobresultresponse'].fetch('jobresult').fetch('errortext')
387
- puts "#{ui.color("ERROR! Job failed with #{errortext}", :red)}"
388
- end
389
-
390
- if server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 1
391
-
392
- Chef::Log.debug("Job ID: #{jobid} \n")
393
- Chef::Log.debug("Options: #{options} \n")
394
- server_start = connection.query_async_job_result('jobid'=>jobid)
395
- Chef::Log.debug("Server_Start: #{server_start} \n")
396
-
397
- @server = server_start['queryasyncjobresultresponse']['jobresult']['virtualmachine']
398
-
399
- server_display_name = @server['displayname']
400
- server_id = @server['name']
401
- server_serviceoffering = @server['serviceofferingname']
402
- server_template = @server['templatename']
403
- if @server['password'] != nil
404
- config[:ssh_password] = @server['password']
405
- else
406
- config[:ssh_password] = locate_config_value(:ssh_password)
407
- end
408
-
409
- ssh_user = locate_config_value(:ssh_user)
410
-
411
- @primary_ip = nil
412
-
413
- if @server['nic'].size > 0
414
- @primary_ip = @server['nic'].first['ipaddress']
415
- end
416
-
417
- if locate_config_value(:random_ssh_port) != nil
418
- public_ips = connection.list_public_ip_addresses("associatednetworkid" => @server['nic'][0]['networkid'])
419
- primary_public_ip_id = public_ips['listpublicipaddressesresponse']['publicipaddress'][0]['id']
420
- @primary_ip = public_ips['listpublicipaddressesresponse']['publicipaddress'][0]['ipaddress']
421
- pubport = rand(49152..65535)
422
- while (check_port_available(pubport, primary_public_ip_id) == false)
423
- pubport = rand(49152..65535)
424
- end
425
- add_port_forward(pubport, pubport, server_id, primary_public_ip_id, @sshport)
426
- @sshport = pubport
427
- end
428
-
429
- Chef::Log.debug("Connecting over port #{@sshport}")
430
- config[:ssh_port] = @sshport
431
- config[:server_name] = @primary_ip
432
- @template_file = find_template(config[:bootstrap_template])
433
-
434
- puts "\n\n"
435
- puts "#{ui.color("Name", :cyan)}: #{server_display_name}"
436
- puts "#{ui.color("Primary IP", :cyan)}: #{@primary_ip}"
437
- puts "#{ui.color("Username", :cyan)}: #{ssh_user}"
438
- puts "#{ui.color("Password", :cyan)}: #{config[:ssh_password]}"
439
-
440
- print "#{ui.color("Waiting for SSH.", :magenta)}"
441
- if config[:ssh_gateway]
442
- Chef::Log.debug("Using SSH Gateway: #{config[:ssh_gateway]}")
443
- sleep @initial_sleep_delay
444
- print "#{ui.color(".", :magenta)}"
445
- sleep @initial_sleep_delay
446
- print "#{ui.color(".", :magenta)}"
447
- end
448
- begin
449
- knife_ssh.run
450
- rescue Net::SSH::AuthenticationFailed
451
- unless config[:ssh_password]
452
- ui.info("Failed to authenticate #{config[:ssh_user]} - trying password auth")
453
- knife_ssh_with_password_auth.run
454
- end
455
- sleep @initial_sleep_delay
456
- print "#{ui.color(".", :magenta)}"
457
- retry
458
- rescue Errno::ECONNREFUSED
459
- sleep @initial_sleep_delay
460
- print "#{ui.color(".", :magenta)}"
461
- retry
462
- rescue SocketError
463
- sleep @initial_sleep_delay
464
- print "#{ui.color(".", :magenta)}"
465
- retry
466
- rescue Errno::ETIMEDOUT
467
- sleep @initial_sleep_delay
468
- print "#{ui.color(".", :magenta)}"
469
- retry
470
- rescue Errno::EPERM
471
- sleep @initial_sleep_delay
472
- print "#{ui.color(".", :magenta)}"
473
- retry
474
- rescue Errno::EHOSTUNREACH
475
- sleep @initial_sleep_delay
476
- print "#{ui.color(".", :magenta)}"
477
- retry
478
- rescue Errno::ENETUNREACH
479
- sleep @initial_sleep_delay
480
- print "#{ui.color(".", :magenta)}"
481
- retry
482
- rescue Net::SSH::Disconnect
483
- sleep @initial_sleep_delay
484
- print "#{ui.color(".", :magenta)}"
485
- retry
486
- rescue Net::SSH::AuthenticationFailed
487
- sleep @initial_sleep_delay
488
- print "#{ui.color(".", :magenta)}"
489
- retry
490
- rescue
491
- puts caller
492
- puts $!.inspect
493
- end
494
-
495
- Chef::Log.debug("#{@server}")
496
-
497
- puts "\n"
498
- puts "#{ui.color("Instance Name", :green)}: #{server_display_name}"
499
- puts "#{ui.color("Instance ID", :green)}: #{server_id}"
500
- puts "#{ui.color("Service Offering", :green)}: #{server_serviceoffering}"
501
- puts "#{ui.color("Template", :green)}: #{server_template}"
502
- puts "#{ui.color("Public IP Address", :green)}: #{@primary_ip}"
503
- puts "#{ui.color("Port", :green)}: #{@sshport}"
504
- puts "#{ui.color("User", :green)}: #{ssh_user}"
505
- puts "#{ui.color("Password", :green)}: #{config[:ssh_password]}"
506
- puts "#{ui.color("Environment", :green)}: #{config[:environment] || '_default'}"
507
- puts "#{ui.color("Run List", :green)}: #{config[:run_list].join(', ')}"
508
- end
509
-
510
- end
511
- end
512
- end
29
+ class Knife
30
+ class CloudstackServerCreate < Knife
31
+
32
+ include Knife::CloudstackBase
33
+
34
+ banner "knife cloudstack server create -s SERVICEID -t TEMPLATEID -z ZONEID (options)"
35
+
36
+ option :cloudstack_serviceid,
37
+ :short => "-s SERVICEID",
38
+ :long => "--serviceid SERVICEID",
39
+ :description => "The CloudStack service offering ID."
40
+
41
+ option :cloudstack_templateid,
42
+ :short => "-t TEMPLATEID",
43
+ :long => "--templateid TEMPLATEID",
44
+ :description => "The CloudStack template ID for the server."
45
+
46
+ option :cloudstack_zoneid,
47
+ :short => "-Z ZONEID",
48
+ :long => "--zoneid ZONE",
49
+ :description => "The CloudStack zone ID for the server."
50
+
51
+ option :cloudstack_networkids,
52
+ :short => "-w NETWORKIDS",
53
+ :long => "--networkids NETWORKIDS",
54
+ :description => "Comma separated list of CloudStack network IDs.",
55
+ :proc => lambda { |n| n.split(/[\s,]+/) },
56
+ :default => []
57
+
58
+ option :cloudstack_groupids,
59
+ :short => "-g SECURITYGROUPIDS",
60
+ :long => "--groupids SECURITYGROUPIDS",
61
+ :description => "Comma separated list of CloudStack Security Group IDs.",
62
+ :proc => lambda { |n| n.split(/[\s,]+/) },
63
+ :default => []
64
+
65
+ option :cloudstack_groupnames,
66
+ :short => "-G SECURITYGROUPNAMES",
67
+ :long => "--groupnames SECURITYGROUPNAMES",
68
+ :description => "Comma separated list of CloudStack Security Group names. Each group name must be encapuslated in quotes if it contains whitespace.",
69
+ :proc => lambda { |n| n.split(/[\s,]+/) },
70
+ :default => []
71
+
72
+ option :distro,
73
+ :short => "-d DISTRO",
74
+ :long => "--distro DISTRO",
75
+ :description => "Bootstrap a distro using a template; default is 'chef-full'",
76
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
77
+ :default => "chef-full"
78
+
79
+ option :template_file,
80
+ :long => "--template-file TEMPLATE",
81
+ :description => "Full path to location of template to use",
82
+ :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
83
+ :default => false
84
+
85
+ option :run_list,
86
+ :short => "-r RUN_LIST",
87
+ :long => "--run-list RUN_LIST",
88
+ :description => "Comma separated list of roles/recipes to apply",
89
+ :proc => lambda { |o| o.split(/[\s,]+/) },
90
+ :default => []
91
+
92
+ option :ssh_user,
93
+ :short => "-x USERNAME",
94
+ :long => "--ssh-user USERNAME",
95
+ :description => "The ssh username",
96
+ :default => 'root'
97
+
98
+ option :ssh_password,
99
+ :short => "-P PASSWORD",
100
+ :long => "--ssh-password PASSWORD",
101
+ :description => "The ssh password"
102
+
103
+ option :identity_file,
104
+ :short => "-i PRIVATE_KEY_FILE",
105
+ :long => "--identity-file PRIVATE_KEY_FILE",
106
+ :description => "The Private key file for authenticating SSH session. --keypair option is also needed."
107
+
108
+ option :ssh_port,
109
+ :short => "-p PORT",
110
+ :long => "--ssh-port PORT",
111
+ :description => "The port which SSH should be listening on. If unspecified, will default to 22."
112
+
113
+ option :server_display_name,
114
+ :short => "-N NAME",
115
+ :long => "--display-name NAME",
116
+ :description => "The instance display name"
117
+
118
+ option :host_name,
119
+ :short => "-H NAME",
120
+ :long => "--hostname NAME",
121
+ :description => "The instance host name"
122
+
123
+ option :keypair,
124
+ :short => "-k KEYPAIR",
125
+ :long => "--keypair KEYPAIR",
126
+ :description => "The CloudStack Key Pair to use for SSH key authentication."
127
+
128
+ option :diskoffering,
129
+ :short => "-D DISKOFFERINGID",
130
+ :long => "--diskoffering DISKOFFERINGID",
131
+ :description => "Specifies either the Disk Offering ID for the ROOT disk for an ISO template, or a DATA disk."
132
+
133
+ option :size,
134
+ :long => "--size SIZE",
135
+ :description => "Specifies the arbitrary Disk Size for DATADISK volume in GB. Must be passed with custom size Disk Offering ID."
136
+
137
+ option :random_ssh_port,
138
+ :long => "--random-ssh-port",
139
+ :description => "Map a random, unused high-level port to 22 for SSH and creates a port forward for this mapping. For Isolated Networking and VPC only."
140
+
141
+ option :ssh_gateway,
142
+ :short => "-W GATEWAY",
143
+ :long => "--ssh-gateway GATEWAY",
144
+ :description => "The ssh gateway server. Connection is defined as USERNAME@HOST:PORT",
145
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
146
+
147
+ option :user_data,
148
+ :long => "--user-data USER_DATA_FILE",
149
+ :description => "The user data file to provision the instance with",
150
+ :proc => Proc.new { |m| Chef::Config[:knife][:cloudstack_user_data] = m },
151
+ :default => nil
152
+
153
+ option :keyboard,
154
+ :long => "--keyboard KEYBOARD_TYPE",
155
+ :description => "An optional keyboard device type for the virtual machine"
156
+
157
+ option :hypervisor,
158
+ :long => "--hypervisor HYPERVISOR",
159
+ :description => "the hypervisor on which to deploy the virtual machine",
160
+ :default => nil
161
+
162
+ # def bootstrap_for_node(host, user, password)
163
+ def bootstrap_for_node(server, ssh_host)
164
+ host = server["name"]
165
+ user = config[:ssh_user]
166
+ password = server["password"]
167
+ Chef::Log.debug("Bootstrap host: #{host}")
168
+ Chef::Log.debug("Bootstrap user: #{user}")
169
+ Chef::Log.debug("Bootstrap pass: #{password}")
170
+ bootstrap = Chef::Knife::Bootstrap.new
171
+ bootstrap.name_args = [ssh_host]
172
+ bootstrap.config[:run_list] = config[:run_list]
173
+ bootstrap.config[:ssh_user] = user
174
+ bootstrap.config[:ssh_password] = password
175
+ bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
176
+ bootstrap.config[:identity_file] = locate_config_value(:identity_file)
177
+ bootstrap.config[:chef_node_name] = config[:server_display_name] if config[:server_display_name]
178
+ bootstrap.config[:prerelease] = config[:prerelease]
179
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
180
+ bootstrap.config[:distro] = locate_config_value(:distro)
181
+ bootstrap.config[:use_sudo] = true
182
+ bootstrap.config[:template_file] = locate_config_value(:template_file)
183
+ bootstrap.config[:environment] = config[:environment]
184
+ # may be needed for vpc_mode
185
+ bootstrap.config[:no_host_key_verify] = config[:no_host_key_verify]
186
+ begin
187
+ bootstrap
188
+ rescue
189
+ sleep @initial_sleep_delay
190
+ retry
191
+ end
192
+ end
193
+
194
+ def check_port_available(public_port, ipaddressid)
195
+ Chef::Log.debug("Checking if port #{public_port} is available.")
196
+ pubport = public_port.to_i
197
+ port_forward_rules_query = connection.list_port_forwarding_rules({'ipaddressid' => ipaddressid })
198
+ port_rules = port_forward_rules_query['listportforwardingrulesresponse']['portforwardingrule']
199
+ is_available = true
200
+ some_possible_rules = port_rules.select { |rule| rule['publicport'].to_i <= pubport }
201
+ possible_rules = some_possible_rules.select { |rule| rule['publicendport'].to_i >= pubport }
202
+ possible_rules.each do |rule|
203
+ startport = rule['publicport'].to_i
204
+ endport = rule['publicendport'].to_i
205
+ Chef::Log.debug("Determining if #{pubport} is between #{startport} and #{endport}.")
206
+ if (endport != startport)
207
+ if pubport.between?(startport, endport)
208
+ is_available = false
209
+ else
210
+ is_available = true
211
+ end
212
+ else
213
+ if (pubport == startport)
214
+ is_available = false
215
+ else
216
+ is_available = true
217
+ end
218
+ end
219
+ end
220
+ return is_available
221
+ end
222
+
223
+ def add_port_forward(public_start_port, public_end_port, server_id, ipaddressid, privateport)
224
+ pfwdops = {}
225
+ pfwdops['ipaddressid'] = ipaddressid
226
+ pfwdops['privateport'] = privateport
227
+ pfwdops['protocol'] = "TCP"
228
+ pfwdops['virtualmachineid'] = server_id
229
+ pfwdops['openfirewall'] = "true"
230
+ pfwdops['publicport'] = public_start_port
231
+ pfwdops['publicendport'] = public_end_port
232
+ rule_create_job = connection.create_port_forwarding_rule(pfwdops)
233
+ print "#{ui.color("Creating port forwarding rule.", :cyan)}"
234
+ while (@connection.query_async_job_result({'jobid' => rule_create_job['createportforwardingruleresponse']['jobid']})['queryasyncjobresultresponse'].fetch('jobstatus') == 0)
235
+ print("#{ui.color(".", :cyan)}")
236
+ sleep 2
237
+ end
238
+ print("\n")
239
+ end
240
+
241
+ def create_server_def
242
+ server_def = {}
243
+
244
+ if locate_config_value(:server_display_name) != nil
245
+ server_def["displayname"] = locate_config_value(:server_display_name)
246
+ end
247
+
248
+ if locate_config_value(:host_name) != nil
249
+ server_def["name"] = locate_config_value(:host_name)
250
+ end
251
+
252
+ network_ids = ""
253
+ if locate_config_value(:cloudstack_networkids) != []
254
+ cs_networkids = locate_config_value(:cloudstack_networkids)
255
+ cs_networkids.join(",")
256
+ server_def["networkids"] = network_ids
257
+ end
258
+
259
+ security_groups = ""
260
+ if locate_config_value(:cloudstack_groupids) != []
261
+ cs_groupids = locate_config_value(:cloudstack_groupids)
262
+ security_groups = cs_groupids.join(",")
263
+ server_def["securitygroupids"] = security_groups
264
+ elsif locate_config_value(:cloudstack_groupnames) != []
265
+ cs_groupnames = locate_config_value(:cloudstack_groupnames)
266
+ security_groups = cs_groupnames.join(",")
267
+ server_def["securitygroupnames"] = security_groups
268
+ end
269
+
270
+ if locate_config_value(:keypair) != nil
271
+ server_def["keypair"] = locate_config_value(:keypair)
272
+ end
273
+
274
+ if locate_config_value(:diskoffering) != nil
275
+ server_def["diskofferingid"] = locate_config_value(:diskoffering)
276
+ end
277
+
278
+ if locate_config_value(:size) != nil
279
+ server_def["size"] = locate_config_value(:size)
280
+ end
281
+
282
+ if locate_config_value(:hypervisor) != nil
283
+ server_def["hypervisor"] = locate_config_value(:hypervisor)
284
+ end
285
+
286
+ if locate_config_value(:cloudstack_user_data) != nil
287
+ require 'base64'
288
+ begin
289
+ server_def["userdata"] = Base64.strict_encode64(File.read(Chef::Config[:knife][:cloudstack_user_data]))
290
+ rescue
291
+ ui.warn("Cannot read #{Chef::Config[:knife][:cloudstack_user_data]}: #{$!.inspect}. Ignoring")
292
+ end
293
+ end
294
+ if locate_config_value(:keyboard) != nil
295
+ server_def["keyboard"] = locate_config_value(:keyboard)
296
+ end
297
+
298
+ server_def
299
+ end
300
+
301
+ def knife_ssh
302
+ ssh = Chef::Knife::Ssh.new
303
+ ssh.ui = ui
304
+ ssh.name_args = [ @primary_ip, ssh_command ]
305
+ ssh.config[:ssh_user] = Chef::Config[:knife][:ssh_user] || config[:ssh_user]
306
+ ssh.config[:ssh_password] = config[:ssh_password]
307
+ ssh.config[:ssh_port] = Chef::Config[:knife][:ssh_port] || config[:ssh_port]
308
+ ssh.config[:ssh_gateway] = Chef::Config[:knife][:ssh_gateway] || config[:ssh_gateway]
309
+ ssh.config[:forward_agent] = Chef::Config[:knife][:forward_agent] || config[:forward_agent]
310
+ ssh.config[:identity_file] = Chef::Config[:knife][:identity_file] || config[:identity_file]
311
+ ssh.config[:manual] = true
312
+ ssh.config[:host_key_verify] = Chef::Config[:knife][:host_key_verify] || config[:host_key_verify]
313
+ ssh.config[:on_error] = :raise
314
+ Chef::Log.debug("SSH User: #{ssh.config[:ssh_user]}")
315
+ Chef::Log.debug("SSH Password: #{ssh.config[:ssh_password]}")
316
+ Chef::Log.debug("SSH Port: #{ssh.config[:ssh_port]}")
317
+ Chef::Log.debug("SSH Gateway: #{ssh.config[:ssh_gateway]}")
318
+ Chef::Log.debug("SSH Identity File: #{ssh.config[:identity_file]}")
319
+ ssh
320
+ end
321
+
322
+ def find_template(template=nil)
323
+ # Are we bootstrapping using an already shipped template?
324
+ if config[:template_file]
325
+ bootstrap_files = config[:template_file]
326
+ else
327
+ bootstrap_files = []
328
+ bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
329
+ bootstrap_files << File.join(Knife.chef_config_dir, "bootstrap", "#{config[:distro]}.erb") if Knife.chef_config_dir
330
+ bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb") if ENV['HOME']
331
+ bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
332
+ bootstrap_files.flatten!
333
+ end
334
+
335
+ template = Array(bootstrap_files).find do |bootstrap_template|
336
+ Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
337
+ File.exists?(bootstrap_template)
338
+ end
339
+
340
+ unless template
341
+ ui.info("Can not find bootstrap definition for #{config[:distro]}")
342
+ raise Errno::ENOENT
343
+ end
344
+
345
+ Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
346
+
347
+ template
348
+ end
349
+
350
+ def render_template(template=nil)
351
+ context = Knife::Core::BootstrapContext.new(config, config[:run_list], Chef::Config)
352
+ Erubis::Eruby.new(template).evaluate(context)
353
+ end
354
+
355
+ def read_template
356
+ IO.read(@template_file).chomp
357
+ end
358
+
359
+ def knife_ssh_with_password_auth
360
+ ssh = knife_ssh
361
+ ssh.config[:identity_file] = nil
362
+ Chef::Log.debug("Private Key failed or not specified. Trying password of #{ssh.get_password}")
363
+ ssh.config[:ssh_password] = ssh.get_password
364
+ ssh
365
+ end
366
+
367
+ def ssh_command
368
+ command = render_template(read_template)
369
+
370
+ if config[:use_sudo]
371
+ command = config[:use_sudo_password] ? "echo #{config[:ssh_password]} | sudo -S #{command}" : "sudo #{command}"
372
+ end
373
+
374
+ command
375
+ end
376
+
377
+ def run
378
+ $stdout.sync = true
379
+ options = create_server_def
380
+ Chef::Log.debug("Options: #{options} \n")
381
+
382
+ @initial_sleep_delay = 10
383
+ @sshport = 22
384
+
385
+ config[:host_key_verify] = false
386
+
387
+ if locate_config_value(:ssh_port) != nil
388
+ @sshport = locate_config_value(:ssh_port).to_i
389
+ end
390
+
391
+ # binding.pry
392
+ serverdeploy = connection.deploy_virtual_machine(locate_config_value(:cloudstack_serviceid),
393
+ locate_config_value(:cloudstack_templateid), locate_config_value(:cloudstack_zoneid), options)
394
+
395
+ jobid = serverdeploy['deployvirtualmachineresponse'].fetch('jobid')
396
+
397
+ server_start = connection.query_async_job_result(jobid)
398
+
399
+ Chef::Log.debug("Job ID: #{jobid} \n")
400
+
401
+ print "#{ui.color("Waiting for server", :magenta)}"
402
+ while server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 0
403
+ print "#{ui.color(".", :magenta)}"
404
+ sleep @initial_sleep_delay
405
+ server_start = connection.query_async_job_result(jobid)
406
+ Chef::Log.debug("Server_Start: #{server_start} \n")
407
+ end
408
+ puts "\n\n"
409
+
410
+ if server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 2
411
+ errortext = server_start['queryasyncjobresultresponse'].fetch('jobresult').fetch('errortext')
412
+ puts "#{ui.color("ERROR! Job failed with #{errortext}", :red)}"
413
+ end
414
+
415
+ if server_start['queryasyncjobresultresponse'].fetch('jobstatus') == 1
416
+
417
+ Chef::Log.debug("Job ID: #{jobid} \n")
418
+ Chef::Log.debug("Options: #{options} \n")
419
+ server_start = connection.query_async_job_result(jobid)
420
+ Chef::Log.debug("Server_Start: #{server_start} \n")
421
+
422
+ @server = server_start['queryasyncjobresultresponse']['jobresult']['virtualmachine']
423
+
424
+ server_display_name = @server['displayname']
425
+ server_id = @server['name']
426
+ server_serviceoffering = @server['serviceofferingname']
427
+ server_template = @server['templatename']
428
+ if @server['password'] != nil
429
+ config[:ssh_password] = @server['password']
430
+ else
431
+ config[:ssh_password] = locate_config_value(:ssh_password)
432
+ end
433
+
434
+ ssh_user = locate_config_value(:ssh_user)
435
+
436
+ @primary_ip = nil
437
+
438
+ if @server['nic'].size > 0
439
+ @primary_ip = @server['nic'].first['ipaddress']
440
+ end
441
+
442
+ if locate_config_value(:random_ssh_port) != nil
443
+ public_ips = connection.list_public_ip_addresses("associatednetworkid" => @server['nic'][0]['networkid'])
444
+ primary_public_ip_id = public_ips['listpublicipaddressesresponse']['publicipaddress'][0]['id']
445
+ @primary_ip = public_ips['listpublicipaddressesresponse']['publicipaddress'][0]['ipaddress']
446
+ pubport = rand(49152..65535)
447
+ while (check_port_available(pubport, primary_public_ip_id) == false)
448
+ pubport = rand(49152..65535)
449
+ end
450
+ add_port_forward(pubport, pubport, server_id, primary_public_ip_id, @sshport)
451
+ @sshport = pubport
452
+ end
453
+
454
+ Chef::Log.debug("Connecting over port #{@sshport}")
455
+ config[:ssh_port] = @sshport
456
+ config[:server_name] = @primary_ip
457
+ @template_file = find_template(config[:bootstrap_template])
458
+
459
+ puts "\n\n"
460
+ puts "#{ui.color("Name", :cyan)}: #{server_display_name}"
461
+ puts "#{ui.color("Primary IP", :cyan)}: #{@primary_ip}"
462
+ puts "#{ui.color("Username", :cyan)}: #{ssh_user}"
463
+ puts "#{ui.color("Password", :cyan)}: #{config[:ssh_password]}"
464
+
465
+ print "#{ui.color("Waiting for SSH.", :magenta)}"
466
+ if config[:ssh_gateway]
467
+ Chef::Log.debug("Using SSH Gateway: #{config[:ssh_gateway]}")
468
+ sleep @initial_sleep_delay
469
+ print "#{ui.color(".", :magenta)}"
470
+ sleep @initial_sleep_delay
471
+ print "#{ui.color(".", :magenta)}"
472
+ end
473
+ begin
474
+ knife_ssh.run
475
+ rescue Net::SSH::AuthenticationFailed
476
+ unless config[:ssh_password]
477
+ ui.info("Failed to authenticate #{config[:ssh_user]} - trying password auth")
478
+ knife_ssh_with_password_auth.run
479
+ end
480
+ sleep @initial_sleep_delay
481
+ print "#{ui.color(".", :magenta)}"
482
+ retry
483
+ rescue Errno::ECONNREFUSED
484
+ sleep @initial_sleep_delay
485
+ print "#{ui.color(".", :magenta)}"
486
+ retry
487
+ rescue SocketError
488
+ sleep @initial_sleep_delay
489
+ print "#{ui.color(".", :magenta)}"
490
+ retry
491
+ rescue Errno::ETIMEDOUT
492
+ sleep @initial_sleep_delay
493
+ print "#{ui.color(".", :magenta)}"
494
+ retry
495
+ rescue Errno::EPERM
496
+ sleep @initial_sleep_delay
497
+ print "#{ui.color(".", :magenta)}"
498
+ retry
499
+ rescue Errno::EHOSTUNREACH
500
+ sleep @initial_sleep_delay
501
+ print "#{ui.color(".", :magenta)}"
502
+ retry
503
+ rescue Errno::ENETUNREACH
504
+ sleep @initial_sleep_delay
505
+ print "#{ui.color(".", :magenta)}"
506
+ retry
507
+ rescue Net::SSH::Disconnect
508
+ sleep @initial_sleep_delay
509
+ print "#{ui.color(".", :magenta)}"
510
+ retry
511
+ rescue Net::SSH::AuthenticationFailed
512
+ sleep @initial_sleep_delay
513
+ print "#{ui.color(".", :magenta)}"
514
+ retry
515
+ rescue
516
+ puts caller
517
+ puts $!.inspect
518
+ end
519
+
520
+ Chef::Log.debug("#{@server}")
521
+
522
+ puts "\n"
523
+ puts "#{ui.color("Instance Name", :green)}: #{server_display_name}"
524
+ puts "#{ui.color("Instance ID", :green)}: #{server_id}"
525
+ puts "#{ui.color("Service Offering", :green)}: #{server_serviceoffering}"
526
+ puts "#{ui.color("Template", :green)}: #{server_template}"
527
+ puts "#{ui.color("Public IP Address", :green)}: #{@primary_ip}"
528
+ puts "#{ui.color("Port", :green)}: #{@sshport}"
529
+ puts "#{ui.color("User", :green)}: #{ssh_user}"
530
+ puts "#{ui.color("Password", :green)}: #{config[:ssh_password]}"
531
+ puts "#{ui.color("Environment", :green)}: #{config[:environment] || '_default'}"
532
+ puts "#{ui.color("Run List", :green)}: #{config[:run_list].join(', ')}"
533
+ end
534
+
535
+ end
536
+ end
537
+ end
513
538
  end
@@ -40,7 +40,7 @@ class Chef
40
40
  puts "#{ui.color("Public IP", :red)}: #{instance_ip}"
41
41
  puts "\n"
42
42
  confirm("#{ui.color("Do you really want to delete this server", :red)}")
43
- connection.destroy_virtual_machine('id' => real_instance_id)
43
+ connection.destroy_virtual_machine(instance_id)
44
44
  ui.warn("Deleted server #{instance_name}")
45
45
  end
46
46
  end
@@ -40,7 +40,7 @@ class Chef
40
40
  puts "#{ui.color("Public IP", :red)}: #{instance_ip}"
41
41
  puts "\n"
42
42
  confirm("#{ui.color("Do you really want to destroy this server", :red)}")
43
- connection.destroy_virtual_machine('id' => real_instance_id)
43
+ connection.destroy_virtual_machine(instance_id)
44
44
  ui.warn("Destroyed server #{instance_name}")
45
45
  end
46
46
  end
@@ -106,7 +106,7 @@ class Chef
106
106
  hypervisor = locate_config_value(:hypervisor)
107
107
  templateid = locate_config_value(:templateid)
108
108
 
109
- settings = connection.list_templates('templatefilter' => filter)
109
+ settings = connection.list_templates(filter)
110
110
  if response = settings['listtemplatesresponse']
111
111
  Chef::Log.debug("Response: #{response}")
112
112
  if templates = response['template']
@@ -1,6 +1,6 @@
1
1
  module Knife
2
2
  module Cloudstack
3
- VERSION = "0.5.2"
3
+ VERSION = "0.6.0"
4
4
  MAJOR, MINOR, TINY = VERSION.split('.')
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-cloudstack-fog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chirag Jog (chiragjog)
@@ -12,48 +12,60 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2014-05-22 00:00:00.000000000 Z
15
+ date: 2014-08-18 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: fog
19
19
  requirement: !ruby/object:Gem::Requirement
20
20
  requirements:
21
+ - - "~>"
22
+ - !ruby/object:Gem::Version
23
+ version: '1.23'
21
24
  - - ">="
22
25
  - !ruby/object:Gem::Version
23
- version: 1.10.0
26
+ version: 1.23.0
24
27
  type: :runtime
25
28
  prerelease: false
26
29
  version_requirements: !ruby/object:Gem::Requirement
27
30
  requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.23'
28
34
  - - ">="
29
35
  - !ruby/object:Gem::Version
30
- version: 1.10.0
36
+ version: 1.23.0
31
37
  - !ruby/object:Gem::Dependency
32
38
  name: chef
33
39
  requirement: !ruby/object:Gem::Requirement
34
40
  requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '11.12'
35
44
  - - ">="
36
45
  - !ruby/object:Gem::Version
37
- version: 11.2.0
46
+ version: 11.12.8
38
47
  type: :runtime
39
48
  prerelease: false
40
49
  version_requirements: !ruby/object:Gem::Requirement
41
50
  requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '11.12'
42
54
  - - ">="
43
55
  - !ruby/object:Gem::Version
44
- version: 11.2.0
56
+ version: 11.12.8
45
57
  - !ruby/object:Gem::Dependency
46
58
  name: rake
47
59
  requirement: !ruby/object:Gem::Requirement
48
60
  requirements:
49
- - - ">="
61
+ - - "~>"
50
62
  - !ruby/object:Gem::Version
51
63
  version: '0'
52
64
  type: :runtime
53
65
  prerelease: false
54
66
  version_requirements: !ruby/object:Gem::Requirement
55
67
  requirements:
56
- - - ">="
68
+ - - "~>"
57
69
  - !ruby/object:Gem::Version
58
70
  version: '0'
59
71
  description: Support for the Chef Knife command, leveraging FOG, for the Apache CloudStack
@@ -118,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
130
  version: '0'
119
131
  requirements: []
120
132
  rubyforge_project:
121
- rubygems_version: 2.2.2
133
+ rubygems_version: 2.2.1
122
134
  signing_key:
123
135
  specification_version: 4
124
136
  summary: Cloudstack Compute Support for Chef's Knife Command