cloudstack-cli 0.2.1 → 0.2.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/Gemfile.lock +1 -1
- data/README.md +5 -1
- data/lib/cloudstack-cli/base.rb +3 -2
- data/lib/cloudstack-cli/commands/server.rb +12 -34
- data/lib/cloudstack-cli/commands/stack.rb +14 -7
- data/lib/cloudstack-cli/helper.rb +10 -22
- data/lib/cloudstack-cli/version.rb +1 -1
- data/lib/cloudstack-client/client.rb +4 -3
- data/lib/cloudstack-client/commands/network.rb +14 -0
- data/lib/cloudstack-client/commands/server.rb +2 -0
- data/lib/cloudstack-client/version.rb +1 -1
- data/test/stack_example.json +6 -3
- metadata +1 -1
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -55,6 +55,8 @@ An example stackfile looks like this
|
|
|
55
55
|
"description": "Web Application Stack",
|
|
56
56
|
"version": "1.0",
|
|
57
57
|
"zone": "DC-BIE-1",
|
|
58
|
+
"group": "my_web_stack",
|
|
59
|
+
"keypair": "mykeypair",
|
|
58
60
|
"servers": [
|
|
59
61
|
{
|
|
60
62
|
"name": "web-d1, web-d2",
|
|
@@ -67,7 +69,9 @@ An example stackfile looks like this
|
|
|
67
69
|
{
|
|
68
70
|
"name": "db-01",
|
|
69
71
|
"description": "PostgreSQL Master",
|
|
70
|
-
"
|
|
72
|
+
"iso": "CentOS-6.4-x86_64-swisstxt-v15",
|
|
73
|
+
"disk_offering": "Perf Storage",
|
|
74
|
+
"disk_size": "5",
|
|
71
75
|
"offering": "2cpu_4gb",
|
|
72
76
|
"networks": "server_network, storage_network"
|
|
73
77
|
}
|
data/lib/cloudstack-cli/base.rb
CHANGED
|
@@ -18,12 +18,13 @@ module CloudstackCli
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
no_commands do
|
|
21
|
-
def client
|
|
21
|
+
def client(opts = {})
|
|
22
22
|
@config ||= CloudstackClient::ConnectionHelper.load_configuration(options[:config])
|
|
23
23
|
@client ||= CloudstackClient::Connection.new(
|
|
24
24
|
@config[:url],
|
|
25
25
|
@config[:api_key],
|
|
26
|
-
@config[:secret_key]
|
|
26
|
+
@config[:secret_key],
|
|
27
|
+
opts
|
|
27
28
|
)
|
|
28
29
|
end
|
|
29
30
|
|
|
@@ -33,44 +33,22 @@ class Server < CloudstackCli::Base
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
desc "create NAME", "create a server"
|
|
36
|
-
option :template, desc: "name of the template"
|
|
37
|
-
option :iso, desc: "name of the iso"
|
|
38
|
-
option :offering, required: true
|
|
39
|
-
option :networks, type: :array
|
|
40
|
-
option :zone
|
|
41
|
-
option :project
|
|
42
|
-
option :port_rules, type: :array,
|
|
36
|
+
option :template, aliases: '-t', desc: "name of the template"
|
|
37
|
+
option :iso, desc: "name of the iso", desc: "name of the iso template"
|
|
38
|
+
option :offering, aliases: '-o', required: true, desc: "computing offering name"
|
|
39
|
+
option :networks, aliases: '-n', type: :array, desc: "network names"
|
|
40
|
+
option :zone, aliases: '-z', desc: "availability zone name"
|
|
41
|
+
option :project, aliases: '-p', desc: "project name"
|
|
42
|
+
option :port_rules, aliases: '-pr', type: :array,
|
|
43
43
|
default: [],
|
|
44
44
|
desc: "Port Forwarding Rules [public_ip]:port ..."
|
|
45
|
-
option :disk_offering
|
|
45
|
+
option :disk_offering, desc: "disk offering - data disk for template, root disk for iso"
|
|
46
46
|
option :disk_size, desc: "disk size in GB"
|
|
47
47
|
option :hypervisor, desc: "only used for iso deployments, default: vmware"
|
|
48
48
|
option :keypair, desc: "the name of the ssh keypair to use"
|
|
49
|
+
option :group, desc: "group name"
|
|
49
50
|
def create(name)
|
|
50
|
-
|
|
51
|
-
project_id = project["id"]
|
|
52
|
-
end
|
|
53
|
-
server = client.get_server(name, project_id)
|
|
54
|
-
unless server
|
|
55
|
-
say "Create server #{name}...", :yellow
|
|
56
|
-
server = client.create_server(
|
|
57
|
-
options.merge({name: name})
|
|
58
|
-
)
|
|
59
|
-
puts
|
|
60
|
-
say "Server #{name} has been created.", :green
|
|
61
|
-
client.wait_for_server_state(server["id"], "Running")
|
|
62
|
-
say "Server #{name} is running.", :green
|
|
63
|
-
else
|
|
64
|
-
say "Server #{name} already exists.", :yellow
|
|
65
|
-
# TODO: check status of server
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
if options[:port_rules] && options[:port_rules].size > 0
|
|
69
|
-
invoke "port_rule:create", name,
|
|
70
|
-
project: options[:project],
|
|
71
|
-
network: options[:networks].first,
|
|
72
|
-
rules: options[:port_rules]
|
|
73
|
-
end
|
|
51
|
+
bootstrap_server(options.merge({name: name}))
|
|
74
52
|
end
|
|
75
53
|
|
|
76
54
|
desc "destroy NAME [NAME2 ..]", "destroy a server"
|
|
@@ -85,8 +63,8 @@ class Server < CloudstackCli::Base
|
|
|
85
63
|
say "Server #{server_name} not found.", :red
|
|
86
64
|
else
|
|
87
65
|
ask = "Destroy #{server_name} (#{server['state']})?"
|
|
88
|
-
if options[:force] == true || yes?(ask)
|
|
89
|
-
say "
|
|
66
|
+
if options[:force] == true || yes?(ask, :yellow)
|
|
67
|
+
say "destroying #{server_name} "
|
|
90
68
|
client.destroy_server(server["id"])
|
|
91
69
|
puts
|
|
92
70
|
end
|
|
@@ -10,13 +10,19 @@ class Stack < CloudstackCli::Base
|
|
|
10
10
|
server["name"].split(', ').each_with_index do |name, i|
|
|
11
11
|
threads << Thread.new(i) {
|
|
12
12
|
bootstrap_server(
|
|
13
|
-
name,
|
|
14
|
-
server["
|
|
15
|
-
server["
|
|
16
|
-
server["
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
name: name,
|
|
14
|
+
displayname: server["decription"],
|
|
15
|
+
zone: server["zone"] || stack["zone"],
|
|
16
|
+
template: server["template"],
|
|
17
|
+
iso: server["iso"] ,
|
|
18
|
+
offering: server["offering"],
|
|
19
|
+
networks: server["networks"] ? server["networks"].split(', ') : nil,
|
|
20
|
+
port_rules: server["port_rules"] ? server["port_rules"].split(', ') : nil,
|
|
21
|
+
project: stack["project"],
|
|
22
|
+
disk_offering: server["disk_offering"],
|
|
23
|
+
disk_size: server["disk_size"],
|
|
24
|
+
group: server["group"] || stack["group"],
|
|
25
|
+
keypair: server["keypair"] || stack["keypair"]
|
|
20
26
|
)
|
|
21
27
|
}
|
|
22
28
|
end
|
|
@@ -37,6 +43,7 @@ class Stack < CloudstackCli::Base
|
|
|
37
43
|
server["name"].split(', ').each {|name| servers << name}
|
|
38
44
|
end
|
|
39
45
|
say "Destroy stack #{stack["name"]}...", :yellow
|
|
46
|
+
puts
|
|
40
47
|
invoke "server:destroy", servers, project: stack["project"], force: options[:force]
|
|
41
48
|
end
|
|
42
49
|
|
|
@@ -11,50 +11,38 @@ module CloudstackCli
|
|
|
11
11
|
number < 0 ? 0 : number
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def bootstrap_server(
|
|
15
|
-
if project = client.get_project(project)
|
|
14
|
+
def bootstrap_server(args = {})
|
|
15
|
+
if args[:project] && project = client(quiet: true).get_project(args[:project])
|
|
16
16
|
project_id = project["id"]
|
|
17
17
|
project_name = project['name']
|
|
18
18
|
end
|
|
19
|
-
server = client.get_server(name, project_id)
|
|
19
|
+
server = client(quiet: true).get_server(args[:name], project_id)
|
|
20
20
|
unless server
|
|
21
|
-
say "Create server #{name}..."
|
|
22
|
-
server = client.create_server(
|
|
23
|
-
name: name,
|
|
24
|
-
offering: offering,
|
|
25
|
-
template: template,
|
|
26
|
-
zone: zone,
|
|
27
|
-
networks: networks,
|
|
28
|
-
project: project_name
|
|
29
|
-
)
|
|
30
|
-
puts
|
|
21
|
+
say "Create server #{args[:name]}...", :yellow
|
|
22
|
+
server = client.create_server(args)
|
|
31
23
|
say "Server #{server["name"]} has been created.", :green
|
|
32
24
|
client.wait_for_server_state(server["id"], "Running")
|
|
33
25
|
say "Server #{server["name"]} is running.", :green
|
|
34
26
|
else
|
|
35
|
-
say "Server #{name} already exists.", :yellow
|
|
27
|
+
say "Server #{args[:name]} already exists (#{server['state']}).", :yellow
|
|
36
28
|
end
|
|
37
29
|
|
|
38
|
-
if
|
|
39
|
-
puts
|
|
30
|
+
if args[:port_rules] && args[:port_rules].size > 0
|
|
40
31
|
frontendip = nil
|
|
41
|
-
|
|
32
|
+
args[:port_rules].each do |pf_rule|
|
|
42
33
|
ip = pf_rule.split(":")[0]
|
|
43
34
|
if ip != ''
|
|
44
35
|
ip_addr = client.get_public_ip_address(ip)
|
|
45
36
|
else
|
|
46
37
|
ip_addr = frontendip ||= client.associate_ip_address(
|
|
47
|
-
|
|
38
|
+
server["nic"].first["networkid"]
|
|
48
39
|
)
|
|
49
40
|
end
|
|
50
41
|
port = pf_rule.split(":")[1]
|
|
51
|
-
|
|
52
|
-
say "Create port forwarding rule #{ip}:#{port} ", :yellow
|
|
42
|
+
say "Create port forwarding rule #{ip_addr['ipaddress']}:#{port} for server #{args[:name]}.", :yellow
|
|
53
43
|
client.create_port_forwarding_rule(ip_addr["id"], port, 'TCP', port, server["id"])
|
|
54
|
-
puts
|
|
55
44
|
end
|
|
56
45
|
end
|
|
57
|
-
puts
|
|
58
46
|
end
|
|
59
47
|
|
|
60
48
|
def bootstrap_server_interactive
|
|
@@ -20,11 +20,12 @@ module CloudstackClient
|
|
|
20
20
|
include Object.const_get("CloudstackClient").const_get(module_name)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def initialize(api_url, api_key, secret_key)
|
|
23
|
+
def initialize(api_url, api_key, secret_key, opts = {})
|
|
24
24
|
@api_url = api_url
|
|
25
25
|
@api_key = api_key
|
|
26
26
|
@secret_key = secret_key
|
|
27
27
|
@use_ssl = api_url.start_with? "https"
|
|
28
|
+
@verbose = !opts[:quiet]
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
##
|
|
@@ -91,12 +92,12 @@ module CloudstackClient
|
|
|
91
92
|
json = send_request(params)
|
|
92
93
|
status = json['jobstatus']
|
|
93
94
|
|
|
94
|
-
print "."
|
|
95
|
+
print "." if @verbose
|
|
95
96
|
|
|
96
97
|
if status == 1 then
|
|
97
98
|
return json['jobresult']
|
|
98
99
|
elsif status == 2 then
|
|
99
|
-
|
|
100
|
+
puts
|
|
100
101
|
puts "Request failed (#{json['jobresultcode']}): #{json['jobresult']}"
|
|
101
102
|
exit 1
|
|
102
103
|
end
|
|
@@ -2,6 +2,20 @@ module CloudstackClient
|
|
|
2
2
|
|
|
3
3
|
module Network
|
|
4
4
|
|
|
5
|
+
##
|
|
6
|
+
# Finds the network with the specified name.
|
|
7
|
+
|
|
8
|
+
def networkid_to_name(id, project_id=nil)
|
|
9
|
+
params = {
|
|
10
|
+
'command' => 'listNetworks',
|
|
11
|
+
'id' => id
|
|
12
|
+
}
|
|
13
|
+
params['projectid'] = project_id if project_id
|
|
14
|
+
json = send_request(params)
|
|
15
|
+
|
|
16
|
+
json['network'] ? json['network'].first['name'] : nil
|
|
17
|
+
end
|
|
18
|
+
|
|
5
19
|
##
|
|
6
20
|
# Finds the network with the specified name.
|
|
7
21
|
|
|
@@ -206,6 +206,8 @@ module CloudstackClient
|
|
|
206
206
|
params['hypervisor'] = (args[:hypervisor] || 'vmware') if iso
|
|
207
207
|
params['keypair'] = args[:keypair] if args[:keypair]
|
|
208
208
|
params['size'] = args[:disk_size] if args[:disk_size]
|
|
209
|
+
params['group'] = args[:group] if args[:group]
|
|
210
|
+
params['displayname'] = args[:displayname] if args[:displayname]
|
|
209
211
|
|
|
210
212
|
json = send_async_request(params)
|
|
211
213
|
json['virtualmachine']
|
data/test/stack_example.json
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
"version": "1.0",
|
|
5
5
|
"zone": "BIEL_CU01",
|
|
6
6
|
"project": "Playground",
|
|
7
|
+
"group": "my_web_stack",
|
|
7
8
|
"servers": [
|
|
8
9
|
{
|
|
9
|
-
"name": "web-
|
|
10
|
+
"name": "web-001, web-002",
|
|
10
11
|
"description": "Web nodes",
|
|
11
12
|
"template": "CentOS-6.4-x64-v1.2",
|
|
12
13
|
"offering": "1cpu_1gb",
|
|
@@ -14,9 +15,11 @@
|
|
|
14
15
|
"port_rules": ":80, :443"
|
|
15
16
|
},
|
|
16
17
|
{
|
|
17
|
-
"name": "db-
|
|
18
|
+
"name": "db-001",
|
|
18
19
|
"description": "PostgreSQL Master",
|
|
19
|
-
"
|
|
20
|
+
"iso": "CentOS-6.4-x86_64-swisstxt-v15",
|
|
21
|
+
"disk_offering": "Perf Storage",
|
|
22
|
+
"disk_size": "5",
|
|
20
23
|
"offering": "2cpu_4gb",
|
|
21
24
|
"networks": "M_PLAY"
|
|
22
25
|
}
|