]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/blob
7a439e23dfe70ab4c1547b1a0c532f1245a1a885
[ceph-ci.git] /
1 <cd-modal [pageURL]="pageURL"
2           [modalRef]="activeModal">
3   <span class="modal-title"
4         i18n>{{ action | titlecase }} {{ resource | upperFirst }}</span>
5   <ng-container class="modal-content">
6     <form #frm="ngForm"
7           [formGroup]="serviceForm"
8           novalidate>
9       <div class="modal-body">
10         <cd-alert-panel *ngIf="serviceForm.controls.service_type.value === 'rgw' && showRealmCreationForm"
11                         type="info"
12                         spacingClass="mb-3"
13                         i18n>
14           <a class="text-decoration-underline"
15              (click)="createMultisiteSetup()">
16              Click here</a> to create a new Realm/Zone Group/Zone
17         </cd-alert-panel>
18
19         <!-- Service type -->
20         <div class="form-group row">
21           <label class="cd-col-form-label required"
22                  for="service_type"
23                  i18n>Type</label>
24           <div class="cd-col-form-input">
25             <select id="service_type"
26                     name="service_type"
27                     class="form-select"
28                     formControlName="service_type"
29                     (change)="onServiceTypeChange($event.target.value)">
30               <option i18n
31                       [ngValue]="null">-- Select a service type --</option>
32               <option *ngFor="let serviceType of serviceTypes"
33                       [value]="serviceType">
34                 {{ serviceType }}
35               </option>
36             </select>
37             <span class="invalid-feedback"
38                   *ngIf="serviceForm.showError('service_type', frm, 'required')"
39                   i18n>This field is required.</span>
40           </div>
41         </div>
42
43         <!-- backend_service -->
44         <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
45              class="form-group row">
46           <label i18n
47                  class="cd-col-form-label"
48                  [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
49                  for="backend_service">Backend Service</label>
50           <div class="cd-col-form-input">
51             <select id="backend_service"
52                     name="backend_service"
53                     class="form-select"
54                     formControlName="backend_service"
55                     (change)="prePopulateId()">
56               <option *ngIf="services === null"
57                       [ngValue]="null"
58                       i18n>Loading...</option>
59               <option *ngIf="services !== null && services.length === 0"
60                       [ngValue]="null"
61                       i18n>-- No service available --</option>
62               <option *ngIf="services !== null && services.length > 0"
63                       [ngValue]="null"
64                       i18n>-- Select an existing service --</option>
65               <option *ngFor="let service of services"
66                       [value]="service.service_name">{{ service.service_name }}</option>
67             </select>
68             <span class="invalid-feedback"
69                   *ngIf="serviceForm.showError('backend_service', frm, 'required')"
70                   i18n>This field is required.</span>
71           </div>
72         </div>
73
74         <!-- NVMe/TCP -->
75         <!-- Block Pool -->
76         <div class="form-group row"
77              *ngIf="serviceForm.controls.service_type.value === 'nvmeof'">
78           <label i18n
79                  class="cd-col-form-label required"
80                  for="pool">Block Pool</label>
81           <div class="cd-col-form-input">
82             <select id="pool"
83                     name="pool"
84                     class="form-select"
85                     formControlName="pool"
86                     (change)="onBlockPoolChange()">
87               <option *ngIf="rbdPools === null"
88                       [ngValue]="null"
89                       i18n>Loading...</option>
90               <option *ngIf="rbdPools && rbdPools.length === 0"
91                       [ngValue]="null"
92                       i18n>-- No block pools available --</option>
93               <option *ngIf="rbdPools && rbdPools.length > 0"
94                       [ngValue]="null"
95                       i18n>-- Select a pool --</option>
96               <option *ngFor="let pool of rbdPools"
97                       [value]="pool.pool_name">{{ pool.pool_name }}</option>
98             </select>
99             <cd-help-text i18n>
100               A pool in which the gateway configuration can be managed.
101             </cd-help-text>
102             <span class="invalid-feedback"
103                   *ngIf="serviceForm.showError('pool', frm, 'required')"
104                   i18n>This field is required.</span>
105           </div>
106         </div>
107
108         <!-- Service id -->
109         <div class="form-group row"
110              *ngIf="serviceForm.controls.service_type.value !== 'snmp-gateway'">
111           <label class="cd-col-form-label"
112                  [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)}"
113                  for="service_id">
114             <span i18n>Service Name</span>
115           </label>
116           <div class="cd-col-form-input">
117             <div class="input-group">
118               <span class="input-group-text"
119                     *ngIf="serviceForm.controls.service_type.value && ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceForm.controls.service_type.value)"
120                     for="userId"
121                     i18n>{{serviceForm.controls.service_type.value}}.
122               </span>
123               <input id="service_id"
124                      class="form-control"
125                      type="text"
126                      formControlName="service_id">
127             </div>
128             <span class="invalid-feedback"
129                   *ngIf="serviceForm.showError('service_id', frm, 'required')"
130                   i18n>This field is required.</span>
131             <span class="invalid-feedback"
132                   *ngIf="serviceForm.showError('service_id', frm, 'uniqueName')"
133                   i18n>This service id is already in use.</span>
134             <span class="invalid-feedback"
135                   *ngIf="serviceForm.showError('service_id', frm, 'mdsPattern')"
136                   i18n>MDS service id must start with a letter and contain alphanumeric characters or '.', '-', and '_'</span>
137           </div>
138         </div>
139
140         <div class="form-group row"
141              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
142           <label class="cd-col-form-label"
143                  for="realm_name"
144                  i18n>Realm</label>
145           <div class="cd-col-form-input">
146             <select class="form-select"
147                     id="realm_name"
148                     formControlName="realm_name"
149                     name="realm_name"
150                     [attr.disabled]="realmList.length === 0  || editing ? true : null">
151             <option *ngIf="realmList.length === 0"
152                     i18n
153                     selected>-- No realm available --</option>
154             <option *ngFor="let realm of realmList"
155                     [value]="realm.name">
156                   {{ realm.name }}
157             </option>
158             </select>
159           </div>
160         </div>
161
162         <div class="form-group row"
163              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
164           <label class="cd-col-form-label"
165                  for="zonegroup_name"
166                  i18n>Zone Group</label>
167           <div class="cd-col-form-input">
168             <select class="form-select"
169                     id="zonegroup_name"
170                     formControlName="zonegroup_name"
171                     name="zonegroup_name"
172                     [attr.disabled]="zonegroupList.length === 0  || editing ? true : null">
173               <option *ngFor="let zonegroup of zonegroupList"
174                       [value]="zonegroup.name">
175               {{ zonegroup.name }}
176               </option>
177             </select>
178           </div>
179         </div>
180
181         <div class="form-group row"
182              *ngIf="serviceForm.controls.service_type.value === 'rgw'">
183           <label class="cd-col-form-label"
184                  for="zone_name"
185                  i18n>Zone</label>
186           <div class="cd-col-form-input">
187             <select class="form-select"
188                     id="zone_name"
189                     formControlName="zone_name"
190                     name="zone_name"
191                     [attr.disabled]="zoneList.length === 0  || editing ? true : null">
192               <option *ngFor="let zone of zoneList"
193                       [value]="zone.name">
194               {{ zone.name }}
195               </option>
196             </select>
197           </div>
198         </div>
199
200         <!-- unmanaged -->
201         <div class="form-group row">
202           <div class="cd-col-form-offset">
203             <div class="custom-control custom-checkbox">
204               <input class="custom-control-input"
205                      id="unmanaged"
206                      type="checkbox"
207                      formControlName="unmanaged">
208               <label class="custom-control-label m-0"
209                      for="unmanaged"
210                      i18n>Unmanaged</label>
211               <cd-help-text i18n>If Unmanaged is selected, the orchestrator will not stop or stop any daemons associated with this service. Placement and all other properties will be ignored.</cd-help-text>
212             </div>
213           </div>
214         </div>
215
216         <!-- Placement -->
217         <div *ngIf="!serviceForm.controls.unmanaged.value"
218              class="form-group row">
219           <label class="cd-col-form-label"
220                  for="placement"
221                  i18n>Placement</label>
222           <div class="cd-col-form-input">
223             <select id="placement"
224                     class="form-select"
225                     formControlName="placement"
226                     (change)="onServiceTypeChange($event.target.value)">
227               <option i18n
228                       value="hosts">Hosts</option>
229               <option i18n
230                       value="label">Label</option>
231             </select>
232           </div>
233         </div>
234
235         <!-- Label -->
236         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'label'"
237              class="form-group row">
238           <label i18n
239                  class="cd-col-form-label"
240                  for="label">Label</label>
241           <div class="cd-col-form-input">
242             <input id="label"
243                    class="form-control"
244                    type="text"
245                    formControlName="label"
246                    [ngbTypeahead]="searchLabels"
247                    (focus)="labelFocus.next($any($event).target.value)"
248                    (click)="labelClick.next($any($event).target.value)">
249             <span class="invalid-feedback"
250                   *ngIf="serviceForm.showError('label', frm, 'required')"
251                   i18n>This field is required.</span>
252           </div>
253         </div>
254
255         <!-- Hosts -->
256         <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'hosts'"
257              class="form-group row">
258           <label class="cd-col-form-label"
259                  for="hosts"
260                  i18n>Hosts</label>
261           <div class="cd-col-form-input">
262             <cd-select-badges id="hosts"
263                               [data]="serviceForm.controls.hosts.value"
264                               [options]="hosts.options"
265                               [messages]="hosts.messages">
266             </cd-select-badges>
267           </div>
268         </div>
269
270         <!-- Count -->
271         <div *ngIf="!serviceForm.controls.unmanaged.value"
272              class="form-group row">
273           <label class="cd-col-form-label"
274                  for="count">
275             <span i18n>Count</span>
276           </label>
277           <div class="cd-col-form-input">
278             <input id="count"
279                    class="form-control"
280                    type="number"
281                    formControlName="count"
282                    min="1">
283             <cd-help-text i18n>Number of deamons that will be deployed</cd-help-text>
284             <span class="invalid-feedback"
285                   *ngIf="serviceForm.showError('count', frm, 'min')"
286                   i18n>The value must be at least 1.</span>
287             <span class="invalid-feedback"
288                   *ngIf="serviceForm.showError('count', frm, 'pattern')"
289                   i18n>The entered value needs to be a number.</span>
290           </div>
291         </div>
292
293         <!-- RGW -->
294         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'rgw'">
295           <!-- rgw_frontend_port -->
296           <div class="form-group row">
297             <label i18n
298                    class="cd-col-form-label"
299                    for="rgw_frontend_port">Port</label>
300             <div class="cd-col-form-input">
301               <input id="rgw_frontend_port"
302                      class="form-control"
303                      type="number"
304                      formControlName="rgw_frontend_port"
305                      min="1"
306                      max="65535">
307               <span class="invalid-feedback"
308                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'pattern')"
309                     i18n>The entered value needs to be a number.</span>
310               <span class="invalid-feedback"
311                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'min')"
312                     i18n>The value must be at least 1.</span>
313               <span class="invalid-feedback"
314                     *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'max')"
315                     i18n>The value cannot exceed 65535.</span>
316             </div>
317           </div>
318         </ng-container>
319
320         <!-- iSCSI -->
321         <!-- pool -->
322         <div class="form-group row"
323              *ngIf="serviceForm.controls.service_type.value === 'iscsi'">
324           <label i18n
325                  class="cd-col-form-label required"
326                  for="pool">Pool</label>
327           <div class="cd-col-form-input">
328             <select id="pool"
329                     name="pool"
330                     class="form-select"
331                     formControlName="pool">
332               <option *ngIf="pools === null"
333                       [ngValue]="null"
334                       i18n>Loading...</option>
335               <option *ngIf="pools && pools.length === 0"
336                       [ngValue]="null"
337                       i18n>-- No pools available --</option>
338               <option *ngIf="pools && pools.length > 0"
339                       [ngValue]="null"
340                       i18n>-- Select a pool --</option>
341               <option *ngFor="let pool of pools"
342                       [value]="pool.pool_name">{{ pool.pool_name }}</option>
343             </select>
344             <span class="invalid-feedback"
345                   *ngIf="serviceForm.showError('pool', frm, 'required')"
346                   i18n>This field is required.</span>
347           </div>
348         </div>
349
350         <!-- fields in iSCSI which are hidden when unmanaged is true -->
351         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'iscsi'">
352           <!-- trusted_ip_list -->
353           <div class="form-group row">
354             <label class="cd-col-form-label"
355                    for="trusted_ip_list">
356               <span i18n>Trusted IPs</span>
357               <cd-helper>
358                 <span i18n>Comma separated list of IP addresses.</span>
359                 <br>
360                 <span i18n>Please add the <b>Ceph Manager</b> IP addresses here, otherwise the iSCSI gateways can't be reached.</span>
361               </cd-helper>
362             </label>
363             <div class="cd-col-form-input">
364               <input id="trusted_ip_list"
365                      class="form-control"
366                      type="text"
367                      formControlName="trusted_ip_list">
368             </div>
369           </div>
370
371           <!-- api_port -->
372           <div class="form-group row">
373             <label i18n
374                    class="cd-col-form-label"
375                    for="api_port">Port</label>
376             <div class="cd-col-form-input">
377               <input id="api_port"
378                      class="form-control"
379                      type="number"
380                      formControlName="api_port"
381                      min="1"
382                      max="65535">
383               <span class="invalid-feedback"
384                     *ngIf="serviceForm.showError('api_port', frm, 'pattern')"
385                     i18n>The entered value needs to be a number.</span>
386               <span class="invalid-feedback"
387                     *ngIf="serviceForm.showError('api_port', frm, 'min')"
388                     i18n>The value must be at least 1.</span>
389               <span class="invalid-feedback"
390                     *ngIf="serviceForm.showError('api_port', frm, 'max')"
391                     i18n>The value cannot exceed 65535.</span>
392             </div>
393           </div>
394
395           <!-- api_user -->
396           <div class="form-group row">
397             <label i18n
398                    class="cd-col-form-label"
399                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
400                    for="api_user">User</label>
401             <div class="cd-col-form-input">
402               <input id="api_user"
403                      class="form-control"
404                      type="text"
405                      formControlName="api_user">
406               <span class="invalid-feedback"
407                     *ngIf="serviceForm.showError('api_user', frm, 'required')"
408                     i18n>This field is required.</span>
409             </div>
410           </div>
411
412           <!-- api_password -->
413           <div class="form-group row">
414             <label i18n
415                    class="cd-col-form-label"
416                    [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
417                    for="api_password">Password</label>
418             <div class="cd-col-form-input">
419               <div class="input-group">
420                 <input id="api_password"
421                        class="form-control"
422                        type="password"
423                        autocomplete="new-password"
424                        formControlName="api_password">
425                 <button type="button"
426                         class="btn btn-light"
427                         cdPasswordButton="api_password">
428                 </button>
429                 <cd-copy-2-clipboard-button source="api_password">
430                 </cd-copy-2-clipboard-button>
431                 <span class="invalid-feedback"
432                       *ngIf="serviceForm.showError('api_password', frm, 'required')"
433                       i18n>This field is required.</span>
434               </div>
435             </div>
436           </div>
437         </ng-container>
438
439         <!-- smb -->
440         <ng-container *ngIf="serviceForm.controls.service_type.value === 'smb'">
441           <div class="form-group row">
442             <label class="cd-col-form-label required"
443                    for="cluster_id"
444                    i18n>
445               Cluster id
446               <cd-helper>
447                 <span>A short name identifying the SMB “cluster”. In this case a cluster is simply a management unit of one or more Samba services sharing a common configuration,
448                    and may not provide actual clustering or availability mechanisms.</span>
449               </cd-helper>
450             </label>
451             <div class="cd-col-form-input">
452               <input id="cluster_id"
453                      class="form-control"
454                      type="text"
455                      formControlName="cluster_id"
456                      placeholder="foo"
457                      i18n-placeholder>
458               <span class="invalid-feedback"
459                     *ngIf="serviceForm.showError('cluster_id', frm, 'required')"
460                     i18n>This field is required.</span>
461             </div>
462           </div>
463
464           <div class="form-group row">
465             <label class="cd-col-form-label required"
466                    for="config_uri">
467               <span i18n>Config URI</span>
468               <cd-helper i18n>
469                 Configuration source that should be loaded by the samba-container as the primary configuration file.
470               </cd-helper>
471             </label>
472             <div class="cd-col-form-input">
473               <input id="config_uri"
474                      class="form-control"
475                      type="text"
476                      formControlName="config_uri"
477                      placeholder="rados://.smb/foo/scc.toml"
478                      i18n-placeholder>
479               <span class="invalid-feedback"
480                     *ngIf="serviceForm.showError('config_uri', frm, 'required')"
481                     i18n>This field is required.</span>
482               <span class="invalid-feedback"
483                     *ngIf="serviceForm.showError('config_uri', frm, 'configUriPattern')"
484                     i18n>The value must start with either 'http:', 'https:', 'rados:' or 'rados:mon-config-key:'</span>
485             </div>
486           </div>
487
488           <div class="form-group row"
489                formGroupName="features">
490             <label class="cd-col-form-label"
491                    for="features"
492                    i18n>Features
493               <cd-helper>
494                 <span>Pre-defined terms enabling specific deployment characteristics.</span>
495               </cd-helper>
496             </label>
497             <div class="cd-col-form-input">
498               <div class="custom-control custom-checkbox"
499                    *ngFor="let feature of smbFeaturesList">
500                 <input class="custom-control-input"
501                        type="checkbox"
502                        name="{{feature}}"
503                        id="{{feature}}"
504                        formControlName="{{feature}}">
505                 <label class="custom-control-label"
506                        for="{{feature}}"
507                        i18n>{{feature}}
508                 </label>
509               </div>
510             </div>
511           </div>
512
513           <div class="form-group row">
514             <label class="cd-col-form-label"
515                    for="custom_dns">
516               <span i18n>Custom DNS</span>
517               <cd-helper i18n>
518                 <span>Comma separated list of DNSs.</span>
519                 <br>
520                 <span>A list of IP addresses that will be used as the DNS servers for a Samba container.</span>
521               </cd-helper>
522             </label>
523             <div class="cd-col-form-input">
524               <input id="custom_dns"
525                      class="form-control"
526                      type="text"
527                      formControlName="custom_dns"
528                      placeholder="192.168.76.204"
529                      i18n-placeholder>
530             </div>
531           </div>
532
533           <div class="form-group row">
534             <label class="cd-col-form-label"
535                    for="join_sources">
536               <span i18n>Join sources</span>
537               <cd-helper i18n>
538                 <span>Comma separated list of URIs.</span>
539                 <br>
540                 <span>A list of values that will be used to identify where authentication data that will be used to perform domain joins are located.</span>
541               </cd-helper>
542             </label>
543             <div class="cd-col-form-input">
544               <input id="join_sources"
545                      class="form-control"
546                      type="text"
547                      formControlName="join_sources"
548                      placeholder="rados:mon-config-key:smb/config/foo/join1.json"
549                      i18n-placeholder>
550             </div>
551           </div>
552
553           <div class="form-group row">
554             <label class="cd-col-form-label"
555                    for="user_sources">
556               <span i18n>User sources</span>
557               <cd-helper i18n>
558                 <span>Comma separated list of URIs.</span>
559                 <br>
560                 <span>A list of pseudo-uris containing data the samba-container can use to create users (and/or
561                   groups). A ceph based samba container may typically use a rados uri
562                   or a mon config-key store uri </span>
563               </cd-helper>
564             </label>
565             <div class="cd-col-form-input">
566               <input id="user_sources"
567                      class="form-control"
568                      type="text"
569                      formControlName="user_sources"
570                      placeholder="rados:mon-config-key:smb/config/foo/join2.json"
571                      i18n-placeholder>
572             </div>
573           </div>
574
575           <div class="form-group row">
576             <label class="cd-col-form-label"
577                    for="include_ceph_users">
578               <span i18n>Ceph users</span>
579               <cd-helper i18n>
580                 <span>Comma separated list of Ceph users.</span>
581                 <br>
582                 <span>A list of cephx user names that the Samba Containers may use.</span>
583               </cd-helper>
584             </label>
585             <div class="cd-col-form-input">
586               <input id="include_ceph_users"
587                      class="form-control"
588                      type="text"
589                      formControlName="include_ceph_users"
590                      placeholder="client.smb.fs.cluster.foo"
591                      i18n-placeholder>
592             </div>
593           </div>
594
595         </ng-container>
596
597         <!-- Ingress -->
598         <ng-container *ngIf="serviceForm.controls.service_type.value === 'ingress'">
599           <!-- virtual_ip -->
600           <div class="form-group row">
601             <label class="cd-col-form-label"
602                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
603                    for="virtual_ip">
604               <span i18n>Virtual IP</span>
605               <cd-helper>
606                 <span i18n>The virtual IP address and subnet (in CIDR notation) where the ingress service will be available.</span>
607               </cd-helper>
608             </label>
609             <div class="cd-col-form-input">
610               <input id="virtual_ip"
611                      class="form-control"
612                      type="text"
613                      formControlName="virtual_ip">
614               <span class="invalid-feedback"
615                     *ngIf="serviceForm.showError('virtual_ip', frm, 'required')"
616                     i18n>This field is required.</span>
617             </div>
618           </div>
619
620           <!-- frontend_port -->
621           <div class="form-group row">
622             <label class="cd-col-form-label"
623                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
624                    for="frontend_port">
625               <span i18n>Frontend Port</span>
626               <cd-helper>
627                 <span i18n>The port used to access the ingress service.</span>
628               </cd-helper>
629             </label>
630             <div class="cd-col-form-input">
631               <input id="frontend_port"
632                      class="form-control"
633                      type="number"
634                      formControlName="frontend_port"
635                      min="1"
636                      max="65535">
637               <span class="invalid-feedback"
638                     *ngIf="serviceForm.showError('frontend_port', frm, 'pattern')"
639                     i18n>The entered value needs to be a number.</span>
640               <span class="invalid-feedback"
641                     *ngIf="serviceForm.showError('frontend_port', frm, 'min')"
642                     i18n>The value must be at least 1.</span>
643               <span class="invalid-feedback"
644                     *ngIf="serviceForm.showError('frontend_port', frm, 'max')"
645                     i18n>The value cannot exceed 65535.</span>
646               <span class="invalid-feedback"
647                     *ngIf="serviceForm.showError('frontend_port', frm, 'required')"
648                     i18n>This field is required.</span>
649             </div>
650           </div>
651
652           <!-- monitor_port -->
653           <div class="form-group row">
654             <label class="cd-col-form-label"
655                    [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
656                    for="monitor_port">
657               <span i18n>Monitor Port</span>
658               <cd-helper>
659                 <span i18n>The port used by haproxy for load balancer status.</span>
660               </cd-helper>
661             </label>
662             <div class="cd-col-form-input">
663               <input id="monitor_port"
664                      class="form-control"
665                      type="number"
666                      formControlName="monitor_port"
667                      min="1"
668                      max="65535">
669               <span class="invalid-feedback"
670                     *ngIf="serviceForm.showError('monitor_port', frm, 'pattern')"
671                     i18n>The entered value needs to be a number.</span>
672               <span class="invalid-feedback"
673                     *ngIf="serviceForm.showError('monitor_port', frm, 'min')"
674                     i18n>The value must be at least 1.</span>
675               <span class="invalid-feedback"
676                     *ngIf="serviceForm.showError('monitor_port', frm, 'max')"
677                     i18n>The value cannot exceed 65535.</span>
678               <span class="invalid-feedback"
679                     *ngIf="serviceForm.showError('monitor_port', frm, 'required')"
680                     i18n>This field is required.</span>
681             </div>
682           </div>
683           <!-- virtual_interface_networks -->
684           <div class="form-group row"
685                *ngIf="!serviceForm.controls.unmanaged.value">
686             <label class="cd-col-form-label"
687                    for="virtual_interface_networks">
688               <span i18n>CIDR Networks</span>
689               <cd-helper>
690                 <span i18n>A list of networks to identify which network interface to use for the virtual IP address.</span>
691               </cd-helper>
692             </label>
693             <div class="cd-col-form-input">
694               <input id="virtual_interface_networks"
695                      class="form-control"
696                      type="text"
697                      formControlName="virtual_interface_networks">
698             </div>
699           </div>
700         </ng-container>
701
702         <!-- SNMP-Gateway -->
703         <ng-container *ngIf="serviceForm.controls.service_type.value === 'snmp-gateway'">
704           <!-- snmp-version -->
705           <div class="form-group row">
706             <label class="cd-col-form-label required"
707                    for="snmp_version"
708                    i18n>Version</label>
709             <div class="cd-col-form-input">
710               <select id="snmp_version"
711                       name="snmp_version"
712                       class="form-select"
713                       formControlName="snmp_version"
714                       (change)="clearValidations()">
715                 <option i18n
716                         [ngValue]="null">-- Select SNMP version --</option>
717                 <option *ngFor="let snmpVersion of ['V2c', 'V3']"
718                         [value]="snmpVersion">{{ snmpVersion }}</option>
719               </select>
720               <span class="invalid-feedback"
721                     *ngIf="serviceForm.showError('snmp_version', frm, 'required')"
722                     i18n>This field is required.</span>
723             </div>
724           </div>
725           <!-- Destination -->
726           <div class="form-group row">
727             <label class="cd-col-form-label required"
728                    for="snmp_destination">
729               <span i18n>Destination</span>
730               <cd-helper>
731                 <span i18n>Must be of the format hostname:port.</span>
732               </cd-helper>
733             </label>
734             <div class="cd-col-form-input">
735               <input id="snmp_destination"
736                      class="form-control"
737                      type="text"
738                      formControlName="snmp_destination">
739               <span class="invalid-feedback"
740                     *ngIf="serviceForm.showError('snmp_destination', frm, 'required')"
741                     i18n>This field is required.</span>
742               <span class="invalid-feedback"
743                     *ngIf="serviceForm.showError('snmp_destination', frm, 'snmpDestinationPattern')"
744                     i18n>The value does not match the pattern: <strong>hostname:port</strong></span>
745             </div>
746           </div>
747           <!-- Engine id for snmp V3 -->
748           <div class="form-group row"
749                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
750             <label class="cd-col-form-label required"
751                    for="engine_id">
752               <span i18n>Engine Id</span>
753               <cd-helper>
754                 <span i18n>Unique identifier for the device (in hex).</span>
755               </cd-helper>
756             </label>
757             <div class="cd-col-form-input">
758               <input id="engine_id"
759                      class="form-control"
760                      type="text"
761                      formControlName="engine_id">
762               <span class="invalid-feedback"
763                     *ngIf="serviceForm.showError('engine_id', frm, 'required')"
764                     i18n>This field is required.</span>
765               <span class="invalid-feedback"
766                     *ngIf="serviceForm.showError('engine_id', frm, 'snmpEngineIdPattern')"
767                     i18n>The value does not match the pattern: <strong>Must be in hexadecimal and length must be multiple of 2 with min value = 10 amd max value = 64.</strong></span>
768             </div>
769           </div>
770           <!-- Auth protocol for snmp V3 -->
771           <div class="form-group row"
772                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
773             <label class="cd-col-form-label required"
774                    for="auth_protocol"
775                    i18n>Auth Protocol</label>
776             <div class="cd-col-form-input">
777               <select id="auth_protocol"
778                       name="auth_protocol"
779                       class="form-select"
780                       formControlName="auth_protocol">
781                 <option i18n
782                         [ngValue]="null">-- Select auth protocol --</option>
783                 <option *ngFor="let authProtocol of ['SHA', 'MD5']"
784                         [value]="authProtocol">
785                   {{ authProtocol }}
786                 </option>
787               </select>
788               <span class="invalid-feedback"
789                     *ngIf="serviceForm.showError('auth_protocol', frm, 'required')"
790                     i18n>This field is required.</span>
791             </div>
792           </div>
793           <!-- Privacy protocol for snmp V3 -->
794           <div class="form-group row"
795                *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
796             <label class="cd-col-form-label"
797                    for="privacy_protocol"
798                    i18n>Privacy Protocol</label>
799             <div class="cd-col-form-input">
800               <select id="privacy_protocol"
801                       name="privacy_protocol"
802                       class="form-select"
803                       formControlName="privacy_protocol">
804                 <option i18n
805                         [ngValue]="null">-- Select privacy protocol --</option>
806                 <option *ngFor="let privacyProtocol of ['DES', 'AES']"
807                         [value]="privacyProtocol">
808                   {{ privacyProtocol }}
809                 </option>
810               </select>
811             </div>
812           </div>
813           <!-- Credentials -->
814           <fieldset>
815             <legend i18n>Credentials</legend>
816             <!-- snmp v2c snmp_community -->
817             <div class="form-group row"
818                  *ngIf="serviceForm.controls.snmp_version.value === 'V2c'">
819               <label class="cd-col-form-label required"
820                      for="snmp_community">
821                 <span i18n>SNMP Community</span>
822               </label>
823               <div class="cd-col-form-input">
824                 <input id="snmp_community"
825                        class="form-control"
826                        type="text"
827                        formControlName="snmp_community">
828                 <span class="invalid-feedback"
829                       *ngIf="serviceForm.showError('snmp_community', frm, 'required')"
830                       i18n>This field is required.</span>
831               </div>
832             </div>
833             <!-- snmp v3 auth username -->
834             <div class="form-group row"
835                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
836               <label class="cd-col-form-label required"
837                      for="snmp_v3_auth_username">
838                 <span i18n>Username</span>
839               </label>
840               <div class="cd-col-form-input">
841                 <input id="snmp_v3_auth_username"
842                        class="form-control"
843                        type="text"
844                        formControlName="snmp_v3_auth_username">
845                 <span class="invalid-feedback"
846                       *ngIf="serviceForm.showError('snmp_v3_auth_username', frm, 'required')"
847                       i18n>This field is required.</span>
848               </div>
849             </div>
850             <!-- snmp v3 auth password -->
851             <div class="form-group row"
852                  *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
853               <label class="cd-col-form-label required"
854                      for="snmp_v3_auth_password">
855                 <span i18n>Password</span>
856               </label>
857               <div class="cd-col-form-input">
858                 <input id="snmp_v3_auth_password"
859                        class="form-control"
860                        type="password"
861                        formControlName="snmp_v3_auth_password">
862                 <span class="invalid-feedback"
863                       *ngIf="serviceForm.showError('snmp_v3_auth_password', frm, 'required')"
864                       i18n>This field is required.</span>
865               </div>
866             </div>
867             <!-- snmp v3 priv password -->
868             <div class="form-group row"
869                  *ngIf="serviceForm.controls.snmp_version.value === 'V3' && serviceForm.controls.privacy_protocol.value !== null && serviceForm.controls.privacy_protocol.value !== undefined">
870               <label class="cd-col-form-label required"
871                      for="snmp_v3_priv_password">
872                 <span i18n>Encryption</span>
873               </label>
874               <div class="cd-col-form-input">
875                 <input id="snmp_v3_priv_password"
876                        class="form-control"
877                        type="password"
878                        formControlName="snmp_v3_priv_password">
879                 <span class="invalid-feedback"
880                       *ngIf="serviceForm.showError('snmp_v3_priv_password', frm, 'required')"
881                       i18n>This field is required.</span>
882               </div>
883             </div>
884           </fieldset>
885         </ng-container>
886         <!-- RGW, Ingress & iSCSI -->
887         <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)">
888           <!-- ssl -->
889           <div class="form-group row">
890             <div class="cd-col-form-offset">
891               <div class="custom-control custom-checkbox">
892                 <input class="custom-control-input"
893                        id="ssl"
894                        type="checkbox"
895                        formControlName="ssl">
896                 <label class="custom-control-label"
897                        for="ssl"
898                        i18n>SSL</label>
899               </div>
900             </div>
901           </div>
902
903           <!-- ssl_cert -->
904           <div *ngIf="serviceForm.controls.ssl.value"
905                class="form-group row">
906             <label class="cd-col-form-label"
907                    for="ssl_cert">
908               <span i18n>Certificate</span>
909               <cd-helper i18n>The SSL certificate in PEM format.</cd-helper>
910             </label>
911             <div class="cd-col-form-input">
912               <textarea id="ssl_cert"
913                         class="form-control resize-vertical text-monospace text-pre"
914                         formControlName="ssl_cert"
915                         rows="5">
916               </textarea>
917               <input type="file"
918                      (change)="fileUpload($event.target.files, 'ssl_cert')">
919               <span class="invalid-feedback"
920                     *ngIf="serviceForm.showError('ssl_cert', frm, 'required')"
921                     i18n>This field is required.</span>
922               <span class="invalid-feedback"
923                     *ngIf="serviceForm.showError('ssl_cert', frm, 'pattern')"
924                     i18n>Invalid SSL certificate.</span>
925             </div>
926           </div>
927
928           <!-- ssl_key -->
929           <div *ngIf="serviceForm.controls.ssl.value && !(['rgw', 'ingress'].includes(serviceForm.controls.service_type.value))"
930                class="form-group row">
931             <label class="cd-col-form-label"
932                    for="ssl_key">
933               <span i18n>Private key</span>
934               <cd-helper i18n>The SSL private key in PEM format.</cd-helper>
935             </label>
936             <div class="cd-col-form-input">
937               <textarea id="ssl_key"
938                         class="form-control resize-vertical text-monospace text-pre"
939                         formControlName="ssl_key"
940                         rows="5">
941               </textarea>
942               <input type="file"
943                      (change)="fileUpload($event.target.files,'ssl_key')">
944               <span class="invalid-feedback"
945                     *ngIf="serviceForm.showError('ssl_key', frm, 'required')"
946                     i18n>This field is required.</span>
947               <span class="invalid-feedback"
948                     *ngIf="serviceForm.showError('ssl_key', frm, 'pattern')"
949                     i18n>Invalid SSL private key.</span>
950             </div>
951           </div>
952         </ng-container>
953         <!-- Grafana -->
954         <ng-container *ngIf="serviceForm.controls.service_type.value === 'grafana'">
955           <div class="form-group row">
956             <label class="cd-col-form-label"
957                    for="grafana_port">
958               <span i18n>Grafana Port</span>
959               <cd-helper>
960                 <span i18n>The default port used by grafana.</span>
961               </cd-helper>
962             </label>
963             <div class="cd-col-form-input">
964               <input id="grafana_port"
965                      class="form-control"
966                      type="number"
967                      formControlName="grafana_port"
968                      min="1"
969                      max="65535">
970               <span class="invalid-feedback"
971                     *ngIf="serviceForm.showError('grafana_port', frm, 'pattern')"
972                     i18n>The entered value needs to be a number.</span>
973               <span class="invalid-feedback"
974                     *ngIf="serviceForm.showError('grafana_port', frm, 'min')"
975                     i18n>The value must be at least 1.</span>
976               <span class="invalid-feedback"
977                     *ngIf="serviceForm.showError('grafana_port', frm, 'max')"
978                     i18n>The value cannot exceed 65535.</span>
979               <span class="invalid-feedback"
980                     *ngIf="serviceForm.showError('grafana_port', frm, 'required')"
981                     i18n>This field is required.</span>
982             </div>
983           </div>
984
985           <div class="form-group row">
986             <label i18n
987                    class="cd-col-form-label"
988                    for="grafana_admin_password">
989               <span>Grafana Password</span>
990               <cd-helper>The password of the default Grafana Admin. Set once on first-run.</cd-helper>
991             </label>
992             <div class="cd-col-form-input">
993               <div class="input-group">
994                 <input id="grafana_admin_password"
995                        class="form-control"
996                        type="password"
997                        autocomplete="new-password"
998                        [attr.disabled]="editing ? true:null"
999                        formControlName="grafana_admin_password">
1000                 <span class="input-group-append">
1001                   <button type="button"
1002                           class="btn btn-light"
1003                           cdPasswordButton="grafana_admin_password">
1004                   </button>
1005                   <cd-copy-2-clipboard-button source="grafana_admin_password">
1006                   </cd-copy-2-clipboard-button>
1007                 </span>
1008               </div>
1009             </div>
1010           </div>
1011         </ng-container>
1012       </div>
1013
1014       <div class="modal-footer">
1015         <div class="text-right">
1016           <cd-form-button-panel (submitActionEvent)="onSubmit()"
1017                                 [form]="serviceForm"
1018                                 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>
1019         </div>
1020       </div>
1021     </form>
1022   </ng-container>
1023 </cd-modal>