Result
This commit is contained in:
53
src/index.ts
53
src/index.ts
@@ -1,5 +1,52 @@
|
|||||||
export class SampleClass {
|
export interface VM {
|
||||||
add(a: number, b: number): number {
|
cpu: number,
|
||||||
return a+b;
|
memory: number,
|
||||||
|
network: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerCapacity {
|
||||||
|
limitCpu: number,
|
||||||
|
limitMemory: number,
|
||||||
|
limitNetwork: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Server = Set<VM>;
|
||||||
|
|
||||||
|
|
||||||
|
export class ServerConsolidation {
|
||||||
|
doesVmFitOnServer(vm: VM, capacity: ServerCapacity): boolean {
|
||||||
|
return vm.cpu <= capacity.limitCpu &&
|
||||||
|
vm.memory <= capacity.limitMemory &&
|
||||||
|
vm.network <= capacity.limitNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
reduceCapacity(vm: VM, capacity: ServerCapacity): void {
|
||||||
|
capacity.limitCpu -= vm.cpu;
|
||||||
|
capacity.limitMemory -= vm.memory;
|
||||||
|
capacity.limitNetwork -= vm.network;
|
||||||
|
}
|
||||||
|
|
||||||
|
fit(vms: VM[], capacity: ServerCapacity): Server[] {
|
||||||
|
const servers: Server[] = [];
|
||||||
|
const capacitiesLeft: ServerCapacity[] = [];
|
||||||
|
for (const vm of vms) {
|
||||||
|
let found = false;
|
||||||
|
for (const [idx, server] of servers.entries()) {
|
||||||
|
const capacity = capacitiesLeft[idx];
|
||||||
|
if (this.doesVmFitOnServer(vm, capacity)) {
|
||||||
|
found = true;
|
||||||
|
server.add(vm);
|
||||||
|
this.reduceCapacity(vm, capacity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
servers.push(new Set([vm]));
|
||||||
|
const newCapacity = {...capacity};
|
||||||
|
this.reduceCapacity(vm, newCapacity);
|
||||||
|
capacitiesLeft.push(newCapacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return servers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
144
test/index.ts
144
test/index.ts
@@ -1,16 +1,140 @@
|
|||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {SampleClass} from '../src';
|
import {ServerCapacity, ServerConsolidation, VM, Server} from '../src';
|
||||||
|
|
||||||
describe('index', () => {
|
interface TestCase {
|
||||||
it('main', () => {
|
vms: VM[],
|
||||||
const cls = new SampleClass();
|
capacity: ServerCapacity,
|
||||||
const cases: [number, number, unknown][] = [
|
results: Server[],
|
||||||
[2, 3, 5],
|
}
|
||||||
[2, 0, 2],
|
|
||||||
[500, -10, 490],
|
describe('ServerConsolidation - fit', () => {
|
||||||
|
const cls = new ServerConsolidation();
|
||||||
|
const vms: {[name: string]: VM} = {
|
||||||
|
'a': {
|
||||||
|
cpu: 1,
|
||||||
|
memory: 1,
|
||||||
|
network: 1,
|
||||||
|
},
|
||||||
|
'b': {
|
||||||
|
cpu: 2,
|
||||||
|
memory: 2,
|
||||||
|
network: 2,
|
||||||
|
},
|
||||||
|
'b-copy': {
|
||||||
|
cpu: 2,
|
||||||
|
memory: 2,
|
||||||
|
network: 2,
|
||||||
|
},
|
||||||
|
'large': {
|
||||||
|
cpu: 10,
|
||||||
|
memory: 10,
|
||||||
|
network: 10,
|
||||||
|
},
|
||||||
|
'd': {
|
||||||
|
cpu: 3,
|
||||||
|
memory: 3,
|
||||||
|
network: 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should match server allocation', () => {
|
||||||
|
const cases: TestCase[] = [
|
||||||
|
// every vm fits on a single server
|
||||||
|
{
|
||||||
|
vms: [vms.a, vms.b],
|
||||||
|
capacity: {
|
||||||
|
limitCpu: 10,
|
||||||
|
limitMemory: 10,
|
||||||
|
limitNetwork: 10,
|
||||||
|
},
|
||||||
|
results: [
|
||||||
|
new Set([vms.a, vms.b]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// multiple servers needed
|
||||||
|
{
|
||||||
|
vms: [vms.a, vms.b, vms.large],
|
||||||
|
capacity: {
|
||||||
|
limitCpu: 10,
|
||||||
|
limitMemory: 10,
|
||||||
|
limitNetwork: 10,
|
||||||
|
},
|
||||||
|
results: [
|
||||||
|
new Set([vms.a, vms.b]),
|
||||||
|
new Set([vms.large]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// reuse of existing servers
|
||||||
|
{
|
||||||
|
vms: [
|
||||||
|
vms.a, vms.b, vms.large, vms.d],
|
||||||
|
capacity: {
|
||||||
|
limitCpu: 10,
|
||||||
|
limitMemory: 10,
|
||||||
|
limitNetwork: 10,
|
||||||
|
},
|
||||||
|
results: [
|
||||||
|
new Set([vms.a, vms.b, vms.d]),
|
||||||
|
new Set([vms.large]),
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
for (const [a, b, res] of cases) {
|
for (const {vms, capacity, results} of cases) {
|
||||||
expect(cls.add(a, b)).to.be.deep.equal(res);
|
const servers = cls.fit(vms, capacity);
|
||||||
|
for (const [idx, server] of servers.entries()) {
|
||||||
|
const result = results[idx];
|
||||||
|
expect(server).to.eqls(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should match reference', () => {
|
||||||
|
const cases: TestCase[] = [
|
||||||
|
// same reference of objects
|
||||||
|
{
|
||||||
|
vms: [
|
||||||
|
vms.a,
|
||||||
|
],
|
||||||
|
capacity: {
|
||||||
|
limitCpu: 10,
|
||||||
|
limitMemory: 10,
|
||||||
|
limitNetwork: 10,
|
||||||
|
},
|
||||||
|
results: [
|
||||||
|
new Set([
|
||||||
|
vms.a,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
for (const {vms, capacity, results} of cases) {
|
||||||
|
const servers = cls.fit(vms, capacity);
|
||||||
|
for (const server of servers[0]) {
|
||||||
|
results[0].has(server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ServerConsolidation - reduceCapacity', () => {
|
||||||
|
const cls = new ServerConsolidation();
|
||||||
|
it('should equal', () => {
|
||||||
|
const capacity: ServerCapacity = {
|
||||||
|
limitCpu: 10,
|
||||||
|
limitMemory: 3,
|
||||||
|
limitNetwork: 9,
|
||||||
|
};
|
||||||
|
const vm: VM = {
|
||||||
|
cpu: 3,
|
||||||
|
memory: 1,
|
||||||
|
network: 0,
|
||||||
|
};
|
||||||
|
const result: ServerCapacity = {
|
||||||
|
limitCpu: 7,
|
||||||
|
limitMemory: 2,
|
||||||
|
limitNetwork: 9,
|
||||||
|
};
|
||||||
|
cls.reduceCapacity(vm, capacity);
|
||||||
|
expect(capacity).to.deep.equal(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user