cloudstack-cli 0.3.1 → 0.3.2
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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/cloudstack-cli/base.rb +7 -1
- data/lib/cloudstack-cli/cli.rb +19 -2
- data/lib/cloudstack-cli/commands/account.rb +1 -1
- data/lib/cloudstack-cli/commands/capacity.rb +2 -2
- data/lib/cloudstack-cli/commands/cluster.rb +20 -0
- data/lib/cloudstack-cli/commands/disk_offering.rb +1 -1
- data/lib/cloudstack-cli/commands/domain.rb +1 -1
- data/lib/cloudstack-cli/commands/ip_address.rb +10 -5
- data/lib/cloudstack-cli/commands/job.rb +30 -0
- data/lib/cloudstack-cli/commands/load_balancer.rb +1 -1
- data/lib/cloudstack-cli/commands/network.rb +0 -5
- data/lib/cloudstack-cli/commands/offering.rb +1 -1
- data/lib/cloudstack-cli/commands/pod.rb +20 -0
- data/lib/cloudstack-cli/commands/project.rb +1 -1
- data/lib/cloudstack-cli/commands/router.rb +45 -15
- data/lib/cloudstack-cli/commands/server.rb +9 -11
- data/lib/cloudstack-cli/commands/snapshot.rb +24 -0
- data/lib/cloudstack-cli/commands/ssh_key_pairs.rb +46 -0
- data/lib/cloudstack-cli/commands/stack.rb +0 -1
- data/lib/cloudstack-cli/commands/user.rb +28 -0
- data/lib/cloudstack-cli/helper.rb +30 -0
- data/lib/cloudstack-cli/version.rb +1 -1
- data/lib/cloudstack-client/client.rb +4 -4
- data/lib/cloudstack-client/commands/cluster.rb +19 -0
- data/lib/cloudstack-client/commands/ip_address.rb +4 -0
- data/lib/cloudstack-client/commands/job.rb +29 -0
- data/lib/cloudstack-client/commands/pod.rb +19 -0
- data/lib/cloudstack-client/commands/router.rb +20 -6
- data/lib/cloudstack-client/commands/snapshot.rb +40 -0
- data/lib/cloudstack-client/commands/ssh_key_pair.rb +105 -0
- data/lib/cloudstack-client/commands/user.rb +32 -0
- data/lib/cloudstack-client/commands/volume.rb +20 -0
- data/lib/cloudstack-client/version.rb +1 -1
- metadata +15 -3
- data/lib/cloudstack-client/commands/command_template +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7554f6d7a5dc9ae9a56557edfb3a39b7b63778c1
|
4
|
+
data.tar.gz: db3d8020dc9497700d7a3e65594c5a8a35140a78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15451bfd39437d023cba04e4da98424e1d7b66286647a538b4bb3c7c03335b00d47e16e32593a0e9f3180e76d6313ea460353bd270561af193720e89e4db93a8
|
7
|
+
data.tar.gz: a68d0d706ffa1e7a091eff9c8e540ea7cadaeaf4086042c2555f7bc24c306c9ef80ffbbb264269289cb856036a34787cbf96f1fc20e71060b0ac5da45824e487
|
data/Gemfile.lock
CHANGED
data/lib/cloudstack-cli/base.rb
CHANGED
@@ -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
|
data/lib/cloudstack-cli/cli.rb
CHANGED
@@ -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 "
|
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
|
-
|
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
|
-
|
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|
|
@@ -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
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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|
|
@@ -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
|
@@ -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
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
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
|
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(*
|
56
|
+
def destroy(*names)
|
58
57
|
projectid = find_project['id'] if options[:project]
|
59
|
-
|
60
|
-
|
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 #{
|
61
|
+
say "Server #{name} not found.", :red
|
64
62
|
else
|
65
|
-
ask = "Destroy #{
|
66
|
-
if options[:force]
|
67
|
-
say "destroying #{
|
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
|
@@ -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"]
|
@@ -11,7 +11,7 @@ module CloudstackClient
|
|
11
11
|
class Connection
|
12
12
|
|
13
13
|
@@async_poll_interval = 2.0
|
14
|
-
@@async_timeout =
|
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)
|
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
|
102
|
+
if status == 1
|
103
103
|
return json['jobresult']
|
104
|
-
elsif status == 2
|
104
|
+
elsif status == 2
|
105
105
|
puts
|
106
106
|
puts "Request failed (#{json['jobresultcode']}): #{json['jobresult']}"
|
107
107
|
exit 1
|
@@ -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
|
@@ -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,
|
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,
|
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,
|
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
|
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.
|
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-
|
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/
|
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
|