vagrant-openstack-provider 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -2
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile +8 -15
  5. data/Vagrantfile +12 -10
  6. data/gemfiles/latest_stable.gemfile +6 -16
  7. data/gemfiles/minimal_release.gemfile +10 -0
  8. data/gemfiles/previous_release.gemfile +6 -16
  9. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +2 -1
  10. data/lib/vagrant-openstack-provider/action/create_server.rb +40 -248
  11. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +30 -29
  12. data/lib/vagrant-openstack-provider/action/sync_folders.rb +19 -9
  13. data/lib/vagrant-openstack-provider/action/wait_accessible.rb +58 -0
  14. data/lib/vagrant-openstack-provider/action/wait_active.rb +5 -3
  15. data/lib/vagrant-openstack-provider/action/wait_stop.rb +5 -3
  16. data/lib/vagrant-openstack-provider/action.rb +19 -11
  17. data/lib/vagrant-openstack-provider/client/http_utils.rb +3 -2
  18. data/lib/vagrant-openstack-provider/client/neutron.rb +11 -1
  19. data/lib/vagrant-openstack-provider/client/nova.rb +49 -30
  20. data/lib/vagrant-openstack-provider/command/abstract_command.rb +10 -1
  21. data/lib/vagrant-openstack-provider/command/flavor_list.rb +1 -1
  22. data/lib/vagrant-openstack-provider/command/floatingip_list.rb +1 -1
  23. data/lib/vagrant-openstack-provider/command/image_list.rb +1 -1
  24. data/lib/vagrant-openstack-provider/command/main.rb +2 -1
  25. data/lib/vagrant-openstack-provider/command/network_list.rb +8 -2
  26. data/lib/vagrant-openstack-provider/command/reset.rb +21 -0
  27. data/lib/vagrant-openstack-provider/command/utils.rb +1 -1
  28. data/lib/vagrant-openstack-provider/command/volume_list.rb +1 -1
  29. data/lib/vagrant-openstack-provider/config.rb +16 -1
  30. data/lib/vagrant-openstack-provider/config_resolver.rb +262 -0
  31. data/lib/vagrant-openstack-provider/errors.rb +40 -0
  32. data/lib/vagrant-openstack-provider/plugin.rb +3 -3
  33. data/lib/vagrant-openstack-provider/utils.rb +21 -0
  34. data/lib/vagrant-openstack-provider/version.rb +1 -1
  35. data/locales/en.yml +35 -1
  36. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +121 -368
  37. data/spec/vagrant-openstack-provider/action/delete_server_spec.rb +54 -0
  38. data/spec/vagrant-openstack-provider/action/message_spec.rb +34 -0
  39. data/spec/vagrant-openstack-provider/action/read_ssh_info_spec.rb +34 -17
  40. data/spec/vagrant-openstack-provider/action/read_state_spec.rb +70 -0
  41. data/spec/vagrant-openstack-provider/action/resume_server_spec.rb +50 -0
  42. data/spec/vagrant-openstack-provider/action/start_server_spec.rb +50 -0
  43. data/spec/vagrant-openstack-provider/action/stop_server_spec.rb +50 -0
  44. data/spec/vagrant-openstack-provider/action/suspend_server_spec.rb +50 -0
  45. data/spec/vagrant-openstack-provider/action/sync_folders_spec.rb +155 -0
  46. data/spec/vagrant-openstack-provider/action/wait_accessible_spec.rb +68 -0
  47. data/spec/vagrant-openstack-provider/action/wait_active_spec.rb +47 -0
  48. data/spec/vagrant-openstack-provider/action/wait_stop_spec.rb +47 -0
  49. data/spec/vagrant-openstack-provider/action_spec.rb +121 -0
  50. data/spec/vagrant-openstack-provider/client/cinder_spec.rb +1 -1
  51. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +1 -1
  52. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +37 -1
  53. data/spec/vagrant-openstack-provider/client/nova_spec.rb +60 -7
  54. data/spec/vagrant-openstack-provider/client/utils_spec.rb +1 -1
  55. data/spec/vagrant-openstack-provider/command/flavor_list_spec.rb +44 -0
  56. data/spec/vagrant-openstack-provider/command/floatingip_list_spec.rb +19 -2
  57. data/spec/vagrant-openstack-provider/command/image_list_spec.rb +48 -0
  58. data/spec/vagrant-openstack-provider/command/network_list_spec.rb +67 -0
  59. data/spec/vagrant-openstack-provider/command/reset_spec.rb +25 -0
  60. data/spec/vagrant-openstack-provider/command/volume_list_spec.rb +10 -2
  61. data/spec/vagrant-openstack-provider/config_resolver_spec.rb +680 -0
  62. data/spec/vagrant-openstack-provider/config_spec.rb +15 -1
  63. data/spec/vagrant-openstack-provider/spec_helper.rb +3 -0
  64. data/spec/vagrant-openstack-provider/utils_spec.rb +103 -0
  65. data/vagrant-openstack-provider.gemspec +4 -2
  66. metadata +78 -11
  67. data/Appraisals +0 -13
  68. data/gemfiles/oldest_current.gemfile +0 -20
@@ -6,7 +6,7 @@ module VagrantPlugins
6
6
  class AbstractCommand < Vagrant.plugin('2', :command)
7
7
  def initialize(argv, env)
8
8
  @env = env
9
- super(argv, env)
9
+ super(normalize_args(argv), env)
10
10
  end
11
11
 
12
12
  def execute(name)
@@ -22,6 +22,15 @@ module VagrantPlugins
22
22
  @env.ui.info('')
23
23
  end
24
24
 
25
+ #
26
+ # Before Vagrant 1.5, args list ends with an extra arg '--'. It removes it if present.
27
+ #
28
+ def normalize_args(args)
29
+ return args if args.nil?
30
+ args.pop if args.size > 0 && args.last == '--'
31
+ args
32
+ end
33
+
25
34
  def cmd(_name, _argv, _env)
26
35
  fail 'Command not implemented. \'cmd\' method must be overridden in all subclasses'
27
36
  end
@@ -11,7 +11,7 @@ module VagrantPlugins
11
11
  I18n.t('vagrant_openstack.command.flavor_list_synopsis')
12
12
  end
13
13
  def cmd(name, argv, env)
14
- fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0 || argv == ['--']
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
15
15
  flavors = env[:openstack_client].nova.get_all_flavors(env)
16
16
 
17
17
  rows = []
@@ -11,7 +11,7 @@ module VagrantPlugins
11
11
  I18n.t('vagrant_openstack.command.flaotingip_list_synopsis')
12
12
  end
13
13
  def cmd(name, argv, env)
14
- fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0 || argv == ['--']
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
15
15
 
16
16
  floating_ip_pools = env[:openstack_client].nova.get_floating_ip_pools(env)
17
17
  floating_ips = env[:openstack_client].nova.get_floating_ips(env)
@@ -11,7 +11,7 @@ module VagrantPlugins
11
11
  I18n.t('vagrant_openstack.command.image_list_synopsis')
12
12
  end
13
13
  def cmd(name, argv, env)
14
- fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0 || argv == ['--']
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
15
15
  images = env[:openstack_client].nova.get_all_images(env)
16
16
  display_item_list(env, images)
17
17
  end
@@ -6,7 +6,8 @@ module VagrantPlugins
6
6
  { name: :'flavor-list', file: 'flavor_list', clazz: 'FlavorList' },
7
7
  { name: :'network-list', file: 'network_list', clazz: 'NetworkList' },
8
8
  { name: :'floatingip-list', file: 'floatingip_list', clazz: 'FloatingIpList' },
9
- { name: :'volume-list', file: 'volume_list', clazz: 'VolumeList' }
9
+ { name: :'volume-list', file: 'volume_list', clazz: 'VolumeList' },
10
+ { name: :'reset', file: 'reset', clazz: 'Reset' }
10
11
  ]
11
12
 
12
13
  class Main < Vagrant.plugin('2', :command)
@@ -11,8 +11,14 @@ module VagrantPlugins
11
11
  I18n.t('vagrant_openstack.command.network_list_synopsis')
12
12
  end
13
13
  def cmd(name, argv, env)
14
- fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0 || argv == ['--']
15
- flavors = env[:openstack_client].neutron.get_private_networks(env)
14
+ fail Errors::UnrecognizedArgForCommand, cmd: name, arg: argv[1] if argv.size > 1
15
+ if argv.size == 0
16
+ flavors = env[:openstack_client].neutron.get_private_networks(env)
17
+ elsif argv[0] == 'all'
18
+ flavors = env[:openstack_client].neutron.get_all_networks(env)
19
+ else
20
+ fail Errors::UnrecognizedArgForCommand, cmd: name, arg: argv[0]
21
+ end
16
22
  display_item_list(env, flavors)
17
23
  end
18
24
  end
@@ -0,0 +1,21 @@
1
+ require 'vagrant-openstack-provider/command/utils'
2
+ require 'vagrant-openstack-provider/command/abstract_command'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Command
7
+ class Reset < AbstractCommand
8
+ include VagrantPlugins::Openstack::Command::Utils
9
+
10
+ def self.synopsis
11
+ I18n.t('vagrant_openstack.command.reset')
12
+ end
13
+ def cmd(name, argv, env)
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
15
+ FileUtils.remove_dir("#{env[:machine].data_dir}")
16
+ env[:ui].info 'Vagrant OpenStack Provider has been reset'
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -14,7 +14,7 @@ module VagrantPlugins
14
14
 
15
15
  def display_table(env, headers, rows)
16
16
  table = Terminal::Table.new headings: headers, rows: rows
17
- env[:ui].info("\n#{table}\n")
17
+ env[:ui].info("\n#{table}")
18
18
  end
19
19
  end
20
20
  end
@@ -11,7 +11,7 @@ module VagrantPlugins
11
11
  I18n.t('vagrant_openstack.command.volume_list_synopsis')
12
12
  end
13
13
  def cmd(name, argv, env)
14
- fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0 || argv == ['--']
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
15
15
  volumes = env[:openstack_client].cinder.get_all_volumes(env)
16
16
 
17
17
  rows = []
@@ -136,6 +136,11 @@ module VagrantPlugins
136
136
  # @return [Hash]
137
137
  attr_accessor :metadata
138
138
 
139
+ # Flag to enable/disable all SSH actions (to use for instance on private networks)
140
+ #
141
+ # @return [Boolean]
142
+ attr_accessor :ssh_disabled
143
+
139
144
  def initialize
140
145
  @password = UNSET_VALUE
141
146
  @openstack_compute_url = UNSET_VALUE
@@ -164,6 +169,7 @@ module VagrantPlugins
164
169
  @security_groups = UNSET_VALUE
165
170
  @user_data = UNSET_VALUE
166
171
  @metadata = UNSET_VALUE
172
+ @ssh_disabled = UNSET_VALUE
167
173
  end
168
174
 
169
175
  # rubocop:disable Style/CyclomaticComplexity
@@ -191,6 +197,7 @@ module VagrantPlugins
191
197
  @security_groups = nil if @security_groups == UNSET_VALUE
192
198
  @user_data = nil if @user_data == UNSET_VALUE
193
199
  @metadata = nil if @metadata == UNSET_VALUE
200
+ @ssh_disabled = false if @ssh_disabled == UNSET_VALUE
194
201
 
195
202
  # The SSH values by default are nil, and the top-level config
196
203
  # `config.ssh` values are used.
@@ -212,6 +219,7 @@ module VagrantPlugins
212
219
  errors << I18n.t('vagrant_openstack.config.username_required') unless @username
213
220
 
214
221
  validate_ssh_username(machine, errors)
222
+ validate_ssh_timeout(errors)
215
223
 
216
224
  if machine.config.ssh.private_key_path
217
225
  puts I18n.t('vagrant_openstack.config.keypair_name_required').yellow unless @keypair_name || @public_key_path
@@ -231,12 +239,19 @@ module VagrantPlugins
231
239
  { 'Openstack Provider' => errors }
232
240
  end
233
241
 
242
+ private
243
+
234
244
  def validate_ssh_username(machine, errors)
235
245
  puts I18n.t('vagrant_openstack.config.ssh_username_deprecated').yellow if @ssh_username
236
246
  errors << I18n.t('vagrant_openstack.config.ssh_username_required') unless @ssh_username || machine.config.ssh.username
237
247
  end
238
248
 
239
- private
249
+ def validate_ssh_timeout(errors)
250
+ return if @ssh_timeout.nil? || @ssh_timeout == UNSET_VALUE
251
+ @ssh_timeout = Integer(@ssh_timeout) if @ssh_timeout.is_a? String
252
+ rescue ArgumentError
253
+ errors << I18n.t('vagrant_openstack.config.invalid_value_for_parameter', parameter: 'ssh_timeout', value: @ssh_timeout)
254
+ end
240
255
 
241
256
  def valid_uri?(value)
242
257
  uri = URI.parse value
@@ -0,0 +1,262 @@
1
+ module VagrantPlugins
2
+ module Openstack
3
+ class ConfigResolver
4
+ def initialize
5
+ @logger = Log4r::Logger.new('vagrant_openstack::action::config_resolver')
6
+ end
7
+
8
+ def resolve_ssh_port(env)
9
+ machine_config = env[:machine].config
10
+ return machine_config.ssh.port if machine_config.ssh.port
11
+ 22
12
+ end
13
+
14
+ def resolve_flavor(env)
15
+ @logger.info 'Resolving flavor'
16
+ config = env[:machine].provider_config
17
+ nova = env[:openstack_client].nova
18
+ env[:ui].info(I18n.t('vagrant_openstack.finding_flavor'))
19
+ flavors = nova.get_all_flavors(env)
20
+ @logger.info "Finding flavor matching name '#{config.flavor}'"
21
+ flavor = find_matching(flavors, config.flavor)
22
+ fail Errors::NoMatchingFlavor unless flavor
23
+ flavor
24
+ end
25
+
26
+ def resolve_image(env)
27
+ @logger.info 'Resolving image'
28
+ config = env[:machine].provider_config
29
+ return nil if config.image.nil?
30
+ nova = env[:openstack_client].nova
31
+ env[:ui].info(I18n.t('vagrant_openstack.finding_image'))
32
+ images = nova.get_all_images(env)
33
+ @logger.info "Finding image matching name '#{config.image}'"
34
+ image = find_matching(images, config.image)
35
+ fail Errors::NoMatchingImage unless image
36
+ image
37
+ end
38
+
39
+ def resolve_floating_ip(env)
40
+ config = env[:machine].provider_config
41
+ nova = env[:openstack_client].nova
42
+ return config.floating_ip if config.floating_ip
43
+ fail Errors::UnableToResolveFloatingIP unless config.floating_ip_pool
44
+ nova.get_all_floating_ips(env).each do |single|
45
+ return single.ip if single.pool == config.floating_ip_pool && single.instance_id.nil?
46
+ end unless config.floating_ip_pool_always_allocate
47
+ nova.allocate_floating_ip(env, config.floating_ip_pool).ip
48
+ end
49
+
50
+ def resolve_keypair(env)
51
+ config = env[:machine].provider_config
52
+ nova = env[:openstack_client].nova
53
+ return config.keypair_name if config.keypair_name
54
+ return nova.import_keypair_from_file(env, config.public_key_path) if config.public_key_path
55
+ generate_keypair(env)
56
+ end
57
+
58
+ def resolve_networks(env)
59
+ @logger.info 'Resolving network(s)'
60
+ config = env[:machine].provider_config
61
+ return [] if config.networks.nil? || config.networks.empty?
62
+ env[:ui].info(I18n.t('vagrant_openstack.finding_networks'))
63
+ return resolve_networks_without_network_service(env) unless env[:openstack_client].session.endpoints.key? :network
64
+
65
+ private_networks = env[:openstack_client].neutron.get_private_networks(env)
66
+ private_network_ids = private_networks.map { |v| v.id }
67
+
68
+ networks = []
69
+ config.networks.each do |network|
70
+ networks << resolve_network(network, private_networks, private_network_ids)
71
+ end
72
+ @logger.debug("Resolved networks : #{networks.to_json}")
73
+ networks
74
+ end
75
+
76
+ def resolve_volume_boot(env)
77
+ @logger.info 'Resolving image'
78
+ config = env[:machine].provider_config
79
+ return nil if config.volume_boot.nil?
80
+ return resolve_volume_without_volume_service(env, config.volume_boot, 'vda') unless env[:openstack_client].session.endpoints.key? :volume
81
+
82
+ volume_list = env[:openstack_client].cinder.get_all_volumes(env)
83
+ volume_ids = volume_list.map { |v| v.id }
84
+
85
+ @logger.debug(volume_list)
86
+
87
+ volume = resolve_volume(config.volume_boot, volume_list, volume_ids)
88
+ device = volume[:device].nil? ? 'vda' : volume[:device]
89
+
90
+ { id: volume[:id], device: device }
91
+ end
92
+
93
+ def resolve_volumes(env)
94
+ @logger.info 'Resolving volume(s)'
95
+ config = env[:machine].provider_config
96
+ return [] if config.volumes.nil? || config.volumes.empty?
97
+ env[:ui].info(I18n.t('vagrant_openstack.finding_volumes'))
98
+ return resolve_volumes_without_volume_service(env) unless env[:openstack_client].session.endpoints.key? :volume
99
+
100
+ volume_list = env[:openstack_client].cinder.get_all_volumes(env)
101
+ volume_ids = volume_list.map { |v| v.id }
102
+
103
+ @logger.debug(volume_list)
104
+
105
+ volumes = []
106
+ config.volumes.each do |volume|
107
+ volumes << resolve_volume(volume, volume_list, volume_ids)
108
+ end
109
+ @logger.debug("Resolved volumes : #{volumes.to_json}")
110
+ volumes
111
+ end
112
+
113
+ def resolve_ssh_username(env)
114
+ config = env[:machine].provider_config
115
+ machine_config = env[:machine].config
116
+ return machine_config.ssh.username if machine_config.ssh.username
117
+ return config.ssh_username if config.ssh_username
118
+ fail Errors::NoMatchingSshUsername
119
+ end
120
+
121
+ def resolve_security_groups(env)
122
+ groups = []
123
+ env[:machine].provider_config.security_groups.each do |group|
124
+ case group
125
+ when String
126
+ groups << { name: group }
127
+ when Hash
128
+ groups << group
129
+ end
130
+ end unless env[:machine].provider_config.security_groups.nil?
131
+ groups
132
+ end
133
+
134
+ private
135
+
136
+ def generate_keypair(env)
137
+ key = SSHKey.generate
138
+ nova = env[:openstack_client].nova
139
+ generated_keyname = nova.import_keypair(env, key.ssh_public_key)
140
+ file_path = "#{env[:machine].data_dir}/#{generated_keyname}"
141
+ File.write(file_path, key.private_key)
142
+ File.chmod(0600, file_path)
143
+ generated_keyname
144
+ end
145
+
146
+ def resolve_networks_without_network_service(env)
147
+ config = env[:machine].provider_config
148
+ networks = []
149
+ config.networks.each do |network|
150
+ case network
151
+ when String
152
+ env[:ui].info(I18n.t('vagrant_openstack.warn_network_identifier_is_assumed_to_be_an_id', network: network))
153
+ networks << { uuid: network }
154
+ when Hash
155
+ fail Errors::ConflictNetworkNameId, network: network if network.key?(:name) && network.key?(:id)
156
+ fail Errors::NetworkServiceUnavailable if network.key? :name
157
+ if network.key?(:address)
158
+ networks << { uuid: network[:id], fixed_ip: network[:address] }
159
+ else
160
+ networks << { uuid: network[:id] }
161
+ end
162
+ end
163
+ end
164
+ networks
165
+ end
166
+
167
+ def resolve_network(network, network_list, network_ids)
168
+ return resolve_network_from_string(network, network_list) if network.is_a? String
169
+ return resolve_network_from_hash(network, network_list, network_ids) if network.is_a? Hash
170
+ fail Errors::InvalidNetworkObject, network: network
171
+ end
172
+
173
+ def resolve_network_from_string(network, network_list)
174
+ found_network = find_matching(network_list, network)
175
+ fail Errors::UnresolvedNetwork, network: network if found_network.nil?
176
+ { uuid: found_network.id }
177
+ end
178
+
179
+ def resolve_network_from_hash(network, network_list, network_ids)
180
+ if network.key?(:id)
181
+ fail Errors::ConflictNetworkNameId, network: network if network.key?(:name)
182
+ network_id = network[:id]
183
+ fail Errors::UnresolvedNetworkId, id: network_id unless network_ids.include? network_id
184
+ elsif network.key?(:name)
185
+ network_list.each do |v|
186
+ next unless v.name.eql? network[:name]
187
+ fail Errors::MultipleNetworkName, name: network[:name] unless network_id.nil?
188
+ network_id = v.id
189
+ end
190
+ fail Errors::UnresolvedNetworkName, name: network[:name] unless network_ids.include? network_id
191
+ else
192
+ fail Errors::ConflictNetworkNameId, network: network
193
+ end
194
+ return { uuid: network_id, fixed_ip: network[:address] } if network.key?(:address)
195
+ { uuid: network_id }
196
+ end
197
+
198
+ def resolve_volumes_without_volume_service(env)
199
+ env[:machine].provider_config.volumes.map { |volume| resolve_volume_without_volume_service(env, volume) }
200
+ end
201
+
202
+ def resolve_volume_without_volume_service(env, volume, default_device = nil)
203
+ case volume
204
+ when String
205
+ env[:ui].info(I18n.t('vagrant_openstack.warn_volume_identifier_is_assumed_to_be_an_id', volume: volume))
206
+ return { id: volume, device: default_device }
207
+ when Hash
208
+ fail Errors::ConflictVolumeNameId, volume: volume if volume.key?(:name) && volume.key?(:id)
209
+ fail Errors::VolumeServiceUnavailable if volume.key? :name
210
+ return { id: volume[:id], device: volume[:device] || default_device }
211
+ end
212
+ fail Errors::InvalidVolumeObject, volume: volume
213
+ end
214
+
215
+ def resolve_volume(volume, volume_list, volume_ids)
216
+ return resolve_volume_from_string(volume, volume_list) if volume.is_a? String
217
+ return resolve_volume_from_hash(volume, volume_list, volume_ids) if volume.is_a? Hash
218
+ fail Errors::InvalidVolumeObject, volume: volume
219
+ end
220
+
221
+ def resolve_volume_from_string(volume, volume_list)
222
+ found_volume = find_matching(volume_list, volume)
223
+ fail Errors::UnresolvedVolume, volume: volume if found_volume.nil?
224
+ { id: found_volume.id, device: nil }
225
+ end
226
+
227
+ def resolve_volume_from_hash(volume, volume_list, volume_ids)
228
+ device = nil
229
+ device = volume[:device] if volume.key?(:device)
230
+ if volume.key?(:id)
231
+ fail Errors::ConflictVolumeNameId, volume: volume if volume.key?(:name)
232
+ volume_id = volume[:id]
233
+ fail Errors::UnresolvedVolumeId, id: volume_id unless volume_ids.include? volume_id
234
+ elsif volume.key?(:name)
235
+ volume_list.each do |v|
236
+ next unless v.name.eql? volume[:name]
237
+ fail Errors::MultipleVolumeName, name: volume[:name] unless volume_id.nil?
238
+ volume_id = v.id
239
+ end
240
+ fail Errors::UnresolvedVolumeName, name: volume[:name] unless volume_ids.include? volume_id
241
+ else
242
+ fail Errors::ConflictVolumeNameId, volume: volume
243
+ end
244
+ { id: volume_id, device: device }
245
+ end
246
+
247
+ # This method finds a matching _thing_ in a collection of
248
+ # _things_. This works matching if the ID or NAME equals to
249
+ # `name`. Or, if `name` is a regexp, a partial match is chosen
250
+ # as well.
251
+ def find_matching(collection, name)
252
+ collection.each do |single|
253
+ return single if single.id == name
254
+ return single if single.name == name
255
+ return single if name.is_a?(Regexp) && name =~ single.name
256
+ end
257
+ @logger.error "Element '#{name}' not found in collection #{collection}"
258
+ nil
259
+ end
260
+ end
261
+ end
262
+ end
@@ -52,6 +52,10 @@ module VagrantPlugins
52
52
  error_key(:no_arg_required_for_command)
53
53
  end
54
54
 
55
+ class UnrecognizedArgForCommand < VagrantOpenstackError
56
+ error_key(:unrecognized_arg_for_command)
57
+ end
58
+
55
59
  class UnableToResolveFloatingIP < VagrantOpenstackError
56
60
  error_key(:unable_to_resolve_floating_ip)
57
61
  end
@@ -64,6 +68,30 @@ module VagrantPlugins
64
68
  error_key(:unable_to_resolve_ssh_key)
65
69
  end
66
70
 
71
+ class InvalidNetworkObject < VagrantOpenstackError
72
+ error_key(:invalid_network_format)
73
+ end
74
+
75
+ class UnresolvedNetwork < VagrantOpenstackError
76
+ error_key(:unresolved_network)
77
+ end
78
+
79
+ class UnresolvedNetworkId < VagrantOpenstackError
80
+ error_key(:unresolved_network_id)
81
+ end
82
+
83
+ class UnresolvedNetworkName < VagrantOpenstackError
84
+ error_key(:unresolved_network_name)
85
+ end
86
+
87
+ class ConflictNetworkNameId < VagrantOpenstackError
88
+ error_key(:conflict_network_name_id)
89
+ end
90
+
91
+ class MultipleNetworkName < VagrantOpenstackError
92
+ error_key(:multiple_network_name)
93
+ end
94
+
67
95
  class InvalidVolumeObject < VagrantOpenstackError
68
96
  error_key(:invalid_volume_format)
69
97
  end
@@ -99,6 +127,18 @@ module VagrantPlugins
99
127
  class NoMatchingSshUsername < VagrantOpenstackError
100
128
  error_key(:ssh_username_missing)
101
129
  end
130
+
131
+ class InstanceNotFound < VagrantOpenstackError
132
+ error_key(:instance_not_found)
133
+ end
134
+
135
+ class NetworkServiceUnavailable < VagrantOpenstackError
136
+ error_key(:nerwork_service_unavailable)
137
+ end
138
+
139
+ class VolumeServiceUnavailable < VagrantOpenstackError
140
+ error_key(:volume_service_unavailable)
141
+ end
102
142
  end
103
143
  end
104
144
  end