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>