-<div class="col-sm-12 col-lg-6">
- <h1 *ngIf="!(info && ecProfiles)"
- class="jumbotron">
- <i class="fa fa-lg fa-pulse fa-spinner text-primary"></i>
- <ng-container i18n>Loading...</ng-container>
- </h1>
+<cd-loading-panel *ngIf="!(info && ecProfiles)"
+ i18n>Loading...</cd-loading-panel>
+
+<div class="cd-col-form">
<form name="form"
*ngIf="info && ecProfiles"
- class="form-horizontal"
#formDir="ngForm"
[formGroup]="form"
novalidate>
- <div class="panel panel-default">
- <div class="panel-heading">
- <h3 i18n="form title|Example: Create Pool@@formTitle"
- class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
- </div>
+ <div class="card">
+ <div i18n="form title|Example: Create Pool@@formTitle"
+ class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div>
- <div class="panel-body">
+ <div class="card-body">
<!-- Name -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('name', formDir)}">
- <label class="control-label col-sm-3"
- for="name">
- <ng-container i18n>Name</ng-container>
- <span class="required"></span>
- </label>
- <div class="col-sm-9">
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="name"
+ i18n>Name</label>
+ <div class="cd-col-form-input">
<input id="name"
name="name"
type="text"
i18n-placeholder
formControlName="name"
autofocus>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', formDir, 'required')"
i18n>This field is required!</span>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('name', formDir, 'uniqueName')"
i18n>The chosen Ceph pool name is already in use.</span>
+ <span *ngIf="form.showError('name', formDir, 'rbdPool')"
+ class="invalid-feedback"
+ i18n>It's not possible to create an RBD pool with '/' in the name.
+ Please change the name or remove 'rbd' from the applications list.</span>
+ <span *ngIf="form.showError('name', formDir, 'pattern')"
+ class="invalid-feedback"
+ i18n>Pool name can only contain letters, numbers, '.', '-', '_' or '/'.</span>
</div>
</div>
<!-- Pool type selection -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('poolType', formDir)}">
- <label class="control-label col-sm-3"
- for="poolType">
- <ng-container i18n>Pool type</ng-container>
- <span class="required"></span>
- </label>
- <div class="col-sm-9">
- <select class="form-control"
+ <div class="form-group row">
+ <label class="cd-col-form-label required"
+ for="poolType"
+ i18n>Pool type</label>
+ <div class="cd-col-form-input">
+ <select class="form-control custom-select"
id="poolType"
formControlName="poolType"
name="poolType">
{{ poolType }}
</option>
</select>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('poolType', formDir, 'required')"
i18n>This field is required!</span>
</div>
</div>
- <div *ngIf="form.getValue('poolType')">
+ <div *ngIf="isReplicated || isErasure">
+ <!-- PG Autoscale Mode -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="pgAutoscaleMode">PG Autoscale</label>
+ <div class="cd-col-form-input">
+ <select class="form-control custom-select"
+ id="pgAutoscaleMode"
+ name="pgAutoscaleMode"
+ formControlName="pgAutoscaleMode">
+ <option *ngFor="let mode of pgAutoscaleModes"
+ [value]="mode">
+ {{ mode }}
+ </option>
+ </select>
+ </div>
+ </div>
+
<!-- Pg number -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('pgNum', formDir)}">
- <label class="control-label col-sm-3"
- for="pgNum">
- <ng-container i18n>Placement groups</ng-container>
- <span class="required"></span>
- </label>
- <div class="col-sm-9">
+ <div class="form-group row"
+ *ngIf="form.getValue('pgAutoscaleMode') !== 'on'">
+ <label class="cd-col-form-label required"
+ for="pgNum"
+ i18n>Placement groups</label>
+ <div class="cd-col-form-input">
<input class="form-control"
id="pgNum"
name="pgNum"
(focus)="externalPgChange = false"
(blur)="alignPgs()"
required>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, 'required')"
i18n>This field is required!</span>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, 'min')"
i18n>At least one placement group is needed!</span>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('pgNum', formDir, '34')"
i18n>Your cluster can't handle this many PGs. Please recalculate the PG amount needed.</span>
- <span class="help-block"
- *ngIf="form.showError('pgNum', formDir, 'noDecrease')"
- i18n>You can only increase the number of PGs of an existing pool.
- Currently your pool has {{ data.pool.pg_num }} PGs.</span>
- <span class="help-block">
+ <span class="form-text text-muted">
<a i18n
target="_blank"
href="http://ceph.com/pgcalc">Calculation help</a>
</span>
- <span class="help-block"
+ <span class="form-text text-muted"
*ngIf="externalPgChange"
i18n>The current PGs settings were calculated for you, you
- should make sure the values suit your needs before submit.</span>
- </div>
- </div>
-
- <!-- Crush ruleset selection -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('crushRule', formDir)}"
- *ngIf="form.getValue('poolType') && current.rules.length > 0">
- <label class="control-label col-sm-3"
- for="crushRule"
- i18n>Crush ruleset</label>
- <div class="col-sm-9">
- <div class="input-group">
- <select class="form-control"
- id="crushRule"
- formControlName="crushRule"
- name="crushSet">
- <option [ngValue]="null"
- i18n>-- Select a crush rule --</option>
- <option *ngFor="let rule of current.rules"
- [ngValue]="rule">
- {{ rule.rule_name }}
- </option>
- </select>
- <span class="input-group-btn">
- <button class="btn btn-default"
- [ngClass]="{'active': data.crushInfo}"
- id="crush-info-button"
- type="button"
- (click)="data.crushInfo = !data.crushInfo">
- <i class="fa fa-question-circle"
- aria-hidden="true"></i>
- </button>
- </span>
- </div>
- <span class="help-block"
- id="crush-info-block"
- *ngIf="data.crushInfo && form.getValue('crushRule')">
- <tabset>
- <tab i18n-heading heading="Crush rule" class="crush-rule-info">
- <cd-table-key-value [renderObjects]="true"
- [data]="form.getValue('crushRule')"
- [autoReload]="false">
- </cd-table-key-value>
- </tab>
- <tab i18n-heading heading="Crush steps" class="crush-rule-steps">
- <ol>
- <li *ngFor="let step of form.get('crushRule').value.steps">
- {{ describeCrushStep(step) }}
- </li>
- </ol>
- </tab>
- </tabset>
- </span>
- <span class="help-block"
- *ngIf="form.showError('crushRule', formDir, 'tooFewOsds')"
- i18n>The rule can't be used in the current cluster as it has
- to few OSDs to meet the minimum required OSD by this rule.</span>
+ should make sure the values suit your needs before submit.</span>
</div>
</div>
<!-- Replica Size -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('size', formDir)}"
- *ngIf="form.getValue('poolType') === 'replicated'">
- <label class="control-label col-sm-3"
- for="size">
- <ng-container i18n>Replicated size</ng-container>
- <span class="required"></span>
- </label>
- <div class="col-sm-9">
+ <div class="form-group row"
+ *ngIf="isReplicated">
+ <label class="cd-col-form-label required"
+ for="size"
+ i18n>Replicated size</label>
+ <div class="cd-col-form-input">
<input class="form-control"
id="size"
[max]="getMaxSize()"
name="size"
type="number"
formControlName="size">
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('size', formDir)">
<ul class="list-inline">
<li i18n>Minimum: {{ getMinSize() }}</li>
<li i18n>Maximum: {{ getMaxSize() }}</li>
</ul>
</span>
- <span class="help-block"
+ <span class="invalid-feedback"
*ngIf="form.showError('size', formDir)"
i18n>The size specified is out of range. A value from
- {{ getMinSize() }} to {{ getMaxSize() }} is valid.</span>
+ {{ getMinSize() }} to {{ getMaxSize() }} is valid.</span>
</div>
</div>
+ <!-- Flags -->
+ <div class="form-group row"
+ *ngIf="info.is_all_bluestore && isErasure">
+ <label i18n
+ class="cd-col-form-label">Flags</label>
+ <div class="cd-col-form-input">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox"
+ class="custom-control-input"
+ id="ec-overwrites"
+ formControlName="ecOverwrites">
+ <label class="custom-control-label"
+ for="ec-overwrites"
+ i18n>EC Overwrites</label>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <!-- Applications -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="applications">Applications</label>
+ <div class="cd-col-form-input">
+ <cd-select-badges id="applications"
+ [customBadges]="true"
+ [customBadgeValidators]="data.applications.validators"
+ [messages]="data.applications.messages"
+ [data]="data.applications.selected"
+ [options]="data.applications.available"
+ [selectionLimit]="4"
+ (selection)="appSelection()">
+ </cd-select-badges>
+ </div>
+ </div>
+
+ <!-- CRUSH -->
+ <div *ngIf="isErasure || isReplicated">
+
+ <legend i18n>CRUSH</legend>
+
<!-- Erasure Profile select -->
- <div class="form-group"
- *ngIf="form.getValue('poolType') === 'erasure'">
+ <div class="form-group row"
+ *ngIf="isErasure">
<label i18n
- class="control-label col-sm-3"
+ class="cd-col-form-label"
for="erasureProfile">Erasure code profile</label>
- <div class="col-sm-9">
+ <div class="cd-col-form-input">
<div class="input-group">
- <select class="form-control"
+ <select class="form-control custom-select"
id="erasureProfile"
name="erasureProfile"
formControlName="erasureProfile">
{{ ecp.name }}
</option>
</select>
- <span class="input-group-btn">
- <button class="btn btn-default"
+ <span class="input-group-append">
+ <button class="btn btn-light"
[ngClass]="{'active': data.erasureInfo}"
id="ecp-info-button"
type="button"
(click)="data.erasureInfo = !data.erasureInfo">
- <i class="fa fa-question-circle"
+ <i [ngClass]="[icons.questionCircle]"
aria-hidden="true"></i>
</button>
- <button class="btn btn-default"
+ <button class="btn btn-light"
type="button"
- [disabled]="editing"
+ *ngIf="!editing"
(click)="addErasureCodeProfile()">
- <i class="fa fa-plus"
+ <i [ngClass]="[icons.add]"
aria-hidden="true"></i>
</button>
- <button class="btn btn-default"
+ <button class="btn btn-light"
type="button"
- (click)="deleteErasureCodeProfile()"
- [disabled]="editing || ecProfiles.length < 1">
- <i class="fa fa-trash-o"
+ *ngIf="!editing"
+ tooltip="This profile can't be deleted as it is in use."
+ i18n-tooltip
+ triggers=""
+ #ecpDeletionBtn="bs-tooltip"
+ (click)="deleteErasureCodeProfile()">
+ <i [ngClass]="[icons.trash]"
aria-hidden="true"></i>
</button>
</span>
</div>
- <span class="help-block"
+ <span class="form-text text-muted"
id="ecp-info-block"
*ngIf="data.erasureInfo && form.getValue('erasureProfile')">
- <cd-table-key-value [renderObjects]="true"
- [data]="form.getValue('erasureProfile')"
- [autoReload]="false">
- </cd-table-key-value>
+ <tabset #ecpInfoTabs>
+ <tab i18n-heading
+ heading="Profile"
+ class="ecp-info">
+ <cd-table-key-value [renderObjects]="true"
+ [data]="form.getValue('erasureProfile')"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ <tab i18n-heading
+ heading="Used by pools"
+ class="used-by-pools">
+ <ng-template #ecpIsNotUsed>
+ <span i18n>Profile is not in use.</span>
+ </ng-template>
+ <ul *ngIf="ecpUsage; else ecpIsNotUsed">
+ <li *ngFor="let pool of ecpUsage">
+ {{ pool }}
+ </li>
+ </ul>
+ </tab>
+ </tabset>
</span>
</div>
</div>
- <!-- Flags -->
- <div class="form-group"
- *ngIf="info.is_all_bluestore && form.getValue('poolType') === 'erasure'">
- <label i18n
- class="control-label col-sm-3">Flags</label>
- <div class="col-sm-9">
- <div class="input-group">
- <div class="checkbox checkbox-primary">
- <input id="ec-overwrites"
- type="checkbox"
- formControlName="ecOverwrites">
- <label for="ec-overwrites"
- i18n>EC Overwrites</label>
+ <!-- Crush ruleset selection -->
+ <div class="form-group row"
+ *ngIf="isErasure && !editing">
+ <label class="cd-col-form-label"
+ for="crushRule"
+ i18n>Crush ruleset</label>
+ <div class="cd-col-form-input">
+ <span class="form-text text-muted"
+ i18n>A new crush ruleset will be implicitly created.</span>
+ </div>
+ </div>
+ <div class="form-group row"
+ *ngIf="isReplicated || editing">
+ <label class="cd-col-form-label"
+ for="crushRule"
+ i18n>Crush ruleset</label>
+ <div class="cd-col-form-input">
+ <ng-template #noRules>
+ <span class="form-text text-muted">
+ <span i18n>There are no rules.</span>
+ </span>
+ </ng-template>
+ <div *ngIf="current.rules.length > 0; else noRules">
+ <div class="input-group">
+ <select class="form-control custom-select"
+ id="crushRule"
+ formControlName="crushRule"
+ name="crushSet">
+ <option [ngValue]="null"
+ i18n>-- Select a crush rule --</option>
+ <option *ngFor="let rule of current.rules"
+ [ngValue]="rule">
+ {{ rule.rule_name }}
+ </option>
+ </select>
+ <span class="input-group-append">
+ <button class="btn btn-light"
+ [ngClass]="{'active': data.crushInfo}"
+ id="crush-info-button"
+ type="button"
+ (click)="data.crushInfo = !data.crushInfo">
+ <i [ngClass]="[icons.questionCircle]"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-light"
+ type="button"
+ *ngIf="isReplicated && !editing"
+ (click)="addCrushRule()">
+ <i [ngClass]="[icons.add]"
+ aria-hidden="true"></i>
+ </button>
+ <button class="btn btn-light"
+ *ngIf="isReplicated && !editing"
+ type="button"
+ tooltip="This rule can't be deleted as it is in use."
+ i18n-tooltip
+ triggers=""
+ #crushDeletionBtn="bs-tooltip"
+ (click)="deleteCrushRule()">
+ <i [ngClass]="[icons.trash]"
+ aria-hidden="true"></i>
+ </button>
+ </span>
</div>
+ <span class="form-text text-muted"
+ id="crush-info-block"
+ *ngIf="data.crushInfo && form.getValue('crushRule')">
+ <tabset #crushInfoTabs>
+ <tab i18n-heading
+ heading="Crush rule"
+ class="crush-rule-info">
+ <cd-table-key-value [renderObjects]="true"
+ [data]="form.getValue('crushRule')"
+ [autoReload]="false">
+ </cd-table-key-value>
+ </tab>
+ <tab i18n-heading
+ heading="Crush steps"
+ class="crush-rule-steps">
+ <ol>
+ <li *ngFor="let step of form.get('crushRule').value.steps">
+ {{ describeCrushStep(step) }}
+ </li>
+ </ol>
+ </tab>
+ <tab i18n-heading
+ heading="Used by pools"
+ class="used-by-pools">
+ <ng-template #ruleIsNotUsed>
+ <span i18n>Rule is not in use.</span>
+ </ng-template>
+ <ul *ngIf="crushUsage; else ruleIsNotUsed">
+ <li *ngFor="let pool of crushUsage">
+ {{ pool }}
+ </li>
+ </ul>
+ </tab>
+ </tabset>
+ </span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('crushRule', formDir, 'required')"
+ i18n>This field is required!</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('crushRule', formDir, 'tooFewOsds')"
+ i18n>The rule can't be used in the current cluster as it has
+ too few OSDs to meet the minimum required OSD by this rule.</span>
</div>
</div>
</div>
- </div>
- <!-- Applications -->
- <div class="form-group">
- <label i18n
- class="col-sm-3 control-label"
- for="applications">Applications</label>
- <div class="col-sm-9">
- <span class="form-control no-border full-height">
- <cd-select-badges id="applications"
- [customBadges]="true"
- [customBadgeValidators]="data.applications.validators"
- [messages]="data.applications.messages"
- [data]="data.applications.selected"
- [options]="data.applications.available"
- [selectionLimit]="4"
- (selection)="appSelection()">
- </cd-select-badges>
- </span>
- </div>
</div>
- <!-- Compression -->
- <div *ngIf="info.is_all_bluestore"
- formGroupName="compression">
- <legend i18n>Compression</legend>
+ <!-- Compression -->
+ <div *ngIf="info.is_all_bluestore"
+ formGroupName="compression">
+ <legend i18n>Compression</legend>
- <!-- Compression Mode -->
- <div class="form-group">
+ <!-- Compression Mode -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="mode">Mode</label>
+ <div class="cd-col-form-input">
+ <select class="form-control custom-select"
+ id="mode"
+ name="mode"
+ formControlName="mode">
+ <option *ngFor="let mode of info.compression_modes"
+ [value]="mode">
+ {{ mode }}
+ </option>
+ </select>
+ </div>
+ </div>
+ <div *ngIf="hasCompressionEnabled()">
+ <!-- Compression algorithm selection -->
+ <div class="form-group row">
<label i18n
- class="control-label col-sm-3"
- for="mode">Mode</label>
- <div class="col-sm-9">
- <select class="form-control"
- id="mode"
- name="mode"
- formControlName="mode">
- <option *ngFor="let mode of info.compression_modes"
- [value]="mode">
- {{ mode }}
+ class="cd-col-form-label"
+ for="algorithm">Algorithm</label>
+ <div class="cd-col-form-input">
+ <select class="form-control custom-select"
+ id="algorithm"
+ name="algorithm"
+ formControlName="algorithm">
+ <option *ngIf="!info.compression_algorithms"
+ ngValue=""
+ i18n>Loading...</option>
+ <option *ngIf="info.compression_algorithms && info.compression_algorithms.length === 0"
+ i18n
+ ngValue="">-- No erasure compression algorithm available --</option>
+ <option *ngFor="let algorithm of info.compression_algorithms"
+ [value]="algorithm">
+ {{ algorithm }}
</option>
</select>
</div>
</div>
- <div *ngIf="hasCompressionEnabled()">
- <!-- Compression algorithm selection -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('algorithm', formDir)}">
- <label i18n
- class="control-label col-sm-3"
- for="algorithm">Algorithm</label>
- <div class="col-sm-9">
- <select class="form-control"
- id="algorithm"
- name="algorithm"
- formControlName="algorithm">
- <option *ngIf="!info.compression_algorithms"
- ngValue=""
- i18n>Loading...</option>
- <option *ngIf="info.compression_algorithms && info.compression_algorithms.length === 0"
- i18n
- ngValue="">-- No erasure compression algorithm available --</option>
- <option *ngFor="let algorithm of info.compression_algorithms"
- [value]="algorithm">
- {{ algorithm }}
- </option>
- </select>
- </div>
- </div>
- <!-- Compression min blob size -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('minBlobSize', formDir)}">
- <label i18n
- class="control-label col-sm-3"
- for="minBlobSize">Minimum blob size</label>
- <div class="col-sm-9">
- <input id="minBlobSize"
- name="minBlobSize"
- formControlName="minBlobSize"
- type="text"
- min="0"
- class="form-control"
- i18n-placeholder
- placeholder="e.g., 128KiB"
- defaultUnit="KiB"
- cdDimlessBinary>
- <span class="help-block"
- *ngIf="form.showError('minBlobSize', formDir, 'min')"
- i18n>Value should be greater than 0</span>
- <span class="help-block"
- *ngIf="form.showError('minBlobSize', formDir, 'maximum')"
- i18n>Value should be greater than the maximum blob size</span>
- </div>
+ <!-- Compression min blob size -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="minBlobSize">Minimum blob size</label>
+ <div class="cd-col-form-input">
+ <input id="minBlobSize"
+ name="minBlobSize"
+ formControlName="minBlobSize"
+ type="text"
+ min="0"
+ class="form-control"
+ i18n-placeholder
+ placeholder="e.g., 128KiB"
+ defaultUnit="KiB"
+ cdDimlessBinary>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('minBlobSize', formDir, 'min')"
+ i18n>Value should be greater than 0</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('minBlobSize', formDir, 'maximum')"
+ i18n>Value should be less than the maximum blob size</span>
</div>
+ </div>
- <!-- Compression max blob size -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('maxBlobSize', formDir)}">
- <label i18n
- class="control-label col-sm-3"
- for="maxBlobSize">Maximum blob size</label>
- <div class="col-sm-9">
- <input id="maxBlobSize"
- type="text"
- min="0"
- formControlName="maxBlobSize"
- class="form-control"
- i18n-placeholder
- placeholder="e.g., 512KiB"
- defaultUnit="KiB"
- cdDimlessBinary>
- <span class="help-block"
- *ngIf="form.showError('maxBlobSize', formDir, 'min')"
- i18n>Value should be greater than 0</span>
- <span class="help-block"
- *ngIf="form.showError('maxBlobSize', formDir, 'minimum')"
- i18n>Value should be greater than the minimum blob size</span>
- </div>
+ <!-- Compression max blob size -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="maxBlobSize">Maximum blob size</label>
+ <div class="cd-col-form-input">
+ <input id="maxBlobSize"
+ type="text"
+ min="0"
+ formControlName="maxBlobSize"
+ class="form-control"
+ i18n-placeholder
+ placeholder="e.g., 512KiB"
+ defaultUnit="KiB"
+ cdDimlessBinary>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('maxBlobSize', formDir, 'min')"
+ i18n>Value should be greater than 0</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('maxBlobSize', formDir, 'minimum')"
+ i18n>Value should be greater than the minimum blob size</span>
</div>
+ </div>
- <!-- Compression ratio -->
- <div class="form-group"
- [ngClass]="{'has-error': form.showError('ratio', formDir)}">
- <label i18n
- class="control-label col-sm-3"
- for="ratio">Ratio</label>
- <div class="col-sm-9">
- <input id="ratio"
- name="ratio"
- formControlName="ratio"
- type="number"
- min="0"
- max="1"
- step="0.1"
- class="form-control"
- i18n-placeholder
- placeholder="Compression ratio">
- <span class="help-block"
- *ngIf="form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
- i18n>Value should be between 0.0 and 1.0</span>
- </div>
+ <!-- Compression ratio -->
+ <div class="form-group row">
+ <label i18n
+ class="cd-col-form-label"
+ for="ratio">Ratio</label>
+ <div class="cd-col-form-input">
+ <input id="ratio"
+ name="ratio"
+ formControlName="ratio"
+ type="number"
+ min="0"
+ max="1"
+ step="0.1"
+ class="form-control"
+ i18n-placeholder
+ placeholder="Compression ratio">
+ <span class="invalid-feedback"
+ *ngIf="form.showError('ratio', formDir, 'min') || form.showError('ratio', formDir, 'max')"
+ i18n>Value should be between 0.0 and 1.0</span>
</div>
+ </div>
+
+ </div>
+ </div>
+ <!-- Quotas -->
+ <div>
+ <legend i18n>Quotas</legend>
+
+ <!-- Max Bytes -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="max_bytes">
+ <ng-container i18n>Max bytes</ng-container>
+ <cd-helper>
+ <span i18n>Leave it blank or specify 0 to disable this quota.</span>
+ <br>
+ <span i18n>A valid quota should be greater than 0.</span>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ id="max_bytes"
+ name="max_bytes"
+ type="text"
+ formControlName="max_bytes"
+ i18n-placeholder
+ placeholder="e.g., 10GiB"
+ defaultUnit="GiB"
+ cdDimlessBinary>
</div>
</div>
+ <!-- Max Objects -->
+ <div class="form-group row">
+ <label class="cd-col-form-label"
+ for="max_objects">
+ <ng-container i18n>Max objects</ng-container>
+ <cd-helper>
+ <span i18n>Leave it blank or specify 0 to disable this quota.</span>
+ <br>
+ <span i18n>A valid quota should be greater than 0.</span>
+ </cd-helper>
+ </label>
+ <div class="cd-col-form-input">
+ <input class="form-control"
+ id="max_objects"
+ min="0"
+ name="max_objects"
+ type="number"
+ formControlName="max_objects">
+ <span class="invalid-feedback"
+ *ngIf="form.showError('max_objects', formDir, 'min')"
+ i18n>The value should be greater or equal to 0</span>
+ </div>
+ </div>
+ </div>
+
<!-- Pool configuration -->
- <div [hidden]="form.get('poolType').value !== 'replicated' || data.applications.selected.indexOf('rbd') === -1">
+ <div [hidden]="isErasure || data.applications.selected.indexOf('rbd') === -1">
<cd-rbd-configuration-form [form]="form"
[initializeData]="initializeConfigData"
(changes)="currentConfigurationValues = $event()">
</cd-rbd-configuration-form>
</div>
-
- <div class="form-group has-error">
- <div class="col-sm-offset-3 col-sm-9"
- *ngIf="form.hasError('rbdPool')">
- <br>
- <span class="help-block"
- i18n>It's not possible to create an RBD pool with '/' in the name.</span>
- <span class="help-block"
- i18n>Please change the name or remove 'rbd' from the applications list.</span>
- </div>
- </div>
</div>
- <div class="panel-footer">
+ <div class="card-footer">
<div class="button-group text-right">
- <cd-submit-button
- [form]="formDir"
- type="button"
- i18n="form action button|Example: Create Pool@@formActionButton"
- (submitAction)="submit()">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
+ <cd-submit-button [form]="formDir"
+ i18n="form action button|Example: Create Pool@@formActionButton"
+ (submitAction)="submit()">{{ action | titlecase }} {{ resource | upperFirst }}
+ </cd-submit-button>
<cd-back-button></cd-back-button>
</div>
</div>