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.
@@ -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: #{method} => #{path}"
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["publicURL"])
355
+ @uri = URI.parse(ep[connection.endpoint_type])
328
356
  end
329
357
  end
330
358
  else
331
- @uri = URI.parse(endpoints[0]["publicURL"])
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["publicURL"])
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
- class Network
4
-
5
- attr_reader :id
6
- attr_reader :name
7
- attr_reader :admin_state_up
8
- attr_reader :status
9
- attr_reader :subnets
10
- attr_reader :shared
11
- attr_reader :tenant_id
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 :tenant_ip
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
- @external_geteway_info = router_info['external_gateway_info']
17
+ @external_gateway_info = router_info['external_gateway_info']
18
18
  @admin_state_up = router_info['admin_state_up']
19
- @tenant_ip = router_info['tenant_ip']
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
- def read(foo)
172
- @file.read(@size)
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