cloudstack-cli 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile.lock +1 -3
  3. data/cloudstack-cli.gemspec +0 -1
  4. data/lib/cloudstack-cli/base.rb +3 -0
  5. data/lib/cloudstack-cli/cli.rb +5 -0
  6. data/lib/cloudstack-cli/commands/server.rb +8 -7
  7. data/lib/cloudstack-cli/helper.rb +6 -2
  8. data/lib/cloudstack-cli/version.rb +1 -1
  9. data/lib/cloudstack-client/client.rb +7 -980
  10. data/lib/cloudstack-client/commands/account.rb +22 -0
  11. data/lib/cloudstack-client/commands/capacity.rb +19 -0
  12. data/lib/cloudstack-client/commands/command_template +8 -0
  13. data/lib/cloudstack-client/commands/disk_offering.rb +49 -0
  14. data/lib/cloudstack-client/commands/domain.rb +22 -0
  15. data/lib/cloudstack-client/commands/ip_address.rb +77 -0
  16. data/lib/cloudstack-client/commands/iso.rb +60 -0
  17. data/lib/cloudstack-client/commands/load_balancer_rule.rb +61 -0
  18. data/lib/cloudstack-client/commands/network.rb +101 -0
  19. data/lib/cloudstack-client/commands/port_forwarding_rule.rb +50 -0
  20. data/lib/cloudstack-client/commands/project.rb +32 -0
  21. data/lib/cloudstack-client/commands/router.rb +74 -0
  22. data/lib/cloudstack-client/commands/server.rb +291 -0
  23. data/lib/cloudstack-client/commands/service_offering.rb +98 -0
  24. data/lib/cloudstack-client/commands/template.rb +60 -0
  25. data/lib/cloudstack-client/commands/volumes.rb +20 -0
  26. data/lib/cloudstack-client/commands/zone.rb +57 -0
  27. data/lib/cloudstack-client/helper.rb +2 -2
  28. data/lib/cloudstack-client/version.rb +3 -0
  29. data/lib/cloudstack_cli.rb +0 -8
  30. data/lib/cloudstack_client.rb +2 -2
  31. metadata +26 -34
  32. data/config/cloudstack.example.yml +0 -3
  33. data/lib/cloudstack-client/ssh_command.rb +0 -15
@@ -0,0 +1,291 @@
1
+ module CloudstackClient
2
+
3
+ module Server
4
+
5
+ ##
6
+ # Finds the server with the specified name.
7
+
8
+ def get_server(name, project_id=nil)
9
+ params = {
10
+ 'command' => 'listVirtualMachines',
11
+ 'name' => name
12
+ }
13
+ params['projectid'] = project_id if project_id
14
+ json = send_request(params)
15
+ machines = json['virtualmachine']
16
+
17
+ if !machines || machines.empty? then
18
+ return nil
19
+ end
20
+
21
+ machines.select {|m| m['name'] == name }.first
22
+ end
23
+
24
+ def get_server_state(id)
25
+ params = {
26
+ 'command' => 'listVirtualMachines',
27
+ 'id' => id
28
+ }
29
+ json = send_request(params)
30
+ machine_state = json['virtualmachine'][0]['state']
31
+
32
+ if !machine_state || machine_state.empty?
33
+ return nil
34
+ end
35
+
36
+ machine_state
37
+ end
38
+
39
+ def wait_for_server_state(id, state)
40
+ while get_server_state(id) != state
41
+ print '..'
42
+ sleep 5
43
+ end
44
+ state
45
+ end
46
+
47
+ ##
48
+ # Finds the public ip for a server
49
+
50
+ def get_server_public_ip(server, cached_rules=nil)
51
+ return nil unless server
52
+
53
+ # find the public ip
54
+ nic = get_server_default_nic(server) || {}
55
+ if nic['type'] == 'Virtual'
56
+ ssh_rule = get_ssh_port_forwarding_rule(server, cached_rules)
57
+ ssh_rule ? ssh_rule['ipaddress'] : nil
58
+ else
59
+ nic['ipaddress']
60
+ end
61
+ end
62
+
63
+ ##
64
+ # Returns the fully qualified domain name for a server.
65
+
66
+ def get_server_fqdn(server)
67
+ return nil unless server
68
+
69
+ nic = get_server_default_nic(server) || {}
70
+ networks = list_networks(project_id: server['projectid']) || {}
71
+
72
+ id = nic['networkid']
73
+ network = networks.select { |net|
74
+ net['id'] == id
75
+ }.first
76
+ return nil unless network
77
+
78
+ "#{server['name']}.#{network['networkdomain']}"
79
+ end
80
+
81
+ def get_server_default_nic(server)
82
+ server['nic'].each do |nic|
83
+ return nic if nic['isdefault']
84
+ end
85
+ end
86
+
87
+ ##
88
+ # Lists all the servers in your account.
89
+
90
+ def list_servers(options = {})
91
+ params = {
92
+ 'command' => 'listVirtualMachines',
93
+ 'listAll' => true
94
+ }
95
+ params['projectid'] = options[:project_id] if options[:project_id]
96
+ if options[:account]
97
+ if account = list_accounts({name: options[:account]}).first
98
+ params['domainid'] = account["domainid"]
99
+ params['account'] = options[:account]
100
+ end
101
+ end
102
+
103
+ json = send_request(params)
104
+ json['virtualmachine'] || []
105
+ end
106
+
107
+ ##
108
+ # Deploys a new server using the specified parameters.
109
+
110
+ def create_server(args = {})
111
+ if args[:name]
112
+ if get_server(args[:name])
113
+ puts "Error: Server '#{args[:name]}' already exists."
114
+ exit 1
115
+ end
116
+ end
117
+
118
+ service = get_service_offering(args[:offering])
119
+ if !service
120
+ puts "Error: Service offering '#{args[:offering]}' is invalid"
121
+ exit 1
122
+ end
123
+
124
+ if args[:template]
125
+ template = get_template(args[:template])
126
+ if !template
127
+ puts "Error: Template '#{args[:template]}' is invalid"
128
+ exit 1
129
+ end
130
+ end
131
+
132
+ if args[:disk_offering]
133
+ disk_offering = get_disk_offering(args[:disk_offering])
134
+ unless disk_offering
135
+ msg = "Disk offering '#{args[:disk_offering]}' is invalid"
136
+ puts "Error: #{msg}"
137
+ exit 1
138
+ end
139
+ end
140
+
141
+ if args[:iso]
142
+ iso = get_iso(args[:iso])
143
+ unless iso
144
+ puts "Error: Iso '#{args[:iso]}' is invalid"
145
+ exit 1
146
+ end
147
+ unless disk_offering
148
+ puts "Error: a disk offering is required when using iso"
149
+ exit 1
150
+ end
151
+ end
152
+
153
+ if !template && !iso
154
+ puts "Error: Iso or Template is required"
155
+ exit 1
156
+ end
157
+
158
+ zone = args[:zone] ? get_zone(args[:zone]) : get_default_zone
159
+ if !zone
160
+ msg = args[:zone] ? "Zone '#{args[:zone]}' is invalid" : "No default zone found"
161
+ puts "Error: #{msg}"
162
+ exit 1
163
+ end
164
+
165
+ if args[:project]
166
+ project = get_project(args[:project])
167
+ if !project
168
+ msg = "Project '#{args[:project]}' is invalid"
169
+ puts "Error: #{msg}"
170
+ exit 1
171
+ end
172
+ end
173
+
174
+ networks = []
175
+ if args[:networks]
176
+ args[:networks].each do |name|
177
+ network = project ? get_network(name, project['id']) : get_network(name)
178
+ if !network
179
+ puts "Error: Network '#{name}' not found"
180
+ exit 1
181
+ end
182
+ networks << network
183
+ end
184
+ end
185
+ if networks.empty?
186
+ networks << get_default_network
187
+ end
188
+ if networks.empty?
189
+ puts "No default network found"
190
+ exit 1
191
+ end
192
+ network_ids = networks.map { |network|
193
+ network['id']
194
+ }
195
+
196
+ params = {
197
+ 'command' => 'deployVirtualMachine',
198
+ 'serviceOfferingId' => service['id'],
199
+ 'templateId' => template ? template['id'] : iso['id'],
200
+ 'zoneId' => zone['id'],
201
+ 'networkids' => network_ids.join(',')
202
+ }
203
+ params['name'] = args[:name] if args[:name]
204
+ params['projectid'] = project['id'] if project
205
+ params['diskofferingid'] = disk_offering['id'] if disk_offering
206
+ params['hypervisor'] = (args[:hypervisor] || 'vmware') if iso
207
+ params['keypair'] = args[:keypair] if args[:keypair]
208
+ params['size'] = args[:disk_size] if args[:disk_size]
209
+
210
+ json = send_async_request(params)
211
+ json['virtualmachine']
212
+ end
213
+
214
+ ##
215
+ # Stops the server with the specified name.
216
+ #
217
+
218
+ def stop_server(name, forced=nil)
219
+ server = get_server(name)
220
+ if !server || !server['id']
221
+ puts "Error: Virtual machine '#{name}' does not exist"
222
+ exit 1
223
+ end
224
+
225
+ params = {
226
+ 'command' => 'stopVirtualMachine',
227
+ 'id' => server['id']
228
+ }
229
+ params['forced'] = true if forced
230
+
231
+ json = send_async_request(params)
232
+ json['virtualmachine']
233
+ end
234
+
235
+ ##
236
+ # Start the server with the specified name.
237
+ #
238
+
239
+ def start_server(name)
240
+ server = get_server(name)
241
+ if !server || !server['id']
242
+ puts "Error: Virtual machine '#{name}' does not exist"
243
+ exit 1
244
+ end
245
+
246
+ params = {
247
+ 'command' => 'startVirtualMachine',
248
+ 'id' => server['id']
249
+ }
250
+
251
+ json = send_async_request(params)
252
+ json['virtualmachine']
253
+ end
254
+
255
+ ##
256
+ # Reboot the server with the specified name.
257
+ #
258
+
259
+ def reboot_server(name)
260
+ server = get_server(name)
261
+ if !server || !server['id']
262
+ puts "Error: Virtual machine '#{name}' does not exist"
263
+ exit 1
264
+ end
265
+
266
+ params = {
267
+ 'command' => 'rebootVirtualMachine',
268
+ 'id' => server['id']
269
+ }
270
+
271
+ json = send_async_request(params)
272
+ json['virtualmachine']
273
+ end
274
+
275
+ ##
276
+ # Destroy the server with the specified name.
277
+ #
278
+
279
+ def destroy_server(id)
280
+ params = {
281
+ 'command' => 'destroyVirtualMachine',
282
+ 'id' => id
283
+ }
284
+
285
+ json = send_async_request(params)
286
+ json['virtualmachine']
287
+ end
288
+
289
+ end
290
+
291
+ end
@@ -0,0 +1,98 @@
1
+ module CloudstackClient
2
+
3
+ module ServiceOffering
4
+
5
+ ##
6
+ # Finds the service offering with the specified name.
7
+
8
+ def get_service_offering(name)
9
+
10
+ # TODO: use name parameter
11
+ # listServiceOfferings in CloudStack 2.2 doesn't seem to work
12
+ # when the name parameter is specified. When this is fixed,
13
+ # the name parameter should be added to the request.
14
+ params = {
15
+ 'command' => 'listServiceOfferings'
16
+ }
17
+ json = send_request(params)
18
+
19
+ services = json['serviceoffering']
20
+ return nil unless services
21
+
22
+ services.each { |s|
23
+ if s['name'] == name then
24
+ return s
25
+ end
26
+ }
27
+ nil
28
+ end
29
+
30
+ ##
31
+ # Lists all available service offerings.
32
+
33
+ def list_service_offerings(domain = nil)
34
+ params = {
35
+ 'command' => 'listServiceOfferings'
36
+ }
37
+
38
+ if domain
39
+ params['domainid'] = list_domains(domain).first["id"]
40
+ end
41
+
42
+ json = send_request(params)
43
+ json['serviceoffering'] || []
44
+ end
45
+
46
+ ##
47
+ # Create a service offering.
48
+
49
+ def create_offering(args)
50
+ params = {
51
+ 'command' => 'createServiceOffering',
52
+ 'name' => args[:name],
53
+ 'cpunumber' => args[:cpunumber],
54
+ 'cpuspeed' => args[:cpuspeed],
55
+ 'displaytext' => args[:displaytext],
56
+ 'memory' => args[:memory]
57
+ }
58
+
59
+ if args['domain']
60
+ params['domainid'] = list_domains(args['domain']).first["id"]
61
+ end
62
+
63
+ params['tags'] = args[:tags] if args[:tags]
64
+ params['offerha'] = 'true' if args[:ha]
65
+
66
+ json = send_request(params)
67
+ json['serviceoffering'].first
68
+ end
69
+
70
+ ##
71
+ # Delete a service offering.
72
+
73
+ def delete_offering(id)
74
+ params = {
75
+ 'command' => 'deleteServiceOffering',
76
+ 'id' => id
77
+ }
78
+
79
+ json = send_request(params)
80
+ json['success']
81
+ end
82
+
83
+ def update_offering(args)
84
+ params = {
85
+ 'command' => 'updateServiceOffering',
86
+ 'id' => args['id']
87
+ }
88
+ params['name'] = args['name'] if args['name']
89
+ params['displaytext'] = args['displaytext'] if args['displaytext']
90
+ params['sortkey'] = args['sortkey'] if args['sortkey']
91
+
92
+ json = send_request(params)
93
+ json['serviceoffering']
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,60 @@
1
+ module CloudstackClient
2
+
3
+ module Template
4
+
5
+ ##
6
+ # Finds the template with the specified name.
7
+
8
+ def get_template(name)
9
+
10
+ # TODO: use name parameter
11
+ # listTemplates in CloudStack 2.2 doesn't seem to work
12
+ # when the name parameter is specified. When this is fixed,
13
+ # the name parameter should be added to the request.
14
+ params = {
15
+ 'command' => 'listTemplates',
16
+ 'templateFilter' => 'executable'
17
+ }
18
+ json = send_request(params)
19
+
20
+ templates = json['template']
21
+ if !templates then
22
+ return nil
23
+ end
24
+
25
+ templates.each { |t|
26
+ if t['name'] == name then
27
+ return t
28
+ end
29
+ }
30
+
31
+ nil
32
+ end
33
+
34
+ ##
35
+ # Lists all templates that match the specified filter.
36
+ #
37
+ # Allowable filter values are:
38
+ #
39
+ # * featured - templates that are featured and are public
40
+ # * self - templates that have been registered/created by the owner
41
+ # * self-executable - templates that have been registered/created by the owner that can be used to deploy a new VM
42
+ # * executable - all templates that can be used to deploy a new VM
43
+ # * community - templates that are public
44
+
45
+ def list_templates(args = {})
46
+ filter = args[:filter] || 'featured'
47
+ params = {
48
+ 'command' => 'listTemplates',
49
+ 'templateFilter' => filter
50
+ }
51
+ params['projectid'] = args[:project_id] if args[:project_id]
52
+ params['zoneid'] = args[:zone_id] if args[:zone_id]
53
+
54
+ json = send_request(params)
55
+ json['template'] || []
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,20 @@
1
+ module CloudstackClient
2
+
3
+ module Volumes
4
+
5
+ ##
6
+ # Lists all volumes.
7
+
8
+ def list_volumes(project_id = nil)
9
+ params = {
10
+ 'command' => 'listVolumes',
11
+ 'listall' => true,
12
+ }
13
+ params['projectid'] = project_id if project_id
14
+ json = send_request(params)
15
+ json['network'] || []
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,57 @@
1
+ module CloudstackClient
2
+
3
+ module Zone
4
+
5
+ ##
6
+ # Finds the zone with the specified name.
7
+
8
+ def get_zone(name)
9
+ params = {
10
+ 'command' => 'listZones',
11
+ 'available' => 'true'
12
+ }
13
+ json = send_request(params)
14
+
15
+ networks = json['zone']
16
+ return nil unless networks
17
+
18
+ networks.each { |z|
19
+ if z['name'] == name then
20
+ return z
21
+ end
22
+ }
23
+
24
+ nil
25
+ end
26
+
27
+ ##
28
+ # Finds the default zone for your account.
29
+
30
+ def get_default_zone
31
+ params = {
32
+ 'command' => 'listZones',
33
+ 'available' => 'true'
34
+ }
35
+ json = send_request(params)
36
+
37
+ zones = json['zone']
38
+ return nil unless zones
39
+
40
+ zones.first
41
+ end
42
+
43
+ ##
44
+ # Lists all available zones.
45
+
46
+ def list_zones
47
+ params = {
48
+ 'command' => 'listZones',
49
+ 'available' => 'true'
50
+ }
51
+ json = send_request(params)
52
+ json['zone'] || []
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -1,5 +1,5 @@
1
1
  module CloudstackClient
2
- class ConnectionHelper
2
+ module ConnectionHelper
3
3
  def self.load_configuration(config_file)
4
4
  begin
5
5
  return YAML::load(IO.read(config_file))
@@ -10,4 +10,4 @@ module CloudstackClient
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -0,0 +1,3 @@
1
+ module CloudstackClient
2
+ VERSION = "0.2.0"
3
+ end
@@ -1,12 +1,4 @@
1
- require 'yaml'
2
- require "thor"
3
-
4
1
  require "cloudstack-cli/version"
5
2
  require "cloudstack-cli/helper"
6
3
  require "cloudstack-cli/base"
7
-
8
- # require subcommands
9
- Dir[File.dirname(__FILE__) + '/../lib/cloudstack-cli/commands/*.rb'].each do |file|
10
- require file
11
- end
12
4
  require "cloudstack-cli/cli"
@@ -1,3 +1,3 @@
1
+ require "cloudstack-client/version"
1
2
  require "cloudstack-client/client"
2
- require "cloudstack-client/helper"
3
- require "cloudstack-client/ssh_command"
3
+ require "cloudstack-client/helper"
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudstack-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Nik Wolfgramm
@@ -14,23 +13,20 @@ dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rdoc
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: thor
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,27 +48,10 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
61
54
  version: 0.18.1
62
- - !ruby/object:Gem::Dependency
63
- name: net-ssh
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
66
- requirements:
67
- - - ~>
68
- - !ruby/object:Gem::Version
69
- version: 2.6.7
70
- type: :runtime
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
- requirements:
75
- - - ~>
76
- - !ruby/object:Gem::Version
77
- version: 2.6.7
78
55
  description: cloudstack-cli is a CloudStack API client written in Ruby.
79
56
  email:
80
57
  - nik.wolfgramm@gmail.com
@@ -90,7 +67,6 @@ files:
90
67
  - README.md
91
68
  - bin/cs
92
69
  - cloudstack-cli.gemspec
93
- - config/cloudstack.example.yml
94
70
  - lib/cloudstack-cli/base.rb
95
71
  - lib/cloudstack-cli/cli.rb
96
72
  - lib/cloudstack-cli/commands/account.rb
@@ -114,13 +90,31 @@ files:
114
90
  - lib/cloudstack-cli/helper.rb
115
91
  - lib/cloudstack-cli/version.rb
116
92
  - lib/cloudstack-client/client.rb
93
+ - lib/cloudstack-client/commands/account.rb
94
+ - lib/cloudstack-client/commands/capacity.rb
95
+ - lib/cloudstack-client/commands/command_template
96
+ - lib/cloudstack-client/commands/disk_offering.rb
97
+ - lib/cloudstack-client/commands/domain.rb
98
+ - lib/cloudstack-client/commands/ip_address.rb
99
+ - lib/cloudstack-client/commands/iso.rb
100
+ - lib/cloudstack-client/commands/load_balancer_rule.rb
101
+ - lib/cloudstack-client/commands/network.rb
102
+ - lib/cloudstack-client/commands/port_forwarding_rule.rb
103
+ - lib/cloudstack-client/commands/project.rb
104
+ - lib/cloudstack-client/commands/router.rb
105
+ - lib/cloudstack-client/commands/server.rb
106
+ - lib/cloudstack-client/commands/service_offering.rb
107
+ - lib/cloudstack-client/commands/template.rb
108
+ - lib/cloudstack-client/commands/volumes.rb
109
+ - lib/cloudstack-client/commands/zone.rb
117
110
  - lib/cloudstack-client/helper.rb
118
- - lib/cloudstack-client/ssh_command.rb
111
+ - lib/cloudstack-client/version.rb
119
112
  - lib/cloudstack_cli.rb
120
113
  - lib/cloudstack_client.rb
121
114
  - test/stack_example.json
122
115
  homepage: https://bitbucket.org/swisstxt/cloudstack-cli
123
116
  licenses: []
117
+ metadata: {}
124
118
  post_install_message:
125
119
  rdoc_options:
126
120
  - --line-numbers
@@ -128,22 +122,20 @@ rdoc_options:
128
122
  require_paths:
129
123
  - lib
130
124
  required_ruby_version: !ruby/object:Gem::Requirement
131
- none: false
132
125
  requirements:
133
- - - ! '>='
126
+ - - '>='
134
127
  - !ruby/object:Gem::Version
135
128
  version: 1.9.3
136
129
  required_rubygems_version: !ruby/object:Gem::Requirement
137
- none: false
138
130
  requirements:
139
- - - ! '>='
131
+ - - '>='
140
132
  - !ruby/object:Gem::Version
141
133
  version: '0'
142
134
  requirements: []
143
135
  rubyforge_project:
144
- rubygems_version: 1.8.23
136
+ rubygems_version: 2.0.2
145
137
  signing_key:
146
- specification_version: 3
138
+ specification_version: 4
147
139
  summary: cloudstack-cli CloudStack API client
148
140
  test_files:
149
141
  - test/stack_example.json