});
it('should select all values automatically by selecting "ssd-host" as root', () => {
+ formHelper.setValue('device_class', 'ssd', true);
assert.valuesOnRootChange('ssd-host', 'osd', 'ssd');
});
it('should override automatic selections', () => {
assert.formFieldValues(get.nodeByName('default'), 'osd-rack', '');
+ formHelper.setValue('device_class', 'ssd', true);
assert.valuesOnRootChange('ssd-host', 'osd', 'ssd');
+ formHelper.setValue('device_class', '', true);
assert.valuesOnRootChange('mix-host', 'osd-rack', '');
});
});
it('should preselect device by domain selection', () => {
+ formHelper.setValue('device_class', 'ssd', true);
formHelper.setValue('failure_domain', 'osd', true);
assert.formFieldValues(get.nodeByName('default'), 'osd', 'ssd');
});
});
it('creates a rule with all fields', () => {
+ formHelper.setValue('device_class', 'ssd', true);
assert.valuesOnRootChange('ssd-host', 'osd', 'ssd');
assert.creation(Mocks.getCrushRuleConfig('ssd-host-rule', 'ssd-host', 'osd', 'ssd'));
});
nodes,
this.form.get('root'),
this.form.get('failure_domain'),
- this.form.get('device_class')
+ this.form.get('device_class'),
+ false
);
this.names = names;
});
*ngIf="form.showError('k', frm, 'min')"
i18n>Must be equal to or greater than 2.</span>
<span class="invalid-feedback"
- *ngIf="form.showError('k', frm, 'max')"
+ *ngIf="form.showError('k', frm, 'max') && form.getValue('crushFailureDomain') === CrushFailureDomains.Osd"
i18n>Chunks (k+m) have exceeded the available OSDs of {{deviceCount}}.</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('k', frm, 'max') && form.getValue('crushFailureDomain') === CrushFailureDomains.Host"
+ i18n>Chunks (k+m+1) have exceeded the available hosts of {{deviceCount}}.</span>
<span class="invalid-feedback"
*ngIf="form.showError('k', frm, 'unequal')"
i18n>For an equal distribution k has to be a multiple of (k+m)/l.</span>
*ngIf="form.showError('m', frm, 'min')"
i18n>Must be equal to or greater than 1.</span>
<span class="invalid-feedback"
- *ngIf="form.showError('m', frm, 'max')"
+ *ngIf="form.showError('m', frm, 'max') && form.getValue('crushFailureDomain') === CrushFailureDomains.Osd"
i18n>Chunks (k+m) have exceeded the available OSDs of {{deviceCount}}.</span>
+ <span class="invalid-feedback"
+ *ngIf="form.showError('m', frm, 'max') && form.getValue('crushFailureDomain') === CrushFailureDomains.Host"
+ i18n>Chunks (k+m+1) have exceeded the available hosts of {{deviceCount}}.</span>
</div>
</div>
<select class="form-select"
id="crushFailureDomain"
name="crushFailureDomain"
- formControlName="crushFailureDomain">
+ formControlName="crushFailureDomain"
+ (change)="onCrushFailureDomainChane()">
<option *ngIf="!failureDomains"
ngValue=""
i18n>Loading...</option>
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
import { CdValidators } from '~/app/shared/forms/cd-validators';
import { CrushNode } from '~/app/shared/models/crush-node';
-import { ErasureCodeProfile } from '~/app/shared/models/erasure-code-profile';
+import { ErasureCodeProfile, CrushFailureDomains } from '~/app/shared/models/erasure-code-profile';
import { FinishedTask } from '~/app/shared/models/finished-task';
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
lrcGroups: number;
lrcMultiK: number;
+ public CrushFailureDomains = CrushFailureDomains;
+
constructor(
private formBuilder: CdFormBuilder,
public activeModal: NgbActiveModal,
private baseValueValidation(dataChunk: boolean = false): boolean {
return this.validValidation(() => {
+ const kMSum =
+ this.form.get('crushFailureDomain').value === CrushFailureDomains.Host
+ ? this.getKMSum() + 1
+ : this.getKMSum();
return (
- this.getKMSum() > this.deviceCount &&
- this.form.getValue('k') > this.form.getValue('m') === dataChunk
+ kMSum > this.deviceCount && this.form.getValue('k') > this.form.getValue('m') === dataChunk
);
});
}
const value = this.form.getValue(name);
ecp[differentApiAttributes[name] || name] = name === 'crushRoot' ? value.name : value;
}
+
+ onCrushFailureDomainChane() {
+ this.form.get('k').updateValueAndValidity();
+ this.form.get('m').updateValueAndValidity();
+ }
}
import _ from 'lodash';
import { CrushNode } from '../models/crush-node';
+import { CrushFailureDomains } from '../models/erasure-code-profile';
export class CrushNodeSelectionClass {
private nodes: CrushNode[] = [];
}
private updateDevices(failureDomain: string = this.controls.failure.value) {
- const subNodes = _.flatten(
- this.failureDomains[failureDomain].map((node) =>
- CrushNodeSelectionClass.getSubNodes(node, this.idTree)
- )
- );
- this.allDevices = subNodes.filter((n) => n.device_class).map((n) => n.device_class);
- this.devices = _.uniq(this.allDevices).sort();
- const device =
- this.devices.length === 1
- ? this.devices[0]
- : this.getIncludedCustomValue(this.controls.device, this.devices);
- if (this.autoDeviceUpdate) this.silentSet(this.controls.device, device);
- this.onDeviceChange(device);
+ if (failureDomain === CrushFailureDomains.Host) {
+ this.allDevices = this.failureDomains[failureDomain]
+ .filter((fD) => fD.type)
+ .map((fD) => fD.type);
+ this.onDeviceChange('');
+ } else {
+ const subNodes = _.flatten(
+ this.failureDomains[failureDomain].map((node) =>
+ CrushNodeSelectionClass.getSubNodes(node, this.idTree)
+ )
+ );
+ this.allDevices = subNodes.filter((n) => n.device_class).map((n) => n.device_class);
+ this.devices = _.uniq(this.allDevices).sort();
+ const device =
+ this.devices.length === 1
+ ? this.devices[0]
+ : this.getIncludedCustomValue(this.controls.device, this.devices);
+ if (this.autoDeviceUpdate) this.silentSet(this.controls.device, device);
+ this.onDeviceChange(device);
+ }
}
private onDeviceChange(deviceType: string = this.controls.device.value) {
'crush-device-class'?: string;
'directory'?: string;
}
+
+export enum CrushFailureDomains {
+ Osd = 'osd',
+ Host = 'host'
+}