Skip to content

Commit 6052bfa

Browse files
authored
Merge pull request ceph#58303 from rhcs-dashboard/nfs-export-subvol
mgr/dashboard: nfs export enhancement for CEPHFS Reviewed-by: afreen23 <NOT@FOUND> Reviewed-by: Ankush Behl <[email protected]>
2 parents e7f3bed + 69a45db commit 6052bfa

File tree

4 files changed

+121
-9
lines changed

4 files changed

+121
-9
lines changed

src/pybind/mgr/dashboard/controllers/cephfs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,15 @@ def get(self, vol_name, info=True):
842842
f'Failed to get info for subvolume group {group["name"]}: {err}'
843843
)
844844
group['info'] = json.loads(out)
845+
846+
error_code, out, err = mgr.remote('volumes', '_cmd_fs_subvolumegroup_getpath',
847+
None, {'vol_name': vol_name,
848+
'group_name': group['name']})
849+
if error_code != 0:
850+
raise DashboardException(
851+
f'Failed to get path for subvolume group {group["name"]}: {err}'
852+
)
853+
group['info']['path'] = out
845854
return subvolume_groups
846855

847856
@RESTController.Resource('GET')

src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.html

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
formControlName="fs_name"
5858
name="fs_name"
5959
id="fs_name"
60-
(change)="pathChangeHandler()">
60+
(change)="volumeChangeHandler()">
6161
<option *ngIf="allFsNames === null"
6262
value=""
6363
i18n>Loading...</option>
@@ -112,6 +112,58 @@
112112
</div>
113113
</div>
114114

115+
<div class="form-group row"
116+
*ngIf="storageBackend === 'CEPH'">
117+
<label class="cd-col-form-label"
118+
for="subvolume_group"
119+
i18n>Subvolume Group</label>
120+
<div class="cd-col-form-input">
121+
<select class="form-select"
122+
formControlName="subvolume_group"
123+
name="subvolume_group"
124+
id="subvolume_group"
125+
(change)="getSubVol()">
126+
<option *ngIf="allsubvolgrps === null"
127+
value=""
128+
i18n>Loading...</option>
129+
<option *ngIf="allsubvolgrps !== null && allsubvolgrps.length === 0"
130+
value=""
131+
i18n>-- No CephFS subvolume group available --</option>
132+
<option *ngIf="allsubvolgrps !== null && allsubvolgrps.length > 0"
133+
value=""
134+
i18n>-- Select the CephFS subvolume group --</option>
135+
<option *ngFor="let subvol_grp of allsubvolgrps"
136+
[value]="subvol_grp.name">{{ subvol_grp.name }}</option>
137+
</select>
138+
</div>
139+
</div>
140+
141+
<div class="form-group row"
142+
*ngIf="storageBackend === 'CEPH'">
143+
<label class="cd-col-form-label"
144+
for="subvolume"
145+
i18n>Subvolume</label>
146+
<div class="cd-col-form-input">
147+
<select class="form-select"
148+
formControlName="subvolume"
149+
name="subvolume"
150+
id="subvolume"
151+
(change)="getPath()">
152+
<option *ngIf="allsubvols === null"
153+
value=""
154+
i18n>Loading...</option>
155+
<option *ngIf="allsubvols !== null && allsubvols.length === 0"
156+
value=""
157+
i18n>-- No CephFS subvolume available --</option>
158+
<option *ngIf="allsubvols !== null && allsubvols.length > 0"
159+
value=""
160+
i18n>-- Select the CephFS subvolume --</option>
161+
<option *ngFor="let subvolume of allsubvols"
162+
[value]="subvolume.name">{{ subvolume.name }}</option>
163+
</select>
164+
</div>
165+
</div>
166+
115167
<!-- Path -->
116168
<div class="form-group row"
117169
*ngIf="storageBackend === 'CEPH'">

src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,16 @@ describe('NfsFormComponent', () => {
9191
access_type: 'RW',
9292
clients: [],
9393
cluster_id: 'mynfs',
94-
fsal: { fs_name: 'a', name: 'CEPH' },
94+
fsal: { fs_name: '', name: 'CEPH' },
9595
path: '/',
9696
protocolNfsv4: true,
9797
protocolNfsv3: true,
9898
pseudo: '',
9999
sec_label_xattr: 'security.selinux',
100100
security_label: false,
101101
squash: 'no_root_squash',
102+
subvolume: '',
103+
subvolume_group: '',
102104
transportTCP: true,
103105
transportUDP: true
104106
});

src/pybind/mgr/dashboard/frontend/src/app/ceph/nfs/nfs-form/nfs-form.component.ts

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
2929
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
3030
import { NfsFormClientComponent } from '../nfs-form-client/nfs-form-client.component';
3131
import { getFsalFromRoute, getPathfromFsal } from '../utils';
32+
import { CephfsSubvolumeService } from '~/app/shared/api/cephfs-subvolume.service';
33+
import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
3234

3335
@Component({
3436
selector: 'cd-nfs-form',
@@ -63,6 +65,10 @@ export class NfsFormComponent extends CdForm implements OnInit {
6365
action: string;
6466
resource: string;
6567

68+
allsubvolgrps: any[] = [];
69+
allsubvols: any[] = [];
70+
fsPath: string = null;
71+
6672
pathDataSource = (text$: Observable<string>) => {
6773
return text$.pipe(
6874
debounceTime(200),
@@ -83,6 +89,8 @@ export class NfsFormComponent extends CdForm implements OnInit {
8389
constructor(
8490
private authStorageService: AuthStorageService,
8591
private nfsService: NfsService,
92+
private subvolService: CephfsSubvolumeService,
93+
private subvolgrpService: CephfsSubvolumeGroupService,
8694
private route: ActivatedRoute,
8795
private router: Router,
8896
private rgwBucketService: RgwBucketService,
@@ -139,6 +147,49 @@ export class NfsFormComponent extends CdForm implements OnInit {
139147
});
140148
}
141149

150+
volumeChangeHandler() {
151+
this.pathChangeHandler();
152+
const fs_name = this.nfsForm.getValue('fsal').fs_name;
153+
this.getSubVolGrp(fs_name);
154+
}
155+
156+
getSubVol() {
157+
this.getPath();
158+
const fs_name = this.nfsForm.getValue('fsal').fs_name;
159+
const subvolgrp = this.nfsForm.getValue('subvolume_group');
160+
return this.subvolService.get(fs_name, subvolgrp).subscribe((data: any) => {
161+
this.allsubvols = data;
162+
});
163+
}
164+
165+
getSubVolGrp(fs_name: string) {
166+
return this.subvolgrpService.get(fs_name).subscribe((data: any) => {
167+
this.allsubvolgrps = data;
168+
});
169+
}
170+
171+
getFsPath(volList: any[], value: string) {
172+
const match = volList.find((vol) => vol.name === value);
173+
if (match) {
174+
return match.info.path;
175+
}
176+
}
177+
178+
getPath() {
179+
const subvol = this.nfsForm.getValue('subvolume');
180+
if (subvol === '') {
181+
const subvolGroup = this.nfsForm.getValue('subvolume_group');
182+
this.fsPath = this.getFsPath(this.allsubvolgrps, subvolGroup);
183+
} else {
184+
this.fsPath = this.getFsPath(this.allsubvols, subvol);
185+
}
186+
this.nfsForm.patchValue({
187+
path: this.fsPath
188+
});
189+
190+
this.pathChangeHandler();
191+
}
192+
142193
createForm() {
143194
this.nfsForm = new CdFormGroup({
144195
cluster_id: new UntypedFormControl('', {
@@ -156,6 +207,8 @@ export class NfsFormComponent extends CdForm implements OnInit {
156207
]
157208
})
158209
}),
210+
subvolume_group: new UntypedFormControl(''),
211+
subvolume: new UntypedFormControl(''),
159212
path: new UntypedFormControl('/', {
160213
validators: [Validators.required]
161214
}),
@@ -266,13 +319,6 @@ export class NfsFormComponent extends CdForm implements OnInit {
266319

267320
resolveFilesystems(filesystems: any[]) {
268321
this.allFsNames = filesystems;
269-
if (!this.isEdit && filesystems.length > 0) {
270-
this.nfsForm.patchValue({
271-
fsal: {
272-
fs_name: filesystems[0].name
273-
}
274-
});
275-
}
276322
}
277323

278324
resolveRealms(realms: string[]) {
@@ -439,6 +485,9 @@ export class NfsFormComponent extends CdForm implements OnInit {
439485
delete requestModel.fsal.fs_name;
440486
}
441487

488+
delete requestModel.subvolume;
489+
delete requestModel.subvolume_group;
490+
442491
requestModel.protocols = [];
443492
if (requestModel.protocolNfsv3) {
444493
requestModel.protocols.push(3);

0 commit comments

Comments
 (0)