1 <div class="col-sm-12 col-lg-6">
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="col-form-label col-sm-3"
16 <ng-container i18n>Target IQN</ng-container>
17 <span class="required"></span>
19 <div class="col-sm-9">
20 <div class="input-group">
21 <input class="form-control"
25 formControlName="target_iqn" />
26 <span class="input-group-append">
27 <button class="btn btn-light"
30 (click)="targetSettingsModal()">
31 <i [ngClass]="[icons.deepCheck]"
32 aria-hidden="true"></i>
37 <span class="invalid-feedback"
38 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
39 i18n>This field is required.</span>
41 <span class="invalid-feedback"
42 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
43 i18n>IQN has wrong pattern.</span>
45 <span class="invalid-feedback"
46 *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
47 <ng-container i18n>An IQN has the following notation
48 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
50 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
53 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
54 i18n>More information</a>
57 <span class="form-text text-muted"
58 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
59 i18n>This target has modified advanced settings.</span>
65 <div class="form-group row">
66 <label class="col-form-label col-sm-3"
68 <ng-container i18n>Portals</ng-container>
69 <span class="required"></span>
71 <div class="col-sm-9">
73 <ng-container *ngFor="let portal of portals.value; let i = index">
74 <div class="input-group cd-mb">
75 <input class="cd-form-control"
79 <span class="input-group-append">
80 <button class="btn btn-light"
82 (click)="removePortal(i, portal)">
83 <i [ngClass]="[icons.destroy]"
84 aria-hidden="true"></i>
91 <div class="col-md-12">
92 <cd-select [data]="portals.value"
93 [options]="portalsSelections"
94 [messages]="messages.portals"
95 (selection)="onPortalSelection($event)"
96 elemClass="btn btn-light float-right">
97 <i [ngClass]="[icons.add]"></i>
98 <ng-container i18n>Add portal</ng-container>
103 <input class="form-control"
107 formControlName="portals" />
109 <span class="invalid-feedback"
110 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
111 i18n>At least {{ minimum_gateways }} gateways are required.</span>
118 <div class="form-group row">
119 <label class="col-form-label col-sm-3"
122 <div class="col-sm-9">
123 <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
124 <div class="input-group cd-mb">
125 <input class="cd-form-control"
129 <span class="input-group-append">
130 <button class="btn btn-light"
132 (click)="imageSettingsModal(image)">
133 <i [ngClass]="[icons.deepCheck]"
134 aria-hidden="true"></i>
136 <button class="btn btn-light"
138 (click)="removeImage(i, image)">
139 <i [ngClass]="[icons.destroy]"
140 aria-hidden="true"></i>
146 <span class="form-text text-muted">
147 <ng-container *ngIf="backstores.length > 1"
148 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
150 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
151 i18n>This image has modified settings.</ng-container>
156 <div class="col-md-12">
157 <cd-select [data]="disks.value"
158 [options]="imagesSelections"
159 [messages]="messages.images"
160 (selection)="onImageSelection($event)"
161 elemClass="btn btn-light float-right">
162 <i [ngClass]="[icons.add]"></i>
163 <ng-container i18n>Add image</ng-container>
173 <div class="form-group row">
174 <div class="offset-sm-3 col-sm-9">
175 <div class="custom-control custom-checkbox">
176 <input type="checkbox"
177 class="custom-control-input"
178 formControlName="acl_enabled"
181 <label for="acl_enabled"
182 class="custom-control-label"
183 i18n>ACL authentication</label>
190 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
191 <div formGroupName="auth" *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
194 <div class="form-group row">
195 <label class="col-form-label col-sm-3"
197 <ng-container i18n>User</ng-container>
199 <div class="col-sm-9">
200 <input class="form-control"
204 formControlName="user" />
206 <span class="invalid-feedback"
207 *ngIf="targetForm.showError('user', formDir, 'required')"
208 i18n>This field is required.</span>
210 <span class="invalid-feedback"
211 *ngIf="targetForm.showError('user', formDir, 'pattern')"
212 i18n>Usernames must have a length of 8 to 64 characters and
213 can only contain letters, '.', '@', '-', '_' or ':'.</span>
217 <!-- Target password -->
218 <div class="form-group row">
219 <label class="col-form-label col-sm-3"
220 for="target_password">
221 <ng-container i18n>Password</ng-container>
223 <div class="col-sm-9">
224 <div class="input-group">
225 <input class="form-control"
227 autocomplete="new-password"
229 name="target_password"
230 formControlName="password" />
232 <span class="input-group-append">
233 <button type="button"
234 class="btn btn-light"
235 cdPasswordButton="target_password">
237 <button type="button"
238 class="btn btn-light"
239 cdCopy2ClipboardButton="target_password">
244 <span class="invalid-feedback"
245 *ngIf="targetForm.showError('password', formDir, 'required')"
246 i18n>This field is required.</span>
248 <span class="invalid-feedback"
249 *ngIf="targetForm.showError('password', formDir, 'pattern')"
250 i18n>Passwords must have a length of 12 to 16 characters
251 and can only contain letters, '@', '-', '_' or '/'.</span>
255 <!-- Target mutual_user -->
256 <div class="form-group row">
257 <label class="col-form-label col-sm-3"
258 for="target_mutual_user">
259 <ng-container i18n>Mutual User</ng-container>
261 <div class="col-sm-9">
262 <input class="form-control"
264 id="target_mutual_user"
265 name="target_mutual_user"
266 formControlName="mutual_user" />
268 <span class="invalid-feedback"
269 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
270 i18n>This field is required.</span>
272 <span class="invalid-feedback"
273 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
274 i18n>Usernames must have a length of 8 to 64 characters and
275 can only contain letters, '.', '@', '-', '_' or ':'.</span>
279 <!-- Target mutual_password -->
280 <div class="form-group row">
281 <label class="col-form-label col-sm-3"
282 for="target_mutual_password">
283 <ng-container i18n>Mutual Password</ng-container>
285 <div class="col-sm-9">
286 <div class="input-group">
287 <input class="form-control"
289 autocomplete="new-password"
290 id="target_mutual_password"
291 name="target_mutual_password"
292 formControlName="mutual_password" />
294 <span class="input-group-append">
295 <button type="button"
296 class="btn btn-light"
297 cdPasswordButton="target_mutual_password">
299 <button type="button"
300 class="btn btn-light"
301 cdCopy2ClipboardButton="target_mutual_password">
306 <span class="invalid-feedback"
307 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
308 i18n>This field is required.</span>
310 <span class="invalid-feedback"
311 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
312 i18n>Passwords must have a length of 12 to 16 characters
313 and can only contain letters, '@', '-', '_' or '/'.</span>
320 <div class="form-group row"
321 *ngIf="targetForm.getValue('acl_enabled')">
322 <label class="col-form-label col-sm-3"
324 i18n>Initiators</label>
325 <div class="col-sm-9"
326 formArrayName="initiators">
327 <div class="card mb-2"
328 *ngFor="let initiator of initiators.controls; let ii = index"
329 [formGroupName]="ii">
330 <div class="card-header">
331 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
332 <button type="button"
334 (click)="removeInitiator(ii)">
335 <i [ngClass]="[icons.destroy]"></i>
338 <div class="card-body">
339 <!-- Initiator: Name -->
340 <div class="form-group row">
341 <label class="col-form-label col-sm-3"
343 <ng-container i18n>Client IQN</ng-container>
344 <span class="required"></span>
346 <div class="col-sm-9">
347 <input class="form-control"
349 formControlName="client_iqn"
350 (blur)="updatedInitiatorSelector()">
352 <span class="invalid-feedback"
353 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
354 i18n>Initiator IQN needs to be unique.</span>
356 <span class="invalid-feedback"
357 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
358 i18n>This field is required.</span>
360 <span class="invalid-feedback"
361 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
362 i18n>IQN has wrong pattern.</span>
366 <ng-container formGroupName="auth">
367 <!-- Initiator: User -->
368 <div class="form-group row">
369 <label class="col-form-label col-sm-3"
372 <div class="col-sm-9">
373 <input [id]="'user' + ii"
375 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>Usernames must have a length of 8 to 64 characters and
384 can only contain letters, '.', '@', '-', '_' or ':'.</span>
388 <!-- Initiator: Password -->
389 <div class="form-group row">
390 <label class="col-form-label col-sm-3"
392 i18n>Password</label>
393 <div class="col-sm-9">
394 <div class="input-group">
395 <input [id]="'password' + ii"
397 formControlName="password"
400 <span class="input-group-append">
401 <button type="button"
402 class="btn btn-light"
403 [cdPasswordButton]="'password' + ii">
405 <button type="button"
406 class="btn btn-light"
407 [cdCopy2ClipboardButton]="'password' + ii">
411 <span class="invalid-feedback"
412 *ngIf="initiator.showError('password', formDir, 'required')"
413 i18n>This field is required.</span>
415 <span class="invalid-feedback"
416 *ngIf="initiator.showError('password', formDir, 'pattern')"
417 i18n>Passwords must have a length of 12 to 16 characters
418 and can only contain letters, '@', '-', '_' or '/'.</span>
423 <!-- Initiator: mutual_user -->
424 <div class="form-group row">
425 <label class="col-form-label col-sm-3"
427 <ng-container i18n>Mutual User</ng-container>
429 <div class="col-sm-9">
430 <input [id]="'mutual_user' + ii"
432 formControlName="mutual_user"
435 <span class="invalid-feedback"
436 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
437 i18n>This field is required.</span>
439 <span class="invalid-feedback"
440 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
441 i18n>Usernames must have a length of 8 to 64 characters and
442 can only contain letters, '.', '@', '-', '_' or ':'.</span>
446 <!-- Initiator: mutual_password -->
447 <div class="form-group row">
448 <label class="col-form-label col-sm-3"
449 for="mutual_password"
450 i18n>Mutual Password</label>
451 <div class="col-sm-9">
452 <div class="input-group">
453 <input [id]="'mutual_password' + ii"
455 formControlName="mutual_password"
458 <span class="input-group-append">
459 <button type="button"
460 class="btn btn-light"
461 [cdPasswordButton]="'mutual_password' + ii">
463 <button type="button"
464 class="btn btn-light"
465 [cdCopy2ClipboardButton]="'mutual_password' + ii">
469 <span class="invalid-feedback"
470 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
471 i18n>This field is required.</span>
473 <span class="invalid-feedback"
474 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
475 i18n>Passwords must have a length of 12 to 16 characters and
476 can only contain letters, '@', '-', '_' or '/'.</span>
481 <!-- Initiator: Images -->
482 <div class="form-group row">
483 <label class="col-form-label col-sm-3"
486 <div class="col-sm-9">
487 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
488 <div class="input-group cd-mb">
489 <input class="cd-form-control"
493 <span class="input-group-append">
494 <button class="btn btn-light"
496 (click)="removeInitiatorImage(initiator, li, ii, image)">
497 <i [ngClass]="[icons.destroy]"
498 aria-hidden="true"></i>
504 <span *ngIf="initiator.getValue('cdIsInGroup')"
505 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
508 *ngIf="!initiator.getValue('cdIsInGroup')">
509 <div class="col-md-12">
510 <cd-select [data]="initiator.getValue('luns')"
511 [options]="imagesInitiatorSelections[ii]"
512 [messages]="messages.initiatorImage"
513 elemClass="btn btn-light float-right">
514 <i [ngClass]="[icons.add]"></i>
515 <ng-container i18n>Add image</ng-container>
525 <div class="col-md-12">
526 <span class="form-text text-muted"
527 *ngIf="initiators.controls.length === 0"
528 i18n>No items added.</span>
530 <button (click)="addInitiator(); false"
531 class="btn btn-light float-right">
532 <i [ngClass]="[icons.add]"></i>
533 <ng-container i18n>Add initiator</ng-container>
543 <div class="form-group row"
544 *ngIf="targetForm.getValue('acl_enabled')">
545 <label class="col-form-label col-sm-3"
548 <div class="col-sm-9"
549 formArrayName="groups">
550 <div class="card mb-2"
551 *ngFor="let group of groups.controls; let gi = index"
552 [formGroupName]="gi">
553 <div class="card-header">
554 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
555 <button type="button"
557 (click)="groups.removeAt(gi)">
558 <i [ngClass]="[icons.destroy]"></i>
561 <div class="card-body">
562 <!-- Group: group_id -->
563 <div class="form-group row">
564 <label class="col-form-label col-sm-3"
566 <ng-container i18n>Name</ng-container>
567 <span class="required"></span>
569 <div class="col-sm-9">
570 <input class="form-control"
572 formControlName="group_id">
576 <!-- Group: members -->
577 <div class="form-group row">
578 <label class="col-form-label col-sm-3"
580 <ng-container i18n>Initiators</ng-container>
582 <div class="col-sm-9">
583 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
584 <div class="input-group cd-mb">
585 <input class="cd-form-control"
589 <span class="input-group-append">
590 <button class="btn btn-light"
592 (click)="removeGroupInitiator(group, i, gi)">
593 <i [ngClass]="[icons.destroy]"
594 aria-hidden="true"></i>
601 <div class="col-md-12">
602 <cd-select [data]="group.getValue('members')"
603 [options]="groupMembersSelections[gi]"
604 [messages]="messages.groupInitiator"
605 (selection)="onGroupMemberSelection($event)"
606 elemClass="btn btn-light float-right">
607 <i [ngClass]="[icons.add]"></i>
608 <ng-container i18n>Add initiator</ng-container>
617 <!-- Group: disks -->
618 <div class="form-group row">
619 <label class="col-form-label col-sm-3"
621 <ng-container i18n>Images</ng-container>
623 <div class="col-sm-9">
624 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
625 <div class="input-group cd-mb">
626 <input class="cd-form-control"
630 <span class="input-group-append">
631 <button class="btn btn-light"
633 (click)="removeGroupDisk(group, i, gi)">
634 <i [ngClass]="[icons.destroy]"
635 aria-hidden="true"></i>
642 <div class="col-md-12">
643 <cd-select [data]="group.getValue('disks')"
644 [options]="groupDiskSelections[gi]"
645 [messages]="messages.initiatorImage"
646 elemClass="btn btn-light float-right">
647 <i [ngClass]="[icons.add]"></i>
648 <ng-container i18n>Add image</ng-container>
660 <div class="col-md-12">
661 <span class="form-text text-muted"
662 *ngIf="groups.controls.length === 0"
663 i18n>No items added.</span>
665 <button (click)="addGroup(); false"
666 class="btn btn-light float-right">
667 <i [ngClass]="[icons.add]"></i>
668 <ng-container i18n>Add group</ng-container>
676 <div class="card-footer">
677 <div class="button-group text-right">
678 <cd-submit-button (submitAction)="submit()"
679 i18n="form action button|Example: Create Pool@@formActionButton"
680 [form]="formDir">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
681 <cd-back-button></cd-back-button>