1 import { Component, EventEmitter, OnInit, Output } from '@angular/core';
2 import { Validators } from '@angular/forms';
4 import { BsModalRef } from 'ngx-bootstrap/modal';
6 import { ErasureCodeProfileService } from '../../../shared/api/erasure-code-profile.service';
7 import { CdFormBuilder } from '../../../shared/forms/cd-form-builder';
8 import { CdFormGroup } from '../../../shared/forms/cd-form-group';
9 import { CdValidators } from '../../../shared/forms/cd-validators';
10 import { ErasureCodeProfile } from '../../../shared/models/erasure-code-profile';
11 import { FinishedTask } from '../../../shared/models/finished-task';
12 import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
13 import { ErasureCodeProfileFormTooltips } from './erasure-code-profile-form-tooltips';
16 selector: 'cd-erasure-code-profile-form',
17 templateUrl: './erasure-code-profile-form.component.html',
18 styleUrls: ['./erasure-code-profile-form.component.scss']
20 export class ErasureCodeProfileFormComponent implements OnInit {
22 submitAction = new EventEmitter();
25 failureDomains: string[];
29 requiredControls: string[] = [];
30 devices: string[] = [];
31 tooltips = new ErasureCodeProfileFormTooltips();
34 LRC: 'lrc', // Locally Repairable Erasure Code
35 SHEC: 'shec', // Shingled Erasure Code
36 JERASURE: 'jerasure', // default
37 ISA: 'isa' // Intel Storage Acceleration
39 plugin = this.PLUGIN.JERASURE;
42 private formBuilder: CdFormBuilder,
43 public bsModalRef: BsModalRef,
44 private taskWrapper: TaskWrapperService,
45 private ecpService: ErasureCodeProfileService
48 this.setJerasureDefaults();
52 this.form = this.formBuilder.group({
57 Validators.pattern('[A-Za-z0-9_-]+'),
60 (value) => this.names && this.names.indexOf(value) !== -1
64 plugin: [this.PLUGIN.JERASURE, [Validators.required]],
65 k: [1], // Will be replaced by plugin defaults
66 m: [1], // Will be replaced by plugin defaults
67 crushFailureDomain: ['host'],
68 crushRoot: ['default'], // default for all - is a list possible???
69 crushDeviceClass: [''], // set none to empty at submit - get list from configs?
71 // Only for 'jerasure' and 'isa' use
72 technique: ['reed_sol_van'],
73 // Only for 'jerasure' use
74 packetSize: [2048, [Validators.min(1)]],
76 l: [1, [Validators.required, Validators.min(1)]],
77 crushLocality: [''], // set to none at the end (same list as for failure domains)
78 // Only for 'shec' use
79 c: [1, [Validators.required, Validators.min(1)]]
81 this.form.get('plugin').valueChanges.subscribe((plugin) => this.onPluginChange(plugin));
84 onPluginChange(plugin) {
86 if (plugin === this.PLUGIN.JERASURE) {
87 this.setJerasureDefaults();
88 } else if (plugin === this.PLUGIN.LRC) {
89 this.setLrcDefaults();
90 } else if (plugin === this.PLUGIN.ISA) {
91 this.setIsaDefaults();
92 } else if (plugin === this.PLUGIN.SHEC) {
93 this.setShecDefaults();
97 private setNumberValidators(name: string, required: boolean) {
98 const validators = [Validators.min(1)];
100 validators.push(Validators.required);
102 this.form.get(name).setValidators(validators);
105 private setKMValidators(required: boolean) {
106 ['k', 'm'].forEach((name) => this.setNumberValidators(name, required));
109 private setJerasureDefaults() {
110 this.requiredControls = ['k', 'm'];
115 this.setKMValidators(true);
127 private setLrcDefaults() {
128 this.requiredControls = ['k', 'm', 'l'];
129 this.setKMValidators(true);
130 this.setNumberValidators('l', true);
138 private setIsaDefaults() {
139 this.requiredControls = [];
140 this.setKMValidators(false);
145 this.techniques = ['reed_sol_van', 'cauchy'];
148 private setShecDefaults() {
149 this.requiredControls = [];
150 this.setKMValidators(false);
158 private setDefaults(defaults: object) {
159 Object.keys(defaults).forEach((controlName) => {
160 if (this.form.get(controlName).pristine) {
161 this.form.silentSet(controlName, defaults[controlName]);
177 failure_domains: string[];
183 this.failureDomains = failure_domains;
184 this.plugins = plugins;
186 this.devices = devices;
187 this.form.silentSet('directory', directory);
192 private createJson() {
193 const pluginControls = {
194 technique: [this.PLUGIN.ISA, this.PLUGIN.JERASURE],
195 packetSize: [this.PLUGIN.JERASURE],
196 l: [this.PLUGIN.LRC],
197 crushLocality: [this.PLUGIN.LRC],
198 c: [this.PLUGIN.SHEC]
200 const ecp = new ErasureCodeProfile();
201 const plugin = this.form.getValue('plugin');
202 Object.keys(this.form.controls)
204 const pluginControl = pluginControls[name];
205 const control = this.form.get(name);
206 const usable = (pluginControl && pluginControl.includes(plugin)) || !pluginControl;
209 (control.dirty || this.requiredControls.includes(name)) &&
210 this.form.getValue(name)
214 this.extendJson(name, ecp);
219 private extendJson(name: string, ecp: ErasureCodeProfile) {
220 const differentApiAttributes = {
221 crushFailureDomain: 'crush-failure-domain',
222 crushRoot: 'crush-root',
223 crushDeviceClass: 'crush-device-class',
224 packetSize: 'packetsize',
225 crushLocality: 'crush-locality'
227 ecp[differentApiAttributes[name] || name] = this.form.getValue(name);
231 if (this.form.invalid) {
232 this.form.setErrors({ cdSubmitButton: true });
235 const profile = this.createJson();
237 .wrapTaskAroundCall({
238 task: new FinishedTask('ecp/create', { name: profile.name }),
239 call: this.ecpService.create(profile)
244 this.form.setErrors({ cdSubmitButton: true });
247 this.bsModalRef.hide();
248 this.submitAction.emit(profile);