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,8 +6,8 @@ end
|
|
6
6
|
|
7
7
|
# This is a sanity check to make sure no one is attempting to install
|
8
8
|
# this into an early Vagrant version.
|
9
|
-
if Vagrant::VERSION < '1.
|
10
|
-
fail 'Openstack Cloud provider is only compatible with Vagrant 1.
|
9
|
+
if Vagrant::VERSION < '1.4.0'
|
10
|
+
fail 'Openstack Cloud provider is only compatible with Vagrant 1.4+'
|
11
11
|
end
|
12
12
|
|
13
13
|
module VagrantPlugins
|
@@ -23,7 +23,7 @@ module VagrantPlugins
|
|
23
23
|
Config
|
24
24
|
end
|
25
25
|
|
26
|
-
provider(:openstack) do
|
26
|
+
provider(:openstack, box_optional: true) do
|
27
27
|
# Setup some things
|
28
28
|
Openstack.init_i18n
|
29
29
|
Openstack.init_logging
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module Openstack
|
3
|
+
class Utils
|
4
|
+
def initialize
|
5
|
+
@logger = Log4r::Logger.new('vagrant_openstack::action::config_resolver')
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_ip_address(env)
|
9
|
+
return env[:machine].provider_config.floating_ip unless env[:machine].provider_config.floating_ip.nil?
|
10
|
+
details = env[:openstack_client].nova.get_server_details(env, env[:machine].id)
|
11
|
+
details['addresses'].each do |network|
|
12
|
+
network[1].each do |network_detail|
|
13
|
+
return network_detail['addr'] if network_detail['OS-EXT-IPS:type'] == 'floating'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
return details['addresses'].first[1][0]['addr'] if details['addresses'].size == 1 && details['addresses'].first[1].size == 1
|
17
|
+
fail Errors::UnableToResolveIP
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/locales/en.yml
CHANGED
@@ -44,6 +44,10 @@ en:
|
|
44
44
|
Warning! The Openstack provider doesn't support any of the Vagrant
|
45
45
|
high-level network configurations (`config.vm.network`). They
|
46
46
|
will be silently ignored.
|
47
|
+
warn_network_identifier_is_assumed_to_be_an_id: |-
|
48
|
+
As Neutron endpoint is not available, the identifier '%{network}' is assumed to be an id (not a name).
|
49
|
+
warn_volume_identifier_is_assumed_to_be_an_id: |-
|
50
|
+
As Cinder endpoint is not available, the identifier '%{volume}' is assumed to be an id (not a name).
|
47
51
|
|
48
52
|
config:
|
49
53
|
password_required: |-
|
@@ -68,6 +72,8 @@ en:
|
|
68
72
|
standard vagrant configuration option `config.ssh.username` instead
|
69
73
|
ssh_username_required: |-
|
70
74
|
vagrant standard configuration option `ssh.username` is required
|
75
|
+
invalid_value_for_parameter: |-
|
76
|
+
Invalid value '%{value}' for parameter '%{parameter}'
|
71
77
|
|
72
78
|
errors:
|
73
79
|
default: |-
|
@@ -108,12 +114,26 @@ en:
|
|
108
114
|
SSH server anavailable on instance %{host}. You should maybe increase the timeout value which currently is %{timeout} second(s).
|
109
115
|
no_arg_required_for_command: |-
|
110
116
|
Command '%{cmd}' does not required any argument.
|
117
|
+
unrecognized_arg_for_command: |-
|
118
|
+
Argument '%{arg}' unrecognized for command '%{cmd}'.
|
111
119
|
unable_to_resolve_floating_ip: |-
|
112
120
|
Vagrant was unable to resolve a floating ip to communicate with your OpenStack instance. Please specify in your Vagrantfile either `floating_ip` or `floating_ip_pool`.
|
113
121
|
unable_to_resolve_ip: |-
|
114
122
|
Vagrant was unable to resolve a valid ip to ssh on your OpenStack instance.
|
115
123
|
unable_to_resolve_ssh_key: |-
|
116
124
|
Vagrant was unable to resolve a valid ssh key to connect to your OpenStack instance. Please specify in your Vagrantfile either `public_key_path` or `keypair_name`.
|
125
|
+
invalid_network_format: |-
|
126
|
+
Network '%{network}' is not valid.
|
127
|
+
unresolved_network: |-
|
128
|
+
No matching network with id or name '%{network}'
|
129
|
+
unresolved_network_id: |-
|
130
|
+
No matching network with id '%{id}'
|
131
|
+
unresolved_network_name: |-
|
132
|
+
No matching network with name '%{name}'
|
133
|
+
conflict_network_name_id: |-
|
134
|
+
One (and only one) of 'id' or 'name' must be specified in network definition : %{network}
|
135
|
+
multiple_network_name: |-
|
136
|
+
More than one network exists with name '%{name}'. In this case you can't use name in network definition. Please, use id instead.
|
117
137
|
invalid_volume_format: |-
|
118
138
|
Volume '%{volume}' is not valid.
|
119
139
|
unresolved_volume: |-
|
@@ -125,13 +145,25 @@ en:
|
|
125
145
|
conflict_volume_name_id: |-
|
126
146
|
One (and only one) of 'id' or 'name' must be specified in volume definition : %{volume}
|
127
147
|
multiple_volume_name: |-
|
128
|
-
More than one volume exists with name '%{name}'. In
|
148
|
+
More than one volume exists with name '%{name}'. In this case you can't use name in volume definition. Please, use id instead.
|
129
149
|
missing_boot_option: |-
|
130
150
|
Either 'image' or 'volume_boot' configuration must be provided
|
131
151
|
conflict_boot_option: |-
|
132
152
|
Only one of 'image' and 'volume_boot' configuration must be provided
|
133
153
|
ssh_username_missing: |-
|
134
154
|
Vagrant was unable to resolve which ssh username to use to connect to the machine. Please provide config parameter `ssh.username`
|
155
|
+
instance_not_found: |-
|
156
|
+
Vagrant was unable to find the OpenStack instance used for your vagrant machine.
|
157
|
+
This can happen when the instance has been deleted via OpenStack APIs or OpenStack
|
158
|
+
Dashboard instead of using vagrant commands.
|
159
|
+
We recommend using the command `vagrant openstack reset` to reset
|
160
|
+
vagrant to a clear state
|
161
|
+
nerwork_service_unavailable: |-
|
162
|
+
Neutron service endpoint is not available, thus there is not way to retrieve
|
163
|
+
network id from its name. You have to provide only ids in your Vagrantfile.
|
164
|
+
volume_service_unavailable: |-
|
165
|
+
Cinder service endpoint is not available, thus there is not way to retrieve
|
166
|
+
volume id from its name. You have to provide only ids in your Vagrantfile.
|
135
167
|
|
136
168
|
states:
|
137
169
|
short_active: |-
|
@@ -233,3 +265,5 @@ en:
|
|
233
265
|
List floating IP and floating IP pools
|
234
266
|
volume_list_synopsis : |-
|
235
267
|
List existing volumes
|
268
|
+
reset : |-
|
269
|
+
Reset Vagrant OpenStack provider to a clear state
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'vagrant-openstack-provider/spec_helper'
|
2
|
+
require 'ostruct'
|
2
3
|
require 'sshkey'
|
3
4
|
|
4
5
|
include VagrantPlugins::Openstack::Action
|
@@ -6,25 +7,18 @@ include VagrantPlugins::Openstack::HttpUtils
|
|
6
7
|
include VagrantPlugins::Openstack::Domain
|
7
8
|
|
8
9
|
describe VagrantPlugins::Openstack::Action::CreateServer do
|
9
|
-
include FakeFS::SpecHelpers
|
10
10
|
|
11
11
|
let(:config) do
|
12
12
|
double('config').tap do |config|
|
13
|
-
config.stub(:openstack_auth_url) { 'http://keystoneAuthV2' }
|
14
|
-
config.stub(:openstack_compute_url) { nil }
|
15
|
-
config.stub(:openstack_network_url) { nil }
|
16
13
|
config.stub(:tenant_name) { 'testTenant' }
|
17
|
-
config.stub(:username) { 'username' }
|
18
|
-
config.stub(:password) { 'password' }
|
19
14
|
config.stub(:server_name) { 'testName' }
|
20
|
-
config.stub(:
|
21
|
-
config.stub(:
|
22
|
-
config.stub(:
|
23
|
-
config.stub(:
|
24
|
-
config.stub(:
|
25
|
-
config.stub(:
|
26
|
-
config.stub(:
|
27
|
-
config.stub(:volumes) { nil }
|
15
|
+
config.stub(:image) { 'ubuntu' }
|
16
|
+
config.stub(:volume_boot) { nil }
|
17
|
+
config.stub(:availability_zone) { nil }
|
18
|
+
config.stub(:scheduler_hints) { nil }
|
19
|
+
config.stub(:security_groups) { nil }
|
20
|
+
config.stub(:user_data) { nil }
|
21
|
+
config.stub(:metadata) { nil }
|
28
22
|
end
|
29
23
|
end
|
30
24
|
|
@@ -35,13 +29,6 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
35
29
|
end
|
36
30
|
end
|
37
31
|
|
38
|
-
let(:ssh_key) do
|
39
|
-
double('ssh_key').tap do |key|
|
40
|
-
key.stub(:ssh_public_key) { 'ssh public key' }
|
41
|
-
key.stub(:private_key) { 'private key' }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
32
|
let(:flavor) do
|
46
33
|
double('flavor').tap do |flavor|
|
47
34
|
flavor.stub(:name) { 'flavor_name' }
|
@@ -49,36 +36,8 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
49
36
|
end
|
50
37
|
end
|
51
38
|
|
52
|
-
let(:neutron) do
|
53
|
-
double('neutron').tap do |neutron|
|
54
|
-
neutron.stub(:get_private_networks).with(anything) do
|
55
|
-
[Item.new('net-id-1', 'net-1'), Item.new('net-id-2', 'net-2')]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
39
|
let(:nova) do
|
61
|
-
double('nova')
|
62
|
-
nova.stub(:get_all_floating_ips).with(anything) do
|
63
|
-
[FloatingIP.new('80.81.82.83', 'pool-1', nil), FloatingIP.new('30.31.32.33', 'pool-2', '1234')]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
let(:cinder) do
|
69
|
-
double('cinder').tap do |cinder|
|
70
|
-
cinder.stub(:get_all_volumes).with(anything) do
|
71
|
-
[Volume.new('001', 'vol-01', '1', 'available', 'true', nil, nil),
|
72
|
-
Volume.new('002', 'vol-02', '2', 'available', 'true', nil, nil),
|
73
|
-
Volume.new('003', 'vol-03', '3', 'available', 'true', nil, nil),
|
74
|
-
Volume.new('004', 'vol-04', '4', 'available', 'false', nil, nil),
|
75
|
-
Volume.new('005', 'vol-05', '5', 'available', 'false', nil, nil),
|
76
|
-
Volume.new('006', 'vol-06', '6', 'available', 'false', nil, nil),
|
77
|
-
Volume.new('007', 'vol-07-08', '6', 'available', 'false', nil, nil),
|
78
|
-
Volume.new('008', 'vol-07-08', '6', 'available', 'false', nil, nil)]
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
40
|
+
double('nova')
|
82
41
|
end
|
83
42
|
|
84
43
|
let(:env) do
|
@@ -86,18 +45,47 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
86
45
|
env[:ui] = double('ui')
|
87
46
|
env[:ui].stub(:info).with(anything)
|
88
47
|
env[:machine] = double('machine')
|
89
|
-
env[:machine].
|
90
|
-
|
48
|
+
env[:machine] = OpenStruct.new.tap do |m|
|
49
|
+
m.provider_config = config
|
50
|
+
m.id = nil
|
51
|
+
end
|
91
52
|
env[:openstack_client] = double('openstack_client')
|
92
|
-
env[:openstack_client].stub(:neutron) { neutron }
|
93
53
|
env[:openstack_client].stub(:nova) { nova }
|
94
|
-
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
let(:resolver) do
|
58
|
+
double('resolver').tap do |r|
|
59
|
+
r.stub(:resolve_flavor).with(anything) do
|
60
|
+
Flavor.new('flavor-01', 'small', nil, nil, nil)
|
61
|
+
end
|
62
|
+
r.stub(:resolve_image).with(anything) do
|
63
|
+
Item.new('image-01', 'ubuntu')
|
64
|
+
end
|
65
|
+
r.stub(:resolve_volume_boot).with(anything) { 'ubuntu-drive' }
|
66
|
+
r.stub(:resolve_networks).with(anything) { 'net-001' }
|
67
|
+
r.stub(:resolve_volumes).with(anything) do
|
68
|
+
[{ id: 'vol-01', device: nil }]
|
69
|
+
end
|
70
|
+
r.stub(:resolve_keypair).with(anything) { 'key' }
|
71
|
+
r.stub(:resolve_floating_ip).with(anything) { '1.2.3.4' }
|
72
|
+
r.stub(:resolve_security_groups).with(anything) do
|
73
|
+
[{ name: 'group1' }, { name: 'group2' }]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:utils) do
|
79
|
+
double('utils').tap do |u|
|
80
|
+
u.stub(:get_ip_address) { '1.2.3.4' }
|
95
81
|
end
|
96
82
|
end
|
97
83
|
|
98
84
|
before :each do
|
99
85
|
CreateServer.send(:public, *CreateServer.private_instance_methods)
|
100
|
-
|
86
|
+
app = double('app')
|
87
|
+
app.stub(:call).with(anything)
|
88
|
+
@action = CreateServer.new(app, nil, resolver, utils)
|
101
89
|
end
|
102
90
|
|
103
91
|
describe 'call' do
|
@@ -115,6 +103,21 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
115
103
|
expect { @action.call(env) }.to raise_error Errors::MissingBootOption
|
116
104
|
end
|
117
105
|
end
|
106
|
+
context 'with full options' do
|
107
|
+
it 'works' do
|
108
|
+
allow(@action).to receive(:create_server).and_return('45678')
|
109
|
+
allow(@action).to receive(:assign_floating_ip).and_return('1.2.3.4')
|
110
|
+
allow(@action).to receive(:waiting_for_server_to_be_built)
|
111
|
+
allow(@action).to receive(:attach_volumes)
|
112
|
+
allow(@action).to receive(:waiting_for_server_to_be_reachable)
|
113
|
+
|
114
|
+
expect(@action).to receive(:waiting_for_server_to_be_built).with(env, '45678')
|
115
|
+
expect(@action).to receive(:assign_floating_ip).with(env, '45678').and_return('1.2.3.4')
|
116
|
+
expect(@action).to receive(:attach_volumes).with(env, '45678', [{ id: 'vol-01', device: nil }])
|
117
|
+
|
118
|
+
@action.call(env)
|
119
|
+
end
|
120
|
+
end
|
118
121
|
end
|
119
122
|
|
120
123
|
describe 'create_server' do
|
@@ -126,7 +129,7 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
126
129
|
flavor_ref: flavor.id,
|
127
130
|
image_ref: image.id,
|
128
131
|
volume_boot: nil,
|
129
|
-
networks: ['test-networks'],
|
132
|
+
networks: [{ uuid: 'test-networks-1' }, { uuid: 'test-networks-2', fixed_ip: '1.2.3.4' }],
|
130
133
|
keypair: 'test-keypair',
|
131
134
|
availability_zone: 'test-az',
|
132
135
|
scheduler_hints: 'test-sched-hints',
|
@@ -138,7 +141,7 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
138
141
|
options = {
|
139
142
|
flavor: flavor,
|
140
143
|
image: image,
|
141
|
-
networks: ['test-networks'],
|
144
|
+
networks: [{ uuid: 'test-networks-1' }, { uuid: 'test-networks-2', fixed_ip: '1.2.3.4' }],
|
142
145
|
volumes: [{ id: '001', device: :auto }, { id: '002', device: '/dev/vdc' }],
|
143
146
|
keypair_name: 'test-keypair',
|
144
147
|
availability_zone: 'test-az',
|
@@ -151,333 +154,83 @@ describe VagrantPlugins::Openstack::Action::CreateServer do
|
|
151
154
|
expect(@action.create_server(env, options)).to eq '1234'
|
152
155
|
end
|
153
156
|
end
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
[FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
|
171
|
-
FloatingIP.new('80.81.82.83', 'pool-1', nil)]
|
172
|
-
end
|
173
|
-
nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
|
174
|
-
FloatingIP.new('80.81.82.84', 'pool-1', nil)
|
175
|
-
end
|
176
|
-
config.stub(:floating_ip_pool) { 'pool-1' }
|
177
|
-
@action.resolve_floating_ip(env).should eq('80.81.82.84')
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
context 'with config.floating_pool_always_allocate false' do
|
182
|
-
it 'return one of the available ips' do
|
183
|
-
config.stub(:floating_ip_pool_always_allocate) { false }
|
184
|
-
nova.stub(:get_all_floating_ips).with(anything) do
|
185
|
-
[FloatingIP.new('80.81.82.84', 'pool-1', '1234'),
|
186
|
-
FloatingIP.new('80.81.82.83', 'pool-1', nil)]
|
187
|
-
end
|
188
|
-
config.stub(:floating_ip_pool) { 'pool-1' }
|
189
|
-
@action.resolve_floating_ip(env).should eq('80.81.82.83')
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
context 'if no ip in the same pool is available' do
|
195
|
-
it 'allocate a new floating_ip from the pool' do
|
196
|
-
nova.stub(:get_all_floating_ips).with(anything) do
|
197
|
-
[FloatingIP.new('80.81.82.83', 'pool-1', '1234')]
|
198
|
-
end
|
199
|
-
nova.stub(:allocate_floating_ip).with(env, 'pool-1') do
|
200
|
-
FloatingIP.new('80.81.82.84', 'pool-1', nil)
|
201
|
-
end
|
202
|
-
config.stub(:floating_ip_pool) { 'pool-1' }
|
203
|
-
@action.resolve_floating_ip(env).should eq('80.81.82.84')
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
context 'with neither floating_ip nor floating_ip_pool' do
|
209
|
-
context 'if any ip is not associated with an instance' do
|
210
|
-
it 'return the available ip in the list of floating ips' do
|
211
|
-
nova.stub(:get_all_floating_ips).with(anything) do
|
212
|
-
[FloatingIP.new('80.81.82.84', 'pool-1', '1234'), FloatingIP.new('80.81.82.83', 'pool-1', nil)]
|
213
|
-
end
|
214
|
-
@action.resolve_floating_ip(env).should eq('80.81.82.83')
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
context 'if all ips are already associated with an instance' do
|
219
|
-
it 'fails with an UnableToResolveFloatingIP error' do
|
220
|
-
nova.stub(:get_all_floating_ips).with(anything) do
|
221
|
-
[FloatingIP.new('80.81.82.84', 'pool-1', '1234'), FloatingIP.new('80.81.82.83', 'pool-1', '2345')]
|
222
|
-
end
|
223
|
-
expect { @action.resolve_floating_ip(env) }.to raise_error(Errors::UnableToResolveFloatingIP)
|
157
|
+
context 'with minimal configuration and a single network' do
|
158
|
+
it 'calls nova' do
|
159
|
+
config.stub(:server_name) { nil }
|
160
|
+
nova.stub(:create_server).with(
|
161
|
+
env,
|
162
|
+
name: nil,
|
163
|
+
flavor_ref: flavor.id,
|
164
|
+
image_ref: image.id,
|
165
|
+
volume_boot: nil,
|
166
|
+
networks: [{ uuid: 'test-networks-1' }],
|
167
|
+
keypair: 'test-keypair',
|
168
|
+
availability_zone: nil,
|
169
|
+
scheduler_hints: nil,
|
170
|
+
security_groups: [],
|
171
|
+
user_data: nil,
|
172
|
+
metadata: nil) do '1234'
|
224
173
|
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
describe 'resolve_keypair' do
|
230
|
-
context 'with keypair_name provided' do
|
231
|
-
it 'return the provided keypair_name' do
|
232
|
-
config.stub(:keypair_name) { 'my-keypair' }
|
233
|
-
@action.resolve_keypair(env).should eq('my-keypair')
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
context 'with keypair_name and public_key_path provided' do
|
238
|
-
it 'return the provided keypair_name' do
|
239
|
-
config.stub(:keypair_name) { 'my-keypair' }
|
240
|
-
config.stub(:public_key_path) { '/path/to/key' }
|
241
|
-
@action.resolve_keypair(env).should eq('my-keypair')
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
context 'with public_key_path provided' do
|
246
|
-
it 'return the keypair_name created into nova' do
|
247
|
-
config.stub(:public_key_path) { '/path/to/key' }
|
248
|
-
nova.stub(:import_keypair_from_file).with(env, '/path/to/key') { 'my-keypair-imported' }
|
249
|
-
@action.resolve_keypair(env).should eq('my-keypair-imported')
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
context 'with no keypair_name and no public_key_path provided' do
|
254
|
-
it 'generates a new keypair and return the keypair name imported into nova' do
|
255
|
-
config.stub(:keypair_name) { nil }
|
256
|
-
config.stub(:public_key_path) { nil }
|
257
|
-
@action.stub(:generate_keypair) { 'my-keypair-imported' }
|
258
|
-
@action.resolve_keypair(env).should eq('my-keypair-imported')
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
describe 'generate_keypair' do
|
264
|
-
it 'returns a generated keypair name imported into nova' do
|
265
|
-
nova.stub(:import_keypair) { 'my-keypair-imported' }
|
266
|
-
SSHKey.stub(:generate) { ssh_key }
|
267
|
-
File.should_receive(:write).with('/data/dir/my-keypair-imported', 'private key')
|
268
|
-
@action.generate_keypair(env).should eq('my-keypair-imported')
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
describe 'resolve_networks' do
|
273
|
-
|
274
|
-
context 'with only ids of existing networks' do
|
275
|
-
it 'return the ids array' do
|
276
|
-
config.stub(:networks) { %w(net-id-1 net-id-2) }
|
277
|
-
@action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
context 'with only names of existing networks' do
|
282
|
-
it 'return the ids array' do
|
283
|
-
config.stub(:networks) { %w(net-1 net-2) }
|
284
|
-
@action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
|
285
|
-
end
|
286
|
-
end
|
287
174
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
end
|
301
|
-
|
302
|
-
context 'with no network returned by neutron and no network specified in vagrant provider' do
|
303
|
-
it 'return the ids array' do
|
304
|
-
neutron.stub(:get_private_networks).with(anything) { [] }
|
305
|
-
config.stub(:networks) { [] }
|
306
|
-
@action.resolve_networks(env).should eq([])
|
307
|
-
end
|
308
|
-
end
|
175
|
+
options = {
|
176
|
+
flavor: flavor,
|
177
|
+
image: image,
|
178
|
+
networks: [{ uuid: 'test-networks-1' }],
|
179
|
+
volumes: [],
|
180
|
+
keypair_name: 'test-keypair',
|
181
|
+
availability_zone: nil,
|
182
|
+
scheduler_hints: nil,
|
183
|
+
security_groups: [],
|
184
|
+
user_data: nil,
|
185
|
+
metadata: nil
|
186
|
+
}
|
309
187
|
|
310
|
-
|
311
|
-
it 'return the ids array' do
|
312
|
-
neutron.stub(:get_private_networks).with(anything) { [] }
|
313
|
-
config.stub(:networks) { ['net-id-1'] }
|
314
|
-
expect { @action.resolve_networks(env) }.to raise_error
|
188
|
+
expect(@action.create_server(env, options)).to eq '1234'
|
315
189
|
end
|
316
190
|
end
|
317
|
-
|
318
191
|
end
|
319
192
|
|
320
|
-
describe '
|
321
|
-
context '
|
322
|
-
it '
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
end
|
327
|
-
|
328
|
-
context 'with string volume name' do
|
329
|
-
it 'returns normalized volume' do
|
330
|
-
config.stub(:volume_boot) { 'vol-01' }
|
331
|
-
expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
context 'with hash volume id' do
|
336
|
-
it 'returns normalized volume' do
|
337
|
-
config.stub(:volume_boot) { { id: '001' } }
|
338
|
-
expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
context 'with hash volume name' do
|
343
|
-
it 'returns normalized volume' do
|
344
|
-
config.stub(:volume_boot) { { name: 'vol-01' } }
|
345
|
-
expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
|
346
|
-
end
|
347
|
-
end
|
348
|
-
|
349
|
-
context 'with hash volume id and device' do
|
350
|
-
it 'returns normalized volume' do
|
351
|
-
config.stub(:volume_boot) { { id: '001', device: 'vdb' } }
|
352
|
-
expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vdb'
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
context 'with hash volume name and device' do
|
357
|
-
it 'returns normalized volume' do
|
358
|
-
config.stub(:volume_boot) { { name: 'vol-01', device: 'vdb' } }
|
359
|
-
expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vdb'
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
context 'with empty hash' do
|
364
|
-
it 'raises an error' do
|
365
|
-
config.stub(:volume_boot) { {} }
|
366
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictVolumeNameId)
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
context 'with invalid volume object' do
|
371
|
-
it 'raises an error' do
|
372
|
-
config.stub(:volume_boot) { 1 }
|
373
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::InvalidVolumeObject)
|
193
|
+
describe 'waiting_for_server_to_be_built' do
|
194
|
+
context 'when server is not yet active' do
|
195
|
+
it 'become active after one retry' do
|
196
|
+
nova.stub(:get_server_details).and_return({ 'status' => 'BUILD' }, { 'status' => 'ACTIVE' })
|
197
|
+
nova.should_receive(:get_server_details).with(env, 'server-01').exactly(2).times
|
198
|
+
@action.waiting_for_server_to_be_built(env, 'server-01', 1, 5)
|
374
199
|
end
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
config.stub(:volume_boot) { { id: 'not-exist' } }
|
380
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::UnresolvedVolumeId)
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
context 'with hash containing a bad name' do
|
385
|
-
it 'raises an error' do
|
386
|
-
config.stub(:volume_boot) { { name: 'not-exist' } }
|
387
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::UnresolvedVolumeName)
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
context 'with hash containing both id and name' do
|
392
|
-
it 'raises an error' do
|
393
|
-
config.stub(:volume_boot) { { id: '001', name: 'vol-01' } }
|
394
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::ConflictVolumeNameId)
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
context 'with hash containing a name matching more than one volume' do
|
399
|
-
it 'raises an error' do
|
400
|
-
config.stub(:volume_boot) { { name: 'vol-07-08' } }
|
401
|
-
expect { @action.resolve_volume_boot(env) }.to raise_error(Errors::MultipleVolumeName)
|
200
|
+
it 'timeout before the server become active' do
|
201
|
+
nova.stub(:get_server_details).and_return({ 'status' => 'BUILD' }, { 'status' => 'BUILD' })
|
202
|
+
nova.should_receive(:get_server_details).with(env, 'server-01').at_least(2).times
|
203
|
+
expect { @action.waiting_for_server_to_be_built(env, 'server-01', 1, 3) }.to raise_error Timeout::Error
|
402
204
|
end
|
403
205
|
end
|
404
206
|
end
|
405
207
|
|
406
|
-
describe '
|
407
|
-
context '
|
408
|
-
it '
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
{ name: 'vol-04', device: '/dev/vdy' },
|
415
|
-
{ name: 'vol-05' },
|
416
|
-
{ id: '006' }]
|
417
|
-
end
|
418
|
-
|
419
|
-
expect(@action.resolve_volumes(env)).to eq [{ id: '001', device: nil },
|
420
|
-
{ id: '002', device: nil },
|
421
|
-
{ id: '003', device: '/dev/vdz' },
|
422
|
-
{ id: '004', device: '/dev/vdy' },
|
423
|
-
{ id: '005', device: nil },
|
424
|
-
{ id: '006', device: nil }]
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
context 'with invalid volume object' do
|
429
|
-
it 'raises an error' do
|
430
|
-
config.stub(:volumes) { [1] }
|
431
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::InvalidVolumeObject)
|
432
|
-
end
|
433
|
-
end
|
434
|
-
|
435
|
-
context 'with string that is neither an id nor name matching a volume' do
|
436
|
-
it 'raises an error' do
|
437
|
-
config.stub(:volumes) { ['not-exist'] }
|
438
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolume)
|
439
|
-
end
|
440
|
-
end
|
441
|
-
|
442
|
-
context 'with hash containing a bad id' do
|
443
|
-
it 'raises an error' do
|
444
|
-
config.stub(:volumes) { [{ id: 'not-exist' }] }
|
445
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolumeId)
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
context 'with hash containing a bad name' do
|
450
|
-
it 'raises an error' do
|
451
|
-
config.stub(:volumes) { [{ name: 'not-exist' }] }
|
452
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::UnresolvedVolumeName)
|
208
|
+
describe 'assign_floating_ip' do
|
209
|
+
context 'When resolve correctly floating ip' do
|
210
|
+
it 'calls nova to assign floating ip' do
|
211
|
+
resolver.stub(:resolve_floating_ip).and_return '1.2.3.4'
|
212
|
+
nova.stub(:add_floating_ip)
|
213
|
+
expect(resolver).to receive(:resolve_floating_ip).with(env)
|
214
|
+
expect(nova).to receive(:add_floating_ip).with(env, 'server-01', '1.2.3.4')
|
215
|
+
@action.assign_floating_ip(env, 'server-01')
|
453
216
|
end
|
454
217
|
end
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
expect
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
context 'with hash containing both id and name' do
|
464
|
-
it 'raises an error' do
|
465
|
-
config.stub(:volumes) { [{ id: '001', name: 'vol-01' }] }
|
466
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictVolumeNameId)
|
218
|
+
context 'When unable to resolve floating ip' do
|
219
|
+
it 'does not fail' do
|
220
|
+
resolver.stub(:resolve_floating_ip).and_raise Errors::UnableToResolveFloatingIP
|
221
|
+
nova.stub(:add_floating_ip)
|
222
|
+
expect(resolver).to receive(:resolve_floating_ip).with(env)
|
223
|
+
expect(nova).to_not receive(:add_floating_ip)
|
224
|
+
@action.assign_floating_ip(env, 'server-01')
|
467
225
|
end
|
468
226
|
end
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
expect
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
context 'with hash containing a name matching more than one volume' do
|
478
|
-
it 'raises an error' do
|
479
|
-
config.stub(:volumes) { [{ name: 'vol-07-08' }] }
|
480
|
-
expect { @action.resolve_volumes(env) }.to raise_error(Errors::MultipleVolumeName)
|
227
|
+
context 'When neither floating ip nor floating ip pool is configured' do
|
228
|
+
it 'does nothing' do
|
229
|
+
resolver.stub(:resolve_floating_ip).and_return nil
|
230
|
+
nova.stub(:add_floating_ip)
|
231
|
+
expect(resolver).to receive(:resolve_floating_ip).with(env)
|
232
|
+
expect(nova).to_not receive(:add_floating_ip)
|
233
|
+
@action.assign_floating_ip(env, 'server-01')
|
481
234
|
end
|
482
235
|
end
|
483
236
|
end
|