vagrant-openstack-provider 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/Appraisals +6 -6
  3. data/CHANGELOG.md +44 -1
  4. data/Gemfile +10 -6
  5. data/Vagrantfile +7 -15
  6. data/functional_tests/Vagrantfile +58 -0
  7. data/functional_tests/keys/vagrant-openstack +27 -0
  8. data/functional_tests/keys/vagrant-openstack.pub +1 -0
  9. data/functional_tests/run_tests.sh +142 -0
  10. data/gemfiles/latest_stable.gemfile +5 -0
  11. data/gemfiles/oldest_current.gemfile +5 -0
  12. data/gemfiles/previous_release.gemfile +5 -0
  13. data/lib/vagrant-openstack-provider/action.rb +17 -2
  14. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +60 -8
  15. data/lib/vagrant-openstack-provider/action/create_server.rb +131 -43
  16. data/lib/vagrant-openstack-provider/action/delete_server.rb +2 -0
  17. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +22 -3
  18. data/lib/vagrant-openstack-provider/action/resume.rb +2 -0
  19. data/lib/vagrant-openstack-provider/action/stop_server.rb +1 -0
  20. data/lib/vagrant-openstack-provider/action/suspend.rb +2 -0
  21. data/lib/vagrant-openstack-provider/action/sync_folders.rb +3 -2
  22. data/lib/vagrant-openstack-provider/action/wait_active.rb +29 -0
  23. data/lib/vagrant-openstack-provider/action/wait_stop.rb +1 -1
  24. data/lib/vagrant-openstack-provider/client/domain.rb +26 -0
  25. data/lib/vagrant-openstack-provider/client/http_utils.rb +96 -0
  26. data/lib/vagrant-openstack-provider/client/keystone.rb +30 -41
  27. data/lib/vagrant-openstack-provider/client/neutron.rb +24 -11
  28. data/lib/vagrant-openstack-provider/client/nova.rb +99 -104
  29. data/lib/vagrant-openstack-provider/client/openstack.rb +4 -0
  30. data/lib/vagrant-openstack-provider/client/request_logger.rb +24 -0
  31. data/lib/vagrant-openstack-provider/command/abstract_command.rb +31 -0
  32. data/lib/vagrant-openstack-provider/command/flavor_list.rb +21 -0
  33. data/lib/vagrant-openstack-provider/command/floatingip_list.rb +34 -0
  34. data/lib/vagrant-openstack-provider/command/image_list.rb +21 -0
  35. data/lib/vagrant-openstack-provider/command/main.rb +51 -0
  36. data/lib/vagrant-openstack-provider/command/network_list.rb +21 -0
  37. data/lib/vagrant-openstack-provider/command/utils.rb +22 -0
  38. data/lib/vagrant-openstack-provider/config.rb +31 -3
  39. data/lib/vagrant-openstack-provider/errors.rb +28 -0
  40. data/lib/vagrant-openstack-provider/plugin.rb +5 -0
  41. data/lib/vagrant-openstack-provider/version.rb +1 -1
  42. data/locales/en.yml +45 -1
  43. data/spec/vagrant-openstack-provider/action/connect_openstack_spec.rb +190 -0
  44. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +166 -1
  45. data/spec/vagrant-openstack-provider/action/read_ssh_info_spec.rb +109 -0
  46. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +32 -48
  47. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +42 -4
  48. data/spec/vagrant-openstack-provider/client/nova_spec.rb +247 -6
  49. data/spec/vagrant-openstack-provider/client/utils_spec.rb +58 -5
  50. data/spec/vagrant-openstack-provider/command/floatingip_list_spec.rb +67 -0
  51. data/spec/vagrant-openstack-provider/config_spec.rb +21 -6
  52. data/spec/vagrant-openstack-provider/spec_helper.rb +7 -0
  53. data/{numergyrc → stackrc} +4 -1
  54. metadata +24 -4
  55. data/lib/vagrant-openstack-provider/client/utils.rb +0 -38
@@ -51,7 +51,6 @@ describe VagrantPlugins::Openstack::KeystoneClient do
51
51
  end
52
52
 
53
53
  context 'with good credentials' do
54
-
55
54
  it 'store token and tenant id' do
56
55
  stub_request(:post, 'http://keystoneAuthV2')
57
56
  .with(
@@ -66,52 +65,6 @@ describe VagrantPlugins::Openstack::KeystoneClient do
66
65
 
67
66
  session.token.should eq('0123456789')
68
67
  session.project_id.should eq('testTenantId')
69
- session.endpoints[:compute].should eq('http://nova')
70
- session.endpoints[:network].should eq('http://neutron')
71
- end
72
-
73
- context 'with compute endpoint override' do
74
- it 'store token and tenant id' do
75
- config.stub(:openstack_compute_url) { 'http://novaOverride' }
76
-
77
- stub_request(:post, 'http://keystoneAuthV2')
78
- .with(
79
- body: keystone_request_body,
80
- headers: keystone_request_headers)
81
- .to_return(
82
- status: 200,
83
- body: keystone_response_body,
84
- headers: keystone_request_headers)
85
-
86
- @keystone_client.authenticate(env)
87
-
88
- session.token.should eq('0123456789')
89
- session.project_id.should eq('testTenantId')
90
- session.endpoints[:compute].should eq('http://novaOverride')
91
- session.endpoints[:network].should eq('http://neutron')
92
- end
93
- end
94
-
95
- context 'with network endpoint override' do
96
- it 'store token and tenant id' do
97
- config.stub(:openstack_network_url) { 'http://neutronOverride' }
98
-
99
- stub_request(:post, 'http://keystoneAuthV2')
100
- .with(
101
- body: keystone_request_body,
102
- headers: keystone_request_headers)
103
- .to_return(
104
- status: 200,
105
- body: keystone_response_body,
106
- headers: keystone_request_headers)
107
-
108
- @keystone_client.authenticate(env)
109
-
110
- session.token.should eq('0123456789')
111
- session.project_id.should eq('testTenantId')
112
- session.endpoints[:compute].should eq('http://nova')
113
- session.endpoints[:network].should eq('http://neutronOverride')
114
- end
115
68
  end
116
69
  end
117
70
 
@@ -132,9 +85,40 @@ describe VagrantPlugins::Openstack::KeystoneClient do
132
85
  }',
133
86
  headers: keystone_request_headers)
134
87
 
135
- expect { @keystone_client.authenticate(env) }.to raise_error(RestClient::Unauthorized)
88
+ expect { @keystone_client.authenticate(env) }.to raise_error(Errors::AuthenticationFailed)
89
+ end
90
+ end
91
+
92
+ context 'with bad endpoint' do
93
+ it 'raise a BadAuthenticationEndpoint error' do
94
+ stub_request(:post, 'http://keystoneAuthV2')
95
+ .with(
96
+ body: keystone_request_body,
97
+ headers: keystone_request_headers)
98
+ .to_return(
99
+ status: 404)
100
+
101
+ expect { @keystone_client.authenticate(env) }.to raise_error(Errors::BadAuthenticationEndpoint)
136
102
  end
137
103
  end
138
104
 
105
+ context 'with internal server error' do
106
+ it 'raise a VagrantOpenstackError error with response body as message' do
107
+ stub_request(:post, 'http://keystoneAuthV2')
108
+ .with(
109
+ body: keystone_request_body,
110
+ headers: keystone_request_headers)
111
+ .to_return(
112
+ status: 500,
113
+ body: 'Internal server error')
114
+
115
+ begin
116
+ @keystone_client.authenticate(env)
117
+ fail 'Expected Errors::VagrantOpenstackError'
118
+ rescue Errors::VagrantOpenstackError => e
119
+ e.message.should eq('Internal server error')
120
+ end
121
+ end
122
+ end
139
123
  end
140
124
  end
@@ -43,10 +43,48 @@ describe VagrantPlugins::Openstack::NeutronClient do
43
43
  networks = @neutron_client.get_private_networks(env)
44
44
 
45
45
  expect(networks.length).to eq(2)
46
- expect(networks[0][:id]).to eq('net-1')
47
- expect(networks[0][:name]).to eq('net1')
48
- expect(networks[1][:id]).to eq('net-2')
49
- expect(networks[1][:name]).to eq('net2')
46
+ expect(networks[0].id).to eq('net-1')
47
+ expect(networks[0].name).to eq('net1')
48
+ expect(networks[1].id).to eq('net-2')
49
+ expect(networks[1].name).to eq('net2')
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'get_api_version_list' do
55
+ context 'basic' do
56
+ it 'returns version list' do
57
+ stub_request(:get, 'http://neutron/')
58
+ .with(header: { 'Accept' => 'application/json' })
59
+ .to_return(
60
+ status: 200,
61
+ body: '{
62
+ "versions": [
63
+ {
64
+ "status": "...",
65
+ "id": "v1.0",
66
+ "links": [
67
+ {
68
+ "href": "http://neutron/v1.0",
69
+ "rel": "self"
70
+ }
71
+ ]
72
+ },
73
+ {
74
+ "status": "CURRENT",
75
+ "id": "v2.0",
76
+ "links": [
77
+ {
78
+ "href": "http://neutron/v2.0",
79
+ "rel": "self"
80
+ }
81
+ ]
82
+ }
83
+ ]}')
84
+
85
+ versions = @neutron_client.get_api_version_list(env)
86
+
87
+ expect(versions.size).to eq(2)
50
88
  end
51
89
  end
52
90
  end
@@ -1,6 +1,10 @@
1
1
  require 'vagrant-openstack-provider/spec_helper'
2
2
 
3
3
  describe VagrantPlugins::Openstack::NovaClient do
4
+ include FakeFS::SpecHelpers::All
5
+
6
+ let(:filename) { 'key.pub' }
7
+ let(:ssh_key_content) { 'my public key' }
4
8
 
5
9
  let(:config) do
6
10
  double('config').tap do |config|
@@ -12,6 +16,12 @@ describe VagrantPlugins::Openstack::NovaClient do
12
16
  end
13
17
  end
14
18
 
19
+ let(:file) do
20
+ double('file').tap do |file|
21
+ file.stub(:read) { ssh_key_content }
22
+ end
23
+ end
24
+
15
25
  let(:env) do
16
26
  Hash.new.tap do |env|
17
27
  env[:ui] = double('ui')
@@ -97,7 +107,7 @@ describe VagrantPlugins::Openstack::NovaClient do
97
107
  })
98
108
  .to_return(status: 202, body: '{ "server": { "id": "o1o2o3" } }')
99
109
 
100
- instance_id = @nova_client.create_server(env, 'inst', 'img', 'flav', nil, 'key')
110
+ instance_id = @nova_client.create_server(env, name: 'inst', image_ref: 'img', flavor_ref: 'flav', networks: nil, keypair: 'key')
101
111
 
102
112
  expect(instance_id).to eq('o1o2o3')
103
113
  end
@@ -116,7 +126,27 @@ describe VagrantPlugins::Openstack::NovaClient do
116
126
  })
117
127
  .to_return(status: 202, body: '{ "server": { "id": "o1o2o3" } }')
118
128
 
119
- instance_id = @nova_client.create_server(env, 'inst', 'img', 'flav', %w(net1 net2), 'key')
129
+ instance_id = @nova_client.create_server(env, name: 'inst', image_ref: 'img', flavor_ref: 'flav', networks: %w(net1 net2), keypair: 'key')
130
+
131
+ expect(instance_id).to eq('o1o2o3')
132
+ end
133
+ end
134
+
135
+ context 'with availability_zone' do
136
+ it 'returns new instance id' do
137
+
138
+ stub_request(:post, 'http://nova/a1b2c3/servers')
139
+ .with(
140
+ body: '{"server":{"name":"inst","imageRef":"img","flavorRef":"flav","key_name":"key","availability_zone":"avz"}}',
141
+ headers:
142
+ {
143
+ 'Accept' => 'application/json',
144
+ 'Content-Type' => 'application/json',
145
+ 'X-Auth-Token' => '123456'
146
+ })
147
+ .to_return(status: 202, body: '{ "server": { "id": "o1o2o3" } }')
148
+
149
+ instance_id = @nova_client.create_server(env, name: 'inst', image_ref: 'img', flavor_ref: 'flav', keypair: 'key', availability_zone: 'avz')
120
150
 
121
151
  expect(instance_id).to eq('o1o2o3')
122
152
  end
@@ -143,13 +173,88 @@ describe VagrantPlugins::Openstack::NovaClient do
143
173
  end
144
174
  end
145
175
 
176
+ describe 'import_keypair_from_file' do
177
+ context 'with token and project_id acquainted' do
178
+ it 'returns newly created keypair name' do
179
+ File.should_receive(:exist?).with(filename).and_return(true)
180
+ File.should_receive(:open).with(filename).and_return(file)
181
+ Kernel.stub!(:rand).and_return(2_036_069_739_008)
182
+
183
+ stub_request(:post, 'http://nova/a1b2c3/os-keypairs')
184
+ .with(
185
+ body: "{\"keypair\":{\"name\":\"vagrant-generated-pzcvcpa8\",\"public_key\":\"#{ssh_key_content}\"}}",
186
+ headers: {
187
+ 'Accept' => 'application/json',
188
+ 'Content-Type' => 'application/json',
189
+ 'X-Auth-Token' => '123456' })
190
+ .to_return(status: 200, body: '
191
+ {
192
+ "keypair": {
193
+ "name": "created_key_name"
194
+ }
195
+ }')
196
+
197
+ @nova_client.import_keypair_from_file(env, filename)
198
+
199
+ end
200
+ end
201
+ end
202
+
203
+ describe 'delete_keypair_if_vagrant' do
204
+ context 'with token and project_id acquainted' do
205
+ context 'with keypair not generated by vagrant' do
206
+ it 'do nothing' do
207
+ stub_request(:get, 'http://nova/a1b2c3/servers/o1o2o3')
208
+ .with(headers:
209
+ {
210
+ 'Accept' => 'application/json',
211
+ 'X-Auth-Token' => '123456'
212
+ })
213
+ .to_return(status: 200, body: '
214
+ {
215
+ "server": {
216
+ "id": "o1o2o3",
217
+ "key_name": "other_key"
218
+ }
219
+ }
220
+ ')
221
+
222
+ @nova_client.delete_keypair_if_vagrant(env, 'o1o2o3')
223
+ end
224
+ end
225
+ context 'with keypair generated by vagrant' do
226
+ it 'deletes the key on nova' do
227
+ stub_request(:delete, 'http://nova/a1b2c3/os-keypairs/vagrant-generated-1234')
228
+ .with(headers: { 'X-Auth-Token' => '123456' })
229
+ .to_return(status: 202)
230
+ stub_request(:get, 'http://nova/a1b2c3/servers/o1o2o3')
231
+ .with(headers:
232
+ {
233
+ 'Accept' => 'application/json',
234
+ 'X-Auth-Token' => '123456'
235
+ })
236
+ .to_return(status: 200, body: '
237
+ {
238
+ "server": {
239
+ "id": "o1o2o3",
240
+ "key_name": "vagrant-generated-1234"
241
+ }
242
+ }
243
+ ')
244
+
245
+ @nova_client.delete_keypair_if_vagrant(env, 'o1o2o3')
246
+ end
247
+ end
248
+ end
249
+ end
250
+
146
251
  describe 'suspend_server' do
147
252
  context 'with token and project_id acquainted' do
148
253
  it 'returns new instance id' do
149
254
 
150
255
  stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
151
256
  .with(
152
- body: '{ "suspend": null }',
257
+ body: '{"suspend":null}',
153
258
  headers:
154
259
  {
155
260
  'Accept' => 'application/json',
@@ -169,7 +274,7 @@ describe VagrantPlugins::Openstack::NovaClient do
169
274
 
170
275
  stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
171
276
  .with(
172
- body: '{ "resume": null }',
277
+ body: '{"resume":null}',
173
278
  headers:
174
279
  {
175
280
  'Accept' => 'application/json',
@@ -189,7 +294,7 @@ describe VagrantPlugins::Openstack::NovaClient do
189
294
 
190
295
  stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
191
296
  .with(
192
- body: '{ "os-stop": null }',
297
+ body: '{"os-stop":null}',
193
298
  headers:
194
299
  {
195
300
  'Accept' => 'application/json',
@@ -210,7 +315,7 @@ describe VagrantPlugins::Openstack::NovaClient do
210
315
 
211
316
  stub_request(:post, 'http://nova/a1b2c3/servers/o1o2o3/action')
212
317
  .with(
213
- body: '{ "os-start": null }',
318
+ body: '{"os-start":null}',
214
319
  headers:
215
320
  {
216
321
  'Accept' => 'application/json',
@@ -225,6 +330,76 @@ describe VagrantPlugins::Openstack::NovaClient do
225
330
  end
226
331
  end
227
332
 
333
+ describe 'get_all_floating_ips' do
334
+ context 'with token and project_id acquainted' do
335
+ it 'returns all floating ips' do
336
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ips')
337
+ .with(headers:
338
+ {
339
+ 'Accept' => 'application/json',
340
+ 'Accept-Encoding' => 'gzip, deflate',
341
+ 'User-Agent' => 'Ruby',
342
+ 'X-Auth-Token' => '123456'
343
+ })
344
+ .to_return(status: 200, body: '
345
+ {
346
+ "floating_ips": [
347
+ {"instance_id": "1234",
348
+ "ip": "185.39.216.45",
349
+ "fixed_ip": "192.168.0.54",
350
+ "id": "2345",
351
+ "pool": "PublicNetwork-01"
352
+ },
353
+ {
354
+ "instance_id": null,
355
+ "ip": "185.39.216.95",
356
+ "fixed_ip": null,
357
+ "id": "3456",
358
+ "pool": "PublicNetwork-02"
359
+ }]
360
+ }')
361
+
362
+ floating_ips = @nova_client.get_all_floating_ips(env)
363
+
364
+ expect(floating_ips).to have(2).items
365
+ expect(floating_ips[0].ip).to eql('185.39.216.45')
366
+ expect(floating_ips[0].instance_id).to eql('1234')
367
+ expect(floating_ips[0].pool).to eql('PublicNetwork-01')
368
+ expect(floating_ips[1].ip).to eql('185.39.216.95')
369
+ expect(floating_ips[1].instance_id).to be(nil)
370
+ expect(floating_ips[1].pool).to eql('PublicNetwork-02')
371
+ end
372
+ end
373
+ end
374
+
375
+ describe 'get_all_floating_ips' do
376
+ context 'with token and project_id acquainted' do
377
+ it 'return newly allocated floating_ip' do
378
+ stub_request(:post, 'http://nova/a1b2c3/os-floating-ips')
379
+ .with(body: '{"pool":"pool-1"}',
380
+ headers: {
381
+ 'Accept' => 'application/json',
382
+ 'Content-Type' => 'application/json',
383
+ 'X-Auth-Token' => '123456' })
384
+ .to_return(status: 200, body: '
385
+ {
386
+ "floating_ip": {
387
+ "instance_id": null,
388
+ "ip": "183.45.67.89",
389
+ "fixed_ip": null,
390
+ "id": "o1o2o3",
391
+ "pool": "pool-1"
392
+ }
393
+ }')
394
+ floating_ip = @nova_client.allocate_floating_ip(env, 'pool-1')
395
+
396
+ expect(floating_ip.ip).to eql('183.45.67.89')
397
+ expect(floating_ip.instance_id).to be(nil)
398
+ expect(floating_ip.pool).to eql('pool-1')
399
+ end
400
+ end
401
+ end
402
+
228
403
  describe 'get_server_details' do
229
404
  context 'with token and project_id acquainted' do
230
405
  it 'returns server details' do
@@ -368,6 +543,72 @@ describe VagrantPlugins::Openstack::NovaClient do
368
543
  expect { @nova_client.add_floating_ip(env, 'o1o2o3', '1.2.3.4') }.to raise_error(RuntimeError)
369
544
  end
370
545
  end
546
+ end
547
+
548
+ describe 'get_floating_ip_pools' do
549
+ context 'with token and project_id acquainted' do
550
+ it 'should return floating ip pool' do
551
+
552
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ip-pools')
553
+ .with(headers: { 'Accept' => 'application/json', 'X-Auth-Token' => '123456' })
554
+ .to_return(status: 200, body: '
555
+ {
556
+ "floating_ip_pools": [
557
+ {
558
+ "name": "pool1"
559
+ },
560
+ {
561
+ "name": "pool2"
562
+ }
563
+ ]
564
+ }
565
+ ')
566
+
567
+ pools = @nova_client.get_floating_ip_pools(env)
568
+
569
+ expect(pools[0]['name']).to eq('pool1')
570
+ expect(pools[1]['name']).to eq('pool2')
571
+ end
572
+ end
573
+ end
371
574
 
575
+ describe 'get_floating_ips' do
576
+ context 'with token and project_id acquainted' do
577
+ it 'should return floating ip list' do
578
+
579
+ stub_request(:get, 'http://nova/a1b2c3/os-floating-ips')
580
+ .with(headers: { 'Accept' => 'application/json', 'X-Auth-Token' => '123456' })
581
+ .to_return(status: 200, body: '
582
+ {
583
+ "floating_ips": [
584
+ {
585
+ "fixed_ip": null,
586
+ "id": 1,
587
+ "instance_id": null,
588
+ "ip": "10.10.10.1",
589
+ "pool": "pool1"
590
+ },
591
+ {
592
+ "fixed_ip": null,
593
+ "id": 2,
594
+ "instance_id": "inst001",
595
+ "ip": "10.10.10.2",
596
+ "pool": "pool2"
597
+ }
598
+ ]
599
+ }
600
+ ')
601
+
602
+ ips = @nova_client.get_floating_ips(env)
603
+
604
+ expect(ips[0]['ip']).to eq('10.10.10.1')
605
+ expect(ips[0]['instance_id']).to eq(nil)
606
+ expect(ips[0]['pool']).to eq('pool1')
607
+
608
+ expect(ips[1]['ip']).to eq('10.10.10.2')
609
+ expect(ips[1]['instance_id']).to eq('inst001')
610
+ expect(ips[1]['pool']).to eq('pool2')
611
+ end
612
+ end
372
613
  end
373
614
  end