1 <div class="col-sm-12 col-lg-6">
2 <form name="targetForm"
3 class="form-horizontal"
5 [formGroup]="targetForm"
8 <div class="panel panel-default">
9 <div class="panel-heading">
10 <h3 i18n="form title|Example: Create Pool@@formTitle"
11 class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
14 <div class="panel-body">
16 <div class="form-group"
17 [ngClass]="{'has-error': targetForm.showError('target_iqn', formDir)}">
18 <label class="control-label col-sm-3"
20 <ng-container i18n>Target IQN</ng-container>
21 <span class="required"></span>
23 <div class="col-sm-9">
24 <div class="input-group">
25 <input class="form-control"
29 formControlName="target_iqn" />
30 <span class="input-group-btn">
31 <button class="btn btn-default"
34 (click)="targetSettingsModal()">
35 <i class="fa fa-cogs fa-fw"
36 aria-hidden="true"></i>
41 <span class="help-block"
42 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
43 i18n>This field is required.</span>
45 <span class="help-block"
46 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
47 i18n>IQN has wrong pattern.</span>
49 <span class="help-block"
50 *ngIf="targetForm.showError('target_iqn', formDir, 'iqn')">
51 <ng-container i18n>An IQN has the following notation 'iqn.$year-$month.$reversedAddress:$definedName'</ng-container>
53 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
56 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
57 i18n>More information</a>
60 <span class="help-block"
61 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
62 i18n>This target has modified advanced settings.</span>
68 <div class="form-group"
69 [ngClass]="{'has-error': targetForm.showError('portals', formDir)}">
70 <label class="control-label col-sm-3"
72 <ng-container i18n>Portals</ng-container>
73 <span class="required"></span>
75 <div class="col-sm-9">
77 <ng-container *ngFor="let portal of portals.value; let i = index">
78 <div class="input-group cd-mb">
79 <input class="form-control"
83 <span class="input-group-btn">
84 <button class="btn btn-default"
86 (click)="removePortal(i, portal)">
87 <i class="fa fa-remove fa-fw"
88 aria-hidden="true"></i>
94 <span class="help-block"
95 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
96 i18n>At least {{ minimum_gateways }} gateways are required.</span>
99 <div class="col-md-12">
100 <cd-select [data]="portals.value"
101 [options]="portalsSelections"
102 [messages]="messages.portals"
103 (selection)="onPortalSelection($event)"
104 elemClass="btn btn-default pull-right">
105 <i class="fa fa-fw fa-plus"></i>
106 <ng-container i18n>Add portal</ng-container>
116 <div class="form-group"
117 [ngClass]="{'has-error': targetForm.showError('disks', formDir)}">
118 <label class="control-label col-sm-3"
121 <div class="col-sm-9">
122 <ng-container *ngFor="let image of targetForm.getValue('disks'); let i = index">
123 <div class="input-group cd-mb">
124 <input class="form-control"
128 <span class="input-group-btn">
129 <button class="btn btn-default"
131 (click)="imageSettingsModal(image)">
132 <i class="fa fa-cogs fa-fw"
133 aria-hidden="true"></i>
135 <button class="btn btn-default"
137 (click)="removeImage(i, image)">
138 <i class="fa fa-remove fa-fw"
139 aria-hidden="true"></i>
145 <span class="help-block">
146 <ng-container *ngIf="backstores.length > 1"
147 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}. </ng-container>
149 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
150 i18n>This image has modified settings.</ng-container>
154 <span class="help-block"
155 *ngIf="targetForm.showError('disks', formDir, 'required')"
156 i18n>At least 1 image is required.</span>
159 <div class="col-md-12">
160 <cd-select [data]="disks.value"
161 [options]="imagesSelections"
162 [messages]="messages.images"
163 (selection)="onImageSelection($event)"
164 elemClass="btn btn-default pull-right">
165 <i class="fa fa-fw fa-plus"></i>
166 <ng-container i18n>Add image</ng-container>
176 <div class="form-group">
177 <div class="col-sm-offset-3 col-sm-9">
178 <div class="checkbox checkbox-primary">
179 <input type="checkbox"
180 formControlName="acl_enabled"
183 <label for="acl_enabled"
184 i18n>ACL authentication</label>
191 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
192 <div formGroupName="auth" *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
195 <div class="form-group"
196 [ngClass]="{'has-error': targetForm.showError('user', formDir)}">
197 <label class="control-label col-sm-3"
199 <ng-container i18n>User</ng-container>
201 <div class="col-sm-9">
202 <input class="form-control"
206 formControlName="user" />
208 <span class="help-block"
209 *ngIf="targetForm.showError('user', formDir, 'required')"
210 i18n>This field is required.</span>
212 <span class="help-block"
213 *ngIf="targetForm.showError('user', formDir, 'pattern')"
214 i18n>Usernames must have a length of 8 to 64 characters and
215 can only contain letters, '.', '@', '-', '_' or ':'.</span>
219 <!-- Target password -->
220 <div class="form-group"
221 [ngClass]="{'has-error': targetForm.showError('password', formDir)}">
222 <label class="control-label col-sm-3"
223 for="target_password">
224 <ng-container i18n>Password</ng-container>
226 <div class="col-sm-9">
227 <div class="input-group">
228 <input class="form-control"
230 autocomplete="new-password"
232 name="target_password"
233 formControlName="password" />
235 <span class="input-group-btn">
236 <button type="button"
237 class="btn btn-default"
238 cdPasswordButton="target_password">
240 <button type="button"
241 class="btn btn-default"
242 cdCopy2ClipboardButton="target_password">
247 <span class="help-block"
248 *ngIf="targetForm.showError('password', formDir, 'required')"
249 i18n>This field is required.</span>
251 <span class="help-block"
252 *ngIf="targetForm.showError('password', formDir, 'pattern')"
253 i18n>Passwords must have a length of 12 to 16 characters
254 and can only contain letters, '@', '-', '_' or '/'.</span>
258 <!-- Target mutual_user -->
259 <div class="form-group"
260 [ngClass]="{'has-error': targetForm.showError('mutual_user', formDir)}">
261 <label class="control-label col-sm-3"
262 for="target_mutual_user">
263 <ng-container i18n>Mutual User</ng-container>
265 <div class="col-sm-9">
266 <input class="form-control"
268 id="target_mutual_user"
269 name="target_mutual_user"
270 formControlName="mutual_user" />
272 <span class="help-block"
273 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
274 i18n>This field is required.</span>
276 <span class="help-block"
277 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
278 i18n>Usernames must have a length of 8 to 64 characters and
279 can only contain letters, '.', '@', '-', '_' or ':'.</span>
283 <!-- Target mutual_password -->
284 <div class="form-group"
285 [ngClass]="{'has-error': targetForm.showError('mutual_password', formDir)}">
286 <label class="control-label col-sm-3"
287 for="target_mutual_password">
288 <ng-container i18n>Mutual Password</ng-container>
290 <div class="col-sm-9">
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 <span class="input-group-btn">
300 <button type="button"
301 class="btn btn-default"
302 cdPasswordButton="target_mutual_password">
304 <button type="button"
305 class="btn btn-default"
306 cdCopy2ClipboardButton="target_mutual_password">
311 <span class="help-block"
312 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
313 i18n>This field is required.</span>
315 <span class="help-block"
316 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
317 i18n>Passwords must have a length of 12 to 16 characters
318 and can only contain letters, '@', '-', '_' or '/'.</span>
325 <div class="form-group"
326 *ngIf="targetForm.getValue('acl_enabled')">
327 <label class="control-label col-sm-3"
329 i18n>Initiators</label>
330 <div class="col-sm-9"
331 formArrayName="initiators">
332 <div class="panel panel-default"
333 *ngFor="let initiator of initiators.controls; let ii = index"
334 [formGroupName]="ii">
335 <div class="panel-heading">
336 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
337 <button type="button"
339 (click)="removeInitiator(ii)">
340 <i class="fa fa-remove fa-fw"></i>
343 <div class="panel-body">
344 <!-- Initiator: Name -->
345 <div class="form-group"
346 [ngClass]="{'has-error': initiator.showError('client_iqn', formDir)}">
347 <label class="control-label col-sm-3"
349 <ng-container i18n>Client IQN</ng-container>
350 <span class="required"></span>
352 <div class="col-sm-9">
353 <input class="form-control"
355 formControlName="client_iqn"
356 (blur)="updatedInitiatorSelector()">
358 <span class="help-block"
359 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
360 i18n>Initiator IQN needs to be unique.</span>
362 <span class="help-block"
363 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
364 i18n>This field is required.</span>
366 <span class="help-block"
367 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
368 i18n>IQN has wrong pattern.</span>
372 <ng-container formGroupName="auth">
373 <!-- Initiator: User -->
374 <div class="form-group"
375 [ngClass]="{'has-error': initiator.showError('user', formDir)}">
376 <label class="control-label col-sm-3"
379 <div class="col-sm-9">
380 <input [id]="'user' + ii"
382 formControlName="user"
384 <span class="help-block"
385 *ngIf="initiator.showError('user', formDir, 'required')"
386 i18n>This field is required.</span>
388 <span class="help-block"
389 *ngIf="initiator.showError('user', formDir, 'pattern')"
390 i18n>Usernames must have a length of 8 to 64 characters and
391 can only contain letters, '.', '@', '-', '_' or ':'.</span>
395 <!-- Initiator: Password -->
396 <div class="form-group"
397 [ngClass]="{'has-error': initiator.showError('password', formDir)}">
398 <label class="control-label col-sm-3"
400 i18n>Password</label>
401 <div class="col-sm-9">
402 <div class="input-group">
403 <input [id]="'password' + ii"
405 formControlName="password"
408 <span class="input-group-btn">
409 <button type="button"
410 class="btn btn-default"
411 [cdPasswordButton]="'password' + ii">
413 <button type="button"
414 class="btn btn-default"
415 [cdCopy2ClipboardButton]="'password' + ii">
419 <span class="help-block"
420 *ngIf="initiator.showError('password', formDir, 'required')"
421 i18n>This field is required.</span>
423 <span class="help-block"
424 *ngIf="initiator.showError('password', formDir, 'pattern')"
425 i18n>Passwords must have a length of 12 to 16 characters
426 and can only contain letters, '@', '-', '_' or '/'.</span>
431 <!-- Initiator: mutual_user -->
432 <div class="form-group"
433 [ngClass]="{'has-error': initiator.showError('mutual_user', formDir)}">
434 <label class="control-label col-sm-3"
436 <ng-container i18n>Mutual User</ng-container>
438 <div class="col-sm-9">
439 <input [id]="'mutual_user' + ii"
441 formControlName="mutual_user"
444 <span class="help-block"
445 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
446 i18n>This field is required.</span>
448 <span class="help-block"
449 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
450 i18n>Usernames must have a length of 8 to 64 characters and
451 can only contain letters, '.', '@', '-', '_' or ':'.</span>
455 <!-- Initiator: mutual_password -->
456 <div class="form-group"
457 [ngClass]="{'has-error': initiator.showError('mutual_password', formDir)}">
458 <label class="control-label col-sm-3"
459 for="mutual_password"
460 i18n>Mutual Password</label>
461 <div class="col-sm-9">
462 <div class="input-group">
463 <input [id]="'mutual_password' + ii"
465 formControlName="mutual_password"
468 <span class="input-group-btn">
469 <button type="button"
470 class="btn btn-default"
471 [cdPasswordButton]="'mutual_password' + ii">
473 <button type="button"
474 class="btn btn-default"
475 [cdCopy2ClipboardButton]="'mutual_password' + ii">
479 <span class="help-block"
480 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
481 i18n>This field is required.</span>
483 <span class="help-block"
484 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
485 i18n>Passwords must have a length of 12 to 16 characters and
486 can only contain letters, '@', '-', '_' or '/'.</span>
491 <!-- Initiator: Images -->
492 <div class="form-group"
493 [ngClass]="{'has-error': initiator.showError('luns', formDir)}">
494 <label class="control-label col-sm-3"
497 <div class="col-sm-9">
498 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
499 <div class="input-group cd-mb">
500 <input class="form-control"
504 <span class="input-group-btn">
505 <button class="btn btn-default"
507 (click)="removeInitiatorImage(initiator, li, ii, image)">
508 <i class="fa fa-remove fa-fw"
509 aria-hidden="true"></i>
515 <span *ngIf="initiator.getValue('cdIsInGroup')"
516 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
519 *ngIf="!initiator.getValue('cdIsInGroup')">
520 <div class="col-md-12">
521 <cd-select [data]="initiator.getValue('luns')"
522 [options]="imagesInitiatorSelections[ii]"
523 [messages]="messages.initiatorImage"
524 elemClass="btn btn-default pull-right">
525 <i class="fa fa-fw fa-plus"></i>
526 <ng-container i18n>Add image</ng-container>
536 <div class="col-md-12">
537 <span class="text-muted"
538 *ngIf="initiators.controls.length === 0"
539 i18n>No items added.</span>
541 <button (click)="addInitiator(); false"
542 class="btn btn-default pull-right">
543 <i class="fa fa-fw fa-plus"></i>
544 <ng-container i18n>Add initiator</ng-container>
554 <div class="form-group"
555 *ngIf="targetForm.getValue('acl_enabled')"
556 [ngClass]="{'has-error': targetForm.showError('groups', formDir)}">
557 <label class="control-label col-sm-3"
560 <div class="col-sm-9"
561 formArrayName="groups">
562 <div class="panel panel-default"
563 *ngFor="let group of groups.controls; let gi = index"
564 [formGroupName]="gi">
565 <div class="panel-heading">
566 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
567 <button type="button"
569 (click)="groups.removeAt(gi)">
570 <i class="fa fa-remove fa-fw"></i>
573 <div class="panel-body">
574 <!-- Group: group_id -->
575 <div class="form-group">
576 <label class="control-label col-sm-3"
578 <ng-container i18n>Name</ng-container>
579 <span class="required"></span>
581 <div class="col-sm-9">
582 <input class="form-control"
584 formControlName="group_id">
588 <!-- Group: members -->
589 <div class="form-group"
590 [ngClass]="{'has-error': group.showError('members', formDir)}">
591 <label class="control-label col-sm-3"
593 <ng-container i18n>Initiators</ng-container>
595 <div class="col-sm-9">
596 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
597 <div class="input-group cd-mb">
598 <input class="form-control"
602 <span class="input-group-btn">
603 <button class="btn btn-default"
605 (click)="removeGroupInitiator(group, i, gi)">
606 <i class="fa fa-remove fa-fw"
607 aria-hidden="true"></i>
614 <div class="col-md-12">
615 <cd-select [data]="group.getValue('members')"
616 [options]="groupMembersSelections[gi]"
617 [messages]="messages.groupInitiator"
618 (selection)="onGroupMemberSelection($event)"
619 elemClass="btn btn-default pull-right">
620 <i class="fa fa-fw fa-plus"></i>
621 <ng-container i18n>Add initiator</ng-container>
630 <!-- Group: disks -->
631 <div class="form-group"
632 [ngClass]="{'has-error': group.showError('disks', formDir)}">
633 <label class="control-label col-sm-3"
635 <ng-container i18n>Images</ng-container>
637 <div class="col-sm-9">
638 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
639 <div class="input-group cd-mb">
640 <input class="form-control"
644 <span class="input-group-btn">
645 <button class="btn btn-default"
647 (click)="removeGroupDisk(group, i, gi)">
648 <i class="fa fa-remove fa-fw"
649 aria-hidden="true"></i>
656 <div class="col-md-12">
657 <cd-select [data]="group.getValue('disks')"
658 [options]="groupDiskSelections[gi]"
659 [messages]="messages.initiatorImage"
660 elemClass="btn btn-default pull-right">
661 <i class="fa fa-fw fa-plus"></i>
662 <ng-container i18n>Add image</ng-container>
674 <div class="col-md-12">
675 <span class="text-muted"
676 *ngIf="groups.controls.length === 0"
677 i18n>No items added.</span>
679 <button (click)="addGroup(); false"
680 class="btn btn-default pull-right">
681 <i class="fa fa-fw fa-plus"></i>
682 <ng-container i18n>Add group</ng-container>
690 <div class="panel-footer">
691 <div class="button-group text-right">
694 (submitAction)="submit()"
695 i18n="form action button|Example: Create Pool@@formActionButton"
696 type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
697 <cd-back-button></cd-back-button>