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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cloudstack-cli (0.1.1)
4
+ cloudstack-cli (0.1.2)
5
5
  net-ssh (~> 2.6.7)
6
6
  rainbow (~> 1.1.4)
7
7
  thor (~> 0.18.1)
data/README.md CHANGED
@@ -12,19 +12,19 @@ Install the cloudstack-cli gem:
12
12
 
13
13
  Create the initial configuration:
14
14
 
15
- $ cs setup
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
- :api_key: "cloudstack-api-key"
23
- :secret_key: "cloudstack-api-secret"
22
+ :api_key: "cloudstack-api-key"
23
+ :secret_key: "cloudstack-api-secret"
24
24
 
25
25
  ## Usage
26
26
 
27
- Please see http://rubydoc.info/gems/cloudstack-cli/0.0.3/frames
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 Zone too):
86
- (This command is helpful if you have to deploy new versions of Cloudstack when using redumdant routers)
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
 
@@ -24,5 +24,4 @@ Gem::Specification.new do |gem|
24
24
 
25
25
  gem.add_dependency('thor', '~> 0.18.1')
26
26
  gem.add_dependency('net-ssh', '~> 2.6.7')
27
- gem.add_dependency('rainbow', '~> 1.1.4')
28
27
  end
@@ -68,11 +68,11 @@ module CloudstackCli
68
68
  desc "network SUBCOMMAND ...ARGS", "Manage networks"
69
69
  subcommand "network", Network
70
70
 
71
- desc "physicalnetwork SUBCOMMAND ...ARGS", "Manage physical networks"
72
- subcommand "physicalnetwork", PhysicalNetwork
71
+ desc "physical_network SUBCOMMAND ...ARGS", "Manage physical networks"
72
+ subcommand "physical_network", PhysicalNetwork
73
73
 
74
- desc "lb SUBCOMMAND ...ARGS", "Manage load balancing rules"
75
- subcommand "lb", Lb
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 "publicip SUBCOMMAND ...ARGS", "Manage public ip addresses"
99
- subcommand "publicip", Publicip
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
@@ -1,4 +1,4 @@
1
- class Lb < CloudstackCli::Base
1
+ class LoadBalancer < CloudstackCli::Base
2
2
 
3
3
  desc "list", "list load balancer rules"
4
4
  option :project
@@ -7,31 +7,34 @@ class Network < CloudstackCli::Base
7
7
 
8
8
  desc "list", "list networks"
9
9
  option :project
10
- option :account, default: ""
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, options[:account] != '' ? options[:account] : nil )
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", "State", "ID"]]
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["state"],
33
- network["id"]
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', 'ID', 'Zone ID']]
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["id"],
17
- network["zoneid"]
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, aliases: :pf,
41
+ option :port_rules, type: :array,
41
42
  default: [],
42
- description: "Port Forwarding Rules [public_ip]:port ..."
43
+ desc: "Port Forwarding Rules [public_ip]:port ..."
43
44
  option :interactive, type: :boolean
44
45
  def create(name)
45
- CloudstackCli::Helper.new(options[:config]).bootstrap_server(
46
- name,
47
- options[:zone],
48
- options[:template],
49
- options[:offering],
50
- options[:networks],
51
- options[:port_rules],
52
- options[:project]
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
- CloudstackCli::Helper.new(options[:config]).bootstrap_server_interactive()
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 "Crate stack #{stack["name"]}..."
7
- puts
7
+ say "Create stack #{stack["name"]}..."
8
+ threads = []
8
9
  stack["servers"].each do |server|
9
- server["name"].split(', ').each do |name|
10
- CloudstackCli::Helper.new(options[:config]).bootstrap_server(
11
- name,
12
- server["zone"] || stack['zone'],
13
- server["template"],
14
- server["offering"],
15
- server["networks"] ? server["networks"].split(', ') : nil,
16
- server["port_rules"] ? server["port_rules"].split(', ') : nil,
17
- stack["project"]
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
- class Helper
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 domains(name = nil)
25
- @cs.list_domains(name)
26
- end
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
- server = @cs.get_server(name)
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
- puts "Create server #{name}...".color(:yellow)
63
- server = @cs.create_server(
64
- name,
65
- offering,
66
- template,
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
- puts "Server #{server["name"]} has been created.".color(:green)
74
- puts
75
- puts "Make sure the server is running...".color(:yellow)
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
- puts "Server #{name} already exists".color(:green)
31
+ say "Server #{name} already exists.", :green
80
32
  end
81
33
 
82
- if pf_rules && pf_rules.size > 0
83
- puts
34
+ if pf_rules && pf_rules.size > 0
35
+ puts
84
36
  frontendip = nil
85
- project = @cs.get_project(project)
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
- ip_addr = @cs.get_public_ip_address(ip)
40
+ ip_addr = client.get_public_ip_address(ip)
90
41
  else
91
- ip_addr = frontendip ||= @cs.associate_ip_address(
92
- @cs.get_network(networks[0], project ? project["id"] : nil)["id"]
42
+ ip_addr = frontendip ||= client.associate_ip_address(
43
+ client.get_network(networks[0], project_id)["id"]
93
44
  )
94
45
  end
95
- port = pf_rule.split(":")[1]
46
+ port = pf_rule.split(":")[1]
96
47
  puts
97
- print "Create port forwarding rule #{ip}:#{port} ".color(:yellow)
98
- @cs.create_port_forwarding_rule(ip_addr["id"], port, 'TCP', port, server["id"])
99
- puts
100
- end
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
- ARGV.clear
133
- puts
134
- puts "We are going to deploy a new server and..."
135
- puts "- assign a public IP address"
136
- puts "- create a firewall rule for SSH and HTTP access"
137
- puts "- connect to the server and install the puppet client}"
138
- puts
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
- puts "Select a template:".background(:blue)
155
- print_options(templates)
156
- template = gets.chomp.to_i - 1
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
- puts "Select a availability zone:".background(:blue)
159
- print_options(zones)
160
- zone = gets.chomp.to_i - 1
161
-
162
- # FIXME: show only networks in selected zone
163
- puts "Select a network:".background(:blue)
164
- project_id = projects[project]['id'] rescue nil
165
- networks = @cs.list_networks(project_id)
166
- print_options(networks)
167
- network = gets.chomp.to_i - 1
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
- bootstrap_server(
170
- server_name,
171
- zones[zone]["name"],
172
- templates[template]["name"],
173
- server_offerings[service_offering]["name"],
174
- [networks[network]["name"]],
175
- projects[project]["name"]
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
@@ -1,3 +1,3 @@
1
1
  module CloudstackCli
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  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(filter, project_id = nil)
422
- filter ||= 'featured'
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(project_id = nil, account = nil)
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 account
492
- domain = list_accounts({name: account})
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
  ##
@@ -6,7 +6,7 @@ module CloudstackClient
6
6
  rescue Exception => e
7
7
  $stderr.puts "Can't find the config file #{config_file}."
8
8
  $stderr.puts "To create a new configuration file run \"cs setup\"."
9
- exit
9
+ exit 1
10
10
  end
11
11
  end
12
12
  end
@@ -1,5 +1,4 @@
1
1
  require 'yaml'
2
- require 'rainbow'
3
2
  require "thor"
4
3
 
5
4
  require "cloudstack-cli/version"
@@ -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": "M_ROOT",
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": "M_ROOT"
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.2
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-02 00:00:00.000000000 Z
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: 2.0.2
142
+ rubygems_version: 1.8.23
146
143
  signing_key:
147
- specification_version: 4
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
@@ -1,8 +0,0 @@
1
- class Publicip < CloudstackCli::Base
2
-
3
- desc "remove ID", "remove public IP address"
4
- def remove(id)
5
- puts "OK" if client.disassociate_ip_address(id)
6
- end
7
-
8
- end