vagrant-openstack-provider 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4dd7cf830eecfb15611665ed53da19db9cd5bab5
4
- data.tar.gz: 1b5bce071291bc0af764f91933b839803ee3f4c7
3
+ metadata.gz: 609b227799e2765e0d6f7bb5277e7e8602cb424f
4
+ data.tar.gz: d92034eb5c24737dc80912e983e35443e8929550
5
5
  SHA512:
6
- metadata.gz: b95d4b1ccc79200bcd97f7a189e21768b214b3f50056d77ff53c83d7581b31c3d23a3e9d343f7023b37a31e8128a65cf6303c7315af3f3f00906286e634145c5
7
- data.tar.gz: 2f071db27ddf020cb30cbf15bbcb7e11e0944dcf63572418c6fc3ce751d4080da54931172424fc88dc2aacf7fb7011ec8f6cedf17278ed7793e11f770d257e96
6
+ metadata.gz: 34905aff4b10744c0c2402b01d801d76adff1c4be7107c46d55e85be80455dc44046dccf6d46fd7df3694695ceef9eaabbc603fb3eff217438648ad6473a0763
7
+ data.tar.gz: e4cdb6940e49072f44bd79829981dce5b6fbc4b385e7f59528ff8c9a22663e86137f03b1999389168dc888b9aa90b21ec05e2738b114968b9cc4ce024b47afce
@@ -1,3 +1,17 @@
1
+ # 0.8.0 (November 19, 2016)
2
+
3
+ IMPROVEMENTS:
4
+
5
+ - Move to standard Vagrant synced folders middleware #295
6
+
7
+ FEATURES:
8
+
9
+ - Support Keystone v3 API #4
10
+
11
+ BUG FIXES:
12
+
13
+ - Bugfix on IP address resolution #285
14
+
1
15
  # 0.7.2 (May 1, 2016)
2
16
 
3
17
  IMPROVEMENTS:
data/Gemfile CHANGED
@@ -3,7 +3,14 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git', tag: 'v1.8.1'
6
+ gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git', tag: 'v1.8.5'
7
+ # FIXME: Hack to allow Vagrant v1.6.5 to install for tests. Remove when
8
+ # support for 1.6.5 is dropped.
9
+ gem 'rack', '< 2'
10
+ # FIXME: Version 1.4.0 of the ruby_dep gem added a constraint on the Ruby
11
+ # version being >=2.2.5. This pin to ruby_dep 1.3.1 can be removed when the
12
+ # next Vagrant version after 1.8.5 is released.
13
+ gem 'ruby_dep', '~> 1.3.1'
7
14
  gem 'appraisal', '1.0.0'
8
15
  gem 'rubocop', '0.29.0', require: false
9
16
  gem 'coveralls', require: false
@@ -39,7 +39,13 @@ module VagrantPlugins
39
39
  else
40
40
  b2.use Provision
41
41
  end
42
- b2.use SyncFolders
42
+ if env[:machine].provider_config.use_legacy_synced_folders
43
+ env[:machine].ui.warn I18n.t('vagrant_openstack.config.sync_folders_deprecated')
44
+ b2.use SyncFolders
45
+ else
46
+ # Standard Vagrant implementation.
47
+ b2.use SyncedFolders
48
+ end
43
49
  end
44
50
  end
45
51
  end
@@ -61,6 +67,7 @@ module VagrantPlugins
61
67
  # key.
62
68
  def self.action_read_state
63
69
  new_builder.tap do |b|
70
+ b.use HandleBox
64
71
  b.use ConfigValidate
65
72
  b.use ConnectOpenstack
66
73
  b.use ReadState
@@ -97,6 +104,7 @@ module VagrantPlugins
97
104
 
98
105
  def self.action_up
99
106
  new_builder.tap do |b|
107
+ b.use HandleBox
100
108
  b.use ConfigValidate
101
109
  b.use ConnectOpenstack
102
110
 
@@ -111,7 +119,15 @@ module VagrantPlugins
111
119
  b2.use Provision
112
120
  end
113
121
  end
114
- b2.use SyncFolders
122
+
123
+ if env[:machine].provider_config.use_legacy_synced_folders
124
+ env[:machine].ui.warn I18n.t('vagrant_openstack.config.sync_folders_deprecated')
125
+ b2.use SyncFolders
126
+ else
127
+ # Standard Vagrant implementation.
128
+ b2.use SyncedFolders
129
+ end
130
+
115
131
  b2.use CreateStack
116
132
  b2.use CreateServer
117
133
  b2.use Message, I18n.t('vagrant_openstack.ssh_disabled_provisioning') if ssh_disabled
@@ -99,7 +99,7 @@ module VagrantPlugins
99
99
  end
100
100
  end
101
101
 
102
- log = "Lauching server '#{server_name}' in project '#{config.tenant_name}' "
102
+ log = "Launching server '#{server_name}' in project '#{config.tenant_name}' "
103
103
  log << "with flavor '#{options[:flavor].name}' (#{options[:flavor].id}), "
104
104
  unless options[:image].nil?
105
105
  log << "image '#{options[:image].name}' (#{options[:image].id}) "
@@ -131,7 +131,7 @@ module VagrantPlugins
131
131
  @logger.info "Waiting for the server with id #{server_id} to be built..."
132
132
  env[:ui].info(I18n.t('vagrant_openstack.waiting_for_build'))
133
133
  config = env[:machine].provider_config
134
- timeout(config.server_create_timeout, Errors::Timeout) do
134
+ Timeout.timeout(config.server_create_timeout, Errors::Timeout) do
135
135
  server_status = 'WAITING'
136
136
  until server_status == 'ACTIVE'
137
137
  @logger.debug('Waiting for server to be ACTIVE')
@@ -60,7 +60,7 @@ module VagrantPlugins
60
60
  @logger.info "Waiting for the stack with id #{stack_id} to be built..."
61
61
  env[:ui].info(I18n.t('vagrant_openstack.waiting_for_stack'))
62
62
  config = env[:machine].provider_config
63
- timeout(config.stack_create_timeout, Errors::Timeout) do
63
+ Timeout.timeout(config.stack_create_timeout, Errors::Timeout) do
64
64
  stack_status = 'CREATE_IN_PROGRESS'
65
65
  until stack_status == 'CREATE_COMPLETE'
66
66
  @logger.debug('Waiting for stack to be CREATED')
@@ -32,7 +32,7 @@ module VagrantPlugins
32
32
  @logger.info "Waiting for the instance with id #{instance_id} to be deleted..."
33
33
  env[:ui].info(I18n.t('vagrant_openstack.waiting_deleted'))
34
34
  config = env[:machine].provider_config
35
- timeout(config.server_delete_timeout, Errors::Timeout) do
35
+ Timeout.timeout(config.server_delete_timeout, Errors::Timeout) do
36
36
  delete_ok = false
37
37
  until delete_ok
38
38
  begin
@@ -57,7 +57,7 @@ module VagrantPlugins
57
57
  @logger.info "Waiting for the stack with id #{stack_id} to be deleted..."
58
58
  env[:ui].info(I18n.t('vagrant_openstack.waiting_for_stack_deleted'))
59
59
  config = env[:machine].provider_config
60
- timeout(config.stack_delete_timeout, Errors::Timeout) do
60
+ Timeout.timeout(config.stack_delete_timeout, Errors::Timeout) do
61
61
  stack_status = 'DELETE_IN_PROGRESS'
62
62
  until stack_status == 'DELETE_COMPLETE'
63
63
  @logger.debug('Waiting for stack to be DELETED')
@@ -18,7 +18,7 @@ module VagrantPlugins
18
18
  env[:ui].info(I18n.t('vagrant_openstack.waiting_start'))
19
19
  client = env[:openstack_client].nova
20
20
  config = env[:machine].provider_config
21
- timeout(config.server_active_timeout, Errors::Timeout) do
21
+ Timeout.timeout(config.server_active_timeout, Errors::Timeout) do
22
22
  while client.get_server_details(env, env[:machine].id)['status'] != 'ACTIVE'
23
23
  sleep @retry_interval
24
24
  @logger.info('Waiting for server to be active')
@@ -18,7 +18,7 @@ module VagrantPlugins
18
18
  env[:ui].info(I18n.t('vagrant_openstack.waiting_stop'))
19
19
  client = env[:openstack_client].nova
20
20
  config = env[:machine].provider_config
21
- timeout(config.server_stop_timeout, Errors::Timeout) do
21
+ Timeout.timeout(config.server_stop_timeout, Errors::Timeout) do
22
22
  while client.get_server_details(env, env[:machine].id)['status'] != 'SHUTOFF'
23
23
  sleep @retry_interval
24
24
  @logger.info('Waiting for server to stop')
@@ -10,24 +10,16 @@ module VagrantPlugins
10
10
  config = env[:machine].provider_config
11
11
  client = env[:openstack_client]
12
12
  endpoints = client.session.endpoints
13
- endpoint_type = config.endpoint_type
14
13
  @logger.info(I18n.t('vagrant_openstack.client.looking_for_available_endpoints'))
15
14
  @logger.info("Selecting endpoints matching region '#{config.region}'") unless config.region.nil?
16
15
 
17
16
  catalog.each do |service|
18
17
  se = service['endpoints']
19
- if config.region.nil?
20
- if se.size > 1
21
- env[:ui].warn I18n.t('vagrant_openstack.client.multiple_endpoint', size: se.size, type: service['type'])
22
- env[:ui].warn " => #{service['endpoints'][0][endpoint_type]}"
23
- end
24
- url = se[0][endpoint_type].strip
25
- else
26
- se.each do |endpoint|
27
- url = endpoint[endpoint_type].strip if endpoint['region'].eql? config.region
28
- end
18
+ if config.identity_api_version == '2'
19
+ get_endpoints_2(env, se, service, config, endpoints)
20
+ elsif config.identity_api_version == '3'
21
+ get_interfaces_3(se, service, config, endpoints)
29
22
  end
30
- endpoints[service['type'].to_sym] = url unless url.nil? || url.empty?
31
23
  end
32
24
 
33
25
  endpoints[:network] = choose_api_version('Neutron', 'openstack_network_url', 'v2') do
@@ -41,6 +33,37 @@ module VagrantPlugins
41
33
 
42
34
  private
43
35
 
36
+ def get_endpoints_2(env, se, service, config, endpoints)
37
+ endpoint_type = config.endpoint_type
38
+ if config.region.nil?
39
+ if se.size > 1
40
+ env[:ui].warn I18n.t('vagrant_openstack.client.multiple_endpoint', size: se.size, type: service['type'])
41
+ env[:ui].warn " => #{service['endpoints'][0][endpoint_type]}"
42
+ end
43
+ url = se[0][endpoint_type].strip
44
+ else
45
+ se.each do |endpoint|
46
+ url = endpoint[endpoint_type].strip if endpoint['region'].eql? config.region
47
+ end
48
+ end
49
+ endpoints[service['type'].to_sym] = url unless url.nil? || url.empty?
50
+ end
51
+
52
+ def get_interfaces_3(se, service, config, endpoints)
53
+ url = nil
54
+ se.each do |endpoint|
55
+ next if endpoint['interface'] != config.interface_type
56
+ if config.region.nil?
57
+ url = endpoint['url']
58
+ break
59
+ elsif endpoint['region'] == config.region
60
+ url = endpoint['url']
61
+ break
62
+ end
63
+ end
64
+ endpoints[service['type'].to_sym] = url unless url.nil? || url.empty?
65
+ end
66
+
44
67
  def choose_api_version(service_name, url_property, version_prefix = nil, fail_if_not_found = true)
45
68
  versions = yield
46
69
 
@@ -19,20 +19,13 @@ module VagrantPlugins
19
19
  config = env[:machine].provider_config
20
20
  @logger.info(I18n.t('vagrant_openstack.client.authentication', project: config.tenant_name, user: config.username))
21
21
 
22
- post_body =
23
- {
24
- auth:
25
- {
26
- tenantName: config.tenant_name,
27
- passwordCredentials:
28
- {
29
- username: config.username,
30
- password: '****'
31
- }
32
- }
33
- }
34
-
35
- auth_url = get_auth_url_v2 env
22
+ if config.identity_api_version == '2'
23
+ post_body = get_body_2 config
24
+ auth_url = get_auth_url_2 env
25
+ elsif config.identity_api_version == '3'
26
+ post_body = get_body_3 config
27
+ auth_url = get_auth_url_3 env
28
+ end
36
29
 
37
30
  headers = {
38
31
  content_type: :json,
@@ -41,13 +34,19 @@ module VagrantPlugins
41
34
 
42
35
  log_request(:POST, auth_url, post_body.to_json, headers)
43
36
 
44
- post_body[:auth][:passwordCredentials][:password] = config.password
37
+ if config.identity_api_version == '2'
38
+ post_body[:auth][:passwordCredentials][:password] = config.password
39
+ elsif config.identity_api_version == '3'
40
+ post_body[:auth][:identity][:password][:user][:password] = config.password
41
+ end
45
42
 
46
43
  authentication = RestUtils.post(env, auth_url, post_body.to_json, headers) do |response|
47
44
  log_response(response)
48
45
  case response.code
49
46
  when 200
50
47
  response
48
+ when 201
49
+ response
51
50
  when 401
52
51
  fail Errors::AuthenticationFailed
53
52
  when 404
@@ -57,17 +56,69 @@ module VagrantPlugins
57
56
  end
58
57
  end
59
58
 
60
- access = JSON.parse(authentication)['access']
61
- response_token = access['token']
62
- @session.token = response_token['id']
63
- @session.project_id = response_token['tenant']['id']
64
-
65
- access['serviceCatalog']
59
+ if config.identity_api_version == '2'
60
+ access = JSON.parse(authentication)['access']
61
+ response_token = access['token']
62
+ @session.token = response_token['id']
63
+ @session.project_id = response_token['tenant']['id']
64
+ return access['serviceCatalog']
65
+ elsif config.identity_api_version == '3'
66
+ body = JSON.parse(authentication)
67
+ @session.token = authentication.headers[:x_subject_token]
68
+ @session.project_id = body['token']['project']['id']
69
+ return body['token']['catalog']
70
+ end
66
71
  end
67
72
 
68
73
  private
69
74
 
70
- def get_auth_url_v2(env)
75
+ def get_body_2(config)
76
+ {
77
+ auth:
78
+ {
79
+ tenantName: config.tenant_name,
80
+ passwordCredentials:
81
+ {
82
+ username: config.username,
83
+ password: '****'
84
+ }
85
+ }
86
+ }
87
+ end
88
+
89
+ def get_body_3(config)
90
+ {
91
+ auth:
92
+ {
93
+ identity: {
94
+ methods: ['password'],
95
+ password: {
96
+ user: {
97
+ name: config.username,
98
+ domain: {
99
+ name: config.domain_name
100
+ },
101
+ password: '****'
102
+ }
103
+ }
104
+ },
105
+ scope: {
106
+ project: {
107
+ name: config.project_name,
108
+ domain: { name: config.domain_name }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ end
114
+
115
+ def get_auth_url_3(env)
116
+ url = env[:machine].provider_config.openstack_auth_url
117
+ return url if url.match(%r{/tokens/*$})
118
+ "#{url}/auth/tokens"
119
+ end
120
+
121
+ def get_auth_url_2(env)
71
122
  url = env[:machine].provider_config.openstack_auth_url
72
123
  return url if url.match(%r{/tokens/*$})
73
124
  "#{url}/tokens"
@@ -52,6 +52,11 @@ module VagrantPlugins
52
52
  #
53
53
  attr_accessor :tenant_name
54
54
 
55
+ #
56
+ # The name of the openstack project on witch the vm will be created, changed name in v3 identity API.
57
+ #
58
+ attr_accessor :project_name
59
+
55
60
  # The name of the server. This defaults to the name of the machine
56
61
  # defined by Vagrant (via `config.vm.define`), but can be overriden
57
62
  # here.
@@ -62,6 +67,11 @@ module VagrantPlugins
62
67
  # @return [String]
63
68
  attr_accessor :username
64
69
 
70
+ # The domain name to access Openstack, this defaults to Default.
71
+ #
72
+ # @return [String]
73
+ attr_accessor :domain_name
74
+
65
75
  # The name of the keypair to use.
66
76
  #
67
77
  # @return [String]
@@ -82,6 +92,8 @@ module VagrantPlugins
82
92
 
83
93
  # Opt files/directories in to the rsync operation performed by this provider
84
94
  #
95
+ # @deprecated Use standard Vagrant synced folders instead.
96
+ #
85
97
  # @return [Array]
86
98
  attr_accessor :rsync_includes
87
99
 
@@ -103,12 +115,16 @@ module VagrantPlugins
103
115
 
104
116
  # Sync folder method. Can be either "rsync" or "none"
105
117
  #
118
+ # @deprecated Use standard Vagrant synced folders instead.
119
+ #
106
120
  # @return [String]
107
121
  attr_accessor :sync_method
108
122
 
109
123
  # Sync folder ignore files. A list of files containing exclude patterns to ignore in the rsync operation
110
124
  # performed by this provider
111
125
  #
126
+ # @deprecated Use standard Vagrant synced folders instead.
127
+ #
112
128
  # @return [Array]
113
129
  attr_accessor :rsync_ignore_files
114
130
 
@@ -167,6 +183,16 @@ module VagrantPlugins
167
183
  # @return [String]
168
184
  attr_accessor :endpoint_type
169
185
 
186
+ # Specify the endpoint_type to use : publicL, admin, or internal (default is public)
187
+ #
188
+ # @return [String]
189
+ attr_accessor :interface_type
190
+
191
+ # Specify the authentication version to use : 2 or 3 (ddefault is 2()
192
+ #
193
+ # @return [String]
194
+ attr_accessor :identity_api_version
195
+
170
196
  #
171
197
  # @return [Integer]
172
198
  attr_accessor :server_create_timeout
@@ -199,6 +225,20 @@ module VagrantPlugins
199
225
  # @return [Boolean]
200
226
  attr_accessor :meta_args_support
201
227
 
228
+ # A switch for enabling the legacy synced folders implementation.
229
+ #
230
+ # This defaults to false, but is automatically set to true if any of the
231
+ # legacy synced folder options are used:
232
+ #
233
+ # - {#rsync_includes}
234
+ # - {#rsync_ignore_files}
235
+ # - {#sync_method}
236
+ #
237
+ # @deprecated Use standard Vagrant synced folders instead.
238
+ #
239
+ # @return [Boolean]
240
+ attr_accessor :use_legacy_synced_folders
241
+
202
242
  def initialize
203
243
  @password = UNSET_VALUE
204
244
  @openstack_compute_url = UNSET_VALUE
@@ -208,6 +248,8 @@ module VagrantPlugins
208
248
  @openstack_image_url = UNSET_VALUE
209
249
  @openstack_auth_url = UNSET_VALUE
210
250
  @endpoint_type = UNSET_VALUE
251
+ @interface_type = UNSET_VALUE
252
+ @identity_api_version = UNSET_VALUE
211
253
  @region = UNSET_VALUE
212
254
  @flavor = UNSET_VALUE
213
255
  @image = UNSET_VALUE
@@ -242,6 +284,7 @@ module VagrantPlugins
242
284
  @stack_delete_timeout = UNSET_VALUE
243
285
  @meta_args_support = UNSET_VALUE
244
286
  @http = HttpConfig.new
287
+ @use_legacy_synced_folders = UNSET_VALUE
245
288
  end
246
289
 
247
290
  def merge(other)
@@ -282,7 +325,7 @@ module VagrantPlugins
282
325
  result
283
326
  end
284
327
 
285
- # rubocop:disable Metrics/CyclomaticComplexity
328
+ # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
286
329
  def finalize!
287
330
  @password = nil if @password == UNSET_VALUE
288
331
  @openstack_compute_url = nil if @openstack_compute_url == UNSET_VALUE
@@ -292,19 +335,20 @@ module VagrantPlugins
292
335
  @openstack_image_url = nil if @openstack_image_url == UNSET_VALUE
293
336
  @openstack_auth_url = nil if @openstack_auth_url == UNSET_VALUE
294
337
  @endpoint_type = 'publicURL' if @endpoint_type == UNSET_VALUE
338
+ @interface_type = 'public' if @interface_type == UNSET_VALUE
339
+ @identity_api_version = '2' if @identity_api_version == UNSET_VALUE
295
340
  @region = nil if @region == UNSET_VALUE
296
341
  @flavor = nil if @flavor == UNSET_VALUE
297
342
  @image = nil if @image == UNSET_VALUE
298
343
  @volume_boot = nil if @volume_boot == UNSET_VALUE
299
344
  @tenant_name = nil if @tenant_name == UNSET_VALUE
345
+ @project_name = nil if @project_name == UNSET_VALUE
300
346
  @server_name = nil if @server_name == UNSET_VALUE
301
347
  @username = nil if @username == UNSET_VALUE
302
- @rsync_includes = nil if @rsync_includes.empty?
303
- @rsync_ignore_files = nil if @rsync_ignore_files.empty?
348
+ @domain_name = 'Default' if @domain_name == UNSET_VALUE
304
349
  @floating_ip = nil if @floating_ip == UNSET_VALUE
305
350
  @floating_ip_pool = nil if @floating_ip_pool == UNSET_VALUE
306
351
  @floating_ip_pool_always_allocate = false if floating_ip_pool_always_allocate == UNSET_VALUE
307
- @sync_method = 'rsync' if @sync_method == UNSET_VALUE
308
352
  @keypair_name = nil if @keypair_name == UNSET_VALUE
309
353
  @public_key_path = nil if @public_key_path == UNSET_VALUE
310
354
  @availability_zone = nil if @availability_zone == UNSET_VALUE
@@ -314,6 +358,27 @@ module VagrantPlugins
314
358
  @metadata = nil if @metadata == UNSET_VALUE
315
359
  @ssh_disabled = false if @ssh_disabled == UNSET_VALUE
316
360
 
361
+ # The value of use_legacy_synced_folders is used by action chains
362
+ # to determine which synced folder implementation to run.
363
+ if @use_legacy_synced_folders == UNSET_VALUE
364
+ @use_legacy_synced_folders = !(
365
+ (@rsync_includes.nil? || @rsync_includes.empty?) &&
366
+ (@rsync_ignore_files.nil? || @rsync_ignore_files.empty?) &&
367
+ (@sync_method.nil? || @sync_method == UNSET_VALUE))
368
+ end
369
+
370
+ if @use_legacy_synced_folders
371
+ # Original defaults.
372
+ @rsync_includes = nil if @rsync_includes.empty?
373
+ @rsync_ignore_files = nil if @rsync_ignore_files.empty?
374
+ @sync_method = 'rsync' if @sync_method == UNSET_VALUE
375
+ else
376
+ # Disable all sync settings.
377
+ @rsync_includes = nil
378
+ @rsync_ignore_files = nil
379
+ @sync_method = nil
380
+ end
381
+
317
382
  # The SSH values by default are nil, and the top-level config
318
383
  # `config.ssh` and `config.vm.boot_timeout` values are used.
319
384
  @ssh_username = nil if @ssh_username == UNSET_VALUE
@@ -331,8 +396,10 @@ module VagrantPlugins
331
396
  @stacks = nil if @stacks.empty?
332
397
  @http.finalize!
333
398
  end
334
- # rubocop:enable Metrics/CyclomaticComplexity
399
+ # rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
335
400
 
401
+ #
402
+ # @deprecated Use standard Vagrant synced folders instead.
336
403
  def rsync_include(inc)
337
404
  @rsync_includes << inc
338
405
  end
@@ -342,9 +409,9 @@ module VagrantPlugins
342
409
 
343
410
  errors << I18n.t('vagrant_openstack.config.password_required') if @password.nil? || @password.empty?
344
411
  errors << I18n.t('vagrant_openstack.config.username_required') if @username.nil? || @username.empty?
345
- errors << I18n.t('vagrant_openstack.config.tenant_name_required') if @tenant_name.nil? || @tenant_name.empty?
346
- errors << I18n.t('vagrant_openstack.config.invalid_endpoint_type') unless %w(publicURL adminURL internalURL).include?(@endpoint_type)
412
+ errors << I18n.t('vagrant_openstack.config.invalid_api_version') unless %w(2 3).include?(@identity_api_version)
347
413
 
414
+ validate_api_version(errors)
348
415
  validate_ssh_username(machine, errors)
349
416
  validate_stack_config(errors)
350
417
  validate_ssh_timeout(errors)
@@ -371,6 +438,17 @@ module VagrantPlugins
371
438
 
372
439
  private
373
440
 
441
+ def validate_api_version(errors)
442
+ if @identity_api_version == '2'
443
+ errors << I18n.t('vagrant_openstack.config.tenant_name_required') if @tenant_name.nil? || @tenant_name.empty?
444
+ errors << I18n.t('vagrant_openstack.config.invalid_endpoint_type') unless %w(publicURL adminURL internalURL).include?(@endpoint_type)
445
+ elsif @identity_api_version == '3'
446
+ errors << I18n.t('vagrant_openstack.config.domain_required') if @domain_name.nil? || @domain_name.empty?
447
+ errors << I18n.t('vagrant_openstack.config.project_name_required') if @project_name.nil? || @project_name.empty?
448
+ errors << I18n.t('vagrant_openstack.config.invalid_interface_type') unless %w(public admin internal).include?(@interface_type)
449
+ end
450
+ end
451
+
374
452
  def validate_stack_config(errors)
375
453
  @stacks.each do |stack|
376
454
  errors << I18n.t('vagrant_openstack.config.invalid_stack') unless stack[:name] && stack[:template]
@@ -16,7 +16,12 @@ module VagrantPlugins
16
16
  if addresses.size == 1
17
17
  net_addresses = addresses.first[1]
18
18
  else
19
- net_addresses = addresses[env[:machine].provider_config.networks[0]]
19
+ first_network = env[:machine].provider_config.networks[0]
20
+ if first_network.is_a? String
21
+ net_addresses = addresses[first_network]
22
+ else
23
+ net_addresses = addresses[first_network[:name]]
24
+ end
20
25
  end
21
26
  fail Errors::UnableToResolveIP if net_addresses.size == 0
22
27
  net_addresses[0]['addr']
@@ -4,7 +4,7 @@ module VagrantPlugins
4
4
  # Stable versions must respect the pattern given
5
5
  # by VagrantPlugins::Openstack::VERSION_PATTERN
6
6
  #
7
- VERSION = '0.7.2'
7
+ VERSION = '0.8.0'
8
8
 
9
9
  #
10
10
  # Stable version must respect the naming convention 'x.y.z'
@@ -65,7 +65,7 @@ module VagrantPlugins
65
65
 
66
66
  # rubocop:disable Lint/HandleExceptions
67
67
  def self.check_version
68
- timeout(3, Errors::Timeout) do
68
+ Timeout.timeout(3, Errors::Timeout) do
69
69
  VersionChecker.instance.check
70
70
  end
71
71
  rescue
@@ -138,6 +138,19 @@ en:
138
138
  to the standard vagrant configuration option `config.vm.boot_timeout`.
139
139
  invalid_value_for_parameter: |-
140
140
  Invalid value '%{value}' for parameter '%{parameter}'
141
+ sync_folders_deprecated: |-
142
+ The following configuration settings are deprecated and should be
143
+ removed: rsync_includes, rsync_ignore_files, sync_method. Using these
144
+ settings causes the OpenStack provider to fall back to an old synced
145
+ folder implementation instead of using standard Vagrant synced folders.
146
+ domain_required: |-
147
+ A domain is required when using identity API version 3
148
+ project_name_required: |-
149
+ A project name is required when using identity API version 3
150
+ invalid_interface_type: |-
151
+ Interface type must be public, admin or internal (if not provided, default is public)
152
+ invalid_api_version: |-
153
+ identity API verison must be 2 or 3 (if nto provided, default is 2)
141
154
 
142
155
  errors:
143
156
  default: |-
@@ -18,10 +18,13 @@ describe VagrantPlugins::Openstack::Action::ConnectOpenstack do
18
18
  config.stub(:openstack_volume_url) { nil }
19
19
  config.stub(:openstack_image_url) { nil }
20
20
  config.stub(:tenant_name) { 'testTenant' }
21
+ config.stub(:project_name) { 'testTenant' }
21
22
  config.stub(:username) { 'username' }
22
23
  config.stub(:password) { 'password' }
23
24
  config.stub(:region) { nil }
24
25
  config.stub(:endpoint_type) { 'publicURL' }
26
+ config.stub(:interface_type) { 'public' }
27
+ config.stub(:identity_api_version) { '2' }
25
28
  end
26
29
  end
27
30
 
@@ -243,6 +246,78 @@ describe VagrantPlugins::Openstack::Action::ConnectOpenstack do
243
246
  end
244
247
  end
245
248
 
249
+ context 'with one endpoint by service v3' do
250
+ it 'read service catalog and stores endpoints URL in session v3' do
251
+ catalog = [
252
+ {
253
+ 'endpoints' => [
254
+ {
255
+ 'url' => 'http://nova/v2/projectId',
256
+ 'interface' => 'public',
257
+ 'region' => 'RegionOne',
258
+ 'id' => '1'
259
+ }
260
+ ],
261
+ 'type' => 'compute',
262
+ 'name' => 'nova'
263
+ },
264
+ {
265
+ 'endpoints' => [
266
+ {
267
+ 'url' => 'http://neutron',
268
+ 'interface' => 'public',
269
+ 'region' => 'RegionOne',
270
+ 'id' => '2'
271
+ }
272
+ ],
273
+ 'type' => 'network',
274
+ 'name' => 'neutron'
275
+ },
276
+ {
277
+ 'endpoints' => [
278
+ {
279
+ 'url' => 'http://cinder/v2/projectId',
280
+ 'interface' => 'public',
281
+ 'region' => 'RegionOne',
282
+ 'id' => '2'
283
+ }
284
+ ],
285
+ 'type' => 'volume',
286
+ 'name' => 'cinder'
287
+ },
288
+ {
289
+ 'endpoints' => [
290
+ {
291
+ 'url' => 'http://glance',
292
+ 'interface' => 'public',
293
+ 'region' => 'RegionOne',
294
+ 'id' => '2'
295
+ }
296
+ ],
297
+ 'type' => 'image',
298
+ 'name' => 'glance'
299
+ }
300
+ ]
301
+
302
+ double.tap do |keystone|
303
+ keystone.stub(:authenticate).with(anything) { catalog }
304
+ env[:openstack_client].stub(:keystone) { keystone }
305
+ end
306
+ env[:openstack_client].stub(:neutron) { neutron }
307
+ env[:openstack_client].stub(:glance) { glance }
308
+ config.stub(:domain_name) { 'dummy' }
309
+ config.stub(:identity_api_version) { '3' }
310
+
311
+ @action.call(env)
312
+
313
+ expect(env[:openstack_client].session.endpoints)
314
+ .to eq(compute: 'http://nova/v2/projectId',
315
+ network: 'http://neutron/v2.0',
316
+ volume: 'http://cinder/v2/projectId',
317
+ image: 'http://glance/v2.0')
318
+ end
319
+ end
320
+
246
321
  context 'with multiple regions' do
247
322
  it 'read service catalog and stores endpoints URL for desired regions in session' do
248
323
  catalog = [
@@ -17,6 +17,9 @@ describe VagrantPlugins::Openstack::KeystoneClient do
17
17
  config.stub(:username) { 'username' }
18
18
  config.stub(:password) { 'password' }
19
19
  config.stub(:http) { http }
20
+ config.stub(:interface_type) { 'public' }
21
+ config.stub(:identity_api_version) { '2' }
22
+ config.stub(:project_name) { 'testTenant' }
20
23
  end
21
24
  end
22
25
 
@@ -52,6 +55,29 @@ describe VagrantPlugins::Openstack::KeystoneClient do
52
55
  ]}}'
53
56
  end
54
57
 
58
+ let(:keystone_response_headers_v3) do
59
+ {
60
+ 'Accept' => 'application/json',
61
+ 'Content-Type' => 'application/json',
62
+ 'x_subject_token' => '0123456789'
63
+ }
64
+ end
65
+
66
+ let(:keystone_request_body_v3) do
67
+ '{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":"username","domain":'\
68
+ '{"name":"dummy"},"password":"password"}}},"scope":{"project":{"name":"testTenant","domain":'\
69
+ '{"name":"dummy"}}}}}'
70
+ end
71
+
72
+ let(:keystone_response_body_v3) do
73
+ '{"token":{"is_domain":false,"methods":["password"],"roles":[{"id":"1234","name":"_member_"}],
74
+ "is_admin_project":false,"project":{"domain":{"id":"1234","name":"dummy"},"id":"012345678910",
75
+ "name":"testTenantId"},"catalog":[
76
+ {"endpoints":[{"id":"eid1","interface":"public","url":"http://nova"}],"type":"compute"},
77
+ {"endpoints":[{"id":"eid2","interface":"public","url":"http://neutron"}],"type":"network"}
78
+ ]}}'
79
+ end
80
+
55
81
  before :each do
56
82
  @keystone_client = VagrantPlugins::Openstack.keystone
57
83
  end
@@ -146,5 +172,53 @@ describe VagrantPlugins::Openstack::KeystoneClient do
146
172
  end
147
173
  end
148
174
  end
175
+
176
+ # V3
177
+ context 'with good credentials v3' do
178
+ it 'store token and tenant id' do
179
+ config.stub(:domain_name) { 'dummy' }
180
+ config.stub(:identity_api_version) { '3' }
181
+ config.stub(:openstack_auth_url) { 'http://keystoneAuthV3' }
182
+
183
+ stub_request(:post, 'http://keystoneAuthV3/auth/tokens')
184
+ .with(
185
+ body: keystone_request_body_v3,
186
+ headers: keystone_request_headers)
187
+ .to_return(
188
+ status: 200,
189
+ body: keystone_response_body_v3,
190
+ headers: keystone_response_headers_v3)
191
+
192
+ @keystone_client.authenticate(env)
193
+
194
+ session.token.should eq('0123456789')
195
+ session.project_id.should eq('012345678910')
196
+ end
197
+ end
198
+
199
+ context 'with wrong credentials v3' do
200
+ it 'raise an unauthorized error ' do
201
+ config.stub(:domain_name) { 'dummy' }
202
+ config.stub(:identity_api_version) { '3' }
203
+ config.stub(:openstack_auth_url) { 'http://keystoneAuthV3' }
204
+
205
+ stub_request(:post, 'http://keystoneAuthV3/auth/tokens')
206
+ .with(
207
+ body: keystone_request_body_v3,
208
+ headers: keystone_request_headers)
209
+ .to_return(
210
+ status: 401,
211
+ body: '{
212
+ "error": {
213
+ "message": "The request you have made requires authentication.",
214
+ "code": 401,
215
+ "title": "Unauthorized"
216
+ }
217
+ }',
218
+ headers: keystone_response_headers_v3)
219
+
220
+ expect { @keystone_client.authenticate(env) }.to raise_error(Errors::AuthenticationFailed)
221
+ end
222
+ end
149
223
  end
150
224
  end
@@ -16,7 +16,10 @@ describe VagrantPlugins::Openstack::Config do
16
16
  its(:image) { should be_nil }
17
17
  its(:server_name) { should be_nil }
18
18
  its(:username) { should be_nil }
19
+ its(:use_legacy_synced_folders) { should eq(false) }
19
20
  its(:rsync_includes) { should be_nil }
21
+ its(:rsync_ignore_files) { should be_nil }
22
+ its(:sync_method) { should be_nil }
20
23
  its(:keypair_name) { should be_nil }
21
24
  its(:public_key_path) { should be_nil }
22
25
  its(:availability_zone) { should be_nil }
@@ -55,11 +58,36 @@ describe VagrantPlugins::Openstack::Config do
55
58
  end
56
59
  end
57
60
 
61
+ describe 'use_legacy_synced_folders' do
62
+ it 'should default to true if sync_method is set' do
63
+ subject.sync_method = 'rsync'
64
+ subject.finalize!
65
+
66
+ expect(subject.use_legacy_synced_folders).to eq(true)
67
+ end
68
+
69
+ it 'should default to true if rsync_includes is non-empty' do
70
+ subject.rsync_includes = ['some/file']
71
+ subject.finalize!
72
+
73
+ expect(subject.use_legacy_synced_folders).to eq(true)
74
+ end
75
+
76
+ it 'should default to true if rsync_ignore_files is non-empty' do
77
+ subject.rsync_ignore_files = ['some/file']
78
+ subject.finalize!
79
+
80
+ expect(subject.use_legacy_synced_folders).to eq(true)
81
+ end
82
+ end
83
+
58
84
  it 'should not default rsync_includes if overridden' do
59
85
  inc = 'core'
60
86
  subject.send(:rsync_include, inc)
61
87
  subject.finalize!
62
- subject.send(:rsync_includes).should include(inc)
88
+
89
+ expect(subject.rsync_includes).to include(inc)
90
+ expect(subject.use_legacy_synced_folders).to eq(true)
63
91
  end
64
92
  end
65
93
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-openstack-provider
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillaume Giamarchi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-30 00:00:00.000000000 Z
12
+ date: 2016-11-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json