oneacct-export 0.1.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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +11 -0
  6. data/Rakefile +18 -0
  7. data/bin/oneacct-export +72 -0
  8. data/config/conf.yml +53 -0
  9. data/config/sidekiq.yml +6 -0
  10. data/lib/errors.rb +7 -0
  11. data/lib/errors/authentication_error.rb +3 -0
  12. data/lib/errors/resource_not_found_error.rb +3 -0
  13. data/lib/errors/resource_retrieval_error.rb +3 -0
  14. data/lib/errors/resource_state_error.rb +3 -0
  15. data/lib/errors/user_not_authorized_error.rb +3 -0
  16. data/lib/input_validator.rb +18 -0
  17. data/lib/one_data_accessor.rb +147 -0
  18. data/lib/one_worker.rb +181 -0
  19. data/lib/one_writer.rb +51 -0
  20. data/lib/oneacct_exporter.rb +88 -0
  21. data/lib/oneacct_exporter/log.rb +15 -0
  22. data/lib/oneacct_exporter/version.rb +3 -0
  23. data/lib/oneacct_opts.rb +131 -0
  24. data/lib/redis_conf.rb +29 -0
  25. data/lib/settings.rb +13 -0
  26. data/lib/sidekiq_conf.rb +11 -0
  27. data/lib/templates/apel-0.2.erb +30 -0
  28. data/mock/one_worker_DEPLOY_ID_missing.xml +136 -0
  29. data/mock/one_worker_DISK_missing.xml +119 -0
  30. data/mock/one_worker_ETIME_0.xml +137 -0
  31. data/mock/one_worker_ETIME_missing.xml +136 -0
  32. data/mock/one_worker_ETIME_nan.xml +137 -0
  33. data/mock/one_worker_GID_missing.xml +136 -0
  34. data/mock/one_worker_GNAME_missing.xml +136 -0
  35. data/mock/one_worker_HISTORY_RECORDS_missing.xml +91 -0
  36. data/mock/one_worker_HISTORY_many.xml +137 -0
  37. data/mock/one_worker_HISTORY_missing.xml +93 -0
  38. data/mock/one_worker_HISTORY_one.xml +115 -0
  39. data/mock/one_worker_IMAGE_ID_missing.xml +136 -0
  40. data/mock/one_worker_MEMORY_0.xml +137 -0
  41. data/mock/one_worker_MEMORY_missing.xml +136 -0
  42. data/mock/one_worker_MEMORY_nan.xml +137 -0
  43. data/mock/one_worker_NET_RX_0.xml +137 -0
  44. data/mock/one_worker_NET_RX_missing.xml +136 -0
  45. data/mock/one_worker_NET_RX_nan.xml +137 -0
  46. data/mock/one_worker_NET_TX_0.xml +137 -0
  47. data/mock/one_worker_NET_TX_missing.xml +136 -0
  48. data/mock/one_worker_NET_TX_nan.xml +137 -0
  49. data/mock/one_worker_RETIME_0.xml +115 -0
  50. data/mock/one_worker_RETIME_missing.xml +114 -0
  51. data/mock/one_worker_RSTIME_0.xml +115 -0
  52. data/mock/one_worker_RSTIME_>_RETIME.xml +115 -0
  53. data/mock/one_worker_RSTIME_missing.xml +114 -0
  54. data/mock/one_worker_STATE_missing.xml +136 -0
  55. data/mock/one_worker_STATE_out_of_range.xml +137 -0
  56. data/mock/one_worker_STIME_>_ETIME.xml +137 -0
  57. data/mock/one_worker_STIME_missing.xml +136 -0
  58. data/mock/one_worker_STIME_nan.xml +137 -0
  59. data/mock/one_worker_TEMPLATE_missing.xml +79 -0
  60. data/mock/one_worker_UID_missing.xml +136 -0
  61. data/mock/one_worker_VCPU_0.xml +137 -0
  62. data/mock/one_worker_VCPU_missing.xml +136 -0
  63. data/mock/one_worker_VCPU_nan.xml +137 -0
  64. data/mock/one_worker_malformed_vm.xml +136 -0
  65. data/mock/one_worker_valid_machine.xml +137 -0
  66. data/mock/one_worker_vm1.xml +137 -0
  67. data/mock/one_worker_vm2.xml +137 -0
  68. data/mock/one_worker_vm3.xml +137 -0
  69. data/mock/one_writer_testfile +2 -0
  70. data/oneacct-export.gemspec +31 -0
  71. data/spec/one_data_accessor_spec.rb +441 -0
  72. data/spec/one_worker_spec.rb +684 -0
  73. data/spec/one_writer_spec.rb +146 -0
  74. data/spec/oneacct_exporter_spec.rb +262 -0
  75. data/spec/oneacct_opts_spec.rb +229 -0
  76. data/spec/redis_conf_spec.rb +94 -0
  77. data/spec/spec_helper.rb +11 -0
  78. metadata +254 -0
@@ -0,0 +1,684 @@
1
+ require 'spec_helper'
2
+
3
+ describe OneWorker do
4
+ subject { one_worker }
5
+
6
+ let(:one_worker) { OneWorker.new }
7
+ let(:oda) { double('oda') }
8
+
9
+ describe '.common_data' do
10
+ before :example do
11
+ Settings['endpoint'] = 'machine.hogwarts.co.uk'
12
+ Settings['site_name'] = 'Hogwarts'
13
+ Settings['cloud_type'] = 'OpenNebula'
14
+ end
15
+
16
+ let(:common_data) { { 'endpoint' => 'machine.hogwarts.co.uk', 'site_name' => 'Hogwarts', 'cloud_type' => 'OpenNebula' } }
17
+
18
+ it 'returns data common for every vm in form of hash' do
19
+ expect(subject.common_data).to eq(common_data)
20
+ end
21
+ end
22
+
23
+ describe '.create_user_map' do
24
+ it 'returns user map' do
25
+ expect(subject).to receive(:create_map).with(OpenNebula::UserPool, anything, anything) { 'map' }
26
+ expect(subject.create_user_map(oda)).to eq('map')
27
+ end
28
+ end
29
+
30
+ describe '.create_image_map' do
31
+ it 'returns image map' do
32
+ expect(subject).to receive(:create_map).with(OpenNebula::ImagePool, anything, anything) { 'map' }
33
+ expect(subject.create_image_map(oda)).to eq('map')
34
+ end
35
+ end
36
+
37
+ describe '.create_map' do
38
+ let(:pool_type) { double('pool_type') }
39
+ let(:mapping) { double('mapping') }
40
+
41
+ context 'without any error during data retrieval' do
42
+ before :example do
43
+ expect(oda).to receive(:mapping).with(pool_type, mapping)
44
+ end
45
+
46
+ it 'returns requested map' do
47
+ subject.create_map(pool_type, mapping, oda)
48
+ end
49
+ end
50
+
51
+ context 'with error during data retrieval' do
52
+ before :example do
53
+ expect(oda).to receive(:mapping).and_raise(Errors::ResourceRetrievalError)
54
+ end
55
+
56
+ it 'raises an error' do
57
+ expect { subject.create_map(pool_type, mapping, oda) }.to raise_error(RuntimeError)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '.load_vm' do
63
+ context 'without error' do
64
+ before :example do
65
+ expect(oda).to receive(:vm).with(5) { vm }
66
+ end
67
+
68
+ let(:vm) { double('vm') }
69
+
70
+ it 'returns vm with given ID' do
71
+ expect(subject.load_vm(5, oda)).to eq(vm)
72
+ end
73
+ end
74
+
75
+ context 'with error' do
76
+ before :example do
77
+ expect(oda).to receive(:vm).and_raise(Errors::ResourceRetrievalError)
78
+ end
79
+
80
+ it 'returns nil' do
81
+ expect(subject.load_vm(5, oda)).to be_nil
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '.parse' do
87
+ let(:regex) { /[[:digit:]]+/ }
88
+
89
+ context 'with three parameters' do
90
+ context 'if regex matches the value' do
91
+ it 'returns the value' do
92
+ expect(subject.parse('42', regex, '0')).to eq('42')
93
+ end
94
+ end
95
+
96
+ context 'if regex does not match the value' do
97
+ it 'it returns substitute' do
98
+ expect(subject.parse('abc', regex, '0')).to eq('0')
99
+ end
100
+ end
101
+ end
102
+
103
+ context 'with two parameters' do
104
+ context 'if regex matches the value' do
105
+ it 'returns the value' do
106
+ expect(subject.parse('42', regex)).to eq('42')
107
+ end
108
+ end
109
+
110
+ context 'if regex does not match the value' do
111
+ it 'returns "NULL"' do
112
+ expect(subject.parse('abc', regex)).to eq('NULL')
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ describe 'write_data' do
119
+ before :example do
120
+ expect(OneWriter).to receive(:new).with(data, output, anything) { ow }
121
+ end
122
+
123
+ let(:data) { double('data') }
124
+ let(:output) { double('output') }
125
+ let(:ow) { double('one_writer') }
126
+
127
+ context 'without error' do
128
+ before :example do
129
+ expect(ow).to receive(:write)
130
+ end
131
+
132
+ it 'calls OneWriter.write with specified data and output directory' do
133
+ subject.write_data(data, output)
134
+ end
135
+ end
136
+
137
+ context 'with error' do
138
+ before :example do
139
+ expect(ow).to receive(:write).and_raise(Errors::ResourceRetrievalError)
140
+ end
141
+
142
+ it 'raises a RuntimeError' do
143
+ expect { subject.write_data(data, output) }.to raise_error(RuntimeError)
144
+ end
145
+ end
146
+ end
147
+
148
+ describe '.process_vm' do
149
+ before :example do
150
+ Settings['endpoint'] = 'machine.hogwarts.co.uk'
151
+ Settings['site_name'] = 'Hogwarts'
152
+ Settings['cloud_type'] = 'OpenNebula'
153
+ end
154
+
155
+ let(:vm) do
156
+ xml = File.read("#{GEM_DIR}/mock/#{filename}")
157
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
158
+ end
159
+
160
+ let(:data) do
161
+ data = {}
162
+ data['endpoint'] = 'machine.hogwarts.co.uk'
163
+ data['site_name'] = 'Hogwarts'
164
+ data['cloud_type'] = 'OpenNebula'
165
+ data['vm_uuid'] = '36551'
166
+ data['start_time'] = '1383741160'
167
+ data['start_time_readable'] = '2013-11-06 13:32:40+01:00'
168
+ data['end_time'] = '1383742270'
169
+ data['machine_name'] = 'one-36551'
170
+ data['user_id'] = '120'
171
+ data['group_id'] = '0'
172
+ data['user_name'] = 'user_name'
173
+ data['fqan'] = 'gname'
174
+ data['status'] = 'completed'
175
+ data['duration'] = '596'
176
+ data['suspend'] = '514'
177
+ data['cpu_count'] = '1'
178
+ data['network_inbound'] = 0
179
+ data['network_outbound'] = 0
180
+ data['memory'] = '1736960'
181
+ data['image_name'] = 'image_name'
182
+
183
+ data
184
+ end
185
+
186
+ let(:user_map) { { '120' => 'user_name' } }
187
+ let(:image_map) { { '31' => 'image_name' } }
188
+
189
+ context 'with valid vm' do
190
+ let(:filename) { 'one_worker_valid_machine.xml' }
191
+
192
+ it 'returns correct vm data' do
193
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
194
+ end
195
+ end
196
+
197
+ context 'vm without STIME' do
198
+ let(:filename) { 'one_worker_STIME_missing.xml' }
199
+
200
+ it 'returns nil' do
201
+ expect(subject.process_vm(vm, user_map, image_map)).to be_nil
202
+ end
203
+ end
204
+
205
+ context 'vm with STIME that is not a number' do
206
+ let(:filename) { 'one_worker_STIME_nan.xml' }
207
+
208
+ it 'returns nil' do
209
+ expect(subject.process_vm(vm, user_map, image_map)).to be_nil
210
+ end
211
+ end
212
+
213
+ context 'vm without ETIME' do
214
+ before :example do
215
+ data['end_time'] = 'NULL'
216
+ data['suspend'] = 'NULL'
217
+ end
218
+
219
+ let(:filename) { 'one_worker_ETIME_missing.xml' }
220
+
221
+ it 'replaces ETIME with "NULL"' do
222
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
223
+ end
224
+ end
225
+
226
+ context 'vm with ETIME that is not a number' do
227
+ before :example do
228
+ data['end_time'] = 'NULL'
229
+ data['suspend'] = 'NULL'
230
+ end
231
+
232
+ let(:filename) { 'one_worker_ETIME_nan.xml' }
233
+
234
+ it 'replaces ETIME with "NULL"' do
235
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
236
+ end
237
+ end
238
+
239
+ context 'vm ETIME that is 0' do
240
+ before :example do
241
+ data['end_time'] = 'NULL'
242
+ data['suspend'] = 'NULL'
243
+ end
244
+
245
+ let(:filename) { 'one_worker_ETIME_0.xml' }
246
+
247
+ it 'replaces ETIME with "NULL"' do
248
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
249
+ end
250
+ end
251
+
252
+ context 'vm with STIME bigger than ETIME' do
253
+ let(:filename) { 'one_worker_STIME_>_ETIME.xml' }
254
+
255
+ it 'returns nil' do
256
+ expect(subject.process_vm(vm, user_map, image_map)).to be_nil
257
+ end
258
+ end
259
+
260
+ context 'vm without DEPLOY_ID' do
261
+ let(:filename) { 'one_worker_DEPLOY_ID_missing.xml' }
262
+
263
+ it 'replaces machine name with string created from id and prefix "one-"' do
264
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
265
+ end
266
+ end
267
+
268
+ context 'vm without UID' do
269
+ before :example do
270
+ data['user_id'] = 'NULL'
271
+ data['user_name'] = 'NULL'
272
+ end
273
+
274
+ let(:filename) { 'one_worker_UID_missing.xml' }
275
+
276
+ it 'replaces user id with "NULL"' do
277
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
278
+ end
279
+ end
280
+
281
+ context 'vm without GID' do
282
+ before :example do
283
+ data['group_id'] = 'NULL'
284
+ end
285
+
286
+ let(:filename) { 'one_worker_GID_missing.xml' }
287
+
288
+ it 'replaces group id with "NULL"' do
289
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
290
+ end
291
+ end
292
+
293
+ context 'vm without GNAME' do
294
+ before :example do
295
+ data['fqan'] = nil
296
+ end
297
+
298
+ let(:filename) { 'one_worker_GNAME_missing.xml' }
299
+
300
+ it 'sets fqan to nil' do
301
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
302
+ end
303
+ end
304
+
305
+ context 'vm without STATE' do
306
+ before :example do
307
+ data['status'] = 'NULL'
308
+ end
309
+
310
+ let(:filename) { 'one_worker_STATE_missing.xml' }
311
+
312
+ it 'replaces status with "NULL"' do
313
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
314
+ end
315
+ end
316
+
317
+ context 'vm with STATE with value out of range' do
318
+ before :example do
319
+ data['status'] = 'NULL'
320
+ end
321
+
322
+ let(:filename) { 'one_worker_STATE_out_of_range.xml' }
323
+
324
+ it 'replaces status with "NULL"' do
325
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
326
+ end
327
+ end
328
+
329
+ context 'vm without HISTORY_RECORDS' do
330
+ let(:filename) { 'one_worker_HISTORY_RECORDS_missing.xml' }
331
+
332
+ it 'returns nil' do
333
+ expect(subject.process_vm(vm, user_map, image_map)).to be_nil
334
+ end
335
+ end
336
+
337
+ context 'vm one HISTORY record' do
338
+ let(:filename) { 'one_worker_HISTORY_one.xml' }
339
+
340
+ it 'returns correct vm data' do
341
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
342
+ end
343
+ end
344
+
345
+ context 'vm many HISTORY records' do
346
+ before :example do
347
+ data['duration'] = '831'
348
+ data['suspend'] = '279'
349
+ end
350
+
351
+ let(:filename) { 'one_worker_HISTORY_many.xml' }
352
+
353
+ it 'returns correct vm data' do
354
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
355
+ end
356
+ end
357
+
358
+ context 'vm without TEMPLATE' do
359
+ before :example do
360
+ data['cpu_count'] = '1'
361
+ data['image_name'] = 'NULL'
362
+ end
363
+
364
+ let(:filename) { 'one_worker_TEMPLATE_missing.xml' }
365
+
366
+ it 'replaces items in TEMPLATE section with "NULL"' do
367
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
368
+ end
369
+ end
370
+
371
+ context 'vm without VCPU' do
372
+ before :example do
373
+ data['cpu_count'] = '1'
374
+ end
375
+
376
+ let(:filename) { 'one_worker_VCPU_missing.xml' }
377
+
378
+ it 'replaces cpu count with value 1' do
379
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
380
+ end
381
+ end
382
+
383
+ context 'vm with VCPU that is 0' do
384
+ before :example do
385
+ data['cpu_count'] = '1'
386
+ end
387
+
388
+ let(:filename) { 'one_worker_VCPU_0.xml' }
389
+
390
+ it 'replaces cpu count with value 1' do
391
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
392
+ end
393
+ end
394
+
395
+ context 'vm with VCPU that is not a number' do
396
+ before :example do
397
+ data['cpu_count'] = '1'
398
+ end
399
+
400
+ let(:filename) { 'one_worker_VCPU_nan.xml' }
401
+
402
+ it 'replaces cpu count with value 1' do
403
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
404
+ end
405
+ end
406
+
407
+ context 'vm without NET_TX' do
408
+ before :example do
409
+ data['network_inbound'] = 0
410
+ end
411
+
412
+ let(:filename) { 'one_worker_NET_TX_missing.xml' }
413
+
414
+ it 'replaces network outbound with value 0' do
415
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
416
+ end
417
+ end
418
+
419
+ context 'vm with NET_TX that is 0' do
420
+ before :example do
421
+ data['network_inbound'] = 0
422
+ end
423
+
424
+ let(:filename) { 'one_worker_NET_TX_0.xml' }
425
+
426
+ it 'replaces network outbound with value 0' do
427
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
428
+ end
429
+ end
430
+
431
+ context 'vm with NET_TX that is not a number' do
432
+ before :example do
433
+ data['network_inbound'] = 0
434
+ end
435
+
436
+ let(:filename) { 'one_worker_NET_TX_nan.xml' }
437
+
438
+ it 'replaces network outbound with value 0' do
439
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
440
+ end
441
+ end
442
+
443
+ context 'vm without NET_RX' do
444
+ before :example do
445
+ data['network_outbound'] = 0
446
+ end
447
+
448
+ let(:filename) { 'one_worker_NET_RX_missing.xml' }
449
+
450
+ it 'replaces network outbound with value 0' do
451
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
452
+ end
453
+ end
454
+
455
+ context 'vm with NET_RX that is 0' do
456
+ before :example do
457
+ data['network_outbound'] = 0
458
+ end
459
+
460
+ let(:filename) { 'one_worker_NET_RX_0.xml' }
461
+
462
+ it 'replaces network outbound with value 0' do
463
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
464
+ end
465
+ end
466
+
467
+ context 'vm with NET_RX that is not a number' do
468
+ before :example do
469
+ data['network_outbound'] = 0
470
+ end
471
+
472
+ let(:filename) { 'one_worker_NET_RX_nan.xml' }
473
+
474
+ it 'replaces network outbound with value 0' do
475
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
476
+ end
477
+ end
478
+
479
+ context 'vm without MEMORY' do
480
+ before :example do
481
+ data['memory'] = '0'
482
+ end
483
+
484
+ let(:filename) { 'one_worker_MEMORY_missing.xml' }
485
+
486
+ it 'replaces memory with value 0' do
487
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
488
+ end
489
+ end
490
+
491
+ context 'vm with MEMORY that is 0' do
492
+ before :example do
493
+ data['memory'] = '0'
494
+ end
495
+
496
+ let(:filename) { 'one_worker_MEMORY_0.xml' }
497
+
498
+ it 'replaces memory with value 0' do
499
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
500
+ end
501
+ end
502
+
503
+ context 'vm with MEMORY that is not a number' do
504
+ before :example do
505
+ data['memory'] = '0'
506
+ end
507
+
508
+ let(:filename) { 'one_worker_MEMORY_nan.xml' }
509
+
510
+ it 'replaces memory with value 0' do
511
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
512
+ end
513
+ end
514
+
515
+ context 'vm without DISK' do
516
+ before :example do
517
+ data['image_name'] = 'NULL'
518
+ end
519
+
520
+ let(:filename) { 'one_worker_DISK_missing.xml' }
521
+
522
+ it 'replaces image name with "NULL"' do
523
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
524
+ end
525
+ end
526
+
527
+ context 'vm without IMAGE_ID' do
528
+ before :example do
529
+ data['image_name'] = 'NULL'
530
+ end
531
+
532
+ let(:filename) { 'one_worker_IMAGE_ID_missing.xml' }
533
+
534
+ it 'replaces image name with "NULL"' do
535
+ expect(subject.process_vm(vm, user_map, image_map)).to eq(data)
536
+ end
537
+ end
538
+ end
539
+
540
+ describe '.sum_rstime' do
541
+ let(:vm) do
542
+ xml = File.read("#{GEM_DIR}/mock/#{filename}")
543
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
544
+ end
545
+
546
+ context 'vm without RSTIME' do
547
+ let(:filename) { 'one_worker_RSTIME_missing.xml' }
548
+
549
+ it 'returns 0' do
550
+ expect(subject.sum_rstime(vm)).to eq(0)
551
+ end
552
+ end
553
+
554
+ context 'vm with RSTIME that is 0' do
555
+ let(:filename) { 'one_worker_RSTIME_0.xml' }
556
+
557
+ it 'returns 0' do
558
+ expect(subject.sum_rstime(vm)).to eq(0)
559
+ end
560
+ end
561
+
562
+ context 'vm without RETIME' do
563
+ let(:filename) { 'one_worker_RETIME_missing.xml' }
564
+
565
+ it 'returns 0' do
566
+ expect(subject.sum_rstime(vm)).to eq(0)
567
+ end
568
+ end
569
+
570
+ context 'vm with RETIME that is 0' do
571
+ let(:filename) { 'one_worker_RETIME_0.xml' }
572
+
573
+ it 'returns 0' do
574
+ expect(subject.sum_rstime(vm)).to eq(0)
575
+ end
576
+ end
577
+
578
+ context 'vm with RSTIME bigger than RETIME' do
579
+ let(:filename) { 'one_worker_RSTIME_>_RETIME.xml' }
580
+
581
+ it 'returns nil' do
582
+ expect(subject.sum_rstime(vm)).to be_nil
583
+ end
584
+ end
585
+ end
586
+
587
+ describe '.perform' do
588
+ before :example do
589
+ allow(OneDataAccessor).to receive(:new) { oda }
590
+ allow(subject).to receive(:create_user_map) { user_map }
591
+ allow(subject).to receive(:create_image_map) { image_map }
592
+ allow(subject).to receive(:load_vm).and_return(:default)
593
+ allow(subject).to receive(:load_vm).with('10', oda).and_return(vm1)
594
+ allow(subject).to receive(:load_vm).with('20', oda).and_return(vm2)
595
+ allow(subject).to receive(:load_vm).with('30', oda).and_return(vm3)
596
+ end
597
+
598
+ let(:vms) { '10|20|30' }
599
+ let(:user_map) { { '120' => 'user_name' } }
600
+ let(:image_map) { { '31' => 'image_name' } }
601
+ let(:vm1) do
602
+ xml = File.read("#{GEM_DIR}/mock/one_worker_vm1.xml")
603
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
604
+ end
605
+ let(:vm2) do
606
+ xml = File.read("#{GEM_DIR}/mock/one_worker_vm2.xml")
607
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
608
+ end
609
+ let(:vm3) do
610
+ xml = File.read("#{GEM_DIR}/mock/one_worker_vm3.xml")
611
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
612
+ end
613
+
614
+ let(:data) do
615
+ data = {}
616
+ data['endpoint'] = 'machine.hogwarts.co.uk'
617
+ data['site_name'] = 'Hogwarts'
618
+ data['cloud_type'] = 'OpenNebula'
619
+ data['vm_uuid'] = '36551'
620
+ data['start_time'] = '1383741160'
621
+ data['start_time_readable'] = '2013-11-06 13:32:40+01:00'
622
+ data['end_time'] = '1383742270'
623
+ data['machine_name'] = 'one-36551'
624
+ data['user_id'] = '120'
625
+ data['group_id'] = '0'
626
+ data['user_name'] = 'user_name'
627
+ data['fqan'] = 'gname'
628
+ data['status'] = 'completed'
629
+ data['duration'] = '596'
630
+ data['suspend'] = '514'
631
+ data['cpu_count'] = '1'
632
+ data['network_inbound'] = 0
633
+ data['network_outbound'] = 0
634
+ data['memory'] = '1736960'
635
+ data['image_name'] = 'image_name'
636
+
637
+ data
638
+ end
639
+
640
+ let(:vm1_data) { data }
641
+ let(:vm2_data) do
642
+ vm2_data = data.clone
643
+ vm2_data['vm_uuid'] = '36552'
644
+
645
+ vm2_data
646
+ end
647
+ let(:vm3_data) do
648
+ vm3_data = data.clone
649
+ vm3_data['vm_uuid'] = '36553'
650
+
651
+ vm3_data
652
+ end
653
+
654
+ context 'with valid vms' do
655
+ it 'writes vm data' do
656
+ expect(subject).to receive(:write_data).with([vm1_data, vm2_data, vm3_data], anything)
657
+ subject.perform(vms, 'output_dir')
658
+ end
659
+ end
660
+
661
+ context 'with one vm not loaded correclty' do
662
+ before :example do
663
+ allow(subject).to receive(:load_vm).with('20', oda).and_return(nil)
664
+ end
665
+
666
+ it 'writes data of the correct vms' do
667
+ expect(subject).to receive(:write_data).with([vm1_data, vm3_data], anything)
668
+ subject.perform(vms, 'output_dir')
669
+ end
670
+ end
671
+
672
+ context 'with one vm that has malformed data' do
673
+ let(:vm2) do
674
+ xml = File.read("#{GEM_DIR}/mock/one_worker_malformed_vm.xml")
675
+ OpenNebula::XMLElement.new(OpenNebula::XMLElement.build_xml(xml, 'VM'))
676
+ end
677
+
678
+ it 'writes data of the correct vms' do
679
+ expect(subject).to receive(:write_data).with([vm1_data, vm3_data], anything)
680
+ subject.perform(vms, 'output_dir')
681
+ end
682
+ end
683
+ end
684
+ end