1 <div class="cd-col-form"
2 *cdFormLoading="loading">
3 <form name="targetForm"
5 [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 required"
16 i18n>Target IQN</label>
17 <div class="cd-col-form-input">
18 <div class="input-group">
19 <input class="form-control"
23 formControlName="target_iqn"
25 <span class="input-group-append">
26 <button class="btn btn-light"
29 (click)="targetSettingsModal()">
30 <i [ngClass]="[icons.deepCheck]"
31 aria-hidden="true"></i>
36 <span class="invalid-feedback"
37 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
38 i18n>This field is required.</span>
40 <span class="invalid-feedback"
41 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
42 i18n>IQN has wrong pattern.</span>
44 <span class="invalid-feedback"
45 *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
46 <ng-container i18n>An IQN has the following notation
47 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
49 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
52 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
53 i18n>More information</a>
56 <span class="form-text text-muted"
57 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
58 i18n>This target has modified advanced settings.</span>
64 <div class="form-group row">
65 <label class="cd-col-form-label required"
68 <div class="cd-col-form-input">
70 <ng-container *ngFor="let portal of portals.value; let i = index">
71 <div class="input-group cd-mb">
72 <input class="cd-form-control"
76 <span class="input-group-append">
77 <button class="btn btn-light"
79 (click)="removePortal(i, portal)">
80 <i [ngClass]="[icons.destroy]"
81 aria-hidden="true"></i>
88 <div class="col-md-12">
89 <cd-select [data]="portals.value"
90 [options]="portalsSelections"
91 [messages]="messages.portals"
92 (selection)="onPortalSelection($event)"
93 elemClass="btn btn-light float-right">
94 <i [ngClass]="[icons.add]"></i>
95 <ng-container i18n>Add portal</ng-container>
100 <input class="form-control"
104 formControlName="portals" />
106 <span class="invalid-feedback"
107 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
108 i18n>At least {{ minimum_gateways }} gateways are required.</span>
115 <div class="form-group row">
116 <label class="cd-col-form-label"
119 <div class="cd-col-form-input">
120 <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
121 <div class="input-group cd-mb">
122 <input class="cd-form-control"
126 <span class="input-group-append">
127 <div class="input-group-text"
128 *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
129 <button class="btn btn-light"
131 (click)="imageSettingsModal(image)">
132 <i [ngClass]="[icons.deepCheck]"
133 aria-hidden="true"></i>
135 <button class="btn btn-light"
137 (click)="removeImage(i, image)">
138 <i [ngClass]="[icons.destroy]"
139 aria-hidden="true"></i>
145 <span class="form-text text-muted">
146 <ng-container *ngIf="backstores.length > 1"
147 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
149 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
150 i18n>This image has modified settings.</ng-container>
154 <input class="form-control"
158 formControlName="disks" />
160 <span class="invalid-feedback"
161 *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
162 i18n>Duplicated LUN numbers.</span>
164 <span class="invalid-feedback"
165 *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
166 i18n>Duplicated WWN.</span>
169 <div class="col-md-12">
170 <cd-select [data]="disks.value"
171 [options]="imagesSelections"
172 [messages]="messages.images"
173 (selection)="onImageSelection($event)"
174 elemClass="btn btn-light float-right">
175 <i [ngClass]="[icons.add]"></i>
176 <ng-container i18n>Add image</ng-container>
186 <div class="form-group row">
187 <div class="cd-col-form-offset">
188 <div class="custom-control custom-checkbox">
189 <input type="checkbox"
190 class="custom-control-input"
191 formControlName="acl_enabled"
194 <label for="acl_enabled"
195 class="custom-control-label"
196 i18n>ACL authentication</label>
203 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
204 <div formGroupName="auth"
205 *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
208 <div class="form-group row">
209 <label class="cd-col-form-label"
211 <ng-container i18n>User</ng-container>
213 <div class="cd-col-form-input">
214 <input class="form-control"
219 formControlName="user" />
221 <span class="invalid-feedback"
222 *ngIf="targetForm.showError('user', formDir, 'required')"
223 i18n>This field is required.</span>
225 <span class="invalid-feedback"
226 *ngIf="targetForm.showError('user', formDir, 'pattern')"
227 i18n>User names must have a length of 8 to 64 characters and can contain
228 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
232 <!-- Target password -->
233 <div class="form-group row">
234 <label class="cd-col-form-label"
235 for="target_password">
236 <ng-container i18n>Password</ng-container>
238 <div class="cd-col-form-input">
239 <div class="input-group">
240 <input class="form-control"
242 autocomplete="new-password"
244 name="target_password"
245 formControlName="password" />
246 <span class="input-group-append">
247 <button type="button"
248 class="btn btn-light"
249 cdPasswordButton="target_password">
251 <cd-copy-2-clipboard-button source="target_password">
252 </cd-copy-2-clipboard-button>
256 <span class="invalid-feedback"
257 *ngIf="targetForm.showError('password', formDir, 'required')"
258 i18n>This field is required.</span>
260 <span class="invalid-feedback"
261 *ngIf="targetForm.showError('password', formDir, 'pattern')"
262 i18n>Passwords must have a length of 12 to 16 characters and can contain
263 alphanumeric characters, '@', '-', '_' or '/'.</span>
267 <!-- Target mutual_user -->
268 <div class="form-group row">
269 <label class="cd-col-form-label"
270 for="target_mutual_user">
271 <ng-container i18n>Mutual User</ng-container>
273 <div class="cd-col-form-input">
274 <input class="form-control"
277 id="target_mutual_user"
278 name="target_mutual_user"
279 formControlName="mutual_user" />
281 <span class="invalid-feedback"
282 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
283 i18n>This field is required.</span>
285 <span class="invalid-feedback"
286 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
287 i18n>User names must have a length of 8 to 64 characters and can contain
288 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
292 <!-- Target mutual_password -->
293 <div class="form-group row">
294 <label class="cd-col-form-label"
295 for="target_mutual_password">
296 <ng-container i18n>Mutual Password</ng-container>
298 <div class="cd-col-form-input">
299 <div class="input-group">
300 <input class="form-control"
302 autocomplete="new-password"
303 id="target_mutual_password"
304 name="target_mutual_password"
305 formControlName="mutual_password" />
307 <span class="input-group-append">
308 <button type="button"
309 class="btn btn-light"
310 cdPasswordButton="target_mutual_password">
312 <cd-copy-2-clipboard-button source="target_mutual_password">
313 </cd-copy-2-clipboard-button>
317 <span class="invalid-feedback"
318 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
319 i18n>This field is required.</span>
321 <span class="invalid-feedback"
322 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
323 i18n>Passwords must have a length of 12 to 16 characters and can contain
324 alphanumeric characters, '@', '-', '_' or '/'.</span>
331 <div class="form-group row"
332 *ngIf="targetForm.getValue('acl_enabled')">
333 <label class="cd-col-form-label"
335 i18n>Initiators</label>
336 <div class="cd-col-form-input"
337 formArrayName="initiators">
338 <div class="card mb-2"
339 *ngFor="let initiator of initiators.controls; let ii = index"
340 [formGroupName]="ii">
341 <div class="card-header">
342 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
343 <button type="button"
345 (click)="removeInitiator(ii)">
346 <i [ngClass]="[icons.destroy]"></i>
349 <div class="card-body">
350 <!-- Initiator: Name -->
351 <div class="form-group row">
352 <label class="cd-col-form-label required"
354 i18n>Client IQN</label>
355 <div class="cd-col-form-input">
356 <input class="form-control"
358 formControlName="client_iqn"
360 (blur)="updatedInitiatorSelector()">
362 <span class="invalid-feedback"
363 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
364 i18n>Initiator IQN needs to be unique.</span>
366 <span class="invalid-feedback"
367 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
368 i18n>This field is required.</span>
370 <span class="invalid-feedback"
371 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
372 i18n>IQN has wrong pattern.</span>
376 <ng-container formGroupName="auth">
377 <!-- Initiator: User -->
378 <div class="form-group row">
379 <label class="cd-col-form-label"
382 <div class="cd-col-form-input">
383 <input [id]="'user' + ii"
385 formControlName="user"
388 <span class="invalid-feedback"
389 *ngIf="initiator.showError('user', formDir, 'required')"
390 i18n>This field is required.</span>
392 <span class="invalid-feedback"
393 *ngIf="initiator.showError('user', formDir, 'pattern')"
394 i18n>User names must have a length of 8 to 64 characters and can contain
395 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
399 <!-- Initiator: Password -->
400 <div class="form-group row">
401 <label class="cd-col-form-label"
403 i18n>Password</label>
404 <div class="cd-col-form-input">
405 <div class="input-group">
406 <input [id]="'password' + ii"
408 formControlName="password"
409 autocomplete="new-password"
412 <span class="input-group-append">
413 <button type="button"
414 class="btn btn-light"
415 [cdPasswordButton]="'password' + ii">
417 <cd-copy-2-clipboard-button [source]="'password' + ii">
418 </cd-copy-2-clipboard-button>
421 <span class="invalid-feedback"
422 *ngIf="initiator.showError('password', formDir, 'required')"
423 i18n>This field is required.</span>
425 <span class="invalid-feedback"
426 *ngIf="initiator.showError('password', formDir, 'pattern')"
427 i18n>Passwords must have a length of 12 to 16 characters and can contain
428 alphanumeric characters, '@', '-', '_' or '/'.</span>
433 <!-- Initiator: mutual_user -->
434 <div class="form-group row">
435 <label class="cd-col-form-label"
437 <ng-container i18n>Mutual User</ng-container>
439 <div class="cd-col-form-input">
440 <input [id]="'mutual_user' + ii"
442 formControlName="mutual_user"
446 <span class="invalid-feedback"
447 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
448 i18n>This field is required.</span>
450 <span class="invalid-feedback"
451 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
452 i18n>User names must have a length of 8 to 64 characters and can contain
453 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
457 <!-- Initiator: mutual_password -->
458 <div class="form-group row">
459 <label class="cd-col-form-label"
460 for="mutual_password"
461 i18n>Mutual Password</label>
462 <div class="cd-col-form-input">
463 <div class="input-group">
464 <input [id]="'mutual_password' + ii"
466 formControlName="mutual_password"
467 autocomplete="new-password"
470 <span class="input-group-append">
471 <button type="button"
472 class="btn btn-light"
473 [cdPasswordButton]="'mutual_password' + ii">
475 <cd-copy-2-clipboard-button [source]="'mutual_password' + ii">
476 </cd-copy-2-clipboard-button>
479 <span class="invalid-feedback"
480 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
481 i18n>This field is required.</span>
483 <span class="invalid-feedback"
484 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
485 i18n>Passwords must have a length of 12 to 16 characters and can contain
486 alphanumeric characters, '@', '-', '_' or '/'.</span>
491 <!-- Initiator: Images -->
492 <div class="form-group row">
493 <label class="cd-col-form-label"
496 <div class="cd-col-form-input">
497 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
498 <div class="input-group cd-mb">
499 <input class="cd-form-control"
503 <span class="input-group-append">
504 <button class="btn btn-light"
506 (click)="removeInitiatorImage(initiator, li, ii, image)">
507 <i [ngClass]="[icons.destroy]"
508 aria-hidden="true"></i>
514 <span *ngIf="initiator.getValue('cdIsInGroup')"
515 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
518 *ngIf="!initiator.getValue('cdIsInGroup')">
519 <div class="col-md-12">
520 <cd-select [data]="initiator.getValue('luns')"
521 [options]="imagesInitiatorSelections[ii]"
522 [messages]="messages.initiatorImage"
523 elemClass="btn btn-light float-right">
524 <i [ngClass]="[icons.add]"></i>
525 <ng-container i18n>Add image</ng-container>
535 <div class="col-md-12">
536 <span class="form-text text-muted"
537 *ngIf="initiators.controls.length === 0"
538 i18n>No items added.</span>
540 <button (click)="addInitiator(); false"
541 class="btn btn-light float-right">
542 <i [ngClass]="[icons.add]"></i>
543 <ng-container i18n>Add initiator</ng-container>
553 <div class="form-group row"
554 *ngIf="targetForm.getValue('acl_enabled')">
555 <label class="cd-col-form-label"
558 <div class="cd-col-form-input"
559 formArrayName="groups">
560 <div class="card mb-2"
561 *ngFor="let group of groups.controls; let gi = index"
562 [formGroupName]="gi">
563 <div class="card-header">
564 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
565 <button type="button"
567 (click)="removeGroup(gi)">
568 <i [ngClass]="[icons.destroy]"></i>
571 <div class="card-body">
572 <!-- Group: group_id -->
573 <div class="form-group row">
574 <label class="cd-col-form-label required"
577 <div class="cd-col-form-input">
578 <input class="form-control"
580 formControlName="group_id">
584 <!-- Group: members -->
585 <div class="form-group row">
586 <label class="cd-col-form-label"
588 <ng-container i18n>Initiators</ng-container>
590 <div class="cd-col-form-input">
591 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
592 <div class="input-group cd-mb">
593 <input class="cd-form-control"
597 <span class="input-group-append">
598 <button class="btn btn-light"
600 (click)="removeGroupInitiator(group, i, gi)">
601 <i [ngClass]="[icons.destroy]"
602 aria-hidden="true"></i>
609 <div class="col-md-12">
610 <cd-select [data]="group.getValue('members')"
611 [options]="groupMembersSelections[gi]"
612 [messages]="messages.groupInitiator"
613 (selection)="onGroupMemberSelection($event, gi)"
614 elemClass="btn btn-light float-right">
615 <i [ngClass]="[icons.add]"></i>
616 <ng-container i18n>Add initiator</ng-container>
625 <!-- Group: disks -->
626 <div class="form-group row">
627 <label class="cd-col-form-label"
629 <ng-container i18n>Images</ng-container>
631 <div class="cd-col-form-input">
632 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
633 <div class="input-group cd-mb">
634 <input class="cd-form-control"
638 <span class="input-group-append">
639 <button class="btn btn-light"
641 (click)="removeGroupDisk(group, i, gi)">
642 <i [ngClass]="[icons.destroy]"
643 aria-hidden="true"></i>
650 <div class="col-md-12">
651 <cd-select [data]="group.getValue('disks')"
652 [options]="groupDiskSelections[gi]"
653 [messages]="messages.initiatorImage"
654 elemClass="btn btn-light float-right">
655 <i [ngClass]="[icons.add]"></i>
656 <ng-container i18n>Add image</ng-container>
668 <div class="col-md-12">
669 <span class="form-text text-muted"
670 *ngIf="groups.controls.length === 0"
671 i18n>No items added.</span>
673 <button (click)="addGroup(); false"
674 class="btn btn-light float-right">
675 <i [ngClass]="[icons.add]"></i>
676 <ng-container i18n>Add group</ng-container>
684 <div class="card-footer">
685 <cd-form-button-panel (submitActionEvent)="submit()"
687 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
688 wrappingClass="text-right"></cd-form-button-panel>