cloudstack-cli 1.5.3 → 1.5.4

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: 6b75da05246b3ab3ac85f5ca8e93a28db01f8968
4
- data.tar.gz: fc2d98e9c509876350509db6da5b5e7ab3b900b2
3
+ metadata.gz: 1fc85400b51baea8a039a7d3ff78dd81057bc733
4
+ data.tar.gz: 850b702b9158cb5f016d90f71207172d7f5dee15
5
5
  SHA512:
6
- metadata.gz: 573c55dfed55ed68409424ef04562a9cd0dca835d23a458ce031c3f5fc0653fc87326f05cfd45c18e76ccbdb409dba6a90a1a5098f4c779ff81065514d50c804
7
- data.tar.gz: 22dd3887d463b7b3e08792b1396ec08002ba65bf1a94d9bec2090f72776a64a6b03630cd4dc6c5dd363281d195550cceb991e1677c11b2bf6fe02935c2e6a982
6
+ metadata.gz: ceb5a646a675bbd3f49bd27b772d1aad9cc3fa9ffa44130069619af7f8eefbe611036ff2b72257ce71aa6b96815b3019e3e1803005cdbb910991febc326817a5
7
+ data.tar.gz: 195edfdec98780452c0a121f9902cd1540169fcb35a2fab348b2c9ce20ec922b6a0f57f00a9ee21bc55ab6f5a75765514506c09b91bd7147830867c000ef8ff8
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../cloudstack_client/
3
3
  specs:
4
- cloudstack_client (1.4.1)
4
+ cloudstack_client (1.4.3)
5
5
 
6
6
  PATH
7
7
  remote: .
@@ -13,7 +13,7 @@ PATH
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- rake (11.1.2)
16
+ rake (11.2.0)
17
17
  thor (0.19.1)
18
18
 
19
19
  PLATFORMS
@@ -22,7 +22,7 @@ PLATFORMS
22
22
  DEPENDENCIES
23
23
  cloudstack-cli!
24
24
  cloudstack_client!
25
- rake (~> 11.1)
25
+ rake (~> 11.2)
26
26
 
27
27
  BUNDLED WITH
28
- 1.12.0
28
+ 1.12.4
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.require_paths = %w(lib)
22
22
  gem.rdoc_options = %w[--line-numbers --inline-source]
23
23
 
24
- gem.add_development_dependency('rake', '~> 11.1')
24
+ gem.add_development_dependency('rake', '~> 11.2')
25
25
 
26
26
  gem.add_dependency('cloudstack_client', '~> 1.4')
27
27
  gem.add_dependency('thor', '~> 0.19')
@@ -1,49 +1,52 @@
1
1
  class Stack < CloudstackCli::Base
2
2
 
3
- desc "create STACKFILE", "create a stack of VMs"
3
+ desc "create STACKFILE", "create a stack of VM's"
4
+ option :limit, type: :array, aliases: '-l',
5
+ desc: "Limit on specific server names."
4
6
  option :skip_forwarding_rules, default: false,
5
7
  type: :boolean, aliases: '-s',
6
8
  desc: "Skip creation of port forwarding rules."
7
9
  def create(stackfile)
8
10
  stack = parse_file(stackfile)
9
11
  project_id = find_project_by_name(stack["project"])
10
-
11
12
  say "Create stack #{stack["name"]}...", :green
12
13
  jobs = []
13
14
  stack["servers"].each do |instance|
14
15
  string_to_array(instance["name"]).each do |name|
15
- server = client.list_virtual_machines(name: name, project_id: project_id).first
16
- if server
17
- say "VM #{name} (#{server["state"]}) already exists.", :yellow
18
- jobs << {
19
- id: 0,
20
- name: "Create VM #{name}",
21
- status: 1
22
- }
23
- else
24
- options.merge!({
25
- name: name,
26
- displayname: instance["decription"],
27
- zone: instance["zone"] || stack["zone"],
28
- project: stack["project"],
29
- template: instance["template"],
30
- iso: instance["iso"] ,
31
- offering: instance["offering"],
32
- networks: load_string_or_array(instance["networks"]),
33
- ip_network_list: instance["ip_network_list"],
34
- disk_offering: instance["disk_offering"],
35
- size: instance["disk_size"],
36
- group: instance["group"] || stack["group"],
37
- keypair: instance["keypair"] || stack["keypair"],
38
- ip_address: instance["ip_address"]
39
- })
40
- jobs << {
41
- id: client.deploy_virtual_machine(
42
- vm_options_to_params,
43
- {sync: true}
44
- )['jobid'],
45
- name: "Create VM #{name}"
46
- }
16
+ if options[:limit].include?(name)
17
+ server = client.list_virtual_machines(name: name, project_id: project_id).first
18
+ if server
19
+ say "VM #{name} (#{server["state"]}) already exists.", :yellow
20
+ jobs << {
21
+ id: 0,
22
+ name: "Create VM #{name}",
23
+ status: 1
24
+ }
25
+ else
26
+ options.merge!({
27
+ name: name,
28
+ displayname: instance["decription"],
29
+ zone: instance["zone"] || stack["zone"],
30
+ project: stack["project"],
31
+ template: instance["template"],
32
+ iso: instance["iso"] ,
33
+ offering: instance["offering"],
34
+ networks: load_string_or_array(instance["networks"]),
35
+ ip_network_list: instance["ip_network_list"],
36
+ disk_offering: instance["disk_offering"],
37
+ size: instance["disk_size"],
38
+ group: instance["group"] || stack["group"],
39
+ keypair: instance["keypair"] || stack["keypair"],
40
+ ip_address: instance["ip_address"]
41
+ })
42
+ jobs << {
43
+ id: client.deploy_virtual_machine(
44
+ vm_options_to_params,
45
+ {sync: true}
46
+ )['jobid'],
47
+ name: "Create VM #{name}"
48
+ }
49
+ end
47
50
  end
48
51
  end
49
52
  end
@@ -54,20 +57,17 @@ class Stack < CloudstackCli::Base
54
57
  jobs = []
55
58
  stack["servers"].each do |instance|
56
59
  string_to_array(instance["name"]).each do |name|
57
- if port_rules = string_to_array(instance["port_rules"])
60
+ if options[:limit].include?(name) && port_rules = string_to_array(instance["port_rules"])
58
61
  server = client.list_virtual_machines(name: name, project_id: project_id).first
59
62
  create_port_rules(server, port_rules, false).each_with_index do |job_id, index|
60
- jobs << {
61
- id: job_id,
62
- name: "Create port forwarding rules (#{port_rules[index]}) for VM #{name}"
63
- }
63
+ job_name = "Create port forwarding rules (#{port_rules[index]}) for VM #{name}"
64
+ jobs << {id: job_id, name: job_name}
64
65
  end
65
66
  end
66
67
  end
67
68
  end
68
69
  watch_jobs(jobs)
69
70
  end
70
-
71
71
  say "Finished.", :green
72
72
  end
73
73
 
@@ -82,12 +82,21 @@ class Stack < CloudstackCli::Base
82
82
  type: :boolean,
83
83
  default: false,
84
84
  aliases: '-E'
85
+ option :limit, type: :array, aliases: '-l',
86
+ desc: "Limit on specific server names."
85
87
  def destroy(stackfile)
86
88
  stack = parse_file(stackfile)
87
89
  project_id = find_project_by_name(stack["project"])
88
90
  servers = []
89
91
  stack["servers"].each do |server|
90
- string_to_array(server["name"]).each {|name| servers << name}
92
+ string_to_array(server["name"]).each do |name|
93
+ servers << name if options[:limit].include?(name)
94
+ end
95
+ end
96
+
97
+ if servers.size == 0
98
+ say "No servers in stack selected.", :yellow
99
+ exit
91
100
  end
92
101
 
93
102
  if options[:force] || yes?("Destroy the following VM #{servers.join(', ')}? [y/N]:", :yellow)
@@ -102,15 +102,13 @@ class VirtualMachine < CloudstackCli::Base
102
102
  end
103
103
 
104
104
  vm_options_to_params
105
- say "Start deploying virtual machine#{ "s" if names.size > 1 }...", :green
105
+ say "Start deploying virtual machine#{"s" if names.size > 1}...", :green
106
106
  jobs = names.map do |name|
107
- if virtual_machine = client.list_virtual_machines(name: name, project_id: options[:project_id]).first
107
+ if virtual_machine = client.list_virtual_machines(
108
+ name: name, project_id: options[:project_id]
109
+ ).first
108
110
  say "virtual machine #{name} (#{virtual_machine["state"]}) already exists.", :yellow
109
- job = {
110
- id: 0,
111
- name: "Create virtual machine #{name}",
112
- status: 1
113
- }
111
+ job = {id: 0, name: "Create virtual machine #{name}", status: 1}
114
112
  else
115
113
  job = {
116
114
  id: client.deploy_virtual_machine(options.merge(name: name), {sync: true})['jobid'],
@@ -166,37 +166,63 @@ module CloudstackCli
166
166
  end
167
167
 
168
168
  def create_port_rules(server, port_rules, async = true)
169
- frontendip = nil
169
+ frontendip_id = nil
170
170
  jobs = []
171
171
  client.verbose = async
172
172
  project_id = server['projectid'] || nil
173
173
  port_rules.each do |pf_rule|
174
- ip = pf_rule.split(":")[0]
175
- if ip != ''
176
- ip_addr = client.get_public_ip_address(ip, project_id)
177
- unless ip_addr
178
- say "Error: IP #{ip} not found.", :red
174
+ pf_rule = pf_rule_to_object(pf_rule)
175
+ if pf_rule[:ipaddress]
176
+ pub_ip = client.list_public_ip_addresses(
177
+ network_id: get_server_default_nic(server)["networkid"],
178
+ project_id: project_id,
179
+ ipaddress: pf_rule[:ipaddress]
180
+ )
181
+ ip_addr = pub_ip.find { |addr| addr['ipaddress'] == pf_rule[:ipaddress]} if pub_ip
182
+ if ip_addr
183
+ frontendip = ip_addr['id']
184
+ else
185
+ say "Error: IP #{pf_rule[:ipaddress]} not found.", :red
179
186
  next
180
187
  end
181
- else
182
- ip_addr = frontendip ||= client.associate_ip_address(
183
- network_id: server["nic"].first["networkid"]
184
- )["ipaddress"]
185
188
  end
186
- port = pf_rule.split(":")[1]
187
- args = {
188
- ipaddressid: ip_addr["id"],
189
- publicport: port,
190
- privateport: port,
191
- protocol: 'TCP',
192
- virtualmachineid: server["id"]
193
- }
194
- if async
195
- say "Create port forwarding rule #{ip_addr['ipaddress']}:#{port} for server #{server["name"]}.", :yellow
196
- client.create_port_forwarding_rule(args)
197
- return
189
+
190
+ # check if there is already an existing rule
191
+ rules = client.list_port_forwarding_rules(
192
+ networkid: get_server_default_nic(server)["networkid"],
193
+ ipaddressid: frontendip_id,
194
+ projectid: project_id
195
+ )
196
+ existing_pf_rules = rules.find do |rule|
197
+ # remember matching address for additional rules
198
+ frontendip_id = rule['ipaddressid'] if rule['virtualmachineid'] == server['id']
199
+
200
+ rule['virtualmachineid'] == server['id'] &&
201
+ rule['publicport'] == pf_rule[:publicport] &&
202
+ rule['privateport'] == pf_rule[:privateport] &&
203
+ rule['protocol'] == pf_rule[:protocol]
204
+ end
205
+
206
+ if existing_pf_rules
207
+ say "Port forwarding rule on port #{pf_rule[:privateport]} for VM #{server["name"]} already exists.", :yellow
198
208
  else
199
- jobs << client.create_port_forwarding_rule(args, {sync: true})['jobid']
209
+ unless frontendip_id
210
+ frontendip_id = client.associate_ip_address(
211
+ network_id: get_server_default_nic(server)["networkid"],
212
+ project_id: project_id
213
+ )['ipaddress']['id']
214
+ end
215
+ args = pf_rule.merge({
216
+ ipaddressid: frontendip_id,
217
+ virtualmachineid: server["id"]
218
+ })
219
+ if async
220
+ say "Create port forwarding rule #{pf_rule[:ipaddress]}:#{port} for VM #{server["name"]}.", :yellow
221
+ client.create_port_forwarding_rule(args)
222
+ return
223
+ else
224
+ jobs << client.create_port_forwarding_rule(args, {sync: true})['jobid']
225
+ end
200
226
  end
201
227
  end
202
228
  jobs
@@ -267,57 +293,21 @@ module CloudstackCli
267
293
  end
268
294
  end
269
295
 
270
- ##
271
- # Finds the public ip for a server
272
-
273
- def get_server_public_ip(server, cached_rules=nil)
274
- return nil unless server
275
-
276
- # find the public ip
277
- nic = get_server_default_nic(server) || {}
278
- if nic['type'] == 'Virtual'
279
- ssh_rule = get_ssh_port_forwarding_rule(server, cached_rules)
280
- ssh_rule ? ssh_rule['ipaddress'] : nil
281
- else
282
- nic['ipaddress']
283
- end
284
- end
285
-
286
- ##
287
- # Gets the SSH port forwarding rule for the specified server.
288
-
289
- def get_ssh_port_forwarding_rule(server, cached_rules=nil)
290
- rules = cached_rules || client.list_port_forwarding_rules(project_id: server["projectid"]) || []
291
- rules.find_all { |r|
292
- r['virtualmachineid'] == server['id'] &&
293
- r['privateport'] == '22'&&
294
- r['publicport'] == '22'
295
- }.first
296
- end
297
-
298
- ##
299
- # Returns the fully qualified domain name for a server.
300
-
301
- def get_server_fqdn(server)
302
- return nil unless server
303
-
304
- nic = get_server_default_nic(server) || {}
305
- networks = client.list_networks(project_id: server['projectid']) || {}
306
-
307
- id = nic['networkid']
308
- network = networks.select { |net|
309
- net['id'] == id
310
- }.first
311
- return nil unless network
312
-
313
- "#{server['name']}.#{network['networkdomain']}"
314
- end
315
-
316
296
  def get_server_default_nic(server)
317
297
  server['nic'].each do |nic|
318
298
  return nic if nic['isdefault']
319
299
  end
320
300
  end
321
301
 
302
+ def pf_rule_to_object(pf_rule)
303
+ pf_rule = pf_rule.split(":")
304
+ {
305
+ ipaddress: (pf_rule[0] == '' ? nil : pf_rule[0]),
306
+ privateport: pf_rule[1],
307
+ publicport: (pf_rule[2] || pf_rule[1]),
308
+ protocol: (pf_rule[3] || 'tcp').downcase
309
+ }
310
+ end
311
+
322
312
  end
323
313
  end
@@ -1,3 +1,3 @@
1
1
  module CloudstackCli
2
- VERSION = "1.5.3"
2
+ VERSION = "1.5.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudstack-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nik Wolfgramm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-04 00:00:00.000000000 Z
11
+ date: 2016-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '11.1'
19
+ version: '11.2'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '11.1'
26
+ version: '11.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: cloudstack_client
29
29
  requirement: !ruby/object:Gem::Requirement