cloudstack-cli 0.0.1 → 0.0.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.
- data/.gitignore +1 -0
- data/README.md +14 -0
- data/cloudstack-cli.gemspec +7 -5
- data/lib/cloudstack-cli/cli.rb +31 -2
- data/lib/cloudstack-cli/commands/account.rb +1 -1
- data/lib/cloudstack-cli/commands/domain.rb +1 -1
- data/lib/cloudstack-cli/commands/load_balancer.rb +3 -3
- data/lib/cloudstack-cli/commands/network.rb +1 -3
- data/lib/cloudstack-cli/commands/offering.rb +4 -4
- data/lib/cloudstack-cli/commands/project.rb +1 -1
- data/lib/cloudstack-cli/commands/publicip.rb +1 -1
- data/lib/cloudstack-cli/commands/router.rb +37 -12
- data/lib/cloudstack-cli/commands/server.rb +1 -1
- data/lib/cloudstack-cli/commands/template.rb +1 -1
- data/lib/cloudstack-cli/commands/volume.rb +1 -1
- data/lib/cloudstack-cli/commands/zone.rb +1 -1
- data/lib/cloudstack-cli/helper.rb +14 -5
- data/lib/cloudstack-cli/version.rb +1 -1
- data/lib/cloudstack-client/client.rb +32 -1
- data/lib/cloudstack-client/helper.rb +3 -2
- metadata +6 -6
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -16,6 +16,20 @@ Or install it yourself as:
|
|
16
16
|
|
17
17
|
$ gem install cloudstack-cli
|
18
18
|
|
19
|
+
## Setup
|
20
|
+
|
21
|
+
Create the initial configuration:
|
22
|
+
|
23
|
+
cs setup
|
24
|
+
|
25
|
+
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.
|
26
|
+
|
27
|
+
Example content of the configuration file:
|
28
|
+
|
29
|
+
:url: "https://my-cloudstack-server/client/api/"
|
30
|
+
:api_key: "cloudstack-api-key"
|
31
|
+
:secret_key: "cloudstack-api-secret"
|
32
|
+
|
19
33
|
## Usage
|
20
34
|
|
21
35
|
See the help screen
|
data/cloudstack-cli.gemspec
CHANGED
@@ -6,18 +6,20 @@ require 'cloudstack-cli/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "cloudstack-cli"
|
8
8
|
gem.version = CloudstackCli::VERSION
|
9
|
-
gem.authors = ["
|
9
|
+
gem.authors = ["Nik Wolfgramm"]
|
10
10
|
gem.email = ["nik.wolfgramm@gmail.com"]
|
11
|
-
gem.description = %q{
|
12
|
-
gem.summary = %q{cloudstack-cli}
|
13
|
-
gem.homepage = ""
|
11
|
+
gem.description = %q{cloudstack-cli is a CloudStack API client written in Ruby.}
|
12
|
+
gem.summary = %q{cloudstack-cli CloudStack API client}
|
13
|
+
gem.homepage = "https://bitbucket.org/swisstxt/cloudstack-cli"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
|
-
gem.executables =
|
16
|
+
gem.executables = ['cs']
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
|
+
|
19
20
|
gem.add_development_dependency('rdoc')
|
20
21
|
gem.add_development_dependency('rake', '~> 10.0.4')
|
22
|
+
|
21
23
|
gem.add_dependency('thor', '~> 0.18.1')
|
22
24
|
gem.add_dependency('net-ssh', '~> 2.6.7')
|
23
25
|
gem.add_dependency('rainbow', '~> 1.1.4')
|
data/lib/cloudstack-cli/cli.rb
CHANGED
@@ -1,11 +1,40 @@
|
|
1
1
|
module CloudstackCli
|
2
2
|
class Cli < Thor
|
3
|
-
|
3
|
+
include Thor::Actions
|
4
|
+
|
5
|
+
class_option :config, default: File.join(Dir.home, '.cloudstack-cli.yml'), aliases: '-c'
|
4
6
|
class_option :verbose, type: :boolean
|
5
7
|
|
8
|
+
desc "setup", "initial setup of the Cloudstack connection"
|
9
|
+
option :url
|
10
|
+
option :api_key
|
11
|
+
option :secret_key
|
12
|
+
def setup(file = options[:config])
|
13
|
+
config = {}
|
14
|
+
unless options[:url]
|
15
|
+
say "What's the URL of your Cloudstack API?", :blue
|
16
|
+
say "Example: https://my-cloudstack-server/client/api/", :blue
|
17
|
+
config[:url] = ask("URL:", :magenta)
|
18
|
+
end
|
19
|
+
|
20
|
+
unless options[:api_key]
|
21
|
+
config[:api_key] = ask("API Key:", :magenta)
|
22
|
+
end
|
23
|
+
|
24
|
+
unless options[:secret_key]
|
25
|
+
config[:secret_key] = ask("Secret Key:", :magenta)
|
26
|
+
end
|
27
|
+
|
28
|
+
if File.exists? file
|
29
|
+
say "Warning: #{file} already exists.", :red
|
30
|
+
exit unless yes?("Overwrite [y/N]", :red)
|
31
|
+
end
|
32
|
+
File.open(file, 'w+') {|f| f.write(config.to_yaml) }
|
33
|
+
end
|
34
|
+
|
6
35
|
desc "command COMMAND [arg1=val1 arg2=val2...]", "run a custom api command"
|
7
36
|
def command(command, *args)
|
8
|
-
client = CloudstackCli::Helper.new
|
37
|
+
client = CloudstackCli::Helper.new(options[:config])
|
9
38
|
params = {'command' => command}
|
10
39
|
args.each do |arg|
|
11
40
|
arg = arg.split('=')
|
@@ -2,7 +2,7 @@ class Lb < Thor
|
|
2
2
|
desc "list", "list load balancer rules"
|
3
3
|
option :project
|
4
4
|
def list
|
5
|
-
cs_cli = CloudstackCli::Helper.new
|
5
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
6
6
|
if options[:project]
|
7
7
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
8
8
|
exit_now! "Project '#{options[:project]}' not found" unless project
|
@@ -24,7 +24,7 @@ class Lb < Thor
|
|
24
24
|
option :public_port, :required => true
|
25
25
|
option :private_port
|
26
26
|
def create(name)
|
27
|
-
cs_cli = CloudstackCli::Helper.new
|
27
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
28
28
|
if options[:project]
|
29
29
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
30
30
|
exit_now! "Project '#{options[:project]}' not found" unless project
|
@@ -44,7 +44,7 @@ class Lb < Thor
|
|
44
44
|
option :project
|
45
45
|
option :servers, required: true, type: :array, description: 'server names'
|
46
46
|
def add(name)
|
47
|
-
cs_cli = CloudstackCli::Helper.new
|
47
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
48
48
|
if options[:project]
|
49
49
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
50
50
|
exit_now! "Project '#{options[:project]}' not found" unless project
|
@@ -11,7 +11,7 @@ class Network < Thor
|
|
11
11
|
option :project
|
12
12
|
option :physical, type: :boolean
|
13
13
|
def list
|
14
|
-
cs_cli = CloudstackCli::Helper.new
|
14
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
15
15
|
if options[:project]
|
16
16
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
17
17
|
raise "Project '#{options[:project]}' not found" unless project
|
@@ -19,7 +19,6 @@ class Network < Thor
|
|
19
19
|
|
20
20
|
if options[:physical]
|
21
21
|
networks = cs_cli.physical_networks
|
22
|
-
|
23
22
|
if networks.size < 1
|
24
23
|
puts "No networks found"
|
25
24
|
else
|
@@ -42,7 +41,6 @@ class Network < Thor
|
|
42
41
|
end
|
43
42
|
else
|
44
43
|
networks = cs_cli.networks(project ? project['id'] : -1)
|
45
|
-
|
46
44
|
if networks.size < 1
|
47
45
|
puts "No networks found"
|
48
46
|
else
|
@@ -4,7 +4,7 @@ class Offering < Thor
|
|
4
4
|
desc 'list', 'list offerings by type [compute|network|storage]'
|
5
5
|
option :domain
|
6
6
|
def list(type='compute')
|
7
|
-
cs_cli = CloudstackCli::Helper.new
|
7
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
8
8
|
offerings = cs_cli.server_offerings(options[:domain])
|
9
9
|
|
10
10
|
offerings.group_by{|o| o["domain"]}.each_value do |offers|
|
@@ -47,20 +47,20 @@ class Offering < Thor
|
|
47
47
|
option :tags
|
48
48
|
def create(name)
|
49
49
|
options[:name] = name
|
50
|
-
cs_cli = CloudstackCli::Helper.new
|
50
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
51
51
|
puts "OK" if cs_cli.create_offering(options)
|
52
52
|
end
|
53
53
|
|
54
54
|
desc 'delete ID', 'delete offering'
|
55
55
|
def delete(id)
|
56
|
-
cs_cli = CloudstackCli::Helper.new
|
56
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
57
57
|
puts "OK" if cs_cli.delete_offering(id)
|
58
58
|
end
|
59
59
|
|
60
60
|
|
61
61
|
desc 'sort', 'sort by cpu and memory grouped by domain'
|
62
62
|
def sort
|
63
|
-
cs_cli = CloudstackCli::Helper.new
|
63
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
64
64
|
offerings = cs_cli.server_offerings(options[:domain])
|
65
65
|
sortkey = -1
|
66
66
|
offerings.group_by{|o| o["domain"]}.each_value do |offers|
|
@@ -1,15 +1,18 @@
|
|
1
1
|
class Router < Thor
|
2
|
+
include Thor::Actions
|
2
3
|
include CommandLineReporter
|
3
4
|
|
4
5
|
desc "list", "list virtual routers"
|
5
6
|
option :project
|
6
7
|
option :account
|
8
|
+
option :zone
|
7
9
|
option :status, desc: "Running or Stopped"
|
8
10
|
option :redundant_state, desc: "MASTER, BACKUP or UNKNOWN"
|
9
11
|
option :listall, type: :boolean
|
10
12
|
option :text, type: :boolean, desc: "text output (only the instance name)"
|
13
|
+
option :command, desc: "command to execute for each router: START or STOP"
|
11
14
|
def list
|
12
|
-
cs_cli = CloudstackCli::Helper.new
|
15
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
13
16
|
if options[:project]
|
14
17
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
15
18
|
raise "Project '#{options[:project]}' not found" unless project
|
@@ -21,6 +24,7 @@ class Router < Thor
|
|
21
24
|
account: options[:account],
|
22
25
|
projectid: projectid,
|
23
26
|
status: options[:status],
|
27
|
+
zone: options[:zone]
|
24
28
|
},
|
25
29
|
options[:redundant_state]
|
26
30
|
)
|
@@ -33,7 +37,8 @@ class Router < Thor
|
|
33
37
|
{
|
34
38
|
account: options[:account],
|
35
39
|
projectid: project['id'],
|
36
|
-
status: options[:status]
|
40
|
+
status: options[:status],
|
41
|
+
zone: options[:zone]
|
37
42
|
},
|
38
43
|
options[:redundant_state]
|
39
44
|
)
|
@@ -70,24 +75,44 @@ class Router < Thor
|
|
70
75
|
end
|
71
76
|
end
|
72
77
|
|
78
|
+
if options[:command]
|
79
|
+
case options[:command].downcase
|
80
|
+
when "start"
|
81
|
+
exit unless yes?("Start the routers above? [y/N]:", :magenta)
|
82
|
+
routers.each do |router|
|
83
|
+
say "Start router #{router['name']}"
|
84
|
+
cs_cli.start_router router['id']
|
85
|
+
end
|
86
|
+
when "stop"
|
87
|
+
exit unless yes?("Stop the routers above? [y/N]:", :magenta)
|
88
|
+
routers.each do |router|
|
89
|
+
say "Stop router #{router['name']}"
|
90
|
+
cs_cli.stop_router router['id']
|
91
|
+
end
|
92
|
+
else
|
93
|
+
say "Command #{options[:command]} not supported", :red
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
end
|
73
97
|
end
|
74
98
|
|
75
|
-
desc "stop
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
99
|
+
desc "stop ID", "stop virtual router"
|
100
|
+
def stop(id)
|
101
|
+
exit unless yes?("Stop the router with ID #{id}?", :magenta)
|
102
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
103
|
+
cs_cli.stop_router id
|
80
104
|
end
|
81
105
|
|
82
|
-
desc "start
|
83
|
-
|
84
|
-
|
85
|
-
|
106
|
+
desc "start ID", "start virtual router"
|
107
|
+
def start(id)
|
108
|
+
exit unless yes?("Start the router with ID #{id}?", :magenta)
|
109
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
110
|
+
cs_cli.start_router id
|
86
111
|
end
|
87
112
|
|
88
113
|
desc "destroy ID", "destroy virtual router"
|
89
114
|
def destroy(id)
|
90
|
-
cs_cli = CloudstackCli::Helper.new
|
115
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
91
116
|
puts "OK" if cs_cli.destroy_router(name)
|
92
117
|
end
|
93
118
|
|
@@ -6,7 +6,7 @@ class Server < Thor
|
|
6
6
|
option :project
|
7
7
|
option :account
|
8
8
|
def list
|
9
|
-
cs_cli = CloudstackCli::Helper.new
|
9
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
10
10
|
if options[:project]
|
11
11
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
12
12
|
exit_now! "Project '#{options[:project]}' not found" unless project
|
@@ -3,7 +3,7 @@ class Template < Thor
|
|
3
3
|
desc 'list', 'list templates by type [featured|self|self-executable|executable|community]'
|
4
4
|
option :project
|
5
5
|
def list(type='featured')
|
6
|
-
cs_cli = CloudstackCli::Helper.new
|
6
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
7
7
|
|
8
8
|
if options[:project]
|
9
9
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
@@ -2,7 +2,7 @@ class Volume < Thor
|
|
2
2
|
desc "list", "list networks"
|
3
3
|
option :project
|
4
4
|
def list
|
5
|
-
cs_cli = CloudstackCli::Helper.new
|
5
|
+
cs_cli = CloudstackCli::Helper.new(options[:config])
|
6
6
|
if options[:project]
|
7
7
|
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
8
8
|
raise "Project '#{options[:project]}' not found" unless project
|
@@ -4,11 +4,12 @@ module CloudstackCli
|
|
4
4
|
|
5
5
|
attr_reader :cs
|
6
6
|
|
7
|
-
def initialize
|
7
|
+
def initialize(config_file)
|
8
|
+
@config_file = config_file
|
8
9
|
@cs = CloudstackClient::Connection.new(
|
9
|
-
options[:
|
10
|
-
options[:
|
11
|
-
options[:
|
10
|
+
options[:url],
|
11
|
+
options[:api_key],
|
12
|
+
options[:secret_key]
|
12
13
|
)
|
13
14
|
end
|
14
15
|
|
@@ -175,8 +176,16 @@ module CloudstackCli
|
|
175
176
|
@cs.destroy_router(id)
|
176
177
|
end
|
177
178
|
|
179
|
+
def start_router(id)
|
180
|
+
@cs.start_router(id)
|
181
|
+
end
|
182
|
+
|
183
|
+
def stop_router(id)
|
184
|
+
@cs.stop_router(id)
|
185
|
+
end
|
186
|
+
|
178
187
|
def options
|
179
|
-
@options ||= CloudstackClient::ConnectionHelper.load_configuration()
|
188
|
+
@options ||= CloudstackClient::ConnectionHelper.load_configuration(@config_file)
|
180
189
|
end
|
181
190
|
|
182
191
|
def print_options(options, attr = 'name')
|
@@ -728,7 +728,14 @@ module CloudstackClient
|
|
728
728
|
'listall' => 'true',
|
729
729
|
'isrecursive' => 'true'
|
730
730
|
}
|
731
|
-
|
731
|
+
if args[:zone]
|
732
|
+
zone = get_zone(args[:zone])
|
733
|
+
unless zone
|
734
|
+
puts "Error: Zone #{args[:zone]} not found"
|
735
|
+
exit 1
|
736
|
+
end
|
737
|
+
params['zoneid'] = zone['id']
|
738
|
+
end
|
732
739
|
params['projectid'] = args[:projectid] if args[:projectid]
|
733
740
|
params['state'] = args[:status] if args[:status]
|
734
741
|
params['name'] = args[:name] if args[:name]
|
@@ -754,6 +761,30 @@ module CloudstackClient
|
|
754
761
|
json['router'].first
|
755
762
|
end
|
756
763
|
|
764
|
+
##
|
765
|
+
# Start virtual router.
|
766
|
+
|
767
|
+
def start_router(id)
|
768
|
+
params = {
|
769
|
+
'command' => 'startRouter',
|
770
|
+
'id' => id
|
771
|
+
}
|
772
|
+
|
773
|
+
json = send_async_request(params)
|
774
|
+
end
|
775
|
+
|
776
|
+
##
|
777
|
+
# Stop virtual router.
|
778
|
+
|
779
|
+
def stop_router(id)
|
780
|
+
params = {
|
781
|
+
'command' => 'stopRouter',
|
782
|
+
'id' => id
|
783
|
+
}
|
784
|
+
|
785
|
+
json = send_async_request(params)
|
786
|
+
end
|
787
|
+
|
757
788
|
##
|
758
789
|
# Lists accounts.
|
759
790
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module CloudstackClient
|
2
2
|
class ConnectionHelper
|
3
|
-
def self.load_configuration(config_file
|
3
|
+
def self.load_configuration(config_file)
|
4
4
|
begin
|
5
5
|
return YAML::load(IO.read(config_file))
|
6
6
|
rescue Exception => e
|
7
|
-
puts "
|
7
|
+
$stderr.puts "Can't find the config file '#{config_file}'"
|
8
|
+
$stderr.puts "Please see https://bitbucket.org/swisstxt/cloudstack-cli under 'Setup'"
|
8
9
|
exit
|
9
10
|
end
|
10
11
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudstack-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
|
-
-
|
8
|
+
- Nik Wolfgramm
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rdoc
|
@@ -107,7 +107,7 @@ dependencies:
|
|
107
107
|
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: 3.2.1
|
110
|
-
description:
|
110
|
+
description: cloudstack-cli is a CloudStack API client written in Ruby.
|
111
111
|
email:
|
112
112
|
- nik.wolfgramm@gmail.com
|
113
113
|
executables:
|
@@ -144,7 +144,7 @@ files:
|
|
144
144
|
- lib/cloudstack-client/ssh_command.rb
|
145
145
|
- lib/cloudstack_cli.rb
|
146
146
|
- lib/cloudstack_client.rb
|
147
|
-
homepage:
|
147
|
+
homepage: https://bitbucket.org/swisstxt/cloudstack-cli
|
148
148
|
licenses: []
|
149
149
|
post_install_message:
|
150
150
|
rdoc_options: []
|
@@ -167,5 +167,5 @@ rubyforge_project:
|
|
167
167
|
rubygems_version: 1.8.23
|
168
168
|
signing_key:
|
169
169
|
specification_version: 3
|
170
|
-
summary: cloudstack-cli
|
170
|
+
summary: cloudstack-cli CloudStack API client
|
171
171
|
test_files: []
|