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.
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