Skip to content

Commit

Permalink
fix(moac): distribute nexuses more evenly
Browse files Browse the repository at this point in the history
We still keep the rule that one replica is always local to the
nexus, but when deciding which replica is chosen as local we try
to choose the node with smallest number of nexuses.
  • Loading branch information
Jan Kryl committed Jan 19, 2021
1 parent 45d21b7 commit f9eb305
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 3 deletions.
137 changes: 137 additions & 0 deletions csi/moac/test/volumes_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const enums = require('./grpc_enums');
const sleep = require('sleep-promise');

const UUID = 'ba5e39e9-0c0e-4973-8a3a-0dccada09cbb';
const UUID2 = 'aa5e39e9-0c0e-4973-8a3a-0dccada09cbc';
const EYE_BLINK_MS = 30;

module.exports = function () {
Expand Down Expand Up @@ -379,6 +380,142 @@ module.exports = function () {
expect(volume.nexus).to.equal(nexus);
expect(volEvents).to.have.lengthOf(6);
});

it('should distribute nexuses evenly over available nodes', async () => {
const replica1 = new Replica({
uuid: UUID,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID}`
});
const replica2 = new Replica({
uuid: UUID,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID}`
});
const replica3 = new Replica({
uuid: UUID,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID}`
});
const replica4 = new Replica({
uuid: UUID2,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID2}`
});
const replica5 = new Replica({
uuid: UUID2,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID2}`
});
const replica6 = new Replica({
uuid: UUID2,
size: 95,
share: 'REPLICA_NONE',
uri: `bdev:///${UUID2}`
});
replica1.pool = pool1;
replica2.pool = pool2;
replica3.pool = pool3;
replica4.pool = pool1;
replica5.pool = pool2;
replica6.pool = pool3;

// Fake the volume
volume = new Volume(UUID, registry, () => {}, {
replicaCount: 3,
preferredNodes: [],
requiredNodes: [],
requiredBytes: 90,
limitBytes: 110,
protocol: 'nvmf'
});
volume.newReplica(replica1);
volume.newReplica(replica2);
volume.newReplica(replica3);

const volume2 = new Volume(UUID2, registry, () => {}, {
replicaCount: 3,
preferredNodes: [],
requiredNodes: [],
requiredBytes: 90,
limitBytes: 110,
protocol: 'nvmf'
});
volume2.newReplica(replica4);
volume2.newReplica(replica5);
volume2.newReplica(replica6);
volumes.volumes[UUID] = volume;
volumes.volumes[UUID2] = volume2;
volume.state = 'healthy';
volume2.state = 'healthy';

volumes.start();

// set share pcols for replicas of the first volume
stub2.onCall(0).resolves({ uri: `nvmf://${UUID}` });
stub3.onCall(0).resolves({ uri: `nvmf://${UUID}` });
// create first nexus reply
stub1.onCall(0).resolves({
uuid: UUID,
deviceUri: '',
size: 95,
state: 'NEXUS_ONLINE',
children: [{
uri: `bdev:///${UUID}`,
state: 'CHILD_ONLINE'
}, {
uri: `nvmf://${UUID}`,
state: 'CHILD_ONLINE'
}, {
uri: `nvmf://${UUID}`,
state: 'CHILD_ONLINE'
}]
});
// nexus publish reply
stub1.onCall(1).resolves({
deviceUri: `nvmf://${UUID}`
});

// publish the first volume
let uri = await volume.publish('nvmf');
expect(uri).to.equal(`nvmf://${UUID}`);
expect(volume.publishedOn).to.equal('node1');

// set share pcols for replicas of the first volume
stub1.onCall(2).resolves({ uri: `nvmf://${UUID2}` });
stub3.onCall(1).resolves({ uri: `nvmf://${UUID2}` });
// create second nexus reply
stub2.onCall(1).resolves({
uuid: UUID2,
deviceUri: '',
size: 95,
state: 'NEXUS_ONLINE',
children: [{
uri: `bdev:///${UUID2}`,
state: 'CHILD_ONLINE'
}, {
uri: `nvmf://${UUID2}`,
state: 'CHILD_ONLINE'
}, {
uri: `nvmf://${UUID2}`,
state: 'CHILD_ONLINE'
}]
});
// nexus publish reply
stub2.onCall(2).resolves({
deviceUri: `nvmf://${UUID2}`
});

// publish the second volume - should be on a different node
uri = await volume2.publish('nvmf');
expect(uri).to.equal(`nvmf://${UUID2}`);
expect(volume2.publishedOn).to.equal('node2');
});
});

describe('import volume', function () {
Expand Down
13 changes: 10 additions & 3 deletions csi/moac/volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -646,9 +646,16 @@ export class Volume {
}
replicaSet.splice(this.replicaCount);

// If nexus does not exist it will be created on the same node as the most
// preferred replica.
const nexusNode = this.nexus ? this.nexus.node : replicaSet[0].pool!.node;
// If nexus does not exist it will be created on one of the replica nodes
// with the least # of nexuses.
let nexusNode;
if (this.nexus) {
nexusNode = this.nexus.node;
} else {
nexusNode = replicaSet
.map((r: Replica) => r.pool!.node)
.sort((a: Node, b: Node) => a.nexus.length - b.nexus.length)[0];
}

for (let i = 0; i < replicaSet.length; i++) {
const replica = replicaSet[i];
Expand Down

0 comments on commit f9eb305

Please sign in to comment.