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">
115 href=
"http://ceph.com/pgcalc">Calculation help
</a>
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 valid.
</span>
153 <div class=
"form-group row"
154 *
ngIf=
"info.is_all_bluestore && isErasure">
156 class=
"cd-col-form-label">Flags
</label>
157 <div class=
"cd-col-form-input">
158 <div class=
"custom-control custom-checkbox">
159 <input type=
"checkbox"
160 class=
"custom-control-input"
162 formControlName=
"ecOverwrites">
163 <label class=
"custom-control-label"
165 i18n
>EC Overwrites
</label>
171 <!-- Applications -->
172 <div class=
"form-group row">
174 class=
"cd-col-form-label"
175 for=
"applications">Applications
</label>
176 <div class=
"cd-col-form-input">
177 <cd-select-badges id=
"applications"
178 [customBadges]=
"true"
179 [customBadgeValidators]=
"data.applications.validators"
180 [messages]=
"data.applications.messages"
181 [data]=
"data.applications.selected"
182 [options]=
"data.applications.available"
184 (selection)=
"appSelection()">
190 <div *
ngIf=
"isErasure || isReplicated">
192 <legend i18n
>CRUSH
</legend>
194 <!-- Erasure Profile select -->
195 <div class=
"form-group row"
198 class=
"cd-col-form-label"
199 for=
"erasureProfile">Erasure code profile
</label>
200 <div class=
"cd-col-form-input">
201 <div class=
"input-group">
202 <select class=
"form-control custom-select"
204 name=
"erasureProfile"
205 formControlName=
"erasureProfile">
206 <option *
ngIf=
"!ecProfiles"
208 i18n
>Loading...
</option>
209 <option *
ngIf=
"ecProfiles && ecProfiles.length === 0"
211 i18n
>-- No erasure code profile available --
</option>
212 <option *
ngIf=
"ecProfiles && ecProfiles.length > 0"
214 i18n
>-- Select an erasure code profile --
</option>
215 <option *
ngFor=
"let ecp of ecProfiles"
220 <span class=
"input-group-append">
221 <button class=
"btn btn-light"
222 [ngClass]=
"{'active': data.erasureInfo}"
225 (click)=
"data.erasureInfo = !data.erasureInfo">
226 <i [ngClass]=
"[icons.questionCircle]"
227 aria-hidden=
"true"></i>
229 <button class=
"btn btn-light"
232 (click)=
"addErasureCodeProfile()">
233 <i [ngClass]=
"[icons.add]"
234 aria-hidden=
"true"></i>
236 <button class=
"btn btn-light"
239 tooltip=
"This profile can't be deleted as it is in use."
242 #
ecpDeletionBtn=
"bs-tooltip"
243 (click)=
"deleteErasureCodeProfile()">
244 <i [ngClass]=
"[icons.trash]"
245 aria-hidden=
"true"></i>
249 <span class=
"form-text text-muted"
251 *
ngIf=
"data.erasureInfo && form.getValue('erasureProfile')">
252 <tabset #ecpInfoTabs
>
256 <cd-table-key-value [renderObjects]=
"true"
257 [data]=
"form.getValue('erasureProfile')"
258 [autoReload]=
"false">
259 </cd-table-key-value>
262 heading=
"Used by pools"
263 class=
"used-by-pools">
264 <ng-template #ecpIsNotUsed
>
265 <span i18n
>Profile is not in use.
</span>
267 <ul *
ngIf=
"ecpUsage; else ecpIsNotUsed">
268 <li *
ngFor=
"let pool of ecpUsage">
278 <!-- Crush ruleset selection -->
279 <div class=
"form-group row"
280 *
ngIf=
"isErasure && !editing">
281 <label class=
"cd-col-form-label"
283 i18n
>Crush ruleset
</label>
284 <div class=
"cd-col-form-input">
285 <span class=
"form-text text-muted"
286 i18n
>A new crush ruleset will be implicitly created.
</span>
289 <div class=
"form-group row"
290 *
ngIf=
"isReplicated || editing">
291 <label class=
"cd-col-form-label"
293 i18n
>Crush ruleset
</label>
294 <div class=
"cd-col-form-input">
295 <ng-template #noRules
>
296 <span class=
"form-text text-muted">
297 <span i18n
>There are no rules.
</span>
300 <div *
ngIf=
"current.rules.length > 0; else noRules">
301 <div class=
"input-group">
302 <select class=
"form-control custom-select"
304 formControlName=
"crushRule"
306 <option [ngValue]=
"null"
307 i18n
>-- Select a crush rule --
</option>
308 <option *
ngFor=
"let rule of current.rules"
313 <span class=
"input-group-append">
314 <button class=
"btn btn-light"
315 [ngClass]=
"{'active': data.crushInfo}"
316 id=
"crush-info-button"
318 (click)=
"data.crushInfo = !data.crushInfo">
319 <i [ngClass]=
"[icons.questionCircle]"
320 aria-hidden=
"true"></i>
322 <button class=
"btn btn-light"
324 *
ngIf=
"isReplicated && !editing"
325 (click)=
"addCrushRule()">
326 <i [ngClass]=
"[icons.add]"
327 aria-hidden=
"true"></i>
329 <button class=
"btn btn-light"
330 *
ngIf=
"isReplicated && !editing"
332 tooltip=
"This rule can't be deleted as it is in use."
335 #
crushDeletionBtn=
"bs-tooltip"
336 (click)=
"deleteCrushRule()">
337 <i [ngClass]=
"[icons.trash]"
338 aria-hidden=
"true"></i>
342 <span class=
"form-text text-muted"
343 id=
"crush-info-block"
344 *
ngIf=
"data.crushInfo && form.getValue('crushRule')">
345 <tabset #crushInfoTabs
>
348 class=
"crush-rule-info">
349 <cd-table-key-value [renderObjects]=
"true"
350 [data]=
"form.getValue('crushRule')"
351 [autoReload]=
"false">
352 </cd-table-key-value>
355 heading=
"Crush steps"
356 class=
"crush-rule-steps">
358 <li *
ngFor=
"let step of form.get('crushRule').value.steps">
359 {{ describeCrushStep(step) }}
364 heading=
"Used by pools"
365 class=
"used-by-pools">
366 <ng-template #ruleIsNotUsed
>
367 <span i18n
>Rule is not in use.
</span>
369 <ul *
ngIf=
"crushUsage; else ruleIsNotUsed">
370 <li *
ngFor=
"let pool of crushUsage">
377 <span class=
"invalid-feedback"
378 *
ngIf=
"form.showError('crushRule', formDir, 'required')"
379 i18n
>This field is required!
</span>
380 <span class=
"invalid-feedback"
381 *
ngIf=
"form.showError('crushRule', formDir, 'tooFewOsds')"
382 i18n
>The rule can't be used in the current cluster as it has
383 too few OSDs to meet the minimum required OSD by this rule.
</span>
391 <div *
ngIf=
"info.is_all_bluestore"
392 formGroupName=
"compression">
393 <legend i18n
>Compression
</legend>
395 <!-- Compression Mode -->
396 <div class=
"form-group row">
398 class=
"cd-col-form-label"
399 for=
"mode">Mode
</label>
400 <div class=
"cd-col-form-input">
401 <select class=
"form-control custom-select"
404 formControlName=
"mode">
405 <option *
ngFor=
"let mode of info.compression_modes"
412 <div *
ngIf=
"hasCompressionEnabled()">
413 <!-- Compression algorithm selection -->
414 <div class=
"form-group row">
416 class=
"cd-col-form-label"
417 for=
"algorithm">Algorithm
</label>
418 <div class=
"cd-col-form-input">
419 <select class=
"form-control custom-select"
422 formControlName=
"algorithm">
423 <option *
ngIf=
"!info.compression_algorithms"
425 i18n
>Loading...
</option>
426 <option *
ngIf=
"info.compression_algorithms && info.compression_algorithms.length === 0"
428 ngValue=
"">-- No erasure compression algorithm available --
</option>
429 <option *
ngFor=
"let algorithm of info.compression_algorithms"
437 <!-- Compression min blob size -->
438 <div class=
"form-group row">
440 class=
"cd-col-form-label"
441 for=
"minBlobSize">Minimum blob size
</label>
442 <div class=
"cd-col-form-input">
443 <input id=
"minBlobSize"
445 formControlName=
"minBlobSize"
450 placeholder=
"e.g., 128KiB"
453 <span class=
"invalid-feedback"
454 *
ngIf=
"form.showError('minBlobSize', formDir, 'min')"
455 i18n
>Value should be greater than
0</span>
456 <span class=
"invalid-feedback"
457 *
ngIf=
"form.showError('minBlobSize', formDir, 'maximum')"
458 i18n
>Value should be less than the maximum blob size
</span>
462 <!-- Compression max blob size -->
463 <div class=
"form-group row">
465 class=
"cd-col-form-label"
466 for=
"maxBlobSize">Maximum blob size
</label>
467 <div class=
"cd-col-form-input">
468 <input id=
"maxBlobSize"
471 formControlName=
"maxBlobSize"
474 placeholder=
"e.g., 512KiB"
477 <span class=
"invalid-feedback"
478 *
ngIf=
"form.showError('maxBlobSize', formDir, 'min')"
479 i18n
>Value should be greater than
0</span>
480 <span class=
"invalid-feedback"
481 *
ngIf=
"form.showError('maxBlobSize', formDir, 'minimum')"
482 i18n
>Value should be greater than the minimum blob size
</span>
486 <!-- Compression ratio -->
487 <div class=
"form-group row">
489 class=
"cd-col-form-label"
490 for=
"ratio">Ratio
</label>
491 <div class=
"cd-col-form-input">
494 formControlName=
"ratio"
501 placeholder=
"Compression ratio">
502 <span class=
"invalid-feedback"
503 *
ngIf=
"form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
504 i18n
>Value should be between
0.0 and
1.0</span>
513 <legend i18n
>Quotas
</legend>
516 <div class=
"form-group row">
517 <label class=
"cd-col-form-label"
519 <ng-container i18n
>Max bytes
</ng-container>
521 <span i18n
>Leave it blank or specify
0 to disable this quota.
</span>
523 <span i18n
>A valid quota should be greater than
0.
</span>
526 <div class=
"cd-col-form-input">
527 <input class=
"form-control"
531 formControlName=
"max_bytes"
533 placeholder=
"e.g., 10GiB"
540 <div class=
"form-group row">
541 <label class=
"cd-col-form-label"
543 <ng-container i18n
>Max objects
</ng-container>
545 <span i18n
>Leave it blank or specify
0 to disable this quota.
</span>
547 <span i18n
>A valid quota should be greater than
0.
</span>
550 <div class=
"cd-col-form-input">
551 <input class=
"form-control"
556 formControlName=
"max_objects">
557 <span class=
"invalid-feedback"
558 *
ngIf=
"form.showError('max_objects', formDir, 'min')"
559 i18n
>The value should be greater or equal to
0</span>
564 <!-- Pool configuration -->
565 <div [hidden]=
"isErasure || data.applications.selected.indexOf('rbd') === -1">
566 <cd-rbd-configuration-form [form]=
"form"
567 [initializeData]=
"initializeConfigData"
568 (changes)=
"currentConfigurationValues = $event()">
569 </cd-rbd-configuration-form>
572 <div class=
"card-footer">
573 <div class=
"button-group text-right">
574 <cd-submit-button [form]=
"formDir"
575 i18n=
"form action button|Example: Create Pool@@formActionButton"
576 (submitAction)=
"submit()">{{ action | titlecase }} {{ resource | upperFirst }}
578 <cd-back-button></cd-back-button>