fog-openstack 0.1.19 → 0.1.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/docs/orchestration.md +23 -0
  3. data/examples/event/basics.rb +22 -0
  4. data/gemfiles/Gemfile-1.9 +1 -0
  5. data/lib/fog/compute/openstack.rb +28 -2
  6. data/lib/fog/compute/openstack/models/os_interface.rb +15 -0
  7. data/lib/fog/compute/openstack/models/os_interfaces.rb +28 -0
  8. data/lib/fog/compute/openstack/models/server.rb +5 -0
  9. data/lib/fog/compute/openstack/requests/create_os_interface.rb +42 -0
  10. data/lib/fog/compute/openstack/requests/delete_key_pair.rb +1 -1
  11. data/lib/fog/compute/openstack/requests/delete_os_interface.rb +24 -0
  12. data/lib/fog/compute/openstack/requests/get_hypervisor.rb +64 -0
  13. data/lib/fog/compute/openstack/requests/get_key_pair.rb +1 -1
  14. data/lib/fog/compute/openstack/requests/get_os_interface.rb +24 -0
  15. data/lib/fog/compute/openstack/requests/list_hypervisor_servers.rb +42 -0
  16. data/lib/fog/compute/openstack/requests/list_hypervisors.rb +27 -0
  17. data/lib/fog/compute/openstack/requests/list_hypervisors_detail.rb +71 -0
  18. data/lib/fog/compute/openstack/requests/list_os_interfaces.rb +24 -0
  19. data/lib/fog/dns/openstack/v2/requests/create_zone.rb +1 -1
  20. data/lib/fog/event/openstack.rb +120 -0
  21. data/lib/fog/event/openstack/models/event.rb +16 -0
  22. data/lib/fog/event/openstack/models/events.rb +23 -0
  23. data/lib/fog/event/openstack/requests/get_event.rb +27 -0
  24. data/lib/fog/event/openstack/requests/list_events.rb +42 -0
  25. data/lib/fog/identity/openstack/v3/models/domains.rb +23 -11
  26. data/lib/fog/key_manager/openstack.rb +1 -1
  27. data/lib/fog/metering/openstack.rb +1 -0
  28. data/lib/fog/network/openstack.rb +10 -0
  29. data/lib/fog/network/openstack/models/subnet_pool.rb +47 -0
  30. data/lib/fog/network/openstack/models/subnet_pools.rb +33 -0
  31. data/lib/fog/network/openstack/requests/create_subnet_pool.rb +56 -0
  32. data/lib/fog/network/openstack/requests/delete_subnet_pool.rb +28 -0
  33. data/lib/fog/network/openstack/requests/get_subnet_pool.rb +29 -0
  34. data/lib/fog/network/openstack/requests/list_subnet_pools.rb +25 -0
  35. data/lib/fog/network/openstack/requests/update_subnet_pool.rb +46 -0
  36. data/lib/fog/openstack.rb +90 -68
  37. data/lib/fog/openstack/core.rb +53 -7
  38. data/lib/fog/openstack/version.rb +1 -1
  39. data/lib/fog/shared_file_system/openstack.rb +51 -8
  40. data/lib/fog/shared_file_system/openstack/models/share.rb +28 -0
  41. data/lib/fog/shared_file_system/openstack/models/share_access_rule.rb +35 -0
  42. data/lib/fog/shared_file_system/openstack/models/share_access_rules.rb +30 -0
  43. data/lib/fog/shared_file_system/openstack/requests/extend_share.rb +24 -0
  44. data/lib/fog/shared_file_system/openstack/requests/get_limits.rb +45 -0
  45. data/lib/fog/shared_file_system/openstack/requests/get_quota.rb +26 -0
  46. data/lib/fog/shared_file_system/openstack/requests/grant_share_access.rb +34 -0
  47. data/lib/fog/shared_file_system/openstack/requests/list_share_access_rules.rb +29 -0
  48. data/lib/fog/shared_file_system/openstack/requests/revoke_share_access.rb +24 -0
  49. data/lib/fog/shared_file_system/openstack/requests/share_action.rb +16 -0
  50. data/lib/fog/shared_file_system/openstack/requests/shrink_share.rb +24 -0
  51. data/lib/fog/shared_file_system/openstack/requests/update_quota.rb +30 -0
  52. metadata +36 -2
@@ -0,0 +1,56 @@
1
+ module Fog
2
+ module Network
3
+ class OpenStack
4
+ class Real
5
+ def create_subnet_pool(name, prefixes, options = {})
6
+ data = {
7
+ 'subnetpool' => {
8
+ 'name' => name,
9
+ 'prefixes' => prefixes
10
+ }
11
+ }
12
+
13
+ vanilla_options = [:description, :address_scope_id, :shared,
14
+ :min_prefixlen, :max_prefixlen, :default_prefixlen]
15
+ vanilla_options.select { |o| options.key?(o) }.each do |key|
16
+ data['subnetpool'][key] = options[key]
17
+ end
18
+
19
+ request(
20
+ :body => Fog::JSON.encode(data),
21
+ :expects => [201],
22
+ :method => 'POST',
23
+ :path => 'subnetpools'
24
+ )
25
+ end
26
+ end
27
+
28
+ class Mock
29
+ def create_subnet_pool(name, prefixes, options = {})
30
+ response = Excon::Response.new
31
+ response.status = 201
32
+ data = {
33
+ 'id' => Fog::Mock.random_numbers(6).to_s,
34
+ 'name' => name,
35
+ 'prefixes' => prefixes,
36
+ 'description' => options[:description],
37
+ 'min_prefixlen' => options[:min_prefixlen] || 64,
38
+ 'max_prefixlen' => options[:max_prefixlen] || 64,
39
+ 'default_prefixlen' => options[:default_prefixlen] || 64,
40
+ 'address_scope_id' => options[:address_scope_id],
41
+ 'default_quota' => options[:default_quota],
42
+ 'ip_version' => options[:ip_version] || 4,
43
+ 'shared' => options[:shared].nil? ? false : options[:shared],
44
+ 'is_default' => options[:is_default].nil? ? false : options[:is_default],
45
+ 'created_at' => Time.now.to_s,
46
+ 'updated_at' => Time.now.to_s,
47
+ 'tenant_id' => Fog::Mock.random_hex(8).to_s
48
+ }
49
+ self.data[:subnet_pools][data['id']] = data
50
+ response.body = {'subnetpool' => data}
51
+ response
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,28 @@
1
+ module Fog
2
+ module Network
3
+ class OpenStack
4
+ class Real
5
+ def delete_subnet_pool(subnet_pool_id)
6
+ request(
7
+ :expects => 204,
8
+ :method => 'DELETE',
9
+ :path => "subnetpools/#{subnet_pool_id}"
10
+ )
11
+ end
12
+ end
13
+
14
+ class Mock
15
+ def delete_subnet_pool(subnet_pool_id)
16
+ response = Excon::Response.new
17
+ if list_subnet_pools.body['subnetpools'].map { |r| r['id'] }.include? subnet_pool_id
18
+ data[:subnet_pools].delete(subnet_pool_id)
19
+ response.status = 204
20
+ response
21
+ else
22
+ raise Fog::Network::OpenStack::NotFound
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Fog
2
+ module Network
3
+ class OpenStack
4
+ class Real
5
+ def get_subnet_pool(subnet_pool_id)
6
+ request(
7
+ :expects => [200],
8
+ :method => 'GET',
9
+ :path => "subnetpools/#{subnet_pool_id}"
10
+ )
11
+ end
12
+ end
13
+
14
+ class Mock
15
+ def get_subnet_pool(subnet_pool_id)
16
+ data = self.data[:subnet_pools][subnet_pool_id]
17
+ if data
18
+ response = Excon::Response.new
19
+ response.status = 200
20
+ response.body = {'subnetpool' => data}
21
+ response
22
+ else
23
+ raise Fog::Network::OpenStack::NotFound
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ module Fog
2
+ module Network
3
+ class OpenStack
4
+ class Real
5
+ def list_subnet_pools(filters = {})
6
+ request(
7
+ :expects => 200,
8
+ :method => 'GET',
9
+ :path => 'subnetpools',
10
+ :query => filters
11
+ )
12
+ end
13
+ end
14
+
15
+ class Mock
16
+ def list_subnet_pools(_filters = {})
17
+ Excon::Response.new(
18
+ :body => {'subnetpools' => data[:subnet_pools].values},
19
+ :status => 200
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ module Fog
2
+ module Network
3
+ class OpenStack
4
+ class Real
5
+ def update_subnet_pool(subnet_pool_id, options = {})
6
+ data = {'subnetpool' => {}}
7
+
8
+ vanilla_options = [:name, :description, :prefixes, :address_scope_id,
9
+ :min_prefixlen, :max_prefixlen, :default_prefixlen]
10
+ vanilla_options.select { |o| options.key?(o) }.each do |key|
11
+ data['subnetpool'][key] = options[key]
12
+ end
13
+
14
+ request(
15
+ :body => Fog::JSON.encode(data),
16
+ :expects => 200,
17
+ :method => 'PUT',
18
+ :path => "subnetpools/#{subnet_pool_id}"
19
+ )
20
+ end
21
+ end
22
+
23
+ class Mock
24
+ def update_subnet_pool(subnet_pool_id, options = {})
25
+ subnet_pool = list_subnet_pools.body['subnetpools'].find { |s| s['id'] == subnet_pool_id }
26
+ if subnet_pool
27
+ subnet_pool['name'] = options[:name]
28
+ subnet_pool['description'] = options[:description]
29
+ subnet_pool['prefixes'] = options[:prefixes] || []
30
+ subnet_pool['min_prefixlen'] = options[:min_prefixlen] || 64
31
+ subnet_pool['max_prefixlen'] = options[:max_prefixlen] || 64
32
+ subnet_pool['default_prefixlen'] = options[:default_prefixlen] || 64
33
+ subnet_pool['address_scope_id'] = options[:address_scope_id]
34
+ subnet_pool['updated_at'] = Time.now.to_s
35
+ response = Excon::Response.new
36
+ response.body = {'subnetpool' => subnet_pool}
37
+ response.status = 200
38
+ response
39
+ else
40
+ raise Fog::Network::OpenStack::NotFound
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -29,6 +29,10 @@ module Fog
29
29
  end
30
30
  end
31
31
 
32
+ module Event
33
+ autoload :OpenStack, File.expand_path('../event/openstack', __FILE__)
34
+ end
35
+
32
36
  module Identity
33
37
  autoload :OpenStack, File.expand_path('../identity/openstack', __FILE__)
34
38
 
@@ -51,6 +55,10 @@ module Fog
51
55
  autoload :OpenStack, File.expand_path('../introspection/openstack', __FILE__)
52
56
  end
53
57
 
58
+ module KeyManager
59
+ autoload :OpenStack, File.expand_path('../key_manager/openstack', __FILE__)
60
+ end
61
+
54
62
  module Metering
55
63
  autoload :OpenStack, File.expand_path('../metering/openstack', __FILE__)
56
64
  end
@@ -100,32 +108,29 @@ module Fog
100
108
  end
101
109
  end
102
110
 
103
- module KeyManager
104
- autoload :OpenStack, File.expand_path('../key_manager/openstack', __FILE__)
105
- end
106
-
107
111
  module OpenStack
108
112
  extend Fog::Provider
109
113
 
114
+ service(:baremetal, 'Baremetal')
110
115
  service(:compute, 'Compute')
111
- service(:image, 'Image')
116
+ service(:container_infra, 'ContainerInfra')
117
+ service(:dns, 'DNS')
118
+ service(:event, 'Event')
112
119
  service(:identity, 'Identity')
113
- service(:network, 'Network')
114
- service(:storage, 'Storage')
115
- service(:volume, 'Volume')
120
+ service(:image, 'Image')
121
+ service(:introspection, 'Introspection')
122
+ service(:key, 'KeyManager')
116
123
  service(:metering, 'Metering')
117
124
  service(:metric, 'Metric')
118
- service(:orchestration, 'Orchestration')
125
+ service(:monitoring, 'Monitoring')
126
+ service(:network, 'Network')
119
127
  service(:nfv, 'NFV')
120
- service(:baremetal, 'Baremetal')
128
+ service(:orchestration, 'Orchestration')
121
129
  service(:planning, 'Planning')
122
- service(:introspection, 'Introspection')
123
- service(:monitoring, 'Monitoring')
124
- service(:workflow, 'Workflow')
125
- service(:dns, 'DNS')
126
- service(:key, 'KeyManager')
127
130
  service(:shared_file_system, 'SharedFileSystem')
128
- service(:container_infra, 'ContainerInfra')
131
+ service(:storage, 'Storage')
132
+ service(:volume, 'Volume')
133
+ service(:workflow, 'Workflow')
129
134
 
130
135
  @token_cache = {}
131
136
 
@@ -259,7 +264,7 @@ module Fog
259
264
 
260
265
  # Keystone Style Auth
261
266
  def self.authenticate_v3(options, connection_options = {})
262
- uri = options[:openstack_auth_uri]
267
+ uri = options[:openstack_auth_uri]
263
268
  project_name = options[:openstack_project_name]
264
269
  service_type = options[:openstack_service_type]
265
270
  service_name = options[:openstack_service_name]
@@ -302,6 +307,26 @@ module Fog
302
307
  service = get_service_v3(body, service_type, service_name, openstack_region, options)
303
308
  end
304
309
 
310
+ # If no identity endpoint is found, try the auth uri (slicing /auth/tokens)
311
+ # It covers the case where identityv3 endpoint is not present in the catalog but we have to use it
312
+ unless service
313
+ if service_type.include? "identity"
314
+ identity_uri = uri.to_s.sub('/auth/tokens', '')
315
+ response = Fog::Core::Connection.new(identity_uri, false, connection_options).request({:method => 'GET'})
316
+ if response.status == 200
317
+ service = {
318
+ "endpoints" => [{
319
+ "url" => identity_uri,
320
+ "region" => openstack_region,
321
+ "interface" => endpoint_type
322
+ }],
323
+ "type" => service_type,
324
+ "name" => service_name
325
+ }
326
+ end
327
+ end
328
+ end
329
+
305
330
  unless service
306
331
  available_services = body['token']['catalog'].map { |service|
307
332
  service['type']
@@ -537,65 +562,27 @@ module Fog
537
562
  end
538
563
 
539
564
  def self.get_supported_version(supported_versions, uri, auth_token, connection_options = {})
540
- connection = Fog::Core::Connection.new("#{uri.scheme}://#{uri.host}:#{uri.port}", false, connection_options)
541
- response = connection.request({
542
- :expects => [200, 204, 300],
543
- :headers => {'Content-Type' => 'application/json',
544
- 'Accept' => 'application/json',
545
- 'X-Auth-Token' => auth_token},
546
- :method => 'GET'
547
- })
548
-
549
- body = Fog::JSON.decode(response.body)
550
- version = nil
551
- unless body['versions'].empty?
552
- versions = body['versions'].kind_of?(Array) ? body['versions'] : body['versions']['values']
553
- supported_version = versions.find do |x|
554
- x["id"].match(supported_versions) &&
555
- (x["status"] == "CURRENT" || x["status"] == "SUPPORTED" || x["status"] == "stable")
556
- end
557
- version = supported_version["id"] if supported_version
558
- end
559
- if version.nil?
560
- raise Fog::OpenStack::Errors::ServiceUnavailable.new(
561
- "OpenStack service only supports API versions #{supported_versions.inspect}")
562
- end
565
+ supported_version = get_version(supported_versions, uri, auth_token, connection_options)
566
+ version = supported_version['id'] if supported_version
567
+ version_raise(supported_versions) if version.nil?
563
568
 
564
569
  version
565
570
  end
566
571
 
567
572
  def self.get_supported_version_path(supported_versions, uri, auth_token, connection_options = {})
568
- # Find a version in the path (e.g. the v1 in /xyz/v1/tenantid/abc) and get the path up until that version (e.g. /xyz))
569
- path_components = uri.path.split '/'
570
- version_component_index = path_components.index{|comp| comp.match(/v[0-9].?[0-9]?/) }
571
- versionless_path = (path_components.take(version_component_index).join '/' if version_component_index) || uri.path
572
- connection = Fog::Core::Connection.new("#{uri.scheme}://#{uri.host}:#{uri.port}#{versionless_path}", false, connection_options)
573
- response = connection.request({
574
- :expects => [200, 204, 300],
575
- :headers => {'Content-Type' => 'application/json',
576
- 'Accept' => 'application/json',
577
- 'X-Auth-Token' => auth_token},
578
- :method => 'GET'
579
- })
580
-
581
- body = Fog::JSON.decode(response.body)
582
- path = nil
583
- unless body['versions'].empty?
584
- versions = body['versions'].kind_of?(Array) ? body['versions'] : body['versions']['values']
585
- supported_version = versions.find do |x|
586
- x["id"].match(supported_versions) &&
587
- (x["status"] == "CURRENT" || x["status"] == "SUPPORTED")
588
- end
589
- path = URI.parse(supported_version['links'].first['href']).path if supported_version
590
- end
591
- if path.nil?
592
- raise Fog::OpenStack::Errors::ServiceUnavailable.new(
593
- "OpenStack service only supports API versions #{supported_versions.inspect}")
594
- end
573
+ supported_version = get_version(supported_versions, uri, auth_token, connection_options)
574
+ link = supported_version['links'].find { |l| l['rel'] == 'self' } if supported_version
575
+ path = URI.parse(link['href']).path if link
576
+ version_raise(supported_versions) if path.nil?
595
577
 
596
578
  path.chomp '/'
597
579
  end
598
580
 
581
+ def self.get_supported_microversion(supported_versions, uri, auth_token, connection_options = {})
582
+ supported_version = get_version(supported_versions, uri, auth_token, connection_options)
583
+ supported_version['version'] if supported_version
584
+ end
585
+
599
586
  # CGI.escape, but without special treatment on spaces
600
587
  def self.escape(str, extra_exclude_chars = '')
601
588
  str.gsub(/([^a-zA-Z0-9_.-#{extra_exclude_chars}]+)/) do
@@ -614,6 +601,41 @@ module Fog
614
601
  end
615
602
 
616
603
  end
617
- end
618
604
 
605
+ def self.get_version(supported_versions, uri, auth_token, connection_options = {})
606
+ version_cache = "#{uri}#{supported_versions}"
607
+ return @version[version_cache] if @version && @version[version_cache]
608
+ connection = Fog::Core::Connection.new("#{uri.scheme}://#{uri.host}:#{uri.port}", false, connection_options)
609
+ response = connection.request(
610
+ :expects => [200, 204, 300],
611
+ :headers => {'Content-Type' => 'application/json',
612
+ 'Accept' => 'application/json',
613
+ 'X-Auth-Token' => auth_token},
614
+ :method => 'GET'
615
+ )
616
+
617
+ body = Fog::JSON.decode(response.body)
618
+
619
+ @version = {} unless @version
620
+ @version[version_cache] = extract_version_from_body(body, supported_versions)
621
+ end
622
+
623
+ def self.extract_version_from_body(body, supported_versions)
624
+ return nil if body['versions'].empty?
625
+ versions = body['versions'].kind_of?(Array) ? body['versions'] : body['versions']['values']
626
+ version = nil
627
+ # order is important, preffered status should be first
628
+ %w(CURRENT stable SUPPORTED DEPRECATED).each do |status|
629
+ version = versions.find { |x| x['id'].match(supported_versions) && (x['status'] == status) }
630
+ break if version
631
+ end
632
+
633
+ version
634
+ end
635
+
636
+ def self.version_raise(supported_versions)
637
+ raise Fog::OpenStack::Errors::ServiceUnavailable,
638
+ "OpenStack service only supports API versions #{supported_versions.inspect}"
639
+ end
640
+ end
619
641
  end
@@ -50,9 +50,9 @@ module Fog
50
50
  @openstack_can_reauthenticate = true
51
51
  end
52
52
 
53
- @current_user = options[:current_user]
53
+ @current_user = options[:current_user]
54
54
  @current_user_id = options[:current_user_id]
55
- @current_tenant = options[:current_tenant]
55
+ @current_tenant = options[:current_tenant]
56
56
  end
57
57
 
58
58
  def credentials
@@ -79,11 +79,7 @@ module Fog
79
79
  retried = false
80
80
  begin
81
81
  response = @connection.request(params.merge(
82
- :headers => {
83
- 'Content-Type' => 'application/json',
84
- 'Accept' => 'application/json',
85
- 'X-Auth-Token' => @auth_token
86
- }.merge!(params[:headers] || {}),
82
+ :headers => headers(params.delete(:headers)),
87
83
  :path => "#{@path}/#{params[:path]}"
88
84
  ))
89
85
  rescue Excon::Errors::Unauthorized => error
@@ -119,6 +115,53 @@ module Fog
119
115
  # if the service supports multiple versions, do the selection here
120
116
  end
121
117
 
118
+ def set_microversion
119
+ @microversion_key ||= 'Openstack-API-Version'.freeze
120
+ @microversion_service_type ||= @openstack_service_type.first
121
+
122
+ @microversion = Fog::OpenStack.get_supported_microversion(
123
+ @supported_versions,
124
+ @openstack_management_uri,
125
+ @auth_token,
126
+ @connection_options
127
+ ).to_s
128
+
129
+ # choose minimum out of reported and supported version
130
+ if microversion_newer_than?(@supported_microversion)
131
+ @microversion = @supported_microversion
132
+ end
133
+
134
+ # choose minimum out of set and wished version
135
+ if @fixed_microversion && microversion_newer_than?(@fixed_microversion)
136
+ @microversion = @fixed_microversion
137
+ elsif @fixed_microversion && @microversion != @fixed_microversion
138
+ Fog::Logger.warning("Microversion #{@fixed_microversion} not supported")
139
+ end
140
+ end
141
+
142
+ def microversion_newer_than?(version)
143
+ Gem::Version.new(version) < Gem::Version.new(@microversion)
144
+ end
145
+
146
+ def headers(additional_headers)
147
+ additional_headers ||= {}
148
+ if @microversion
149
+ microversion_value = if @microversion_key == 'Openstack-API-Version'
150
+ "#{@microversion_service_type} #{@microversion}"
151
+ else
152
+ @microversion
153
+ end
154
+ microversion_header = {@microversion_key => microversion_value}
155
+ additional_headers.merge!(microversion_header)
156
+ end
157
+
158
+ {
159
+ 'Content-Type' => 'application/json',
160
+ 'Accept' => 'application/json',
161
+ 'X-Auth-Token' => @auth_token
162
+ }.merge!(additional_headers)
163
+ end
164
+
122
165
  def openstack_options
123
166
  options = {}
124
167
  # Create a hash of (:openstack_*, value) of all the @openstack_* instance variables
@@ -165,6 +208,9 @@ module Fog
165
208
  )
166
209
  end
167
210
 
211
+ # both need to be set in service's initialize for microversions to work
212
+ set_microversion if @supported_microversion && @supported_versions
213
+
168
214
  true
169
215
  end
170
216
  end