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 [ngClass]="{':invalid': targetForm.showError('target_iqn', formDir)}">
15 <label class="col-form-label col-sm-3"
17 <ng-container i18n>Target IQN</ng-container>
18 <span class="required"></span>
20 <div class="col-sm-9">
21 <div class="input-group">
22 <input class="form-control"
26 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="form-text text-muted"
39 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
40 i18n>This field is required.</span>
42 <span class="form-text text-muted"
43 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
44 i18n>IQN has wrong pattern.</span>
46 <span class="form-text text-muted"
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 [ngClass]="{':invalid': targetForm.showError('portals', formDir)}">
68 <label class="col-form-label col-sm-3"
70 <ng-container i18n>Portals</ng-container>
71 <span class="required"></span>
73 <div class="col-sm-9">
75 <ng-container *ngFor="let portal of portals.value; let i = index">
76 <div class="input-group cd-mb">
77 <input class="cd-form-control"
81 <span class="input-group-append">
82 <button class="btn btn-light"
84 (click)="removePortal(i, portal)">
85 <i [ngClass]="[icons.destroy]"
86 aria-hidden="true"></i>
92 <span class="form-text text-muted"
93 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
94 i18n>At least {{ minimum_gateways }} gateways are required.</span>
97 <div class="col-md-12">
98 <cd-select [data]="portals.value"
99 [options]="portalsSelections"
100 [messages]="messages.portals"
101 (selection)="onPortalSelection($event)"
102 elemClass="btn btn-light float-right">
103 <i [ngClass]="[icons.add]"></i>
104 <ng-container i18n>Add portal</ng-container>
114 <div class="form-group row"
115 [ngClass]="{':invalid': targetForm.showError('disks', formDir)}">
116 <label class="col-form-label col-sm-3"
119 <div class="col-sm-9">
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 <button class="btn btn-light"
129 (click)="imageSettingsModal(image)">
130 <i [ngClass]="[icons.deepCheck]"
131 aria-hidden="true"></i>
133 <button class="btn btn-light"
135 (click)="removeImage(i, image)">
136 <i [ngClass]="[icons.destroy]"
137 aria-hidden="true"></i>
143 <span class="form-text text-muted">
144 <ng-container *ngIf="backstores.length > 1"
145 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
147 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
148 i18n>This image has modified settings.</ng-container>
152 <span class="form-text text-muted"
153 *ngIf="targetForm.showError('disks', formDir, 'required')"
154 i18n>At least 1 image is required.</span>
157 <div class="col-md-12">
158 <cd-select [data]="disks.value"
159 [options]="imagesSelections"
160 [messages]="messages.images"
161 (selection)="onImageSelection($event)"
162 elemClass="btn btn-light float-right">
163 <i [ngClass]="[icons.add]"></i>
164 <ng-container i18n>Add image</ng-container>
174 <div class="form-group row">
175 <div class="offset-sm-3 col-sm-9">
176 <div class="checkbox checkbox-primary">
177 <input type="checkbox"
178 formControlName="acl_enabled"
181 <label for="acl_enabled"
182 i18n>ACL authentication</label>
190 <div class="form-group row"
191 *ngIf="targetForm.getValue('acl_enabled')">
192 <label class="col-form-label col-sm-3"
194 i18n>Initiators</label>
195 <div class="col-sm-9"
196 formArrayName="initiators">
197 <div class="card mb-2"
198 *ngFor="let initiator of initiators.controls; let ii = index"
199 [formGroupName]="ii">
200 <div class="card-header">
201 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
202 <button type="button"
204 (click)="removeInitiator(ii)">
205 <i [ngClass]="[icons.deepCheck]"></i>
208 <div class="card-body">
209 <!-- Initiator: Name -->
210 <div class="form-group row"
211 [ngClass]="{':invalid': initiator.showError('client_iqn', formDir)}">
212 <label class="col-form-label col-sm-3"
214 <ng-container i18n>Client IQN</ng-container>
215 <span class="required"></span>
217 <div class="col-sm-9">
218 <input class="form-control"
220 formControlName="client_iqn"
221 (blur)="updatedInitiatorSelector()">
223 <span class="form-text text-muted"
224 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
225 i18n>Initiator IQN needs to be unique.</span>
227 <span class="form-text text-muted"
228 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
229 i18n>This field is required.</span>
231 <span class="form-text text-muted"
232 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
233 i18n>IQN has wrong pattern.</span>
237 <ng-container formGroupName="auth">
238 <!-- Initiator: User -->
239 <div class="form-group row"
240 [ngClass]="{':invalid': initiator.showError('user', formDir)}">
241 <label class="col-form-label col-sm-3"
244 <div class="col-sm-9">
245 <input [id]="'user' + ii"
247 formControlName="user"
249 <span class="form-text text-muted"
250 *ngIf="initiator.showError('user', formDir, 'required')"
251 i18n>This field is required.</span>
253 <span class="form-text text-muted"
254 *ngIf="initiator.showError('user', formDir, 'pattern')"
255 i18n>Usernames must have a length of 8 to 64 characters and
256 can only contain letters, '.', '@', '-', '_' or ':'.</span>
260 <!-- Initiator: Password -->
261 <div class="form-group row"
262 [ngClass]="{':invalid': initiator.showError('password', formDir)}">
263 <label class="col-form-label col-sm-3"
265 i18n>Password</label>
266 <div class="col-sm-9">
267 <div class="input-group">
268 <input [id]="'password' + ii"
270 formControlName="password"
273 <span class="input-group-append">
274 <button type="button"
275 class="btn btn-light"
276 [cdPasswordButton]="'password' + ii">
278 <button type="button"
279 class="btn btn-light"
280 [cdCopy2ClipboardButton]="'password' + ii">
284 <span class="form-text text-muted"
285 *ngIf="initiator.showError('password', formDir, 'required')"
286 i18n>This field is required.</span>
288 <span class="form-text text-muted"
289 *ngIf="initiator.showError('password', formDir, 'pattern')"
290 i18n>Passwords must have a length of 12 to 16 characters
291 and can only contain letters, '@', '-', '_' or '/'.</span>
296 <!-- Initiator: mutual_user -->
297 <div class="form-group row"
298 [ngClass]="{':invalid': initiator.showError('mutual_user', formDir)}">
299 <label class="col-form-label col-sm-3"
301 <ng-container i18n>Mutual User</ng-container>
303 <div class="col-sm-9">
304 <input [id]="'mutual_user' + ii"
306 formControlName="mutual_user"
309 <span class="form-text text-muted"
310 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
311 i18n>This field is required.</span>
313 <span class="form-text text-muted"
314 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
315 i18n>Usernames must have a length of 8 to 64 characters and
316 can only contain letters, '.', '@', '-', '_' or ':'.</span>
320 <!-- Initiator: mutual_password -->
321 <div class="form-group row"
322 [ngClass]="{':invalid': initiator.showError('mutual_password', formDir)}">
323 <label class="col-form-label col-sm-3"
324 for="mutual_password"
325 i18n>Mutual Password</label>
326 <div class="col-sm-9">
327 <div class="input-group">
328 <input [id]="'mutual_password' + ii"
330 formControlName="mutual_password"
333 <span class="input-group-append">
334 <button type="button"
335 class="btn btn-light"
336 [cdPasswordButton]="'mutual_password' + ii">
338 <button type="button"
339 class="btn btn-light"
340 [cdCopy2ClipboardButton]="'mutual_password' + ii">
344 <span class="form-text text-muted"
345 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
346 i18n>This field is required.</span>
348 <span class="form-text text-muted"
349 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
350 i18n>Passwords must have a length of 12 to 16 characters and
351 can only contain letters, '@', '-', '_' or '/'.</span>
356 <!-- Initiator: Images -->
357 <div class="form-group row"
358 [ngClass]="{':invalid': initiator.showError('luns', formDir)}">
359 <label class="col-form-label col-sm-3"
362 <div class="col-sm-9">
363 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
364 <div class="input-group cd-mb">
365 <input class="cd-form-control"
369 <span class="input-group-append">
370 <button class="btn btn-light"
372 (click)="removeInitiatorImage(initiator, li, ii, image)">
373 <i [ngClass]="[icons.destroy]"
374 aria-hidden="true"></i>
380 <span *ngIf="initiator.getValue('cdIsInGroup')"
381 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
384 *ngIf="!initiator.getValue('cdIsInGroup')">
385 <div class="col-md-12">
386 <cd-select [data]="initiator.getValue('luns')"
387 [options]="imagesInitiatorSelections[ii]"
388 [messages]="messages.initiatorImage"
389 elemClass="btn btn-light float-right">
390 <i [ngClass]="[icons.add]"></i>
391 <ng-container i18n>Add image</ng-container>
401 <div class="col-md-12">
402 <span class="form-text text-muted"
403 *ngIf="initiators.controls.length === 0"
404 i18n>No items added.</span>
406 <button (click)="addInitiator(); false"
407 class="btn btn-light float-right">
408 <i [ngClass]="[icons.add]"></i>
409 <ng-container i18n>Add initiator</ng-container>
419 <div class="form-group row"
420 *ngIf="targetForm.getValue('acl_enabled')"
421 [ngClass]="{':invalid': targetForm.showError('groups', formDir)}">
422 <label class="col-form-label col-sm-3"
425 <div class="col-sm-9"
426 formArrayName="groups">
427 <div class="card mb-2"
428 *ngFor="let group of groups.controls; let gi = index"
429 [formGroupName]="gi">
430 <div class="card-header">
431 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
432 <button type="button"
434 (click)="groups.removeAt(gi)">
435 <i [ngClass]="[icons.destroy]"></i>
438 <div class="card-body">
439 <!-- Group: group_id -->
440 <div class="form-group row">
441 <label class="col-form-label col-sm-3"
443 <ng-container i18n>Name</ng-container>
444 <span class="required"></span>
446 <div class="col-sm-9">
447 <input class="form-control"
449 formControlName="group_id">
453 <!-- Group: members -->
454 <div class="form-group row"
455 [ngClass]="{':invalid': group.showError('members', formDir)}">
456 <label class="col-form-label col-sm-3"
458 <ng-container i18n>Initiators</ng-container>
460 <div class="col-sm-9">
461 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
462 <div class="input-group cd-mb">
463 <input class="cd-form-control"
467 <span class="input-group-append">
468 <button class="btn btn-light"
470 (click)="removeGroupInitiator(group, i, gi)">
471 <i [ngClass]="[icons.destroy]"
472 aria-hidden="true"></i>
479 <div class="col-md-12">
480 <cd-select [data]="group.getValue('members')"
481 [options]="groupMembersSelections[gi]"
482 [messages]="messages.groupInitiator"
483 (selection)="onGroupMemberSelection($event)"
484 elemClass="btn btn-light float-right">
485 <i [ngClass]="[icons.add]"></i>
486 <ng-container i18n>Add initiator</ng-container>
495 <!-- Group: disks -->
496 <div class="form-group row"
497 [ngClass]="{':invalid': group.showError('disks', formDir)}">
498 <label class="col-form-label col-sm-3"
500 <ng-container i18n>Images</ng-container>
502 <div class="col-sm-9">
503 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
504 <div class="input-group cd-mb">
505 <input class="cd-form-control"
509 <span class="input-group-append">
510 <button class="btn btn-light"
512 (click)="removeGroupDisk(group, i, gi)">
513 <i [ngClass]="[icons.destroy]"
514 aria-hidden="true"></i>
521 <div class="col-md-12">
522 <cd-select [data]="group.getValue('disks')"
523 [options]="groupDiskSelections[gi]"
524 [messages]="messages.initiatorImage"
525 elemClass="btn btn-light float-right">
526 <i [ngClass]="[icons.add]"></i>
527 <ng-container i18n>Add image</ng-container>
539 <div class="col-md-12">
540 <span class="form-text text-muted"
541 *ngIf="groups.controls.length === 0"
542 i18n>No items added.</span>
544 <button (click)="addGroup(); false"
545 class="btn btn-light float-right">
546 <i [ngClass]="[icons.add]"></i>
547 <ng-container i18n>Add group</ng-container>
555 <div class="card-footer">
556 <div class="button-group text-right">
557 <cd-submit-button (submitAction)="submit()"
558 i18n="form action button|Example: Create Pool@@formActionButton"
559 [form]="formDir">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
560 <cd-back-button></cd-back-button>