attempt proper logic for snapshot size_bytes

Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
Travis Glenn Hansen 2021-11-03 20:46:12 -06:00
parent 567ce8545e
commit ff99a8fcd2
4 changed files with 313 additions and 724 deletions

959
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "democratic-csi", "name": "democratic-csi",
"version": "1.4.2", "version": "1.4.3",
"description": "kubernetes csi driver framework", "description": "kubernetes csi driver framework",
"main": "bin/democratic-csi", "main": "bin/democratic-csi",
"scripts": { "scripts": {
@ -38,6 +38,6 @@
"yargs": "^17.0.1" "yargs": "^17.0.1"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.22.0" "eslint": "^8.1.0"
} }
} }

View File

@ -2,6 +2,7 @@ const { CsiBaseDriver } = require("../index");
const SshClient = require("../../utils/ssh").SshClient; const SshClient = require("../../utils/ssh").SshClient;
const { GrpcError, grpc } = require("../../utils/grpc"); const { GrpcError, grpc } = require("../../utils/grpc");
const sleep = require("../../utils/general").sleep; const sleep = require("../../utils/general").sleep;
const getLargestNumber = require("../../utils/general").getLargestNumber;
const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs"); const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs");
@ -1248,7 +1249,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
let sleep_time = 3000; let sleep_time = 3000;
let current_try = 1; let current_try = 1;
let success = false; let success = false;
while(!success && current_try <= max_tries) { while (!success && current_try <= max_tries) {
try { try {
await zb.zfs.destroy(datasetName, { recurse: true, force: true }); await zb.zfs.destroy(datasetName, { recurse: true, force: true });
success = true; success = true;
@ -1800,6 +1801,9 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
"refquota", "refquota",
"avail", "avail",
"used", "used",
"volsize",
"referenced",
"logicalreferenced",
VOLUME_CSI_NAME_PROPERTY_NAME, VOLUME_CSI_NAME_PROPERTY_NAME,
SNAPSHOT_CSI_NAME_PROPERTY_NAME, SNAPSHOT_CSI_NAME_PROPERTY_NAME,
MANAGED_PROPERTY_NAME, MANAGED_PROPERTY_NAME,
@ -1864,6 +1868,20 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
return; return;
} }
// TODO: properly handle use-case where datasetEnableQuotas is not turned on
let size_bytes = 0;
if (driverZfsResourceType == "filesystem") {
// independent of detached snapshots when creating a volume from a 'snapshot'
// we could be using detached clones (ie: send/receive)
// so we must be cognizant and use the highest possible value here
// note that whatever value is returned here can/will essentially impact the refquota
// value of a derived volume
size_bytes = getLargestNumber(row.referenced, row.logicalreferenced);
} else {
// get the size of the parent volume
size_bytes = row.volsize;
}
if (source_volume_id) if (source_volume_id)
entries.push({ entries.push({
snapshot: { snapshot: {
@ -1874,7 +1892,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
* In that vein, I think it's best to return 0 here given the * In that vein, I think it's best to return 0 here given the
* unknowns of 'cow' implications. * unknowns of 'cow' implications.
*/ */
//size_bytes: 0, size_bytes,
// remove parent dataset details // remove parent dataset details
snapshot_id: row["name"].replace( snapshot_id: row["name"].replace(
@ -1920,6 +1938,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
const driverZfsResourceType = this.getDriverZfsResourceType(); const driverZfsResourceType = this.getDriverZfsResourceType();
const zb = await this.getZetabyte(); const zb = await this.getZetabyte();
let size_bytes = 0;
let detachedSnapshot = false; let detachedSnapshot = false;
try { try {
let tmpDetachedSnapshot = JSON.parse( let tmpDetachedSnapshot = JSON.parse(
@ -1976,6 +1995,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
); );
} }
const volumeDatasetName = volumeParentDatasetName + "/" + source_volume_id;
const datasetName = datasetParentName + "/" + source_volume_id; const datasetName = datasetParentName + "/" + source_volume_id;
snapshotProperties[SNAPSHOT_CSI_NAME_PROPERTY_NAME] = name; snapshotProperties[SNAPSHOT_CSI_NAME_PROPERTY_NAME] = name;
snapshotProperties[SNAPSHOT_CSI_SOURCE_VOLUME_ID_PROPERTY_NAME] = snapshotProperties[SNAPSHOT_CSI_SOURCE_VOLUME_ID_PROPERTY_NAME] =
@ -2062,12 +2082,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
if (detachedSnapshot) { if (detachedSnapshot) {
tmpSnapshotName = tmpSnapshotName =
volumeParentDatasetName + volumeDatasetName + "@" + VOLUME_SOURCE_DETACHED_SNAPSHOT_PREFIX + name;
"/" +
source_volume_id +
"@" +
VOLUME_SOURCE_DETACHED_SNAPSHOT_PREFIX +
name;
snapshotDatasetName = datasetName + "/" + name; snapshotDatasetName = datasetName + "/" + name;
await zb.zfs.create(datasetName, { parents: true }); await zb.zfs.create(datasetName, { parents: true });
@ -2123,11 +2138,17 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
force: true, force: true,
defer: true, defer: true,
}); });
// let things settle down
//await sleep(3000);
} else { } else {
try { try {
await zb.zfs.snapshot(fullSnapshotName, { await zb.zfs.snapshot(fullSnapshotName, {
properties: snapshotProperties, properties: snapshotProperties,
}); });
// let things settle down
//await sleep(3000);
} catch (err) { } catch (err) {
if (err.toString().includes("dataset does not exist")) { if (err.toString().includes("dataset does not exist")) {
throw new GrpcError( throw new GrpcError(
@ -2150,6 +2171,11 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
"refquota", "refquota",
"avail", "avail",
"used", "used",
"volsize",
"referenced",
"refreservation",
"logicalused",
"logicalreferenced",
VOLUME_CSI_NAME_PROPERTY_NAME, VOLUME_CSI_NAME_PROPERTY_NAME,
SNAPSHOT_CSI_NAME_PROPERTY_NAME, SNAPSHOT_CSI_NAME_PROPERTY_NAME,
SNAPSHOT_CSI_SOURCE_VOLUME_ID_PROPERTY_NAME, SNAPSHOT_CSI_SOURCE_VOLUME_ID_PROPERTY_NAME,
@ -2160,6 +2186,22 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
properties = properties[fullSnapshotName]; properties = properties[fullSnapshotName];
driver.ctx.logger.verbose("snapshot properties: %j", properties); driver.ctx.logger.verbose("snapshot properties: %j", properties);
// TODO: properly handle use-case where datasetEnableQuotas is not turned on
if (driverZfsResourceType == "filesystem") {
// independent of detached snapshots when creating a volume from a 'snapshot'
// we could be using detached clones (ie: send/receive)
// so we must be cognizant and use the highest possible value here
// note that whatever value is returned here can/will essentially impact the refquota
// value of a derived volume
size_bytes = getLargestNumber(
properties.referenced.value,
properties.logicalreferenced.value
);
} else {
// get the size of the parent volume
size_bytes = properties.volsize.value;
}
// set this just before sending out response so we know if volume completed // set this just before sending out response so we know if volume completed
// this should give us a relatively sane way to clean up artifacts over time // this should give us a relatively sane way to clean up artifacts over time
await zb.zfs.set(fullSnapshotName, { [SUCCESS_PROPERTY_NAME]: "true" }); await zb.zfs.set(fullSnapshotName, { [SUCCESS_PROPERTY_NAME]: "true" });
@ -2173,7 +2215,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
* In that vein, I think it's best to return 0 here given the * In that vein, I think it's best to return 0 here given the
* unknowns of 'cow' implications. * unknowns of 'cow' implications.
*/ */
//size_bytes: 0, size_bytes,
// remove parent dataset details // remove parent dataset details
snapshot_id: properties.name.value.replace( snapshot_id: properties.name.value.replace(

View File

@ -34,5 +34,23 @@ function lockKeysFromRequest(call, serviceMethodName) {
} }
} }
function getLargestNumber() {
let number;
for (let i = 0; i < arguments.length; i++) {
value = Number(arguments[i]);
if (isNaN(value)) {
continue;
}
if (isNaN(number)) {
number = value;
continue;
}
number = value > number ? value : number;
}
return number;
}
module.exports.sleep = sleep; module.exports.sleep = sleep;
module.exports.lockKeysFromRequest = lockKeysFromRequest; module.exports.lockKeysFromRequest = lockKeysFromRequest;
module.exports.getLargestNumber = getLargestNumber;