cloudstack-cli 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +7 -0
- data/README.md +40 -0
- data/bin/cs +7 -0
- data/cloudstack-cli.gemspec +25 -0
- data/config/cloudstack.example.yml +3 -0
- data/lib/cloudstack-cli/cli.rb +59 -0
- data/lib/cloudstack-cli/commands/account.rb +16 -0
- data/lib/cloudstack-cli/commands/domain.rb +16 -0
- data/lib/cloudstack-cli/commands/load_balancer.rb +58 -0
- data/lib/cloudstack-cli/commands/network.rb +74 -0
- data/lib/cloudstack-cli/commands/offering.rb +80 -0
- data/lib/cloudstack-cli/commands/project.rb +15 -0
- data/lib/cloudstack-cli/commands/publicip.rb +9 -0
- data/lib/cloudstack-cli/commands/router.rb +94 -0
- data/lib/cloudstack-cli/commands/server.rb +65 -0
- data/lib/cloudstack-cli/commands/stack.rb +16 -0
- data/lib/cloudstack-cli/commands/template.rb +25 -0
- data/lib/cloudstack-cli/commands/volume.rb +20 -0
- data/lib/cloudstack-cli/commands/zone.rb +16 -0
- data/lib/cloudstack-cli/helper.rb +236 -0
- data/lib/cloudstack-cli/version.rb +3 -0
- data/lib/cloudstack-client/client.rb +871 -0
- data/lib/cloudstack-client/helper.rb +12 -0
- data/lib/cloudstack-client/ssh_command.rb +15 -0
- data/lib/cloudstack_cli.rb +16 -0
- data/lib/cloudstack_client.rb +5 -0
- metadata +171 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
cloudstack-cli (0.0.1)
|
5
|
+
command_line_reporter (~> 3.2.1)
|
6
|
+
net-ssh (~> 2.6.7)
|
7
|
+
rainbow (~> 1.1.4)
|
8
|
+
thor (~> 0.18.1)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
colored (1.2)
|
14
|
+
command_line_reporter (3.2.1)
|
15
|
+
colored (>= 1.2)
|
16
|
+
json (1.8.0)
|
17
|
+
net-ssh (2.6.7)
|
18
|
+
rainbow (1.1.4)
|
19
|
+
rake (10.0.4)
|
20
|
+
rdoc (4.0.1)
|
21
|
+
json (~> 1.4)
|
22
|
+
thor (0.18.1)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
cloudstack-cli!
|
29
|
+
rake (~> 10.0.4)
|
30
|
+
rdoc
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2013 niwo
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Cloudstack CLI
|
2
|
+
|
3
|
+
Cloudstack CLI gives command line access to the CloudStack API commands.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem "cloudstack-cli"
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install cloudstack-cli
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
See the help screen
|
22
|
+
|
23
|
+
$ bin/cs
|
24
|
+
|
25
|
+
Example: Bootsrap a server
|
26
|
+
|
27
|
+
$ bin/cs server create delete-me-10 --zone ZUERICH_IX --port-forwarding 146.159.95.194:22 146.159.95.194:80 --template CentOS-6.4-x64-v1.2 --offering demo_1cpu_1gb --networks M_ZRH_NMC-Demo
|
28
|
+
|
29
|
+
Example: Run a custom API command
|
30
|
+
|
31
|
+
bin/cs command listAlerts type=8
|
32
|
+
|
33
|
+
|
34
|
+
## Contributing
|
35
|
+
|
36
|
+
1. Fork it
|
37
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
38
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
39
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
40
|
+
5. Create new Pull Request
|
data/bin/cs
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cloudstack-cli/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cloudstack-cli"
|
8
|
+
gem.version = CloudstackCli::VERSION
|
9
|
+
gem.authors = ["niwo"]
|
10
|
+
gem.email = ["nik.wolfgramm@gmail.com"]
|
11
|
+
gem.description = %q{Cloudstack CLI gives command line access to the CloudStack API commands.}
|
12
|
+
gem.summary = %q{cloudstack-cli}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.add_development_dependency('rdoc')
|
20
|
+
gem.add_development_dependency('rake', '~> 10.0.4')
|
21
|
+
gem.add_dependency('thor', '~> 0.18.1')
|
22
|
+
gem.add_dependency('net-ssh', '~> 2.6.7')
|
23
|
+
gem.add_dependency('rainbow', '~> 1.1.4')
|
24
|
+
gem.add_dependency('command_line_reporter', '~> 3.2.1')
|
25
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module CloudstackCli
|
2
|
+
class Cli < Thor
|
3
|
+
class_option :config
|
4
|
+
class_option :verbose, type: :boolean
|
5
|
+
|
6
|
+
desc "command COMMAND [arg1=val1 arg2=val2...]", "run a custom api command"
|
7
|
+
def command(command, *args)
|
8
|
+
client = CloudstackCli::Helper.new
|
9
|
+
params = {'command' => command}
|
10
|
+
args.each do |arg|
|
11
|
+
arg = arg.split('=')
|
12
|
+
params[arg[0]] = arg[1]
|
13
|
+
end
|
14
|
+
puts JSON.pretty_generate(client.cs.send_request params)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "zone SUBCOMMAND ...ARGS", "manage zones"
|
18
|
+
subcommand "zone", Zone
|
19
|
+
|
20
|
+
desc "project SUBCOMMAND ...ARGS", "manage servers"
|
21
|
+
subcommand "project", Project
|
22
|
+
|
23
|
+
desc "server SUBCOMMAND ...ARGS", "manage servers"
|
24
|
+
subcommand "server", Server
|
25
|
+
|
26
|
+
desc "offering SUBCOMMAND ...ARGS", "manage offerings"
|
27
|
+
subcommand "offering", Offering
|
28
|
+
|
29
|
+
desc "network SUBCOMMAND ...ARGS", "manage networks"
|
30
|
+
subcommand "network", Network
|
31
|
+
|
32
|
+
desc "lb SUBCOMMAND ...ARGS", "manage load balancing rules"
|
33
|
+
subcommand "lb", Lb
|
34
|
+
|
35
|
+
desc "template SUBCOMMAND ...ARGS", "manage template"
|
36
|
+
subcommand "template", Template
|
37
|
+
|
38
|
+
desc "router SUBCOMMAND ...ARGS", "manage virtual routers"
|
39
|
+
subcommand "router", Router
|
40
|
+
|
41
|
+
desc "router SUBCOMMAND ...ARGS", "manage virtual routers"
|
42
|
+
subcommand "router", Router
|
43
|
+
|
44
|
+
desc "volume SUBCOMMAND ...ARGS", "manage volumes"
|
45
|
+
subcommand "volume", Volume
|
46
|
+
|
47
|
+
desc "stack SUBCOMMAND ...ARGS", "manage stacks"
|
48
|
+
subcommand "stack", Stack
|
49
|
+
|
50
|
+
desc "account SUBCOMMAND ...ARGS", "manage accounts"
|
51
|
+
subcommand "account", Account
|
52
|
+
|
53
|
+
desc "domain SUBCOMMAND ...ARGS", "manage domains"
|
54
|
+
subcommand "domain", Domain
|
55
|
+
|
56
|
+
desc "publicip SUBCOMMAND ...ARGS", "manage public ip addresses"
|
57
|
+
subcommand "publicip", Publicip
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Account < Thor
|
2
|
+
|
3
|
+
desc 'list [NAME]', 'list accounts'
|
4
|
+
def list(name = nil)
|
5
|
+
cs_cli = CloudstackCli::Helper.new
|
6
|
+
accounts = cs_cli.list_accounts(name)
|
7
|
+
if accounts.size < 1
|
8
|
+
puts "No accounts found"
|
9
|
+
else
|
10
|
+
accounts.each do |account|
|
11
|
+
puts "#{account['name']} - #{account['domain']}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Domain < Thor
|
2
|
+
|
3
|
+
desc 'list [NAME]', 'list domains'
|
4
|
+
def list(name = nil)
|
5
|
+
cs_cli = CloudstackCli::Helper.new
|
6
|
+
domains = cs_cli.domains(name)
|
7
|
+
if domains.size < 1
|
8
|
+
puts "No domains found"
|
9
|
+
else
|
10
|
+
domains.each do |domain|
|
11
|
+
puts "#{domain['name']}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Lb < Thor
|
2
|
+
desc "list", "list load balancer rules"
|
3
|
+
option :project
|
4
|
+
def list
|
5
|
+
cs_cli = CloudstackCli::Helper.new
|
6
|
+
if options[:project]
|
7
|
+
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
8
|
+
exit_now! "Project '#{options[:project]}' not found" unless project
|
9
|
+
end
|
10
|
+
|
11
|
+
rules = cs_cli.list_load_balancer_rules(project ? project['id'] : nil)
|
12
|
+
if rules.size < 1
|
13
|
+
puts "No load balancer rules found"
|
14
|
+
else
|
15
|
+
rules.each do |rule|
|
16
|
+
puts "#{rule['name']} - #{rule['publicip']}:#{rule['publicport']}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "create NAME", "create load balancer rule"
|
22
|
+
option :project
|
23
|
+
option :ip, :required => true
|
24
|
+
option :public_port, :required => true
|
25
|
+
option :private_port
|
26
|
+
def create(name)
|
27
|
+
cs_cli = CloudstackCli::Helper.new
|
28
|
+
if options[:project]
|
29
|
+
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
30
|
+
exit_now! "Project '#{options[:project]}' not found" unless project
|
31
|
+
end
|
32
|
+
|
33
|
+
options[:private_port] = options[:public_port] if options[:private_port] == nil
|
34
|
+
|
35
|
+
rule = cs_cli.create_load_balancer_rule(
|
36
|
+
name,
|
37
|
+
options[:ip],
|
38
|
+
options[:private_port],
|
39
|
+
options[:public_port],
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "add NAME", "assign servers to balancer rule"
|
44
|
+
option :project
|
45
|
+
option :servers, required: true, type: :array, description: 'server names'
|
46
|
+
def add(name)
|
47
|
+
cs_cli = CloudstackCli::Helper.new
|
48
|
+
if options[:project]
|
49
|
+
project = cs_cli.projects.select { |p| p['name'] == options[:project] }.first
|
50
|
+
exit_now! "Project '#{options[:project]}' not found" unless project
|
51
|
+
end
|
52
|
+
|
53
|
+
rule = cs_cli.assign_to_load_balancer_rule(
|
54
|
+
name,
|
55
|
+
options[:servers],
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class Network < Thor
|
2
|
+
include CommandLineReporter
|
3
|
+
|
4
|
+
desc "create NAME", "create network"
|
5
|
+
def create(name)
|
6
|
+
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "list", "list networks"
|
11
|
+
option :project
|
12
|
+
option :physical, type: :boolean
|
13
|
+
def list
|
14
|
+
cs_cli = CloudstackCli::Helper.new
|
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
|
+
|
20
|
+
if options[:physical]
|
21
|
+
networks = cs_cli.physical_networks
|
22
|
+
|
23
|
+
if networks.size < 1
|
24
|
+
puts "No networks found"
|
25
|
+
else
|
26
|
+
table(border: true) do
|
27
|
+
row do
|
28
|
+
column 'ID', width: 40
|
29
|
+
column 'Name', width: 30
|
30
|
+
column 'Zone ID', width: 14 unless options[:project]
|
31
|
+
column 'State'
|
32
|
+
end
|
33
|
+
networks.each do |network|
|
34
|
+
row do
|
35
|
+
column network["id"]
|
36
|
+
column network["name"]
|
37
|
+
column network["zoneid"]
|
38
|
+
column network["state"]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
else
|
44
|
+
networks = cs_cli.networks(project ? project['id'] : -1)
|
45
|
+
|
46
|
+
if networks.size < 1
|
47
|
+
puts "No networks found"
|
48
|
+
else
|
49
|
+
table(border: true) do
|
50
|
+
row do
|
51
|
+
column 'ID', width: 40
|
52
|
+
column 'Name', width: 30
|
53
|
+
column 'Displaytext', width: 30
|
54
|
+
column 'Account', width: 14 unless options[:project]
|
55
|
+
column 'Project', width: 14 if options[:listall] || options[:project]
|
56
|
+
column 'State'
|
57
|
+
end
|
58
|
+
networks.each do |network|
|
59
|
+
row do
|
60
|
+
column network["id"]
|
61
|
+
column network["name"]
|
62
|
+
column network["displaytext"]
|
63
|
+
column network["account"] unless options[:project]
|
64
|
+
column network["project"] if options[:listall] || options[:project]
|
65
|
+
column network["state"]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Offering < Thor
|
2
|
+
include CommandLineReporter
|
3
|
+
|
4
|
+
desc 'list', 'list offerings by type [compute|network|storage]'
|
5
|
+
option :domain
|
6
|
+
def list(type='compute')
|
7
|
+
cs_cli = CloudstackCli::Helper.new
|
8
|
+
offerings = cs_cli.server_offerings(options[:domain])
|
9
|
+
|
10
|
+
offerings.group_by{|o| o["domain"]}.each_value do |offers|
|
11
|
+
offers.sort {
|
12
|
+
|oa, ob| [oa["cpunumber"], oa["memory"]] <=> [ob["cpunumber"], ob["memory"]]
|
13
|
+
}.each do |offer|
|
14
|
+
puts "#{offer['domain']} - #{offer["displaytext"]}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
if offerings.size < 1
|
19
|
+
puts "No offerings found"
|
20
|
+
else
|
21
|
+
table(border: true) do
|
22
|
+
row do
|
23
|
+
column 'Name', width: 20
|
24
|
+
column 'Description', width: 30
|
25
|
+
column 'ID', width: 30
|
26
|
+
column 'Domain', width: 16
|
27
|
+
end
|
28
|
+
offerings.each do |offering|
|
29
|
+
row do
|
30
|
+
column offering["name"]
|
31
|
+
column offering["id"]
|
32
|
+
column offering["displaytext"]
|
33
|
+
column offering["domain"]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'create NAME', 'create offering'
|
41
|
+
option :cpunumber, required: true
|
42
|
+
option :cpuspeed, required: true
|
43
|
+
option :displaytext, required: true
|
44
|
+
option :memory, required: true
|
45
|
+
option :domain
|
46
|
+
option :ha, type: :boolean
|
47
|
+
option :tags
|
48
|
+
def create(name)
|
49
|
+
options[:name] = name
|
50
|
+
cs_cli = CloudstackCli::Helper.new
|
51
|
+
puts "OK" if cs_cli.create_offering(options)
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'delete ID', 'delete offering'
|
55
|
+
def delete(id)
|
56
|
+
cs_cli = CloudstackCli::Helper.new
|
57
|
+
puts "OK" if cs_cli.delete_offering(id)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
desc 'sort', 'sort by cpu and memory grouped by domain'
|
62
|
+
def sort
|
63
|
+
cs_cli = CloudstackCli::Helper.new
|
64
|
+
offerings = cs_cli.server_offerings(options[:domain])
|
65
|
+
sortkey = -1
|
66
|
+
offerings.group_by{|o| o["domain"]}.each_value do |offers|
|
67
|
+
offers.sort {
|
68
|
+
|oa, ob| [oa["cpunumber"], oa["memory"]] <=> [ob["cpunumber"], ob["memory"]]
|
69
|
+
}.each do |offer|
|
70
|
+
puts "#{sortkey.abs} #{offer['domain']} - #{offer["displaytext"]}"
|
71
|
+
cs_cli.update_offering({
|
72
|
+
"id" => offer['id'],
|
73
|
+
'sortkey' => sortkey
|
74
|
+
})
|
75
|
+
sortkey -= 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|