]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | import { Component, EventEmitter, OnInit } from '@angular/core'; |
2 | import { FormControl, ValidatorFn, Validators } from '@angular/forms'; | |
3 | import { ActivatedRoute, Router } from '@angular/router'; | |
4 | ||
5 | import { I18n } from '@ngx-translate/i18n-polyfill'; | |
6 | import * as _ from 'lodash'; | |
7 | import { Observable } from 'rxjs'; | |
8 | ||
9 | import { PoolService } from '../../../shared/api/pool.service'; | |
10 | import { RbdService } from '../../../shared/api/rbd.service'; | |
11 | import { ActionLabelsI18n } from '../../../shared/constants/app.constants'; | |
12 | import { CdFormGroup } from '../../../shared/forms/cd-form-group'; | |
13 | import { | |
14 | RbdConfigurationEntry, | |
15 | RbdConfigurationSourceField | |
16 | } from '../../../shared/models/configuration'; | |
17 | import { FinishedTask } from '../../../shared/models/finished-task'; | |
18 | import { Permission } from '../../../shared/models/permissions'; | |
19 | import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe'; | |
20 | import { AuthStorageService } from '../../../shared/services/auth-storage.service'; | |
21 | import { FormatterService } from '../../../shared/services/formatter.service'; | |
22 | import { TaskWrapperService } from '../../../shared/services/task-wrapper.service'; | |
23 | import { RbdFormCloneRequestModel } from './rbd-form-clone-request.model'; | |
24 | import { RbdFormCopyRequestModel } from './rbd-form-copy-request.model'; | |
25 | import { RbdFormCreateRequestModel } from './rbd-form-create-request.model'; | |
26 | import { RbdFormEditRequestModel } from './rbd-form-edit-request.model'; | |
27 | import { RbdFormMode } from './rbd-form-mode.enum'; | |
28 | import { RbdFormResponseModel } from './rbd-form-response.model'; | |
29 | ||
30 | @Component({ | |
31 | selector: 'cd-rbd-form', | |
32 | templateUrl: './rbd-form.component.html', | |
33 | styleUrls: ['./rbd-form.component.scss'] | |
34 | }) | |
35 | export class RbdFormComponent implements OnInit { | |
36 | poolPermission: Permission; | |
37 | rbdForm: CdFormGroup; | |
38 | featuresFormGroups: CdFormGroup; | |
39 | deepFlattenFormControl: FormControl; | |
40 | layeringFormControl: FormControl; | |
41 | exclusiveLockFormControl: FormControl; | |
42 | objectMapFormControl: FormControl; | |
43 | journalingFormControl: FormControl; | |
44 | fastDiffFormControl: FormControl; | |
45 | getDirtyConfigurationValues: ( | |
46 | includeLocalField?: boolean, | |
47 | localField?: RbdConfigurationSourceField | |
48 | ) => RbdConfigurationEntry[]; | |
49 | ||
50 | pools: Array<string> = null; | |
51 | allPools: Array<string> = null; | |
52 | dataPools: Array<string> = null; | |
53 | allDataPools: Array<string> = null; | |
54 | features: any; | |
55 | featuresList = []; | |
56 | initializeConfigData = new EventEmitter<{ | |
57 | initialData: RbdConfigurationEntry[]; | |
58 | sourceType: RbdConfigurationSourceField; | |
59 | }>(); | |
60 | ||
61 | pool: string; | |
62 | ||
63 | advancedEnabled = false; | |
64 | ||
65 | public rbdFormMode = RbdFormMode; | |
66 | mode: RbdFormMode; | |
67 | ||
68 | response: RbdFormResponseModel; | |
69 | snapName: string; | |
70 | ||
71 | defaultObjectSize = '4 MiB'; | |
72 | ||
73 | objectSizes: Array<string> = [ | |
74 | '4 KiB', | |
75 | '8 KiB', | |
76 | '16 KiB', | |
77 | '32 KiB', | |
78 | '64 KiB', | |
79 | '128 KiB', | |
80 | '256 KiB', | |
81 | '512 KiB', | |
82 | '1 MiB', | |
83 | '2 MiB', | |
84 | '4 MiB', | |
85 | '8 MiB', | |
86 | '16 MiB', | |
87 | '32 MiB' | |
88 | ]; | |
89 | action: string; | |
90 | resource: string; | |
91 | ||
92 | constructor( | |
93 | private authStorageService: AuthStorageService, | |
94 | private route: ActivatedRoute, | |
95 | private router: Router, | |
96 | private poolService: PoolService, | |
97 | private rbdService: RbdService, | |
98 | private formatter: FormatterService, | |
99 | private taskWrapper: TaskWrapperService, | |
100 | private dimlessBinaryPipe: DimlessBinaryPipe, | |
101 | private i18n: I18n, | |
102 | public actionLabels: ActionLabelsI18n | |
103 | ) { | |
104 | this.poolPermission = this.authStorageService.getPermissions().pool; | |
105 | this.resource = this.i18n('RBD'); | |
106 | this.features = { | |
107 | 'deep-flatten': { | |
108 | desc: this.i18n('Deep flatten'), | |
109 | requires: null, | |
110 | allowEnable: false, | |
111 | allowDisable: true | |
112 | }, | |
113 | layering: { | |
114 | desc: this.i18n('Layering'), | |
115 | requires: null, | |
116 | allowEnable: false, | |
117 | allowDisable: false | |
118 | }, | |
119 | 'exclusive-lock': { | |
120 | desc: this.i18n('Exclusive lock'), | |
121 | requires: null, | |
122 | allowEnable: true, | |
123 | allowDisable: true | |
124 | }, | |
125 | 'object-map': { | |
126 | desc: this.i18n('Object map (requires exclusive-lock)'), | |
127 | requires: 'exclusive-lock', | |
128 | allowEnable: true, | |
129 | allowDisable: true | |
130 | }, | |
131 | journaling: { | |
132 | desc: this.i18n('Journaling (requires exclusive-lock)'), | |
133 | requires: 'exclusive-lock', | |
134 | allowEnable: true, | |
135 | allowDisable: true | |
136 | }, | |
137 | 'fast-diff': { | |
138 | desc: this.i18n('Fast diff (requires object-map)'), | |
139 | requires: 'object-map', | |
140 | allowEnable: true, | |
141 | allowDisable: true | |
142 | } | |
143 | }; | |
144 | this.createForm(); | |
145 | for (const key of Object.keys(this.features)) { | |
146 | const listItem = this.features[key]; | |
147 | listItem.key = key; | |
148 | this.featuresList.push(listItem); | |
149 | } | |
150 | } | |
151 | ||
152 | createForm() { | |
153 | this.deepFlattenFormControl = new FormControl(false); | |
154 | this.layeringFormControl = new FormControl(false); | |
155 | this.exclusiveLockFormControl = new FormControl(false); | |
156 | this.objectMapFormControl = new FormControl({ value: false, disabled: true }); | |
157 | this.journalingFormControl = new FormControl({ value: false, disabled: true }); | |
158 | this.fastDiffFormControl = new FormControl({ value: false, disabled: true }); | |
159 | this.featuresFormGroups = new CdFormGroup({ | |
160 | 'deep-flatten': this.deepFlattenFormControl, | |
161 | layering: this.layeringFormControl, | |
162 | 'exclusive-lock': this.exclusiveLockFormControl, | |
163 | 'object-map': this.objectMapFormControl, | |
164 | journaling: this.journalingFormControl, | |
165 | 'fast-diff': this.fastDiffFormControl | |
166 | }); | |
167 | this.rbdForm = new CdFormGroup( | |
168 | { | |
169 | parent: new FormControl(''), | |
170 | name: new FormControl('', { | |
171 | validators: [Validators.required, Validators.pattern(/^[^@/]+?$/)] | |
172 | }), | |
173 | pool: new FormControl(null, { | |
174 | validators: [Validators.required] | |
175 | }), | |
176 | useDataPool: new FormControl(false), | |
177 | dataPool: new FormControl(null), | |
178 | size: new FormControl(null, { | |
179 | updateOn: 'blur' | |
180 | }), | |
181 | obj_size: new FormControl(this.defaultObjectSize), | |
182 | features: this.featuresFormGroups, | |
183 | stripingUnit: new FormControl(null), | |
184 | stripingCount: new FormControl(null, { | |
185 | updateOn: 'blur' | |
186 | }) | |
187 | }, | |
188 | this.validateRbdForm(this.formatter) | |
189 | ); | |
190 | } | |
191 | ||
192 | disableForEdit() { | |
193 | this.rbdForm.get('parent').disable(); | |
194 | this.rbdForm.get('pool').disable(); | |
195 | this.rbdForm.get('useDataPool').disable(); | |
196 | this.rbdForm.get('dataPool').disable(); | |
197 | this.rbdForm.get('obj_size').disable(); | |
198 | this.rbdForm.get('stripingUnit').disable(); | |
199 | this.rbdForm.get('stripingCount').disable(); | |
200 | } | |
201 | ||
202 | disableForClone() { | |
203 | this.rbdForm.get('parent').disable(); | |
204 | this.rbdForm.get('size').disable(); | |
205 | } | |
206 | ||
207 | disableForCopy() { | |
208 | this.rbdForm.get('parent').disable(); | |
209 | this.rbdForm.get('size').disable(); | |
210 | } | |
211 | ||
212 | ngOnInit() { | |
213 | if (this.router.url.startsWith('/block/rbd/edit')) { | |
214 | this.mode = this.rbdFormMode.editing; | |
215 | this.action = this.actionLabels.EDIT; | |
216 | this.disableForEdit(); | |
217 | } else if (this.router.url.startsWith('/block/rbd/clone')) { | |
218 | this.mode = this.rbdFormMode.cloning; | |
219 | this.disableForClone(); | |
220 | this.action = this.actionLabels.CLONE; | |
221 | } else if (this.router.url.startsWith('/block/rbd/copy')) { | |
222 | this.mode = this.rbdFormMode.copying; | |
223 | this.action = this.actionLabels.COPY; | |
224 | this.disableForCopy(); | |
225 | } else { | |
226 | this.action = this.actionLabels.CREATE; | |
227 | } | |
228 | if ( | |
229 | this.mode === this.rbdFormMode.editing || | |
230 | this.mode === this.rbdFormMode.cloning || | |
231 | this.mode === this.rbdFormMode.copying | |
232 | ) { | |
233 | this.route.params.subscribe((params: { pool: string; name: string; snap: string }) => { | |
234 | const poolName = decodeURIComponent(params.pool); | |
235 | const rbdName = decodeURIComponent(params.name); | |
236 | if (params.snap) { | |
237 | this.snapName = decodeURIComponent(params.snap); | |
238 | } | |
239 | this.rbdService.get(poolName, rbdName).subscribe((resp: RbdFormResponseModel) => { | |
240 | this.setResponse(resp, this.snapName); | |
241 | }); | |
242 | }); | |
243 | } else { | |
244 | this.rbdService.defaultFeatures().subscribe((defaultFeatures: Array<string>) => { | |
245 | this.setFeatures(defaultFeatures); | |
246 | }); | |
247 | } | |
248 | if (this.mode !== this.rbdFormMode.editing && this.poolPermission.read) { | |
249 | this.poolService | |
250 | .list(['pool_name', 'type', 'flags_names', 'application_metadata']) | |
251 | .then((resp) => { | |
252 | const pools = []; | |
253 | const dataPools = []; | |
254 | for (const pool of resp) { | |
255 | if (_.indexOf(pool.application_metadata, 'rbd') !== -1) { | |
256 | if (!pool.pool_name.includes('/')) { | |
257 | if (pool.type === 'replicated') { | |
258 | pools.push(pool); | |
259 | dataPools.push(pool); | |
260 | } else if ( | |
261 | pool.type === 'erasure' && | |
262 | pool.flags_names.indexOf('ec_overwrites') !== -1 | |
263 | ) { | |
264 | dataPools.push(pool); | |
265 | } | |
266 | } | |
267 | } | |
268 | } | |
269 | this.pools = pools; | |
270 | this.allPools = pools; | |
271 | this.dataPools = dataPools; | |
272 | this.allDataPools = dataPools; | |
273 | if (this.pools.length === 1) { | |
274 | const poolName = this.pools[0]['pool_name']; | |
275 | this.rbdForm.get('pool').setValue(poolName); | |
276 | this.onPoolChange(poolName); | |
277 | } | |
278 | }); | |
279 | } | |
280 | this.deepFlattenFormControl.valueChanges.subscribe((value) => { | |
281 | this.watchDataFeatures('deep-flatten', value); | |
282 | }); | |
283 | this.layeringFormControl.valueChanges.subscribe((value) => { | |
284 | this.watchDataFeatures('layering', value); | |
285 | }); | |
286 | this.exclusiveLockFormControl.valueChanges.subscribe((value) => { | |
287 | this.watchDataFeatures('exclusive-lock', value); | |
288 | }); | |
289 | this.objectMapFormControl.valueChanges.subscribe((value) => { | |
290 | this.watchDataFeatures('object-map', value); | |
291 | }); | |
292 | this.journalingFormControl.valueChanges.subscribe((value) => { | |
293 | this.watchDataFeatures('journaling', value); | |
294 | }); | |
295 | this.fastDiffFormControl.valueChanges.subscribe((value) => { | |
296 | this.watchDataFeatures('fast-diff', value); | |
297 | }); | |
298 | } | |
299 | ||
300 | onPoolChange(selectedPoolName) { | |
301 | const newDataPools = this.allDataPools.filter((dataPool: any) => { | |
302 | return dataPool.pool_name !== selectedPoolName; | |
303 | }); | |
304 | if (this.rbdForm.getValue('dataPool') === selectedPoolName) { | |
305 | this.rbdForm.get('dataPool').setValue(null); | |
306 | } | |
307 | this.dataPools = newDataPools; | |
308 | } | |
309 | ||
310 | onUseDataPoolChange() { | |
311 | if (!this.rbdForm.getValue('useDataPool')) { | |
312 | this.rbdForm.get('dataPool').setValue(null); | |
313 | this.onDataPoolChange(null); | |
314 | } | |
315 | } | |
316 | ||
317 | onDataPoolChange(selectedDataPoolName) { | |
318 | const newPools = this.allPools.filter((pool: any) => { | |
319 | return pool.pool_name !== selectedDataPoolName; | |
320 | }); | |
321 | if (this.rbdForm.getValue('pool') === selectedDataPoolName) { | |
322 | this.rbdForm.get('pool').setValue(null); | |
323 | } | |
324 | this.pools = newPools; | |
325 | } | |
326 | ||
327 | validateRbdForm(formatter: FormatterService): ValidatorFn { | |
328 | return (formGroup: CdFormGroup) => { | |
329 | // Data Pool | |
330 | const useDataPoolControl = formGroup.get('useDataPool'); | |
331 | const dataPoolControl = formGroup.get('dataPool'); | |
332 | let dataPoolControlErrors = null; | |
333 | if (useDataPoolControl.value && dataPoolControl.value == null) { | |
334 | dataPoolControlErrors = { required: true }; | |
335 | } | |
336 | dataPoolControl.setErrors(dataPoolControlErrors); | |
337 | // Size | |
338 | const sizeControl = formGroup.get('size'); | |
339 | const objectSizeControl = formGroup.get('obj_size'); | |
340 | const objectSizeInBytes = formatter.toBytes( | |
341 | objectSizeControl.value != null ? objectSizeControl.value : this.defaultObjectSize | |
342 | ); | |
343 | const stripingCountControl = formGroup.get('stripingCount'); | |
344 | const stripingCount = stripingCountControl.value != null ? stripingCountControl.value : 1; | |
345 | let sizeControlErrors = null; | |
346 | if (sizeControl.value === null) { | |
347 | sizeControlErrors = { required: true }; | |
348 | } else { | |
349 | const sizeInBytes = formatter.toBytes(sizeControl.value); | |
350 | if (stripingCount * objectSizeInBytes > sizeInBytes) { | |
351 | sizeControlErrors = { invalidSizeObject: true }; | |
352 | } | |
353 | } | |
354 | sizeControl.setErrors(sizeControlErrors); | |
355 | // Striping Unit | |
356 | const stripingUnitControl = formGroup.get('stripingUnit'); | |
357 | let stripingUnitControlErrors = null; | |
358 | if (stripingUnitControl.value === null && stripingCountControl.value !== null) { | |
359 | stripingUnitControlErrors = { required: true }; | |
360 | } else if (stripingUnitControl.value !== null) { | |
361 | const stripingUnitInBytes = formatter.toBytes(stripingUnitControl.value); | |
362 | if (stripingUnitInBytes > objectSizeInBytes) { | |
363 | stripingUnitControlErrors = { invalidStripingUnit: true }; | |
364 | } | |
365 | } | |
366 | stripingUnitControl.setErrors(stripingUnitControlErrors); | |
367 | // Striping Count | |
368 | let stripingCountControlErrors = null; | |
369 | if (stripingCountControl.value === null && stripingUnitControl.value !== null) { | |
370 | stripingCountControlErrors = { required: true }; | |
371 | } else if (stripingCount < 1) { | |
372 | stripingCountControlErrors = { min: true }; | |
373 | } | |
374 | stripingCountControl.setErrors(stripingCountControlErrors); | |
375 | return null; | |
376 | }; | |
377 | } | |
378 | ||
379 | deepBoxCheck(key, checked) { | |
380 | _.forIn(this.features, (details, feature) => { | |
381 | if (details.requires === key) { | |
382 | if (checked) { | |
383 | this.rbdForm.get(feature).enable(); | |
384 | } else { | |
385 | this.rbdForm.get(feature).disable(); | |
386 | this.rbdForm.get(feature).setValue(checked); | |
387 | this.watchDataFeatures(feature, checked); | |
388 | this.deepBoxCheck(feature, checked); | |
389 | } | |
390 | } | |
391 | if (this.mode === this.rbdFormMode.editing && this.rbdForm.get(feature).enabled) { | |
392 | if (this.response.features_name.indexOf(feature) !== -1 && !details.allowDisable) { | |
393 | this.rbdForm.get(feature).disable(); | |
394 | } else if (this.response.features_name.indexOf(feature) === -1 && !details.allowEnable) { | |
395 | this.rbdForm.get(feature).disable(); | |
396 | } | |
397 | } | |
398 | }); | |
399 | } | |
400 | ||
401 | featureFormUpdate(key, checked) { | |
402 | if (checked) { | |
403 | const required = this.features[key].requires; | |
404 | if (required && !this.rbdForm.getValue(required)) { | |
405 | this.rbdForm.get(key).setValue(false); | |
406 | return; | |
407 | } | |
408 | } | |
409 | this.deepBoxCheck(key, checked); | |
410 | } | |
411 | ||
412 | watchDataFeatures(key, checked) { | |
413 | this.featureFormUpdate(key, checked); | |
414 | } | |
415 | ||
416 | setFeatures(features: Array<string>) { | |
417 | const featuresControl = this.rbdForm.get('features'); | |
418 | _.forIn(this.features, (feature) => { | |
419 | if (features.indexOf(feature.key) !== -1) { | |
420 | featuresControl.get(feature.key).setValue(true); | |
421 | } | |
422 | this.watchDataFeatures(feature.key, featuresControl.get(feature.key).value); | |
423 | }); | |
424 | } | |
425 | ||
426 | setResponse(response: RbdFormResponseModel, snapName: string) { | |
427 | this.response = response; | |
428 | if (this.mode === this.rbdFormMode.cloning) { | |
429 | this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}@${snapName}`); | |
430 | } else if (this.mode === this.rbdFormMode.copying) { | |
431 | if (snapName) { | |
432 | this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}@${snapName}`); | |
433 | } else { | |
434 | this.rbdForm.get('parent').setValue(`${response.pool_name}/${response.name}`); | |
435 | } | |
436 | } else if (response.parent) { | |
437 | const parent = response.parent; | |
438 | this.rbdForm | |
439 | .get('parent') | |
440 | .setValue(`${parent.pool_name}/${parent.image_name}@${parent.snap_name}`); | |
441 | } | |
442 | if (this.mode === this.rbdFormMode.editing) { | |
443 | this.rbdForm.get('name').setValue(response.name); | |
444 | } | |
445 | this.rbdForm.get('pool').setValue(response.pool_name); | |
446 | if (response.data_pool) { | |
447 | this.rbdForm.get('useDataPool').setValue(true); | |
448 | this.rbdForm.get('dataPool').setValue(response.data_pool); | |
449 | } | |
450 | this.rbdForm.get('size').setValue(this.dimlessBinaryPipe.transform(response.size)); | |
451 | this.rbdForm.get('obj_size').setValue(this.dimlessBinaryPipe.transform(response.obj_size)); | |
452 | this.setFeatures(response.features_name); | |
453 | this.rbdForm | |
454 | .get('stripingUnit') | |
455 | .setValue(this.dimlessBinaryPipe.transform(response.stripe_unit)); | |
456 | this.rbdForm.get('stripingCount').setValue(response.stripe_count); | |
457 | ||
458 | /* Configuration */ | |
459 | this.initializeConfigData.emit({ | |
460 | initialData: this.response.configuration, | |
461 | sourceType: RbdConfigurationSourceField.image | |
462 | }); | |
463 | } | |
464 | ||
465 | createRequest() { | |
466 | const request = new RbdFormCreateRequestModel(); | |
467 | request.pool_name = this.rbdForm.getValue('pool'); | |
468 | request.name = this.rbdForm.getValue('name'); | |
469 | request.size = this.formatter.toBytes(this.rbdForm.getValue('size')); | |
470 | request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size')); | |
471 | _.forIn(this.features, (feature) => { | |
472 | if (this.rbdForm.getValue(feature.key)) { | |
473 | request.features.push(feature.key); | |
474 | } | |
475 | }); | |
476 | ||
477 | /* Striping */ | |
478 | request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit')); | |
479 | request.stripe_count = this.rbdForm.getValue('stripingCount'); | |
480 | request.data_pool = this.rbdForm.getValue('dataPool'); | |
481 | ||
482 | /* Configuration */ | |
483 | request.configuration = this.getDirtyConfigurationValues(); | |
484 | ||
485 | return request; | |
486 | } | |
487 | ||
488 | createAction(): Observable<any> { | |
489 | const request = this.createRequest(); | |
490 | return this.taskWrapper.wrapTaskAroundCall({ | |
491 | task: new FinishedTask('rbd/create', { | |
492 | pool_name: request.pool_name, | |
493 | image_name: request.name | |
494 | }), | |
495 | call: this.rbdService.create(request) | |
496 | }); | |
497 | } | |
498 | ||
499 | editRequest() { | |
500 | const request = new RbdFormEditRequestModel(); | |
501 | request.name = this.rbdForm.getValue('name'); | |
502 | request.size = this.formatter.toBytes(this.rbdForm.getValue('size')); | |
503 | _.forIn(this.features, (feature) => { | |
504 | if (this.rbdForm.getValue(feature.key)) { | |
505 | request.features.push(feature.key); | |
506 | } | |
507 | }); | |
508 | ||
509 | request.configuration = this.getDirtyConfigurationValues(); | |
510 | ||
511 | return request; | |
512 | } | |
513 | ||
514 | cloneRequest(): RbdFormCloneRequestModel { | |
515 | const request = new RbdFormCloneRequestModel(); | |
516 | request.child_pool_name = this.rbdForm.getValue('pool'); | |
517 | request.child_image_name = this.rbdForm.getValue('name'); | |
518 | request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size')); | |
519 | _.forIn(this.features, (feature) => { | |
520 | if (this.rbdForm.getValue(feature.key)) { | |
521 | request.features.push(feature.key); | |
522 | } | |
523 | }); | |
524 | ||
525 | /* Striping */ | |
526 | request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit')); | |
527 | request.stripe_count = this.rbdForm.getValue('stripingCount'); | |
528 | request.data_pool = this.rbdForm.getValue('dataPool'); | |
529 | ||
530 | /* Configuration */ | |
531 | request.configuration = this.getDirtyConfigurationValues( | |
532 | true, | |
533 | RbdConfigurationSourceField.image | |
534 | ); | |
535 | ||
536 | return request; | |
537 | } | |
538 | ||
539 | editAction(): Observable<any> { | |
540 | return this.taskWrapper.wrapTaskAroundCall({ | |
541 | task: new FinishedTask('rbd/edit', { | |
542 | pool_name: this.response.pool_name, | |
543 | image_name: this.response.name | |
544 | }), | |
545 | call: this.rbdService.update(this.response.pool_name, this.response.name, this.editRequest()) | |
546 | }); | |
547 | } | |
548 | ||
549 | cloneAction(): Observable<any> { | |
550 | const request = this.cloneRequest(); | |
551 | return this.taskWrapper.wrapTaskAroundCall({ | |
552 | task: new FinishedTask('rbd/clone', { | |
553 | parent_pool_name: this.response.pool_name, | |
554 | parent_image_name: this.response.name, | |
555 | parent_snap_name: this.snapName, | |
556 | child_pool_name: request.child_pool_name, | |
557 | child_image_name: request.child_image_name | |
558 | }), | |
559 | call: this.rbdService.cloneSnapshot( | |
560 | this.response.pool_name, | |
561 | this.response.name, | |
562 | this.snapName, | |
563 | request | |
564 | ) | |
565 | }); | |
566 | } | |
567 | ||
568 | copyRequest(): RbdFormCopyRequestModel { | |
569 | const request = new RbdFormCopyRequestModel(); | |
570 | if (this.snapName) { | |
571 | request.snapshot_name = this.snapName; | |
572 | } | |
573 | request.dest_pool_name = this.rbdForm.getValue('pool'); | |
574 | request.dest_image_name = this.rbdForm.getValue('name'); | |
575 | request.obj_size = this.formatter.toBytes(this.rbdForm.getValue('obj_size')); | |
576 | _.forIn(this.features, (feature) => { | |
577 | if (this.rbdForm.getValue(feature.key)) { | |
578 | request.features.push(feature.key); | |
579 | } | |
580 | }); | |
581 | ||
582 | /* Striping */ | |
583 | request.stripe_unit = this.formatter.toBytes(this.rbdForm.getValue('stripingUnit')); | |
584 | request.stripe_count = this.rbdForm.getValue('stripingCount'); | |
585 | request.data_pool = this.rbdForm.getValue('dataPool'); | |
586 | ||
587 | /* Configuration */ | |
588 | request.configuration = this.getDirtyConfigurationValues( | |
589 | true, | |
590 | RbdConfigurationSourceField.image | |
591 | ); | |
592 | ||
593 | return request; | |
594 | } | |
595 | ||
596 | copyAction(): Observable<any> { | |
597 | const request = this.copyRequest(); | |
598 | ||
599 | return this.taskWrapper.wrapTaskAroundCall({ | |
600 | task: new FinishedTask('rbd/copy', { | |
601 | src_pool_name: this.response.pool_name, | |
602 | src_image_name: this.response.name, | |
603 | dest_pool_name: request.dest_pool_name, | |
604 | dest_image_name: request.dest_image_name | |
605 | }), | |
606 | call: this.rbdService.copy(this.response.pool_name, this.response.name, request) | |
607 | }); | |
608 | } | |
609 | ||
610 | submit() { | |
611 | let action: Observable<any>; | |
612 | ||
613 | if (this.mode === this.rbdFormMode.editing) { | |
614 | action = this.editAction(); | |
615 | } else if (this.mode === this.rbdFormMode.cloning) { | |
616 | action = this.cloneAction(); | |
617 | } else if (this.mode === this.rbdFormMode.copying) { | |
618 | action = this.copyAction(); | |
619 | } else { | |
620 | action = this.createAction(); | |
621 | } | |
622 | ||
623 | action.subscribe( | |
624 | undefined, | |
625 | () => this.rbdForm.setErrors({ cdSubmitButton: true }), | |
626 | () => this.router.navigate(['/block/rbd']) | |
627 | ); | |
628 | } | |
629 | } |