1 <cd-loading-panel *
ngIf=
"!(info && ecProfiles)"
2 i18n
>Loading...
</cd-loading-panel>
4 <div class=
"cd-col-form">
6 *
ngIf=
"info && ecProfiles"
11 <div i18n=
"form title|Example: Create Pool@@formTitle"
12 class=
"card-header">{{ action | titlecase }} {{ resource | upperFirst }}
</div>
14 <div class=
"card-body">
16 <div class=
"form-group row">
17 <label class=
"cd-col-form-label required"
20 <div class=
"cd-col-form-input">
27 formControlName=
"name"
29 <span class=
"invalid-feedback"
30 *
ngIf=
"form.showError('name', formDir, 'required')"
31 i18n
>This field is required!
</span>
32 <span class=
"invalid-feedback"
33 *
ngIf=
"form.showError('name', formDir, 'uniqueName')"
34 i18n
>The chosen Ceph pool name is already in use.
</span>
35 <span *
ngIf=
"form.showError('name', formDir, 'rbdPool')"
36 class=
"invalid-feedback"
37 i18n
>It's not possible to create an RBD pool with '/' in the name.
38 Please change the name or remove 'rbd' from the applications list.
</span>
39 <span *
ngIf=
"form.showError('name', formDir, 'pattern')"
40 class=
"invalid-feedback"
41 i18n
>Pool name can only contain letters, numbers, '.', '-', '_' or '/'.
</span>
45 <!-- Pool type selection -->
46 <div class=
"form-group row">
47 <label class=
"cd-col-form-label required"
49 i18n
>Pool type
</label>
50 <div class=
"cd-col-form-input">
51 <select class=
"form-control custom-select"
53 formControlName=
"poolType"
56 i18n
>-- Select a pool type --
</option>
57 <option *
ngFor=
"let poolType of data.poolTypes"
62 <span class=
"invalid-feedback"
63 *
ngIf=
"form.showError('poolType', formDir, 'required')"
64 i18n
>This field is required!
</span>
68 <div *
ngIf=
"isReplicated || isErasure">
69 <!-- PG Autoscale Mode -->
70 <div class=
"form-group row">
72 class=
"cd-col-form-label"
73 for=
"pgAutoscaleMode">PG Autoscale
</label>
74 <div class=
"cd-col-form-input">
75 <select class=
"form-control custom-select"
77 name=
"pgAutoscaleMode"
78 formControlName=
"pgAutoscaleMode">
79 <option *
ngFor=
"let mode of pgAutoscaleModes"
88 <div class=
"form-group row"
89 *
ngIf=
"form.getValue('pgAutoscaleMode') !== 'on'">
90 <label class=
"cd-col-form-label required"
92 i18n
>Placement groups
</label>
93 <div class=
"cd-col-form-input">
94 <input class=
"form-control"
97 formControlName=
"pgNum"
100 (focus)=
"externalPgChange = false"
103 <span class=
"invalid-feedback"
104 *
ngIf=
"form.showError('pgNum', formDir, 'required')"
105 i18n
>This field is required!
</span>
106 <span class=
"invalid-feedback"
107 *
ngIf=
"form.showError('pgNum', formDir, 'min')"
108 i18n
>At least one placement group is needed!
</span>
109 <span class=
"invalid-feedback"
110 *
ngIf=
"form.showError('pgNum', formDir, '34')"
111 i18n
>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.
</span>
112 <span class=
"form-text text-muted">
113 <cd-doc section=
"pgs"
114 docText=
"Calculation help"
115 i18n-docText
></cd-doc>
117 <span class=
"form-text text-muted"
118 *
ngIf=
"externalPgChange"
119 i18n
>The current PGs settings were calculated for you, you
120 should make sure the values suit your needs before submit.
</span>
124 <!-- Replica Size -->
125 <div class=
"form-group row"
126 *
ngIf=
"isReplicated">
127 <label class=
"cd-col-form-label required"
129 i18n
>Replicated size
</label>
130 <div class=
"cd-col-form-input">
131 <input class=
"form-control"
137 formControlName=
"size">
138 <span class=
"invalid-feedback"
139 *
ngIf=
"form.showError('size', formDir)">
140 <ul class=
"list-inline">
141 <li i18n
>Minimum: {{ getMinSize() }}
</li>
142 <li i18n
>Maximum: {{ getMaxSize() }}
</li>
145 <span class=
"invalid-feedback"
146 *
ngIf=
"form.showError('size', formDir)"
147 i18n
>The size specified is out of range. A value from
148 {{ getMinSize() }} to {{ getMaxSize() }} is usable.
</span>
149 <span class=
"text-warning-dark"
150 *
ngIf=
"form.getValue('size') === 1"
151 i18n
>A size of
1 will not create a replication of the
152 object. The 'Replicated size' includes the object itself.
</span>
157 <div class=
"form-group row"
158 *
ngIf=
"info.is_all_bluestore && isErasure">
160 class=
"cd-col-form-label">Flags
</label>
161 <div class=
"cd-col-form-input">
162 <div class=
"custom-control custom-checkbox">
163 <input type=
"checkbox"
164 class=
"custom-control-input"
166 formControlName=
"ecOverwrites">
167 <label class=
"custom-control-label"
169 i18n
>EC Overwrites
</label>
175 <!-- Applications -->
176 <div class=
"form-group row">
178 class=
"cd-col-form-label"
179 for=
"applications">Applications
</label>
180 <div class=
"cd-col-form-input">
181 <cd-select-badges id=
"applications"
182 [customBadges]=
"true"
183 [customBadgeValidators]=
"data.applications.validators"
184 [messages]=
"data.applications.messages"
185 [data]=
"data.applications.selected"
186 [options]=
"data.applications.available"
188 (selection)=
"appSelection()">
194 <div *
ngIf=
"isErasure || isReplicated">
196 <legend i18n
>CRUSH
</legend>
198 <!-- Erasure Profile select -->
199 <div class=
"form-group row"
202 class=
"cd-col-form-label"
203 for=
"erasureProfile">Erasure code profile
</label>
204 <div class=
"cd-col-form-input">
205 <div class=
"input-group">
206 <select class=
"form-control custom-select"
208 name=
"erasureProfile"
209 formControlName=
"erasureProfile">
210 <option *
ngIf=
"!ecProfiles"
212 i18n
>Loading...
</option>
213 <option *
ngIf=
"ecProfiles && ecProfiles.length === 0"
215 i18n
>-- No erasure code profile available --
</option>
216 <option *
ngIf=
"ecProfiles && ecProfiles.length > 0"
218 i18n
>-- Select an erasure code profile --
</option>
219 <option *
ngFor=
"let ecp of ecProfiles"
224 <span class=
"input-group-append">
225 <button class=
"btn btn-light"
226 [ngClass]=
"{'active': data.erasureInfo}"
229 (click)=
"data.erasureInfo = !data.erasureInfo">
230 <i [ngClass]=
"[icons.questionCircle]"
231 aria-hidden=
"true"></i>
233 <button class=
"btn btn-light"
236 (click)=
"addErasureCodeProfile()">
237 <i [ngClass]=
"[icons.add]"
238 aria-hidden=
"true"></i>
240 <button class=
"btn btn-light"
243 tooltip=
"This profile can't be deleted as it is in use."
246 #
ecpDeletionBtn=
"bs-tooltip"
247 (click)=
"deleteErasureCodeProfile()">
248 <i [ngClass]=
"[icons.trash]"
249 aria-hidden=
"true"></i>
253 <span class=
"form-text text-muted"
255 *
ngIf=
"data.erasureInfo && form.getValue('erasureProfile')">
256 <tabset #ecpInfoTabs
>
260 <cd-table-key-value [renderObjects]=
"true"
261 [hideKeys]=
"['name']"
262 [data]=
"form.getValue('erasureProfile')"
263 [autoReload]=
"false">
264 </cd-table-key-value>
267 heading=
"Used by pools"
268 class=
"used-by-pools">
269 <ng-template #ecpIsNotUsed
>
270 <span i18n
>Profile is not in use.
</span>
272 <ul *
ngIf=
"ecpUsage; else ecpIsNotUsed">
273 <li *
ngFor=
"let pool of ecpUsage">
283 <!-- Crush ruleset selection -->
284 <div class=
"form-group row"
285 *
ngIf=
"isErasure && !editing">
286 <label class=
"cd-col-form-label"
288 i18n
>Crush ruleset
</label>
289 <div class=
"cd-col-form-input">
290 <span class=
"form-text text-muted"
291 i18n
>A new crush ruleset will be implicitly created.
</span>
294 <div class=
"form-group row"
295 *
ngIf=
"isReplicated || editing">
296 <label class=
"cd-col-form-label"
298 i18n
>Crush ruleset
</label>
299 <div class=
"cd-col-form-input">
300 <ng-template #noRules
>
301 <span class=
"form-text text-muted">
302 <span i18n
>There are no rules.
</span>
305 <div *
ngIf=
"current.rules.length > 0; else noRules">
306 <div class=
"input-group">
307 <select class=
"form-control custom-select"
309 formControlName=
"crushRule"
311 <option [ngValue]=
"null"
312 i18n
>-- Select a crush rule --
</option>
313 <option *
ngFor=
"let rule of current.rules"
318 <span class=
"input-group-append">
319 <button class=
"btn btn-light"
320 [ngClass]=
"{'active': data.crushInfo}"
321 id=
"crush-info-button"
323 (click)=
"data.crushInfo = !data.crushInfo">
324 <i [ngClass]=
"[icons.questionCircle]"
325 aria-hidden=
"true"></i>
327 <button class=
"btn btn-light"
329 *
ngIf=
"isReplicated && !editing"
330 (click)=
"addCrushRule()">
331 <i [ngClass]=
"[icons.add]"
332 aria-hidden=
"true"></i>
334 <button class=
"btn btn-light"
335 *
ngIf=
"isReplicated && !editing"
337 tooltip=
"This rule can't be deleted as it is in use."
340 #
crushDeletionBtn=
"bs-tooltip"
341 (click)=
"deleteCrushRule()">
342 <i [ngClass]=
"[icons.trash]"
343 aria-hidden=
"true"></i>
347 <span class=
"form-text text-muted"
348 id=
"crush-info-block"
349 *
ngIf=
"data.crushInfo && form.getValue('crushRule')">
350 <tabset #crushInfoTabs
>
353 class=
"crush-rule-info">
354 <cd-table-key-value [renderObjects]=
"false"
355 [hideKeys]=
"['steps', 'ruleset', 'type', 'rule_name']"
356 [data]=
"form.getValue('crushRule')"
357 [autoReload]=
"false">
358 </cd-table-key-value>
361 heading=
"Crush steps"
362 class=
"crush-rule-steps">
364 <li *
ngFor=
"let step of form.get('crushRule').value.steps">
365 {{ describeCrushStep(step) }}
370 heading=
"Used by pools"
371 class=
"used-by-pools">
372 <ng-template #ruleIsNotUsed
>
373 <span i18n
>Rule is not in use.
</span>
375 <ul *
ngIf=
"crushUsage; else ruleIsNotUsed">
376 <li *
ngFor=
"let pool of crushUsage">
383 <span class=
"invalid-feedback"
384 *
ngIf=
"form.showError('crushRule', formDir, 'required')"
385 i18n
>This field is required!
</span>
386 <span class=
"invalid-feedback"
387 *
ngIf=
"form.showError('crushRule', formDir, 'tooFewOsds')"
388 i18n
>The rule can't be used in the current cluster as it has
389 too few OSDs to meet the minimum required OSD by this rule.
</span>
397 <div *
ngIf=
"info.is_all_bluestore"
398 formGroupName=
"compression">
399 <legend i18n
>Compression
</legend>
401 <!-- Compression Mode -->
402 <div class=
"form-group row">
404 class=
"cd-col-form-label"
405 for=
"mode">Mode
</label>
406 <div class=
"cd-col-form-input">
407 <select class=
"form-control custom-select"
410 formControlName=
"mode">
411 <option *
ngFor=
"let mode of info.compression_modes"
418 <div *
ngIf=
"hasCompressionEnabled()">
419 <!-- Compression algorithm selection -->
420 <div class=
"form-group row">
422 class=
"cd-col-form-label"
423 for=
"algorithm">Algorithm
</label>
424 <div class=
"cd-col-form-input">
425 <select class=
"form-control custom-select"
428 formControlName=
"algorithm">
429 <option *
ngIf=
"!info.compression_algorithms"
431 i18n
>Loading...
</option>
432 <option *
ngIf=
"info.compression_algorithms && info.compression_algorithms.length === 0"
434 ngValue=
"">-- No erasure compression algorithm available --
</option>
435 <option *
ngFor=
"let algorithm of info.compression_algorithms"
443 <!-- Compression min blob size -->
444 <div class=
"form-group row">
446 class=
"cd-col-form-label"
447 for=
"minBlobSize">Minimum blob size
</label>
448 <div class=
"cd-col-form-input">
449 <input id=
"minBlobSize"
451 formControlName=
"minBlobSize"
456 placeholder=
"e.g., 128KiB"
459 <span class=
"invalid-feedback"
460 *
ngIf=
"form.showError('minBlobSize', formDir, 'min')"
461 i18n
>Value should be greater than
0</span>
462 <span class=
"invalid-feedback"
463 *
ngIf=
"form.showError('minBlobSize', formDir, 'maximum')"
464 i18n
>Value should be less than the maximum blob size
</span>
468 <!-- Compression max blob size -->
469 <div class=
"form-group row">
471 class=
"cd-col-form-label"
472 for=
"maxBlobSize">Maximum blob size
</label>
473 <div class=
"cd-col-form-input">
474 <input id=
"maxBlobSize"
477 formControlName=
"maxBlobSize"
480 placeholder=
"e.g., 512KiB"
483 <span class=
"invalid-feedback"
484 *
ngIf=
"form.showError('maxBlobSize', formDir, 'min')"
485 i18n
>Value should be greater than
0</span>
486 <span class=
"invalid-feedback"
487 *
ngIf=
"form.showError('maxBlobSize', formDir, 'minimum')"
488 i18n
>Value should be greater than the minimum blob size
</span>
492 <!-- Compression ratio -->
493 <div class=
"form-group row">
495 class=
"cd-col-form-label"
496 for=
"ratio">Ratio
</label>
497 <div class=
"cd-col-form-input">
500 formControlName=
"ratio"
507 placeholder=
"Compression ratio">
508 <span class=
"invalid-feedback"
509 *
ngIf=
"form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
510 i18n
>Value should be between
0.0 and
1.0</span>
519 <legend i18n
>Quotas
</legend>
522 <div class=
"form-group row">
523 <label class=
"cd-col-form-label"
525 <ng-container i18n
>Max bytes
</ng-container>
527 <span i18n
>Leave it blank or specify
0 to disable this quota.
</span>
529 <span i18n
>A valid quota should be greater than
0.
</span>
532 <div class=
"cd-col-form-input">
533 <input class=
"form-control"
537 formControlName=
"max_bytes"
539 placeholder=
"e.g., 10GiB"
546 <div class=
"form-group row">
547 <label class=
"cd-col-form-label"
549 <ng-container i18n
>Max objects
</ng-container>
551 <span i18n
>Leave it blank or specify
0 to disable this quota.
</span>
553 <span i18n
>A valid quota should be greater than
0.
</span>
556 <div class=
"cd-col-form-input">
557 <input class=
"form-control"
562 formControlName=
"max_objects">
563 <span class=
"invalid-feedback"
564 *
ngIf=
"form.showError('max_objects', formDir, 'min')"
565 i18n
>The value should be greater or equal to
0</span>
570 <!-- Pool configuration -->
571 <div [hidden]=
"isErasure || data.applications.selected.indexOf('rbd') === -1">
572 <cd-rbd-configuration-form [form]=
"form"
573 [initializeData]=
"initializeConfigData"
574 (changes)=
"currentConfigurationValues = $event()">
575 </cd-rbd-configuration-form>
578 <div class=
"card-footer">
579 <div class=
"button-group text-right">
580 <cd-submit-button [form]=
"formDir"
581 i18n=
"form action button|Example: Create Pool@@formActionButton"
582 (submitAction)=
"submit()">{{ action | titlecase }} {{ resource | upperFirst }}
584 <cd-back-button></cd-back-button>