From 4275a5e470ed15f35e0639f87b298572cc928fb4 Mon Sep 17 00:00:00 2001 From: Avan Thakkar Date: Thu, 27 Jun 2024 15:36:42 +0530 Subject: [PATCH] mgr/dashboard: nfs export enhancement for CEPHFS Fixes: https://tracker.ceph.com/issues/66718 Signed-off-by: Avan Thakkar (cherry picked from commit 69a45db9c3cc9ed4ac36e7f2d6db78bd7940530b) --- .../mgr/dashboard/controllers/cephfs.py | 9 +++ .../ceph/nfs/nfs-form/nfs-form.component.html | 54 ++++++++++++++- .../nfs/nfs-form/nfs-form.component.spec.ts | 4 +- .../ceph/nfs/nfs-form/nfs-form.component.ts | 67 ++++++++++++++++--- 4 files changed, 124 insertions(+), 10 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/cephfs.py b/src/pybind/mgr/dashboard/controllers/cephfs.py index fcd87833f85fc..7183808e19f17 100644 --- a/src/pybind/mgr/dashboard/controllers/cephfs.py +++ b/src/pybind/mgr/dashboard/controllers/cephfs.py @@ -826,6 +826,15 @@ class CephFSSubvolumeGroups(RESTController): f'Failed to get info for subvolume group {group["name"]}: {err}' ) group['info'] = json.loads(out) + + error_code, out, err = mgr.remote('volumes', '_cmd_fs_subvolumegroup_getpath', + None, {'vol_name': vol_name, + 'group_name': group['name']}) + if error_code != 0: + raise DashboardException( + f'Failed to get path for subvolume group {group["name"]}: {err}' + ) + group['info']['path'] = out return subvolume_groups @RESTController.Resource('GET') diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html index 1ab3ed173ce81..a83091a2c39a1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html @@ -90,7 +90,7 @@ formControlName="fs_name" name="fs_name" id="fs_name" - (change)="pathChangeHandler()"> + (change)="volumeChangeHandler()"> @@ -145,6 +145,58 @@ +
+ +
+ +
+
+ +
+ +
+ +
+
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts index 62efec423d36a..3273468bb4b10 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts @@ -96,13 +96,15 @@ describe('NfsFormComponent', () => { access_type: 'RW', clients: [], cluster_id: 'mynfs', - fsal: { fs_name: 'a', name: 'CEPH' }, + fsal: { fs_name: '', name: 'CEPH' }, path: '/', protocolNfsv4: true, pseudo: '', sec_label_xattr: 'security.selinux', security_label: false, squash: 'no_root_squash', + subvolume: '', + subvolume_group: '', transportTCP: true, transportUDP: true }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts index 540b7bfe64bee..438c01a7370ca 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts @@ -28,6 +28,8 @@ import { CdHttpErrorResponse } from '~/app/shared/services/api-interceptor.servi import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service'; import { NfsFormClientComponent } from '../nfs-form-client/nfs-form-client.component'; +import { CephfsSubvolumeService } from '~/app/shared/api/cephfs-subvolume.service'; +import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service'; @Component({ selector: 'cd-nfs-form', @@ -61,6 +63,10 @@ export class NfsFormComponent extends CdForm implements OnInit { action: string; resource: string; + allsubvolgrps: any[] = []; + allsubvols: any[] = []; + fsPath: string = null; + pathDataSource = (text$: Observable) => { return text$.pipe( debounceTime(200), @@ -81,6 +87,8 @@ export class NfsFormComponent extends CdForm implements OnInit { constructor( private authStorageService: AuthStorageService, private nfsService: NfsService, + private subvolService: CephfsSubvolumeService, + private subvolgrpService: CephfsSubvolumeGroupService, private route: ActivatedRoute, private router: Router, private rgwBucketService: RgwBucketService, @@ -138,6 +146,49 @@ export class NfsFormComponent extends CdForm implements OnInit { }); } + volumeChangeHandler() { + this.pathChangeHandler(); + const fs_name = this.nfsForm.getValue('fsal').fs_name; + this.getSubVolGrp(fs_name); + } + + getSubVol() { + this.getPath(); + const fs_name = this.nfsForm.getValue('fsal').fs_name; + const subvolgrp = this.nfsForm.getValue('subvolume_group'); + return this.subvolService.get(fs_name, subvolgrp).subscribe((data: any) => { + this.allsubvols = data; + }); + } + + getSubVolGrp(fs_name: string) { + return this.subvolgrpService.get(fs_name).subscribe((data: any) => { + this.allsubvolgrps = data; + }); + } + + getFsPath(volList: any[], value: string) { + const match = volList.find((vol) => vol.name === value); + if (match) { + return match.info.path; + } + } + + getPath() { + const subvol = this.nfsForm.getValue('subvolume'); + if (subvol === '') { + const subvolGroup = this.nfsForm.getValue('subvolume_group'); + this.fsPath = this.getFsPath(this.allsubvolgrps, subvolGroup); + } else { + this.fsPath = this.getFsPath(this.allsubvols, subvol); + } + this.nfsForm.patchValue({ + path: this.fsPath + }); + + this.pathChangeHandler(); + } + createForm() { this.nfsForm = new CdFormGroup({ cluster_id: new UntypedFormControl('', { @@ -155,7 +206,11 @@ export class NfsFormComponent extends CdForm implements OnInit { ] }) }), - path: new UntypedFormControl('/'), + subvolume_group: new UntypedFormControl(''), + subvolume: new UntypedFormControl(''), + path: new UntypedFormControl('/', { + validators: [Validators.required] + }), protocolNfsv4: new UntypedFormControl(true), pseudo: new UntypedFormControl('', { validators: [ @@ -253,13 +308,6 @@ export class NfsFormComponent extends CdForm implements OnInit { resolveFilesystems(filesystems: any[]) { this.allFsNames = filesystems; - if (!this.isEdit && filesystems.length > 0) { - this.nfsForm.patchValue({ - fsal: { - fs_name: filesystems[0].name - } - }); - } } fsalChangeHandler() { @@ -470,6 +518,9 @@ export class NfsFormComponent extends CdForm implements OnInit { delete requestModel.fsal.fs_name; } + delete requestModel.subvolume; + delete requestModel.subvolume_group; + requestModel.protocols = []; if (requestModel.protocolNfsv4) { requestModel.protocols.push(4); -- 2.39.5