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