]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/blob
29fc65aa22ea2540b1df2b965e18ebd166bacdc0
[ceph.git] /
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
7 import { ToastModule } from 'ng2-toastr';
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,
34       immediate_data: 'Yes'
35     },
36     required_rbd_features: {
37       'backstore:1': 0,
38       'backstore:2': 0
39     },
40     supported_rbd_features: {
41       'backstore:1': 61,
42       'backstore:2': 61
43     },
44     backstores: ['backstore:1', 'backstore:2'],
45     default_backstore: 'backstore:1'
46   };
47
48   const LIST_TARGET = [
49     {
50       target_iqn: 'iqn.2003-01.com.redhat.iscsi-gw:iscsi-igw',
51       portals: [{ host: 'node1', ip: '192.168.100.201' }],
52       disks: [{ pool: 'rbd', image: 'disk_1', controls: {}, backstore: 'backstore:1' }],
53       clients: [
54         {
55           client_iqn: 'iqn.1994-05.com.redhat:rh7-client',
56           luns: [{ pool: 'rbd', image: 'disk_1' }],
57           auth: {
58             user: 'myiscsiusername',
59             password: 'myiscsipassword',
60             mutual_user: null,
61             mutual_password: null
62           }
63         }
64       ],
65       groups: [],
66       target_controls: {}
67     }
68   ];
69
70   const PORTALS = [
71     { name: 'node1', ip_addresses: ['192.168.100.201', '10.0.2.15'] },
72     { name: 'node2', ip_addresses: ['192.168.100.202'] }
73   ];
74
75   const RBD_LIST = [
76     { status: 0, value: [], pool_name: 'ganesha' },
77     {
78       status: 0,
79       value: [
80         {
81           size: 96636764160,
82           obj_size: 4194304,
83           num_objs: 23040,
84           order: 22,
85           block_name_prefix: 'rbd_data.148162fb31a8',
86           name: 'disk_1',
87           id: '148162fb31a8',
88           pool_name: 'rbd',
89           features: 61,
90           features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'],
91           timestamp: '2019-01-18T10:44:26Z',
92           stripe_count: 1,
93           stripe_unit: 4194304,
94           data_pool: null,
95           parent: null,
96           snapshots: [],
97           total_disk_usage: 0,
98           disk_usage: 0
99         },
100         {
101           size: 119185342464,
102           obj_size: 4194304,
103           num_objs: 28416,
104           order: 22,
105           block_name_prefix: 'rbd_data.14b292cee6cb',
106           name: 'disk_2',
107           id: '14b292cee6cb',
108           pool_name: 'rbd',
109           features: 61,
110           features_name: ['deep-flatten', 'exclusive-lock', 'fast-diff', 'layering', 'object-map'],
111           timestamp: '2019-01-18T10:45:56Z',
112           stripe_count: 1,
113           stripe_unit: 4194304,
114           data_pool: null,
115           parent: null,
116           snapshots: [],
117           total_disk_usage: 0,
118           disk_usage: 0
119         }
120       ],
121       pool_name: 'rbd'
122     }
123   ];
124
125   configureTestBed(
126     {
127       declarations: [IscsiTargetFormComponent],
128       imports: [
129         SharedModule,
130         ReactiveFormsModule,
131         HttpClientTestingModule,
132         RouterTestingModule,
133         ToastModule.forRoot()
134       ],
135       providers: [
136         i18nProviders,
137         {
138           provide: ActivatedRoute,
139           useValue: new ActivatedRouteStub({ target_iqn: undefined })
140         }
141       ]
142     },
143     true
144   );
145
146   beforeEach(() => {
147     fixture = TestBed.createComponent(IscsiTargetFormComponent);
148     component = fixture.componentInstance;
149     httpTesting = TestBed.get(HttpTestingController);
150     activatedRoute = TestBed.get(ActivatedRoute);
151     fixture.detectChanges();
152
153     httpTesting.expectOne('ui-api/iscsi/settings').flush(SETTINGS);
154     httpTesting.expectOne('ui-api/iscsi/portals').flush(PORTALS);
155     httpTesting.expectOne('api/summary').flush({});
156     httpTesting.expectOne('api/block/image').flush(RBD_LIST);
157     httpTesting.expectOne('api/iscsi/target').flush(LIST_TARGET);
158     httpTesting.verify();
159   });
160
161   it('should create', () => {
162     expect(component).toBeTruthy();
163   });
164
165   it('should only show images not used in other targets', () => {
166     expect(component.imagesAll).toEqual([RBD_LIST[1]['value'][1]]);
167     expect(component.imagesSelections).toEqual([
168       { description: '', name: 'rbd/disk_2', selected: false }
169     ]);
170   });
171
172   it('should generate portals selectOptions', () => {
173     expect(component.portalsSelections).toEqual([
174       { description: '', name: 'node1:192.168.100.201', selected: false },
175       { description: '', name: 'node1:10.0.2.15', selected: false },
176       { description: '', name: 'node2:192.168.100.202', selected: false }
177     ]);
178   });
179
180   it('should create the form', () => {
181     expect(component.targetForm.value).toEqual({
182       disks: [],
183       groups: [],
184       initiators: [],
185       acl_enabled: false,
186       portals: [],
187       target_controls: {},
188       target_iqn: component.targetForm.value.target_iqn
189     });
190   });
191
192   it('should prepare data when selecting an image', () => {
193     expect(component.imagesSettings).toEqual({});
194     component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
195     expect(component.imagesSettings).toEqual({
196       'rbd/disk_2': {
197         backstore: 'backstore:1',
198         'backstore:1': {}
199       }
200     });
201   });
202
203   it('should clean data when removing an image', () => {
204     component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
205     component.addGroup();
206     component.groups.controls[0].patchValue({
207       group_id: 'foo',
208       disks: ['rbd/disk_2']
209     });
210
211     expect(component.groups.controls[0].value).toEqual({
212       disks: ['rbd/disk_2'],
213       group_id: 'foo',
214       members: []
215     });
216
217     component.onImageSelection({ option: { name: 'rbd/disk_2', selected: false } });
218
219     expect(component.groups.controls[0].value).toEqual({ disks: [], group_id: 'foo', members: [] });
220     expect(component.imagesSettings).toEqual({
221       'rbd/disk_2': {
222         backstore: 'backstore:1',
223         'backstore:1': {}
224       }
225     });
226   });
227
228   describe('should test initiators', () => {
229     beforeEach(() => {
230       component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true });
231       component.addGroup().patchValue({ name: 'group_1' });
232       component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
233
234       component.addInitiator();
235       component.initiators.controls[0].patchValue({
236         client_iqn: 'iqn.initiator'
237       });
238       component.updatedInitiatorSelector();
239     });
240
241     it('should prepare data when creating an initiator', () => {
242       expect(component.initiators.controls.length).toBe(1);
243       expect(component.initiators.controls[0].value).toEqual({
244         auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
245         cdIsInGroup: false,
246         client_iqn: 'iqn.initiator',
247         luns: []
248       });
249       expect(component.imagesInitiatorSelections).toEqual([
250         [{ description: '', name: 'rbd/disk_2', selected: false }]
251       ]);
252       expect(component.groupMembersSelections).toEqual([
253         [{ description: '', name: 'iqn.initiator', selected: false }]
254       ]);
255     });
256
257     it('should update data when changing an initiator name', () => {
258       expect(component.groupMembersSelections).toEqual([
259         [{ description: '', name: 'iqn.initiator', selected: false }]
260       ]);
261
262       component.initiators.controls[0].patchValue({
263         client_iqn: 'iqn.initiator_new'
264       });
265       component.updatedInitiatorSelector();
266
267       expect(component.groupMembersSelections).toEqual([
268         [{ description: '', name: 'iqn.initiator_new', selected: false }]
269       ]);
270     });
271
272     it('should clean data when removing an initiator', () => {
273       component.groups.controls[0].patchValue({
274         group_id: 'foo',
275         members: ['iqn.initiator']
276       });
277
278       expect(component.groups.controls[0].value).toEqual({
279         disks: [],
280         group_id: 'foo',
281         members: ['iqn.initiator']
282       });
283
284       component.removeInitiator(0);
285
286       expect(component.groups.controls[0].value).toEqual({
287         disks: [],
288         group_id: 'foo',
289         members: []
290       });
291       expect(component.groupMembersSelections).toEqual([[]]);
292       expect(component.imagesInitiatorSelections).toEqual([]);
293     });
294
295     it('should remove images in the initiator when added in a group', () => {
296       component.initiators.controls[0].patchValue({
297         luns: ['rbd/disk_2']
298       });
299       expect(component.initiators.controls[0].value).toEqual({
300         auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
301         cdIsInGroup: false,
302         client_iqn: 'iqn.initiator',
303         luns: ['rbd/disk_2']
304       });
305
306       component.addGroup();
307       component.groups.controls[0].patchValue({
308         group_id: 'foo',
309         members: ['iqn.initiator']
310       });
311       component.onGroupMemberSelection({
312         option: {
313           name: 'iqn.initiator',
314           selected: true
315         }
316       });
317
318       expect(component.initiators.controls[0].value).toEqual({
319         auth: { mutual_password: '', mutual_user: '', password: '', user: '' },
320         cdIsInGroup: true,
321         client_iqn: 'iqn.initiator',
322         luns: []
323       });
324     });
325   });
326
327   describe('should submit request', () => {
328     beforeEach(() => {
329       component.targetForm.patchValue({ disks: ['rbd/disk_2'], acl_enabled: true });
330       component.onImageSelection({ option: { name: 'rbd/disk_2', selected: true } });
331       component.portals.setValue(['node1:192.168.100.201', 'node2:192.168.100.202']);
332       component.addInitiator().patchValue({
333         client_iqn: 'iqn.initiator'
334       });
335       component.addGroup().patchValue({
336         group_id: 'foo',
337         members: ['iqn.initiator'],
338         disks: ['rbd/disk_2']
339       });
340     });
341
342     it('should call update', () => {
343       activatedRoute.setParams({ target_iqn: 'iqn.iscsi' });
344       component.isEdit = true;
345       component.target_iqn = 'iqn.iscsi';
346
347       component.submit();
348
349       const req = httpTesting.expectOne('api/iscsi/target/iqn.iscsi');
350       expect(req.request.method).toBe('PUT');
351       expect(req.request.body).toEqual({
352         clients: [
353           {
354             auth: { mutual_password: null, mutual_user: null, password: null, user: null },
355             cdIsInGroup: false,
356             client_iqn: 'iqn.initiator',
357             luns: []
358           }
359         ],
360         disks: [{ backstore: 'backstore:1', controls: {}, image: 'disk_2', pool: 'rbd' }],
361         groups: [
362           { disks: [{ image: 'disk_2', pool: 'rbd' }], group_id: 'foo', members: ['iqn.initiator'] }
363         ],
364         new_target_iqn: component.targetForm.value.target_iqn,
365         portals: [
366           { host: 'node1', ip: '192.168.100.201' },
367           { host: 'node2', ip: '192.168.100.202' }
368         ],
369         target_controls: {},
370         target_iqn: component.target_iqn,
371         acl_enabled: true
372       });
373     });
374
375     it('should call create', () => {
376       component.submit();
377
378       const req = httpTesting.expectOne('api/iscsi/target');
379       expect(req.request.method).toBe('POST');
380       expect(req.request.body).toEqual({
381         clients: [
382           {
383             auth: { mutual_password: null, mutual_user: null, password: null, user: null },
384             cdIsInGroup: false,
385             client_iqn: 'iqn.initiator',
386             luns: []
387           }
388         ],
389         disks: [{ backstore: 'backstore:1', controls: {}, image: 'disk_2', pool: 'rbd' }],
390         groups: [
391           {
392             disks: [{ image: 'disk_2', pool: 'rbd' }],
393             group_id: 'foo',
394             members: ['iqn.initiator']
395           }
396         ],
397         portals: [
398           { host: 'node1', ip: '192.168.100.201' },
399           { host: 'node2', ip: '192.168.100.202' }
400         ],
401         target_controls: {},
402         target_iqn: component.targetForm.value.target_iqn,
403         acl_enabled: true
404       });
405     });
406
407     it('should call create with acl_enabled disabled', () => {
408       component.targetForm.patchValue({ acl_enabled: false });
409       component.submit();
410
411       const req = httpTesting.expectOne('api/iscsi/target');
412       expect(req.request.method).toBe('POST');
413       expect(req.request.body).toEqual({
414         clients: [],
415         disks: [{ backstore: 'backstore:1', controls: {}, image: 'disk_2', pool: 'rbd' }],
416         groups: [],
417         acl_enabled: false,
418         portals: [
419           { host: 'node1', ip: '192.168.100.201' },
420           { host: 'node2', ip: '192.168.100.202' }
421         ],
422         target_controls: {},
423         target_iqn: component.targetForm.value.target_iqn
424       });
425     });
426   });
427 });