1 <div class="cd-col-form"
2 *cdFormLoading="loading">
3 <form name="targetForm"
5 [formGroup]="targetForm"
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 <button class="btn btn-light"
28 (click)="targetSettingsModal()">
29 <i [ngClass]="[icons.deepCheck]"
30 aria-hidden="true"></i>
34 <span class="invalid-feedback"
35 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
36 i18n>This field is required.</span>
38 <span class="invalid-feedback"
39 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
40 i18n>IQN has wrong pattern.</span>
42 <span class="invalid-feedback"
43 *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
44 <ng-container i18n>An IQN has the following notation
45 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
47 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
50 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
51 i18n>More information</a>
54 <span class="form-text text-muted"
55 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
56 i18n>This target has modified advanced settings.</span>
62 <div class="form-group row">
63 <label class="cd-col-form-label required"
66 <div class="cd-col-form-input">
68 <ng-container *ngFor="let portal of portals.value; let i = index">
69 <div class="input-group cd-mb">
70 <input class="cd-form-control"
74 <button class="btn btn-light"
76 (click)="removePortal(i, portal)">
77 <i [ngClass]="[icons.destroy]"
78 aria-hidden="true"></i>
84 <div class="col-md-12">
85 <cd-select [data]="portals.value"
86 [options]="portalsSelections"
87 [messages]="messages.portals"
88 (selection)="onPortalSelection($event)"
89 elemClass="btn btn-light float-end">
90 <i [ngClass]="[icons.add]"></i>
91 <ng-container i18n>Add portal</ng-container>
96 <input class="form-control"
100 formControlName="portals" />
102 <span class="invalid-feedback"
103 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
104 i18n>At least {{ minimum_gateways }} gateways are required.</span>
111 <div class="form-group row">
112 <label class="cd-col-form-label"
115 <div class="cd-col-form-input">
116 <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
117 <div class="input-group cd-mb">
118 <input class="cd-form-control"
122 <div class="input-group-text"
123 *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
124 <button class="btn btn-light"
126 (click)="imageSettingsModal(image)">
127 <i [ngClass]="[icons.deepCheck]"
128 aria-hidden="true"></i>
130 <button class="btn btn-light"
132 (click)="removeImage(i, image)">
133 <i [ngClass]="[icons.destroy]"
134 aria-hidden="true"></i>
139 <span class="form-text text-muted">
140 <ng-container *ngIf="backstores.length > 1"
141 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
143 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
144 i18n>This image has modified settings.</ng-container>
148 <input class="form-control"
152 formControlName="disks" />
154 <span class="invalid-feedback"
155 *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
156 i18n>Duplicated LUN numbers.</span>
158 <span class="invalid-feedback"
159 *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
160 i18n>Duplicated WWN.</span>
163 <div class="col-md-12">
164 <cd-select [data]="disks.value"
165 [options]="imagesSelections"
166 [messages]="messages.images"
167 (selection)="onImageSelection($event)"
168 elemClass="btn btn-light float-end">
169 <i [ngClass]="[icons.add]"></i>
170 <ng-container i18n>Add image</ng-container>
180 <div class="form-group row">
181 <div class="cd-col-form-offset">
182 <div class="custom-control custom-checkbox">
183 <input type="checkbox"
184 class="custom-control-input"
185 formControlName="acl_enabled"
188 <label for="acl_enabled"
189 class="custom-control-label"
190 i18n>ACL authentication</label>
197 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
198 <div formGroupName="auth"
199 *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
202 <div class="form-group row">
203 <label class="cd-col-form-label"
205 <ng-container i18n>User</ng-container>
207 <div class="cd-col-form-input">
208 <input class="form-control"
213 formControlName="user" />
215 <span class="invalid-feedback"
216 *ngIf="targetForm.showError('user', formDir, 'required')"
217 i18n>This field is required.</span>
219 <span class="invalid-feedback"
220 *ngIf="targetForm.showError('user', formDir, 'pattern')"
221 i18n>User names must have a length of 8 to 64 characters and can contain
222 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
226 <!-- Target password -->
227 <div class="form-group row">
228 <label class="cd-col-form-label"
229 for="target_password">
230 <ng-container i18n>Password</ng-container>
232 <div class="cd-col-form-input">
233 <div class="input-group">
234 <input class="form-control"
236 autocomplete="new-password"
238 name="target_password"
239 formControlName="password" />
240 <button type="button"
241 class="btn btn-light"
242 cdPasswordButton="target_password">
244 <cd-copy-2-clipboard-button source="target_password">
245 </cd-copy-2-clipboard-button>
248 <span class="invalid-feedback"
249 *ngIf="targetForm.showError('password', formDir, 'required')"
250 i18n>This field is required.</span>
252 <span class="invalid-feedback"
253 *ngIf="targetForm.showError('password', formDir, 'pattern')"
254 i18n>Passwords must have a length of 12 to 16 characters and can contain
255 alphanumeric characters, '@', '-', '_' or '/'.</span>
259 <!-- Target mutual_user -->
260 <div class="form-group row">
261 <label class="cd-col-form-label"
262 for="target_mutual_user">
263 <ng-container i18n>Mutual User</ng-container>
265 <div class="cd-col-form-input">
266 <input class="form-control"
269 id="target_mutual_user"
270 name="target_mutual_user"
271 formControlName="mutual_user" />
273 <span class="invalid-feedback"
274 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
275 i18n>This field is required.</span>
277 <span class="invalid-feedback"
278 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
279 i18n>User names must have a length of 8 to 64 characters and can contain
280 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
284 <!-- Target mutual_password -->
285 <div class="form-group row">
286 <label class="cd-col-form-label"
287 for="target_mutual_password">
288 <ng-container i18n>Mutual Password</ng-container>
290 <div class="cd-col-form-input">
291 <div class="input-group">
292 <input class="form-control"
294 autocomplete="new-password"
295 id="target_mutual_password"
296 name="target_mutual_password"
297 formControlName="mutual_password" />
299 <button type="button"
300 class="btn btn-light"
301 cdPasswordButton="target_mutual_password">
303 <cd-copy-2-clipboard-button source="target_mutual_password">
304 </cd-copy-2-clipboard-button>
307 <span class="invalid-feedback"
308 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
309 i18n>This field is required.</span>
311 <span class="invalid-feedback"
312 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
313 i18n>Passwords must have a length of 12 to 16 characters and can contain
314 alphanumeric characters, '@', '-', '_' or '/'.</span>
321 <div class="form-group row"
322 *ngIf="targetForm.getValue('acl_enabled')">
323 <label class="cd-col-form-label"
325 i18n>Initiators</label>
326 <div class="cd-col-form-input"
327 formArrayName="initiators">
328 <div class="card mb-2"
329 *ngFor="let initiator of initiators.controls; let ii = index"
330 [formGroup]="initiator">
331 <div class="card-header">
332 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
333 <button type="button"
334 class="btn-close float-end"
335 (click)="removeInitiator(ii)">
338 <div class="card-body">
339 <!-- Initiator: Name -->
340 <div class="form-group row">
341 <label class="cd-col-form-label required"
343 i18n>Client IQN</label>
344 <div class="cd-col-form-input">
345 <input class="form-control"
347 formControlName="client_iqn"
349 (blur)="updatedInitiatorSelector()">
351 <span class="invalid-feedback"
352 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
353 i18n>Initiator IQN needs to be unique.</span>
355 <span class="invalid-feedback"
356 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
357 i18n>This field is required.</span>
359 <span class="invalid-feedback"
360 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
361 i18n>IQN has wrong pattern.</span>
365 <ng-container formGroupName="auth">
366 <!-- Initiator: User -->
367 <div class="form-group row">
368 <label class="cd-col-form-label"
371 <div class="cd-col-form-input">
372 <input [id]="'user' + ii"
374 formControlName="user"
377 <span class="invalid-feedback"
378 *ngIf="initiator.showError('user', formDir, 'required')"
379 i18n>This field is required.</span>
381 <span class="invalid-feedback"
382 *ngIf="initiator.showError('user', formDir, 'pattern')"
383 i18n>User names must have a length of 8 to 64 characters and can contain
384 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
388 <!-- Initiator: Password -->
389 <div class="form-group row">
390 <label class="cd-col-form-label"
392 i18n>Password</label>
393 <div class="cd-col-form-input">
394 <div class="input-group">
395 <input [id]="'password' + ii"
397 formControlName="password"
398 autocomplete="new-password"
401 <button type="button"
402 class="btn btn-light"
403 [cdPasswordButton]="'password' + ii">
405 <cd-copy-2-clipboard-button [source]="'password' + ii">
406 </cd-copy-2-clipboard-button>
408 <span class="invalid-feedback"
409 *ngIf="initiator.showError('password', formDir, 'required')"
410 i18n>This field is required.</span>
412 <span class="invalid-feedback"
413 *ngIf="initiator.showError('password', formDir, 'pattern')"
414 i18n>Passwords must have a length of 12 to 16 characters and can contain
415 alphanumeric characters, '@', '-', '_' or '/'.</span>
420 <!-- Initiator: mutual_user -->
421 <div class="form-group row">
422 <label class="cd-col-form-label"
424 <ng-container i18n>Mutual User</ng-container>
426 <div class="cd-col-form-input">
427 <input [id]="'mutual_user' + ii"
429 formControlName="mutual_user"
433 <span class="invalid-feedback"
434 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
435 i18n>This field is required.</span>
437 <span class="invalid-feedback"
438 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
439 i18n>User names must have a length of 8 to 64 characters and can contain
440 alphanumeric characters, '.', '@', '-', '_' or ':'.</span>
444 <!-- Initiator: mutual_password -->
445 <div class="form-group row">
446 <label class="cd-col-form-label"
447 for="mutual_password"
448 i18n>Mutual Password</label>
449 <div class="cd-col-form-input">
450 <div class="input-group">
451 <input [id]="'mutual_password' + ii"
453 formControlName="mutual_password"
454 autocomplete="new-password"
457 <button type="button"
458 class="btn btn-light"
459 [cdPasswordButton]="'mutual_password' + ii">
461 <cd-copy-2-clipboard-button [source]="'mutual_password' + ii">
462 </cd-copy-2-clipboard-button>
464 <span class="invalid-feedback"
465 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
466 i18n>This field is required.</span>
468 <span class="invalid-feedback"
469 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
470 i18n>Passwords must have a length of 12 to 16 characters and can contain
471 alphanumeric characters, '@', '-', '_' or '/'.</span>
476 <!-- Initiator: Images -->
477 <div class="form-group row">
478 <label class="cd-col-form-label"
481 <div class="cd-col-form-input">
482 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
483 <div class="input-group cd-mb">
484 <input class="cd-form-control"
488 <button class="btn btn-light"
490 (click)="removeInitiatorImage(initiator, li, ii, image)">
491 <i [ngClass]="[icons.destroy]"
492 aria-hidden="true"></i>
497 <span *ngIf="initiator.getValue('cdIsInGroup')"
498 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
501 *ngIf="!initiator.getValue('cdIsInGroup')">
502 <div class="col-md-12">
503 <cd-select [data]="initiator.getValue('luns')"
504 [options]="imagesInitiatorSelections[ii]"
505 [messages]="messages.initiatorImage"
506 elemClass="btn btn-light float-end">
507 <i [ngClass]="[icons.add]"></i>
508 <ng-container i18n>Add image</ng-container>
518 <div class="col-md-12">
519 <span class="form-text text-muted"
520 *ngIf="initiators.controls.length === 0"
521 i18n>No items added.</span>
523 <button (click)="addInitiator(); false"
524 class="btn btn-light float-end">
525 <i [ngClass]="[icons.add]"></i>
526 <ng-container i18n>Add initiator</ng-container>
536 <div class="form-group row"
537 *ngIf="targetForm.getValue('acl_enabled')">
538 <label class="cd-col-form-label"
541 <div class="cd-col-form-input"
542 formArrayName="groups">
543 <div class="card mb-2"
544 *ngFor="let group of groups.controls; let gi = index"
546 <div class="card-header">
547 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
548 <button type="button"
549 class="btn-close float-end"
550 (click)="removeGroup(gi)">
553 <div class="card-body">
554 <!-- Group: group_id -->
555 <div class="form-group row">
556 <label class="cd-col-form-label required"
559 <div class="cd-col-form-input">
560 <input class="form-control"
562 formControlName="group_id">
566 <!-- Group: members -->
567 <div class="form-group row">
568 <label class="cd-col-form-label"
570 <ng-container i18n>Initiators</ng-container>
572 <div class="cd-col-form-input">
573 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
574 <div class="input-group cd-mb">
575 <input class="cd-form-control"
579 <button class="btn btn-light"
581 (click)="removeGroupInitiator(group, i, gi)">
582 <i [ngClass]="[icons.destroy]"
583 aria-hidden="true"></i>
589 <div class="col-md-12">
590 <cd-select [data]="group.getValue('members')"
591 [options]="groupMembersSelections[gi]"
592 [messages]="messages.groupInitiator"
593 (selection)="onGroupMemberSelection($event, gi)"
594 elemClass="btn btn-light float-end">
595 <i [ngClass]="[icons.add]"></i>
596 <ng-container i18n>Add initiator</ng-container>
605 <!-- Group: disks -->
606 <div class="form-group row">
607 <label class="cd-col-form-label"
609 <ng-container i18n>Images</ng-container>
611 <div class="cd-col-form-input">
612 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
613 <div class="input-group cd-mb">
614 <input class="cd-form-control"
618 <button class="btn btn-light"
620 (click)="removeGroupDisk(group, i, gi)">
621 <i [ngClass]="[icons.destroy]"
622 aria-hidden="true"></i>
628 <div class="col-md-12">
629 <cd-select [data]="group.getValue('disks')"
630 [options]="groupDiskSelections[gi]"
631 [messages]="messages.initiatorImage"
632 elemClass="btn btn-light float-end">
633 <i [ngClass]="[icons.add]"></i>
634 <ng-container i18n>Add image</ng-container>
646 <div class="col-md-12">
647 <span class="form-text text-muted"
648 *ngIf="groups.controls.length === 0"
649 i18n>No items added.</span>
651 <button (click)="addGroup(); false"
652 class="btn btn-light float-end">
653 <i [ngClass]="[icons.add]"></i>
654 <ng-container i18n>Add group</ng-container>
662 <div class="card-footer">
663 <cd-form-button-panel (submitActionEvent)="submit()"
665 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
666 wrappingClass="text-right"></cd-form-button-panel>