*ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
osdRecvSpeedForm.showError(attr.key, formDir, 'required')"
i18n>This field is required!</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'pattern')"
+ i18n>{{ attr.value.patternHelpText }}</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'max')"
+ i18n>The entered value is too high! It must not be greater than {{ attr.value.maxValue }}.</span>
+ <span class="help-block"
+ *ngIf="osdRecvSpeedForm.getValue('customizePriority') &&
+ osdRecvSpeedForm.showError(attr.key, formDir, 'min')"
+ i18n>The entered value is too low! It must not be lower than {{ attr.value.minValue }}.</span>
</div>
</div>
</div>
});
});
});
+
+ describe('setValidators', () => {
+ const configOptions = [
+ {
+ name: 'osd_max_backfills',
+ type: 'uint'
+ },
+ {
+ name: 'osd_recovery_max_active',
+ type: 'uint'
+ },
+ {
+ name: 'osd_recovery_max_single_start',
+ type: 'uint'
+ },
+ {
+ name: 'osd_recovery_sleep',
+ type: 'float'
+ }
+ ];
+
+ it('should set needed validators for config option', () => {
+ component.setValidators(configOptions);
+ configOptions.forEach((configOption) => {
+ const control = component.osdRecvSpeedForm.controls[configOption.name];
+
+ if (configOption.type === 'float') {
+ expect(component.priorityAttrs[configOption.name].patternHelpText).toBe(
+ 'The entered value needs to be a number or decimal.'
+ );
+ } else {
+ expect(component.priorityAttrs[configOption.name].minValue).toBe(0);
+ expect(component.priorityAttrs[configOption.name].patternHelpText).toBe(
+ 'The entered value needs to be an unsigned number.'
+ );
+
+ control.setValue(-1);
+ expect(control.hasError('min')).toBeTruthy();
+ }
+
+ control.setValue(null);
+ expect(control.hasError('required')).toBeTruthy();
+ control.setValue('E');
+ expect(control.hasError('pattern')).toBeTruthy();
+ control.setValue(3);
+ expect(control.hasError('required')).toBeFalsy();
+ expect(control.hasError('min')).toBeFalsy();
+ expect(control.hasError('pattern')).toBeFalsy();
+ });
+ });
+ });
});
import { NotificationType } from '../../../../shared/enum/notification-type.enum';
import { CdFormGroup } from '../../../../shared/forms/cd-form-group';
import { NotificationService } from '../../../../shared/services/notification.service';
+import { ConfigOptionTypes } from '../../configuration/configuration-form/configuration-form.types';
@Component({
selector: 'cd-osd-recv-speed-modal',
this.priorityAttrs = {
osd_max_backfills: {
text: this.i18n('Max Backfills'),
- desc: ''
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
},
osd_recovery_max_active: {
text: this.i18n('Recovery Max Active'),
- desc: ''
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
},
osd_recovery_max_single_start: {
text: this.i18n('Recovery Max Single Start'),
- desc: ''
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
},
osd_recovery_sleep: {
text: this.i18n('Recovery Sleep'),
- desc: ''
+ desc: '',
+ patternHelpText: '',
+ maxValue: undefined,
+ minValue: undefined
}
};
this.setPriority(priority);
});
this.setDescription(resp.configOptions);
+ this.setValidators(resp.configOptions);
});
}
});
}
+ setValidators(configOptions: Array<any>) {
+ configOptions.forEach((configOption) => {
+ const typeValidators = ConfigOptionTypes.getTypeValidators(configOption);
+ if (typeValidators) {
+ typeValidators.validators.push(Validators.required);
+
+ if ('max' in typeValidators && typeValidators.max !== '') {
+ this.priorityAttrs[configOption.name].maxValue = typeValidators.max;
+ }
+
+ if ('min' in typeValidators && typeValidators.min !== '') {
+ this.priorityAttrs[configOption.name].minValue = typeValidators.min;
+ }
+
+ this.priorityAttrs[configOption.name].patternHelpText = typeValidators.patternHelpText;
+ this.osdRecvSpeedForm.controls[configOption.name].setValidators(typeValidators.validators);
+ } else {
+ this.osdRecvSpeedForm.controls[configOption.name].setValidators(Validators.required);
+ }
+ });
+ }
+
onCustomizePriorityChange() {
if (this.osdRecvSpeedForm.getValue('customizePriority')) {
const values = {};
_.find(this.priorities, (p) => {
return p.name === selectedPriorityName;
}) || this.priorities[0];
+ // Uncheck the 'Customize priority values' checkbox.
+ this.osdRecvSpeedForm.get('customizePriority').setValue(false);
+ // Set the priority profile values.
this.setPriority(selectedPriority);
}
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html</context>
- <context context-type="linenumber">79</context>
+ <context context-type="linenumber">91</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/cluster/osd/osd-reweight-modal/osd-reweight-modal.component.html</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html</context>
- <context context-type="linenumber">75</context>
+ <context context-type="linenumber">87</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">app/ceph/cluster/osd/osd-scrub-modal/osd-scrub-modal.component.html</context>
<context context-type="sourcefile">app/ceph/pool/pool-form/pool-form.component.html</context>
<context context-type="linenumber">95</context>
</context-group>
+ </trans-unit><trans-unit id="b699e94bf376491bd50b70a98531071c737eaf40" datatype="html">
+ <source><x id="INTERPOLATION" equiv-text="{{ attr.value.patternHelpText }}"/></source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html</context>
+ <context context-type="linenumber">71</context>
+ </context-group>
+ </trans-unit><trans-unit id="98fe13e7ad6c2b80375d204b47858ded83f80e15" datatype="html">
+ <source>The entered value is too high! It must not be greater than <x id="INTERPOLATION" equiv-text="{{ attr.value.maxValue }}"/>.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html</context>
+ <context context-type="linenumber">75</context>
+ </context-group>
+ </trans-unit><trans-unit id="5423a3c111be47fc5a1bfe46ceb58c81c84db691" datatype="html">
+ <source>The entered value is too low! It must not be lower than <x id="INTERPOLATION" equiv-text="{{ attr.value.minValue }}"/>.</source>
+ <context-group purpose="location">
+ <context context-type="sourcefile">app/ceph/cluster/osd/osd-recv-speed-modal/osd-recv-speed-modal.component.html</context>
+ <context context-type="linenumber">79</context>
+ </context-group>
</trans-unit><trans-unit id="272696ff8acdbed0af6dc13f09729e70be435b82" datatype="html">
<source>Reweight OSD</source>
<context-group purpose="location">