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