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">
7 [formGroup]="serviceForm"
9 <div class="modal-body">
12 <div class="form-group row">
13 <label class="cd-col-form-label required"
16 <div class="cd-col-form-input">
17 <select id="service_type"
20 formControlName="service_type"
21 (change)="getServiceIds($event.target.value)">
23 [ngValue]="null">-- Select a service type --</option>
24 <option *ngFor="let serviceType of serviceTypes"
25 [value]="serviceType">
29 <span class="invalid-feedback"
30 *ngIf="serviceForm.showError('service_type', frm, 'required')"
31 i18n>This field is required.</span>
35 <!-- backend_service -->
36 <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
37 class="form-group row">
39 class="cd-col-form-label"
40 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
41 for="backend_service">Backend Service</label>
42 <div class="cd-col-form-input">
43 <select id="backend_service"
44 name="backend_service"
46 formControlName="backend_service"
47 (change)="prePopulateId()">
48 <option *ngIf="services === null"
50 i18n>Loading...</option>
51 <option *ngIf="services !== null && services.length === 0"
53 i18n>-- No service available --</option>
54 <option *ngIf="services !== null && services.length > 0"
56 i18n>-- Select an existing service --</option>
57 <option *ngFor="let service of services"
58 [value]="service.service_name">{{ service.service_name }}</option>
60 <span class="invalid-feedback"
61 *ngIf="serviceForm.showError('backend_service', frm, 'required')"
62 i18n>This field is required.</span>
67 <div class="form-group row"
68 *ngIf="serviceForm.controls.service_type.value !== 'snmp-gateway'">
69 <label class="cd-col-form-label"
70 [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)}"
73 <cd-helper i18n>Used in the service name which is <service_type.service_id></cd-helper>
75 <div class="cd-col-form-input">
76 <input id="service_id"
79 formControlName="service_id">
80 <span class="invalid-feedback"
81 *ngIf="serviceForm.showError('service_id', frm, 'required')"
82 i18n>This field is required.</span>
83 <span class="invalid-feedback"
84 *ngIf="serviceForm.showError('service_id', frm, 'uniqueName')"
85 i18n>This service id is already in use.</span>
86 <span class="invalid-feedback"
87 *ngIf="serviceForm.showError('service_id', frm, 'rgwPattern')"
88 i18n>The value does not match the pattern <strong><service_id>[.<realm_name>.<zone_name>]</strong>.</span>
89 <span class="invalid-feedback"
90 *ngIf="serviceForm.showError('service_id', frm, 'mdsPattern')"
91 i18n>MDS service id must start with a letter and contain alphanumeric characters or '.', '-', and '_'</span>
96 <div class="form-group row">
97 <div class="cd-col-form-offset">
98 <div class="custom-control custom-checkbox">
99 <input class="custom-control-input"
102 formControlName="unmanaged">
103 <label class="custom-control-label"
105 i18n>Unmanaged</label>
106 <cd-helper i18n>If set to true, the orchestrator will not start nor stop any daemon associated with this service.
107 Placement and all other properties will be ignored.</cd-helper>
113 <div *ngIf="!serviceForm.controls.unmanaged.value"
114 class="form-group row">
115 <label class="cd-col-form-label"
117 i18n>Placement</label>
118 <div class="cd-col-form-input">
119 <select id="placement"
121 formControlName="placement">
123 value="hosts">Hosts</option>
125 value="label">Label</option>
131 <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'label'"
132 class="form-group row">
134 class="cd-col-form-label"
135 for="label">Label</label>
136 <div class="cd-col-form-input">
140 formControlName="label"
141 [ngbTypeahead]="searchLabels"
142 (focus)="labelFocus.next($any($event).target.value)"
143 (click)="labelClick.next($any($event).target.value)">
144 <span class="invalid-feedback"
145 *ngIf="serviceForm.showError('label', frm, 'required')"
146 i18n>This field is required.</span>
151 <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'hosts'"
152 class="form-group row">
153 <label class="cd-col-form-label"
156 <div class="cd-col-form-input">
157 <cd-select-badges id="hosts"
158 [data]="serviceForm.controls.hosts.value"
159 [options]="hosts.options"
160 [messages]="hosts.messages">
166 <div *ngIf="!serviceForm.controls.unmanaged.value"
167 class="form-group row">
168 <label class="cd-col-form-label"
170 <span i18n>Count</span>
171 <cd-helper i18n>Only that number of daemons will be created.</cd-helper>
173 <div class="cd-col-form-input">
177 formControlName="count"
179 <span class="invalid-feedback"
180 *ngIf="serviceForm.showError('count', frm, 'min')"
181 i18n>The value must be at least 1.</span>
182 <span class="invalid-feedback"
183 *ngIf="serviceForm.showError('count', frm, 'pattern')"
184 i18n>The entered value needs to be a number.</span>
189 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'rgw'">
190 <!-- rgw_frontend_port -->
191 <div class="form-group row">
193 class="cd-col-form-label"
194 for="rgw_frontend_port">Port</label>
195 <div class="cd-col-form-input">
196 <input id="rgw_frontend_port"
199 formControlName="rgw_frontend_port"
202 <span class="invalid-feedback"
203 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'pattern')"
204 i18n>The entered value needs to be a number.</span>
205 <span class="invalid-feedback"
206 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'min')"
207 i18n>The value must be at least 1.</span>
208 <span class="invalid-feedback"
209 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'max')"
210 i18n>The value cannot exceed 65535.</span>
217 <div class="form-group row"
218 *ngIf="serviceForm.controls.service_type.value === 'iscsi'">
220 class="cd-col-form-label required"
221 for="pool">Pool</label>
222 <div class="cd-col-form-input">
226 formControlName="pool">
227 <option *ngIf="pools === null"
229 i18n>Loading...</option>
230 <option *ngIf="pools && pools.length === 0"
232 i18n>-- No pools available --</option>
233 <option *ngIf="pools && pools.length > 0"
235 i18n>-- Select a pool --</option>
236 <option *ngFor="let pool of pools"
237 [value]="pool.pool_name">{{ pool.pool_name }}</option>
239 <span class="invalid-feedback"
240 *ngIf="serviceForm.showError('pool', frm, 'required')"
241 i18n>This field is required.</span>
245 <!-- fields in iSCSI which are hidden when unmanaged is true -->
246 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'iscsi'">
247 <!-- trusted_ip_list -->
248 <div class="form-group row">
249 <label class="cd-col-form-label"
250 for="trusted_ip_list">
251 <span i18n>Trusted IPs</span>
253 <span i18n>Comma separated list of IP addresses.</span>
255 <span i18n>Please add the <b>Ceph Manager</b> IP addresses here, otherwise the iSCSI gateways can't be reached.</span>
258 <div class="cd-col-form-input">
259 <input id="trusted_ip_list"
262 formControlName="trusted_ip_list">
267 <div class="form-group row">
269 class="cd-col-form-label"
270 for="api_port">Port</label>
271 <div class="cd-col-form-input">
275 formControlName="api_port"
278 <span class="invalid-feedback"
279 *ngIf="serviceForm.showError('api_port', frm, 'pattern')"
280 i18n>The entered value needs to be a number.</span>
281 <span class="invalid-feedback"
282 *ngIf="serviceForm.showError('api_port', frm, 'min')"
283 i18n>The value must be at least 1.</span>
284 <span class="invalid-feedback"
285 *ngIf="serviceForm.showError('api_port', frm, 'max')"
286 i18n>The value cannot exceed 65535.</span>
291 <div class="form-group row">
293 class="cd-col-form-label"
294 [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
295 for="api_user">User</label>
296 <div class="cd-col-form-input">
300 formControlName="api_user">
301 <span class="invalid-feedback"
302 *ngIf="serviceForm.showError('api_user', frm, 'required')"
303 i18n>This field is required.</span>
307 <!-- api_password -->
308 <div class="form-group row">
310 class="cd-col-form-label"
311 [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
312 for="api_password">Password</label>
313 <div class="cd-col-form-input">
314 <div class="input-group">
315 <input id="api_password"
318 autocomplete="new-password"
319 formControlName="api_password">
320 <button type="button"
321 class="btn btn-light"
322 cdPasswordButton="api_password">
324 <cd-copy-2-clipboard-button source="api_password">
325 </cd-copy-2-clipboard-button>
326 <span class="invalid-feedback"
327 *ngIf="serviceForm.showError('api_password', frm, 'required')"
328 i18n>This field is required.</span>
335 <ng-container *ngIf="serviceForm.controls.service_type.value === 'ingress'">
337 <div class="form-group row">
338 <label class="cd-col-form-label"
339 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
341 <span i18n>Virtual IP</span>
343 <span i18n>The virtual IP address and subnet (in CIDR notation) where the ingress service will be available.</span>
346 <div class="cd-col-form-input">
347 <input id="virtual_ip"
350 formControlName="virtual_ip">
351 <span class="invalid-feedback"
352 *ngIf="serviceForm.showError('virtual_ip', frm, 'required')"
353 i18n>This field is required.</span>
357 <!-- frontend_port -->
358 <div class="form-group row">
359 <label class="cd-col-form-label"
360 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
362 <span i18n>Frontend Port</span>
364 <span i18n>The port used to access the ingress service.</span>
367 <div class="cd-col-form-input">
368 <input id="frontend_port"
371 formControlName="frontend_port"
374 <span class="invalid-feedback"
375 *ngIf="serviceForm.showError('frontend_port', frm, 'pattern')"
376 i18n>The entered value needs to be a number.</span>
377 <span class="invalid-feedback"
378 *ngIf="serviceForm.showError('frontend_port', frm, 'min')"
379 i18n>The value must be at least 1.</span>
380 <span class="invalid-feedback"
381 *ngIf="serviceForm.showError('frontend_port', frm, 'max')"
382 i18n>The value cannot exceed 65535.</span>
383 <span class="invalid-feedback"
384 *ngIf="serviceForm.showError('frontend_port', frm, 'required')"
385 i18n>This field is required.</span>
389 <!-- monitor_port -->
390 <div class="form-group row">
391 <label class="cd-col-form-label"
392 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
394 <span i18n>Monitor Port</span>
396 <span i18n>The port used by haproxy for load balancer status.</span>
399 <div class="cd-col-form-input">
400 <input id="monitor_port"
403 formControlName="monitor_port"
406 <span class="invalid-feedback"
407 *ngIf="serviceForm.showError('monitor_port', frm, 'pattern')"
408 i18n>The entered value needs to be a number.</span>
409 <span class="invalid-feedback"
410 *ngIf="serviceForm.showError('monitor_port', frm, 'min')"
411 i18n>The value must be at least 1.</span>
412 <span class="invalid-feedback"
413 *ngIf="serviceForm.showError('monitor_port', frm, 'max')"
414 i18n>The value cannot exceed 65535.</span>
415 <span class="invalid-feedback"
416 *ngIf="serviceForm.showError('monitor_port', frm, 'required')"
417 i18n>This field is required.</span>
420 <!-- virtual_interface_networks -->
421 <div class="form-group row"
422 *ngIf="!serviceForm.controls.unmanaged.value">
423 <label class="cd-col-form-label"
424 for="virtual_interface_networks">
425 <span i18n>CIDR Networks</span>
427 <span i18n>A list of networks to identify which network interface to use for the virtual IP address.</span>
430 <div class="cd-col-form-input">
431 <input id="virtual_interface_networks"
434 formControlName="virtual_interface_networks">
439 <!-- SNMP-Gateway -->
440 <ng-container *ngIf="serviceForm.controls.service_type.value === 'snmp-gateway'">
441 <!-- snmp-version -->
442 <div class="form-group row">
443 <label class="cd-col-form-label required"
446 <div class="cd-col-form-input">
447 <select id="snmp_version"
450 formControlName="snmp_version"
451 (change)="clearValidations()">
453 [ngValue]="null">-- Select SNMP version --</option>
454 <option *ngFor="let snmpVersion of ['V2c', 'V3']"
455 [value]="snmpVersion">{{ snmpVersion }}</option>
457 <span class="invalid-feedback"
458 *ngIf="serviceForm.showError('snmp_version', frm, 'required')"
459 i18n>This field is required.</span>
463 <div class="form-group row">
464 <label class="cd-col-form-label required"
465 for="snmp_destination">
466 <span i18n>Destination</span>
468 <span i18n>Must be of the format hostname:port.</span>
471 <div class="cd-col-form-input">
472 <input id="snmp_destination"
475 formControlName="snmp_destination">
476 <span class="invalid-feedback"
477 *ngIf="serviceForm.showError('snmp_destination', frm, 'required')"
478 i18n>This field is required.</span>
479 <span class="invalid-feedback"
480 *ngIf="serviceForm.showError('snmp_destination', frm, 'snmpDestinationPattern')"
481 i18n>The value does not match the pattern: <strong>hostname:port</strong></span>
484 <!-- Engine id for snmp V3 -->
485 <div class="form-group row"
486 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
487 <label class="cd-col-form-label required"
489 <span i18n>Engine Id</span>
491 <span i18n>Unique identifier for the device (in hex).</span>
494 <div class="cd-col-form-input">
495 <input id="engine_id"
498 formControlName="engine_id">
499 <span class="invalid-feedback"
500 *ngIf="serviceForm.showError('engine_id', frm, 'required')"
501 i18n>This field is required.</span>
502 <span class="invalid-feedback"
503 *ngIf="serviceForm.showError('engine_id', frm, 'snmpEngineIdPattern')"
504 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>
507 <!-- Auth protocol for snmp V3 -->
508 <div class="form-group row"
509 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
510 <label class="cd-col-form-label required"
512 i18n>Auth Protocol</label>
513 <div class="cd-col-form-input">
514 <select id="auth_protocol"
517 formControlName="auth_protocol">
519 [ngValue]="null">-- Select auth protocol --</option>
520 <option *ngFor="let authProtocol of ['SHA', 'MD5']"
521 [value]="authProtocol">
525 <span class="invalid-feedback"
526 *ngIf="serviceForm.showError('auth_protocol', frm, 'required')"
527 i18n>This field is required.</span>
530 <!-- Privacy protocol for snmp V3 -->
531 <div class="form-group row"
532 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
533 <label class="cd-col-form-label"
534 for="privacy_protocol"
535 i18n>Privacy Protocol</label>
536 <div class="cd-col-form-input">
537 <select id="privacy_protocol"
538 name="privacy_protocol"
540 formControlName="privacy_protocol">
542 [ngValue]="null">-- Select privacy protocol --</option>
543 <option *ngFor="let privacyProtocol of ['DES', 'AES']"
544 [value]="privacyProtocol">
545 {{ privacyProtocol }}
552 <legend i18n>Credentials</legend>
553 <!-- snmp v2c snmp_community -->
554 <div class="form-group row"
555 *ngIf="serviceForm.controls.snmp_version.value === 'V2c'">
556 <label class="cd-col-form-label required"
557 for="snmp_community">
558 <span i18n>SNMP Community</span>
560 <div class="cd-col-form-input">
561 <input id="snmp_community"
564 formControlName="snmp_community">
565 <span class="invalid-feedback"
566 *ngIf="serviceForm.showError('snmp_community', frm, 'required')"
567 i18n>This field is required.</span>
570 <!-- snmp v3 auth username -->
571 <div class="form-group row"
572 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
573 <label class="cd-col-form-label required"
574 for="snmp_v3_auth_username">
575 <span i18n>Username</span>
577 <div class="cd-col-form-input">
578 <input id="snmp_v3_auth_username"
581 formControlName="snmp_v3_auth_username">
582 <span class="invalid-feedback"
583 *ngIf="serviceForm.showError('snmp_v3_auth_username', frm, 'required')"
584 i18n>This field is required.</span>
587 <!-- snmp v3 auth password -->
588 <div class="form-group row"
589 *ngIf="serviceForm.controls.snmp_version.value === 'V3'">
590 <label class="cd-col-form-label required"
591 for="snmp_v3_auth_password">
592 <span i18n>Password</span>
594 <div class="cd-col-form-input">
595 <input id="snmp_v3_auth_password"
598 formControlName="snmp_v3_auth_password">
599 <span class="invalid-feedback"
600 *ngIf="serviceForm.showError('snmp_v3_auth_password', frm, 'required')"
601 i18n>This field is required.</span>
604 <!-- snmp v3 priv password -->
605 <div class="form-group row"
606 *ngIf="serviceForm.controls.snmp_version.value === 'V3' && serviceForm.controls.privacy_protocol.value !== null && serviceForm.controls.privacy_protocol.value !== undefined">
607 <label class="cd-col-form-label required"
608 for="snmp_v3_priv_password">
609 <span i18n>Encryption</span>
611 <div class="cd-col-form-input">
612 <input id="snmp_v3_priv_password"
615 formControlName="snmp_v3_priv_password">
616 <span class="invalid-feedback"
617 *ngIf="serviceForm.showError('snmp_v3_priv_password', frm, 'required')"
618 i18n>This field is required.</span>
623 <!-- RGW, Ingress & iSCSI -->
624 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)">
626 <div class="form-group row">
627 <div class="cd-col-form-offset">
628 <div class="custom-control custom-checkbox">
629 <input class="custom-control-input"
632 formControlName="ssl">
633 <label class="custom-control-label"
641 <div *ngIf="serviceForm.controls.ssl.value"
642 class="form-group row">
643 <label class="cd-col-form-label"
645 <span i18n>Certificate</span>
646 <cd-helper i18n>The SSL certificate in PEM format.</cd-helper>
648 <div class="cd-col-form-input">
649 <textarea id="ssl_cert"
650 class="form-control resize-vertical text-monospace text-pre"
651 formControlName="ssl_cert"
655 (change)="fileUpload($event.target.files, 'ssl_cert')">
656 <span class="invalid-feedback"
657 *ngIf="serviceForm.showError('ssl_cert', frm, 'required')"
658 i18n>This field is required.</span>
659 <span class="invalid-feedback"
660 *ngIf="serviceForm.showError('ssl_cert', frm, 'pattern')"
661 i18n>Invalid SSL certificate.</span>
666 <div *ngIf="serviceForm.controls.ssl.value && !(['rgw', 'ingress'].includes(serviceForm.controls.service_type.value))"
667 class="form-group row">
668 <label class="cd-col-form-label"
670 <span i18n>Private key</span>
671 <cd-helper i18n>The SSL private key in PEM format.</cd-helper>
673 <div class="cd-col-form-input">
674 <textarea id="ssl_key"
675 class="form-control resize-vertical text-monospace text-pre"
676 formControlName="ssl_key"
680 (change)="fileUpload($event.target.files,'ssl_key')">
681 <span class="invalid-feedback"
682 *ngIf="serviceForm.showError('ssl_key', frm, 'required')"
683 i18n>This field is required.</span>
684 <span class="invalid-feedback"
685 *ngIf="serviceForm.showError('ssl_key', frm, 'pattern')"
686 i18n>Invalid SSL private key.</span>
691 <ng-container *ngIf="serviceForm.controls.service_type.value === 'grafana'">
692 <div class="form-group row">
693 <label class="cd-col-form-label"
695 <span i18n>Grafana Port</span>
697 <span i18n>The default port used by grafana.</span>
700 <div class="cd-col-form-input">
701 <input id="grafana_port"
704 formControlName="grafana_port"
707 <span class="invalid-feedback"
708 *ngIf="serviceForm.showError('grafana_port', frm, 'pattern')"
709 i18n>The entered value needs to be a number.</span>
710 <span class="invalid-feedback"
711 *ngIf="serviceForm.showError('grafana_port', frm, 'min')"
712 i18n>The value must be at least 1.</span>
713 <span class="invalid-feedback"
714 *ngIf="serviceForm.showError('grafana_port', frm, 'max')"
715 i18n>The value cannot exceed 65535.</span>
716 <span class="invalid-feedback"
717 *ngIf="serviceForm.showError('grafana_port', frm, 'required')"
718 i18n>This field is required.</span>
722 <div class="form-group row">
724 class="cd-col-form-label"
725 for="grafana_admin_password">
726 <span>Grafana Password</span>
727 <cd-helper>The password of the default Grafana Admin. Set once on first-run.</cd-helper>
729 <div class="cd-col-form-input">
730 <div class="input-group">
731 <input id="grafana_admin_password"
734 autocomplete="new-password"
735 [attr.disabled]="editing ? true:null"
736 formControlName="grafana_admin_password">
737 <span class="input-group-append">
738 <button type="button"
739 class="btn btn-light"
740 cdPasswordButton="grafana_admin_password">
742 <cd-copy-2-clipboard-button source="grafana_admin_password">
743 </cd-copy-2-clipboard-button>
751 <div class="modal-footer">
752 <div class="text-right">
753 <cd-form-button-panel (submitActionEvent)="onSubmit()"
755 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>