summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
diff options
context:
space:
mode:
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html')
-rw-r--r--src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html692
1 files changed, 692 insertions, 0 deletions
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
new file mode 100644
index 000000000..852866a86
--- /dev/null
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
@@ -0,0 +1,692 @@
+<div class="cd-col-form"
+ *cdFormLoading="loading">
+ <form name="targetForm"
+ #formDir="ngForm"
+ [formGroup]="targetForm"
+ novalidate>
+ <div class="card">
+ <div i18n="form title"
+ class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div>
+
+ <div class="card-body">
+ <!-- Target IQN -->
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="target_iqn"
+ i18n>Target IQN</label>
+ <div class="cd-col-form-input">
+ <div class="input-group">
+ <input class="form-control"
+ type="text"
+ id="target_iqn"
+ name="target_iqn"
+ formControlName="target_iqn"
+ cdTrim />
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ id="ecp-info-button"
+ type="button"
+ (click)="targetSettingsModal()">
+ <i [ngClass]="[icons.deepCheck]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
+ i18n>IQN has wrong pattern.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
+ <ng-container i18n>An IQN has the following notation
+ 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
+ <br>
+ <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
+ <br>
+ <a target="_blank"
+ href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
+ i18n>More information</a>
+ </span>
+
+ <span class="form-text text-muted"
+ *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
+ i18n>This target has modified advanced settings.</span>
+ <hr />
+ </div>
+ </div>
+
+ <!-- Portals -->
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="portals"
+ i18n>Portals</label>
+ <div class="cd-col-form-input">
+
+ <ng-container *ngFor="let portal of portals.value; let i = index">
+ <div class="input-group cd-mb">
+ <input class="cd-form-control"
+ type="text"
+ [value]="portal"
+ disabled />
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ type="button"
+ (click)="removePortal(i, portal)">
+ <i [ngClass]="[icons.destroy]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="portals.value"
+ [options]="portalsSelections"
+ [messages]="messages.portals"
+ (selection)="onPortalSelection($event)"
+ elemClass="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add portal</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <input class="form-control"
+ type="hidden"
+ id="portals"
+ name="portals"
+ formControlName="portals" />
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
+ i18n>At least {{ minimum_gateways }} gateways are required.</span>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Images -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="disks"
+ i18n>Images</label>
+ <div class="cd-col-form-input">
+ <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="cd-form-control"
+ type="text"
+ [value]="image"
+ disabled />
+ <span class="input-group-append">
+ <div class="input-group-text"
+ *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
+ <button class="btn btn-light"
+ type="button"
+ (click)="imageSettingsModal(image)">
+ <i [ngClass]="[icons.deepCheck]"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-light"
+ type="button"
+ (click)="removeImage(i, image)">
+ <i [ngClass]="[icons.destroy]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+
+ </div>
+
+ <span class="form-text text-muted">
+ <ng-container *ngIf="backstores.length > 1"
+ i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}.&nbsp;</ng-container>
+
+ <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
+ i18n>This image has modified settings.</ng-container>
+ </span>
+ </ng-container>
+
+ <input class="form-control"
+ type="hidden"
+ id="disks"
+ name="disks"
+ formControlName="disks" />
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
+ i18n>Duplicated LUN numbers.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
+ i18n>Duplicated WWN.</span>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="disks.value"
+ [options]="imagesSelections"
+ [messages]="messages.images"
+ (selection)="onImageSelection($event)"
+ elemClass="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- acl_enabled -->
+ <div class="form-group row">
+ <div class="cd-col-form-offset">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ formControlName="acl_enabled"
+ name="acl_enabled"
+ id="acl_enabled">
+ <label for="acl_enabled"
+ class="custom-control-label"
+ i18n>ACL authentication</label>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
+ <div formGroupName="auth"
+ *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
+
+ <!-- Target user -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="target_user">
+ <ng-container i18n>User</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ autocomplete="off"
+ id="target_user"
+ name="target_user"
+ formControlName="user" />
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('user', formDir, 'pattern')"
+ i18n>User names must have a length of 8 to 64 characters and can contain
+ alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Target password -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="target_password">
+ <ng-container i18n>Password</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ autocomplete="new-password"
+ id="target_password"
+ name="target_password"
+ formControlName="password" />
+ <span class="input-group-append">
+ <button type="button"
+ class="btn btn-light"
+ cdPasswordButton="target_password">
+ </button>
+ <cd-copy-2-clipboard-button source="target_password">
+ </cd-copy-2-clipboard-button>
+ </span>
+ </div>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and can contain
+ alphanumeric characters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+ <!-- Target mutual_user -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="target_mutual_user">
+ <ng-container i18n>Mutual User</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ autocomplete="off"
+ id="target_mutual_user"
+ name="target_mutual_user"
+ formControlName="mutual_user" />
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
+ i18n>User names must have a length of 8 to 64 characters and can contain
+ alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Target mutual_password -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="target_mutual_password">
+ <ng-container i18n>Mutual Password</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <div class="input-group">
+ <input class="form-control"
+ type="password"
+ autocomplete="new-password"
+ id="target_mutual_password"
+ name="target_mutual_password"
+ formControlName="mutual_password" />
+
+ <span class="input-group-append">
+ <button type="button"
+ class="btn btn-light"
+ cdPasswordButton="target_mutual_password">
+ </button>
+ <cd-copy-2-clipboard-button source="target_mutual_password">
+ </cd-copy-2-clipboard-button>
+ </span>
+ </div>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and can contain
+ alphanumeric characters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- Initiators -->
+ <div class="form-group row"
+ *ngIf="targetForm.getValue('acl_enabled')">
+ <label class="cd-col-form-label"
+ for="initiators"
+ i18n>Initiators</label>
+ <div class="cd-col-form-input"
+ formArrayName="initiators">
+ <div class="card mb-2"
+ *ngFor="let initiator of initiators.controls; let ii = index"
+ [formGroup]="initiator">
+ <div class="card-header">
+ <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
+ <button type="button"
+ class="close"
+ (click)="removeInitiator(ii)">
+ <i [ngClass]="[icons.destroy]"></i>
+ </button>
+ </div>
+ <div class="card-body">
+ <!-- Initiator: Name -->
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="client_iqn"
+ i18n>Client IQN</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ formControlName="client_iqn"
+ cdTrim
+ (blur)="updatedInitiatorSelector()">
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
+ i18n>Initiator IQN needs to be unique.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('client_iqn', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
+ i18n>IQN has wrong pattern.</span>
+ </div>
+ </div>
+
+ <ng-container formGroupName="auth">
+ <!-- Initiator: User -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="user"
+ i18n>User</label>
+ <div class="cd-col-form-input">
+ <input [id]="'user' + ii"
+ class="form-control"
+ formControlName="user"
+ autocomplete="off"
+ type="text">
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('user', formDir, 'pattern')"
+ i18n>User names must have a length of 8 to 64 characters and can contain
+ alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Initiator: Password -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="password"
+ i18n>Password</label>
+ <div class="cd-col-form-input">
+ <div class="input-group">
+ <input [id]="'password' + ii"
+ class="form-control"
+ formControlName="password"
+ autocomplete="new-password"
+ type="password">
+
+ <span class="input-group-append">
+ <button type="button"
+ class="btn btn-light"
+ [cdPasswordButton]="'password' + ii">
+ </button>
+ <cd-copy-2-clipboard-button [source]="'password' + ii">
+ </cd-copy-2-clipboard-button>
+ </span>
+ </div>
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and can contain
+ alphanumeric characters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+
+
+ <!-- Initiator: mutual_user -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="mutual_user">
+ <ng-container i18n>Mutual User</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <input [id]="'mutual_user' + ii"
+ class="form-control"
+ formControlName="mutual_user"
+ autocomplete="off"
+ type="text">
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('mutual_user', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
+ i18n>User names must have a length of 8 to 64 characters and can contain
+ alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
+ </div>
+ </div>
+
+ <!-- Initiator: mutual_password -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="mutual_password"
+ i18n>Mutual Password</label>
+ <div class="cd-col-form-input">
+ <div class="input-group">
+ <input [id]="'mutual_password' + ii"
+ class="form-control"
+ formControlName="mutual_password"
+ autocomplete="new-password"
+ type="password">
+
+ <span class="input-group-append">
+ <button type="button"
+ class="btn btn-light"
+ [cdPasswordButton]="'mutual_password' + ii">
+ </button>
+ <cd-copy-2-clipboard-button [source]="'mutual_password' + ii">
+ </cd-copy-2-clipboard-button>
+ </span>
+ </div>
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('mutual_password', formDir, 'required')"
+ i18n>This field is required.</span>
+
+ <span class="invalid-feedback"
+ *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
+ i18n>Passwords must have a length of 12 to 16 characters and can contain
+ alphanumeric characters, '@', '-', '_' or '/'.</span>
+ </div>
+ </div>
+ </ng-container>
+
+ <!-- Initiator: Images -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="luns"
+ i18n>Images</label>
+ <div class="cd-col-form-input">
+ <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
+ <div class="input-group cd-mb">
+ <input class="cd-form-control"
+ type="text"
+ [value]="image"
+ disabled />
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ type="button"
+ (click)="removeInitiatorImage(initiator, li, ii, image)">
+ <i [ngClass]="[icons.destroy]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <span *ngIf="initiator.getValue('cdIsInGroup')"
+ i18n>Initiator belongs to a group. Images will be configure in the group.</span>
+
+ <div class="row"
+ *ngIf="!initiator.getValue('cdIsInGroup')">
+ <div class="col-md-12">
+ <cd-select [data]="initiator.getValue('luns')"
+ [options]="imagesInitiatorSelections[ii]"
+ [messages]="messages.initiatorImage"
+ elemClass="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <span class="form-text text-muted"
+ *ngIf="initiators.controls.length === 0"
+ i18n>No items added.</span>
+
+ <button (click)="addInitiator(); false"
+ class="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add initiator</ng-container>
+ </button>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Groups -->
+ <div class="form-group row"
+ *ngIf="targetForm.getValue('acl_enabled')">
+ <label class="cd-col-form-label"
+ for="initiators"
+ i18n>Groups</label>
+ <div class="cd-col-form-input"
+ formArrayName="groups">
+ <div class="card mb-2"
+ *ngFor="let group of groups.controls; let gi = index"
+ [formGroup]="group">
+ <div class="card-header">
+ <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
+ <button type="button"
+ class="close"
+ (click)="removeGroup(gi)">
+ <i [ngClass]="[icons.destroy]"></i>
+ </button>
+ </div>
+ <div class="card-body">
+ <!-- Group: group_id -->
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="group_id"
+ i18n>Name</label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ type="text"
+ formControlName="group_id">
+ </div>
+ </div>
+
+ <!-- Group: members -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="members">
+ <ng-container i18n>Initiators</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <ng-container *ngFor="let member of group.getValue('members'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="cd-form-control"
+ type="text"
+ [value]="member"
+ disabled />
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ type="button"
+ (click)="removeGroupInitiator(group, i, gi)">
+ <i [ngClass]="[icons.destroy]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="group.getValue('members')"
+ [options]="groupMembersSelections[gi]"
+ [messages]="messages.groupInitiator"
+ (selection)="onGroupMemberSelection($event, gi)"
+ elemClass="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add initiator</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+
+ <!-- Group: disks -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="disks">
+ <ng-container i18n>Images</ng-container>
+ </label>
+ <div class="cd-col-form-input">
+ <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
+ <div class="input-group cd-mb">
+ <input class="cd-form-control"
+ type="text"
+ [value]="disk"
+ disabled />
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ type="button"
+ (click)="removeGroupDisk(group, i, gi)">
+ <i [ngClass]="[icons.destroy]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
+ </div>
+ </ng-container>
+
+ <div class="row">
+ <div class="col-md-12">
+ <cd-select [data]="group.getValue('disks')"
+ [options]="groupDiskSelections[gi]"
+ [messages]="messages.initiatorImage"
+ elemClass="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add image</ng-container>
+ </cd-select>
+ </div>
+ </div>
+
+ <hr />
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="row">
+ <div class="col-md-12">
+ <span class="form-text text-muted"
+ *ngIf="groups.controls.length === 0"
+ i18n>No items added.</span>
+
+ <button (click)="addGroup(); false"
+ class="btn btn-light float-right">
+ <i [ngClass]="[icons.add]"></i>
+ <ng-container i18n>Add group</ng-container>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <div class="card-footer">
+ <cd-form-button-panel (submitActionEvent)="submit()"
+ [form]="targetForm"
+ [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
+ wrappingClass="text-right"></cd-form-button-panel>
+ </div>
+ </div>
+ </form>
+</div>