File

src/app/ceph/nfs/nfs-form/nfs-form.component.ts

Implements

OnInit

Metadata

selector cd-nfs-form
styleUrls ./nfs-form.component.scss
templateUrl ./nfs-form.component.html

Index

Properties
Methods

Constructor

constructor(authStorageService: AuthStorageService, nfsService: NfsService, route: ActivatedRoute, router: Router, rgwUserService: RgwUserService, formBuilder: CdFormBuilder, taskWrapper: TaskWrapperService, cdRef: ChangeDetectorRef, i18n: I18n)
Parameters :
Name Type Optional
authStorageService AuthStorageService No
nfsService NfsService No
route ActivatedRoute No
router Router No
rgwUserService RgwUserService No
formBuilder CdFormBuilder No
taskWrapper TaskWrapperService No
cdRef ChangeDetectorRef No
i18n I18n No

Methods

_buildRequest
_buildRequest()
Returns : any
_generatePseudo
_generatePseudo()
Returns : any
_generateTag
_generateTag()
Returns : any
bucketChangeHandler
bucketChangeHandler()
Returns : void
createForm
createForm()
Returns : void
fsalChangeHandler
fsalChangeHandler()
Returns : void
getAccessTypeHelp
getAccessTypeHelp(accessType)
Parameters :
Name Optional
accessType No
Returns : any
getBucketTypeahead
getBucketTypeahead(path: string)
Parameters :
Name Type Optional
path string No
Returns : Observable<any>
getData
getData(promises)
Parameters :
Name Optional
promises No
Returns : void
getId
getId()
Returns : string
getPathTypeahead
getPathTypeahead(path)
Parameters :
Name Optional
path No
Returns : any
ngOnInit
ngOnInit()
Returns : void
onClusterChange
onClusterChange()
Returns : void
onDaemonSelection
onDaemonSelection()
Returns : void
pathChangeHandler
pathChangeHandler()
Returns : void
removeDaemon
removeDaemon(index, daemon)
Parameters :
Name Optional
index No
daemon No
Returns : boolean
resolveClients
resolveClients(clients)
Parameters :
Name Optional
clients No
Returns : void
resolveDaemons
resolveDaemons(daemons)
Parameters :
Name Optional
daemons No
Returns : void
resolveFilesystems
resolveFilesystems(filesystems)
Parameters :
Name Optional
filesystems No
Returns : void
resolvefsals
resolvefsals(res: string[])
Parameters :
Name Type Optional
res string[] No
Returns : void
resolveModel
resolveModel(res)
Parameters :
Name Optional
res No
Returns : void
rgwUserIdChangeHandler
rgwUserIdChangeHandler()
Returns : void
setPathValidation
setPathValidation()
Returns : void
submitAction
submitAction()
Returns : void

Properties

allCephxClients
Type : any[]
Default value : null
allClusters
Type : string[]
Default value : null
allDaemons
Type : object
Default value : {}
allFsals
Type : any[]
Default value : []
allFsNames
Type : any[]
Default value : null
allRgwUsers
Type : any[]
Default value : []
bucketDataSource
Type : Observable<any>
Default value : Observable.create((observer: any) => { observer.next(this.nfsForm.getValue('path')); }).pipe(mergeMap((token: string) => this.getBucketTypeahead(token)))
cluster_id
Type : null
Default value : null
daemonsMessages
Default value : new SelectMessages( { noOptions: this.i18n('There are no daemons available.') }, this.i18n )
daemonsSelections
Type : SelectOption[]
Default value : []
export_id
Type : null
Default value : null
isDefaultCluster
Default value : false
isEdit
Default value : false
isNewBucket
Default value : false
isNewDirectory
Default value : false
nfsAccessType
Type : any[]
Default value : this.nfsService.nfsAccessType
nfsClients
Type : NfsFormClientComponent
Decorators :
@ViewChild('nfsClients')
nfsForm
Type : CdFormGroup
nfsSquash
Type : any[]
Default value : this.nfsService.nfsSquash
pathDataSource
Type : Observable<any>
Default value : Observable.create((observer: any) => { observer.next(this.nfsForm.getValue('path')); }).pipe( mergeMap((token: string) => this.getPathTypeahead(token)), map((val: any) => val.paths) )
permission
Type : Permission
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { I18n } from '@ngx-translate/i18n-polyfill';
import * as _ from 'lodash';
import { forkJoin, Observable, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';

import { NfsService } from '../../../shared/api/nfs.service';
import { RgwUserService } from '../../../shared/api/rgw-user.service';
import { SelectMessages } from '../../../shared/components/select/select-messages.model';
import { SelectOption } from '../../../shared/components/select/select-option.model';
import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
import { CdFormGroup } from '../../../shared/forms/cd-form-group';
import { CdValidators } from '../../../shared/forms/cd-validators';
import { FinishedTask } from '../../../shared/models/finished-task';
import { Permission } from '../../../shared/models/permissions';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
import { NfsFormClientComponent } from '../nfs-form-client/nfs-form-client.component';

@Component({
  selector: 'cd-nfs-form',
  templateUrl: './nfs-form.component.html',
  styleUrls: ['./nfs-form.component.scss']
})
export class NfsFormComponent implements OnInit {
  @ViewChild('nfsClients')
  nfsClients: NfsFormClientComponent;

  permission: Permission;
  nfsForm: CdFormGroup;
  isEdit = false;

  cluster_id = null;
  export_id = null;

  isNewDirectory = false;
  isNewBucket = false;
  isDefaultCluster = false;

  allClusters: string[] = null;
  allDaemons = {};

  allFsals: any[] = [];
  allRgwUsers: any[] = [];
  allCephxClients: any[] = null;
  allFsNames: any[] = null;

  nfsAccessType: any[] = this.nfsService.nfsAccessType;
  nfsSquash: any[] = this.nfsService.nfsSquash;

  daemonsSelections: SelectOption[] = [];
  daemonsMessages = new SelectMessages(
    { noOptions: this.i18n('There are no daemons available.') },
    this.i18n
  );

  pathDataSource: Observable<any> = Observable.create((observer: any) => {
    observer.next(this.nfsForm.getValue('path'));
  }).pipe(
    mergeMap((token: string) => this.getPathTypeahead(token)),
    map((val: any) => val.paths)
  );

  bucketDataSource: Observable<any> = Observable.create((observer: any) => {
    observer.next(this.nfsForm.getValue('path'));
  }).pipe(mergeMap((token: string) => this.getBucketTypeahead(token)));

  constructor(
    private authStorageService: AuthStorageService,
    private nfsService: NfsService,
    private route: ActivatedRoute,
    private router: Router,
    private rgwUserService: RgwUserService,
    private formBuilder: CdFormBuilder,
    private taskWrapper: TaskWrapperService,
    private cdRef: ChangeDetectorRef,
    private i18n: I18n
  ) {
    this.permission = this.authStorageService.getPermissions().pool;
    this.createForm();
  }

  ngOnInit() {
    const promises: any[] = [
      this.nfsService.daemon(),
      this.nfsService.fsals(),
      this.nfsService.clients(),
      this.nfsService.filesystems()
    ];

    if (this.router.url.startsWith('/nfs/edit')) {
      this.isEdit = true;
    }

    if (this.isEdit) {
      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);
      });
    } else {
      this.getData(promises);
    }
  }

  getData(promises) {
    forkJoin(promises).subscribe((data: any[]) => {
      this.resolveDaemons(data[0]);
      this.resolvefsals(data[1]);
      this.resolveClients(data[2]);
      this.resolveFilesystems(data[3]);
      if (data[4]) {
        this.resolveModel(data[4]);
      }
    });
  }

  createForm() {
    this.nfsForm = new CdFormGroup({
      cluster_id: new FormControl('', {
        validators: [Validators.required]
      }),
      daemons: new FormControl([]),
      fsal: new CdFormGroup({
        name: new FormControl('', {
          validators: [Validators.required]
        }),
        user_id: new FormControl('', {
          validators: [
            CdValidators.requiredIf({
              name: 'CEPH'
            })
          ]
        }),
        fs_name: new FormControl('', {
          validators: [
            CdValidators.requiredIf({
              name: 'CEPH'
            })
          ]
        }),
        rgw_user_id: new FormControl('', {
          validators: [
            CdValidators.requiredIf({
              name: 'RGW'
            })
          ]
        })
      }),
      path: new FormControl(''),
      protocolNfsv3: new FormControl(true, {
        validators: [
          CdValidators.requiredIf({ protocolNfsv4: false }, (value) => {
            return !value;
          })
        ]
      }),
      protocolNfsv4: new FormControl(true, {
        validators: [
          CdValidators.requiredIf({ protocolNfsv3: false }, (value) => {
            return !value;
          })
        ]
      }),
      tag: new FormControl(''),
      pseudo: new FormControl('', {
        validators: [
          CdValidators.requiredIf({ protocolNfsv4: true }),
          Validators.pattern('^/[^><|&()]*$')
        ]
      }),
      access_type: new FormControl('RW', {
        validators: [Validators.required]
      }),
      squash: new FormControl('', {
        validators: [Validators.required]
      }),
      transportUDP: new FormControl(true, {
        validators: [
          CdValidators.requiredIf({ transportTCP: false }, (value) => {
            return !value;
          })
        ]
      }),
      transportTCP: new FormControl(true, {
        validators: [
          CdValidators.requiredIf({ transportUDP: false }, (value) => {
            return !value;
          })
        ]
      }),
      clients: this.formBuilder.array([]),
      security_label: new FormControl(false),
      sec_label_xattr: new FormControl(
        'security.selinux',
        CdValidators.requiredIf({ security_label: true, 'fsal.name': 'CEPH' })
      )
    });

    this.nfsForm.get('protocolNfsv4').valueChanges.subscribe(() => {
      this.nfsForm.get('pseudo').updateValueAndValidity({ emitEvent: false });
    });
  }

  resolveModel(res) {
    if (res.fsal.name === 'CEPH') {
      res.sec_label_xattr = res.fsal.sec_label_xattr;
    }

    this.daemonsSelections = _.map(
      this.allDaemons[res.cluster_id],
      (daemon) => new SelectOption(res.daemons.indexOf(daemon) !== -1, daemon, '')
    );
    this.daemonsSelections = [...this.daemonsSelections];

    res.protocolNfsv3 = res.protocols.indexOf(3) !== -1;
    res.protocolNfsv4 = res.protocols.indexOf(4) !== -1;
    delete res.protocols;

    res.transportTCP = res.transports.indexOf('TCP') !== -1;
    res.transportUDP = res.transports.indexOf('UDP') !== -1;
    delete res.transports;

    res.clients.forEach((client) => {
      let addressStr = '';
      client.addresses.forEach((address) => {
        addressStr += address + ', ';
      });
      if (addressStr.length >= 2) {
        addressStr = addressStr.substring(0, addressStr.length - 2);
      }
      client.addresses = addressStr;
    });

    this.nfsForm.patchValue(res);
    this.setPathValidation();
    this.nfsClients.resolveModel(res.clients);
  }

  resolveDaemons(daemons) {
    daemons = _.sortBy(daemons, ['daemon_id']);

    this.allClusters = _(daemons)
      .map((daemon) => daemon.cluster_id)
      .sortedUniq()
      .value();

    _.forEach(this.allClusters, (cluster) => {
      this.allDaemons[cluster] = [];
    });

    _.forEach(daemons, (daemon) => {
      this.allDaemons[daemon.cluster_id].push(daemon.daemon_id);
    });

    const hasOneCluster = _.isArray(this.allClusters) && this.allClusters.length === 1;
    this.isDefaultCluster = hasOneCluster && this.allClusters[0] === '_default_';
    if (hasOneCluster) {
      this.nfsForm.patchValue({
        cluster_id: this.allClusters[0]
      });
      this.onClusterChange();
    }
  }

  resolvefsals(res: string[]) {
    res.forEach((fsal) => {
      const fsalItem = this.nfsService.nfsFsal.find((currentFsalItem) => {
        return fsal === currentFsalItem.value;
      });

      if (_.isObjectLike(fsalItem)) {
        this.allFsals.push(fsalItem);
        if (fsalItem.value === 'RGW') {
          this.rgwUserService.list().subscribe((result: any) => {
            result.forEach((user) => {
              if (user.suspended === 0 && user.keys.length > 0) {
                this.allRgwUsers.push(user.user_id);
              }
            });
          });
        }
      }
    });

    if (this.allFsals.length === 1 && _.isUndefined(this.nfsForm.getValue('fsal'))) {
      this.nfsForm.patchValue({
        fsal: this.allFsals[0]
      });
    }
  }

  resolveClients(clients) {
    this.allCephxClients = clients;
  }

  resolveFilesystems(filesystems) {
    this.allFsNames = filesystems;
    if (filesystems.length === 1) {
      this.nfsForm.patchValue({
        fsal: {
          fs_name: filesystems[0].name
        }
      });
    }
  }

  fsalChangeHandler() {
    this.nfsForm.patchValue({
      tag: this._generateTag(),
      pseudo: this._generatePseudo()
    });

    this.setPathValidation();

    this.cdRef.detectChanges();
  }

  setPathValidation() {
    if (this.nfsForm.getValue('name') === 'RGW') {
      this.nfsForm
        .get('path')
        .setValidators([Validators.required, Validators.pattern('^(/|[^/><|&()#?]+)$')]);
    } else {
      this.nfsForm
        .get('path')
        .setValidators([Validators.required, Validators.pattern('^/[^><|&()?]*$')]);
    }
  }

  rgwUserIdChangeHandler() {
    this.nfsForm.patchValue({
      pseudo: this._generatePseudo()
    });
  }

  getAccessTypeHelp(accessType) {
    const accessTypeItem = this.nfsAccessType.find((currentAccessTypeItem) => {
      if (accessType === currentAccessTypeItem.value) {
        return currentAccessTypeItem;
      }
    });
    return _.isObjectLike(accessTypeItem) ? accessTypeItem.help : '';
  }

  getId() {
    if (
      _.isString(this.nfsForm.getValue('cluster_id')) &&
      _.isString(this.nfsForm.getValue('path'))
    ) {
      return this.nfsForm.getValue('cluster_id') + ':' + this.nfsForm.getValue('path');
    }
    return '';
  }

  getPathTypeahead(path) {
    if (!_.isString(path) || path === '/') {
      return of([]);
    }

    return this.nfsService.lsDir(path);
  }

  pathChangeHandler() {
    this.nfsForm.patchValue({
      pseudo: this._generatePseudo()
    });

    const path = this.nfsForm.getValue('path');
    this.getPathTypeahead(path).subscribe((res: any) => {
      this.isNewDirectory = path !== '/' && res.paths.indexOf(path) === -1;
    });
  }

  bucketChangeHandler() {
    this.nfsForm.patchValue({
      tag: this._generateTag(),
      pseudo: this._generatePseudo()
    });

    const bucket = this.nfsForm.getValue('path');
    this.getBucketTypeahead(bucket).subscribe((res: any) => {
      this.isNewBucket = bucket !== '' && res.indexOf(bucket) === -1;
    });
  }

  getBucketTypeahead(path: string): Observable<any> {
    const rgwUserId = this.nfsForm.getValue('rgw_user_id');

    if (_.isString(rgwUserId) && _.isString(path) && path !== '/' && path !== '') {
      return this.nfsService.buckets(rgwUserId);
    } else {
      return of([]);
    }
  }

  _generateTag() {
    let newTag = this.nfsForm.getValue('tag');
    if (!this.nfsForm.get('tag').dirty) {
      newTag = undefined;
      if (this.nfsForm.getValue('fsal') === 'RGW') {
        newTag = this.nfsForm.getValue('path');
      }
    }
    return newTag;
  }

  _generatePseudo() {
    let newPseudo = this.nfsForm.getValue('pseudo');
    if (this.nfsForm.get('pseudo') && !this.nfsForm.get('pseudo').dirty) {
      newPseudo = undefined;
      if (this.nfsForm.getValue('fsal') === 'CEPH') {
        newPseudo = '/cephfs';
        if (_.isString(this.nfsForm.getValue('path'))) {
          newPseudo += this.nfsForm.getValue('path');
        }
      } else if (this.nfsForm.getValue('fsal') === 'RGW') {
        if (_.isString(this.nfsForm.getValue('rgw_user_id'))) {
          newPseudo = '/' + this.nfsForm.getValue('rgw_user_id');
          if (_.isString(this.nfsForm.getValue('path'))) {
            newPseudo += '/' + this.nfsForm.getValue('path');
          }
        }
      }
    }
    return newPseudo;
  }

  onClusterChange() {
    const cluster_id = this.nfsForm.getValue('cluster_id');
    this.daemonsSelections = _.map(
      this.allDaemons[cluster_id],
      (daemon) => new SelectOption(false, daemon, '')
    );
    this.daemonsSelections = [...this.daemonsSelections];
    this.nfsForm.patchValue({ daemons: [] });
  }

  removeDaemon(index, daemon) {
    this.daemonsSelections.forEach((value) => {
      if (value.name === daemon) {
        value.selected = false;
      }
    });

    const daemons = this.nfsForm.get('daemons');
    daemons.value.splice(index, 1);
    daemons.setValue(daemons.value);

    return false;
  }

  onDaemonSelection() {
    this.nfsForm.get('daemons').setValue(this.nfsForm.getValue('daemons'));
  }

  submitAction() {
    let action: Observable<any>;
    const requestModel = this._buildRequest();

    if (this.isEdit) {
      action = this.taskWrapper.wrapTaskAroundCall({
        task: new FinishedTask('nfs/edit', {
          cluster_id: this.cluster_id,
          export_id: this.export_id
        }),
        call: this.nfsService.update(this.cluster_id, this.export_id, requestModel)
      });
    } else {
      // Create
      action = this.taskWrapper.wrapTaskAroundCall({
        task: new FinishedTask('nfs/create', {
          path: requestModel.path,
          fsal: requestModel.fsal,
          cluster_id: requestModel.cluster_id
        }),
        call: this.nfsService.create(requestModel)
      });
    }

    action.subscribe(
      undefined,
      () => this.nfsForm.setErrors({ cdSubmitButton: true }),
      () => this.router.navigate(['/nfs'])
    );
  }

  _buildRequest() {
    const requestModel: any = _.cloneDeep(this.nfsForm.value);

    if (_.isUndefined(requestModel.tag) || requestModel.tag === '') {
      requestModel.tag = null;
    }

    if (this.isEdit) {
      requestModel.export_id = this.export_id;
    }

    if (requestModel.fsal.name === 'CEPH') {
      delete requestModel.fsal.rgw_user_id;
    } else {
      delete requestModel.fsal.fs_name;
      delete requestModel.fsal.user_id;
    }

    requestModel.protocols = [];
    if (requestModel.protocolNfsv3) {
      requestModel.protocols.push(3);
    } else {
      requestModel.tag = null;
    }
    delete requestModel.protocolNfsv3;
    if (requestModel.protocolNfsv4) {
      requestModel.protocols.push(4);
    } else {
      requestModel.pseudo = null;
    }
    delete requestModel.protocolNfsv4;

    requestModel.transports = [];
    if (requestModel.transportTCP) {
      requestModel.transports.push('TCP');
    }
    delete requestModel.transportTCP;
    if (requestModel.transportUDP) {
      requestModel.transports.push('UDP');
    }
    delete requestModel.transportUDP;

    requestModel.clients.forEach((client) => {
      if (_.isString(client.addresses)) {
        client.addresses = _(client.addresses)
          .split(/[ ,]+/)
          .uniq()
          .filter((address) => address !== '')
          .value();
      } else {
        client.addresses = [];
      }
    });

    if (requestModel.security_label === false || requestModel.fsal.name === 'RGW') {
      requestModel.fsal.sec_label_xattr = null;
    } else {
      requestModel.fsal.sec_label_xattr = requestModel.sec_label_xattr;
    }
    delete requestModel.sec_label_xattr;

    return requestModel;
  }
}
<div class="col-sm-12 col-lg-6">
  <form name="nfsForm"
        class="form-horizontal"
        #formDir="ngForm"
        [formGroup]="nfsForm"
        novalidate>
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title"
            i18n>NFS export {{ export_id ? cluster_id + ':' + export_id : '' }}</h3>
      </div>

      <div class="panel-body">

        <!-- cluster_id -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('cluster_id', formDir)}"
             *ngIf="!isDefaultCluster">
          <label class="col-sm-3 control-label"
                 for="cluster_id">
            <ng-container i18n>Cluster</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <select class="form-control"
                    formControlName="cluster_id"
                    name="cluster_id"
                    id="cluster_id"
                    (change)="onClusterChange()">
              <option *ngIf="allClusters === null"
                      value=""
                      i18n>Loading...</option>
              <option *ngIf="allClusters !== null && allClusters.length === 0"
                      value=""
                      i18n>-- No cluster available --</option>
              <option *ngIf="allClusters !== null && allClusters.length > 0"
                      value=""
                      i18n>-- Select the cluster --</option>
              <option *ngFor="let cluster of allClusters"
                      [value]="cluster">{{ cluster }}</option>
            </select>
            <span class="help-block"
                  *ngIf="nfsForm.showError('cluster_id', formDir, 'required')"
                  i18n>Required field</span>
          </div>
        </div>

        <!-- daemons -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('daemons', formDir)}">
          <label class="col-sm-3 control-label"
                 for="daemons">
            <ng-container i18n>Daemons</ng-container>
          </label>
          <div class="col-sm-9">
            <ng-container *ngFor="let daemon of nfsForm.getValue('daemons'); let i = index">
              <div class="input-group cd-mb">
                <input class="form-control"
                       type="text"
                       [value]="daemon"
                       disabled />
                <span class="input-group-btn">
                  <button class="btn btn-default"
                          type="button"
                          (click)="removeDaemon(i, daemon)">
                    <i class="fa fa-remove fa-fw"
                       aria-hidden="true"></i>
                  </button>
                </span>
              </div>
            </ng-container>

            <div class="row">
              <div class="col-md-12">
                <cd-select [data]="nfsForm.get('daemons').value"
                           [options]="daemonsSelections"
                           [messages]="daemonsMessages"
                           (selection)="onDaemonSelection()"
                           elemClass="btn btn-default pull-right">
                  <i class="fa fa-fw fa-plus"></i>
                  <ng-container i18n>Add daemon</ng-container>
                </cd-select>
              </div>
            </div>
          </div>
        </div>

        <!-- FSAL -->
        <div formGroupName="fsal">
          <!-- Name -->
          <div class="form-group"
               [ngClass]="{'has-error': nfsForm.showError('name', formDir)}">
            <label class="col-sm-3 control-label"
                   for="name">
              <ng-container i18n>Storage Backend</ng-container>
              <span class="required"></span>
            </label>
            <div class="col-sm-9">
              <select class="form-control"
                      formControlName="name"
                      name="name"
                      id="name"
                      (change)="fsalChangeHandler()">
                <option *ngIf="allFsals === null"
                        value=""
                        i18n>Loading...</option>
                <option *ngIf="allFsals !== null && allFsals.length === 0"
                        value=""
                        i18n>-- No data pools available --</option>
                <option *ngIf="allFsals !== null && allFsals.length > 0"
                        value=""
                        i18n>-- Select the storage backend --</option>
                <option *ngFor="let fsal of allFsals"
                        [value]="fsal.value">{{ fsal.descr }}</option>
              </select>
              <span class="help-block"
                    *ngIf="nfsForm.showError('name', formDir, 'required')"
                    i18n>Required field</span>
            </div>
          </div>

          <!-- RGW user -->
          <div class="form-group"
               [ngClass]="{'has-error': nfsForm.showError('rgw_user_id', formDir)}"
               *ngIf="nfsForm.getValue('name') === 'RGW'">
            <label class="col-sm-3 control-label"
                   for="rgw_user_id">
              <ng-container i18n>Object Gateway User</ng-container>
              <span class="required"></span>
            </label>
            <div class="col-sm-9">
              <select class="form-control"
                      formControlName="rgw_user_id"
                      name="rgw_user_id"
                      id="rgw_user_id"
                      (change)="rgwUserIdChangeHandler()">
                <option *ngIf="allRgwUsers === null"
                        value=""
                        i18n>Loading...</option>
                <option *ngIf="allRgwUsers !== null && allRgwUsers.length === 0"
                        value=""
                        i18n>-- No users available --</option>
                <option *ngIf="allRgwUsers !== null && allRgwUsers.length > 0"
                        value=""
                        i18n>-- Select the object gateway user --</option>
                <option *ngFor="let rgwUserId of allRgwUsers"
                        [value]="rgwUserId">{{ rgwUserId }}</option>
              </select>
              <span class="help-block"
                    *ngIf="nfsForm.showError('rgw_user_id', formDir, 'required')"
                    i18n>Required field</span>
            </div>
          </div>

          <!-- CephFS user_id -->
          <div class="form-group"
               [ngClass]="{'has-error': nfsForm.showError('user_id', formDir)}"
               *ngIf="nfsForm.getValue('name') === 'CEPH'">
            <label class="col-sm-3 control-label"
                   for="user_id">
              <ng-container i18n>CephFS User ID</ng-container>
              <span class="required"></span>
            </label>
            <div class="col-sm-9">
              <select class="form-control"
                      formControlName="user_id"
                      name="user_id"
                      id="user_id">
                <option *ngIf="allCephxClients === null"
                        value=""
                        i18n>Loading...</option>
                <option *ngIf="allCephxClients !== null && allCephxClients.length === 0"
                        value=""
                        i18n>-- No clients available --</option>
                <option *ngIf="allCephxClients !== null && allCephxClients.length > 0"
                        value=""
                        i18n>-- Select the cephx client --</option>
                <option *ngFor="let client of allCephxClients"
                        [value]="client">{{ client }}</option>
              </select>
              <span class="help-block"
                    *ngIf="nfsForm.showError('user_id', formDir, 'required')"
                    i18n>Required field</span>
            </div>
          </div>

          <!-- CephFS fs_name -->
          <div class="form-group"
               [ngClass]="{'has-error': nfsForm.showError('fs_name', formDir)}"
               *ngIf="nfsForm.getValue('name') === 'CEPH'">
            <label class="col-sm-3 control-label"
                   for="fs_name">
              <ng-container i18n>CephFS Name</ng-container>
              <span class="required"></span>
            </label>
            <div class="col-sm-9">
              <select class="form-control"
                      formControlName="fs_name"
                      name="fs_name"
                      id="fs_name"
                      (change)="rgwUserIdChangeHandler()">
                <option *ngIf="allFsNames === null"
                        value=""
                        i18n>Loading...</option>
                <option *ngIf="allFsNames !== null && allFsNames.length === 0"
                        value=""
                        i18n>-- No CephFS filesystem available --</option>
                <option *ngIf="allFsNames !== null && allFsNames.length > 0"
                        value=""
                        i18n>-- Select the CephFS filesystem --</option>
                <option *ngFor="let filesystem of allFsNames"
                        [value]="filesystem.name">{{ filesystem.name }}</option>
              </select>
              <span class="help-block"
                    *ngIf="nfsForm.showError('fs_name', formDir, 'required')"
                    i18n>Required field</span>
            </div>
          </div>
        </div>

        <!-- Secutiry Label -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('security_label', formDir)}"
             *ngIf="nfsForm.getValue('name') === 'CEPH'">
          <label class="col-sm-3 control-label"
                 for="security_label">
            <ng-container i18n>Security Label</ng-container>
            <span class="required"
                  *ngIf="nfsForm.getValue('security_label')"></span>
          </label>

          <div class="col-sm-9">
            <div class="checkbox checkbox-primary">
              <input type="checkbox"
                     formControlName="security_label"
                     name="security_label"
                     id="security_label">
              <label for="security_label"
                     i18n>Enable security label</label>
            </div>

            <br>

            <input type="text"
                   *ngIf="nfsForm.getValue('security_label')"
                   class="form-control"
                   name="sec_label_xattr"
                   id="sec_label_xattr"
                   formControlName="sec_label_xattr">

            <span class="help-block"
                  *ngIf="nfsForm.showError('sec_label_xattr', formDir, 'required')"
                  i18n>Required field</span>
          </div>
        </div>

        <!-- Path -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('path', formDir)}"
             *ngIf="nfsForm.getValue('name') === 'CEPH'">
          <label class="col-sm-3 control-label"
                 for="path">
            <ng-container i18n>CephFS Path</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <input type="text"
                   class="form-control"
                   name="path"
                   id="path"
                   formControlName="path"
                   [typeahead]="pathDataSource"
                   (typeaheadOnSelect)="pathChangeHandler()"
                   (blur)="pathChangeHandler()">
            <span class="help-block"
                  *ngIf="nfsForm.showError('path', formDir, 'required')"
                  i18n>Required field</span>

            <span class="help-block"
                  *ngIf="nfsForm.showError('path', formDir, 'pattern')"
                  i18n>Path need to start with a '/' and can be followed by a word</span>
            <span class="help-block"
                  *ngIf="isNewDirectory && !nfsForm.showError('path', formDir)"
                  i18n>New directory will be created</span>
          </div>
        </div>

        <!-- Bucket -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('path', formDir)}"
             *ngIf="nfsForm.getValue('name') === 'RGW'">
          <label class="col-sm-3 control-label"
                 for="path">
            <ng-container i18n>Path</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <input type="text"
                   class="form-control"
                   name="path"
                   id="path"
                   formControlName="path"
                   [typeahead]="bucketDataSource"
                   (typeaheadOnSelect)="bucketChangeHandler()"
                   (blur)="bucketChangeHandler()">

            <span class="help-block"
                  *ngIf="nfsForm.showError('path', formDir, 'required')"
                  i18n>Required field</span>

            <span class="help-block"
                  *ngIf="nfsForm.showError('path', formDir, 'pattern')"
                  i18n>Path can only be a single '/' or a word</span>

            <span class="help-block"
                  *ngIf="isNewBucket && !nfsForm.showError('path', formDir)"
                  i18n>New bucket will be created</span>
          </div>
        </div>

        <!-- NFS Protocol -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('protocolNfsv3', formDir) || nfsForm.showError('protocolNfsv4', formDir)}">
          <label class="col-sm-3 control-label"
                 for="protocols">
            <ng-container i18n>NFS Protocol</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <div class="checkbox checkbox-primary">
              <input type="checkbox"
                     id="protocolNfsv3"
                     name="protocolNfsv3"
                     formControlName="protocolNfsv3">
              <label i18n
                     for="protocolNfsv3">NFSv3</label>
            </div>
            <div class="checkbox checkbox-primary">
              <input type="checkbox"
                     formControlName="protocolNfsv4"
                     name="protocolNfsv4"
                     id="protocolNfsv4">
              <label i18n
                     for="protocolNfsv4">NFSv4</label>
            </div>
            <span class="help-block"
                  *ngIf="nfsForm.showError('protocolNfsv3', formDir, 'required') ||
                  nfsForm.showError('protocolNfsv4', formDir, 'required')"
                  i18n>Required field</span>
          </div>
        </div>

        <!-- Tag -->
        <div class="form-group"
             *ngIf="nfsForm.getValue('protocolNfsv3')">
          <label class="col-sm-3 control-label"
                 for="tag">
            <ng-container i18n>NFS Tag</ng-container>
            <cd-helper>
              <p i18n>Alternative access for <strong>NFS v3</strong> mounts (it must not have a leading /).</p>
              <p i18n>Clients may not mount subdirectories (i.e. if Tag = foo, the client may not mount foo/baz).</p>
              <p i18n>By using different Tag options, the same Path may be exported multiple times.</p>
            </cd-helper>
          </label>
          <div class="col-sm-9">
            <input type="text"
                   class="form-control"
                   name="tag"
                   id="tag"
                   formControlName="tag">
          </div>
        </div>

        <!-- Pseudo -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('pseudo', formDir)}"
             *ngIf="nfsForm.getValue('protocolNfsv4')">
          <label class="col-sm-3 control-label"
                 for="pseudo">
            <ng-container i18n>Pseudo</ng-container>
            <span class="required"></span>
            <cd-helper>
              <p i18n>The position that this <strong>NFS v4</strong> export occupies
                in the <strong>Pseudo FS</strong> (it must be unique).</p>
              <p i18n>By using different Pseudo options, the same Path may be exported multiple times.</p>
            </cd-helper>
          </label>
          <div class="col-sm-9">
            <input type="text"
                   class="form-control"
                   name="pseudo"
                   id="pseudo"
                   formControlName="pseudo">
            <span class="help-block"
                  *ngIf="nfsForm.showError('pseudo', formDir, 'required')"
                  i18n>Required field</span>
            <span class="help-block"
                  *ngIf="nfsForm.showError('pseudo', formDir, 'pattern')"
                  i18n>Wrong format</span>
          </div>
        </div>

        <!-- Access Type -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('access_type', formDir)}">
          <label class="col-sm-3 control-label"
                 for="access_type">
            <ng-container i18n>Access Type</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <select class="form-control"
                    formControlName="access_type"
                    name="access_type"
                    id="access_type">
              <option *ngIf="nfsAccessType === null"
                      value=""
                      i18n>Loading...</option>
              <option *ngIf="nfsAccessType !== null && nfsAccessType.length === 0"
                      value=""
                      i18n>-- No access type available --</option>
              <option *ngIf="nfsAccessType !== null && nfsAccessType.length > 0"
                      value=""
                      i18n>-- Select the access type --</option>
              <option *ngFor="let accessType of nfsAccessType"
                      [value]="accessType.value">{{ accessType.value }}</option>
            </select>
            <span class="help-block"
                  *ngIf="nfsForm.getValue('access_type')">
              {{ getAccessTypeHelp(nfsForm.getValue('access_type')) }}
            </span>
            <span class="help-block"
                  *ngIf="nfsForm.showError('access_type', formDir, 'required')"
                  i18n>Required field</span>
          </div>
        </div>

        <!-- Squash -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('squash', formDir)}">
          <label class="col-sm-3 control-label"
                 for="squash">
            <ng-container i18n>Squash</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <select class="form-control"
                    name="squash"
                    formControlName="squash"
                    id="squash">
              <option *ngIf="nfsSquash === null"
                      value=""
                      i18n>Loading...</option>
              <option *ngIf="nfsSquash !== null && nfsSquash.length === 0"
                      value=""
                      i18n>-- No squash available --</option>
              <option *ngIf="nfsSquash !== null && nfsSquash.length > 0"
                      value=""
                      i18n>--Select what kind of user id squashing is performed --</option>
              <option *ngFor="let squash of nfsSquash"
                      [value]="squash">{{ squash }}</option>

            </select>
            <span class="help-block"
                  *ngIf="nfsForm.showError('squash', formDir,'required')"
                  i18n>Required field</span>
          </div>
        </div>

        <!-- Transport Protocol -->
        <div class="form-group"
             [ngClass]="{'has-error': nfsForm.showError('transportUDP', formDir) || nfsForm.showError('transportTCP', formDir)}">
          <label class="col-sm-3 control-label"
                 for="transports">
            <ng-container i18n>Transport Protocol</ng-container>
            <span class="required"></span>
          </label>
          <div class="col-sm-9">
            <div class="checkbox checkbox-primary">
              <input type="checkbox"
                     formControlName="transportUDP"
                     name="transportUDP"
                     id="transportUDP">
              <label for="transportUDP"
                     i18n>UDP</label>
            </div>
            <div class="checkbox checkbox-primary">
              <input type="checkbox"
                     formControlName="transportTCP"
                     name="transportTCP"
                     id="transportTCP">
              <label for="transportTCP"
                     i18n>TCP</label>
            </div>
            <span class="help-block"
                  *ngIf="nfsForm.showError('transportUDP', formDir, 'required') ||
                  nfsForm.showError('transportTCP', formDir, 'required')"
                  i18n>Required field</span>
            <hr>
          </div>
        </div>

        <!-- Clients -->
        <cd-nfs-form-client [form]="nfsForm"
                            #nfsClients>
        </cd-nfs-form-client>

      </div>

      <div class="panel-footer">
        <div class="button-group text-right">
          <cd-submit-button [form]="formDir"
                            type="button"
                            (submitAction)="submitAction()">
            <ng-container i18n>Submit</ng-container>
          </cd-submit-button>
          <cd-back-button></cd-back-button>
        </div>
      </div>
    </div>
  </form>
</div>

./nfs-form.component.scss

.cd-mb {
  margin-bottom: 10px;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""