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="custom-control custom-checkbox">
177 <input type="checkbox"
178 class="custom-control-input"
179 formControlName="acl_enabled"
182 <label for="acl_enabled"
183 class="custom-control-label"
184 i18n>ACL authentication</label>
192 <div class="form-group row"
193 *ngIf="targetForm.getValue('acl_enabled')">
194 <label class="col-form-label col-sm-3"
196 i18n>Initiators</label>
197 <div class="col-sm-9"
198 formArrayName="initiators">
199 <div class="card mb-2"
200 *ngFor="let initiator of initiators.controls; let ii = index"
201 [formGroupName]="ii">
202 <div class="card-header">
203 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
204 <button type="button"
206 (click)="removeInitiator(ii)">
207 <i [ngClass]="[icons.deepCheck]"></i>
210 <div class="card-body">
211 <!-- Initiator: Name -->
212 <div class="form-group row"
213 [ngClass]="{':invalid': initiator.showError('client_iqn', formDir)}">
214 <label class="col-form-label col-sm-3"
216 <ng-container i18n>Client IQN</ng-container>
217 <span class="required"></span>
219 <div class="col-sm-9">
220 <input class="form-control"
222 formControlName="client_iqn"
223 (blur)="updatedInitiatorSelector()">
225 <span class="form-text text-muted"
226 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
227 i18n>Initiator IQN needs to be unique.</span>
229 <span class="form-text text-muted"
230 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
231 i18n>This field is required.</span>
233 <span class="form-text text-muted"
234 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
235 i18n>IQN has wrong pattern.</span>
239 <ng-container formGroupName="auth">
240 <!-- Initiator: User -->
241 <div class="form-group row"
242 [ngClass]="{':invalid': initiator.showError('user', formDir)}">
243 <label class="col-form-label col-sm-3"
246 <div class="col-sm-9">
247 <input [id]="'user' + ii"
249 formControlName="user"
251 <span class="form-text text-muted"
252 *ngIf="initiator.showError('user', formDir, 'required')"
253 i18n>This field is required.</span>
255 <span class="form-text text-muted"
256 *ngIf="initiator.showError('user', formDir, 'pattern')"
257 i18n>Usernames must have a length of 8 to 64 characters and
258 can only contain letters, '.', '@', '-', '_' or ':'.</span>
262 <!-- Initiator: Password -->
263 <div class="form-group row"
264 [ngClass]="{':invalid': initiator.showError('password', formDir)}">
265 <label class="col-form-label col-sm-3"
267 i18n>Password</label>
268 <div class="col-sm-9">
269 <div class="input-group">
270 <input [id]="'password' + ii"
272 formControlName="password"
275 <span class="input-group-append">
276 <button type="button"
277 class="btn btn-light"
278 [cdPasswordButton]="'password' + ii">
280 <button type="button"
281 class="btn btn-light"
282 [cdCopy2ClipboardButton]="'password' + ii">
286 <span class="form-text text-muted"
287 *ngIf="initiator.showError('password', formDir, 'required')"
288 i18n>This field is required.</span>
290 <span class="form-text text-muted"
291 *ngIf="initiator.showError('password', formDir, 'pattern')"
292 i18n>Passwords must have a length of 12 to 16 characters
293 and can only contain letters, '@', '-', '_' or '/'.</span>
298 <!-- Initiator: mutual_user -->
299 <div class="form-group row"
300 [ngClass]="{':invalid': initiator.showError('mutual_user', formDir)}">
301 <label class="col-form-label col-sm-3"
303 <ng-container i18n>Mutual User</ng-container>
305 <div class="col-sm-9">
306 <input [id]="'mutual_user' + ii"
308 formControlName="mutual_user"
311 <span class="form-text text-muted"
312 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
313 i18n>This field is required.</span>
315 <span class="form-text text-muted"
316 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
317 i18n>Usernames must have a length of 8 to 64 characters and
318 can only contain letters, '.', '@', '-', '_' or ':'.</span>
322 <!-- Initiator: mutual_password -->
323 <div class="form-group row"
324 [ngClass]="{':invalid': initiator.showError('mutual_password', formDir)}">
325 <label class="col-form-label col-sm-3"
326 for="mutual_password"
327 i18n>Mutual Password</label>
328 <div class="col-sm-9">
329 <div class="input-group">
330 <input [id]="'mutual_password' + ii"
332 formControlName="mutual_password"
335 <span class="input-group-append">
336 <button type="button"
337 class="btn btn-light"
338 [cdPasswordButton]="'mutual_password' + ii">
340 <button type="button"
341 class="btn btn-light"
342 [cdCopy2ClipboardButton]="'mutual_password' + ii">
346 <span class="form-text text-muted"
347 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
348 i18n>This field is required.</span>
350 <span class="form-text text-muted"
351 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
352 i18n>Passwords must have a length of 12 to 16 characters and
353 can only contain letters, '@', '-', '_' or '/'.</span>
358 <!-- Initiator: Images -->
359 <div class="form-group row"
360 [ngClass]="{':invalid': initiator.showError('luns', formDir)}">
361 <label class="col-form-label col-sm-3"
364 <div class="col-sm-9">
365 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
366 <div class="input-group cd-mb">
367 <input class="cd-form-control"
371 <span class="input-group-append">
372 <button class="btn btn-light"
374 (click)="removeInitiatorImage(initiator, li, ii, image)">
375 <i [ngClass]="[icons.destroy]"
376 aria-hidden="true"></i>
382 <span *ngIf="initiator.getValue('cdIsInGroup')"
383 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
386 *ngIf="!initiator.getValue('cdIsInGroup')">
387 <div class="col-md-12">
388 <cd-select [data]="initiator.getValue('luns')"
389 [options]="imagesInitiatorSelections[ii]"
390 [messages]="messages.initiatorImage"
391 elemClass="btn btn-light float-right">
392 <i [ngClass]="[icons.add]"></i>
393 <ng-container i18n>Add image</ng-container>
403 <div class="col-md-12">
404 <span class="form-text text-muted"
405 *ngIf="initiators.controls.length === 0"
406 i18n>No items added.</span>
408 <button (click)="addInitiator(); false"
409 class="btn btn-light float-right">
410 <i [ngClass]="[icons.add]"></i>
411 <ng-container i18n>Add initiator</ng-container>
421 <div class="form-group row"
422 *ngIf="targetForm.getValue('acl_enabled')"
423 [ngClass]="{':invalid': targetForm.showError('groups', formDir)}">
424 <label class="col-form-label col-sm-3"
427 <div class="col-sm-9"
428 formArrayName="groups">
429 <div class="card mb-2"
430 *ngFor="let group of groups.controls; let gi = index"
431 [formGroupName]="gi">
432 <div class="card-header">
433 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
434 <button type="button"
436 (click)="groups.removeAt(gi)">
437 <i [ngClass]="[icons.destroy]"></i>
440 <div class="card-body">
441 <!-- Group: group_id -->
442 <div class="form-group row">
443 <label class="col-form-label col-sm-3"
445 <ng-container i18n>Name</ng-container>
446 <span class="required"></span>
448 <div class="col-sm-9">
449 <input class="form-control"
451 formControlName="group_id">
455 <!-- Group: members -->
456 <div class="form-group row"
457 [ngClass]="{':invalid': group.showError('members', formDir)}">
458 <label class="col-form-label col-sm-3"
460 <ng-container i18n>Initiators</ng-container>
462 <div class="col-sm-9">
463 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
464 <div class="input-group cd-mb">
465 <input class="cd-form-control"
469 <span class="input-group-append">
470 <button class="btn btn-light"
472 (click)="removeGroupInitiator(group, i, gi)">
473 <i [ngClass]="[icons.destroy]"
474 aria-hidden="true"></i>
481 <div class="col-md-12">
482 <cd-select [data]="group.getValue('members')"
483 [options]="groupMembersSelections[gi]"
484 [messages]="messages.groupInitiator"
485 (selection)="onGroupMemberSelection($event)"
486 elemClass="btn btn-light float-right">
487 <i [ngClass]="[icons.add]"></i>
488 <ng-container i18n>Add initiator</ng-container>
497 <!-- Group: disks -->
498 <div class="form-group row"
499 [ngClass]="{':invalid': group.showError('disks', formDir)}">
500 <label class="col-form-label col-sm-3"
502 <ng-container i18n>Images</ng-container>
504 <div class="col-sm-9">
505 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
506 <div class="input-group cd-mb">
507 <input class="cd-form-control"
511 <span class="input-group-append">
512 <button class="btn btn-light"
514 (click)="removeGroupDisk(group, i, gi)">
515 <i [ngClass]="[icons.destroy]"
516 aria-hidden="true"></i>
523 <div class="col-md-12">
524 <cd-select [data]="group.getValue('disks')"
525 [options]="groupDiskSelections[gi]"
526 [messages]="messages.initiatorImage"
527 elemClass="btn btn-light float-right">
528 <i [ngClass]="[icons.add]"></i>
529 <ng-container i18n>Add image</ng-container>
541 <div class="col-md-12">
542 <span class="form-text text-muted"
543 *ngIf="groups.controls.length === 0"
544 i18n>No items added.</span>
546 <button (click)="addGroup(); false"
547 class="btn btn-light float-right">
548 <i [ngClass]="[icons.add]"></i>
549 <ng-container i18n>Add group</ng-container>
557 <div class="card-footer">
558 <div class="button-group text-right">
559 <cd-submit-button (submitAction)="submit()"
560 i18n="form action button|Example: Create Pool@@formActionButton"
561 [form]="formDir">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
562 <cd-back-button></cd-back-button>