knife-cloudstack 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ # Copyright:: Copyright (c) 2013
2
+ # License:: Apache License, Version 2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'chef/knife/cs_base'
18
+
19
+ module KnifeCloudstack
20
+ class CsKeypairDelete < Chef::Knife
21
+
22
+ include Chef::Knife::KnifeCloudstackBase
23
+
24
+ deps do
25
+ require 'knife-cloudstack/connection'
26
+ Chef::Knife.load_deps
27
+ end
28
+
29
+ banner "knife cs keypair delete KEY_NAME (options)"
30
+
31
+ option :name,
32
+ :long => "--name NAME",
33
+ :description => "Specify the ssh keypair name"
34
+
35
+ def run
36
+ validate_base_options
37
+
38
+ Chef::Log.debug("Validate keypair name")
39
+ keypairname = locate_config_value(:name) || @name_args.first
40
+ unless /^[a-zA-Z0-9][a-zA-Z0-9\-\_]*$/.match(keypairname) then
41
+ ui.error "Invalid keypairname. Please specify a short name for the keypair"
42
+ exit 1
43
+ end
44
+
45
+ params = {
46
+ 'command' => 'deleteSSHKeyPair',
47
+ 'name' => keypairname,
48
+ }
49
+
50
+ json = connection.send_request(params)
51
+
52
+ unless json['success'] == 'true' then
53
+ ui.error("Unable to delete SSH Keypair")
54
+ exit 1
55
+ end
56
+ print "#{ui.color("Deleted the SSH Keypair: #{keypairname}", :magenta)}\n"
57
+ end
58
+
59
+ end # class
60
+ end
@@ -0,0 +1,83 @@
1
+ # Copyright:: Copyright (c) 2011 Edmunds, Inc.
2
+ # Copyright:: Copyright (c) 2013 Sander Botman.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/cs_base'
19
+ require 'chef/knife/cs_baselist'
20
+
21
+ module KnifeCloudstack
22
+ class CsKeypairList < Chef::Knife
23
+
24
+ include Chef::Knife::KnifeCloudstackBase
25
+ include Chef::Knife::KnifeCloudstackBaseList
26
+
27
+ deps do
28
+ require 'chef/knife'
29
+ require 'knife-cloudstack/connection'
30
+ Chef::Knife.load_deps
31
+ end
32
+
33
+ banner "knife cs keypair list (options)"
34
+
35
+ def run
36
+ validate_base_options
37
+
38
+ object_list = []
39
+ object_list << ui.color('Index', :bold) if locate_config_value(:index)
40
+
41
+ if locate_config_value(:fields)
42
+ locate_config_value(:fields).split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
43
+ else
44
+ [
45
+ ui.color('Name', :bold),
46
+ ui.color('Fingerprint', :bold),
47
+ ].each { |field| object_list << field }
48
+ end
49
+
50
+ columns = object_list.count
51
+ object_list = [] if locate_config_value(:noheader)
52
+
53
+ connection_result = connection.list_object(
54
+ "listSSHKeyPairs",
55
+ "sshkeypair",
56
+ locate_config_value(:filter),
57
+ false,
58
+ locate_config_value(:keyword),
59
+ locate_config_value(:name)
60
+ )
61
+
62
+ output_format(connection_result)
63
+
64
+ index_num = 0
65
+ connection_result.each do |r|
66
+ if locate_config_value(:index)
67
+ index_num += 1
68
+ object_list << index_num.to_s
69
+ end
70
+
71
+ if locate_config_value(:fields)
72
+ locate_config_value(:fields).downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'N/A') }
73
+ else
74
+ object_list << r['name'].to_s
75
+ object_list << r['fingerprint'].to_s
76
+ end
77
+ end
78
+ puts ui.list(object_list, :uneven_columns_across, columns)
79
+ list_object_fields(connection_result) if locate_config_value(:fieldlist)
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,88 @@
1
+ #
2
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
3
+ # Copyright:: Copyright (c) 2013 Sander Botman.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'chef/knife/cs_base'
20
+ require 'chef/knife/cs_baselist'
21
+
22
+ module KnifeCloudstack
23
+ class CsPublicipList < Chef::Knife
24
+
25
+ include Chef::Knife::KnifeCloudstackBase
26
+ include Chef::Knife::KnifeCloudstackBaseList
27
+
28
+ deps do
29
+ require 'knife-cloudstack/connection'
30
+ Chef::Knife.load_deps
31
+ end
32
+
33
+ banner "knife cs publicip list (options)"
34
+
35
+ option :listall,
36
+ :long => "--listall",
37
+ :description => "List all public ip addresses",
38
+ :boolean => true
39
+
40
+ def run
41
+ validate_base_options
42
+
43
+ if locate_config_value(:fields)
44
+ object_list = []
45
+ locate_config_value(:fields).split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
46
+ else
47
+ object_list = [
48
+ ui.color('IP', :bold),
49
+ ui.color('Account', :bold),
50
+ ui.color('Domain', :bold),
51
+ ui.color('Zone', :bold),
52
+ ui.color('State', :bold),
53
+ ui.color('Allocated', :bold)
54
+ ]
55
+ end
56
+
57
+ columns = object_list.count
58
+ object_list = [] if locate_config_value(:noheader)
59
+
60
+ connection_result = connection.list_object(
61
+ "listPublicIpAddresses",
62
+ "publicipaddress",
63
+ locate_config_value(:filter),
64
+ locate_config_value(:listall),
65
+ locate_config_value(:keyword),
66
+ locate_config_value(:name)
67
+ )
68
+
69
+ output_format(connection_result)
70
+
71
+ connection_result.each do |r|
72
+ if locate_config_value(:fields)
73
+ locate_config_value(:fields).downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'N/A') }
74
+ else
75
+ object_list << r['ipaddress'].to_s
76
+ object_list << r['account'].to_s
77
+ object_list << r['domain'].to_s
78
+ object_list << r['zonename'].to_s
79
+ object_list << r['state'].to_s
80
+ object_list << r['allocated'].to_s
81
+ end
82
+ end
83
+ puts ui.list(object_list, :uneven_columns_across, columns)
84
+ list_object_fields(connection_result) if locate_config_value(:fieldlist)
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,134 @@
1
+ #
2
+ # Author:: Ryan Holmes (<rholmes@edmunds.com>)
3
+ # Author:: Sander Botman (<sbotman@schubergphilis.com>)
4
+ # Author:: Sebastien Goasguen (<runseb@gmail.com>)
5
+ # Copyright:: Copyright (c) 2011 Edmunds, Inc.
6
+ # Copyright:: Copyright (c) 2013 Sander Botman.
7
+ # License:: Apache License, Version 2.0
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+
22
+ require 'chef/knife/cs_base'
23
+ require 'chef/knife/cs_baselist'
24
+
25
+ module KnifeCloudstack
26
+ class CsSecuritygroupList < Chef::Knife
27
+
28
+ include Chef::Knife::KnifeCloudstackBase
29
+ include Chef::Knife::KnifeCloudstackBaseList
30
+
31
+ deps do
32
+ require 'chef/knife'
33
+ require 'knife-cloudstack/connection'
34
+ Chef::Knife.load_deps
35
+ end
36
+
37
+ banner "knife cs securitygroup list (options)"
38
+
39
+ option :name,
40
+ :long => "--name NAME",
41
+ :description => "Specify security group to list"
42
+
43
+ option :keyword,
44
+ :long => "--keyword NAME",
45
+ :description => "Specify part of servicename to list"
46
+
47
+ option :index,
48
+ :long => "--index",
49
+ :description => "Add index numbers to the output",
50
+ :boolean => true
51
+
52
+ def run
53
+ validate_base_options
54
+
55
+ object_list = []
56
+ object_list << ui.color('Index', :bold) if locate_config_value(:index)
57
+
58
+ if locate_config_value(:fields)
59
+ locate_config_value(:fields).split(',').each { |n| object_list << ui.color(("#{n}").strip, :bold) }
60
+ elsif locate_config_value(:keyword)
61
+ [
62
+ ui.color('Name', :bold),
63
+ ui.color('Description', :bold),
64
+ ui.color('Account', :bold),
65
+ ui.color('IngressRules', :bold)
66
+ ].each { |field| object_list << field }
67
+ else
68
+ [
69
+ ui.color('Name', :bold),
70
+ ui.color('Description', :bold),
71
+ ui.color('Account', :bold)
72
+ ].each { |field| object_list << field }
73
+ end
74
+
75
+ columns = object_list.count
76
+ object_list = [] if locate_config_value(:noheader)
77
+
78
+ connection_result = connection.list_object(
79
+ "listSecurityGroups",
80
+ "securitygroup",
81
+ locate_config_value(:filter),
82
+ false,
83
+ locate_config_value(:keyword),
84
+ locate_config_value(:name)
85
+ )
86
+
87
+ output_format(connection_result)
88
+
89
+ if locate_config_value(:keyword)
90
+ index_num = 0
91
+ connection_result['ingressrule'].each do |r|
92
+ if r.nil?
93
+ else
94
+ if locate_config_value(:index)
95
+ index_num += 1
96
+ object_list << index_num.to_s
97
+ end
98
+
99
+ if locate_config_value(:fields)
100
+ locate_config_value(:fields).downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'N/A') }
101
+ else
102
+ object_list << connection_result['name'].to_s
103
+ object_list << connection_result['description'].to_s
104
+ object_list << connection_result['account'].to_s
105
+ object_list << r.to_s
106
+ end
107
+ end
108
+ end
109
+
110
+ else
111
+ index_num = 0
112
+ connection_result.each do |r|
113
+ if locate_config_value(:index)
114
+ index_num += 1
115
+ object_list << index_num.to_s
116
+ end
117
+
118
+ if locate_config_value(:fields)
119
+ locate_config_value(:fields).downcase.split(',').each { |n| object_list << ((r[("#{n}").strip]).to_s || 'N/A') }
120
+ else
121
+ object_list << r['name'].to_s
122
+ object_list << r['description'].to_s
123
+ object_list << r['account'].to_s
124
+ end
125
+ end
126
+
127
+ end
128
+
129
+ puts ui.list(object_list, :uneven_columns_across, columns)
130
+ list_object_fields(connection_result) if locate_config_value(:fieldlist)
131
+ end
132
+
133
+ end
134
+ end
@@ -1,6 +1,7 @@
1
1
  #
2
2
  # Author:: Ryan Holmes (<rholmes@edmunds.com>)
3
3
  # Author:: Sander Botman (<sbotman@schubergphilis.com>)
4
+ # Author:: Sander van Harmelen (<svanharmelen@schubergphilis.com>)
4
5
  # Copyright:: Copyright (c) 2011 Edmunds, Inc.
5
6
  # Copyright:: Copyright (c) 2013 Sander Botman.
6
7
  # License:: Apache License, Version 2.0
@@ -81,6 +82,12 @@ module KnifeCloudstack
81
82
  :proc => lambda { |n| n.split(',').map {|sn| sn.strip}} ,
82
83
  :default => []
83
84
 
85
+ option :cloudstack_disk,
86
+ :short => "-D DISK",
87
+ :long => "--disk DISK",
88
+ :description => "The CloudStack disk offering name",
89
+ :proc => Proc.new { |d| Chef::Config[:knife][:cloudstack_disk] = d }
90
+
84
91
  option :cloudstack_hypervisor,
85
92
  :long => '--cloudstack-hypervisor HYPERVISOR',
86
93
  :description => "The CloudStack hypervisor type for the server"
@@ -169,6 +176,11 @@ module KnifeCloudstack
169
176
  :proc => lambda { |o| o.split(/[\s,]+/) },
170
177
  :default => []
171
178
 
179
+ option :keypair,
180
+ :long => "--keypair NAME",
181
+ :description => "Name of the keypair that should be used to create the vm",
182
+ :default => false
183
+
172
184
  option :static_nat,
173
185
  :long => '--static-nat',
174
186
  :description => 'Support Static NAT',
@@ -184,7 +196,7 @@ module KnifeCloudstack
184
196
  option :fw_rules,
185
197
  :short => "-f PORT_RULES",
186
198
  :long => "--fw-rules PORT_RULES",
187
- :description => "Comma separated list of firewall rules, e.g. '1024:10000:TCP:192.168.0.0/16,25:25:TCP:10.0.0.0/8'",
199
+ :description => "Comma separated list of firewall rules, e.g. 'TCP:192.168.0.0/16:1024:65535,TCP::22,UDP::123,ICMP'",
188
200
  :proc => lambda { |o| o.split(/[\s,]+/) },
189
201
  :default => []
190
202
 
@@ -197,6 +209,13 @@ module KnifeCloudstack
197
209
  :long => '--fqdn',
198
210
  :description => "FQDN which Kerberos Understands (only for Windows Servers)"
199
211
 
212
+ option :set_display_name,
213
+ :long => '--set-display-name',
214
+ :description => "Set the same server display name as Chef node name.",
215
+ :boolean => true,
216
+ :default => false
217
+
218
+
200
219
  def run
201
220
  validate_base_options
202
221
 
@@ -208,6 +227,11 @@ module KnifeCloudstack
208
227
  end
209
228
  validate_options
210
229
 
230
+ # This little peace of code sets the Chef node-name to the VM name when a node-name is not specifically given
231
+ unless locate_config_value :chef_node_name
232
+ Chef::Config[:knife][:chef_node_name] = @name_args.first
233
+ end
234
+
211
235
  if @windows_image and locate_config_value(:kerberos_realm)
212
236
  Chef::Log.debug("Load additional gems for AD/Kerberos Authentication")
213
237
  if @windows_platform
@@ -222,18 +246,23 @@ module KnifeCloudstack
222
246
  Chef::Log.info("Creating instance with
223
247
  service : #{locate_config_value(:cloudstack_service)}
224
248
  template : #{locate_config_value(:cloudstack_template)}
249
+ disk : #{locate_config_value(:cloudstack_disk)}
225
250
  zone : #{locate_config_value(:cloudstack_zone)}
226
251
  project: #{locate_config_value(:cloudstack_project)}
227
252
  network: #{locate_config_value(:cloudstack_networks)}")
228
253
 
229
254
  print "\n#{ui.color("Waiting for Server to be created", :magenta)}"
230
- params = {}
255
+ params = {}
231
256
  params['hypervisor'] = locate_config_value(:cloudstack_hypervisor) if locate_config_value(:cloudstack_hypervisor)
232
257
 
258
+ params['keypair'] = locate_config_value :keypair if locate_config_value :keypair
259
+ params['displayname'] = if locate_config_value :set_display_name and locate_config_value :chef_node_name then locate_config_value :chef_node_name else hostname end
260
+
233
261
  server = connection.create_server(
234
262
  hostname,
235
263
  locate_config_value(:cloudstack_service),
236
264
  locate_config_value(:cloudstack_template),
265
+ locate_config_value(:cloudstack_disk),
237
266
  locate_config_value(:cloudstack_zone),
238
267
  locate_config_value(:cloudstack_networks),
239
268
  params
@@ -244,7 +273,7 @@ module KnifeCloudstack
244
273
  object_fields = []
245
274
  object_fields << ui.color("Name:", :cyan)
246
275
  object_fields << server['name'].to_s
247
- object_fields << ui.color("Name:", :cyan) if locate_config_value(:cloudstack_password)
276
+ object_fields << ui.color("Password:", :cyan) if locate_config_value(:cloudstack_password)
248
277
  object_fields << server['password'] if locate_config_value(:cloudstack_password)
249
278
  object_fields << ui.color("Public IP:", :cyan)
250
279
  object_fields << public_ip
@@ -256,18 +285,22 @@ module KnifeCloudstack
256
285
  return unless config[:bootstrap]
257
286
 
258
287
  if @bootstrap_protocol == 'ssh'
259
- print "\n#{ui.color("Waiting for sshd", :magenta)}"
288
+ print "\n#{ui.color("Waiting for sshd on: #{public_ip}", :magenta)}"
260
289
 
261
290
  print(".") until is_ssh_open?(public_ip) {
262
291
  sleep BOOTSTRAP_DELAY
263
292
  puts "\n"
264
293
  }
265
- else
266
- print "\n#{ui.color("Waiting for winrm to be active", :magenta)}"
294
+ elsif @bootstrap_protocol == 'winrm'
295
+ print "\n#{ui.color("Waiting for winrm to be active on: #{public_ip}", :magenta)}"
267
296
  print(".") until tcp_test_winrm(public_ip,locate_config_value(:winrm_port)) {
268
297
  sleep WINRM_BOOTSTRAP_DELAY
269
298
  puts("\n")
270
299
  }
300
+ else
301
+ puts "Cannot determine the bootstrap protocol."
302
+ puts "Please specify either ssh or winrm as bootstrap protocol."
303
+ exit 1
271
304
  end
272
305
 
273
306
  object_fields = []
@@ -293,7 +326,7 @@ module KnifeCloudstack
293
326
  end
294
327
 
295
328
  def is_image_windows?
296
- template = connection.get_template(locate_config_value(:cloudstack_template))
329
+ template = connection.get_template(locate_config_value(:cloudstack_template),locate_config_value(:cloudstack_zone))
297
330
  if !template
298
331
  ui.error("Template: #{template} does not exist")
299
332
  exit 1
@@ -364,6 +397,7 @@ module KnifeCloudstack
364
397
  end
365
398
 
366
399
  def create_port_forwarding_rules(ip_address, server_id, connection)
400
+ Chef::Log.debug("Creating IP Forwarding Rule")
367
401
  rules = locate_config_value(:port_rules)
368
402
  if config[:bootstrap]
369
403
  if @bootstrap_protocol == 'ssh'
@@ -394,6 +428,7 @@ module KnifeCloudstack
394
428
  end
395
429
 
396
430
  def create_ip_forwarding_rules(ip_address, connection)
431
+ Chef::Log.debug("Creating IP Forwarding Rule")
397
432
  rules = locate_config_value(:ipfwd_rules)
398
433
  return unless rules
399
434
  rules.each do |rule|
@@ -410,17 +445,33 @@ module KnifeCloudstack
410
445
  end
411
446
 
412
447
  def create_firewall_rules(ip_address, connection)
448
+ Chef::Log.debug("Creating Firewall Rule")
413
449
  rules = locate_config_value(:fw_rules)
414
450
  return unless rules
451
+ icmptype={
452
+ '0' => {'code' => [0]},
453
+ '8' => {'code' => [0]},
454
+ '3' => {'code' => [0, 1]}
455
+ }
415
456
  rules.each do |rule|
416
457
  args = rule.split(':')
417
- startport = args[0]
418
- endport = args[1] || args[0]
419
- protocol = args[2] || "TCP"
420
- cidr_list = args[3] || "0.0.0.0/0"
421
- Chef::Log.debug("Creating Firewall Rule for
458
+ protocol = args[0]
459
+ cidr_list = (args[1].nil? || args[1].length == 0) ? "0.0.0.0/0" : args[1]
460
+ startport = args[2]
461
+ endport = args[3] || args[2]
462
+ if protocol == "ICMP"
463
+ icmptype.each do |type, value|
464
+ value['code'].each do |code_id|
465
+ Chef::Log.debug("Creating Firewall Rule for
466
+ #{ip_address['ipaddress']} with protocol: #{protocol}, icmptype: #{type}, icmpcode: #{code_id}, cidrList: #{cidr_list}")
467
+ connection.create_firewall_rule(ip_address['id'], protocol, type, code_id, cidr_list)
468
+ end
469
+ end
470
+ else
471
+ Chef::Log.debug("Creating Firewall Rule for
422
472
  #{ip_address['ipaddress']} with protocol: #{protocol}, startport: #{startport}, endport: #{endport}, cidrList: #{cidr_list}")
423
- connection.create_firewall_rule(ip_address['id'], protocol, startport, endport, cidr_list)
473
+ connection.create_firewall_rule(ip_address['id'], protocol, startport, endport, cidr_list)
474
+ end
424
475
  end
425
476
  end
426
477
 
@@ -516,7 +567,6 @@ module KnifeCloudstack
516
567
  ui.error("Unsupported Bootstrapping Protocol. Supported : winrm, ssh")
517
568
  exit 1
518
569
  end
519
- bootstrap.config[:environment] = locate_config_value(:environment)
520
570
  bootstrap.config[:chef_node_name] = config[:chef_node_name] || server['id']
521
571
  bootstrap.config[:encrypted_data_bag_secret] = config[:encrypted_data_bag_secret]
522
572
  bootstrap.config[:encrypted_data_bag_secret_file] = config[:encrypted_data_bag_secret_file]
@@ -529,6 +579,8 @@ module KnifeCloudstack
529
579
  bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
530
580
  bootstrap.config[:distro] = locate_config_value(:distro)
531
581
  bootstrap.config[:template_file] = locate_config_value(:template_file)
582
+ bootstrap.config[:first_boot_attributes] = locate_config_value(:first_boot_attributes)
583
+ bootstrap.config[:environment] = locate_config_value(:environment)
532
584
  bootstrap
533
585
  end
534
586
 
@@ -545,7 +597,6 @@ module KnifeCloudstack
545
597
  bootstrap.config[:identity_file] = locate_config_value(:identity_file)
546
598
  bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server["name"]
547
599
  bootstrap.config[:use_sudo] = true unless locate_config_value(:ssh_user) == 'root'
548
- bootstrap.config[:environment] = locate_config_value(:environment)
549
600
 
550
601
  # may be needed for vpc_mode
551
602
  bootstrap.config[:host_key_verify] = config[:host_key_verify]