From: Tiago Melo Date: Wed, 16 Sep 2020 15:57:51 +0000 (+0000) Subject: mgr/dashboard: Allow managing iSCSI Initiator after removing from group X-Git-Tag: v16.1.0~415^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=38a1829ed30cb9bb04a46131b5960edd9dc791b8;p=ceph.git mgr/dashboard: Allow managing iSCSI Initiator after removing from group Fixes: https://tracker.ceph.com/issues/47445 Signed-off-by: Tiago Melo --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html index 825e821144a6..9dcdaedc0460 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html @@ -572,7 +572,7 @@ Group: {{ group.getValue('group_id') }} @@ -618,7 +618,7 @@ Add initiator diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts index fb6eef30e8a4..f60471a0e86b 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.spec.ts @@ -4,6 +4,7 @@ import { ReactiveFormsModule } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; +import { SelectOption } from 'app/shared/components/select/select-option.model'; import { ToastrModule } from 'ngx-toastr'; import { ActivatedRouteStub } from '../../../../testing/activated-route-stub'; @@ -329,6 +330,14 @@ describe('IscsiTargetFormComponent', () => { component.initiators.controls[0].patchValue({ luns: ['rbd/disk_2'] }); + component.imagesInitiatorSelections[0] = [ + { + description: '', + enabled: true, + name: 'rbd/disk_2', + selected: true + } + ]; expect(component.initiators.controls[0].value).toEqual({ auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, cdIsInGroup: false, @@ -336,17 +345,19 @@ describe('IscsiTargetFormComponent', () => { luns: ['rbd/disk_2'] }); - component.addGroup(); component.groups.controls[0].patchValue({ group_id: 'foo', members: ['iqn.initiator'] }); - component.onGroupMemberSelection({ - option: { - name: 'iqn.initiator', - selected: true - } - }); + component.onGroupMemberSelection( + { + option: { + name: 'iqn.initiator', + selected: true + } + }, + 0 + ); expect(component.initiators.controls[0].value).toEqual({ auth: { mutual_password: '', mutual_user: '', password: '', user: '' }, @@ -354,6 +365,14 @@ describe('IscsiTargetFormComponent', () => { client_iqn: 'iqn.initiator', luns: [] }); + expect(component.imagesInitiatorSelections[0]).toEqual([ + { + description: '', + enabled: true, + name: 'rbd/disk_2', + selected: false + } + ]); }); it('should disabled the initiator when selected', () => { @@ -363,7 +382,7 @@ describe('IscsiTargetFormComponent', () => { ]); component.groupMembersSelections[0][0].selected = true; - component.onGroupMemberSelection({ option: { name: 'iqn.initiator', selected: true } }); + component.onGroupMemberSelection({ option: { name: 'iqn.initiator', selected: true } }, 0); expect(component.groupMembersSelections).toEqual([ [{ description: '', enabled: false, name: 'iqn.initiator', selected: true }], @@ -371,6 +390,49 @@ describe('IscsiTargetFormComponent', () => { ]); }); + describe('should remove from group', () => { + beforeEach(() => { + component.onGroupMemberSelection( + { option: new SelectOption(true, 'iqn.initiator', '') }, + 0 + ); + component.groupDiskSelections[0][0].selected = true; + component.groups.controls[0].patchValue({ + disks: ['rbd/disk_2'], + members: ['iqn.initiator'] + }); + + expect(component.initiators.value[0].luns).toEqual([]); + expect(component.imagesInitiatorSelections[0]).toEqual([ + { description: '', enabled: true, name: 'rbd/disk_2', selected: false } + ]); + expect(component.initiators.value[0].cdIsInGroup).toBe(true); + }); + + it('should update initiator images when deselecting', () => { + component.onGroupMemberSelection( + { option: new SelectOption(false, 'iqn.initiator', '') }, + 0 + ); + + expect(component.initiators.value[0].luns).toEqual(['rbd/disk_2']); + expect(component.imagesInitiatorSelections[0]).toEqual([ + { description: '', enabled: true, name: 'rbd/disk_2', selected: true } + ]); + expect(component.initiators.value[0].cdIsInGroup).toBe(false); + }); + + it('should update initiator when removing', () => { + component.removeGroupInitiator(component.groups.controls[0] as CdFormGroup, 0, 0); + + expect(component.initiators.value[0].luns).toEqual(['rbd/disk_2']); + expect(component.imagesInitiatorSelections[0]).toEqual([ + { description: '', enabled: true, name: 'rbd/disk_2', selected: true } + ]); + expect(component.initiators.value[0].cdIsInGroup).toBe(false); + }); + }); + it('should validate authentication', () => { const control = component.initiators.controls[0]; const formHelper = new FormHelper(control as CdFormGroup); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts index eefb0bca28fa..40e83117fb2f 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts @@ -264,12 +264,12 @@ export class IscsiTargetFormComponent extends CdForm implements OnInit { // updatedInitiatorSelector() }); - _.forEach(res.groups, (group) => { + (res.groups as any[]).forEach((group: any, group_index: number) => { const fg = this.addGroup(); group.disks = _.map(group.disks, (disk) => `${disk.pool}/${disk.image}`); fg.patchValue(group); _.forEach(group.members, (member) => { - this.onGroupMemberSelection({ option: new SelectOption(true, member, '') }); + this.onGroupMemberSelection({ option: new SelectOption(true, member, '') }, group_index); }); }); } @@ -577,26 +577,44 @@ export class IscsiTargetFormComponent extends CdForm implements OnInit { } removeGroup(index: number) { + // Remove group and disk selections this.groups.removeAt(index); + + // Free initiator from group + const selectedMembers = this.groupMembersSelections[index].filter((value) => value.selected); + selectedMembers.forEach((selection) => { + selection.selected = false; + this.onGroupMemberSelection({ option: selection }, index); + }); + + this.groupMembersSelections.splice(index, 1); this.groupDiskSelections.splice(index, 1); } - onGroupMemberSelection($event: any) { + onGroupMemberSelection($event: any, group_index: number) { const option = $event.option; - let initiator_index: number; + let luns: string[] = []; + if (!option.selected) { + const selectedDisks = this.groupDiskSelections[group_index].filter((value) => value.selected); + luns = selectedDisks.map((value) => value.name); + } + this.initiators.controls.forEach((element, index) => { if (element.value.client_iqn === option.name) { - element.patchValue({ luns: [] }); + element.patchValue({ luns: luns }); element.get('cdIsInGroup').setValue(option.selected); - initiator_index = index; - } - }); - // Members can only be at one group at a time, so when a member is selected - // in one group we need to disable its selection in other groups - _.forEach(this.groupMembersSelections, (group) => { - group[initiator_index].enabled = !option.selected; + // Members can only be at one group at a time, so when a member is selected + // in one group we need to disable its selection in other groups + _.forEach(this.groupMembersSelections, (group) => { + group[index].enabled = !option.selected; + }); + + this.imagesInitiatorSelections[index].forEach((image) => { + image.selected = luns.includes(image.name); + }); + } }); } @@ -604,14 +622,7 @@ export class IscsiTargetFormComponent extends CdForm implements OnInit { const name = group.getValue('members')[member_index]; group.getValue('members').splice(member_index, 1); - this.groupMembersSelections[group_index].forEach((value) => { - if (value.name === name) { - value.selected = false; - } - }); - this.groupMembersSelections[group_index] = [...this.groupMembersSelections[group_index]]; - - this.onGroupMemberSelection({ option: new SelectOption(false, name, '') }); + this.onGroupMemberSelection({ option: new SelectOption(false, name, '') }, group_index); } removeGroupDisk(group: CdFormGroup, disk_index: number, group_index: number) {