</div>
</div>
+ <!-- RGW Export Type -->
+ <div *ngIf="storageBackend === 'RGW' && !isEdit"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="rgw_export_type"
+ i18n>Type</label>
+ <div class="col-md-auto custom-checkbox form-check-inline ms-3">
+ <input class="form-check-input"
+ formControlName="rgw_export_type"
+ id="bucket_export"
+ type="radio"
+ value="bucket"
+ (change)="setBucket()">
+ <label class="form-check-label"
+ for="bucket_export"
+ i18n>Bucket</label>
+ </div>
+ <div class="col-md-auto custom-checkbox form-check-inline">
+ <input class="form-check-input"
+ formControlName="rgw_export_type"
+ id="user_export"
+ type="radio"
+ value="user"
+ (change)="setUsers()">
+ <label class="form-check-label"
+ for="user_export"
+ i18n>User</label>
+ </div>
+ </div>
+
<!-- FSAL -->
<div formGroupName="fsal">
<!-- CephFS Volume -->
i18n>This field is required.</span>
</div>
</div>
+
+ <!-- RGW User -->
+ <div class="form-group row"
+ *ngIf="storageBackend === 'RGW' && nfsForm.getValue('rgw_export_type') === 'user'">
+ <label class="cd-col-form-label"
+ for="user_id">
+ <span class="required"
+ i18n>User</span>
+ </label>
+ <div class="cd-col-form-input">
+ <select class="form-select"
+ formControlName="user_id"
+ name="user_id"
+ id="user_id"
+ (change)="pathChangeHandler()">
+ <option *ngIf="allRGWUsers === null"
+ value=""
+ i18n>Loading...</option>
+ <option *ngIf="allRGWUsers !== null && allRGWUsers.length === 0"
+ value=""
+ i18n>-- No RGW User available --</option>
+ <option *ngIf="allRGWUsers !== null && allRGWUsers.length > 0"
+ value=""
+ i18n>-- Select the RGW User --</option>
+ <option *ngFor="let user of allRGWUsers"
+ [value]="user.user_id">{{ user.user_id }}</option>
+ </select>
+ <span class="invalid-feedback"
+ *ngIf="nfsForm.showError('user_id', formDir, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
</div>
<!-- Security Label -->
<!-- Bucket -->
<div class="form-group row"
- *ngIf="storageBackend === 'RGW'">
+ *ngIf="storageBackend === 'RGW' && nfsForm.getValue('rgw_export_type') === 'bucket'">
<label class="cd-col-form-label"
for="path">
<span class="required"
id="path"
data-testid="rgw_path"
formControlName="path"
- [ngbTypeahead]="bucketDataSource">
+ [ngbTypeahead]="bucketDataSource"
+ (selectItem)="pathChangeHandler()"
+ (blur)="pathChangeHandler()">
<span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'required')"
<span class="invalid-feedback"
*ngIf="nfsForm.showError('path', formDir, 'bucketNameNotAllowed')"
i18n>The bucket does not exist or is not in the default realm (if multiple realms are configured).
- To continue, <a routerLink="/rgw/bucket/create"
- class="btn-link">create a new bucket</a>.</span>
+ To continue, <a routerLink="/rgw/bucket/create"
+ class="btn-link">create a new bucket</a>.</span>
</div>
</div>
import { getFsalFromRoute, getPathfromFsal } from '../utils';
import { CephfsSubvolumeService } from '~/app/shared/api/cephfs-subvolume.service';
import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
+import { RgwUserService } from '~/app/shared/api/rgw-user.service';
+import { RgwExportType } from '../nfs-list/nfs-list.component';
@Component({
selector: 'cd-nfs-form',
allFsNames: any[] = null;
+ allRGWUsers: any[] = null;
+
storageBackend: SUPPORTED_FSAL;
storageBackendError: string = null;
private route: ActivatedRoute,
private router: Router,
private rgwBucketService: RgwBucketService,
+ private rgwUserService: RgwUserService,
private rgwSiteService: RgwSiteService,
private formBuilder: CdFormBuilder,
private taskWrapper: TaskWrapperService,
this.createForm();
const promises: Observable<any>[] = [this.nfsService.listClusters()];
- if (this.storageBackend === 'RGW') {
+ if (this.storageBackend === SUPPORTED_FSAL.RGW) {
promises.push(this.rgwSiteService.get('realms'));
} else {
promises.push(this.nfsService.filesystems());
if (this.isEdit) {
this.action = this.actionLabels.EDIT;
- this.route.params.subscribe((params: { cluster_id: string; export_id: string }) => {
- this.cluster_id = decodeURIComponent(params.cluster_id);
- this.export_id = decodeURIComponent(params.export_id);
- promises.push(this.nfsService.get(this.cluster_id, this.export_id));
- this.getData(promises);
- });
+ this.route.params.subscribe(
+ (params: { cluster_id: string; export_id: string; rgw_export_type?: string }) => {
+ this.cluster_id = decodeURIComponent(params.cluster_id);
+ this.export_id = decodeURIComponent(params.export_id);
+ if (params.rgw_export_type) {
+ this.nfsForm.get('rgw_export_type').setValue(params.rgw_export_type);
+ if (params.rgw_export_type === RgwExportType.BUCKET) {
+ this.setBucket();
+ } else {
+ this.setUsers();
+ }
+ }
+ promises.push(this.nfsService.get(this.cluster_id, this.export_id));
+ this.getData(promises);
+ }
+ );
this.nfsForm.get('cluster_id').disable();
+ this.nfsForm.get('path').disable();
+ this.nfsForm.get('fsal.user_id').disable();
} else {
this.action = this.actionLabels.CREATE;
this.route.params.subscribe(
}
);
+ if (this.storageBackend === SUPPORTED_FSAL.RGW) {
+ this.nfsForm.get('rgw_export_type').setValue('bucket');
+ this.setBucket();
+ }
this.getData(promises);
}
}
createForm() {
this.nfsForm = new CdFormGroup({
+ // Common fields
cluster_id: new UntypedFormControl('', {
validators: [Validators.required]
}),
- fsal: new CdFormGroup({
- name: new UntypedFormControl(this.storageBackend, {
- validators: [Validators.required]
- }),
- fs_name: new UntypedFormControl('', {
- validators: [
- CdValidators.requiredIf({
- name: 'CEPH'
- })
- ]
- })
- }),
- subvolume_group: new UntypedFormControl(''),
- subvolume: new UntypedFormControl(''),
path: new UntypedFormControl('/', {
validators: [Validators.required]
}),
}),
clients: this.formBuilder.array([]),
security_label: new UntypedFormControl(false),
+
+ // FSAL fields (common for RGW and CephFS)
+ fsal: new CdFormGroup({
+ name: new UntypedFormControl(this.storageBackend, {
+ validators: [Validators.required]
+ }),
+ // RGW-specific field
+ user_id: new UntypedFormControl('', {
+ validators: [
+ CdValidators.requiredIf({
+ name: 'RGW'
+ })
+ ]
+ }),
+ // CephFS-specific field
+ fs_name: new UntypedFormControl('', {
+ validators: [
+ CdValidators.requiredIf({
+ name: 'CEPH'
+ })
+ ]
+ })
+ }),
+
+ // CephFS-specific fields
+ subvolume_group: new UntypedFormControl(''),
+ subvolume: new UntypedFormControl(''),
sec_label_xattr: new UntypedFormControl(
'security.selinux',
CdValidators.requiredIf({ security_label: true, 'fsal.name': 'CEPH' })
+ ),
+
+ // RGW-specific fields
+ rgw_export_type: new UntypedFormControl(
+ null,
+ CdValidators.requiredIf({
+ 'fsal.name': 'RGW'
+ })
)
});
}
}
resolveFsals(res: string[]) {
- if (this.storageBackend === 'RGW') {
- this.setPathValidation();
+ if (this.storageBackend === SUPPORTED_FSAL.RGW) {
this.resolveRealms(res);
} else {
this.resolveFilesystems(res);
}
}
+ setUsers() {
+ this.nfsForm.get('fsal.user_id').enable();
+ this.nfsForm.get('path').setValue('');
+ this.nfsForm.get('path').disable();
+ this.rgwUserService.list().subscribe((users: any) => {
+ this.allRGWUsers = users;
+ });
+ }
+
+ setBucket() {
+ this.nfsForm.get('path').enable();
+ this.nfsForm.get('fsal.user_id').setValue('');
+ this.nfsForm.get('fsal.user_id').disable();
+
+ this.setPathValidation();
+ }
+
accessTypeChangeHandler() {
const name = this.nfsForm.getValue('name');
const accessType = this.nfsForm.getValue('access_type');
}
private generatePseudo() {
- let newPseudo = this.nfsForm.getValue('pseudo');
- if (this.nfsForm.get('pseudo') && !this.nfsForm.get('pseudo').dirty) {
- newPseudo = undefined;
- if (this.storageBackend === 'CEPH') {
- newPseudo = '/cephfs';
- if (_.isString(this.nfsForm.getValue('path'))) {
- newPseudo += this.nfsForm.getValue('path');
- }
+ const pseudoControl = this.nfsForm.get('pseudo');
+ let newPseudo = pseudoControl?.dirty && this.nfsForm.getValue('pseudo');
+
+ if (!newPseudo) {
+ const path = this.nfsForm.getValue('path');
+ newPseudo = `/${getPathfromFsal(this.storageBackend)}`;
+
+ if (_.isString(path) && !_.isEmpty(path)) {
+ newPseudo += '/' + path;
+ } else if (!_.isEmpty(this.nfsForm.getValue('fsal').user_id)) {
+ newPseudo += '/' + this.nfsForm.getValue('fsal').user_id;
}
}
+
return newPseudo;
}
if (this.isEdit) {
requestModel.export_id = _.parseInt(this.export_id);
+ if (requestModel.fsal.name === SUPPORTED_FSAL.RGW) {
+ requestModel.fsal.user_id = this.nfsForm.getValue('fsal').user_id;
+ requestModel.path = this.nfsForm.getValue('path');
+ }
}
- if (requestModel.fsal.name === 'RGW') {
+ if (requestModel.fsal.name === SUPPORTED_FSAL.RGW) {
delete requestModel.fsal.fs_name;
+ if (requestModel.rgw_export_type === 'bucket') {
+ delete requestModel.fsal.user_id;
+ } else {
+ requestModel.path = '';
+ }
+ } else {
+ delete requestModel.fsal.user_id;
}
-
+ delete requestModel.rgw_export_type;
delete requestModel.subvolume;
delete requestModel.subvolume_group;