knife-cloudstack-fog 0.5.2 → 0.6.0

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