]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | <div class="cd-col-form" |
2 | *cdFormLoading="loading"> | |
11fdf7f2 | 3 | <form name="rbdForm" |
11fdf7f2 TL |
4 | #formDir="ngForm" |
5 | [formGroup]="rbdForm" | |
6 | novalidate> | |
9f95a23c | 7 | <div class="card"> |
a4b75251 | 8 | <div i18n="form title" |
9f95a23c TL |
9 | class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div> |
10 | <div class="card-body"> | |
11fdf7f2 TL |
11 | |
12 | <!-- Parent --> | |
9f95a23c | 13 | <div class="form-group row" |
11fdf7f2 TL |
14 | *ngIf="rbdForm.getValue('parent')"> |
15 | <label i18n | |
9f95a23c | 16 | class="cd-col-form-label" |
11fdf7f2 | 17 | for="name">{{ action | titlecase }} from</label> |
9f95a23c | 18 | <div class="cd-col-form-input"> |
11fdf7f2 TL |
19 | <input class="form-control" |
20 | type="text" | |
21 | id="parent" | |
22 | name="parent" | |
23 | formControlName="parent"> | |
24 | <hr> | |
25 | </div> | |
26 | </div> | |
27 | ||
28 | <!-- Name --> | |
9f95a23c TL |
29 | <div class="form-group row"> |
30 | <label class="cd-col-form-label required" | |
31 | for="name" | |
32 | i18n>Name</label> | |
33 | <div class="cd-col-form-input"> | |
11fdf7f2 TL |
34 | <input class="form-control" |
35 | type="text" | |
36 | placeholder="Name..." | |
37 | id="name" | |
38 | name="name" | |
39 | formControlName="name" | |
40 | autofocus> | |
9f95a23c | 41 | <span class="invalid-feedback" |
11fdf7f2 TL |
42 | *ngIf="rbdForm.showError('name', formDir, 'required')"> |
43 | <ng-container i18n>This field is required.</ng-container> | |
44 | </span> | |
9f95a23c | 45 | <span class="invalid-feedback" |
11fdf7f2 TL |
46 | *ngIf="rbdForm.showError('name', formDir, 'pattern')"> |
47 | <ng-container i18n>'/' and '@' are not allowed.</ng-container> | |
48 | </span> | |
49 | </div> | |
50 | </div> | |
51 | ||
52 | <!-- Pool --> | |
9f95a23c | 53 | <div class="form-group row" |
11fdf7f2 | 54 | (change)="onPoolChange($event.target.value)"> |
9f95a23c TL |
55 | <label class="cd-col-form-label" |
56 | [ngClass]="{'required': mode !== 'editing'}" | |
57 | for="pool" | |
58 | i18n>Pool</label> | |
59 | <div class="cd-col-form-input"> | |
11fdf7f2 TL |
60 | <input class="form-control" |
61 | type="text" | |
62 | placeholder="Pool name..." | |
63 | id="pool" | |
64 | name="pool" | |
65 | formControlName="pool" | |
66 | *ngIf="mode === 'editing' || !poolPermission.read"> | |
67 | <select id="pool" | |
68 | name="pool" | |
39ae355f | 69 | class="form-select" |
11fdf7f2 | 70 | formControlName="pool" |
2a845540 TL |
71 | *ngIf="mode !== 'editing' && poolPermission.read" |
72 | (change)="setPoolMirrorMode()"> | |
11fdf7f2 TL |
73 | <option *ngIf="pools === null" |
74 | [ngValue]="null" | |
75 | i18n>Loading...</option> | |
76 | <option *ngIf="pools !== null && pools.length === 0" | |
77 | [ngValue]="null" | |
78 | i18n>-- No rbd pools available --</option> | |
79 | <option *ngIf="pools !== null && pools.length > 0" | |
80 | [ngValue]="null" | |
81 | i18n>-- Select a pool --</option> | |
82 | <option *ngFor="let pool of pools" | |
83 | [value]="pool.pool_name">{{ pool.pool_name }}</option> | |
84 | </select> | |
85 | <span *ngIf="rbdForm.showError('pool', formDir, 'required')" | |
9f95a23c | 86 | class="invalid-feedback" |
11fdf7f2 TL |
87 | i18n>This field is required.</span> |
88 | </div> | |
89 | </div> | |
90 | ||
9f95a23c TL |
91 | <!-- Namespace --> |
92 | <div class="form-group row" | |
93 | *ngIf="mode !== 'editing' && rbdForm.getValue('pool') && namespaces === null"> | |
94 | <div class="cd-col-form-offset"> | |
95 | <i [ngClass]="[icons.spinner, icons.spin]"></i> | |
96 | </div> | |
97 | </div> | |
98 | <div class="form-group row" | |
99 | *ngIf="(mode === 'editing' && rbdForm.getValue('namespace')) || mode !== 'editing' && (namespaces && namespaces.length > 0 || !poolPermission.read)"> | |
100 | <label class="cd-col-form-label" | |
101 | for="pool"> | |
102 | Namespace | |
103 | </label> | |
104 | <div class="cd-col-form-input"> | |
105 | <input class="form-control" | |
106 | type="text" | |
107 | placeholder="Namespace..." | |
108 | id="namespace" | |
109 | name="namespace" | |
110 | formControlName="namespace" | |
111 | *ngIf="mode === 'editing' || !poolPermission.read"> | |
112 | <select id="namespace" | |
113 | name="namespace" | |
39ae355f | 114 | class="form-select" |
9f95a23c TL |
115 | formControlName="namespace" |
116 | *ngIf="mode !== 'editing' && poolPermission.read"> | |
117 | <option *ngIf="pools === null" | |
118 | [ngValue]="null" | |
119 | i18n>Loading...</option> | |
120 | <option *ngIf="pools !== null && pools.length === 0" | |
121 | [ngValue]="null" | |
122 | i18n>-- No namespaces available --</option> | |
123 | <option *ngIf="pools !== null && pools.length > 0" | |
124 | [ngValue]="null" | |
125 | i18n>-- Select a namespace --</option> | |
126 | <option *ngFor="let namespace of namespaces" | |
127 | [value]="namespace">{{ namespace }}</option> | |
128 | </select> | |
129 | </div> | |
130 | </div> | |
131 | ||
11fdf7f2 | 132 | <!-- Use a dedicated pool --> |
9f95a23c TL |
133 | <div class="form-group row"> |
134 | <div class="cd-col-form-offset"> | |
135 | <div class="custom-control custom-checkbox"> | |
11fdf7f2 | 136 | <input type="checkbox" |
9f95a23c | 137 | class="custom-control-input" |
11fdf7f2 TL |
138 | id="useDataPool" |
139 | name="useDataPool" | |
140 | formControlName="useDataPool" | |
141 | (change)="onUseDataPoolChange()"> | |
9f95a23c TL |
142 | <label class="custom-control-label" |
143 | for="useDataPool" | |
144 | i18n>Use a dedicated data pool</label> | |
f67539c2 TL |
145 | <cd-helper *ngIf="allDataPools.length <= 1"> |
146 | <span i18n>You need more than one pool with the rbd application label use to use a dedicated data pool.</span> | |
147 | </cd-helper> | |
11fdf7f2 TL |
148 | </div> |
149 | </div> | |
150 | </div> | |
151 | ||
152 | <!-- Data Pool --> | |
9f95a23c | 153 | <div class="form-group row" |
11fdf7f2 | 154 | *ngIf="rbdForm.getValue('useDataPool')"> |
9f95a23c | 155 | <label class="cd-col-form-label" |
11fdf7f2 | 156 | for="dataPool"> |
9f95a23c TL |
157 | <span [ngClass]="{'required': mode !== 'editing'}" |
158 | i18n>Data pool</span> | |
11fdf7f2 TL |
159 | <cd-helper i18n-html |
160 | html="Dedicated pool that stores the object-data of the RBD."> | |
161 | </cd-helper> | |
162 | </label> | |
9f95a23c | 163 | <div class="cd-col-form-input"> |
11fdf7f2 TL |
164 | <input class="form-control" |
165 | type="text" | |
166 | placeholder="Data pool name..." | |
167 | id="dataPool" | |
168 | name="dataPool" | |
169 | formControlName="dataPool" | |
170 | *ngIf="mode === 'editing' || !poolPermission.read"> | |
171 | <select id="dataPool" | |
172 | name="dataPool" | |
39ae355f | 173 | class="form-select" |
11fdf7f2 TL |
174 | formControlName="dataPool" |
175 | (change)="onDataPoolChange($event.target.value)" | |
176 | *ngIf="mode !== 'editing' && poolPermission.read"> | |
177 | <option *ngIf="dataPools === null" | |
178 | [ngValue]="null" | |
179 | i18n>Loading...</option> | |
180 | <option *ngIf="dataPools !== null && dataPools.length === 0" | |
181 | [ngValue]="null" | |
182 | i18n>-- No data pools available --</option> | |
183 | <option *ngIf="dataPools !== null && dataPools.length > 0" | |
184 | [ngValue]="null">-- Select a data pool -- | |
185 | </option> | |
186 | <option *ngFor="let dataPool of dataPools" | |
187 | [value]="dataPool.pool_name">{{ dataPool.pool_name }}</option> | |
188 | </select> | |
9f95a23c | 189 | <span class="invalid-feedback" |
11fdf7f2 TL |
190 | *ngIf="rbdForm.showError('dataPool', formDir, 'required')" |
191 | i18n>This field is required.</span> | |
192 | </div> | |
193 | </div> | |
194 | ||
195 | <!-- Size --> | |
9f95a23c TL |
196 | <div class="form-group row"> |
197 | <label class="cd-col-form-label required" | |
198 | for="size" | |
199 | i18n>Size</label> | |
200 | <div class="cd-col-form-input"> | |
11fdf7f2 TL |
201 | <input id="size" |
202 | name="size" | |
203 | class="form-control" | |
204 | type="text" | |
205 | formControlName="size" | |
206 | i18n-placeholder | |
207 | placeholder="e.g., 10GiB" | |
208 | defaultUnit="GiB" | |
209 | cdDimlessBinary> | |
9f95a23c | 210 | <span class="invalid-feedback" |
11fdf7f2 TL |
211 | *ngIf="rbdForm.showError('size', formDir, 'required')" |
212 | i18n>This field is required.</span> | |
9f95a23c | 213 | <span class="invalid-feedback" |
11fdf7f2 TL |
214 | *ngIf="rbdForm.showError('size', formDir, 'invalidSizeObject')" |
215 | i18n>You have to increase the size.</span> | |
216 | </div> | |
217 | </div> | |
218 | ||
219 | <!-- Features --> | |
9f95a23c | 220 | <div class="form-group row" |
11fdf7f2 TL |
221 | formGroupName="features"> |
222 | <label i18n | |
9f95a23c | 223 | class="cd-col-form-label" |
11fdf7f2 | 224 | for="features">Features</label> |
9f95a23c TL |
225 | <div class="cd-col-form-input"> |
226 | <div class="custom-control custom-checkbox" | |
11fdf7f2 TL |
227 | *ngFor="let feature of featuresList"> |
228 | <input type="checkbox" | |
9f95a23c | 229 | class="custom-control-input" |
11fdf7f2 TL |
230 | id="{{ feature.key }}" |
231 | name="{{ feature.key }}" | |
232 | formControlName="{{ feature.key }}"> | |
9f95a23c TL |
233 | <label class="custom-control-label" |
234 | for="{{ feature.key }}">{{ feature.desc }}</label> | |
11fdf7f2 TL |
235 | <cd-helper *ngIf="feature.helperHtml" |
236 | html="{{ feature.helperHtml }}"> | |
237 | </cd-helper> | |
238 | </div> | |
239 | </div> | |
240 | </div> | |
241 | ||
2a845540 TL |
242 | <!-- Mirroring --> |
243 | <div class="form-group row"> | |
244 | <div class="cd-col-form-offset"> | |
245 | <div class="custom-control custom-checkbox"> | |
246 | <input type="checkbox" | |
247 | class="custom-control-input" | |
248 | id="mirroring" | |
249 | name="mirroring" | |
250 | (change)="setMirrorMode()" | |
251 | formControlName="mirroring"> | |
252 | <label class="custom-control-label" | |
253 | for="mirroring">Mirroring</label> | |
254 | <cd-helper *ngIf="mirroring === false && this.currentPoolName"> | |
255 | <span i18n>You need to enable a <b>mirror mode</b> in the selected pool. Please <a [routerLink]="['/block/mirroring', {outlets: {modal: ['edit', currentPoolName]}}]">click here to select a mode and enable it in this pool.</a></span> | |
256 | </cd-helper> | |
257 | </div> | |
258 | <div *ngIf="mirroring"> | |
39ae355f | 259 | <div class="custom-control custom-radio ms-2" |
2a845540 TL |
260 | *ngFor="let option of mirroringOptions"> |
261 | <input type="radio" | |
39ae355f | 262 | class="form-check-input" |
2a845540 TL |
263 | [id]="option" |
264 | [value]="option" | |
265 | name="mirroringMode" | |
266 | (change)="setExclusiveLock()" | |
267 | formControlName="mirroringMode" | |
268 | [attr.disabled]="(poolMirrorMode === 'pool' && option === 'snapshot') ? true : null"> | |
39ae355f | 269 | <label class="form-check-label" |
2a845540 TL |
270 | [for]="option">{{ option | titlecase }}</label> |
271 | <cd-helper *ngIf="poolMirrorMode === 'pool' && option === 'snapshot'"> | |
272 | <span i18n>You need to enable <b>image mirror mode</b> in the selected pool. Please <a [routerLink]="['/block/mirroring', {outlets: {modal: ['edit', currentPoolName]}}]">click here to select a mode and enable it in this pool.</a></span> | |
273 | </cd-helper> | |
274 | </div> | |
275 | </div> | |
276 | </div> | |
277 | </div> | |
278 | ||
279 | <div class="form-group row" | |
280 | *ngIf="rbdForm.getValue('mirroringMode') === 'snapshot' && mirroring"> | |
281 | <label class="cd-col-form-label" | |
282 | i18n>Schedule Interval | |
283 | <cd-helper i18n-html | |
39ae355f | 284 | html="Create Mirror-Snapshots automatically on a periodic basis. The interval can be specified in days, hours, or minutes using d, h, m suffix respectively. To create mirror snapshots, you must import or create and have available peers to mirror"> |
2a845540 TL |
285 | </cd-helper></label> |
286 | <div class="cd-col-form-input"> | |
287 | <input id="schedule" | |
288 | name="schedule" | |
289 | class="form-control" | |
290 | type="text" | |
291 | formControlName="schedule" | |
292 | i18n-placeholder | |
293 | placeholder="e.g., 12h or 1d or 10m" | |
39ae355f | 294 | [attr.disabled]="(peerConfigured === false) ? true : null"> |
2a845540 TL |
295 | </div> |
296 | </div> | |
297 | ||
11fdf7f2 TL |
298 | <!-- Advanced --> |
299 | <div class="row"> | |
300 | <div class="col-sm-12"> | |
39ae355f | 301 | <a class="float-end margin-right-md" |
9f95a23c | 302 | (click)="advancedEnabled = true; false" |
11fdf7f2 | 303 | *ngIf="!advancedEnabled" |
9f95a23c | 304 | href="" |
11fdf7f2 TL |
305 | i18n>Advanced...</a> |
306 | </div> | |
307 | </div> | |
9f95a23c | 308 | |
11fdf7f2 TL |
309 | <div [hidden]="!advancedEnabled"> |
310 | ||
9f95a23c TL |
311 | <legend class="cd-header" |
312 | i18n>Advanced</legend> | |
11fdf7f2 | 313 | |
9f95a23c | 314 | <div class="col-md-12"> |
f91f0fd5 TL |
315 | <h4 class="cd-header" |
316 | i18n>Striping</h4> | |
11fdf7f2 TL |
317 | |
318 | <!-- Object Size --> | |
9f95a23c | 319 | <div class="form-group row"> |
11fdf7f2 | 320 | <label i18n |
9f95a23c | 321 | class="cd-col-form-label" |
2a845540 | 322 | for="size">Object size<cd-helper>Objects in the Ceph Storage Cluster have a maximum configurable size (e.g., 2MB, 4MB, etc.). The object size should be large enough to accommodate many stripe units, and should be a multiple of the stripe unit.</cd-helper></label> |
9f95a23c | 323 | <div class="cd-col-form-input"> |
11fdf7f2 TL |
324 | <select id="obj_size" |
325 | name="obj_size" | |
39ae355f | 326 | class="form-select" |
11fdf7f2 TL |
327 | formControlName="obj_size"> |
328 | <option *ngFor="let objectSize of objectSizes" | |
329 | [value]="objectSize">{{ objectSize }}</option> | |
330 | </select> | |
331 | </div> | |
332 | </div> | |
333 | ||
9f95a23c TL |
334 | <!-- stripingUnit --> |
335 | <div class="form-group row"> | |
336 | <label class="cd-col-form-label" | |
337 | [ngClass]="{'required': rbdForm.getValue('stripingCount')}" | |
338 | for="stripingUnit" | |
2a845540 | 339 | i18n>Stripe unit<cd-helper>Stripes have a configurable unit size (e.g., 64kb). The Ceph Client divides the data it will write to objects into equally sized stripe units, except for the last stripe unit. A stripe width, should be a fraction of the Object Size so that an object may contain many stripe units.</cd-helper></label> |
9f95a23c | 340 | <div class="cd-col-form-input"> |
11fdf7f2 TL |
341 | <select id="stripingUnit" |
342 | name="stripingUnit" | |
39ae355f | 343 | class="form-select" |
11fdf7f2 TL |
344 | formControlName="stripingUnit"> |
345 | <option i18n | |
346 | [ngValue]="null">-- Select stripe unit --</option> | |
347 | <option *ngFor="let objectSize of objectSizes" | |
348 | [value]="objectSize">{{ objectSize }}</option> | |
349 | </select> | |
9f95a23c | 350 | <span class="invalid-feedback" |
11fdf7f2 TL |
351 | *ngIf="rbdForm.showError('stripingUnit', formDir, 'required')" |
352 | i18n>This field is required because stripe count is defined!</span> | |
9f95a23c | 353 | <span class="invalid-feedback" |
11fdf7f2 TL |
354 | *ngIf="rbdForm.showError('stripingUnit', formDir, 'invalidStripingUnit')" |
355 | i18n>Stripe unit is greater than object size.</span> | |
356 | </div> | |
357 | </div> | |
358 | ||
359 | <!-- Stripe Count --> | |
9f95a23c TL |
360 | <div class="form-group row"> |
361 | <label class="cd-col-form-label" | |
362 | [ngClass]="{'required': rbdForm.getValue('stripingUnit')}" | |
363 | for="stripingCount" | |
2a845540 | 364 | i18n>Stripe count<cd-helper>The Ceph Client writes a sequence of stripe units over a series of objects determined by the stripe count. The series of objects is called an object set. After the Ceph Client writes to the last object in the object set, it returns to the first object in the object set.</cd-helper></label> |
9f95a23c | 365 | <div class="cd-col-form-input"> |
11fdf7f2 TL |
366 | <input id="stripingCount" |
367 | name="stripingCount" | |
368 | formControlName="stripingCount" | |
369 | class="form-control" | |
370 | type="number"> | |
9f95a23c | 371 | <span class="invalid-feedback" |
11fdf7f2 TL |
372 | *ngIf="rbdForm.showError('stripingCount', formDir, 'required')" |
373 | i18n>This field is required because stripe unit is defined!</span> | |
9f95a23c | 374 | <span class="invalid-feedback" |
11fdf7f2 TL |
375 | *ngIf="rbdForm.showError('stripingCount', formDir, 'min')" |
376 | i18n>Stripe count must be greater than 0.</span> | |
377 | </div> | |
378 | </div> | |
379 | </div> | |
380 | ||
9f95a23c TL |
381 | <cd-rbd-configuration-form [form]="rbdForm" |
382 | [initializeData]="initializeConfigData" | |
383 | (changes)="getDirtyConfigurationValues = $event"></cd-rbd-configuration-form> | |
11fdf7f2 TL |
384 | </div> |
385 | ||
386 | </div> | |
9f95a23c | 387 | <div class="card-footer"> |
f67539c2 TL |
388 | <cd-form-button-panel (submitActionEvent)="submit()" |
389 | [form]="formDir" | |
390 | [submitText]="(action | titlecase) + ' ' + (resource | upperFirst)" | |
391 | wrappingClass="text-right"></cd-form-button-panel> | |
11fdf7f2 TL |
392 | </div> |
393 | </div> | |
394 | </form> | |
395 | </div> |