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