cloudstack-cli 0.1.7 → 0.2.0

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.
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