]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; |
2 | import { ComponentFixture, TestBed } from '@angular/core/testing'; | |
3 | import { ReactiveFormsModule } from '@angular/forms'; | |
4 | import { ActivatedRoute } from '@angular/router'; | |
5 | import { RouterTestingModule } from '@angular/router/testing'; | |
6 | ||
494da23a | 7 | import { ToastrModule } from 'ngx-toastr'; |
11fdf7f2 TL |
8 | |
9 | import { ActivatedRouteStub } from '../../../../testing/activated-route-stub'; | |
10 | import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper'; | |
11 | import { SharedModule } from '../../../shared/shared.module'; | |
12 | import { IscsiTargetFormComponent } from './iscsi-target-form.component'; | |
13 | ||
14 | describe('IscsiTargetFormComponent', () => { | |
15 | let component: IscsiTargetFormComponent; | |
16 | let fixture: ComponentFixture<IscsiTargetFormComponent>; | |
17 | let httpTesting: HttpTestingController; | |
18 | let activatedRoute: ActivatedRouteStub; | |
19 | ||
20 | const SETTINGS = { | |
21 | config: { minimum_gateways: 2 }, | |
22 | disk_default_controls: { | |
23 | 'backstore:1': { | |
24 | hw_max_sectors: 1024, | |
25 | osd_op_timeout: 30 | |
26 | }, | |
27 | 'backstore:2': { | |
28 | qfull_timeout: 5 | |
29 | } | |
30 | }, | |
31 | target_default_controls: { | |
32 | cmdsn_depth: 128, | |
33 | dataout_timeout: 20, | |
eafe8130 | 34 | immediate_data: true |
11fdf7f2 TL |
35 | }, |
36 | required_rbd_features: { | |
37 | 'backstore:1': 0, | |
38 | 'backstore:2': 0 | |
39 | }, | |
81eedcae TL |
40 | unsupported_rbd_features: { |
41 | 'backstore:1': 0, | |
42 | 'backstore:2': 0 | |
11fdf7f2 TL |
43 | }, |
44 | backstores: ['backstore:1', 'backstore:2'], | |
eafe8130 TL |
45 | default_backstore: 'backstore:1', |
46 | api_version: 1 | |
11fdf7f2 TL |
47 | }; |
48 | ||
49 | const LIST_TARGET = [ | |
50 | { | |
51 | target_iqn: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw', | |
52 | portals: [{ host: 'node1', ip: '192.168.100.201' }], | |
eafe8130 TL |
53 | disks: [ |
54 | { | |
55 | pool: 'rbd', | |
56 | image: 'disk_1', | |
57 | controls: {}, | |
58 | backstore: 'backstore:1', | |
59 | wwn: '64af6678-9694-4367-bacc-f8eb0baa' | |
60 | } | |
61 | ], | |
11fdf7f2 TL |
62 | clients: [ |
63 | { | |
64 | client_iqn: 'iqn.1994-05.com.redhat:rh7-client', | |
eafe8130 | 65 | luns: [{ pool: 'rbd', image: 'disk_1', lun: 0 }], |
11fdf7f2 TL |
66 | auth: { |
67 | user: 'myiscsiusername', | |
68 | password: 'myiscsipassword', | |
69 | mutual_user: null, | |
70 | mutual_password: null | |
71 | } | |
72 | } | |
73 | ], | |
74 | groups: [], | |
75 | target_controls: {} | |
76 | } | |
77 | ]; | |
78 | ||
79 | const PORTALS = [ | |
80 | { name: 'node1', ip_addresses: ['192.168.100.201', '10.0.2.15'] }, | |
81 | { name: 'node2', ip_addresses: ['192.168.100.202'] } | |
82 | ]; | |
83 | ||
eafe8130 TL |
84 | const VERSION = { |
85 | ceph_iscsi_config_version: 11 | |
86 | }; | |
87 | ||
11fdf7f2 TL |
88 | const RBD_LIST = [ |
89 | { status: 0, value: [], pool_name: 'ganesha' }, | |
90 | { | |
91 | status: 0, | |
92 | value: [ | |
93 | { | |
94 | size: 96636764160, | |
95 | obj_size: 4194304, | |
96 | num_objs: 23040, | |
97 | order: 22, | |
98 | block_name_prefix: 'rbd_data.148162fb31a8', | |
99 | name: 'disk_1', | |
100 | id: '148162fb31a8', | |
101 | pool_name: 'rbd', | |
102 | features: 61, | |
103 | features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'], | |
104 | timestamp: '2019-01-18T10:44:26Z', | |
105 | stripe_count: 1, | |
106 | stripe_unit: 4194304, | |
107 | data_pool: null, | |
108 | parent: null, | |
109 | snapshots: [], | |
110 | total_disk_usage: 0, | |
111 | disk_usage: 0 | |
112 | }, | |
113 | { | |
114 | size: 119185342464, | |
115 | obj_size: 4194304, | |
116 | num_objs: 28416, | |
117 | order: 22, | |
118 | block_name_prefix: 'rbd_data.14b292cee6cb', | |
119 | name: 'disk_2', | |
120 | id: '14b292cee6cb', | |
121 | pool_name: 'rbd', | |
122 | features: 61, | |
123 | features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'], | |
124 | timestamp: '2019-01-18T10:45:56Z', | |
125 | stripe_count: 1, | |
126 | stripe_unit: 4194304, | |
127 | data_pool: null, | |
128 | parent: null, | |
129 | snapshots: [], | |
130 | total_disk_usage: 0, | |
131 | disk_usage: 0 | |
132 | } | |
133 | ], | |
134 | pool_name: 'rbd' | |
135 | } | |
136 | ]; | |
137 | ||
138 | configureTestBed( | |
139 | { | |
140 | declarations: [IscsiTargetFormComponent], | |
141 | imports: [ | |
142 | SharedModule, | |
143 | ReactiveFormsModule, | |
144 | HttpClientTestingModule, | |
145 | RouterTestingModule, | |
494da23a | 146 | ToastrModule.forRoot() |
11fdf7f2 TL |
147 | ], |
148 | providers: [ | |
149 | i18nProviders, | |
150 | { | |
151 | provide: ActivatedRoute, | |
152 | useValue: new ActivatedRouteStub({ target_iqn: undefined }) | |
153 | } | |
154 | ] | |
155 | }, | |
156 | true | |
157 | ); | |
158 | ||
159 | beforeEach(() => { | |
160 | fixture = TestBed.createComponent(IscsiTargetFormComponent); | |
161 | component = fixture.componentInstance; | |
162 | httpTesting = TestBed.get(HttpTestingController); | |
163 | activatedRoute = TestBed.get(ActivatedRoute); | |
164 | fixture.detectChanges(); | |
165 | ||
166 | httpTesting.expectOne('ui-api/iscsi/settings').flush(SETTINGS); | |
167 | httpTesting.expectOne('ui-api/iscsi/portals').flush(PORTALS); | |
eafe8130 | 168 | httpTesting.expectOne('ui-api/iscsi/version').flush(VERSION); |
11fdf7f2 TL |
169 | httpTesting.expectOne('api/summary').flush({}); |
170 | httpTesting.expectOne('api/block/image').flush(RBD_LIST); | |
171 | httpTesting.expectOne('api/iscsi/target').flush(LIST_TARGET); | |
172 | httpTesting.verify(); | |
173 | }); | |
174 | ||
175 | it('should create', () => { | |
176 | expect(component).toBeTruthy(); | |
177 | }); | |
178 | ||
179 | it('should only show images not used in other targets', () => { | |
180 | expect(component.imagesAll).toEqual([RBD_LIST[1]['value'][1]]); | |
181 | expect(component.imagesSelections).toEqual([ | |
81eedcae | 182 | { description: '', name: 'rbd/disk_2', selected: false, enabled: true } |
11fdf7f2 TL |
183 | ]); |
184 | }); | |
185 | ||
186 | it('should generate portals selectOptions', () => { | |
187 | expect(component.portalsSelections).toEqual([ | |
81eedcae TL |
188 | { description: '', name: 'node1:192.168.100.201', selected: false, enabled: true }, |
189 | { description: '', name: 'node1:10.0.2.15', selected: false, enabled: true }, | |
190 | { description: '', name: 'node2:192.168.100.202', selected: false, enabled: true } | |
11fdf7f2 TL |
191 | ]); |
192 | }); | |
193 | ||
194 | it('should create the form', () => { | |
195 | expect(component.targetForm.value).toEqual({ | |
196 | disks: [], | |
197 | groups: [], | |
198 | initiators: [], | |
199 | acl_enabled: false, | |
eafe8130 TL |
200 | auth: { |
201 | password: '', | |
202 | user: '', | |
203 | mutual_password: '', | |
204 | mutual_user: '' | |
205 | }, | |
11fdf7f2 TL |
206 | portals: [], |
207 | target_controls: {}, | |
208 | target_iqn: component.targetForm.value.target_iqn | |
209 | }); | |
210 | }); | |
211 | ||
212 | it('should prepare data when selecting an image', () => { | |
213 | expect(component.imagesSettings).toEqual({}); | |
214 | component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } }); | |
215 | expect(component.imagesSettings).toEqual({ | |
216 | 'rbd/disk_2': { | |
eafe8130 | 217 | lun: 0, |
11fdf7f2 TL |
218 | backstore: 'backstore:1', |
219 | 'backstore:1': {} | |
220 | } | |
221 | }); | |
222 | }); | |
223 | ||
224 | it('should clean data when removing an image', () => { | |
225 | component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } }); | |
226 | component.addGroup(); | |
227 | component.groups.controls[0].patchValue({ | |
228 | group_id: 'foo', | |
229 | disks: ['rbd/disk_2'] | |
230 | }); | |
231 | ||
232 | expect(component.groups.controls[0].value).toEqual({ | |
233 | disks: ['rbd/disk_2'], | |
234 | group_id: 'foo', | |
235 | members: [] | |
236 | }); | |
237 | ||
238 | component.onImageSelection({ option: { name: 'rbd/disk_2', selected: false } }); | |
239 | ||
240 | expect(component.groups.controls[0].value).toEqual({ disks: [], group_id: 'foo', members: [] }); | |
241 | expect(component.imagesSettings).toEqual({ | |
242 | 'rbd/disk_2': { | |
eafe8130 | 243 | lun: 0, |
11fdf7f2 TL |
244 | backstore: 'backstore:1', |
245 | 'backstore:1': {} | |
246 | } | |
247 | }); | |
248 | }); | |
249 | ||
250 | describe('should test initiators', () => { | |
251 | beforeEach(() => { | |
eafe8130 | 252 | component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } }); |
11fdf7f2 TL |
253 | component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true }); |
254 | component.addGroup().patchValue({ name: 'group_1' }); | |
81eedcae | 255 | component.addGroup().patchValue({ name: 'group_2' }); |
11fdf7f2 TL |
256 | |
257 | component.addInitiator(); | |
258 | component.initiators.controls[0].patchValue({ | |
259 | client_iqn: 'iqn.initiator' | |
260 | }); | |
261 | component.updatedInitiatorSelector(); | |
262 | }); | |
263 | ||
264 | it('should prepare data when creating an initiator', () => { | |
265 | expect(component.initiators.controls.length).toBe(1); | |
266 | expect(component.initiators.controls[0].value).toEqual({ | |
267 | auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, | |
268 | cdIsInGroup: false, | |
269 | client_iqn: 'iqn.initiator', | |
270 | luns: [] | |
271 | }); | |
272 | expect(component.imagesInitiatorSelections).toEqual([ | |
81eedcae | 273 | [{ description: '', name: 'rbd/disk_2', selected: false, enabled: true }] |
11fdf7f2 TL |
274 | ]); |
275 | expect(component.groupMembersSelections).toEqual([ | |
81eedcae TL |
276 | [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }], |
277 | [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }] | |
11fdf7f2 TL |
278 | ]); |
279 | }); | |
280 | ||
281 | it('should update data when changing an initiator name', () => { | |
282 | expect(component.groupMembersSelections).toEqual([ | |
81eedcae TL |
283 | [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }], |
284 | [{ description: '', name: 'iqn.initiator', selected: false, enabled: true }] | |
11fdf7f2 TL |
285 | ]); |
286 | ||
287 | component.initiators.controls[0].patchValue({ | |
288 | client_iqn: 'iqn.initiator_new' | |
289 | }); | |
290 | component.updatedInitiatorSelector(); | |
291 | ||
292 | expect(component.groupMembersSelections).toEqual([ | |
81eedcae TL |
293 | [{ description: '', name: 'iqn.initiator_new', selected: false, enabled: true }], |
294 | [{ description: '', name: 'iqn.initiator_new', selected: false, enabled: true }] | |
11fdf7f2 TL |
295 | ]); |
296 | }); | |
297 | ||
298 | it('should clean data when removing an initiator', () => { | |
299 | component.groups.controls[0].patchValue({ | |
300 | group_id: 'foo', | |
301 | members: ['iqn.initiator'] | |
302 | }); | |
303 | ||
304 | expect(component.groups.controls[0].value).toEqual({ | |
305 | disks: [], | |
306 | group_id: 'foo', | |
307 | members: ['iqn.initiator'] | |
308 | }); | |
309 | ||
310 | component.removeInitiator(0); | |
311 | ||
312 | expect(component.groups.controls[0].value).toEqual({ | |
313 | disks: [], | |
314 | group_id: 'foo', | |
315 | members: [] | |
316 | }); | |
81eedcae | 317 | expect(component.groupMembersSelections).toEqual([[], []]); |
11fdf7f2 TL |
318 | expect(component.imagesInitiatorSelections).toEqual([]); |
319 | }); | |
320 | ||
321 | it('should remove images in the initiator when added in a group', () => { | |
322 | component.initiators.controls[0].patchValue({ | |
323 | luns: ['rbd/disk_2'] | |
324 | }); | |
325 | expect(component.initiators.controls[0].value).toEqual({ | |
326 | auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, | |
327 | cdIsInGroup: false, | |
328 | client_iqn: 'iqn.initiator', | |
329 | luns: ['rbd/disk_2'] | |
330 | }); | |
331 | ||
332 | component.addGroup(); | |
333 | component.groups.controls[0].patchValue({ | |
334 | group_id: 'foo', | |
335 | members: ['iqn.initiator'] | |
336 | }); | |
337 | component.onGroupMemberSelection({ | |
338 | option: { | |
339 | name: 'iqn.initiator', | |
340 | selected: true | |
341 | } | |
342 | }); | |
343 | ||
344 | expect(component.initiators.controls[0].value).toEqual({ | |
345 | auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, | |
346 | cdIsInGroup: true, | |
347 | client_iqn: 'iqn.initiator', | |
348 | luns: [] | |
349 | }); | |
350 | }); | |
81eedcae TL |
351 | |
352 | it('should disabled the initiator when selected', () => { | |
353 | expect(component.groupMembersSelections).toEqual([ | |
354 | [{ description: '', enabled: true, name: 'iqn.initiator', selected: false }], | |
355 | [{ description: '', enabled: true, name: 'iqn.initiator', selected: false }] | |
356 | ]); | |
357 | ||
358 | component.groupMembersSelections[0][0].selected = true; | |
359 | component.onGroupMemberSelection({ option: { name: 'iqn.initiator', selected: true } }); | |
360 | ||
361 | expect(component.groupMembersSelections).toEqual([ | |
362 | [{ description: '', enabled: false, name: 'iqn.initiator', selected: true }], | |
363 | [{ description: '', enabled: false, name: 'iqn.initiator', selected: false }] | |
364 | ]); | |
365 | }); | |
11fdf7f2 TL |
366 | }); |
367 | ||
368 | describe('should submit request', () => { | |
369 | beforeEach(() => { | |
11fdf7f2 | 370 | component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } }); |
eafe8130 | 371 | component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true }); |
11fdf7f2 TL |
372 | component.portals.setValue(['node1:192.168.100.201', 'node2:192.168.100.202']); |
373 | component.addInitiator().patchValue({ | |
374 | client_iqn: 'iqn.initiator' | |
375 | }); | |
376 | component.addGroup().patchValue({ | |
377 | group_id: 'foo', | |
378 | members: ['iqn.initiator'], | |
379 | disks: ['rbd/disk_2'] | |
380 | }); | |
381 | }); | |
382 | ||
383 | it('should call update', () => { | |
384 | activatedRoute.setParams({ target_iqn: 'iqn.iscsi' }); | |
385 | component.isEdit = true; | |
386 | component.target_iqn = 'iqn.iscsi'; | |
387 | ||
388 | component.submit(); | |
389 | ||
390 | const req = httpTesting.expectOne('api/iscsi/target/iqn.iscsi'); | |
391 | expect(req.request.method).toBe('PUT'); | |
392 | expect(req.request.body).toEqual({ | |
393 | clients: [ | |
394 | { | |
395 | auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, | |
396 | client_iqn: 'iqn.initiator', | |
397 | luns: [] | |
398 | } | |
399 | ], | |
eafe8130 TL |
400 | disks: [ |
401 | { | |
402 | backstore: 'backstore:1', | |
403 | controls: {}, | |
404 | image: 'disk_2', | |
405 | pool: 'rbd', | |
406 | lun: 0, | |
407 | wwn: undefined | |
408 | } | |
409 | ], | |
11fdf7f2 TL |
410 | groups: [ |
411 | { disks: [{ image: 'disk_2', pool: 'rbd' }], group_id: 'foo', members: ['iqn.initiator'] } | |
412 | ], | |
413 | new_target_iqn: component.targetForm.value.target_iqn, | |
414 | portals: [ | |
415 | { host: 'node1', ip: '192.168.100.201' }, | |
416 | { host: 'node2', ip: '192.168.100.202' } | |
417 | ], | |
418 | target_controls: {}, | |
419 | target_iqn: component.target_iqn, | |
eafe8130 TL |
420 | acl_enabled: true, |
421 | auth: { | |
422 | password: '', | |
423 | user: '', | |
424 | mutual_password: '', | |
425 | mutual_user: '' | |
426 | } | |
11fdf7f2 TL |
427 | }); |
428 | }); | |
429 | ||
430 | it('should call create', () => { | |
431 | component.submit(); | |
432 | ||
433 | const req = httpTesting.expectOne('api/iscsi/target'); | |
434 | expect(req.request.method).toBe('POST'); | |
435 | expect(req.request.body).toEqual({ | |
436 | clients: [ | |
437 | { | |
438 | auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, | |
439 | client_iqn: 'iqn.initiator', | |
440 | luns: [] | |
441 | } | |
442 | ], | |
eafe8130 TL |
443 | disks: [ |
444 | { | |
445 | backstore: 'backstore:1', | |
446 | controls: {}, | |
447 | image: 'disk_2', | |
448 | pool: 'rbd', | |
449 | lun: 0, | |
450 | wwn: undefined | |
451 | } | |
452 | ], | |
11fdf7f2 TL |
453 | groups: [ |
454 | { | |
455 | disks: [{ image: 'disk_2', pool: 'rbd' }], | |
456 | group_id: 'foo', | |
457 | members: ['iqn.initiator'] | |
458 | } | |
459 | ], | |
460 | portals: [ | |
461 | { host: 'node1', ip: '192.168.100.201' }, | |
462 | { host: 'node2', ip: '192.168.100.202' } | |
463 | ], | |
464 | target_controls: {}, | |
465 | target_iqn: component.targetForm.value.target_iqn, | |
eafe8130 TL |
466 | acl_enabled: true, |
467 | auth: { | |
468 | password: '', | |
469 | user: '', | |
470 | mutual_password: '', | |
471 | mutual_user: '' | |
472 | } | |
11fdf7f2 TL |
473 | }); |
474 | }); | |
475 | ||
476 | it('should call create with acl_enabled disabled', () => { | |
477 | component.targetForm.patchValue({ acl_enabled: false }); | |
478 | component.submit(); | |
479 | ||
480 | const req = httpTesting.expectOne('api/iscsi/target'); | |
481 | expect(req.request.method).toBe('POST'); | |
482 | expect(req.request.body).toEqual({ | |
483 | clients: [], | |
eafe8130 TL |
484 | disks: [ |
485 | { | |
486 | backstore: 'backstore:1', | |
487 | controls: {}, | |
488 | image: 'disk_2', | |
489 | pool: 'rbd', | |
490 | lun: 0, | |
491 | wwn: undefined | |
492 | } | |
493 | ], | |
11fdf7f2 TL |
494 | groups: [], |
495 | acl_enabled: false, | |
eafe8130 TL |
496 | auth: { |
497 | password: '', | |
498 | user: '', | |
499 | mutual_password: '', | |
500 | mutual_user: '' | |
501 | }, | |
11fdf7f2 TL |
502 | portals: [ |
503 | { host: 'node1', ip: '192.168.100.201' }, | |
504 | { host: 'node2', ip: '192.168.100.202' } | |
505 | ], | |
506 | target_controls: {}, | |
507 | target_iqn: component.targetForm.value.target_iqn | |
508 | }); | |
509 | }); | |
510 | }); | |
511 | }); |