vagrant-openstack-provider 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -2
- data/CHANGELOG.md +22 -0
- data/Gemfile +8 -15
- data/Vagrantfile +12 -10
- data/gemfiles/latest_stable.gemfile +6 -16
- data/gemfiles/minimal_release.gemfile +10 -0
- data/gemfiles/previous_release.gemfile +6 -16
- data/lib/vagrant-openstack-provider/action/connect_openstack.rb +2 -1
- data/lib/vagrant-openstack-provider/action/create_server.rb +40 -248
- data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +30 -29
- data/lib/vagrant-openstack-provider/action/sync_folders.rb +19 -9
- data/lib/vagrant-openstack-provider/action/wait_accessible.rb +58 -0
- data/lib/vagrant-openstack-provider/action/wait_active.rb +5 -3
- data/lib/vagrant-openstack-provider/action/wait_stop.rb +5 -3
- data/lib/vagrant-openstack-provider/action.rb +19 -11
- data/lib/vagrant-openstack-provider/client/http_utils.rb +3 -2
- data/lib/vagrant-openstack-provider/client/neutron.rb +11 -1
- data/lib/vagrant-openstack-provider/client/nova.rb +49 -30
- data/lib/vagrant-openstack-provider/command/abstract_command.rb +10 -1
- data/lib/vagrant-openstack-provider/command/flavor_list.rb +1 -1
- data/lib/vagrant-openstack-provider/command/floatingip_list.rb +1 -1
- data/lib/vagrant-openstack-provider/command/image_list.rb +1 -1
- data/lib/vagrant-openstack-provider/command/main.rb +2 -1
- data/lib/vagrant-openstack-provider/command/network_list.rb +8 -2
- data/lib/vagrant-openstack-provider/command/reset.rb +21 -0
- data/lib/vagrant-openstack-provider/command/utils.rb +1 -1
- data/lib/vagrant-openstack-provider/command/volume_list.rb +1 -1
- data/lib/vagrant-openstack-provider/config.rb +16 -1
- data/lib/vagrant-openstack-provider/config_resolver.rb +262 -0
- data/lib/vagrant-openstack-provider/errors.rb +40 -0
- data/lib/vagrant-openstack-provider/plugin.rb +3 -3
- data/lib/vagrant-openstack-provider/utils.rb +21 -0
- data/lib/vagrant-openstack-provider/version.rb +1 -1
- data/locales/en.yml +35 -1
- data/spec/vagrant-openstack-provider/action/create_server_spec.rb +121 -368
- data/spec/vagrant-openstack-provider/action/delete_server_spec.rb +54 -0
- data/spec/vagrant-openstack-provider/action/message_spec.rb +34 -0
- data/spec/vagrant-openstack-provider/action/read_ssh_info_spec.rb +34 -17
- data/spec/vagrant-openstack-provider/action/read_state_spec.rb +70 -0
- data/spec/vagrant-openstack-provider/action/resume_server_spec.rb +50 -0
- data/spec/vagrant-openstack-provider/action/start_server_spec.rb +50 -0
- data/spec/vagrant-openstack-provider/action/stop_server_spec.rb +50 -0
- data/spec/vagrant-openstack-provider/action/suspend_server_spec.rb +50 -0
- data/spec/vagrant-openstack-provider/action/sync_folders_spec.rb +155 -0
- data/spec/vagrant-openstack-provider/action/wait_accessible_spec.rb +68 -0
- data/spec/vagrant-openstack-provider/action/wait_active_spec.rb +47 -0
- data/spec/vagrant-openstack-provider/action/wait_stop_spec.rb +47 -0
- data/spec/vagrant-openstack-provider/action_spec.rb +121 -0
- data/spec/vagrant-openstack-provider/client/cinder_spec.rb +1 -1
- data/spec/vagrant-openstack-provider/client/keystone_spec.rb +1 -1
- data/spec/vagrant-openstack-provider/client/neutron_spec.rb +37 -1
- data/spec/vagrant-openstack-provider/client/nova_spec.rb +60 -7
- data/spec/vagrant-openstack-provider/client/utils_spec.rb +1 -1
- data/spec/vagrant-openstack-provider/command/flavor_list_spec.rb +44 -0
- data/spec/vagrant-openstack-provider/command/floatingip_list_spec.rb +19 -2
- data/spec/vagrant-openstack-provider/command/image_list_spec.rb +48 -0
- data/spec/vagrant-openstack-provider/command/network_list_spec.rb +67 -0
- data/spec/vagrant-openstack-provider/command/reset_spec.rb +25 -0
- data/spec/vagrant-openstack-provider/command/volume_list_spec.rb +10 -2
- data/spec/vagrant-openstack-provider/config_resolver_spec.rb +680 -0
- data/spec/vagrant-openstack-provider/config_spec.rb +15 -1
- data/spec/vagrant-openstack-provider/spec_helper.rb +3 -0
- data/spec/vagrant-openstack-provider/utils_spec.rb +103 -0
- data/vagrant-openstack-provider.gemspec +4 -2
- metadata +78 -11
- data/Appraisals +0 -13
- 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
|
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
|
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
|
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::
|
15
|
-
|
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
|
@@ -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
|
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
|
-
|
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
|