cloudstack-cli 0.1.5 → 0.1.6

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.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloudstack-cli (0.1.4)
4
+ cloudstack-cli (0.1.5)
5
5
  net-ssh (~> 2.6.7)
6
6
  thor (~> 0.18.1)
7
7
 
@@ -9,6 +9,11 @@ module CloudstackCli
9
9
  exit!
10
10
  }
11
11
 
12
+ # exit with return code 1 in case of a error
13
+ def self.exit_on_failure?
14
+ true
15
+ end
16
+
12
17
  no_commands do
13
18
  def client
14
19
  @config ||= CloudstackClient::ConnectionHelper.load_configuration(options[:config])
@@ -29,7 +34,7 @@ module CloudstackCli
29
34
  end
30
35
 
31
36
  def filter_by(objects, tag_name, tag)
32
- objects.select {|r| r[tag_name].downcase == tag }
37
+ objects.select {|r| r[tag_name].downcase == tag.downcase }
33
38
  end
34
39
  end
35
40
  end
@@ -65,6 +65,9 @@ module CloudstackCli
65
65
  desc "offering SUBCOMMAND ...ARGS", "Manage offerings"
66
66
  subcommand "offering", Offering
67
67
 
68
+ desc "disk_offering SUBCOMMAND ...ARGS", "Manage disk offerings"
69
+ subcommand "disk_offering", DiskOffering
70
+
68
71
  desc "network SUBCOMMAND ...ARGS", "Manage networks"
69
72
  subcommand "network", Network
70
73
 
@@ -74,9 +77,12 @@ module CloudstackCli
74
77
  desc "load_balancer SUBCOMMAND ...ARGS", "Manage load balancing rules"
75
78
  subcommand "load_balancer", LoadBalancer
76
79
 
77
- desc "template SUBCOMMAND ...ARGS", "Manage template"
80
+ desc "template SUBCOMMAND ...ARGS", "Manage templates"
78
81
  subcommand "template", Template
79
82
 
83
+ desc "iso SUBCOMMAND ...ARGS", "Manage iso's"
84
+ subcommand "iso", Iso
85
+
80
86
  desc "router SUBCOMMAND ...ARGS", "Manage virtual routers"
81
87
  subcommand "router", Router
82
88
 
@@ -0,0 +1,22 @@
1
+ class DiskOffering < CloudstackCli::Base
2
+
3
+ desc 'list', 'list disk offerings'
4
+ option :domain
5
+ def list
6
+ offerings = client.list_disk_offerings(options[:domain])
7
+ if offerings.size < 1
8
+ puts "No offerings found"
9
+ else
10
+ table = [["Name", "Displaytext", "Domain", "ID"]]
11
+ offerings.each do |offering|
12
+ table << [
13
+ offering["name"],
14
+ offering["displaytext"],
15
+ offering["domain"],
16
+ offering["id"]
17
+ ]
18
+ end
19
+ print_table table
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ class Iso < CloudstackCli::Base
2
+
3
+ desc 'list [TYPE]', "list iso's by type [featured|self|self-executable|executable|community]"
4
+ option :project
5
+ option :zone
6
+ option :account
7
+ def list(type='featured')
8
+ project = find_project if options[:project]
9
+ unless %w(featured self self-executable executable community).include? type
10
+ say "unsupported iso type '#{type}'", :red
11
+ exit 1
12
+ end
13
+ zone = client.get_zone(options[:zone]) if options[:zone]
14
+ isos = client.list_isos(
15
+ type: type,
16
+ project_id: project ? project['id'] : nil,
17
+ zone_id: zone ? zone['id'] : nil
18
+ )
19
+ if isos.size < 1
20
+ puts "No iso's found"
21
+ else
22
+ table = [["Name", "Zone", "Bootable"]]
23
+ isos.each do |iso|
24
+ table << [iso['name'], iso['zonename'], iso['bootable']]
25
+ end
26
+ print_table(table)
27
+ end
28
+ end
29
+
30
+ end
@@ -5,10 +5,31 @@ class Network < CloudstackCli::Base
5
5
  # TODO
6
6
  end
7
7
 
8
+ desc "default", "get the default network"
9
+ option :zone
10
+ def default
11
+ network = client.get_default_network(options[:zone])
12
+ unless network
13
+ puts "No default network found."
14
+ else
15
+ table = [["Name", "Displaytext", "Domain", "Zone"]]
16
+ table[0] << "ID" if options[:showid]
17
+ table << [
18
+ network["name"],
19
+ network["displaytext"],
20
+ network["domain"],
21
+ network["zonename"]
22
+ ]
23
+ table[-1] << network["id"] if options[:showid]
24
+ print_table table
25
+ end
26
+ end
27
+
8
28
  desc "list", "list networks"
9
29
  option :project
10
30
  option :account
11
31
  option :showid, type: :boolean
32
+ option :isdefault, type: :boolean
12
33
  def list
13
34
  project = find_project if options[:project]
14
35
  networks = []
@@ -17,13 +38,13 @@ class Network < CloudstackCli::Base
17
38
  elsif options[:account]
18
39
  networks = client.list_networks(account: options[:account])
19
40
  else
20
- networks = client.list_networks(project_id: -1)
41
+ networks = client.list_networks(project_id: -1, isdefault: options[:isdefault])
21
42
  end
22
43
 
23
44
  if networks.size < 1
24
- puts "No networks found"
45
+ puts "No networks found."
25
46
  else
26
- table = [["Name", "Displaytext", "Account", "Project", "Domain", "State"]]
47
+ table = [["Name", "Displaytext", "Account", "Project", "Domain", "State", "Type"]]
27
48
  table[0] << "ID" if options[:showid]
28
49
  networks.each do |network|
29
50
  table << [
@@ -32,7 +53,8 @@ class Network < CloudstackCli::Base
32
53
  network["account"],
33
54
  network["project"],
34
55
  network["domain"],
35
- network["state"]
56
+ network["state"],
57
+ network["type"]
36
58
  ]
37
59
  table[-1] << network["id"] if options[:showid]
38
60
  end
@@ -40,4 +62,16 @@ class Network < CloudstackCli::Base
40
62
  end
41
63
  end
42
64
 
65
+ desc "delete NAME", "delete network"
66
+ def delete(name)
67
+ network = client.get_network(name, -1)
68
+ unless network
69
+ say "Network #{name} not found."
70
+ exit 1
71
+ end
72
+ if yes? "Destroy network #{network['name']} - #{network['name']}?"
73
+ p client.delete_network(network['id'])
74
+ end
75
+ end
76
+
43
77
  end
@@ -1,18 +1,9 @@
1
1
  class Offering < CloudstackCli::Base
2
2
 
3
- desc 'list', 'list offerings by type [compute|network|storage]'
3
+ desc 'list', 'list compute offerings'
4
4
  option :domain
5
- def list(type='compute')
5
+ def list
6
6
  offerings = client.list_service_offerings(options[:domain])
7
-
8
- offerings.group_by{|o| o["domain"]}.each_value do |offers|
9
- offers.sort {
10
- |oa, ob| [oa["cpunumber"], oa["memory"]] <=> [ob["cpunumber"], ob["memory"]]
11
- }.each do |offer|
12
- puts "#{offer['domain']} - #{offer["displaytext"]}"
13
- end
14
- end
15
-
16
7
  if offerings.size < 1
17
8
  puts "No offerings found"
18
9
  else
@@ -34,14 +34,15 @@ class Server < CloudstackCli::Base
34
34
 
35
35
  desc "create NAME", "create a server"
36
36
  option :zone, required: true
37
- option :template, required: true
37
+ option :template, required: true, desc: "name of template or iso"
38
38
  option :offering, required: true
39
39
  option :networks, type: :array, required: true
40
40
  option :project
41
41
  option :port_rules, type: :array,
42
42
  default: [],
43
43
  desc: "Port Forwarding Rules [public_ip]:port ..."
44
- option :interactive, type: :boolean
44
+ option :disk_offering
45
+ option :hypervisor, desc: "only used for iso deployments, defaults to vmware"
45
46
  def create(name)
46
47
  if project = find_project
47
48
  project_id = project["id"]
@@ -51,14 +52,15 @@ class Server < CloudstackCli::Base
51
52
  say "Create server #{name}...", :yellow
52
53
  server = client.create_server(
53
54
  name, options[:offering], options[:template],
54
- options[:zone], options[:networks], options[:project]
55
+ options[:zone], options[:networks], options[:project],
56
+ options[:disk_offering], options[:hypervisor]
55
57
  )
56
58
  puts
57
59
  say "Server #{name} has been created.", :green
58
60
  client.wait_for_server_state(server["id"], "Running")
59
61
  say "Server #{name} is running.", :green
60
62
  else
61
- say "Server #{name} already exists.", :green
63
+ say "Server #{name} already exists.", :yellow
62
64
  # TODO: check status of server
63
65
  end
64
66
 
@@ -1,20 +1,26 @@
1
1
  class Template < CloudstackCli::Base
2
2
 
3
- desc 'list', 'list templates by type [featured|self|self-executable|executable|community]'
3
+ desc 'list [TYPE]', 'list templates by type [featured|self|self-executable|executable|community]'
4
4
  option :project
5
+ option :zone
5
6
  def list(type='featured')
6
7
  project = find_project if options[:project]
7
8
  unless %w(featured self self-executable executable community).include? type
8
9
  say "unsupported template type '#{type}'", :red
9
10
  exit 1
10
11
  end
11
- templates = client.list_templates(type: type, project_id: project ? project['id'] : nil)
12
+ zone = client.get_zone(options[:zone]) if options[:zone]
13
+ templates = client.list_templates(
14
+ type: type,
15
+ project_id: project ? project['id'] : nil,
16
+ zone_id: zone ? zone['id'] : nil
17
+ )
12
18
  if templates.size < 1
13
19
  puts "No templates found"
14
20
  else
15
- table = [["Name", "Zone"]]
21
+ table = [["Name", "Zone", "Format"]]
16
22
  templates.each do |template|
17
- table << [template['name'], template['zonename']]
23
+ table << [template['name'], template['zonename'], template['format']]
18
24
  end
19
25
  print_table(table)
20
26
  end
@@ -28,7 +28,7 @@ module CloudstackCli
28
28
  client.wait_for_server_state(server["id"], "Running")
29
29
  say "Server #{server["name"]} is running.", :green
30
30
  else
31
- say "Server #{name} already exists.", :green
31
+ say "Server #{name} already exists.", :yellow
32
32
  end
33
33
 
34
34
  if pf_rules && pf_rules.size > 0
@@ -1,3 +1,3 @@
1
1
  module CloudstackCli
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -143,7 +143,8 @@ module CloudstackClient
143
143
  ##
144
144
  # Deploys a new server using the specified parameters.
145
145
 
146
- def create_server(host_name, service_name, template_name, zone_name=nil, network_names=[], project_name=nil)
146
+ def create_server(host_name, service_name, template_name, zone_name=nil,
147
+ network_names=[], project_name=nil, disk_offering=nil, hypervisor=nil)
147
148
  if host_name then
148
149
  if get_server(host_name) then
149
150
  puts "Error: Server '#{host_name}' already exists."
@@ -159,8 +160,11 @@ module CloudstackClient
159
160
 
160
161
  template = get_template(template_name)
161
162
  if !template then
162
- puts "Error: Template '#{template_name}' is invalid"
163
- exit 1
163
+ template = get_iso(template_name)
164
+ if !template then
165
+ puts "Error: Template '#{template_name}' is invalid"
166
+ exit 1
167
+ end
164
168
  end
165
169
 
166
170
  zone = zone_name ? get_zone(zone_name) : get_default_zone
@@ -199,6 +203,16 @@ module CloudstackClient
199
203
  network['id']
200
204
  }
201
205
 
206
+ if disk_offering
207
+ disk_offering = get_disk_offering(disk_offering)
208
+ unless disk_offering
209
+ msg = zone_name ? "Zone '#{zone_name}' is invalid" : "No default zone found"
210
+ puts "Error: #{msg}"
211
+ exit 1
212
+ end
213
+
214
+ end
215
+
202
216
  params = {
203
217
  'command' => 'deployVirtualMachine',
204
218
  'serviceOfferingId' => service['id'],
@@ -208,6 +222,8 @@ module CloudstackClient
208
222
  }
209
223
  params['name'] = host_name if host_name
210
224
  params['projectid'] = project['id'] if project_name
225
+ params['diskofferingid'] = disk_offering['id'] if disk_offering
226
+ params['hypervisor'] = hypervisor || 'vmware' if disk_offering
211
227
 
212
228
  json = send_async_request(params)
213
229
  json['virtualmachine']
@@ -310,7 +326,6 @@ module CloudstackClient
310
326
  return s
311
327
  end
312
328
  }
313
-
314
329
  nil
315
330
  end
316
331
 
@@ -380,6 +395,47 @@ module CloudstackClient
380
395
  json['serviceoffering']
381
396
  end
382
397
 
398
+ ##
399
+ # Lists all available disk offerings.
400
+
401
+ def list_disk_offerings(domain = nil)
402
+ params = {
403
+ 'command' => 'listDiskOfferings'
404
+ }
405
+
406
+ if domain
407
+ params['domainid'] = list_domains(domain).first["id"]
408
+ end
409
+
410
+ json = send_request(params)
411
+ json['diskoffering'] || []
412
+ end
413
+
414
+ ##
415
+ # Get disk offering by name.
416
+
417
+ def get_disk_offering(name)
418
+
419
+ # TODO: use name parameter
420
+ # listServiceOfferings in CloudStack 2.2 doesn't seem to work
421
+ # when the name parameter is specified. When this is fixed,
422
+ # the name parameter should be added to the request.
423
+ params = {
424
+ 'command' => 'listDiskOfferings'
425
+ }
426
+ json = send_request(params)
427
+
428
+ services = json['diskoffering']
429
+ return nil unless services
430
+
431
+ services.each { |s|
432
+ if s['name'] == name then
433
+ return s
434
+ end
435
+ }
436
+ nil
437
+ end
438
+
383
439
  ##
384
440
  # Finds the template with the specified name.
385
441
 
@@ -433,6 +489,59 @@ module CloudstackClient
433
489
  json['template'] || []
434
490
  end
435
491
 
492
+ ##
493
+ # Lists all isos that match the specified filter.
494
+ #
495
+ # Allowable filter values are:
496
+ #
497
+ # * featured - isos that are featured and are public
498
+ # * self - isos that have been registered/created by the owner
499
+ # * self-executable - isos that have been registered/created by the owner that can be used to deploy a new VM
500
+ # * executable - all isos that can be used to deploy a new VM
501
+ # * community - isos that are public
502
+
503
+ def list_isos(args = {})
504
+ filter = args[:filter] || 'featured'
505
+ params = {
506
+ 'command' => 'listIsos',
507
+ 'templateFilter' => filter
508
+ }
509
+ params['projectid'] = args[:project_id] if args[:project_id]
510
+ params['zoneid'] = args[:zone_id] if args[:zone_id]
511
+
512
+ json = send_request(params)
513
+ json['iso'] || []
514
+ end
515
+
516
+ ##
517
+ # Finds the template with the specified name.
518
+
519
+ def get_iso(name)
520
+
521
+ # TODO: use name parameter
522
+ # listIsos in CloudStack 2.2 doesn't seem to work
523
+ # when the name parameter is specified. When this is fixed,
524
+ # the name parameter should be added to the request.
525
+ params = {
526
+ 'command' => 'listIsos',
527
+ 'templateFilter' => 'executable'
528
+ }
529
+ json = send_request(params)
530
+
531
+ isos = json['iso']
532
+ if !isos then
533
+ return nil
534
+ end
535
+
536
+ isos.each { |t|
537
+ if t['name'] == name then
538
+ return t
539
+ end
540
+ }
541
+
542
+ nil
543
+ end
544
+
436
545
  ##
437
546
  # Finds the network with the specified name.
438
547
 
@@ -458,27 +567,26 @@ module CloudstackClient
458
567
  ##
459
568
  # Finds the default network.
460
569
 
461
- def get_default_network
570
+ def get_default_network(zone = nil)
462
571
  params = {
463
572
  'command' => 'listNetworks',
464
573
  'isDefault' => true
465
574
  }
575
+ if zone
576
+ params['zoneid'] = get_zone(zone)['id']
577
+ end
466
578
  json = send_request(params)
467
579
 
468
580
  networks = json['network']
469
581
  return nil if !networks || networks.empty?
470
-
471
- default = networks.first
472
- return default if networks.length == 1
582
+ return networks.first if networks.length == 1
473
583
 
474
584
  networks.each { |n|
475
585
  if n['type'] == 'Direct' then
476
- default = n
477
- break
586
+ return n
478
587
  end
479
588
  }
480
-
481
- default
589
+ nil
482
590
  end
483
591
 
484
592
  ##
@@ -491,6 +599,7 @@ module CloudstackClient
491
599
  }
492
600
  params['projectid'] = args[:project_id] if args[:project_id]
493
601
  params['zoneid'] = args[:zone_id] if args[:zone_id]
602
+ params['isDefault'] = true if args[:isdefault]
494
603
  if args[:account]
495
604
  domain = list_accounts(name: args[:account])
496
605
  if domain.size > 0
@@ -504,6 +613,18 @@ module CloudstackClient
504
613
  json['network'] || []
505
614
  end
506
615
 
616
+ ##
617
+ # Delete network.
618
+
619
+ def delete_network(id)
620
+ params = {
621
+ 'command' => 'deleteNetwork',
622
+ 'id' => id,
623
+ }
624
+ p json = send_async_request(params)
625
+ json['network']
626
+ end
627
+
507
628
  ##
508
629
  # Lists all physical networks.
509
630
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudstack-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -95,8 +95,10 @@ files:
95
95
  - lib/cloudstack-cli/cli.rb
96
96
  - lib/cloudstack-cli/commands/account.rb
97
97
  - lib/cloudstack-cli/commands/capacity.rb
98
+ - lib/cloudstack-cli/commands/disk_offering.rb
98
99
  - lib/cloudstack-cli/commands/domain.rb
99
100
  - lib/cloudstack-cli/commands/ip_address.rb
101
+ - lib/cloudstack-cli/commands/iso.rb
100
102
  - lib/cloudstack-cli/commands/load_balancer.rb
101
103
  - lib/cloudstack-cli/commands/network.rb
102
104
  - lib/cloudstack-cli/commands/offering.rb