]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.html
import ceph 14.2.5
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / block / iscsi-target-form / iscsi-target-form.component.html
CommitLineData
11fdf7f2
TL
1<div class="col-sm-12 col-lg-6">
2 <form name="targetForm"
3 class="form-horizontal"
4 #formDir="ngForm"
5 [formGroup]="targetForm"
6 novalidate
7 *ngIf="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>
12 </div>
13
14 <div class="panel-body">
15 <!-- Target IQN -->
16 <div class="form-group"
17 [ngClass]="{'has-error': targetForm.showError('target_iqn', formDir)}">
18 <label class="control-label col-sm-3"
19 for="target_iqn">
20 <ng-container i18n>Target IQN</ng-container>
21 <span class="required"></span>
22 </label>
23 <div class="col-sm-9">
24 <div class="input-group">
25 <input class="form-control"
26 type="text"
27 id="target_iqn"
28 name="target_iqn"
29 formControlName="target_iqn" />
30 <span class="input-group-btn">
31 <button class="btn btn-default"
32 id="ecp-info-button"
33 type="button"
34 (click)="targetSettingsModal()">
35 <i class="fa fa-cogs fa-fw"
36 aria-hidden="true"></i>
37 </button>
38 </span>
39 </div>
40
41 <span class="help-block"
42 *ngIf="targetForm.showError('target_iqn', formDir, 'required')"
43 i18n>This field is required.</span>
44
45 <span class="help-block"
46 *ngIf="targetForm.showError('target_iqn', formDir, 'pattern')"
47 i18n>IQN has wrong pattern.</span>
48
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>
52 <br>
53 <ng-container i18n>For example: iqn.2016-06.org.dashboard:storage:disk.sn-a8675309</ng-container>
54 <br>
55 <a target="_blank"
56 href="https://en.wikipedia.org/wiki/ISCSI#Addressing"
57 i18n>More information</a>
58 </span>
59
60 <span class="help-block"
61 *ngIf="hasAdvancedSettings(targetForm.getValue('target_controls'))"
62 i18n>This target has modified advanced settings.</span>
63 <hr />
64 </div>
65 </div>
66
67 <!-- Portals -->
68 <div class="form-group"
69 [ngClass]="{'has-error': targetForm.showError('portals', formDir)}">
70 <label class="control-label col-sm-3"
71 for="portals">
72 <ng-container i18n>Portals</ng-container>
73 <span class="required"></span>
74 </label>
75 <div class="col-sm-9">
76
77 <ng-container *ngFor="let portal of portals.value; let i = index">
78 <div class="input-group cd-mb">
79 <input class="form-control"
80 type="text"
81 [value]="portal"
82 disabled />
83 <span class="input-group-btn">
84 <button class="btn btn-default"
85 type="button"
86 (click)="removePortal(i, portal)">
87 <i class="fa fa-remove fa-fw"
88 aria-hidden="true"></i>
89 </button>
90 </span>
91 </div>
92 </ng-container>
93
94 <span class="help-block"
95 *ngIf="targetForm.showError('portals', formDir, 'minGateways')"
96 i18n>At least {{ minimum_gateways }} gateways are required.</span>
97
98 <div class="row">
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>
107 </cd-select>
108 </div>
109 </div>
110
111 <hr />
112 </div>
113 </div>
114
115 <!-- Images -->
116 <div class="form-group"
117 [ngClass]="{'has-error': targetForm.showError('disks', formDir)}">
118 <label class="control-label col-sm-3"
119 for="disks"
120 i18n>Images</label>
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"
125 type="text"
126 [value]="image"
127 disabled />
eafe8130
TL
128 <div class="input-group-addon"
129 *ngIf="api_version >= 1">lun: {{ imagesSettings[image]['lun'] }}</div>
11fdf7f2
TL
130 <span class="input-group-btn">
131 <button class="btn btn-default"
132 type="button"
133 (click)="imageSettingsModal(image)">
134 <i class="fa fa-cogs fa-fw"
135 aria-hidden="true"></i>
136 </button>
137 <button class="btn btn-default"
138 type="button"
139 (click)="removeImage(i, image)">
140 <i class="fa fa-remove fa-fw"
141 aria-hidden="true"></i>
142 </button>
143 </span>
144
145 </div>
146
147 <span class="help-block">
148 <ng-container *ngIf="backstores.length > 1"
149 i18n>Backstore: {{ imagesSettings[image].backstore | iscsiBackstore }}.&nbsp;</ng-container>
150
151 <ng-container *ngIf="hasAdvancedSettings(imagesSettings[image][imagesSettings[image].backstore])"
152 i18n>This image has modified settings.</ng-container>
153 </span>
154 </ng-container>
155
eafe8130
TL
156 <input class="form-control"
157 type="hidden"
158 id="disks"
159 name="disks"
160 formControlName="disks" />
161
162 <span class="help-block"
163 *ngIf="targetForm.showError('disks', formDir, 'dupLunId')"
164 i18n>Duplicated LUN numbers.</span>
165
11fdf7f2 166 <span class="help-block"
eafe8130
TL
167 *ngIf="targetForm.showError('disks', formDir, 'dupWwn')"
168 i18n>Duplicated WWN.</span>
11fdf7f2
TL
169
170 <div class="row">
171 <div class="col-md-12">
172 <cd-select [data]="disks.value"
173 [options]="imagesSelections"
174 [messages]="messages.images"
175 (selection)="onImageSelection($event)"
176 elemClass="btn btn-default pull-right">
177 <i class="fa fa-fw fa-plus"></i>
178 <ng-container i18n>Add image</ng-container>
179 </cd-select>
180 </div>
181 </div>
182
183 <hr />
184 </div>
185 </div>
186
187 <!-- acl_enabled -->
188 <div class="form-group">
189 <div class="col-sm-offset-3 col-sm-9">
190 <div class="checkbox checkbox-primary">
191 <input type="checkbox"
192 formControlName="acl_enabled"
193 name="acl_enabled"
194 id="acl_enabled">
195 <label for="acl_enabled"
196 i18n>ACL authentication</label>
197 </div>
198
199 <hr />
200 </div>
201 </div>
202
eafe8130
TL
203 <!-- Target level authentication was introduced in ceph-iscsi config v11 -->
204 <div formGroupName="auth" *ngIf="cephIscsiConfigVersion > 10 && !targetForm.getValue('acl_enabled')">
205
206 <!-- Target user -->
207 <div class="form-group"
208 [ngClass]="{'has-error': targetForm.showError('user', formDir)}">
209 <label class="control-label col-sm-3"
210 for="target_user">
211 <ng-container i18n>User</ng-container>
212 </label>
213 <div class="col-sm-9">
214 <input class="form-control"
215 type="text"
216 id="target_user"
217 name="target_user"
218 formControlName="user" />
219
220 <span class="help-block"
221 *ngIf="targetForm.showError('user', formDir, 'required')"
222 i18n>This field is required.</span>
223
224 <span class="help-block"
225 *ngIf="targetForm.showError('user', formDir, 'pattern')"
226 i18n>Usernames must have a length of 8 to 64 characters and
227 can only contain letters, '.', '@', '-', '_' or ':'.</span>
228 </div>
229 </div>
230
231 <!-- Target password -->
232 <div class="form-group"
233 [ngClass]="{'has-error': targetForm.showError('password', formDir)}">
234 <label class="control-label col-sm-3"
235 for="target_password">
236 <ng-container i18n>Password</ng-container>
237 </label>
238 <div class="col-sm-9">
239 <div class="input-group">
240 <input class="form-control"
241 type="password"
242 autocomplete="new-password"
243 id="target_password"
244 name="target_password"
245 formControlName="password" />
246 <span class="input-group-btn">
247 <button type="button"
248 class="btn btn-default"
249 cdPasswordButton="target_password">
250 </button>
251 <button type="button"
252 class="btn btn-default"
253 cdCopy2ClipboardButton="target_password">
254 </button>
255 </span>
256 </div>
257
258 <span class="help-block"
259 *ngIf="targetForm.showError('password', formDir, 'required')"
260 i18n>This field is required.</span>
261
262 <span class="help-block"
263 *ngIf="targetForm.showError('password', formDir, 'pattern')"
264 i18n>Passwords must have a length of 12 to 16 characters
265 and can only contain letters, '@', '-', '_' or '/'.</span>
266 </div>
267 </div>
268
269 <!-- Target mutual_user -->
270 <div class="form-group"
271 [ngClass]="{'has-error': targetForm.showError('mutual_user', formDir)}">
272 <label class="control-label col-sm-3"
273 for="target_mutual_user">
274 <ng-container i18n>Mutual User</ng-container>
275 </label>
276 <div class="col-sm-9">
277 <input class="form-control"
278 type="text"
279 id="target_mutual_user"
280 name="target_mutual_user"
281 formControlName="mutual_user" />
282
283 <span class="help-block"
284 *ngIf="targetForm.showError('mutual_user', formDir, 'required')"
285 i18n>This field is required.</span>
286
287 <span class="help-block"
288 *ngIf="targetForm.showError('mutual_user', formDir, 'pattern')"
289 i18n>Usernames must have a length of 8 to 64 characters and
290 can only contain letters, '.', '@', '-', '_' or ':'.</span>
291 </div>
292 </div>
293
294 <!-- Target mutual_password -->
295 <div class="form-group"
296 [ngClass]="{'has-error': targetForm.showError('mutual_password', formDir)}">
297 <label class="control-label col-sm-3"
298 for="target_mutual_password">
299 <ng-container i18n>Mutual Password</ng-container>
300 </label>
301 <div class="col-sm-9">
302 <div class="input-group">
303 <input class="form-control"
304 type="password"
305 autocomplete="new-password"
306 id="target_mutual_password"
307 name="target_mutual_password"
308 formControlName="mutual_password" />
309
310 <span class="input-group-btn">
311 <button type="button"
312 class="btn btn-default"
313 cdPasswordButton="target_mutual_password">
314 </button>
315 <button type="button"
316 class="btn btn-default"
317 cdCopy2ClipboardButton="target_mutual_password">
318 </button>
319 </span>
320 </div>
321
322 <span class="help-block"
323 *ngIf="targetForm.showError('mutual_password', formDir, 'required')"
324 i18n>This field is required.</span>
325
326 <span class="help-block"
327 *ngIf="targetForm.showError('mutual_password', formDir, 'pattern')"
328 i18n>Passwords must have a length of 12 to 16 characters
329 and can only contain letters, '@', '-', '_' or '/'.</span>
330 </div>
331 </div>
332
333 </div>
334
11fdf7f2
TL
335 <!-- Initiators -->
336 <div class="form-group"
337 *ngIf="targetForm.getValue('acl_enabled')">
338 <label class="control-label col-sm-3"
339 for="initiators"
340 i18n>Initiators</label>
341 <div class="col-sm-9"
342 formArrayName="initiators">
343 <div class="panel panel-default"
344 *ngFor="let initiator of initiators.controls; let ii = index"
345 [formGroupName]="ii">
346 <div class="panel-heading">
347 <ng-container i18n>Initiator</ng-container>: {{ initiator.getValue('client_iqn') }}
348 <button type="button"
349 class="close"
350 (click)="removeInitiator(ii)">
351 <i class="fa fa-remove fa-fw"></i>
352 </button>
353 </div>
354 <div class="panel-body">
355 <!-- Initiator: Name -->
356 <div class="form-group"
357 [ngClass]="{'has-error': initiator.showError('client_iqn', formDir)}">
358 <label class="control-label col-sm-3"
359 for="client_iqn">
360 <ng-container i18n>Client IQN</ng-container>
361 <span class="required"></span>
362 </label>
363 <div class="col-sm-9">
364 <input class="form-control"
365 type="text"
366 formControlName="client_iqn"
367 (blur)="updatedInitiatorSelector()">
368
369 <span class="help-block"
370 *ngIf="initiator.showError('client_iqn', formDir, 'notUnique')"
371 i18n>Initiator IQN needs to be unique.</span>
372
373 <span class="help-block"
374 *ngIf="initiator.showError('client_iqn', formDir, 'required')"
375 i18n>This field is required.</span>
376
377 <span class="help-block"
378 *ngIf="initiator.showError('client_iqn', formDir, 'pattern')"
379 i18n>IQN has wrong pattern.</span>
380 </div>
381 </div>
382
383 <ng-container formGroupName="auth">
384 <!-- Initiator: User -->
385 <div class="form-group"
386 [ngClass]="{'has-error': initiator.showError('user', formDir)}">
387 <label class="control-label col-sm-3"
388 for="user"
389 i18n>User</label>
390 <div class="col-sm-9">
81eedcae 391 <input [id]="'user' + ii"
11fdf7f2
TL
392 class="form-control"
393 formControlName="user"
394 type="text">
395 <span class="help-block"
396 *ngIf="initiator.showError('user', formDir, 'required')"
397 i18n>This field is required.</span>
398
399 <span class="help-block"
400 *ngIf="initiator.showError('user', formDir, 'pattern')"
401 i18n>Usernames must have a length of 8 to 64 characters and
402 can only contain letters, '.', '@', '-', '_' or ':'.</span>
403 </div>
404 </div>
405
406 <!-- Initiator: Password -->
407 <div class="form-group"
408 [ngClass]="{'has-error': initiator.showError('password', formDir)}">
409 <label class="control-label col-sm-3"
410 for="password"
411 i18n>Password</label>
412 <div class="col-sm-9">
413 <div class="input-group">
81eedcae 414 <input [id]="'password' + ii"
11fdf7f2
TL
415 class="form-control"
416 formControlName="password"
417 type="password">
418
419 <span class="input-group-btn">
420 <button type="button"
421 class="btn btn-default"
81eedcae 422 [cdPasswordButton]="'password' + ii">
11fdf7f2
TL
423 </button>
424 <button type="button"
425 class="btn btn-default"
81eedcae 426 [cdCopy2ClipboardButton]="'password' + ii">
11fdf7f2
TL
427 </button>
428 </span>
429 </div>
430 <span class="help-block"
431 *ngIf="initiator.showError('password', formDir, 'required')"
432 i18n>This field is required.</span>
433
434 <span class="help-block"
435 *ngIf="initiator.showError('password', formDir, 'pattern')"
436 i18n>Passwords must have a length of 12 to 16 characters
437 and can only contain letters, '@', '-', '_' or '/'.</span>
438 </div>
439 </div>
440
441
442 <!-- Initiator: mutual_user -->
443 <div class="form-group"
444 [ngClass]="{'has-error': initiator.showError('mutual_user', formDir)}">
445 <label class="control-label col-sm-3"
446 for="mutual_user">
447 <ng-container i18n>Mutual User</ng-container>
448 </label>
449 <div class="col-sm-9">
81eedcae 450 <input [id]="'mutual_user' + ii"
11fdf7f2
TL
451 class="form-control"
452 formControlName="mutual_user"
453 type="text">
454
455 <span class="help-block"
456 *ngIf="initiator.showError('mutual_user', formDir, 'required')"
457 i18n>This field is required.</span>
458
459 <span class="help-block"
460 *ngIf="initiator.showError('mutual_user', formDir, 'pattern')"
461 i18n>Usernames must have a length of 8 to 64 characters and
462 can only contain letters, '.', '@', '-', '_' or ':'.</span>
463 </div>
464 </div>
465
466 <!-- Initiator: mutual_password -->
467 <div class="form-group"
468 [ngClass]="{'has-error': initiator.showError('mutual_password', formDir)}">
469 <label class="control-label col-sm-3"
470 for="mutual_password"
471 i18n>Mutual Password</label>
472 <div class="col-sm-9">
473 <div class="input-group">
81eedcae 474 <input [id]="'mutual_password' + ii"
11fdf7f2
TL
475 class="form-control"
476 formControlName="mutual_password"
477 type="password">
478
479 <span class="input-group-btn">
480 <button type="button"
481 class="btn btn-default"
81eedcae 482 [cdPasswordButton]="'mutual_password' + ii">
11fdf7f2
TL
483 </button>
484 <button type="button"
485 class="btn btn-default"
81eedcae 486 [cdCopy2ClipboardButton]="'mutual_password' + ii">
11fdf7f2
TL
487 </button>
488 </span>
489 </div>
490 <span class="help-block"
491 *ngIf="initiator.showError('mutual_password', formDir, 'required')"
492 i18n>This field is required.</span>
493
494 <span class="help-block"
495 *ngIf="initiator.showError('mutual_password', formDir, 'pattern')"
496 i18n>Passwords must have a length of 12 to 16 characters and
497 can only contain letters, '@', '-', '_' or '/'.</span>
498 </div>
499 </div>
500 </ng-container>
501
502 <!-- Initiator: Images -->
503 <div class="form-group"
504 [ngClass]="{'has-error': initiator.showError('luns', formDir)}">
505 <label class="control-label col-sm-3"
506 for="luns"
507 i18n>Images</label>
508 <div class="col-sm-9">
509 <ng-container *ngFor="let image of initiator.getValue('luns'); let li = index">
510 <div class="input-group cd-mb">
511 <input class="form-control"
512 type="text"
513 [value]="image"
514 disabled />
515 <span class="input-group-btn">
516 <button class="btn btn-default"
517 type="button"
518 (click)="removeInitiatorImage(initiator, li, ii, image)">
519 <i class="fa fa-remove fa-fw"
520 aria-hidden="true"></i>
521 </button>
522 </span>
523 </div>
524 </ng-container>
525
526 <span *ngIf="initiator.getValue('cdIsInGroup')"
527 i18n>Initiator belongs to a group. Images will be configure in the group.</span>
528
529 <div class="row"
530 *ngIf="!initiator.getValue('cdIsInGroup')">
531 <div class="col-md-12">
532 <cd-select [data]="initiator.getValue('luns')"
533 [options]="imagesInitiatorSelections[ii]"
534 [messages]="messages.initiatorImage"
535 elemClass="btn btn-default pull-right">
536 <i class="fa fa-fw fa-plus"></i>
537 <ng-container i18n>Add image</ng-container>
538 </cd-select>
539 </div>
540 </div>
541 </div>
542 </div>
543 </div>
544 </div>
545
546 <div class="row">
547 <div class="col-md-12">
548 <span class="text-muted"
549 *ngIf="initiators.controls.length === 0"
550 i18n>No items added.</span>
551
552 <button (click)="addInitiator(); false"
553 class="btn btn-default pull-right">
554 <i class="fa fa-fw fa-plus"></i>
555 <ng-container i18n>Add initiator</ng-container>
556 </button>
557 </div>
558 </div>
559
560 <hr />
561 </div>
562 </div>
563
564 <!-- Groups -->
565 <div class="form-group"
566 *ngIf="targetForm.getValue('acl_enabled')"
567 [ngClass]="{'has-error': targetForm.showError('groups', formDir)}">
568 <label class="control-label col-sm-3"
569 for="initiators"
570 i18n>Groups</label>
571 <div class="col-sm-9"
572 formArrayName="groups">
573 <div class="panel panel-default"
574 *ngFor="let group of groups.controls; let gi = index"
575 [formGroupName]="gi">
576 <div class="panel-heading">
577 <ng-container i18n>Group</ng-container>: {{ group.getValue('group_id') }}
578 <button type="button"
579 class="close"
580 (click)="groups.removeAt(gi)">
581 <i class="fa fa-remove fa-fw"></i>
582 </button>
583 </div>
584 <div class="panel-body">
585 <!-- Group: group_id -->
586 <div class="form-group">
587 <label class="control-label col-sm-3"
588 for="group_id">
589 <ng-container i18n>Name</ng-container>
590 <span class="required"></span>
591 </label>
592 <div class="col-sm-9">
593 <input class="form-control"
594 type="text"
595 formControlName="group_id">
596 </div>
597 </div>
598
599 <!-- Group: members -->
600 <div class="form-group"
601 [ngClass]="{'has-error': group.showError('members', formDir)}">
602 <label class="control-label col-sm-3"
603 for="members">
604 <ng-container i18n>Initiators</ng-container>
605 </label>
606 <div class="col-sm-9">
607 <ng-container *ngFor="let member of group.getValue('members'); let i = index">
608 <div class="input-group cd-mb">
609 <input class="form-control"
610 type="text"
611 [value]="member"
612 disabled />
613 <span class="input-group-btn">
614 <button class="btn btn-default"
615 type="button"
616 (click)="removeGroupInitiator(group, i, gi)">
617 <i class="fa fa-remove fa-fw"
618 aria-hidden="true"></i>
619 </button>
620 </span>
621 </div>
622 </ng-container>
623
624 <div class="row">
625 <div class="col-md-12">
626 <cd-select [data]="group.getValue('members')"
627 [options]="groupMembersSelections[gi]"
628 [messages]="messages.groupInitiator"
629 (selection)="onGroupMemberSelection($event)"
630 elemClass="btn btn-default pull-right">
631 <i class="fa fa-fw fa-plus"></i>
632 <ng-container i18n>Add initiator</ng-container>
633 </cd-select>
634 </div>
635 </div>
636
637 <hr />
638 </div>
639 </div>
640
641 <!-- Group: disks -->
642 <div class="form-group"
643 [ngClass]="{'has-error': group.showError('disks', formDir)}">
644 <label class="control-label col-sm-3"
645 for="disks">
646 <ng-container i18n>Images</ng-container>
647 </label>
648 <div class="col-sm-9">
649 <ng-container *ngFor="let disk of group.getValue('disks'); let i = index">
650 <div class="input-group cd-mb">
651 <input class="form-control"
652 type="text"
653 [value]="disk"
654 disabled />
655 <span class="input-group-btn">
656 <button class="btn btn-default"
657 type="button"
658 (click)="removeGroupDisk(group, i, gi)">
659 <i class="fa fa-remove fa-fw"
660 aria-hidden="true"></i>
661 </button>
662 </span>
663 </div>
664 </ng-container>
665
666 <div class="row">
667 <div class="col-md-12">
668 <cd-select [data]="group.getValue('disks')"
669 [options]="groupDiskSelections[gi]"
670 [messages]="messages.initiatorImage"
671 elemClass="btn btn-default pull-right">
672 <i class="fa fa-fw fa-plus"></i>
673 <ng-container i18n>Add image</ng-container>
674 </cd-select>
675 </div>
676 </div>
677
678 <hr />
679 </div>
680 </div>
681 </div>
682 </div>
683
684 <div class="row">
685 <div class="col-md-12">
686 <span class="text-muted"
687 *ngIf="groups.controls.length === 0"
688 i18n>No items added.</span>
689
690 <button (click)="addGroup(); false"
691 class="btn btn-default pull-right">
692 <i class="fa fa-fw fa-plus"></i>
693 <ng-container i18n>Add group</ng-container>
694 </button>
695 </div>
696 </div>
697 </div>
698 </div>
699
700 </div>
701 <div class="panel-footer">
702 <div class="button-group text-right">
703 <cd-submit-button
704 [form]="formDir"
705 (submitAction)="submit()"
706 i18n="form action button|Example: Create Pool@@formActionButton"
707 type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
708 <cd-back-button></cd-back-button>
709 </div>
710 </div>
711 </div>
712 </form>
713</div>