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