cloudstack-cli 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +6 -6
- data/cloudstack-cli.gemspec +0 -1
- data/lib/cloudstack-cli/cli.rb +9 -9
- data/lib/cloudstack-cli/commands/ip_address.rb +33 -0
- data/lib/cloudstack-cli/commands/load_balancer.rb +1 -1
- data/lib/cloudstack-cli/commands/network.rb +10 -7
- data/lib/cloudstack-cli/commands/physical_network.rb +4 -3
- data/lib/cloudstack-cli/commands/port_rule.rb +66 -0
- data/lib/cloudstack-cli/commands/server.rb +30 -13
- data/lib/cloudstack-cli/commands/stack.rb +16 -12
- data/lib/cloudstack-cli/commands/template.rb +1 -1
- data/lib/cloudstack-cli/commands/volume.rb +1 -1
- data/lib/cloudstack-cli/helper.rb +89 -147
- data/lib/cloudstack-cli/version.rb +1 -1
- data/lib/cloudstack-client/client.rb +45 -14
- data/lib/cloudstack-client/helper.rb +1 -1
- data/lib/cloudstack_cli.rb +0 -1
- data/test/stack_example.json +2 -2
- metadata +21 -24
- checksums.yaml +0 -7
- data/lib/cloudstack-cli/commands/publicip.rb +0 -8
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -12,19 +12,19 @@ Install the cloudstack-cli gem:
|
|
12
12
|
|
13
13
|
Create the initial configuration:
|
14
14
|
|
15
|
-
|
15
|
+
$ cs setup
|
16
16
|
|
17
17
|
cloudstack-cli expects to find a configuartion file with the API URL and your CloudStack credentials in your home directory named .cloudstack-cli.yml. If the file is located elsewhere you can specify the loaction using the --config option.
|
18
18
|
|
19
19
|
Example content of the configuration file:
|
20
20
|
|
21
21
|
:url: "https://my-cloudstack-server/client/api/"
|
22
|
-
|
23
|
-
|
22
|
+
:api_key: "cloudstack-api-key"
|
23
|
+
:secret_key: "cloudstack-api-secret"
|
24
24
|
|
25
25
|
## Usage
|
26
26
|
|
27
|
-
|
27
|
+
For additional documentation find the RubyDoc [here](http://rubydoc.info/gems/cloudstack-cli/).
|
28
28
|
|
29
29
|
See the help screen:
|
30
30
|
|
@@ -82,8 +82,8 @@ Sort all computing offerings by CPU and Memory grouped my Domain:
|
|
82
82
|
|
83
83
|
### Example 5
|
84
84
|
|
85
|
-
Stop all virtual routers of project Demo (you could filter by
|
86
|
-
(This command is helpful if you have to deploy new versions of Cloudstack when using
|
85
|
+
Stop all virtual routers of project Demo (you could filter by zone too):
|
86
|
+
(This command is helpful if you have to deploy new versions of Cloudstack when using redundant routers)
|
87
87
|
|
88
88
|
$ cs router list --project Demo --status running --redundant-state BACKUP --command stop
|
89
89
|
|
data/cloudstack-cli.gemspec
CHANGED
data/lib/cloudstack-cli/cli.rb
CHANGED
@@ -68,11 +68,11 @@ module CloudstackCli
|
|
68
68
|
desc "network SUBCOMMAND ...ARGS", "Manage networks"
|
69
69
|
subcommand "network", Network
|
70
70
|
|
71
|
-
desc "
|
72
|
-
subcommand "
|
71
|
+
desc "physical_network SUBCOMMAND ...ARGS", "Manage physical networks"
|
72
|
+
subcommand "physical_network", PhysicalNetwork
|
73
73
|
|
74
|
-
desc "
|
75
|
-
subcommand "
|
74
|
+
desc "load_balancer SUBCOMMAND ...ARGS", "Manage load balancing rules"
|
75
|
+
subcommand "load_balancer", LoadBalancer
|
76
76
|
|
77
77
|
desc "template SUBCOMMAND ...ARGS", "Manage template"
|
78
78
|
subcommand "template", Template
|
@@ -80,9 +80,6 @@ module CloudstackCli
|
|
80
80
|
desc "router SUBCOMMAND ...ARGS", "Manage virtual routers"
|
81
81
|
subcommand "router", Router
|
82
82
|
|
83
|
-
desc "router SUBCOMMAND ...ARGS", "Manage virtual routers"
|
84
|
-
subcommand "router", Router
|
85
|
-
|
86
83
|
desc "volume SUBCOMMAND ...ARGS", "Manage volumes"
|
87
84
|
subcommand "volume", Volume
|
88
85
|
|
@@ -95,10 +92,13 @@ module CloudstackCli
|
|
95
92
|
desc "domain SUBCOMMAND ...ARGS", "Manage domains"
|
96
93
|
subcommand "domain", Domain
|
97
94
|
|
98
|
-
desc "
|
99
|
-
subcommand "
|
95
|
+
desc "ip_address SUBCOMMAND ...ARGS", "Manage ip addresses"
|
96
|
+
subcommand "ip_address", IpAddress
|
100
97
|
|
101
98
|
desc "capacity SUBCOMMAND ...ARGS", "Lists all the system wide capacities"
|
102
99
|
subcommand "capacity", Capacity
|
100
|
+
|
101
|
+
desc "port_rules SUBCOMMAND ...ARGS", "Manage portforwarding rules"
|
102
|
+
subcommand "port_rule", PortRule
|
103
103
|
end
|
104
104
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class IpAddress < CloudstackCli::Base
|
2
|
+
|
3
|
+
desc "release ID", "release public IP address"
|
4
|
+
def release(id)
|
5
|
+
puts "OK" if client.disassociate_ip_address(id)
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "assign NETWORK", "assign a public IP address"
|
9
|
+
option :project
|
10
|
+
def assign(network)
|
11
|
+
project = find_project if options[:project]
|
12
|
+
unless network = client.get_network(network, project ? project["id"] : nil)
|
13
|
+
error "Network #{network} not found."
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
ip = client.associate_ip_address(network["id"])
|
17
|
+
puts
|
18
|
+
say ip['ipaddress']
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "list", "list public IP address"
|
22
|
+
option :project
|
23
|
+
option :account
|
24
|
+
option :listall
|
25
|
+
def list
|
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
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -7,31 +7,34 @@ class Network < CloudstackCli::Base
|
|
7
7
|
|
8
8
|
desc "list", "list networks"
|
9
9
|
option :project
|
10
|
-
option :account
|
10
|
+
option :account
|
11
|
+
option :showid, type: :boolean
|
11
12
|
def list
|
12
13
|
project = find_project if options[:project]
|
13
|
-
|
14
14
|
networks = []
|
15
15
|
if project
|
16
16
|
networks = client.list_networks(project['id'])
|
17
|
+
elsif options[:account]
|
18
|
+
networks = client.list_networks(account: options[:account])
|
17
19
|
else
|
18
|
-
networks = client.list_networks(-1
|
19
|
-
networks + client.list_networks(nil, options[:account] != '' ? options[:account] : nil )
|
20
|
+
networks = client.list_networks(project_id: -1)
|
20
21
|
end
|
21
22
|
|
22
23
|
if networks.size < 1
|
23
24
|
puts "No networks found"
|
24
25
|
else
|
25
|
-
table = [["Name", "Displaytext", "Account", "Project", "
|
26
|
+
table = [["Name", "Displaytext", "Account", "Project", "Domain", "State"]]
|
27
|
+
table[0] << "ID" if options[:showid]
|
26
28
|
networks.each do |network|
|
27
29
|
table << [
|
28
30
|
network["name"],
|
29
31
|
network["displaytext"],
|
30
32
|
network["account"],
|
31
33
|
network["project"],
|
32
|
-
network["
|
33
|
-
network["
|
34
|
+
network["domain"],
|
35
|
+
network["state"]
|
34
36
|
]
|
37
|
+
table[-1] << network["id"] if options[:showid]
|
35
38
|
end
|
36
39
|
print_table table
|
37
40
|
end
|
@@ -5,16 +5,17 @@ class PhysicalNetwork < CloudstackCli::Base
|
|
5
5
|
def list
|
6
6
|
project = find_project if options[:project]
|
7
7
|
networks = client.list_physical_networks
|
8
|
+
zones = client.list_zones
|
8
9
|
if networks.size < 1
|
9
10
|
puts "No networks found"
|
10
11
|
else
|
11
|
-
table = [['Name', 'State', '
|
12
|
+
table = [['Name', 'State', 'Zone', 'ID']]
|
12
13
|
networks.each do |network|
|
13
14
|
table << [
|
14
15
|
network["name"],
|
15
16
|
network["state"],
|
16
|
-
network["
|
17
|
-
network["
|
17
|
+
zones.select{|zone| zone['id'] == network["zoneid"]}.first["name"],
|
18
|
+
network["id"]
|
18
19
|
]
|
19
20
|
end
|
20
21
|
print_table table
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class PortRule < CloudstackCli::Base
|
2
|
+
|
3
|
+
desc "create SERVER", "create portforwarding rules"
|
4
|
+
option :rules, type: :array,
|
5
|
+
required: true,
|
6
|
+
desc: "Port Forwarding Rules [public_ip]:port ...",
|
7
|
+
aliases: '-r'
|
8
|
+
option :network, required: true, aliases: '-n'
|
9
|
+
option :project
|
10
|
+
def create(server_name)
|
11
|
+
unless server = client.get_server(server_name)
|
12
|
+
error "Server #{server_name} not found."
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
frontendip = nil
|
16
|
+
project = client.get_project(project)
|
17
|
+
options[:rules].each do |pf_rule|
|
18
|
+
ip = pf_rule.split(":")[0]
|
19
|
+
if ip != ''
|
20
|
+
ip_addr = client.get_public_ip_address(ip)
|
21
|
+
else
|
22
|
+
ip_addr = frontendip ||= client.associate_ip_address(
|
23
|
+
client.get_network(options[:network], project ? project["id"] : nil)["id"]
|
24
|
+
)
|
25
|
+
end
|
26
|
+
port = pf_rule.split(":")[1]
|
27
|
+
puts
|
28
|
+
say "Create port forwarding rule #{ip_addr["ipaddress"]}:#{port} for server #{server_name}.", :yellow
|
29
|
+
client.create_port_forwarding_rule(ip_addr["id"], port, 'TCP', port, server["id"])
|
30
|
+
puts
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "list", "list portforwarding rules"
|
35
|
+
option :project
|
36
|
+
def list
|
37
|
+
project_id = find_project['id'] if options[:project]
|
38
|
+
rules = client.list_port_forwarding_rules(ip_address_id=nil, project_id)
|
39
|
+
if rules.size < 1
|
40
|
+
puts "No rules found."
|
41
|
+
else
|
42
|
+
table = [["IP", "Server", "Public-Port", "Private-Port", "Protocol", "State"]]
|
43
|
+
rules.each do |rule|
|
44
|
+
table << [
|
45
|
+
rule['ipaddress'],
|
46
|
+
rule['virtualmachinename'],
|
47
|
+
print_ports(rule, 'public'),
|
48
|
+
print_ports(rule, 'private'),
|
49
|
+
rule['protocol'],
|
50
|
+
rule['state']
|
51
|
+
]
|
52
|
+
end
|
53
|
+
print_table table
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
no_commands do
|
58
|
+
def print_ports(rule, type)
|
59
|
+
if rule["#{type}port"] == rule["#{type}endport"]
|
60
|
+
return rule["#{type}port"]
|
61
|
+
else
|
62
|
+
return rule["#{type}port"] + "-" + rule["#{type}endport"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class Server < CloudstackCli::Base
|
2
|
+
include CloudstackCli::Helper
|
2
3
|
|
3
4
|
desc "list", "list servers"
|
4
5
|
option :project
|
@@ -14,7 +15,7 @@ class Server < CloudstackCli::Base
|
|
14
15
|
end
|
15
16
|
servers = client.list_servers(options)
|
16
17
|
if servers.size < 1
|
17
|
-
puts "No servers found"
|
18
|
+
puts "No servers found."
|
18
19
|
else
|
19
20
|
table = [["Name", "State", "Offering", "Zone", options[:project] ? "Project" : "Account", "IP's"]]
|
20
21
|
servers.each do |server|
|
@@ -37,20 +38,36 @@ class Server < CloudstackCli::Base
|
|
37
38
|
option :offering, required: true
|
38
39
|
option :networks, type: :array, required: true
|
39
40
|
option :project
|
40
|
-
option :port_rules, type: :array,
|
41
|
+
option :port_rules, type: :array,
|
41
42
|
default: [],
|
42
|
-
|
43
|
+
desc: "Port Forwarding Rules [public_ip]:port ..."
|
43
44
|
option :interactive, type: :boolean
|
44
45
|
def create(name)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
if project = @cs.get_project(project)
|
47
|
+
project_id = project["id"]
|
48
|
+
end
|
49
|
+
server = client.get_server(name, project_id)
|
50
|
+
unless server
|
51
|
+
say "Create server #{name}...", :yellow
|
52
|
+
server = client.create_server(
|
53
|
+
name, options[:offering], options[:template],
|
54
|
+
options[:zone], options[:networks], options[:project]
|
55
|
+
)
|
56
|
+
puts
|
57
|
+
say "Server #{name} has been created.", :green
|
58
|
+
client.wait_for_server_state(server["id"], "Running")
|
59
|
+
say "Server #{name} is running.", :green
|
60
|
+
else
|
61
|
+
say "Server #{name} already exists.", :green
|
62
|
+
# TODO: check status of server
|
63
|
+
end
|
64
|
+
|
65
|
+
if options[:port_rules] && options[:port_rules].size > 0
|
66
|
+
invoke "port_rule:create", name,
|
67
|
+
project: options[:project],
|
68
|
+
network: options[:networks].first,
|
69
|
+
rules: options[:port_rules]
|
70
|
+
end
|
54
71
|
end
|
55
72
|
|
56
73
|
desc "destroy NAME [NAME2 ..]", "destroy a server"
|
@@ -76,7 +93,7 @@ class Server < CloudstackCli::Base
|
|
76
93
|
|
77
94
|
desc "bootstrap", "interactive creation of a server with network access"
|
78
95
|
def bootstrap
|
79
|
-
|
96
|
+
bootstrap_server_interactive
|
80
97
|
end
|
81
98
|
|
82
99
|
desc "stop NAME", "stop a server"
|
@@ -1,23 +1,27 @@
|
|
1
1
|
class Stack < CloudstackCli::Base
|
2
|
+
include CloudstackCli::Helper
|
2
3
|
|
3
4
|
desc "create STACKFILE", "create a stack of servers"
|
4
5
|
def create(stackfile)
|
5
6
|
stack = parse_stackfile(stackfile)
|
6
|
-
say "
|
7
|
-
|
7
|
+
say "Create stack #{stack["name"]}..."
|
8
|
+
threads = []
|
8
9
|
stack["servers"].each do |server|
|
9
|
-
server["name"].split(', ').
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
server["name"].split(', ').each_with_index do |name, i|
|
11
|
+
threads << Thread.new(i) {
|
12
|
+
bootstrap_server(
|
13
|
+
name,
|
14
|
+
server["zone"] || stack["zone"],
|
15
|
+
server["template"],
|
16
|
+
server["offering"],
|
17
|
+
server["networks"] ? server["networks"].split(', ') : nil,
|
18
|
+
server["port_rules"] ? server["port_rules"].split(', ') : nil,
|
19
|
+
stack["project"]
|
20
|
+
)
|
21
|
+
}
|
19
22
|
end
|
20
23
|
end
|
24
|
+
threads.each {|t| t.join }
|
21
25
|
end
|
22
26
|
|
23
27
|
desc "destroy STACKFILE", "destroy a stack of servers"
|
@@ -8,7 +8,7 @@ class Template < CloudstackCli::Base
|
|
8
8
|
say "unsupported template type '#{type}'", :red
|
9
9
|
exit 1
|
10
10
|
end
|
11
|
-
templates = client.list_templates(type, project ? project['id'] : nil)
|
11
|
+
templates = client.list_templates(type: type, project_id: project ? project['id'] : nil)
|
12
12
|
if templates.size < 1
|
13
13
|
puts "No templates found"
|
14
14
|
else
|
@@ -4,7 +4,7 @@ class Volume < CloudstackCli::Base
|
|
4
4
|
option :project
|
5
5
|
def list
|
6
6
|
project = find_project if options[:project]
|
7
|
-
networks = client.list_networks(project ? project['id'] : nil)
|
7
|
+
networks = client.list_networks(project_id: project ? project['id'] : nil)
|
8
8
|
if networks.size < 1
|
9
9
|
puts "No networks found"
|
10
10
|
else
|
@@ -1,179 +1,121 @@
|
|
1
1
|
module CloudstackCli
|
2
|
-
|
3
|
-
attr_reader :cs
|
4
|
-
|
5
|
-
def initialize(config_file)
|
6
|
-
@config_file = config_file
|
7
|
-
@cs = CloudstackClient::Connection.new(
|
8
|
-
options[:url],
|
9
|
-
options[:api_key],
|
10
|
-
options[:secret_key]
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
def options
|
15
|
-
@options ||= CloudstackClient::ConnectionHelper.load_configuration(@config_file)
|
16
|
-
end
|
17
|
-
|
2
|
+
module Helper
|
18
3
|
def print_options(options, attr = 'name')
|
19
4
|
options.to_enum.with_index(1).each do |option, i|
|
20
5
|
puts "#{i}: #{option[attr]}"
|
21
6
|
end
|
22
7
|
end
|
23
8
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def server_offerings(domain = nil)
|
29
|
-
@server_offerings ||= @cs.list_service_offerings(domain)
|
30
|
-
end
|
31
|
-
|
32
|
-
def templates(type = 'featured', project_id = -1)
|
33
|
-
@templates ||= @cs.list_templates(type, project_id)
|
34
|
-
end
|
35
|
-
|
36
|
-
def projects
|
37
|
-
@projects ||= @cs.list_projects
|
38
|
-
end
|
39
|
-
|
40
|
-
def zones
|
41
|
-
@zones ||= @cs.list_zones
|
42
|
-
end
|
43
|
-
|
44
|
-
def networks(project_id = nil)
|
45
|
-
@cs.list_networks(project_id)
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
def volumes(project_id = nil)
|
50
|
-
@cs.list_volumes(project_id)
|
51
|
-
end
|
52
|
-
|
53
|
-
def virtual_machines(options = {})
|
54
|
-
@cs.list_servers(options)
|
9
|
+
def ask_number(question)
|
10
|
+
number = ask(question).to_i - 1
|
11
|
+
number < 0 ? 0 : number
|
55
12
|
end
|
56
13
|
|
57
14
|
def bootstrap_server(name, zone, template, offering, networks, pf_rules = [], project = nil)
|
58
|
-
|
59
|
-
|
60
|
-
|
15
|
+
if project = client.get_project(project)
|
16
|
+
project_id = project["id"]
|
17
|
+
project_name = project['name']
|
18
|
+
end
|
19
|
+
server = client.get_server(name, project_id)
|
61
20
|
unless server
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
zone,
|
68
|
-
networks,
|
69
|
-
project
|
70
|
-
)
|
71
|
-
|
21
|
+
say "Create server #{name}..."
|
22
|
+
server = client.create_server(
|
23
|
+
name, offering, template,
|
24
|
+
zone, networks, project_name
|
25
|
+
)
|
72
26
|
puts
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
@cs.wait_for_server_state(server["id"], "Running")
|
77
|
-
puts "OK!".color(:green)
|
27
|
+
say "Server #{server["name"]} has been created.", :green
|
28
|
+
client.wait_for_server_state(server["id"], "Running")
|
29
|
+
say "Server #{server["name"]} is running.", :green
|
78
30
|
else
|
79
|
-
|
31
|
+
say "Server #{name} already exists.", :green
|
80
32
|
end
|
81
33
|
|
82
|
-
|
83
|
-
|
34
|
+
if pf_rules && pf_rules.size > 0
|
35
|
+
puts
|
84
36
|
frontendip = nil
|
85
|
-
|
86
|
-
pf_rules.each do |pf_rule|
|
37
|
+
pf_rules.each do |pf_rule|
|
87
38
|
ip = pf_rule.split(":")[0]
|
88
39
|
if ip != ''
|
89
|
-
|
40
|
+
ip_addr = client.get_public_ip_address(ip)
|
90
41
|
else
|
91
|
-
ip_addr = frontendip ||=
|
92
|
-
|
42
|
+
ip_addr = frontendip ||= client.associate_ip_address(
|
43
|
+
client.get_network(networks[0], project_id)["id"]
|
93
44
|
)
|
94
45
|
end
|
95
|
-
|
46
|
+
port = pf_rule.split(":")[1]
|
96
47
|
puts
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
puts
|
104
|
-
puts "Complete!".color(:green)
|
105
|
-
end
|
106
|
-
|
107
|
-
def list_accounts(name = nil)
|
108
|
-
@cs.list_accounts({ name: name })
|
109
|
-
end
|
110
|
-
|
111
|
-
def list_load_balancer_rules(project = nil)
|
112
|
-
@cs.list_load_balancer_rules(project)
|
113
|
-
end
|
114
|
-
|
115
|
-
def create_load_balancer_rule(name, ip, private_port, public_port, options = {})
|
116
|
-
puts "Create rule #{name}...".color(:yellow)
|
117
|
-
@cs.create_load_balancer_rule(name, ip, private_port, public_port, options = {})
|
118
|
-
puts "OK!".color(:green)
|
119
|
-
end
|
120
|
-
|
121
|
-
def assign_to_load_balancer_rule(id, names)
|
122
|
-
puts "Add #{names.join(', ')} to rule #{id}...".color(:yellow)
|
123
|
-
rule = @cs.assign_to_load_balancer_rule(id, names)
|
124
|
-
if rule['success']
|
125
|
-
puts "OK!".color(:green)
|
126
|
-
else
|
127
|
-
puts "Failed!".color(:red)
|
48
|
+
say "Create port forwarding rule #{ip}:#{port} ", :yellow
|
49
|
+
client.create_port_forwarding_rule(ip_addr["id"], port, 'TCP', port, server["id"])
|
50
|
+
puts
|
51
|
+
end
|
128
52
|
end
|
53
|
+
puts
|
129
54
|
end
|
130
55
|
|
131
56
|
def bootstrap_server_interactive
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
print "Please provide a name for the new server".background(:blue)
|
141
|
-
puts " (spaces or special characters are NOT allowed): "
|
142
|
-
server_name = gets.chomp
|
143
|
-
|
144
|
-
if projects.size > 0
|
145
|
-
puts "Select a project".background(:blue)
|
146
|
-
print_options(projects)
|
147
|
-
project = gets.chomp.to_i - 1
|
148
|
-
end
|
149
|
-
|
150
|
-
puts "Select a computing offering:".background(:blue)
|
151
|
-
print_options(server_offerings)
|
152
|
-
service_offering = gets.chomp.to_i - 1
|
57
|
+
zones = client.list_zones
|
58
|
+
if zones.size > 1
|
59
|
+
say "Select a availability zone:", :yellow
|
60
|
+
print_options(zones)
|
61
|
+
zone = ask_number("Zone Nr.: ")
|
62
|
+
else
|
63
|
+
zone = 0
|
64
|
+
end
|
153
65
|
|
154
|
-
|
155
|
-
|
156
|
-
|
66
|
+
projects = client.list_projects
|
67
|
+
if yes?("Do you want to deploy your server within a project?") && projects.size > 0
|
68
|
+
if projects.size > 0
|
69
|
+
say "Select a project", :yellow
|
70
|
+
print_options(projects)
|
71
|
+
project = ask_number("Project Nr.: ")
|
72
|
+
end
|
73
|
+
project_id = projects[project]['id'] rescue nil
|
74
|
+
end
|
157
75
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
76
|
+
say "Please provide a name for the new server", :yellow
|
77
|
+
say "(spaces or special characters are NOT allowed)"
|
78
|
+
server_name = ask("Server name: ")
|
79
|
+
|
80
|
+
server_offerings = client.list_service_offerings
|
81
|
+
say "Select a computing offering:", :yellow
|
82
|
+
print_options(server_offerings)
|
83
|
+
service_offering = ask_number("Offering Nr.: ")
|
84
|
+
|
85
|
+
templates = client.list_templates(project_id: project_id, zone_id: zones[zone]["id"])
|
86
|
+
say "Select a template:", :yellow
|
87
|
+
print_options(templates)
|
88
|
+
template = ask_number("Template Nr.: ")
|
89
|
+
|
90
|
+
networks = client.list_networks(project_id: project_id, zone_id: zones[zone]["id"])
|
91
|
+
if networks.size > 1
|
92
|
+
say "Select a network:", :yellow
|
93
|
+
print_options(networks)
|
94
|
+
network = ask_number("Network Nr.: ")
|
95
|
+
else
|
96
|
+
network = 0
|
97
|
+
end
|
168
98
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
99
|
+
say "You entered the following configuration:", :yellow
|
100
|
+
table = [["Zone", zones[zone]["name"]]]
|
101
|
+
table << ["Server Name", server_name]
|
102
|
+
table << ["Template", templates[template]["name"]]
|
103
|
+
table << ["Offering", server_offerings[service_offering]["name"]]
|
104
|
+
table << ["Network", networks[network]["name"]]
|
105
|
+
table << ["Project", projects[project]["name"]] if project
|
106
|
+
print_table table
|
107
|
+
|
108
|
+
if yes? "Do you want to deploy this server?"
|
109
|
+
bootstrap_server(
|
110
|
+
server_name,
|
111
|
+
zones[zone]["name"],
|
112
|
+
templates[template]["name"],
|
113
|
+
server_offerings[service_offering]["name"],
|
114
|
+
[networks[network]["name"]], nil,
|
115
|
+
project ? projects[project]["name"] : nil
|
116
|
+
)
|
117
|
+
end
|
177
118
|
end
|
119
|
+
|
178
120
|
end
|
179
121
|
end
|
@@ -103,7 +103,7 @@ module CloudstackClient
|
|
103
103
|
return nil unless server
|
104
104
|
|
105
105
|
nic = get_server_default_nic(server) || {}
|
106
|
-
networks = list_networks(server['projectid']) || {}
|
106
|
+
networks = list_networks(project_id: server['projectid']) || {}
|
107
107
|
|
108
108
|
id = nic['networkid']
|
109
109
|
network = networks.select { |net|
|
@@ -418,13 +418,14 @@ module CloudstackClient
|
|
418
418
|
# * executable - all templates that can be used to deploy a new VM
|
419
419
|
# * community - templates that are public
|
420
420
|
|
421
|
-
def list_templates(
|
422
|
-
filter
|
421
|
+
def list_templates(args = {})
|
422
|
+
filter = args[:filter] || 'featured'
|
423
423
|
params = {
|
424
424
|
'command' => 'listTemplates',
|
425
425
|
'templateFilter' => filter
|
426
426
|
}
|
427
|
-
params['projectid'] = project_id if project_id
|
427
|
+
params['projectid'] = args[:project_id] if args[:project_id]
|
428
|
+
params['zoneid'] = args[:zone_id] if args[:zone_id]
|
428
429
|
|
429
430
|
json = send_request(params)
|
430
431
|
json['template'] || []
|
@@ -449,7 +450,6 @@ module CloudstackClient
|
|
449
450
|
return n
|
450
451
|
end
|
451
452
|
}
|
452
|
-
|
453
453
|
nil
|
454
454
|
end
|
455
455
|
|
@@ -482,19 +482,20 @@ module CloudstackClient
|
|
482
482
|
##
|
483
483
|
# Lists all available networks.
|
484
484
|
|
485
|
-
def list_networks(
|
485
|
+
def list_networks(args = {})
|
486
486
|
params = {
|
487
487
|
'command' => 'listNetworks',
|
488
488
|
'listall' => true,
|
489
489
|
}
|
490
|
-
params['projectid'] = project_id if project_id
|
491
|
-
if
|
492
|
-
|
490
|
+
params['projectid'] = args[:project_id] if args[:project_id]
|
491
|
+
params['zoneid'] = args[:zone_id] if args[:zone_id]
|
492
|
+
if args[:account]
|
493
|
+
domain = list_accounts(name: args[:account])
|
493
494
|
if domain.size > 0
|
494
|
-
params['account'] = account
|
495
|
+
params['account'] = args[:account]
|
495
496
|
params['domainid'] = domain.first["domainid"]
|
496
497
|
else
|
497
|
-
puts "Account #{account} not found."
|
498
|
+
puts "Account #{args[:account]} not found."
|
498
499
|
end
|
499
500
|
end
|
500
501
|
json = send_request(params)
|
@@ -575,6 +576,33 @@ module CloudstackClient
|
|
575
576
|
json['zone'] || []
|
576
577
|
end
|
577
578
|
|
579
|
+
##
|
580
|
+
# Lists the public ip addresses.
|
581
|
+
|
582
|
+
def list_public_ip_addresses(args = {})
|
583
|
+
params = {
|
584
|
+
'command' => 'listPublicIpAddresses',
|
585
|
+
'isrecursive' => true
|
586
|
+
}
|
587
|
+
if args[:project]
|
588
|
+
project = get_project(args[:project])
|
589
|
+
params['projectid'] = project['id']
|
590
|
+
end
|
591
|
+
if args[:account]
|
592
|
+
account = list_accounts({name: args[:account]}).first
|
593
|
+
unless account
|
594
|
+
puts "Error: Account #{args[:account]} not found."
|
595
|
+
exit 1
|
596
|
+
end
|
597
|
+
params['domainid'] = account["domainid"]
|
598
|
+
params['account'] = args[:account]
|
599
|
+
end
|
600
|
+
params['listall'] = args[:listall] if args[:listall]
|
601
|
+
|
602
|
+
json = send_request(params)
|
603
|
+
json['publicipaddress'] || []
|
604
|
+
end
|
605
|
+
|
578
606
|
##
|
579
607
|
# Finds the public ip address for a given ip address string.
|
580
608
|
|
@@ -621,13 +649,16 @@ module CloudstackClient
|
|
621
649
|
##
|
622
650
|
# Lists all port forwarding rules.
|
623
651
|
|
624
|
-
def list_port_forwarding_rules(ip_address_id=nil)
|
652
|
+
def list_port_forwarding_rules(ip_address_id=nil, project_id)
|
625
653
|
params = {
|
626
|
-
'command' => 'listPortForwardingRules'
|
654
|
+
'command' => 'listPortForwardingRules',
|
655
|
+
'listall' => true,
|
656
|
+
'isrecursive' => true
|
627
657
|
}
|
628
658
|
params['ipAddressId'] = ip_address_id if ip_address_id
|
659
|
+
params['projectid'] = project_id if project_id
|
629
660
|
json = send_request(params)
|
630
|
-
json['portforwardingrule']
|
661
|
+
json['portforwardingrule'] || []
|
631
662
|
end
|
632
663
|
|
633
664
|
##
|
data/lib/cloudstack_cli.rb
CHANGED
data/test/stack_example.json
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
"description": "Web nodes",
|
11
11
|
"template": "CentOS-6.4-x64-v1.2",
|
12
12
|
"offering": "1cpu_1gb",
|
13
|
-
"networks": "
|
13
|
+
"networks": "M_PLAY",
|
14
14
|
"port_rules": ":80, :443"
|
15
15
|
},
|
16
16
|
{
|
@@ -18,7 +18,7 @@
|
|
18
18
|
"description": "PostgreSQL Master",
|
19
19
|
"template": "CentOS-6.4-x64-v1.2",
|
20
20
|
"offering": "2cpu_4gb",
|
21
|
-
"networks": "
|
21
|
+
"networks": "M_PLAY"
|
22
22
|
}
|
23
23
|
]
|
24
24
|
}
|
metadata
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudstack-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Nik Wolfgramm
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-06 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: rdoc
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
|
-
- - '>='
|
19
|
+
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
19
21
|
version: '0'
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
|
-
- - '>='
|
27
|
+
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '0'
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: rake
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :development
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: thor
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -55,6 +62,7 @@ dependencies:
|
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: net-ssh
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ~>
|
60
68
|
- !ruby/object:Gem::Version
|
@@ -62,24 +70,11 @@ dependencies:
|
|
62
70
|
type: :runtime
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ~>
|
67
76
|
- !ruby/object:Gem::Version
|
68
77
|
version: 2.6.7
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rainbow
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ~>
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 1.1.4
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ~>
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 1.1.4
|
83
78
|
description: cloudstack-cli is a CloudStack API client written in Ruby.
|
84
79
|
email:
|
85
80
|
- nik.wolfgramm@gmail.com
|
@@ -101,12 +96,13 @@ files:
|
|
101
96
|
- lib/cloudstack-cli/commands/account.rb
|
102
97
|
- lib/cloudstack-cli/commands/capacity.rb
|
103
98
|
- lib/cloudstack-cli/commands/domain.rb
|
99
|
+
- lib/cloudstack-cli/commands/ip_address.rb
|
104
100
|
- lib/cloudstack-cli/commands/load_balancer.rb
|
105
101
|
- lib/cloudstack-cli/commands/network.rb
|
106
102
|
- lib/cloudstack-cli/commands/offering.rb
|
107
103
|
- lib/cloudstack-cli/commands/physical_network.rb
|
104
|
+
- lib/cloudstack-cli/commands/port_rule.rb
|
108
105
|
- lib/cloudstack-cli/commands/project.rb
|
109
|
-
- lib/cloudstack-cli/commands/publicip.rb
|
110
106
|
- lib/cloudstack-cli/commands/router.rb
|
111
107
|
- lib/cloudstack-cli/commands/server.rb
|
112
108
|
- lib/cloudstack-cli/commands/stack.rb
|
@@ -123,7 +119,6 @@ files:
|
|
123
119
|
- test/stack_example.json
|
124
120
|
homepage: https://bitbucket.org/swisstxt/cloudstack-cli
|
125
121
|
licenses: []
|
126
|
-
metadata: {}
|
127
122
|
post_install_message:
|
128
123
|
rdoc_options:
|
129
124
|
- --line-numbers
|
@@ -131,20 +126,22 @@ rdoc_options:
|
|
131
126
|
require_paths:
|
132
127
|
- lib
|
133
128
|
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
134
130
|
requirements:
|
135
|
-
- - '>='
|
131
|
+
- - ! '>='
|
136
132
|
- !ruby/object:Gem::Version
|
137
133
|
version: 1.9.3
|
138
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
139
136
|
requirements:
|
140
|
-
- - '>='
|
137
|
+
- - ! '>='
|
141
138
|
- !ruby/object:Gem::Version
|
142
139
|
version: '0'
|
143
140
|
requirements: []
|
144
141
|
rubyforge_project:
|
145
|
-
rubygems_version:
|
142
|
+
rubygems_version: 1.8.23
|
146
143
|
signing_key:
|
147
|
-
specification_version:
|
144
|
+
specification_version: 3
|
148
145
|
summary: cloudstack-cli CloudStack API client
|
149
146
|
test_files:
|
150
147
|
- test/stack_example.json
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 71a5b85637b159d9b71b76d9c5703ec7eff903c9
|
4
|
-
data.tar.gz: 92774b4af91e17a60e84156c8532ec5eafad2fb2
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: ee45344f2a30049f4de0c8c9aa5cd884faaf6b3a7535656880c9357832846cd197c8ab4c5459ccb703dbda51f2b28098086b51d7fb5840e36352e51ea4c7f648
|
7
|
-
data.tar.gz: 6edfcef7302b4dfd45ddef2ab998c01d908084b1d3f33df872ff7402a4a0951ba38f827a97023f38838c4bb4aa99173b8e125c482394c38d36c6eeb8a8fa75fe
|