cloudstack-cli 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/lib/cloudstack-cli/base.rb +7 -1
  4. data/lib/cloudstack-cli/cli.rb +19 -2
  5. data/lib/cloudstack-cli/commands/account.rb +1 -1
  6. data/lib/cloudstack-cli/commands/capacity.rb +2 -2
  7. data/lib/cloudstack-cli/commands/cluster.rb +20 -0
  8. data/lib/cloudstack-cli/commands/disk_offering.rb +1 -1
  9. data/lib/cloudstack-cli/commands/domain.rb +1 -1
  10. data/lib/cloudstack-cli/commands/ip_address.rb +10 -5
  11. data/lib/cloudstack-cli/commands/job.rb +30 -0
  12. data/lib/cloudstack-cli/commands/load_balancer.rb +1 -1
  13. data/lib/cloudstack-cli/commands/network.rb +0 -5
  14. data/lib/cloudstack-cli/commands/offering.rb +1 -1
  15. data/lib/cloudstack-cli/commands/pod.rb +20 -0
  16. data/lib/cloudstack-cli/commands/project.rb +1 -1
  17. data/lib/cloudstack-cli/commands/router.rb +45 -15
  18. data/lib/cloudstack-cli/commands/server.rb +9 -11
  19. data/lib/cloudstack-cli/commands/snapshot.rb +24 -0
  20. data/lib/cloudstack-cli/commands/ssh_key_pairs.rb +46 -0
  21. data/lib/cloudstack-cli/commands/stack.rb +0 -1
  22. data/lib/cloudstack-cli/commands/user.rb +28 -0
  23. data/lib/cloudstack-cli/helper.rb +30 -0
  24. data/lib/cloudstack-cli/version.rb +1 -1
  25. data/lib/cloudstack-client/client.rb +4 -4
  26. data/lib/cloudstack-client/commands/cluster.rb +19 -0
  27. data/lib/cloudstack-client/commands/ip_address.rb +4 -0
  28. data/lib/cloudstack-client/commands/job.rb +29 -0
  29. data/lib/cloudstack-client/commands/pod.rb +19 -0
  30. data/lib/cloudstack-client/commands/router.rb +20 -6
  31. data/lib/cloudstack-client/commands/snapshot.rb +40 -0
  32. data/lib/cloudstack-client/commands/ssh_key_pair.rb +105 -0
  33. data/lib/cloudstack-client/commands/user.rb +32 -0
  34. data/lib/cloudstack-client/commands/volume.rb +20 -0
  35. data/lib/cloudstack-client/version.rb +1 -1
  36. metadata +15 -3
  37. data/lib/cloudstack-client/commands/command_template +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad30d2392877c54e681e2e916aac9ee73078e956
4
- data.tar.gz: 8becb1fb0bc315c5f7d450ce6db62b48a14c63ff
3
+ metadata.gz: 7554f6d7a5dc9ae9a56557edfb3a39b7b63778c1
4
+ data.tar.gz: db3d8020dc9497700d7a3e65594c5a8a35140a78
5
5
  SHA512:
6
- metadata.gz: 4bd74f7c795a3edde19e4531b7925c3c8e39025db89639e85ad01bc9fd997ebeed105a3f89b7a5cedb0ce509147165019850b08ea376cbb3ffe9bf83d0690a4a
7
- data.tar.gz: 79672ddb07f8e47bfb53c3c6b8d5c4c781d64e64fb513c4249145f18a5ff88d272839a982e5c8a064c240814fb3c91f9ab66c47a92eb114b1708f96e8bdbff33
6
+ metadata.gz: 15451bfd39437d023cba04e4da98424e1d7b66286647a538b4bb3c7c03335b00d47e16e32593a0e9f3180e76d6313ea460353bd270561af193720e89e4db93a8
7
+ data.tar.gz: a68d0d706ffa1e7a091eff9c8e540ea7cadaeaf4086042c2555f7bc24c306c9ef80ffbbb264269289cb856036a34787cbf96f1fc20e71060b0ac5da45824e487
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloudstack-cli (0.2.2)
4
+ cloudstack-cli (0.3.1)
5
5
  thor (~> 0.18.1)
6
6
 
7
7
  GEM
@@ -4,6 +4,8 @@ require "yaml"
4
4
  module CloudstackCli
5
5
  class Base < Thor
6
6
  include Thor::Actions
7
+ include CloudstackCli::Helper
8
+
7
9
  attr_reader :config
8
10
 
9
11
  # catch control-c and exit
@@ -29,11 +31,15 @@ module CloudstackCli
29
31
  end
30
32
 
31
33
  def load_configuration(config_file = options[:config], env = options[:environment])
34
+ unless File.exists?(config_file)
35
+ say "Configuration file #{config_file} not found.", :red
36
+ say "Please run \'cs setup\' to create one."
37
+ exit 1
38
+ end
32
39
  begin
33
40
  config = YAML::load(IO.read(config_file))
34
41
  rescue
35
42
  error "Can't load configuration from file #{config_file}."
36
- error "To create a new configuration file run \"cs setup\"."
37
43
  exit 1
38
44
  end
39
45
  if env
@@ -45,7 +45,6 @@ module CloudstackCli
45
45
  old_config = YAML::load(IO.read(file))
46
46
  rescue
47
47
  error "Can't load configuration from file #{config_file}."
48
- error "To create a new configuration file run \"cs setup\"."
49
48
  exit 1
50
49
  end
51
50
  say "Warning: #{file} already exists.", :red
@@ -73,6 +72,12 @@ module CloudstackCli
73
72
  desc "zone SUBCOMMAND ...ARGS", "Manage zones"
74
73
  subcommand "zone", Zone
75
74
 
75
+ desc "pod SUBCOMMAND ...ARGS", "List pods"
76
+ subcommand "pod", Pod
77
+
78
+ desc "cluster SUBCOMMAND ...ARGS", "List clusters"
79
+ subcommand "cluster", Cluster
80
+
76
81
  desc "project SUBCOMMAND ...ARGS", "Manage servers"
77
82
  subcommand "project", Project
78
83
 
@@ -106,12 +111,18 @@ module CloudstackCli
106
111
  desc "volume SUBCOMMAND ...ARGS", "Manage volumes"
107
112
  subcommand "volume", Volume
108
113
 
114
+ desc "snapshot SUBCOMMAND ...ARGS", "Manage snapshots"
115
+ subcommand "snapshot", Snapshot
116
+
109
117
  desc "stack SUBCOMMAND ...ARGS", "Manage stacks"
110
118
  subcommand "stack", Stack
111
119
 
112
120
  desc "account SUBCOMMAND ...ARGS", "Manage accounts"
113
121
  subcommand "account", Account
114
122
 
123
+ desc "user SUBCOMMAND ...ARGS", "Manage users"
124
+ subcommand "user", User
125
+
115
126
  desc "domain SUBCOMMAND ...ARGS", "Manage domains"
116
127
  subcommand "domain", Domain
117
128
 
@@ -121,7 +132,13 @@ module CloudstackCli
121
132
  desc "capacity SUBCOMMAND ...ARGS", "Lists all the system wide capacities"
122
133
  subcommand "capacity", Capacity
123
134
 
124
- desc "port_rules SUBCOMMAND ...ARGS", "Manage portforwarding rules"
135
+ desc "port_rule SUBCOMMAND ...ARGS", "Manage portforwarding rules"
125
136
  subcommand "port_rule", PortRule
137
+
138
+ desc "job SUBCOMMAND ...ARGS", "Display async jobs"
139
+ subcommand "job", Job
140
+
141
+ desc "ssh_key_pair SUBCOMMAND ...ARGS", "Manage ssh key pairs"
142
+ subcommand "ssh_key_pair", SshKeyPair
126
143
  end
127
144
  end
@@ -10,7 +10,7 @@ class Account < CloudstackCli::Base
10
10
  def list(name = nil)
11
11
  accounts = client.list_accounts({name: name})
12
12
  if accounts.size < 1
13
- puts "No accounts found"
13
+ puts "No accounts found."
14
14
  else
15
15
  table = [["Name", "Type", "Domain"]]
16
16
  accounts.each do |account|
@@ -1,5 +1,5 @@
1
1
  class Capacity < CloudstackCli::Base
2
- TYPES = {
2
+ CAPACITY_TYPES = {
3
3
  0 => "Memory",
4
4
  1 => "CPU",
5
5
  2 => "Storage",
@@ -21,7 +21,7 @@ class Capacity < CloudstackCli::Base
21
21
  capacities.each do |c|
22
22
  table << [
23
23
  c['zonename'],
24
- TYPES[c['type']],
24
+ CAPACITY_TYPES[c['type']],
25
25
  c['capacityused'],
26
26
  c['capacitytotal'],
27
27
  "#{c['percentused']}%"
@@ -0,0 +1,20 @@
1
+ class Cluster < CloudstackCli::Base
2
+
3
+ desc 'list', 'list clusters'
4
+ def list
5
+ clusters = client.list_clusters(options)
6
+ if clusters.size < 1
7
+ say "No clusters found."
8
+ else
9
+ table = [["Name", "Pod-Name", "Type", "Zone"]]
10
+ clusters.each do |cluster|
11
+ table << [
12
+ cluster['name'], cluster['podname'],
13
+ cluster['hypervisortype'], cluster['zonename']
14
+ ]
15
+ end
16
+ print_table table
17
+ end
18
+ end
19
+
20
+ end
@@ -5,7 +5,7 @@ class DiskOffering < CloudstackCli::Base
5
5
  def list
6
6
  offerings = client.list_disk_offerings(options[:domain])
7
7
  if offerings.size < 1
8
- puts "No offerings found"
8
+ puts "No offerings found."
9
9
  else
10
10
  table = [["Name", "Displaytext", "Domain", "ID"]]
11
11
  offerings.each do |offering|
@@ -4,7 +4,7 @@ class Domain < CloudstackCli::Base
4
4
  def list(name = nil)
5
5
  domains = client.list_domains(name)
6
6
  if domains.size < 1
7
- puts "No domains found"
7
+ puts "No domains found."
8
8
  else
9
9
  table = [["Name", "Path"]]
10
10
  domains.each do |domain|
@@ -2,7 +2,7 @@ class IpAddress < CloudstackCli::Base
2
2
 
3
3
  desc "release ID", "release public IP address"
4
4
  def release(id)
5
- puts "OK" if client.disassociate_ip_address(id)
5
+ say("OK", :green) if client.disassociate_ip_address(id)
6
6
  end
7
7
 
8
8
  desc "assign NETWORK", "assign a public IP address"
@@ -24,10 +24,15 @@ class IpAddress < CloudstackCli::Base
24
24
  option :listall
25
25
  def list
26
26
  table = [["Address", "Account", "Zone"]]
27
- client.list_public_ip_addresses(options).each do |address|
28
- table << [address["ipaddress"], address["account"], address["zonename"]]
29
- end
30
- print_table table
27
+ addresses = client.list_public_ip_addresses(options)
28
+ if addresses.size < 1
29
+ say "No ip addresses found."
30
+ else
31
+ addresses.each do |address|
32
+ table << [address["ipaddress"], address["account"], address["zonename"]]
33
+ end
34
+ print_table table
35
+ end
31
36
  end
32
37
 
33
38
  end
@@ -0,0 +1,30 @@
1
+ class Job < CloudstackCli::Base
2
+
3
+ desc 'list', 'list async jobs'
4
+ def list
5
+ jobs = client.list_jobs()
6
+ if jobs.size < 1
7
+ say "No jobs found."
8
+ else
9
+ table = [["Command", "Created", "Status", "ID", "User ID"]]
10
+ jobs.each do |job|
11
+ table << [job['cmd'].split('.')[-1], job['created'], job['jobstatus'], job['jobid'], job['userid']]
12
+ end
13
+ print_table table
14
+ end
15
+ end
16
+
17
+ desc 'query ID', 'query async job'
18
+ def query(id)
19
+ job = client.query_job(id)
20
+ job.each do |key, value|
21
+ say "#{key} : "
22
+ if value.is_a?(Hash)
23
+ value.each {|subkey, subvalue| say " #{subkey} : #{subvalue}"}
24
+ else
25
+ say(value)
26
+ end
27
+ end
28
+ end
29
+
30
+ end
@@ -8,7 +8,7 @@ class LoadBalancer < CloudstackCli::Base
8
8
  { project_name: project ? project['name'] : nil }
9
9
  )
10
10
  if rules.size < 1
11
- puts "No load balancer rules found"
11
+ puts "No load balancer rules found."
12
12
  else
13
13
  table = [["Name", "Public-IP", "Public-Port"]]
14
14
  rules.each do |rule|
@@ -1,10 +1,5 @@
1
1
  class Network < CloudstackCli::Base
2
2
 
3
- desc "create NAME", "create network"
4
- def create(name)
5
- # TODO
6
- end
7
-
8
3
  desc "default", "get the default network"
9
4
  option :zone
10
5
  def default
@@ -5,7 +5,7 @@ class Offering < CloudstackCli::Base
5
5
  def list
6
6
  offerings = client.list_service_offerings(options[:domain])
7
7
  if offerings.size < 1
8
- puts "No offerings found"
8
+ puts "No offerings found."
9
9
  else
10
10
  table = [["Name", "Displaytext", "Domain", "ID"]]
11
11
  offerings.each do |offering|
@@ -0,0 +1,20 @@
1
+ class Pod < CloudstackCli::Base
2
+
3
+ desc 'list', 'list pods'
4
+ def list
5
+ pods = client.list_pods(options)
6
+ if pods.size < 1
7
+ say "No pods found."
8
+ else
9
+ table = [["Name", "Start-IP", "End-IP", "Zone"]]
10
+ pods.each do |pod|
11
+ table << [
12
+ pod['name'], pod['startip'],
13
+ pod['endip'], pod['zonename']
14
+ ]
15
+ end
16
+ print_table table
17
+ end
18
+ end
19
+
20
+ end
@@ -4,7 +4,7 @@ class Project < CloudstackCli::Base
4
4
  def list
5
5
  projects = client.list_projects
6
6
  if projects.size < 1
7
- puts "No projects found"
7
+ puts "No projects found."
8
8
  else
9
9
  table = [["Name", "Displaytext", "Domain"]]
10
10
  projects.each do |project|
@@ -44,7 +44,7 @@ class Router < CloudstackCli::Base
44
44
  say "No routers found."
45
45
  else
46
46
  table = [[
47
- 'Name', 'Zone', 'Account', 'Project', 'Redundant-State', 'Linklocal IP', 'Status', 'ID'
47
+ 'Name', 'Zone', 'Account', 'Project', 'Redundant-State', 'IP', 'Linklocal IP', 'Status', 'ID'
48
48
  ]]
49
49
  table[0].delete('ID') unless options[:showid]
50
50
  routers.each do |router|
@@ -54,6 +54,7 @@ class Router < CloudstackCli::Base
54
54
  router["account"],
55
55
  router["project"],
56
56
  router["redundantstate"],
57
+ router["nic"].first ? router["nic"].first['ipaddress'] : "",
57
58
  router["linklocalip"],
58
59
  router["state"],
59
60
  router["id"]
@@ -71,14 +72,14 @@ class Router < CloudstackCli::Base
71
72
  exit unless yes?("Start the routers above? [y/N]:", :magenta)
72
73
  routers.each do |router|
73
74
  say "Start router #{router['name']}... "
74
- say "job started ", :green if job = client.start_router(router['id'])
75
+ say "job started ", :green if job = client.start_router(router['id'], async: false)
75
76
  say "(jobid: #{job['jobid']})"
76
77
  end
77
78
  when "stop"
78
79
  exit unless yes?("Stop the routers above? [y/N]:", :magenta)
79
80
  routers.each do |router|
80
81
  say "Stop router #{router['name']}... "
81
- say "job started ", :green if job = client.stop_router(router['id'])
82
+ say "job started ", :green if job = client.stop_router(router['id'], async: false)
82
83
  say "(jobid: #{job['jobid']})"
83
84
  end
84
85
  else
@@ -88,22 +89,51 @@ class Router < CloudstackCli::Base
88
89
  end
89
90
  end
90
91
 
91
- desc "stop ID", "stop virtual router"
92
- def stop(id)
93
- exit unless yes?("Stop the router with ID #{id}?", :magenta)
94
- client.stop_router id
92
+ desc "stop NAME [NAME2 ..]", "stop virtual router(s)"
93
+ option :force, description: "stop without asking", type: :boolean, aliases: '-f'
94
+ def stop(*names)
95
+ jobs = []
96
+ names.each do |name|
97
+ router = get_router(name)
98
+ exit unless options[:force] || yes?("Stop router #{router['name']}?", :magenta)
99
+ jobs << {id: client.stop_router(router['id'], async: false)['jobid'], name: "Stop router #{name}"}
100
+ end
101
+ puts
102
+ watch_jobs(jobs)
95
103
  end
96
104
 
97
- desc "start ID", "start virtual router"
98
- def start(id)
99
- exit unless yes?("Start the router with ID #{id}?", :magenta)
100
- client.start_router id
105
+ desc "start NAME [NAME2 ..]", "start virtual router(s)"
106
+ option :force, description: "start without asking", type: :boolean, aliases: '-f'
107
+ def start(*names)
108
+ jobs = []
109
+ names.each do |name|
110
+ router = get_router(name)
111
+ exit unless options[:force] || yes?("Start router #{router['name']}?", :magenta)
112
+ jobs << {id: client.start_router(router['id'], async: false)['jobid'], name: "Start router #{name}"}
113
+ end
114
+ puts
115
+ watch_jobs(jobs)
101
116
  end
102
117
 
103
- desc "destroy ID", "destroy virtual router"
104
- def destroy(id)
105
- exit unless yes?("Destroy the router with ID #{id}?", :magenta)
106
- say "OK", :green if client.destroy_router(id)
118
+ desc "destroy NAME [NAME2 ..]", "destroy virtual router(s)"
119
+ option :force, description: "destroy without asking", type: :boolean, aliases: '-f'
120
+ def destroy(*names)
121
+ names.each do |name|
122
+ router = get_router(name)
123
+ exit unless options[:force] || yes?("Destroy router #{router['name']}?", :magenta)
124
+ say "OK", :green if client.destroy_router(router['id'])
125
+ puts
126
+ end
127
+ end
128
+
129
+ no_commands do
130
+ def get_router(name)
131
+ unless router = client.get_router(name)
132
+ say "Can't find router with name #{name}.", :red
133
+ exit 1
134
+ end
135
+ router
136
+ end
107
137
  end
108
138
 
109
139
  end
@@ -1,5 +1,4 @@
1
1
  class Server < CloudstackCli::Base
2
- include CloudstackCli::Helper
3
2
 
4
3
  desc "list", "list servers"
5
4
  option :project
@@ -32,7 +31,7 @@ class Server < CloudstackCli::Base
32
31
  end
33
32
  end
34
33
 
35
- desc "create NAME", "create a server"
34
+ desc "create NAME [NAME2 ...]", "create server(s)"
36
35
  option :template, aliases: '-t', desc: "name of the template"
37
36
  option :iso, desc: "name of the iso", desc: "name of the iso template"
38
37
  option :offering, aliases: '-o', required: true, desc: "computing offering name"
@@ -51,20 +50,19 @@ class Server < CloudstackCli::Base
51
50
  bootstrap_server(options.merge({name: name}))
52
51
  end
53
52
 
54
- desc "destroy NAME [NAME2 ..]", "destroy a server"
53
+ desc "destroy NAME [NAME2 ..]", "destroy server(s)"
55
54
  option :project
56
55
  option :force, description: "destroy without asking", type: :boolean, aliases: '-f'
57
- def destroy(*name)
56
+ def destroy(*names)
58
57
  projectid = find_project['id'] if options[:project]
59
-
60
- name.each do |server_name|
61
- server = client.get_server(server_name, projectid)
58
+ names.each do |name|
59
+ server = client.get_server(name, projectid)
62
60
  unless server
63
- say "Server #{server_name} not found.", :red
61
+ say "Server #{name} not found.", :red
64
62
  else
65
- ask = "Destroy #{server_name} (#{server['state']})?"
66
- if options[:force] == true || yes?(ask, :yellow)
67
- say "destroying #{server_name} "
63
+ ask = "Destroy #{name} (#{server['state']})?"
64
+ if options[:force] || yes?(ask, :yellow)
65
+ say "destroying #{name} "
68
66
  client.destroy_server(server["id"])
69
67
  puts
70
68
  end
@@ -0,0 +1,24 @@
1
+ class Snapshot < CloudstackCli::Base
2
+
3
+ desc 'list', 'list snapshots'
4
+ option :account
5
+ option :project
6
+ option :domain
7
+ option :listall
8
+ def list
9
+ snapshots = client.list_snapshots(options)
10
+ if snapshots.size < 1
11
+ say "No snapshots found."
12
+ else
13
+ table = [["Account", "Name", "Volume", "Created", "Type"]]
14
+ snapshots.each do |snapshot|
15
+ table << [
16
+ snapshot['account'], snapshot['name'], snapshot['volumename'],
17
+ snapshot['created'], snapshot['snapshottype']
18
+ ]
19
+ end
20
+ print_table table
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,46 @@
1
+ class SshKeyPair < CloudstackCli::Base
2
+
3
+ desc 'list', 'list ssh key pairs'
4
+ option :listall
5
+ option :account
6
+ option :project
7
+ def list
8
+ pairs = client.list_ssh_key_pairs(options)
9
+ if pairs.size < 1
10
+ say "No ssh key pairs found."
11
+ else
12
+ table = [["Name", "Fingerprint"]]
13
+ pairs.each do |pair|
14
+ table << [pair['name'], pair['fingerprint']]
15
+ end
16
+ print_table table
17
+ end
18
+ end
19
+
20
+ desc 'create NAME', 'create ssh key pair'
21
+ option :account
22
+ option :project
23
+ def create(name)
24
+ pair = client.create_ssh_key_pair(name, options)
25
+ say "Name : #{pair['name']}"
26
+ say "Fingerprint : #{pair['fingerprint']}"
27
+ say "Privatekey:"
28
+ say pair['privatekey']
29
+ end
30
+
31
+ desc 'delete NAME', 'delete ssh key pair'
32
+ option :account
33
+ option :project
34
+ option :force, aliases: '-f', desc: "delete without asking"
35
+ def delete(name)
36
+ if options[:force] || yes?("Delete ssh key pair #{name}?", :yellow)
37
+ if client.delete_ssh_key_pair(name, options)['success'] == "true"
38
+ say("OK", :green)
39
+ else
40
+ say("Failed", :red)
41
+ exit 1
42
+ end
43
+ end
44
+ end
45
+
46
+ end
@@ -1,5 +1,4 @@
1
1
  class Stack < CloudstackCli::Base
2
- include CloudstackCli::Helper
3
2
 
4
3
  desc "create STACKFILE", "create a stack of servers"
5
4
  def create(stackfile)
@@ -0,0 +1,28 @@
1
+ class User < CloudstackCli::Base
2
+
3
+ USER_TYPES = {
4
+ 0 => 'user',
5
+ 1 => 'domain-admin',
6
+ 2 => 'admin'
7
+ }
8
+
9
+ desc 'list', 'list async jobs'
10
+ option :listall
11
+ option :account
12
+ def list
13
+ users = client.list_users(options)
14
+ if users.size < 1
15
+ say "No users found."
16
+ else
17
+ table = [["Account", "Type", "Name", "Email", "State", "Domain"]]
18
+ users.each do |user|
19
+ table << [
20
+ user['account'], USER_TYPES[user['accounttype']], "#{user['firstname']} #{user['lastname']}",
21
+ user['email'], user['state'], user['domain']
22
+ ]
23
+ end
24
+ print_table table
25
+ end
26
+ end
27
+
28
+ end
@@ -11,6 +11,36 @@ module CloudstackCli
11
11
  number < 0 ? 0 : number
12
12
  end
13
13
 
14
+ def get_async_job_status(ids)
15
+ ids.map do |id|
16
+ client.query_job(id)['jobstatus']
17
+ end
18
+ end
19
+
20
+ def watch_jobs(jobs)
21
+ chars = %w(| / - \\)
22
+ async_state = {0 => "running", 1 => "completed", 2 => "error"}
23
+ status = get_async_job_status(jobs.map {|job| job[:id]})
24
+ call = 0
25
+ while status.include?(0) do
26
+ status = call.modulo(40) == 0 ? get_async_job_status(jobs.map {|job| job[:id]}) : status
27
+ print ("\r" + "\e[A\e[K" * (status.size)) if call > 0
28
+
29
+ status.each_with_index do |job_status, i|
30
+ puts "#{jobs[i][:name]} : job #{async_state[job_status]} #{chars[0]}"
31
+ end
32
+
33
+ sleep 0.1
34
+ chars.push chars.shift
35
+ call += 1
36
+ end
37
+
38
+ print ("\r" + "\e[A\e[K" * (status.size))
39
+ status.each_with_index do |job_status, i|
40
+ puts "#{jobs[i][:name]} : job #{async_state[job_status]}"
41
+ end
42
+ end
43
+
14
44
  def bootstrap_server(args = {})
15
45
  if args[:project] && project = client(quiet: true).get_project(args[:project])
16
46
  project_id = project["id"]
@@ -1,3 +1,3 @@
1
1
  module CloudstackCli
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -11,7 +11,7 @@ module CloudstackClient
11
11
  class Connection
12
12
 
13
13
  @@async_poll_interval = 2.0
14
- @@async_timeout = 300
14
+ @@async_timeout = 400
15
15
 
16
16
  # include all commands
17
17
  Dir.glob(File.dirname(__FILE__) + "/commands/*.rb").each do |file|
@@ -62,7 +62,7 @@ module CloudstackClient
62
62
  exit 1
63
63
  end
64
64
 
65
- if !response.is_a?(Net::HTTPOK) then
65
+ if !response.is_a?(Net::HTTPOK)
66
66
  puts "Error #{response.code}: #{response.message}"
67
67
  puts JSON.pretty_generate(JSON.parse(response.body))
68
68
  puts "URL: #{url}"
@@ -99,9 +99,9 @@ module CloudstackClient
99
99
 
100
100
  print "." if @verbose
101
101
 
102
- if status == 1 then
102
+ if status == 1
103
103
  return json['jobresult']
104
- elsif status == 2 then
104
+ elsif status == 2
105
105
  puts
106
106
  puts "Request failed (#{json['jobresultcode']}): #{json['jobresult']}"
107
107
  exit 1
@@ -0,0 +1,19 @@
1
+ module CloudstackClient
2
+
3
+ module Cluster
4
+
5
+ ##
6
+ # Lists clusters.
7
+
8
+ def list_clusters(args = {})
9
+ params = {
10
+ 'command' => 'listClusters',
11
+ }
12
+
13
+ json = send_request(params)
14
+ json['cluster'] || []
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -12,6 +12,10 @@ module CloudstackClient
12
12
  }
13
13
  if args[:project]
14
14
  project = get_project(args[:project])
15
+ unless project
16
+ puts "Error: project #{args[:project]} not found."
17
+ exit 1
18
+ end
15
19
  params['projectid'] = project['id']
16
20
  end
17
21
  if args[:account]
@@ -0,0 +1,29 @@
1
+ module CloudstackClient
2
+
3
+ module Job
4
+
5
+ ##
6
+ # Retrieves the current status of asynchronous job.
7
+
8
+ def query_job(id)
9
+ params = {
10
+ 'command' => 'queryAsyncJobResult',
11
+ 'jobid' => id,
12
+ }
13
+ send_request(params)
14
+ end
15
+
16
+ ##
17
+ # Lists all pending asynchronous jobs for the account.
18
+
19
+ def list_jobs(opts = {})
20
+ params = {
21
+ 'command' => 'listAsyncJobs'
22
+ }
23
+ params['listall'] = true if opts[:listall]
24
+ send_request(params)['asyncjobs']
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,19 @@
1
+ module CloudstackClient
2
+
3
+ module Pod
4
+
5
+ ##
6
+ # Lists pods.
7
+
8
+ def list_pods(args = {})
9
+ params = {
10
+ 'command' => 'listPods',
11
+ }
12
+
13
+ json = send_request(params)
14
+ json['pod'] || []
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -2,6 +2,20 @@ module CloudstackClient
2
2
 
3
3
  module Router
4
4
 
5
+ ##
6
+ # Get a router with a given name.
7
+
8
+ def get_router(name)
9
+ params = {
10
+ 'command' => 'listRouters',
11
+ 'listall' => 'true',
12
+ 'name' => name
13
+ }
14
+
15
+ json = send_request(params)
16
+ json['router'] ? json['router'].first : nil
17
+ end
18
+
5
19
  ##
6
20
  # Lists all virtual routers.
7
21
 
@@ -39,34 +53,34 @@ module CloudstackClient
39
53
  ##
40
54
  # Destroy virtual router.
41
55
 
42
- def destroy_router(id, async = false)
56
+ def destroy_router(id, opts = {async: true})
43
57
  params = {
44
58
  'command' => 'destroyRouter',
45
59
  'id' => id
46
60
  }
47
- async ? send_async_request(params) : send_request(params)
61
+ opts[:async] ? send_async_request(params)['router'] : send_request(params)
48
62
  end
49
63
 
50
64
  ##
51
65
  # Start virtual router.
52
66
 
53
- def start_router(id, async = false)
67
+ def start_router(id, opts = {async: true})
54
68
  params = {
55
69
  'command' => 'startRouter',
56
70
  'id' => id
57
71
  }
58
- async ? send_async_request(params) : send_request(params)
72
+ opts[:async] ? send_async_request(params)['router'] : send_request(params)
59
73
  end
60
74
 
61
75
  ##
62
76
  # Stop virtual router.
63
77
 
64
- def stop_router(id, async = false)
78
+ def stop_router(id, opts = {async: true})
65
79
  params = {
66
80
  'command' => 'stopRouter',
67
81
  'id' => id
68
82
  }
69
- async ? send_async_request(params) : send_request(params)
83
+ opts[:async] ? send_async_request(params)['router'] : send_request(params)
70
84
  end
71
85
 
72
86
  end
@@ -0,0 +1,40 @@
1
+ module CloudstackClient
2
+
3
+ module Snapshot
4
+
5
+ ##
6
+ # Lists snapshots.
7
+
8
+ def list_snapshots(args = {})
9
+ params = {
10
+ 'command' => 'listSnapshots',
11
+ 'isrecursive' => 'true'
12
+ }
13
+ params['name'] = args[:name] if args[:name]
14
+
15
+ if args[:project]
16
+ project = get_project(args[:project])
17
+ unless project
18
+ puts "Error: project #{args[:project]} not found."
19
+ exit 1
20
+ end
21
+ params['projectid'] = project['id']
22
+ end
23
+ if args[:account]
24
+ account = list_accounts({name: args[:account]}).first
25
+ unless account
26
+ puts "Error: Account #{args[:account]} not found."
27
+ exit 1
28
+ end
29
+ params['domainid'] = account["domainid"]
30
+ params['account'] = args[:account]
31
+ end
32
+ params['listall'] = args[:listall] if args[:listall]
33
+
34
+ json = send_request(params)
35
+ json['snapshot'] || []
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,105 @@
1
+ module CloudstackClient
2
+
3
+ module SshKeyPair
4
+
5
+ ##
6
+ # Lists ssh key pairs.
7
+ #
8
+
9
+ def list_ssh_key_pairs(args = {})
10
+ params = {
11
+ 'command' => 'listSSHKeyPairs',
12
+ 'isrecursive' => true
13
+ }
14
+ params['listall'] = true if args[:listall]
15
+ params['name'] = args[:name] if args[:name]
16
+
17
+ if args[:project]
18
+ project = get_project(args[:project])
19
+ unless project
20
+ puts "Error: project #{args[:project]} not found."
21
+ exit 1
22
+ end
23
+ params['projectid'] = project['id']
24
+ end
25
+
26
+ if args[:account]
27
+ account = list_accounts({name: args[:account]}).first
28
+ unless account
29
+ puts "Error: Account #{args[:account]} not found."
30
+ exit 1
31
+ end
32
+ params['domainid'] = account["domainid"]
33
+ params['account'] = args[:account]
34
+ end
35
+
36
+ json = send_request(params)
37
+ json['sshkeypair'] || []
38
+ end
39
+
40
+ ##
41
+ # Create ssh key pairs.
42
+ #
43
+
44
+ def create_ssh_key_pair(name, args = {})
45
+ params = {
46
+ 'command' => 'createSSHKeyPair',
47
+ 'name' => name
48
+ }
49
+ if args[:project]
50
+ project = get_project(args[:project])
51
+ unless project
52
+ puts "Error: project #{args[:project]} not found."
53
+ exit 1
54
+ end
55
+ params['projectid'] = project['id']
56
+ end
57
+
58
+ if args[:account]
59
+ account = list_accounts({name: args[:account]}).first
60
+ unless account
61
+ puts "Error: Account #{args[:account]} not found."
62
+ exit 1
63
+ end
64
+ params['domainid'] = account["domainid"]
65
+ params['account'] = args[:account]
66
+ end
67
+
68
+ json = send_request(params)['keypair']
69
+ end
70
+
71
+ ##
72
+ # Delete ssh key pairs.
73
+ #
74
+
75
+ def delete_ssh_key_pair(name, args = {})
76
+ params = {
77
+ 'command' => 'deleteSSHKeyPair',
78
+ 'name' => name
79
+ }
80
+
81
+ if args[:project]
82
+ project = get_project(args[:project])
83
+ unless project
84
+ puts "Error: project #{args[:project]} not found."
85
+ exit 1
86
+ end
87
+ params['projectid'] = project['id']
88
+ end
89
+
90
+ if args[:account]
91
+ account = list_accounts({name: args[:account]}).first
92
+ unless account
93
+ puts "Error: Account #{args[:account]} not found."
94
+ exit 1
95
+ end
96
+ params['domainid'] = account["domainid"]
97
+ params['account'] = args[:account]
98
+ end
99
+
100
+ json = send_request(params)
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,32 @@
1
+ module CloudstackClient
2
+
3
+ module User
4
+
5
+ ##
6
+ # Lists users.
7
+ #
8
+
9
+ def list_users(args = {})
10
+ params = {
11
+ 'command' => 'listUsers',
12
+ 'isrecursive' => true
13
+ }
14
+ params['listall'] = true if args[:listall]
15
+
16
+ if args[:account]
17
+ account = list_accounts({name: args[:account]}).first
18
+ unless account
19
+ puts "Error: Account #{args[:account]} not found."
20
+ exit 1
21
+ end
22
+ params['domainid'] = account["domainid"]
23
+ params['account'] = args[:account]
24
+ end
25
+
26
+ json = send_request(params)
27
+ json['user'] || []
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,20 @@
1
+ module CloudstackClient
2
+
3
+ module Volume
4
+
5
+ ##
6
+ # Lists all volumes.
7
+
8
+ def list_volumes(project_id = nil)
9
+ params = {
10
+ 'command' => 'listVolumes',
11
+ 'listall' => true,
12
+ }
13
+ params['projectid'] = project_id if project_id
14
+ json = send_request(params)
15
+ json['network'] || []
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -1,3 +1,3 @@
1
1
  module CloudstackClient
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
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: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nik Wolfgramm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-13 00:00:00.000000000 Z
11
+ date: 2013-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -71,20 +71,26 @@ files:
71
71
  - lib/cloudstack-cli/cli.rb
72
72
  - lib/cloudstack-cli/commands/account.rb
73
73
  - lib/cloudstack-cli/commands/capacity.rb
74
+ - lib/cloudstack-cli/commands/cluster.rb
74
75
  - lib/cloudstack-cli/commands/disk_offering.rb
75
76
  - lib/cloudstack-cli/commands/domain.rb
76
77
  - lib/cloudstack-cli/commands/ip_address.rb
77
78
  - lib/cloudstack-cli/commands/iso.rb
79
+ - lib/cloudstack-cli/commands/job.rb
78
80
  - lib/cloudstack-cli/commands/load_balancer.rb
79
81
  - lib/cloudstack-cli/commands/network.rb
80
82
  - lib/cloudstack-cli/commands/offering.rb
81
83
  - lib/cloudstack-cli/commands/physical_network.rb
84
+ - lib/cloudstack-cli/commands/pod.rb
82
85
  - lib/cloudstack-cli/commands/port_rule.rb
83
86
  - lib/cloudstack-cli/commands/project.rb
84
87
  - lib/cloudstack-cli/commands/router.rb
85
88
  - lib/cloudstack-cli/commands/server.rb
89
+ - lib/cloudstack-cli/commands/snapshot.rb
90
+ - lib/cloudstack-cli/commands/ssh_key_pairs.rb
86
91
  - lib/cloudstack-cli/commands/stack.rb
87
92
  - lib/cloudstack-cli/commands/template.rb
93
+ - lib/cloudstack-cli/commands/user.rb
88
94
  - lib/cloudstack-cli/commands/volume.rb
89
95
  - lib/cloudstack-cli/commands/zone.rb
90
96
  - lib/cloudstack-cli/helper.rb
@@ -92,19 +98,25 @@ files:
92
98
  - lib/cloudstack-client/client.rb
93
99
  - lib/cloudstack-client/commands/account.rb
94
100
  - lib/cloudstack-client/commands/capacity.rb
95
- - lib/cloudstack-client/commands/command_template
101
+ - lib/cloudstack-client/commands/cluster.rb
96
102
  - lib/cloudstack-client/commands/disk_offering.rb
97
103
  - lib/cloudstack-client/commands/domain.rb
98
104
  - lib/cloudstack-client/commands/ip_address.rb
99
105
  - lib/cloudstack-client/commands/iso.rb
106
+ - lib/cloudstack-client/commands/job.rb
100
107
  - lib/cloudstack-client/commands/load_balancer_rule.rb
101
108
  - lib/cloudstack-client/commands/network.rb
109
+ - lib/cloudstack-client/commands/pod.rb
102
110
  - lib/cloudstack-client/commands/port_forwarding_rule.rb
103
111
  - lib/cloudstack-client/commands/project.rb
104
112
  - lib/cloudstack-client/commands/router.rb
105
113
  - lib/cloudstack-client/commands/server.rb
106
114
  - lib/cloudstack-client/commands/service_offering.rb
115
+ - lib/cloudstack-client/commands/snapshot.rb
116
+ - lib/cloudstack-client/commands/ssh_key_pair.rb
107
117
  - lib/cloudstack-client/commands/template.rb
118
+ - lib/cloudstack-client/commands/user.rb
119
+ - lib/cloudstack-client/commands/volume.rb
108
120
  - lib/cloudstack-client/commands/volumes.rb
109
121
  - lib/cloudstack-client/commands/zone.rb
110
122
  - lib/cloudstack-client/version.rb
@@ -1,8 +0,0 @@
1
- module CloudstackClient
2
-
3
- module Command
4
-
5
-
6
- end
7
-
8
- end