1 <div class="cd-col-form">
2 <form name="targetForm"
4 [formGroup]="targetForm"
8 <div i18n="form title|Example: Create Pool@@formTitle"
9 class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div>
11 <div class="card-body">
13 <div class="form-group row">
14 <label class="cd-col-form-label"
16 <ng-container i18n>Target IQN</ng-container>
17 <span class="required"></span>
19 <div class="cd-col-form-input">
20 <div class="input-group">
21 <input class="form-control"
25 formControlName="target_iqn"
27 <span class="input-group-append">
28 <button class="btn btn-light"
31 (click)="targetSettingsModal()">
32 <i [ngClass]="[icons.deepCheck]"
33 aria-hidden="true"></i>
38 <span class="invalid-feedback"
39 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
40 i18n>This field is required.</span>
42 <span class="invalid-feedback"
43 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
44 i18n>IQN has wrong pattern.</span>
46 <span class="invalid-feedback"
47 *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
48 <ng-container i18n>An IQN has the following notation
49 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
51 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
54 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
55 i18n>More information</a>
58 <span class="form-text text-muted"
59 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
60 i18n>This target has modified advanced settings.</span>
66 <div class="form-group row">
67 <label class="cd-col-form-label"
69 <ng-container i18n>Portals</ng-container>
70 <span class="required"></span>
72 <div class="cd-col-form-input">
74 <ng-container *ngFor="let portal of portals.value; let i = index">
75 <div class="input-group cd-mb">
76 <input class="cd-form-control"
80 <span class="input-group-append">
81 <button class="btn btn-light"
83 (click)="removePortal(i, portal)">
84 <i [ngClass]="[icons.destroy]"
85 aria-hidden="true"></i>
92 <div class="col-md-12">
93 <cd-select [data]="portals.value"
94 [options]="portalsSelections"
95 [messages]="messages.portals"
96 (selection)="onPortalSelection($event)"
97 elemClass="btn btn-light float-right">
98 <i [ngClass]="[icons.add]"></i>
99 <ng-container i18n>Add portal</ng-container>
104 <input class="form-control"
108 formControlName="portals" />
110 <span class="invalid-feedback"
111 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
112 i18n>At least {{ minimum_gateways }} gateways are required.</span>
119 <div class="form-group row">
120 <label class="cd-col-form-label"
123 <div class="cd-col-form-input">
124 <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
125 <div class="input-group cd-mb">
126 <input class="cd-form-control"
130 <span class="input-group-append">
131 <div class="input-group-text"
132 *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
133 <button class="btn btn-light"
135 (click)="imageSettingsModal(image)">
136 <i [ngClass]="[icons.deepCheck]"
137 aria-hidden="true"></i>
139 <button class="btn btn-light"
141 (click)="removeImage(i, image)">
142 <i [ngClass]="[icons.destroy]"
143 aria-hidden="true"></i>
149 <span class="form-text text-muted">
150 <ng-container *ngIf="backstores.length > 1"
151 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
153 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
154 i18n>This image has modified settings.</ng-container>
158 <input class="form-control"
162 formControlName="disks" />
164 <span class="invalid-feedback"
165 *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
166 i18n>Duplicated LUN numbers.</span>
168 <span class="invalid-feedback"
169 *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
170 i18n>Duplicated WWN.</span>
173 <div class="col-md-12">
174 <cd-select [data]="disks.value"
175 [options]="imagesSelections"
176 [messages]="messages.images"
177 (selection)="onImageSelection($event)"
178 elemClass="btn btn-light float-right">
179 <i [ngClass]="[icons.add]"></i>
180 <ng-container i18n>Add image</ng-container>
190 <div class="form-group row">
191 <div class="cd-col-form-offset">
192 <div class="custom-control custom-checkbox">
193 <input type="checkbox"
194 class="custom-control-input"
195 formControlName="acl_enabled"
198 <label for="acl_enabled"
199 class="custom-control-label"
200 i18n>ACL authentication</label>
207 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
208 <div formGroupName="auth"
209 *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
212 <div class="form-group row">
213 <label class="cd-col-form-label"
215 <ng-container i18n>User</ng-container>
217 <div class="cd-col-form-input">
218 <input class="form-control"
222 formControlName="user" />
224 <span class="invalid-feedback"
225 *ngIf="targetForm.showError('user', formDir, 'required')"
226 i18n>This field is required.</span>
228 <span class="invalid-feedback"
229 *ngIf="targetForm.showError('user', formDir, 'pattern')"
230 i18n>Usernames must have a length of 8 to 64 characters and
231 can only contain letters, '.', '@', '-', '_' or ':'.</span>
235 <!-- Target password -->
236 <div class="form-group row">
237 <label class="cd-col-form-label"
238 for="target_password">
239 <ng-container i18n>Password</ng-container>
241 <div class="cd-col-form-input">
242 <div class="input-group">
243 <input class="form-control"
245 autocomplete="new-password"
247 name="target_password"
248 formControlName="password" />
249 <span class="input-group-append">
250 <button type="button"
251 class="btn btn-light"
252 cdPasswordButton="target_password">
254 <button type="button"
255 class="btn btn-light"
256 cdCopy2ClipboardButton="target_password">
261 <span class="invalid-feedback"
262 *ngIf="targetForm.showError('password', formDir, 'required')"
263 i18n>This field is required.</span>
265 <span class="invalid-feedback"
266 *ngIf="targetForm.showError('password', formDir, 'pattern')"
267 i18n>Passwords must have a length of 12 to 16 characters
268 and can only contain letters, '@', '-', '_' or '/'.</span>
272 <!-- Target mutual_user -->
273 <div class="form-group row">
274 <label class="cd-col-form-label"
275 for="target_mutual_user">
276 <ng-container i18n>Mutual User</ng-container>
278 <div class="cd-col-form-input">
279 <input class="form-control"
281 id="target_mutual_user"
282 name="target_mutual_user"
283 formControlName="mutual_user" />
285 <span class="invalid-feedback"
286 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
287 i18n>This field is required.</span>
289 <span class="invalid-feedback"
290 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
291 i18n>Usernames must have a length of 8 to 64 characters and
292 can only contain letters, '.', '@', '-', '_' or ':'.</span>
296 <!-- Target mutual_password -->
297 <div class="form-group row">
298 <label class="cd-col-form-label"
299 for="target_mutual_password">
300 <ng-container i18n>Mutual Password</ng-container>
302 <div class="cd-col-form-input">
303 <div class="input-group">
304 <input class="form-control"
306 autocomplete="new-password"
307 id="target_mutual_password"
308 name="target_mutual_password"
309 formControlName="mutual_password" />
311 <span class="input-group-append">
312 <button type="button"
313 class="btn btn-light"
314 cdPasswordButton="target_mutual_password">
316 <button type="button"
317 class="btn btn-light"
318 cdCopy2ClipboardButton="target_mutual_password">
323 <span class="invalid-feedback"
324 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
325 i18n>This field is required.</span>
327 <span class="invalid-feedback"
328 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
329 i18n>Passwords must have a length of 12 to 16 characters
330 and can only contain letters, '@', '-', '_' or '/'.</span>
337 <div class="form-group row"
338 *ngIf="targetForm.getValue('acl_enabled')">
339 <label class="cd-col-form-label"
341 i18n>Initiators</label>
342 <div class="cd-col-form-input"
343 formArrayName="initiators">
344 <div class="card mb-2"
345 *ngFor="let initiator of initiators.controls; let ii = index"
346 [formGroupName]="ii">
347 <div class="card-header">
348 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
349 <button type="button"
351 (click)="removeInitiator(ii)">
352 <i [ngClass]="[icons.destroy]"></i>
355 <div class="card-body">
356 <!-- Initiator: Name -->
357 <div class="form-group row">
358 <label class="cd-col-form-label"
360 <ng-container i18n>Client IQN</ng-container>
361 <span class="required"></span>
363 <div class="cd-col-form-input">
364 <input class="form-control"
366 formControlName="client_iqn"
368 (blur)="updatedInitiatorSelector()">
370 <span class="invalid-feedback"
371 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
372 i18n>Initiator IQN needs to be unique.</span>
374 <span class="invalid-feedback"
375 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
376 i18n>This field is required.</span>
378 <span class="invalid-feedback"
379 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
380 i18n>IQN has wrong pattern.</span>
384 <ng-container formGroupName="auth">
385 <!-- Initiator: User -->
386 <div class="form-group row">
387 <label class="cd-col-form-label"
390 <div class="cd-col-form-input">
391 <input [id]="'user' + ii"
393 formControlName="user"
395 <span class="invalid-feedback"
396 *ngIf="initiator.showError('user', formDir, 'required')"
397 i18n>This field is required.</span>
399 <span class="invalid-feedback"
400 *ngIf="initiator.showError('user', formDir, 'pattern')"
401 i18n>Usernames must have a length of 8 to 64 characters and
402 can only contain letters, '.', '@', '-', '_' or ':'.</span>
406 <!-- Initiator: Password -->
407 <div class="form-group row">
408 <label class="cd-col-form-label"
410 i18n>Password</label>
411 <div class="cd-col-form-input">
412 <div class="input-group">
413 <input [id]="'password' + ii"
415 formControlName="password"
418 <span class="input-group-append">
419 <button type="button"
420 class="btn btn-light"
421 [cdPasswordButton]="'password' + ii">
423 <button type="button"
424 class="btn btn-light"
425 [cdCopy2ClipboardButton]="'password' + ii">
429 <span class="invalid-feedback"
430 *ngIf="initiator.showError('password', formDir, 'required')"
431 i18n>This field is required.</span>
433 <span class="invalid-feedback"
434 *ngIf="initiator.showError('password', formDir, 'pattern')"
435 i18n>Passwords must have a length of 12 to 16 characters
436 and can only contain letters, '@', '-', '_' or '/'.</span>
441 <!-- Initiator: mutual_user -->
442 <div class="form-group row">
443 <label class="cd-col-form-label"
445 <ng-container i18n>Mutual User</ng-container>
447 <div class="cd-col-form-input">
448 <input [id]="'mutual_user' + ii"
450 formControlName="mutual_user"
453 <span class="invalid-feedback"
454 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
455 i18n>This field is required.</span>
457 <span class="invalid-feedback"
458 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
459 i18n>Usernames must have a length of 8 to 64 characters and
460 can only contain letters, '.', '@', '-', '_' or ':'.</span>
464 <!-- Initiator: mutual_password -->
465 <div class="form-group row">
466 <label class="cd-col-form-label"
467 for="mutual_password"
468 i18n>Mutual Password</label>
469 <div class="cd-col-form-input">
470 <div class="input-group">
471 <input [id]="'mutual_password' + ii"
473 formControlName="mutual_password"
476 <span class="input-group-append">
477 <button type="button"
478 class="btn btn-light"
479 [cdPasswordButton]="'mutual_password' + ii">
481 <button type="button"
482 class="btn btn-light"
483 [cdCopy2ClipboardButton]="'mutual_password' + ii">
487 <span class="invalid-feedback"
488 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
489 i18n>This field is required.</span>
491 <span class="invalid-feedback"
492 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
493 i18n>Passwords must have a length of 12 to 16 characters and
494 can only contain letters, '@', '-', '_' or '/'.</span>
499 <!-- Initiator: Images -->
500 <div class="form-group row">
501 <label class="cd-col-form-label"
504 <div class="cd-col-form-input">
505 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
506 <div class="input-group cd-mb">
507 <input class="cd-form-control"
511 <span class="input-group-append">
512 <button class="btn btn-light"
514 (click)="removeInitiatorImage(initiator, li, ii, image)">
515 <i [ngClass]="[icons.destroy]"
516 aria-hidden="true"></i>
522 <span *ngIf="initiator.getValue('cdIsInGroup')"
523 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
526 *ngIf="!initiator.getValue('cdIsInGroup')">
527 <div class="col-md-12">
528 <cd-select [data]="initiator.getValue('luns')"
529 [options]="imagesInitiatorSelections[ii]"
530 [messages]="messages.initiatorImage"
531 elemClass="btn btn-light float-right">
532 <i [ngClass]="[icons.add]"></i>
533 <ng-container i18n>Add image</ng-container>
543 <div class="col-md-12">
544 <span class="form-text text-muted"
545 *ngIf="initiators.controls.length === 0"
546 i18n>No items added.</span>
548 <button (click)="addInitiator(); false"
549 class="btn btn-light float-right">
550 <i [ngClass]="[icons.add]"></i>
551 <ng-container i18n>Add initiator</ng-container>
561 <div class="form-group row"
562 *ngIf="targetForm.getValue('acl_enabled')">
563 <label class="cd-col-form-label"
566 <div class="cd-col-form-input"
567 formArrayName="groups">
568 <div class="card mb-2"
569 *ngFor="let group of groups.controls; let gi = index"
570 [formGroupName]="gi">
571 <div class="card-header">
572 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
573 <button type="button"
575 (click)="groups.removeAt(gi)">
576 <i [ngClass]="[icons.destroy]"></i>
579 <div class="card-body">
580 <!-- Group: group_id -->
581 <div class="form-group row">
582 <label class="cd-col-form-label"
584 <ng-container i18n>Name</ng-container>
585 <span class="required"></span>
587 <div class="cd-col-form-input">
588 <input class="form-control"
590 formControlName="group_id">
594 <!-- Group: members -->
595 <div class="form-group row">
596 <label class="cd-col-form-label"
598 <ng-container i18n>Initiators</ng-container>
600 <div class="cd-col-form-input">
601 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
602 <div class="input-group cd-mb">
603 <input class="cd-form-control"
607 <span class="input-group-append">
608 <button class="btn btn-light"
610 (click)="removeGroupInitiator(group, i, gi)">
611 <i [ngClass]="[icons.destroy]"
612 aria-hidden="true"></i>
619 <div class="col-md-12">
620 <cd-select [data]="group.getValue('members')"
621 [options]="groupMembersSelections[gi]"
622 [messages]="messages.groupInitiator"
623 (selection)="onGroupMemberSelection($event)"
624 elemClass="btn btn-light float-right">
625 <i [ngClass]="[icons.add]"></i>
626 <ng-container i18n>Add initiator</ng-container>
635 <!-- Group: disks -->
636 <div class="form-group row">
637 <label class="cd-col-form-label"
639 <ng-container i18n>Images</ng-container>
641 <div class="cd-col-form-input">
642 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
643 <div class="input-group cd-mb">
644 <input class="cd-form-control"
648 <span class="input-group-append">
649 <button class="btn btn-light"
651 (click)="removeGroupDisk(group, i, gi)">
652 <i [ngClass]="[icons.destroy]"
653 aria-hidden="true"></i>
660 <div class="col-md-12">
661 <cd-select [data]="group.getValue('disks')"
662 [options]="groupDiskSelections[gi]"
663 [messages]="messages.initiatorImage"
664 elemClass="btn btn-light float-right">
665 <i [ngClass]="[icons.add]"></i>
666 <ng-container i18n>Add image</ng-container>
678 <div class="col-md-12">
679 <span class="form-text text-muted"
680 *ngIf="groups.controls.length === 0"
681 i18n>No items added.</span>
683 <button (click)="addGroup(); false"
684 class="btn btn-light float-right">
685 <i [ngClass]="[icons.add]"></i>
686 <ng-container i18n>Add group</ng-container>
694 <div class="card-footer">
695 <div class="button-group text-right">
696 <cd-submit-button (submitAction)="submit()"
697 i18n="form action button|Example: Create Pool@@formActionButton"
698 [form]="formDir">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
699 <cd-back-button></cd-back-button>