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,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.1.0'
10
- fail 'Openstack Cloud provider is only compatible with Vagrant 1.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
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Openstack
3
- VERSION = '0.4.1'
3
+ VERSION = '0.5.0'
4
4
  end
5
5
  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 the case you can't use name in volume definition. Please, use id instead.
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(:availability_zone) { 'AZ-01' }
21
- config.stub(:floating_ip) { nil }
22
- config.stub(:floating_ip_pool) { nil }
23
- config.stub(:floating_ip_pool_always_allocate) { false }
24
- config.stub(:keypair_name) { nil }
25
- config.stub(:public_key_path) { nil }
26
- config.stub(:networks) { nil }
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').tap do |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].stub(:provider_config) { config }
90
- env[:machine].stub(:data_dir) { '/data/dir' }
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
- env[:openstack_client].stub(:cinder) { cinder }
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
- @action = CreateServer.new(nil, nil)
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
- end
155
-
156
- describe 'resolve_floating_ip' do
157
- context 'with config.floating_ip specified' do
158
- it 'return the specified floating ip' do
159
- config.stub(:floating_ip) { '80.80.80.80' }
160
- @action.resolve_floating_ip(env).should eq('80.80.80.80')
161
- end
162
- end
163
-
164
- context 'with config.floating_pool specified' do
165
- context 'if any ip in the same pool is available' do
166
- context 'with config.floating_pool_always_allocate true' do
167
- it 'allocate a new floating_ip from the pool' do
168
- config.stub(:floating_ip_pool_always_allocate) { true }
169
- nova.stub(:get_all_floating_ips).with(anything) do
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
- context 'with only names and ids of existing networks' do
289
- it 'return the ids array' do
290
- config.stub(:networks) { %w(net-1 net-id-2) }
291
- @action.resolve_networks(env).should eq(%w(net-id-1 net-id-2))
292
- end
293
- end
294
-
295
- context 'with not existing networks' do
296
- it 'return the ids array' do
297
- config.stub(:networks) { %w(net-1 net-id-3) }
298
- expect { @action.resolve_networks(env) }.to raise_error
299
- end
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
- context 'with no network returned by neutron and one network specified in vagrant provider' do
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 'resolve_volume_boot' do
321
- context 'with string volume id' do
322
- it 'returns normalized volume' do
323
- config.stub(:volume_boot) { '001' }
324
- expect(@action.resolve_volume_boot(env)).to eq id: '001', device: 'vda'
325
- end
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
- end
376
-
377
- context 'with hash containing a bad id' do
378
- it 'raises an error' do
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 'resolve_volumes' do
407
- context 'with volume attached in all possible ways' do
408
- it 'returns normalized volume list' do
409
-
410
- config.stub(:volumes) do
411
- ['001',
412
- 'vol-02',
413
- { id: '003', device: '/dev/vdz' },
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
- context 'with empty hash' do
457
- it 'raises an error' do
458
- config.stub(:volumes) { [{}] }
459
- expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictVolumeNameId)
460
- end
461
- end
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
- context 'with hash containing both id and name' do
471
- it 'raises an error' do
472
- config.stub(:volumes) { [{ id: '001', name: 'vol-01' }] }
473
- expect { @action.resolve_volumes(env) }.to raise_error(Errors::ConflictVolumeNameId)
474
- end
475
- end
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