cloudstack-cli 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloudstack-cli (0.0.3)
5
- command_line_reporter (~> 3.2.1)
4
+ cloudstack-cli (0.0.5)
6
5
  net-ssh (~> 2.6.7)
7
6
  rainbow (~> 1.1.4)
8
7
  thor (~> 0.18.1)
@@ -10,9 +9,6 @@ PATH
10
9
  GEM
11
10
  remote: https://rubygems.org/
12
11
  specs:
13
- colored (1.2)
14
- command_line_reporter (3.2.1)
15
- colored (>= 1.2)
16
12
  json (1.8.0)
17
13
  net-ssh (2.6.8)
18
14
  rainbow (1.1.4)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Cloudstack CLI
2
2
 
3
- Cloudstack CLI gives command line access to the CloudStack API commands.
3
+ Cloudstack CLI is a [CloudStack](http://cloudstack.apache.org/) API client written in Ruby.
4
4
 
5
5
  ## Installation
6
6
 
@@ -12,7 +12,7 @@ Install the cloudstack-cli gem:
12
12
 
13
13
  Create the initial configuration:
14
14
 
15
- cs setup
15
+ $ cs setup
16
16
 
17
17
  cloudstack-cli expects to find a configuartion file with the API URL and your CloudStack credentials in your home directory named .cloudstack-cli.yml. If the file is located elsewhere you can specify the loaction using the --config option.
18
18
 
@@ -40,24 +40,24 @@ Bootsrap a server:
40
40
 
41
41
  Run a custom API command:
42
42
 
43
- cs command listAlerts type=8
43
+ $ cs command listAlerts type=8
44
44
 
45
45
  ### Example 3
46
46
 
47
47
  Sort all computing offerings by CPU and Memory grouped my Domain:
48
48
 
49
- cs offering sort
49
+ $ cs offering sort
50
50
 
51
51
  ### Example 4
52
52
 
53
53
  Stop all virtual routers of project Demo (you could filter by Zone too):
54
54
  (This command is helpful if you have to deploy new versions of Cloudstack when using redumdant routers)
55
55
 
56
- cs router list --project Demo --status running --redundant-state BACKUP --command stop
56
+ $ cs router list --project Demo --status running --redundant-state BACKUP --command stop
57
57
 
58
58
  Hint: You can watch the status of the command with watch.
59
59
 
60
- watch -n cs router list --project Demo
60
+ $ watch -n cs router list --project Demo
61
61
 
62
62
 
63
63
  ## References
@@ -25,5 +25,4 @@ Gem::Specification.new do |gem|
25
25
  gem.add_dependency('thor', '~> 0.18.1')
26
26
  gem.add_dependency('net-ssh', '~> 2.6.7')
27
27
  gem.add_dependency('rainbow', '~> 1.1.4')
28
- gem.add_dependency('command_line_reporter', '~> 3.2.1')
29
28
  end
@@ -0,0 +1,36 @@
1
+ module CloudstackCli
2
+ class Base < Thor
3
+ include Thor::Actions
4
+ attr_reader :config
5
+
6
+ # catch control-c and exit
7
+ trap("SIGINT") {
8
+ puts
9
+ puts "bye"
10
+ exit!
11
+ }
12
+
13
+ no_commands do
14
+ def client
15
+ @config ||= CloudstackClient::ConnectionHelper.load_configuration(options[:config])
16
+ @client ||= CloudstackClient::Connection.new(
17
+ @config[:url],
18
+ @config[:api_key],
19
+ @config[:secret_key]
20
+ )
21
+ end
22
+
23
+ def find_project(project_name = options[:project])
24
+ unless project = client.get_project(project_name)
25
+ say "Project '#{options[:project]}' not found", :red
26
+ exit 1
27
+ end
28
+ project
29
+ end
30
+
31
+ def filter_by(objects, tag_name, tag)
32
+ objects.select {|r| r[tag_name].downcase == tag }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,7 +1,5 @@
1
1
  module CloudstackCli
2
- trap("TERM") { puts "SIGTERM received"; exit }
3
-
4
- class Cli < Thor
2
+ class Cli < CloudstackCli::Base
5
3
  include Thor::Actions
6
4
 
7
5
  package_name "cloudstack-cli"
@@ -24,8 +22,8 @@ module CloudstackCli
24
22
  def setup(file = options[:config])
25
23
  config = {}
26
24
  unless options[:url]
27
- say "What's the URL of your Cloudstack API?", :blue
28
- say "Example: https://my-cloudstack-server/client/api/", :blue
25
+ say "What's the URL of your Cloudstack API?", :yellow
26
+ say "Example: https://my-cloudstack-server/client/api/", :yellow
29
27
  config[:url] = ask("URL:", :magenta)
30
28
  end
31
29
 
@@ -55,46 +53,49 @@ module CloudstackCli
55
53
  puts JSON.pretty_generate(client.cs.send_request params)
56
54
  end
57
55
 
58
- desc "zone SUBCOMMAND ...ARGS", "manage zones"
56
+ desc "zone SUBCOMMAND ...ARGS", "Manage zones"
59
57
  subcommand "zone", Zone
60
58
 
61
- desc "project SUBCOMMAND ...ARGS", "manage servers"
59
+ desc "project SUBCOMMAND ...ARGS", "Manage servers"
62
60
  subcommand "project", Project
63
61
 
64
- desc "server SUBCOMMAND ...ARGS", "manage servers"
62
+ desc "server SUBCOMMAND ...ARGS", "Manage servers"
65
63
  subcommand "server", Server
66
64
 
67
- desc "offering SUBCOMMAND ...ARGS", "manage offerings"
65
+ desc "offering SUBCOMMAND ...ARGS", "Manage offerings"
68
66
  subcommand "offering", Offering
69
67
 
70
- desc "network SUBCOMMAND ...ARGS", "manage networks"
68
+ desc "network SUBCOMMAND ...ARGS", "Manage networks"
71
69
  subcommand "network", Network
72
70
 
73
- desc "lb SUBCOMMAND ...ARGS", "manage load balancing rules"
71
+ desc "lb SUBCOMMAND ...ARGS", "Manage load balancing rules"
74
72
  subcommand "lb", Lb
75
73
 
76
- desc "template SUBCOMMAND ...ARGS", "manage template"
74
+ desc "template SUBCOMMAND ...ARGS", "Manage template"
77
75
  subcommand "template", Template
78
76
 
79
- desc "router SUBCOMMAND ...ARGS", "manage virtual routers"
77
+ desc "router SUBCOMMAND ...ARGS", "Manage virtual routers"
80
78
  subcommand "router", Router
81
79
 
82
- desc "router SUBCOMMAND ...ARGS", "manage virtual routers"
80
+ desc "router SUBCOMMAND ...ARGS", "Manage virtual routers"
83
81
  subcommand "router", Router
84
82
 
85
- desc "volume SUBCOMMAND ...ARGS", "manage volumes"
83
+ desc "volume SUBCOMMAND ...ARGS", "Manage volumes"
86
84
  subcommand "volume", Volume
87
85
 
88
- desc "stack SUBCOMMAND ...ARGS", "manage stacks"
86
+ desc "stack SUBCOMMAND ...ARGS", "Manage stacks"
89
87
  subcommand "stack", Stack
90
88
 
91
- desc "account SUBCOMMAND ...ARGS", "manage accounts"
89
+ desc "account SUBCOMMAND ...ARGS", "Manage accounts"
92
90
  subcommand "account", Account
93
91
 
94
- desc "domain SUBCOMMAND ...ARGS", "manage domains"
92
+ desc "domain SUBCOMMAND ...ARGS", "Manage domains"
95
93
  subcommand "domain", Domain
96
94
 
97
- desc "publicip SUBCOMMAND ...ARGS", "manage public ip addresses"
95
+ desc "publicip SUBCOMMAND ...ARGS", "Manage public ip addresses"
98
96
  subcommand "publicip", Publicip
97
+
98
+ desc "capacity SUBCOMMAND ...ARGS", "Lists all the system wide capacities"
99
+ subcommand "capacity", Capacity
99
100
  end
100
101
  end
@@ -1,15 +1,22 @@
1
- class Account < Thor
1
+ class Account < CloudstackCli::Base
2
2
 
3
- desc 'account list [NAME]', 'list accounts'
3
+ TYPES = {
4
+ 0 => 'user',
5
+ 1 => 'domain-admin',
6
+ 2 => 'admin'
7
+ }
8
+
9
+ desc 'list [NAME]', 'list accounts'
4
10
  def list(name = nil)
5
- cs_cli = CloudstackCli::Helper.new(options[:config])
6
- accounts = cs_cli.list_accounts(name)
11
+ accounts = client.list_accounts({name: name})
7
12
  if accounts.size < 1
8
13
  puts "No accounts found"
9
14
  else
15
+ table = [["Name", "Type", "Domain"]]
10
16
  accounts.each do |account|
11
- puts "#{account['name']} - #{account['domain']}"
17
+ table << [account['name'], TYPES[account['accounttype']], account['domain']]
12
18
  end
19
+ print_table table
13
20
  end
14
21
  end
15
22
 
@@ -0,0 +1,34 @@
1
+ class Capacity < CloudstackCli::Base
2
+ TYPES = {
3
+ 0 => "Memory",
4
+ 1 => "CPU",
5
+ 2 => "Storage",
6
+ 3 => "Storage Allocated",
7
+ 4 => "Public IP's",
8
+ 5 => "Private IP's",
9
+ 6 => "Secondary Storage",
10
+ 7 => "VLAN",
11
+ 8 => "Direct Attached Public IP's",
12
+ 9 => "Local Storage"
13
+ }
14
+
15
+ desc "list", "list system capacity"
16
+ option :zone
17
+ def list
18
+ capacities = client.list_capacity
19
+ table = []
20
+ header = ["Zone", "Type", "Capacity Used", "Capacity Total", "Used"]
21
+ capacities.each do |c|
22
+ table << [
23
+ c['zonename'],
24
+ TYPES[c['type']],
25
+ c['capacityused'],
26
+ c['capacitytotal'],
27
+ "#{c['percentused']}%"
28
+ ]
29
+ end
30
+ table = table.sort {|a, b| [a[0], a[1]] <=> [b[0], b[1]]}.insert(0, header)
31
+ print_table table
32
+ end
33
+
34
+ end
@@ -1,15 +1,16 @@
1
- class Domain < Thor
1
+ class Domain < CloudstackCli::Base
2
2
 
3
- desc 'domain list [NAME]', 'list domains'
3
+ desc 'list [NAME]', 'list domains'
4
4
  def list(name = nil)
5
- cs_cli = CloudstackCli::Helper.new(options[:config])
6
- domains = cs_cli.domains(name)
5
+ domains = client.list_domains(name)
7
6
  if domains.size < 1
8
7
  puts "No domains found"
9
8
  else
9
+ table = [["Name", "Path"]]
10
10
  domains.each do |domain|
11
- puts "#{domain['name']}"
11
+ table << [domain['name'], domain['path']]
12
12
  end
13
+ print_table table
13
14
  end
14
15
  end
15
16
 
@@ -1,59 +1,53 @@
1
- class Lb < Thor
1
+ class Lb < CloudstackCli::Base
2
2
 
3
- desc "lb list", "list load balancer rules"
3
+ desc "list", "list load balancer rules"
4
4
  option :project
5
5
  def list
6
- cs_cli = CloudstackCli::Helper.new(options[:config])
7
- if options[:project]
8
- project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
9
- exit_now! "Project '#{options[:project]}' not found" unless project
10
- end
11
-
12
- rules = cs_cli.list_load_balancer_rules(project ? project['id'] : nil)
6
+ project = find_project if options[:project]
7
+ rules = client.list_load_balancer_rules(
8
+ { project_name: project ? project['name'] : nil }
9
+ )
13
10
  if rules.size < 1
14
11
  puts "No load balancer rules found"
15
12
  else
13
+ table = [["Name", "Public-IP", "Public-Port"]]
16
14
  rules.each do |rule|
17
- puts "#{rule['name']} - #{rule['publicip']}:#{rule['publicport']}"
15
+ table << [rule['name'], rule['publicip'], rule['publicport']]
18
16
  end
17
+ print_table table
19
18
  end
20
19
  end
21
20
 
22
- desc "lb create NAME", "create load balancer rule"
21
+ desc "create NAME", "create load balancer rule"
23
22
  option :project
24
- option :ip, :required => true
25
- option :public_port, :required => true
23
+ option :ip, required: true
24
+ option :public_port, required: true
26
25
  option :private_port
27
26
  def create(name)
28
- cs_cli = CloudstackCli::Helper.new(options[:config])
29
- if options[:project]
30
- project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
31
- exit_now! "Project '#{options[:project]}' not found" unless project
32
- end
33
-
27
+ project = find_project
34
28
  options[:private_port] = options[:public_port] if options[:private_port] == nil
35
-
36
- rule = cs_cli.create_load_balancer_rule(
29
+ say "Create rule #{name}...", :yellow
30
+ rule = client.create_load_balancer_rule(
37
31
  name,
38
32
  options[:ip],
39
33
  options[:private_port],
40
34
  options[:public_port],
41
35
  )
36
+ say "OK!", :green
42
37
  end
43
38
 
44
- desc "lb add NAME", "assign servers to balancer rule"
45
- option :project
39
+ desc "add NAME", "assign servers to balancer rule"
46
40
  option :servers, required: true, type: :array, description: 'server names'
47
41
  def add(name)
48
- cs_cli = CloudstackCli::Helper.new(options[:config])
49
- if options[:project]
50
- project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
51
- exit_now! "Project '#{options[:project]}' not found" unless project
52
- end
53
-
54
- rule = cs_cli.assign_to_load_balancer_rule(
42
+ say "Add #{names.join(', ')} to rule #{id}...", :yellow
43
+ rule = client.assign_to_load_balancer_rule(
55
44
  name,
56
45
  options[:servers],
57
46
  )
47
+ if rule['success']
48
+ say "OK!", :green
49
+ else
50
+ say "Failed!", :red
51
+ end
58
52
  end
59
53
  end
@@ -1,71 +1,50 @@
1
- class Network < Thor
2
- include CommandLineReporter
1
+ class Network < CloudstackCli::Base
3
2
 
4
- desc "network create NAME", "create network"
3
+ desc "create NAME", "create network"
5
4
  def create(name)
6
-
7
-
5
+ # TODO
8
6
  end
9
7
 
10
- desc "network list", "list networks"
8
+ desc "list", "list networks"
11
9
  option :project
12
10
  option :physical, type: :boolean
13
11
  def list
14
- cs_cli = CloudstackCli::Helper.new(options[:config])
15
- if options[:project]
16
- project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
17
- raise "Project '#{options[:project]}' not found" unless project
18
- end
19
-
12
+ project = find_project if options[:project]
20
13
  if options[:physical]
21
- networks = cs_cli.physical_networks
14
+ networks = client.list_physical_networks
22
15
  if networks.size < 1
23
16
  puts "No networks found"
24
17
  else
25
- table(border: true) do
26
- row do
27
- column 'ID', width: 40
28
- column 'Name', width: 30
29
- column 'Zone ID', width: 14 unless options[:project]
30
- column 'State'
31
- end
32
- networks.each do |network|
33
- row do
34
- column network["id"]
35
- column network["name"]
36
- column network["zoneid"]
37
- column network["state"]
38
- end
39
- end
18
+ table = [['Name', 'State', 'ID', 'Zone ID']]
19
+ networks.each do |network|
20
+ table << [
21
+ network["name"],
22
+ network["state"],
23
+ network["id"],
24
+ network["zoneid"]
25
+ ]
40
26
  end
27
+ print_table table
41
28
  end
42
29
  else
43
- networks = cs_cli.networks(project ? project['id'] : -1)
30
+ networks = client.list_networks(project ? project['id'] : -1)
44
31
  if networks.size < 1
45
32
  puts "No networks found"
46
33
  else
47
- table(border: true) do
48
- row do
49
- column 'ID', width: 40
50
- column 'Name', width: 30
51
- column 'Displaytext', width: 30
52
- column 'Account', width: 14 unless options[:project]
53
- column 'Project', width: 14 if options[:listall] || options[:project]
54
- column 'State'
55
- end
56
- networks.each do |network|
57
- row do
58
- column network["id"]
59
- column network["name"]
60
- column network["displaytext"]
61
- column network["account"] unless options[:project]
62
- column network["project"] if options[:listall] || options[:project]
63
- column network["state"]
64
- end
65
- end
34
+ table = [["Name", "Displaytext", "Account", "Project", "State", "ID"]]
35
+ networks.each do |network|
36
+ table << [
37
+ network["name"],
38
+ network["displaytext"],
39
+ network["account"],
40
+ network["project"],
41
+ network["state"],
42
+ network["id"]
43
+ ]
66
44
  end
45
+ print_table table
67
46
  end
68
47
  end
69
-
70
48
  end
49
+
71
50
  end