openstack 1.1.2 → 2.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG +58 -0
- data/README.md +19 -0
- data/VERSION +1 -0
- data/lib/openstack.rb +5 -19
- data/lib/openstack/compute/connection.rb +74 -31
- data/lib/openstack/compute/flavor.rb +18 -30
- data/lib/openstack/compute/server.rb +98 -0
- data/lib/openstack/connection.rb +45 -8
- data/lib/openstack/core_ext/to_query.rb +84 -0
- data/lib/openstack/identity/connection.rb +69 -0
- data/lib/openstack/identity/tenant.rb +17 -0
- data/lib/openstack/identity/user.rb +19 -0
- data/lib/openstack/network/network.rb +21 -22
- data/lib/openstack/network/router.rb +3 -5
- data/lib/openstack/swift/connection.rb +10 -4
- data/lib/openstack/volume/connection.rb +25 -0
- data/test/runner.rb +10 -0
- data/test/test_helper.rb +6 -9
- metadata +33 -35
- data/README.rdoc +0 -462
- data/lib/openstack/version.rb +0 -3
- data/test/authentication_test.rb +0 -120
- data/test/connection_test.rb +0 -39
- data/test/exception_test.rb +0 -49
- data/test/metadata_test.rb +0 -210
- data/test/servers_test.rb +0 -210
data/lib/openstack/connection.rb
CHANGED
@@ -22,11 +22,14 @@ class Connection
|
|
22
22
|
attr_reader :service_type
|
23
23
|
attr_reader :proxy_host
|
24
24
|
attr_reader :proxy_port
|
25
|
+
attr_reader :ca_cert
|
26
|
+
attr_reader :ssl_version
|
25
27
|
attr_reader :region
|
26
28
|
attr_reader :regions_list #e.g. os.connection.regions_list == {"region-a.geo-1" => [ {:service=>"object-store", :versionId=>"1.0"}, {:service=>"identity", :versionId=>"2.0"}], "region-b.geo-1"=>[{:service=>"identity", :versionId=>"2.0"}] }
|
27
29
|
|
28
30
|
attr_reader :http
|
29
31
|
attr_reader :is_debug
|
32
|
+
attr_reader :endpoint_type
|
30
33
|
|
31
34
|
# Creates and returns a new Connection object, depending on the service_type
|
32
35
|
# passed in the options:
|
@@ -52,6 +55,9 @@ class Connection
|
|
52
55
|
# :retry_auth - Whether to retry if your auth token expires (defaults to true)
|
53
56
|
# :proxy_host - If you need to connect through a proxy, supply the hostname here
|
54
57
|
# :proxy_port - If you need to connect through a proxy, supply the port here
|
58
|
+
# :ca_cert - path to a CA chain in PEM format
|
59
|
+
# :ssl_version - explicitly set an version (:SSLv3 etc, see OpenSSL::SSL::SSLContext::METHODS)
|
60
|
+
# :is_debug - Only for development purpose for debug output
|
55
61
|
#
|
56
62
|
# The options hash is used to create a new OpenStack::Connection object
|
57
63
|
# (private constructor) and this is passed to the constructor of OpenStack::Compute::Connection
|
@@ -72,6 +78,8 @@ class Connection
|
|
72
78
|
OpenStack::Image::Connection.new(connection)
|
73
79
|
when "network"
|
74
80
|
OpenStack::Network::Connection.new(connection)
|
81
|
+
when "identity"
|
82
|
+
OpenStack::Identity::Connection.new(connection)
|
75
83
|
else
|
76
84
|
raise Exception::InvalidArgument, "Invalid :service_type parameter: #{@service_type}"
|
77
85
|
end
|
@@ -105,9 +113,12 @@ class Connection
|
|
105
113
|
@retry_auth = options[:retry_auth]
|
106
114
|
@proxy_host = options[:proxy_host]
|
107
115
|
@proxy_port = options[:proxy_port]
|
116
|
+
@ca_cert = options[:ca_cert]
|
117
|
+
@ssl_version = options[:ssl_version]
|
108
118
|
@authok = false
|
109
119
|
@http = {}
|
110
120
|
@quantum_version = 'v2.0' if @service_type == 'network'
|
121
|
+
@endpoint_type = options[:endpoint_type] || "publicURL"
|
111
122
|
end
|
112
123
|
|
113
124
|
#specialised from of csreq for PUT object... uses body_stream if possible
|
@@ -155,7 +166,6 @@ class Connection
|
|
155
166
|
|
156
167
|
# This method actually makes the HTTP REST calls out to the server
|
157
168
|
def csreq(method,server,path,port,scheme,headers = {},data = nil,attempts = 0, &block) # :nodoc:
|
158
|
-
|
159
169
|
tries = @retries
|
160
170
|
time = 3
|
161
171
|
|
@@ -173,7 +183,7 @@ class Connection
|
|
173
183
|
response = @http[server].request(request)
|
174
184
|
end
|
175
185
|
if @is_debug
|
176
|
-
puts "REQUEST: #{
|
186
|
+
puts "REQUEST: #{auth_method} => #{path}"
|
177
187
|
puts data if data
|
178
188
|
puts "RESPONSE: #{response.body}"
|
179
189
|
puts '----------------------------------------'
|
@@ -232,6 +242,15 @@ class Connection
|
|
232
242
|
if scheme == "https"
|
233
243
|
@http[server].use_ssl = true
|
234
244
|
@http[server].verify_mode = OpenSSL::SSL::VERIFY_NONE
|
245
|
+
|
246
|
+
# use the ca_cert if were given one, and make sure we verify!
|
247
|
+
if ! @ca_cert.nil?
|
248
|
+
@http[server].ca_file = @ca_cert
|
249
|
+
@http[server].verify_mode = OpenSSL::SSL::VERIFY_PEER
|
250
|
+
end
|
251
|
+
|
252
|
+
# explicitly set the SSL version to use
|
253
|
+
@http[server].ssl_version= @ssl_version if ! @ssl_version.nil?
|
235
254
|
end
|
236
255
|
@http[server].start
|
237
256
|
rescue
|
@@ -280,6 +299,15 @@ class AuthV20
|
|
280
299
|
if connection.auth_scheme == "https"
|
281
300
|
server.use_ssl = true
|
282
301
|
server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
302
|
+
|
303
|
+
# use the ca_cert if were given one, and make sure we verify!
|
304
|
+
if !connection.ca_cert.nil?
|
305
|
+
server.ca_file = connection.ca_cert
|
306
|
+
server.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
307
|
+
end
|
308
|
+
|
309
|
+
# explicitly set the SSL version to use
|
310
|
+
server.ssl_version = connection.ssl_version if !connection.ssl_version.nil?
|
283
311
|
end
|
284
312
|
server.start
|
285
313
|
rescue
|
@@ -324,23 +352,23 @@ class AuthV20
|
|
324
352
|
if connection.region
|
325
353
|
endpoints.each do |ep|
|
326
354
|
if ep["region"] and ep["region"].upcase == connection.region.upcase
|
327
|
-
@uri = URI.parse(ep[
|
355
|
+
@uri = URI.parse(ep[connection.endpoint_type])
|
328
356
|
end
|
329
357
|
end
|
330
358
|
else
|
331
|
-
@uri = URI.parse(endpoints[0][
|
359
|
+
@uri = URI.parse(endpoints[0][connection.endpoint_type])
|
332
360
|
end
|
333
361
|
if @uri == ""
|
334
362
|
raise OpenStack::Exception::Authentication, "No API endpoint for region #{connection.region}"
|
335
363
|
else
|
336
364
|
if @version #already got one version of endpoints
|
337
|
-
current_version = get_version_from_response(service)
|
365
|
+
current_version = get_version_from_response(service,connection.endpoint_type)
|
338
366
|
if @version.to_f > current_version.to_f
|
339
367
|
next
|
340
368
|
end
|
341
369
|
end
|
342
370
|
#grab version to check next time round for multi-version deployments
|
343
|
-
@version = get_version_from_response(service)
|
371
|
+
@version = get_version_from_response(service,connection.endpoint_type)
|
344
372
|
connection.service_host = @uri.host
|
345
373
|
connection.service_path = @uri.path
|
346
374
|
connection.service_port = @uri.port
|
@@ -356,8 +384,8 @@ class AuthV20
|
|
356
384
|
server.finish if server.started?
|
357
385
|
end
|
358
386
|
|
359
|
-
def get_version_from_response(service)
|
360
|
-
service["endpoints"].first["versionId"] || parse_version_from_endpoint(service["endpoints"].first[
|
387
|
+
def get_version_from_response(service,endpoint_type)
|
388
|
+
service["endpoints"].first["versionId"] || parse_version_from_endpoint(service["endpoints"].first[endpoint_type])
|
361
389
|
end
|
362
390
|
|
363
391
|
#IN --> https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/46871569847393
|
@@ -381,6 +409,15 @@ class AuthV10
|
|
381
409
|
if connection.auth_scheme == "https"
|
382
410
|
server.use_ssl = true
|
383
411
|
server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
412
|
+
|
413
|
+
# use the ca_cert if were given one, and make sure to verify!
|
414
|
+
if !connection.ca_cert.nil?
|
415
|
+
server.ca_file = connection.ca_cert
|
416
|
+
server.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
417
|
+
end
|
418
|
+
|
419
|
+
# explicitly set the SSL version to use
|
420
|
+
server.ssl_version = connection.ssl_version if !connection.ssl_version.nil?
|
384
421
|
end
|
385
422
|
server.start
|
386
423
|
rescue
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Alias of <tt>to_s</tt>.
|
5
|
+
def to_param
|
6
|
+
to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
# Converts an object into a string suitable for use as a URL query string,
|
10
|
+
# using the given <tt>key</tt> as the param name.
|
11
|
+
def to_query(key)
|
12
|
+
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class NilClass
|
17
|
+
# Returns +self+.
|
18
|
+
def to_param
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class TrueClass
|
24
|
+
# Returns +self+.
|
25
|
+
def to_param
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class FalseClass
|
31
|
+
# Returns +self+.
|
32
|
+
def to_param
|
33
|
+
self
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Array
|
38
|
+
# Calls <tt>to_param</tt> on all its elements and joins the result with
|
39
|
+
# slashes. This is used by <tt>url_for</tt> in Action Pack.
|
40
|
+
def to_param
|
41
|
+
collect(&:to_param).join '/'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Converts an array into a string suitable for use as a URL query string,
|
45
|
+
# using the given +key+ as the param name.
|
46
|
+
#
|
47
|
+
# ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
|
48
|
+
def to_query(key)
|
49
|
+
prefix = "#{key}[]"
|
50
|
+
|
51
|
+
if empty?
|
52
|
+
nil.to_query(prefix)
|
53
|
+
else
|
54
|
+
collect { |value| value.to_query(prefix) }.join '&'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Hash
|
60
|
+
# Returns a string representation of the receiver suitable for use as a URL
|
61
|
+
# query string:
|
62
|
+
#
|
63
|
+
# {name: 'David', nationality: 'Danish'}.to_query
|
64
|
+
# # => "name=David&nationality=Danish"
|
65
|
+
#
|
66
|
+
# An optional namespace can be passed to enclose key names:
|
67
|
+
#
|
68
|
+
# {name: 'David', nationality: 'Danish'}.to_query('user')
|
69
|
+
# # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
|
70
|
+
#
|
71
|
+
# The string pairs "key=value" that conform the query string
|
72
|
+
# are sorted lexicographically in ascending order.
|
73
|
+
#
|
74
|
+
# This method is also aliased as +to_param+.
|
75
|
+
def to_query(namespace = nil)
|
76
|
+
collect do |key, value|
|
77
|
+
unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
|
78
|
+
value.to_query(namespace ? "#{namespace}[#{key}]" : key)
|
79
|
+
end
|
80
|
+
end.compact.sort! * '&'
|
81
|
+
end
|
82
|
+
|
83
|
+
alias_method :to_param, :to_query
|
84
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module OpenStack
|
2
|
+
module Identity
|
3
|
+
class Connection
|
4
|
+
attr_accessor :connection
|
5
|
+
|
6
|
+
def initialize(connection)
|
7
|
+
@connection = connection
|
8
|
+
OpenStack::Authentication.init(@connection)
|
9
|
+
end
|
10
|
+
|
11
|
+
def list_tenants
|
12
|
+
response = @connection.req('GET', '/tenants')
|
13
|
+
tenants_hash = JSON.parse(response.body)['tenants']
|
14
|
+
tenants_hash.map { |res| OpenStack::Identity::Tenant.new(res) }
|
15
|
+
end
|
16
|
+
alias_method :tenants, :list_tenants
|
17
|
+
|
18
|
+
# create_tenant(name: 'tenant1', description: 'description', enabled: true)
|
19
|
+
#
|
20
|
+
def create_tenant(options)
|
21
|
+
req_body = JSON.generate('tenant' => options)
|
22
|
+
response = @connection.req('POST', '/tenants', data: req_body)
|
23
|
+
OpenStack::Identity::Tenant.new(JSON.parse(response.body)['tenant'])
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_tenant_by_name(name)
|
27
|
+
response = @connection.req('GET', "/tenants?name=#{name}")
|
28
|
+
OpenStack::Identity::Tenant.new(JSON.parse(response.body)['tenant'])
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete_tenant(id)
|
32
|
+
@connection.req('DELETE', "/tenants/#{id}")
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_users
|
37
|
+
response = @connection.req('GET', '/users')
|
38
|
+
users_hash = JSON.parse(response.body)['users']
|
39
|
+
users_hash.map { |res| OpenStack::Identity::User.new(res) }
|
40
|
+
end
|
41
|
+
alias_method :users, :list_users
|
42
|
+
|
43
|
+
# create_user(name: 'user1', password: 'password1', email: 'email@mail.ru')
|
44
|
+
#
|
45
|
+
def create_user(options)
|
46
|
+
req_body = JSON.generate('user' => options)
|
47
|
+
response = @connection.req('POST', '/users', data: req_body)
|
48
|
+
OpenStack::Identity::User.new(JSON.parse(response.body)['user'])
|
49
|
+
end
|
50
|
+
|
51
|
+
def delete_user(id)
|
52
|
+
@connection.req('DELETE', "/users/#{id}")
|
53
|
+
true
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_user_to_tenant(options)
|
57
|
+
req_body = JSON.generate('role' => { 'tenantId' => options[:tenant_id], 'roleId' => options[:role_id] })
|
58
|
+
@connection.req('POST', "/users/#{options[:user_id]}/roleRefs", data: req_body)
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def list_roles
|
63
|
+
response = @connection.req('GET', '/OS-KSADM/roles')
|
64
|
+
OpenStack.symbolize_keys(JSON.parse(response.body)['roles'])
|
65
|
+
end
|
66
|
+
alias_method :roles, :list_roles
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module OpenStack
|
2
|
+
module Identity
|
3
|
+
class Tenant
|
4
|
+
attr_reader :id
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :description
|
7
|
+
attr_reader :enabled
|
8
|
+
|
9
|
+
def initialize(tenant_info = {})
|
10
|
+
@id = tenant_info['id']
|
11
|
+
@name = tenant_info['name']
|
12
|
+
@description = tenant_info['description']
|
13
|
+
@enabled = tenant_info['enabled']
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module OpenStack
|
2
|
+
module Identity
|
3
|
+
class User
|
4
|
+
attr_reader :id
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :tenant_id
|
7
|
+
attr_reader :enabled
|
8
|
+
attr_reader :email
|
9
|
+
|
10
|
+
def initialize(tenant_info = {})
|
11
|
+
@id = tenant_info['id']
|
12
|
+
@name = tenant_info['name']
|
13
|
+
@tenant_id = tenant_info['tenant_id']
|
14
|
+
@email = tenant_info['email']
|
15
|
+
@enabled = tenant_info['enabled']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,26 +1,25 @@
|
|
1
1
|
module OpenStack
|
2
|
-
module Network
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(net_info={})
|
14
|
-
@id = net_info["id"]
|
15
|
-
@name = net_info["name"]
|
16
|
-
@admin_state_up = net_info["admin_state_up"]
|
17
|
-
@status = net_info["status"]
|
18
|
-
@subnets = net_info["subnets"]
|
19
|
-
@shared = net_info["shared"]
|
20
|
-
@tenant_id = net_info["tenant_id"]
|
21
|
-
end
|
2
|
+
module Network
|
3
|
+
class Network
|
4
|
+
attr_reader :id
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :admin_state_up
|
7
|
+
attr_reader :status
|
8
|
+
attr_reader :subnets
|
9
|
+
attr_reader :shared
|
10
|
+
attr_reader :external
|
11
|
+
attr_reader :tenant_id
|
22
12
|
|
13
|
+
def initialize(net_info = {})
|
14
|
+
@id = net_info['id']
|
15
|
+
@name = net_info['name']
|
16
|
+
@admin_state_up = net_info['admin_state_up']
|
17
|
+
@status = net_info['status']
|
18
|
+
@subnets = net_info['subnets']
|
19
|
+
@shared = net_info['shared']
|
20
|
+
@external = net_info['router:external']
|
21
|
+
@tenant_id = net_info['tenant_id']
|
22
|
+
end
|
23
|
+
end
|
23
24
|
end
|
24
25
|
end
|
25
|
-
end
|
26
|
-
|
@@ -7,20 +7,18 @@ module Network
|
|
7
7
|
attr_reader :admin_state_up
|
8
8
|
attr_reader :status
|
9
9
|
attr_reader :external_gateway_info
|
10
|
-
attr_reader :
|
10
|
+
attr_reader :tenant_id
|
11
11
|
attr_reader :enable_snat
|
12
12
|
attr_reader :admin_state_up
|
13
13
|
|
14
14
|
def initialize(router_info={})
|
15
15
|
@name = router_info['name']
|
16
16
|
@status = router_info['status']
|
17
|
-
@
|
17
|
+
@external_gateway_info = router_info['external_gateway_info']
|
18
18
|
@admin_state_up = router_info['admin_state_up']
|
19
|
-
@
|
19
|
+
@tenant_id = router_info['tenant_id']
|
20
20
|
@id = router_info['id']
|
21
21
|
@enable_snat = router_info['enable_snat']
|
22
|
-
# @admin_state_up = router_info['external_gateway_info']['admin_state_up']
|
23
|
-
# @network_id = router_info['external_gateway_info']['network_id']
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
@@ -73,7 +73,7 @@ module Swift
|
|
73
73
|
# cf.containers(2,'cftest')
|
74
74
|
# => ["test", "video"]
|
75
75
|
def containers(limit = nil, marker = nil)
|
76
|
-
path = OpenStack.get_query_params({:limit=>limit, :marker=>marker}, [:limit, :marker], "")
|
76
|
+
path = OpenStack.get_query_params({:limit=>limit, :marker=>marker, :format=>'json'}, [:limit, :marker, :format], "")
|
77
77
|
response = @connection.req("GET", URI.encode(path))
|
78
78
|
OpenStack.symbolize_keys(JSON.parse(response.body)).inject([]){|res,cur| res << cur[:name]; res }
|
79
79
|
end
|
@@ -89,7 +89,7 @@ module Swift
|
|
89
89
|
# => { "container1" => { :bytes => "36543", :count => "146" },
|
90
90
|
# "container2" => { :bytes => "105943", :count => "25" } }
|
91
91
|
def containers_detail(limit = nil, marker = nil)
|
92
|
-
path = OpenStack.get_query_params({:limit=>limit, :marker=>marker}, [:limit, :marker], "")
|
92
|
+
path = OpenStack.get_query_params({:limit=>limit, :marker=>marker, :format=>'json'}, [:limit, :marker, :format], "")
|
93
93
|
response = @connection.req("GET", URI.encode(path))
|
94
94
|
OpenStack.symbolize_keys(JSON.parse(response.body)).inject({}){|res,current| res.merge!({current[:name]=>{:bytes=>current[:bytes].to_s,:count=>current[:count].to_s}}) ; res }
|
95
95
|
end
|
@@ -168,8 +168,14 @@ module Swift
|
|
168
168
|
@file = data
|
169
169
|
end
|
170
170
|
|
171
|
-
|
172
|
-
|
171
|
+
#for ruby 2.x
|
172
|
+
def read(length, buffer=nil)
|
173
|
+
if buffer.nil?
|
174
|
+
chunk = @file.read(length)
|
175
|
+
else
|
176
|
+
chunk = @file.read(length, buffer)
|
177
|
+
end
|
178
|
+
chunk
|
173
179
|
end
|
174
180
|
|
175
181
|
def eof!
|
@@ -88,6 +88,31 @@ module Volume
|
|
88
88
|
true
|
89
89
|
end
|
90
90
|
|
91
|
+
# [ {:extra_specs=>{:volume_backend_name=>"volumes-standard"}, :name=>"slow", :id=>"b3a104b6-fe70-4450-8681-e911a153f41f"},
|
92
|
+
# {:extra_specs=>{:volume_backend_name=>"volumes-speed"}, :name=>"fast", :id=>"0e278952-9baa-4aa8-88a7-fe8387f1d86c"} ]
|
93
|
+
def list_volume_types
|
94
|
+
response = @connection.req('GET', '/types')
|
95
|
+
OpenStack.symbolize_keys(JSON.parse(response.body)['volume_types'])
|
96
|
+
end
|
97
|
+
alias :types :list_volume_types
|
98
|
+
|
99
|
+
# get_quotas(1)
|
100
|
+
# => { "volumes_slow"=>-1, "snapshots_slow"=>-1, "gigabytes_slow"=>-1,
|
101
|
+
# "volumes_fast"=>-1, "snapshots_fast"=>-1, "gigabytes_fast"=>-1,
|
102
|
+
# "volumes"=>10, "snapshots"=>10, "gigabytes"=>1001, "id"=>"1"}
|
103
|
+
def get_quotas(tenant_id)
|
104
|
+
response = @connection.req('GET', "/os-quota-sets/#{tenant_id}")
|
105
|
+
JSON.parse(response.body)['quota_set']
|
106
|
+
end
|
107
|
+
|
108
|
+
# quota_set = { gigabytes: 500, gigabytes_slow: 200, gigabytes_fast: 300 }
|
109
|
+
# cinder.update_quotas(1, quota_set)
|
110
|
+
def update_quotas(tenant_id, quota_set)
|
111
|
+
req_body = JSON.generate({'quota_set' => quota_set})
|
112
|
+
response = @connection.req('PUT', "/os-quota-sets/#{tenant_id}", data: req_body)
|
113
|
+
JSON.parse(response.body)['quota_set']
|
114
|
+
end
|
115
|
+
|
91
116
|
private
|
92
117
|
|
93
118
|
#fudge... not clear if volumes support is available as 'native' volume API or
|