]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html
import ceph pacific 16.2.5
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / services / service-form / service-form.component.html
1 <div class="cd-col-form">
2 <form #frm="ngForm"
3 [formGroup]="serviceForm"
4 novalidate>
5 <div class="card">
6 <div i18n="form title|Example: Create Pool@@formTitle"
7 class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div>
8
9 <div class="card-body">
10 <!-- Service type -->
11 <div class="form-group row">
12 <label class="cd-col-form-label required"
13 for="service_type"
14 i18n>Type</label>
15 <div class="cd-col-form-input">
16 <select id="service_type"
17 name="service_type"
18 class="form-control custom-select"
19 formControlName="service_type">
20 <option i18n
21 [ngValue]="null">-- Select a service type --</option>
22 <option *ngFor="let serviceType of serviceTypes"
23 [value]="serviceType">
24 {{ serviceType }}
25 </option>
26 </select>
27 <span class="invalid-feedback"
28 *ngIf="serviceForm.showError('service_type', frm, 'required')"
29 i18n>This field is required.</span>
30 </div>
31 </div>
32
33 <!-- backend_service -->
34 <div *ngIf="serviceForm.controls.service_type.value === 'ingress'"
35 class="form-group row">
36 <label i18n
37 class="cd-col-form-label"
38 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
39 for="backend_service">Backend Service</label>
40 <div class="cd-col-form-input">
41 <select id="backend_service"
42 name="backend_service"
43 class="form-control custom-select"
44 formControlName="backend_service"
45 (change)="prePopulateId()">
46 <option *ngIf="services === null"
47 [ngValue]="null"
48 i18n>Loading...</option>
49 <option *ngIf="services !== null && services.length === 0"
50 [ngValue]="null"
51 i18n>-- No service available --</option>
52 <option *ngIf="services !== null && services.length > 0"
53 [ngValue]="null"
54 i18n>-- Select an existing RGW service --</option>
55 <option *ngFor="let service of services"
56 [value]="service.service_name">{{ service.service_name }}</option>
57 </select>
58 <span class="invalid-feedback"
59 *ngIf="serviceForm.showError('backend_service', frm, 'required')"
60 i18n>This field is required.</span>
61 </div>
62 </div>
63
64 <!-- Service id -->
65 <div class="form-group row">
66 <label i18n
67 class="cd-col-form-label"
68 [ngClass]="{'required': ['mds', 'rgw', 'nfs', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)}"
69 for="service_id">Id</label>
70 <div class="cd-col-form-input">
71 <input id="service_id"
72 class="form-control"
73 type="text"
74 formControlName="service_id">
75 <span class="invalid-feedback"
76 *ngIf="serviceForm.showError('service_id', frm, 'required')"
77 i18n>This field is required.</span>
78 <span class="invalid-feedback"
79 *ngIf="serviceForm.showError('service_id', frm, 'rgwPattern')"
80 i18n>The value does not match the pattern <strong>&lt;realm_name&gt;.&lt;zone_name&gt;[.&lt;subcluster&gt;]</strong>.</span>
81 </div>
82 </div>
83
84 <!-- unmanaged -->
85 <div class="form-group row">
86 <div class="cd-col-form-offset">
87 <div class="custom-control custom-checkbox">
88 <input class="custom-control-input"
89 id="unmanaged"
90 type="checkbox"
91 formControlName="unmanaged">
92 <label class="custom-control-label"
93 for="unmanaged"
94 i18n>Unmanaged</label>
95 </div>
96 </div>
97 </div>
98
99 <!-- Placement -->
100 <div *ngIf="!serviceForm.controls.unmanaged.value"
101 class="form-group row">
102 <label class="cd-col-form-label"
103 for="placement"
104 i18n>Placement</label>
105 <div class="cd-col-form-input">
106 <select id="placement"
107 class="form-control custom-select"
108 formControlName="placement">
109 <option i18n
110 value="hosts">Hosts</option>
111 <option i18n
112 value="label">Label</option>
113 </select>
114 </div>
115 </div>
116
117 <!-- Label -->
118 <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'label'"
119 class="form-group row">
120 <label i18n
121 class="cd-col-form-label"
122 for="label">Label</label>
123 <div class="cd-col-form-input">
124 <input id="label"
125 class="form-control"
126 type="text"
127 formControlName="label"
128 [ngbTypeahead]="searchLabels"
129 (focus)="labelFocus.next($any($event).target.value)"
130 (click)="labelClick.next($any($event).target.value)">
131 <span class="invalid-feedback"
132 *ngIf="serviceForm.showError('label', frm, 'required')"
133 i18n>This field is required.</span>
134 </div>
135 </div>
136
137 <!-- Hosts -->
138 <div *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.placement.value === 'hosts'"
139 class="form-group row">
140 <label class="cd-col-form-label"
141 for="hosts"
142 i18n>Hosts</label>
143 <div class="cd-col-form-input">
144 <cd-select-badges id="hosts"
145 [data]="serviceForm.controls.hosts.value"
146 [options]="hosts.options"
147 [messages]="hosts.messages">
148 </cd-select-badges>
149 </div>
150 </div>
151
152 <!-- count -->
153 <div *ngIf="!serviceForm.controls.unmanaged.value"
154 class="form-group row">
155 <label class="cd-col-form-label"
156 for="count">
157 <span i18n>Count</span>
158 <cd-helper i18n>Only that number of daemons will be created.</cd-helper>
159 </label>
160 <div class="cd-col-form-input">
161 <input id="count"
162 class="form-control"
163 type="number"
164 formControlName="count"
165 min="1">
166 <span class="invalid-feedback"
167 *ngIf="serviceForm.showError('count', frm, 'min')"
168 i18n>The value must be at least 1.</span>
169 <span class="invalid-feedback"
170 *ngIf="serviceForm.showError('count', frm, 'pattern')"
171 i18n>The entered value needs to be a number.</span>
172 </div>
173 </div>
174
175 <!-- NFS -->
176 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'nfs'">
177 <!-- pool -->
178 <div class="form-group row">
179 <label i18n
180 class="cd-col-form-label required"
181 for="pool">Pool</label>
182 <div class="cd-col-form-input">
183 <select id="pool"
184 name="pool"
185 class="form-control custom-select"
186 formControlName="pool">
187 <option *ngIf="pools === null"
188 [ngValue]="null"
189 i18n>Loading...</option>
190 <option *ngIf="pools !== null && pools.length === 0"
191 [ngValue]="null"
192 i18n>-- No pools available --</option>
193 <option *ngIf="pools !== null && pools.length > 0"
194 [ngValue]="null"
195 i18n>-- Select a pool --</option>
196 <option *ngFor="let pool of pools"
197 [value]="pool.pool_name">{{ pool.pool_name }}</option>
198 </select>
199 <span class="invalid-feedback"
200 *ngIf="serviceForm.showError('pool', frm, 'required')"
201 i18n>This field is required.</span>
202 </div>
203 </div>
204
205 <!-- namespace -->
206 <div class="form-group row">
207 <label i18n
208 class="cd-col-form-label"
209 for="namespace">Namespace</label>
210 <div class="cd-col-form-input">
211 <input id="namespace"
212 class="form-control"
213 type="text"
214 formControlName="namespace">
215 </div>
216 </div>
217 </ng-container>
218
219 <!-- RGW -->
220 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'rgw'">
221 <!-- rgw_frontend_port -->
222 <div class="form-group row">
223 <label i18n
224 class="cd-col-form-label"
225 for="rgw_frontend_port">Port</label>
226 <div class="cd-col-form-input">
227 <input id="rgw_frontend_port"
228 class="form-control"
229 type="number"
230 formControlName="rgw_frontend_port"
231 min="1"
232 max="65535">
233 <span class="invalid-feedback"
234 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'pattern')"
235 i18n>The entered value needs to be a number.</span>
236 <span class="invalid-feedback"
237 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'min')"
238 i18n>The value must be at least 1.</span>
239 <span class="invalid-feedback"
240 *ngIf="serviceForm.showError('rgw_frontend_port', frm, 'max')"
241 i18n>The value cannot exceed 65535.</span>
242 </div>
243 </div>
244 </ng-container>
245
246 <!-- iSCSI -->
247 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'iscsi'">
248 <!-- pool -->
249 <div class="form-group row">
250 <label i18n
251 class="cd-col-form-label required"
252 for="pool">Pool</label>
253 <div class="cd-col-form-input">
254 <select id="pool"
255 name="pool"
256 class="form-control custom-select"
257 formControlName="pool">
258 <option *ngIf="pools === null"
259 [ngValue]="null"
260 i18n>Loading...</option>
261 <option *ngIf="pools !== null && pools.length === 0"
262 [ngValue]="null"
263 i18n>-- No pools available --</option>
264 <option *ngIf="pools !== null && pools.length > 0"
265 [ngValue]="null"
266 i18n>-- Select a pool --</option>
267 <option *ngFor="let pool of pools"
268 [value]="pool.pool_name">{{ pool.pool_name }}</option>
269 </select>
270 <span class="invalid-feedback"
271 *ngIf="serviceForm.showError('pool', frm, 'required')"
272 i18n>This field is required.</span>
273 </div>
274 </div>
275
276 <!-- trusted_ip_list -->
277 <div class="form-group row">
278 <label class="cd-col-form-label"
279 for="trusted_ip_list">
280 <span i18n>Trusted IPs</span>
281 <cd-helper>
282 <span i18n>Comma separated list of IP addresses.</span>
283 <br>
284 <span i18n>Please add the <b>Ceph Manager</b> IP addresses here, otherwise the iSCSI gateways can't be reached.</span>
285 </cd-helper>
286 </label>
287 <div class="cd-col-form-input">
288 <input id="trusted_ip_list"
289 class="form-control"
290 type="text"
291 formControlName="trusted_ip_list">
292 </div>
293 </div>
294
295 <!-- api_port -->
296 <div class="form-group row">
297 <label i18n
298 class="cd-col-form-label"
299 for="api_port">Port</label>
300 <div class="cd-col-form-input">
301 <input id="api_port"
302 class="form-control"
303 type="number"
304 formControlName="api_port"
305 min="1"
306 max="65535">
307 <span class="invalid-feedback"
308 *ngIf="serviceForm.showError('api_port', frm, 'pattern')"
309 i18n>The entered value needs to be a number.</span>
310 <span class="invalid-feedback"
311 *ngIf="serviceForm.showError('api_port', frm, 'min')"
312 i18n>The value must be at least 1.</span>
313 <span class="invalid-feedback"
314 *ngIf="serviceForm.showError('api_port', frm, 'max')"
315 i18n>The value cannot exceed 65535.</span>
316 </div>
317 </div>
318
319 <!-- api_user -->
320 <div class="form-group row">
321 <label i18n
322 class="cd-col-form-label"
323 [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
324 for="api_user">User</label>
325 <div class="cd-col-form-input">
326 <input id="api_user"
327 class="form-control"
328 type="text"
329 formControlName="api_user">
330 <span class="invalid-feedback"
331 *ngIf="serviceForm.showError('api_user', frm, 'required')"
332 i18n>This field is required.</span>
333 </div>
334 </div>
335
336 <!-- api_password -->
337 <div class="form-group row">
338 <label i18n
339 class="cd-col-form-label"
340 [ngClass]="{'required': ['iscsi'].includes(serviceForm.controls.service_type.value)}"
341 for="api_password">Password</label>
342 <div class="cd-col-form-input">
343 <div class="input-group">
344 <input id="api_password"
345 class="form-control"
346 type="password"
347 autocomplete="new-password"
348 formControlName="api_password">
349 <span class="input-group-append">
350 <button type="button"
351 class="btn btn-light"
352 cdPasswordButton="api_password">
353 </button>
354 <cd-copy-2-clipboard-button source="api_password">
355 </cd-copy-2-clipboard-button>
356 </span>
357 <span class="invalid-feedback"
358 *ngIf="serviceForm.showError('api_password', frm, 'required')"
359 i18n>This field is required.</span>
360 </div>
361 </div>
362 </div>
363 </ng-container>
364
365 <!-- Ingress -->
366 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && serviceForm.controls.service_type.value === 'ingress'">
367 <!-- virtual_ip -->
368 <div class="form-group row">
369 <label class="cd-col-form-label"
370 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
371 for="virtual_ip">
372 <span i18n>Virtual IP</span>
373 <cd-helper>
374 <span i18n>The virtual IP address and subnet (in CIDR notation) where the ingress service will be available.</span>
375 </cd-helper>
376 </label>
377 <div class="cd-col-form-input">
378 <input id="virtual_ip"
379 class="form-control"
380 type="text"
381 formControlName="virtual_ip">
382 <span class="invalid-feedback"
383 *ngIf="serviceForm.showError('virtual_ip', frm, 'required')"
384 i18n>This field is required.</span>
385 </div>
386 </div>
387
388 <!-- frontend_port -->
389 <div class="form-group row">
390 <label class="cd-col-form-label"
391 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
392 for="frontend_port">
393 <span i18n>Frontend Port</span>
394 <cd-helper>
395 <span i18n>The port used to access the ingress service.</span>
396 </cd-helper>
397 </label>
398 <div class="cd-col-form-input">
399 <input id="frontend_port"
400 class="form-control"
401 type="number"
402 formControlName="frontend_port"
403 min="1"
404 max="65535">
405 <span class="invalid-feedback"
406 *ngIf="serviceForm.showError('frontend_port', frm, 'pattern')"
407 i18n>The entered value needs to be a number.</span>
408 <span class="invalid-feedback"
409 *ngIf="serviceForm.showError('frontend_port', frm, 'min')"
410 i18n>The value must be at least 1.</span>
411 <span class="invalid-feedback"
412 *ngIf="serviceForm.showError('frontend_port', frm, 'max')"
413 i18n>The value cannot exceed 65535.</span>
414 <span class="invalid-feedback"
415 *ngIf="serviceForm.showError('frontend_port', frm, 'required')"
416 i18n>This field is required.</span>
417 </div>
418 </div>
419
420 <!-- monitor_port -->
421 <div class="form-group row">
422 <label class="cd-col-form-label"
423 [ngClass]="{'required': ['ingress'].includes(serviceForm.controls.service_type.value)}"
424 for="monitor_port">
425 <span i18n>Monitor Port</span>
426 <cd-helper>
427 <span i18n>The port used by haproxy for load balancer status.</span>
428 </cd-helper>
429 </label>
430 <div class="cd-col-form-input">
431 <input id="monitor_port"
432 class="form-control"
433 type="number"
434 formControlName="monitor_port"
435 min="1"
436 max="65535">
437 <span class="invalid-feedback"
438 *ngIf="serviceForm.showError('monitor_port', frm, 'pattern')"
439 i18n>The entered value needs to be a number.</span>
440 <span class="invalid-feedback"
441 *ngIf="serviceForm.showError('monitor_port', frm, 'min')"
442 i18n>The value must be at least 1.</span>
443 <span class="invalid-feedback"
444 *ngIf="serviceForm.showError('monitor_port', frm, 'max')"
445 i18n>The value cannot exceed 65535.</span>
446 <span class="invalid-feedback"
447 *ngIf="serviceForm.showError('monitor_port', frm, 'required')"
448 i18n>This field is required.</span>
449 </div>
450 </div>
451 <!-- virtual_interface_networks -->
452 <div class="form-group row">
453 <label class="cd-col-form-label"
454 for="virtual_interface_networks">
455 <span i18n>CIDR Networks</span>
456 <cd-helper>
457 <span i18n>A list of networks to identify which network interface to use for the virtual IP address.</span>
458 </cd-helper>
459 </label>
460 <div class="cd-col-form-input">
461 <input id="virtual_interface_networks"
462 class="form-control"
463 type="text"
464 formControlName="virtual_interface_networks">
465 </div>
466 </div>
467 </ng-container>
468 <!-- RGW, Ingress & iSCSI -->
469 <ng-container *ngIf="!serviceForm.controls.unmanaged.value && ['rgw', 'iscsi', 'ingress'].includes(serviceForm.controls.service_type.value)">
470 <!-- ssl -->
471 <div class="form-group row">
472 <div class="cd-col-form-offset">
473 <div class="custom-control custom-checkbox">
474 <input class="custom-control-input"
475 id="ssl"
476 type="checkbox"
477 formControlName="ssl">
478 <label class="custom-control-label"
479 for="ssl"
480 i18n>SSL</label>
481 </div>
482 </div>
483 </div>
484
485 <!-- ssl_cert -->
486 <div *ngIf="serviceForm.controls.ssl.value"
487 class="form-group row">
488 <label class="cd-col-form-label"
489 for="ssl_cert">
490 <span i18n>Certificate</span>
491 <cd-helper i18n>The SSL certificate in PEM format.</cd-helper>
492 </label>
493 <div class="cd-col-form-input">
494 <textarea id="ssl_cert"
495 class="form-control resize-vertical text-monospace text-pre"
496 formControlName="ssl_cert"
497 rows="5">
498 </textarea>
499 <input type="file"
500 (change)="fileUpload($event.target.files, 'ssl_cert')">
501 <span class="invalid-feedback"
502 *ngIf="serviceForm.showError('ssl_cert', frm, 'required')"
503 i18n>This field is required.</span>
504 <span class="invalid-feedback"
505 *ngIf="serviceForm.showError('ssl_cert', frm, 'pattern')"
506 i18n>Invalid SSL certificate.</span>
507 </div>
508 </div>
509
510 <!-- ssl_key -->
511 <div *ngIf="serviceForm.controls.ssl.value"
512 class="form-group row">
513 <label class="cd-col-form-label"
514 for="ssl_key">
515 <span i18n>Private key</span>
516 <cd-helper i18n>The SSL private key in PEM format.</cd-helper>
517 </label>
518 <div class="cd-col-form-input">
519 <textarea id="ssl_key"
520 class="form-control resize-vertical text-monospace text-pre"
521 formControlName="ssl_key"
522 rows="5">
523 </textarea>
524 <input type="file"
525 (change)="fileUpload($event.target.files,'ssl_key')">
526 <span class="invalid-feedback"
527 *ngIf="serviceForm.showError('ssl_key', frm, 'required')"
528 i18n>This field is required.</span>
529 <span class="invalid-feedback"
530 *ngIf="serviceForm.showError('ssl_key', frm, 'pattern')"
531 i18n>Invalid SSL private key.</span>
532 </div>
533 </div>
534 </ng-container>
535 </div>
536
537 <div class="card-footer">
538 <div class="text-right">
539 <cd-form-button-panel (submitActionEvent)="onSubmit()"
540 [form]="serviceForm"
541 [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>
542 </div>
543 </div>
544 </div>
545 </form>
546 </div>