cloudstack-cli 0.0.5 → 0.1.0

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