mirror of
https://github.com/democratic-csi/democratic-csi.git
synced 2026-10-22 09:30:21 +02:00
windows node support
windows node support for smb/iscsi (csi-proxy) better logging support (for testing) generating volume_id from name wait for chown/chmod jobs to complete (freenas) general improvement to smb behavior throughout Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
@@ -3,7 +3,7 @@ const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const registry = require("../../utils/registry");
|
||||
const SynologyHttpClient = require("./http").SynologyHttpClient;
|
||||
const semver = require("semver");
|
||||
const sleep = require("../../utils/general").sleep;
|
||||
const GeneralUtils = require("../../utils/general");
|
||||
|
||||
const __REGISTRY_NS__ = "ControllerSynologyDriver";
|
||||
|
||||
@@ -171,7 +171,9 @@ class ControllerSynologyDriver extends CsiBaseDriver {
|
||||
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["nfs", "cifs"].includes(capability.mount.fs_type)
|
||||
!GeneralUtils.default_supported_file_filesystems().includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
message = `invalid fs_type ${capability.mount.fs_type}`;
|
||||
return false;
|
||||
@@ -198,7 +200,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
|
||||
if (capability.access_type == "mount") {
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["btrfs", "ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
!GeneralUtils.default_supported_block_filesystems().includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
@@ -609,12 +611,12 @@ class ControllerSynologyDriver extends CsiBaseDriver {
|
||||
|
||||
let waitTimeBetweenChecks = settleSeconds * 1000;
|
||||
|
||||
await sleep(waitTimeBetweenChecks);
|
||||
await GeneralUtils.sleep(waitTimeBetweenChecks);
|
||||
lun_uuid = await httpClient.GetLunUUIDByName(iscsiName);
|
||||
|
||||
while (currentCheck <= settleMaxRetries && lun_uuid) {
|
||||
currentCheck++;
|
||||
await sleep(waitTimeBetweenChecks);
|
||||
await GeneralUtils.sleep(waitTimeBetweenChecks);
|
||||
lun_uuid = await httpClient.GetLunUUIDByName(iscsiName);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const _ = require("lodash");
|
||||
const { ControllerZfsBaseDriver } = require("../controller-zfs");
|
||||
const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const GeneralUtils = require("../../utils/general");
|
||||
const LocalCliExecClient = require("./exec").LocalCliClient;
|
||||
const registry = require("../../utils/registry");
|
||||
const { Zetabyte } = require("../../utils/zfs");
|
||||
@@ -95,7 +96,7 @@ class ControllerZfsLocalDriver extends ControllerZfsBaseDriver {
|
||||
case "filesystem":
|
||||
return ["zfs"];
|
||||
case "volume":
|
||||
return ["btrfs", "ext3", "ext4", "ext4dev", "xfs"];
|
||||
return GeneralUtils.default_supported_block_filesystems();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const _ = require("lodash");
|
||||
const { CsiBaseDriver } = require("../index");
|
||||
const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const sleep = require("../../utils/general").sleep;
|
||||
const GeneralUtils = require("../../utils/general");
|
||||
const getLargestNumber = require("../../utils/general").getLargestNumber;
|
||||
|
||||
const Handlebars = require("handlebars");
|
||||
@@ -201,9 +201,9 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||
switch (driverZfsResourceType) {
|
||||
case "filesystem":
|
||||
return ["nfs", "cifs"];
|
||||
return GeneralUtils.default_supported_file_filesystems();
|
||||
case "volume":
|
||||
return ["btrfs", "ext3", "ext4", "ext4dev", "xfs"];
|
||||
return GeneralUtils.default_supported_block_filesystems();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,6 +620,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
let snapshotParentDatasetName = this.getDetachedSnapshotParentDatasetName();
|
||||
let zvolBlocksize = this.options.zfs.zvolBlocksize || "16K";
|
||||
let name = call.request.name;
|
||||
let volume_id = await driver.getVolumeIdFromName(name);
|
||||
let volume_content_source = call.request.volume_content_source;
|
||||
|
||||
if (!datasetParentName) {
|
||||
@@ -710,7 +711,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
* NOTE: avoid the urge to templatize this given the name length limits for zvols
|
||||
* ie: namespace-name may quite easily exceed 58 chars
|
||||
*/
|
||||
const datasetName = datasetParentName + "/" + name;
|
||||
const datasetName = datasetParentName + "/" + volume_id;
|
||||
|
||||
// ensure volumes with the same name being requested a 2nd time but with a different size fails
|
||||
try {
|
||||
@@ -862,7 +863,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
volume_content_source_snapshot_id +
|
||||
"@" +
|
||||
VOLUME_SOURCE_CLONE_SNAPSHOT_PREFIX +
|
||||
name;
|
||||
volume_id;
|
||||
}
|
||||
|
||||
driver.ctx.logger.debug("full snapshot name: %s", fullSnapshotName);
|
||||
@@ -909,6 +910,12 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
// remove readonly/undesired props
|
||||
let cloneProperties = volumeProperties;
|
||||
delete cloneProperties["aclmode"];
|
||||
delete cloneProperties["aclinherit"];
|
||||
delete cloneProperties["acltype"];
|
||||
delete cloneProperties["casesensitivity"];
|
||||
response = await zb.zfs.clone(fullSnapshotName, datasetName, {
|
||||
properties: volumeProperties,
|
||||
});
|
||||
@@ -971,7 +978,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
volume_content_source_volume_id +
|
||||
"@" +
|
||||
VOLUME_SOURCE_CLONE_SNAPSHOT_PREFIX +
|
||||
name;
|
||||
volume_id;
|
||||
|
||||
driver.ctx.logger.debug("full snapshot name: %s", fullSnapshotName);
|
||||
|
||||
@@ -1024,9 +1031,15 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
} else {
|
||||
// create clone
|
||||
// zfs origin property contains parent info, ie: pool0/k8s/test/PVC-111@clone-test
|
||||
// remove readonly/undesired props
|
||||
let cloneProperties = volumeProperties;
|
||||
delete cloneProperties["aclmode"];
|
||||
delete cloneProperties["aclinherit"];
|
||||
delete cloneProperties["acltype"];
|
||||
delete cloneProperties["casesensitivity"];
|
||||
try {
|
||||
response = await zb.zfs.clone(fullSnapshotName, datasetName, {
|
||||
properties: volumeProperties,
|
||||
properties: cloneProperties,
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.toString().includes("dataset does not exist")) {
|
||||
@@ -1128,8 +1141,13 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
// TODO: this is unsfafe approach, make it better
|
||||
// probably could see if ^-.*\s and split and then shell escape
|
||||
if (this.options.zfs.datasetPermissionsAcls) {
|
||||
let aclBinary = _.get(
|
||||
driver.options,
|
||||
"zfs.datasetPermissionsAclsBinary",
|
||||
"setfacl"
|
||||
);
|
||||
for (const acl of this.options.zfs.datasetPermissionsAcls) {
|
||||
command = execClient.buildCommand("setfacl", [
|
||||
command = execClient.buildCommand(aclBinary, [
|
||||
acl,
|
||||
properties.mountpoint.value,
|
||||
]);
|
||||
@@ -1147,7 +1165,6 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "volume":
|
||||
// set properties
|
||||
@@ -1191,7 +1208,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
|
||||
const res = {
|
||||
volume: {
|
||||
volume_id: name,
|
||||
volume_id,
|
||||
//capacity_bytes: capacity_bytes, // kubernetes currently pukes if capacity is returned as 0
|
||||
capacity_bytes:
|
||||
this.options.zfs.datasetEnableQuotas ||
|
||||
@@ -1315,7 +1332,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
if (current_try > max_tries) {
|
||||
throw err;
|
||||
} else {
|
||||
await sleep(sleep_time);
|
||||
await GeneralUtils.sleep(sleep_time);
|
||||
}
|
||||
} else {
|
||||
throw err;
|
||||
@@ -2190,7 +2207,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
});
|
||||
|
||||
// let things settle down
|
||||
//await sleep(3000);
|
||||
//await GneralUtils.sleep(3000);
|
||||
} else {
|
||||
try {
|
||||
await zb.zfs.snapshot(fullSnapshotName, {
|
||||
@@ -2198,7 +2215,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
});
|
||||
|
||||
// let things settle down
|
||||
//await sleep(3000);
|
||||
//await GeneralUtils.sleep(3000);
|
||||
} catch (err) {
|
||||
if (err.toString().includes("dataset does not exist")) {
|
||||
throw new GrpcError(
|
||||
|
||||
+31
-14
@@ -4,9 +4,8 @@ const { CsiBaseDriver } = require("../index");
|
||||
const HttpClient = require("./http").Client;
|
||||
const TrueNASApiClient = require("./http/api").Api;
|
||||
const { Zetabyte } = require("../../utils/zfs");
|
||||
const getLargestNumber = require("../../utils/general").getLargestNumber;
|
||||
const registry = require("../../utils/registry");
|
||||
const sleep = require("../../utils/general").sleep;
|
||||
const GeneralUtils = require("../../utils/general");
|
||||
|
||||
const Handlebars = require("handlebars");
|
||||
const uuidv4 = require("uuid").v4;
|
||||
@@ -1565,7 +1564,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
targetId,
|
||||
retries
|
||||
);
|
||||
await sleep(retryWait);
|
||||
await GeneralUtils.sleep(retryWait);
|
||||
response = await httpClient.delete(endpoint);
|
||||
}
|
||||
|
||||
@@ -1958,7 +1957,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
if (capability.access_type == "mount") {
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["btrfs", "ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
!GeneralUtils.default_supported_block_filesystems().includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
@@ -2066,6 +2065,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
let snapshotParentDatasetName = this.getDetachedSnapshotParentDatasetName();
|
||||
let zvolBlocksize = this.options.zfs.zvolBlocksize || "16K";
|
||||
let name = call.request.name;
|
||||
let volume_id = await driver.getVolumeIdFromName(name);
|
||||
let volume_content_source = call.request.volume_content_source;
|
||||
let minimum_volume_size = await driver.getMinimumVolumeSize();
|
||||
let default_required_bytes = 1073741824;
|
||||
@@ -2171,7 +2171,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
* NOTE: avoid the urge to templatize this given the name length limits for zvols
|
||||
* ie: namespace-name may quite easily exceed 58 chars
|
||||
*/
|
||||
const datasetName = datasetParentName + "/" + name;
|
||||
const datasetName = datasetParentName + "/" + volume_id;
|
||||
|
||||
// ensure volumes with the same name being requested a 2nd time but with a different size fails
|
||||
try {
|
||||
@@ -2326,7 +2326,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
volume_content_source_snapshot_id +
|
||||
"@" +
|
||||
VOLUME_SOURCE_CLONE_SNAPSHOT_PREFIX +
|
||||
name;
|
||||
volume_id;
|
||||
}
|
||||
|
||||
driver.ctx.logger.debug("full snapshot name: %s", fullSnapshotName);
|
||||
@@ -2378,7 +2378,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
) {
|
||||
job = await httpApiClient.CoreGetJobs({ id: job_id });
|
||||
job = job[0];
|
||||
await sleep(3000);
|
||||
await GeneralUtils.sleep(3000);
|
||||
}
|
||||
|
||||
job.error = job.error || "";
|
||||
@@ -2488,7 +2488,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
volume_content_source_volume_id +
|
||||
"@" +
|
||||
VOLUME_SOURCE_CLONE_SNAPSHOT_PREFIX +
|
||||
name;
|
||||
volume_id;
|
||||
|
||||
driver.ctx.logger.debug("full snapshot name: %s", fullSnapshotName);
|
||||
|
||||
@@ -2538,7 +2538,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
) {
|
||||
job = await httpApiClient.CoreGetJobs({ id: job_id });
|
||||
job = job[0];
|
||||
await sleep(3000);
|
||||
await GeneralUtils.sleep(3000);
|
||||
}
|
||||
|
||||
job.error = job.error || "";
|
||||
@@ -2626,6 +2626,9 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
volsize: driverZfsResourceType == "volume" ? capacity_bytes : undefined,
|
||||
sparse: driverZfsResourceType == "volume" ? sparse : undefined,
|
||||
create_ancestors: true,
|
||||
share_type: driver.getDriverShareType().includes("smb")
|
||||
? "SMB"
|
||||
: "GENERIC",
|
||||
user_properties: httpApiClient.getPropertiesKeyValueArray(
|
||||
httpApiClient.getUserProperties(volumeProperties)
|
||||
),
|
||||
@@ -2721,7 +2724,18 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
}
|
||||
|
||||
if (setPerms) {
|
||||
await httpApiClient.FilesystemSetperm(perms);
|
||||
response = await httpApiClient.FilesystemSetperm(perms);
|
||||
await httpApiClient.CoreWaitForJob(response, 30);
|
||||
// SetPerm does not alter ownership with extended ACLs
|
||||
// run this in addition just for good measure
|
||||
if (perms.uid || perms.gid) {
|
||||
response = await httpApiClient.FilesystemChown({
|
||||
path: perms.path,
|
||||
uid: perms.uid,
|
||||
gid: perms.gid,
|
||||
});
|
||||
await httpApiClient.CoreWaitForJob(response, 30);
|
||||
}
|
||||
}
|
||||
|
||||
// set acls
|
||||
@@ -2777,7 +2791,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
|
||||
const res = {
|
||||
volume: {
|
||||
volume_id: name,
|
||||
volume_id,
|
||||
//capacity_bytes: capacity_bytes, // kubernetes currently pukes if capacity is returned as 0
|
||||
capacity_bytes:
|
||||
this.options.zfs.datasetEnableQuotas ||
|
||||
@@ -3649,7 +3663,10 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
// 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);
|
||||
size_bytes = GeneralUtils.getLargestNumber(
|
||||
row.referenced,
|
||||
row.logicalreferenced
|
||||
);
|
||||
} else {
|
||||
// get the size of the parent volume
|
||||
size_bytes = row.volsize;
|
||||
@@ -3930,7 +3947,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
while (!job || !["SUCCESS", "ABORTED", "FAILED"].includes(job.state)) {
|
||||
job = await httpApiClient.CoreGetJobs({ id: job_id });
|
||||
job = job[0];
|
||||
await sleep(3000);
|
||||
await GeneralUtils.sleep(3000);
|
||||
}
|
||||
|
||||
job.error = job.error || "";
|
||||
@@ -4045,7 +4062,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
||||
// 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(
|
||||
size_bytes = GeneralUtils.getLargestNumber(
|
||||
properties.referenced.rawvalue,
|
||||
properties.logicalreferenced.rawvalue
|
||||
// TODO: perhaps include minimum volume size here?
|
||||
|
||||
@@ -681,7 +681,13 @@ class Api {
|
||||
throw new Error(JSON.stringify(response.body));
|
||||
}
|
||||
|
||||
async CoreWaitForJob(job_id, timeout = 0) {
|
||||
/**
|
||||
*
|
||||
* @param {*} job_id
|
||||
* @param {*} timeout in seconds
|
||||
* @returns
|
||||
*/
|
||||
async CoreWaitForJob(job_id, timeout = 0, check_interval = 3000) {
|
||||
if (!job_id) {
|
||||
throw new Error("invalid job_id");
|
||||
}
|
||||
@@ -692,16 +698,17 @@ class Api {
|
||||
let job;
|
||||
|
||||
// wait for job to finish
|
||||
while (!job || !["SUCCESS", "ABORTED", "FAILED"].includes(job.state)) {
|
||||
do {
|
||||
if (job) {
|
||||
await sleep(check_interval);
|
||||
}
|
||||
job = await this.CoreGetJobs({ id: job_id });
|
||||
job = job[0];
|
||||
await sleep(3000);
|
||||
|
||||
currentTime = Date.now() / 1000;
|
||||
if (timeout > 0 && currentTime > startTime + timeout) {
|
||||
throw new Error("timeout waiting for job to complete");
|
||||
}
|
||||
}
|
||||
} while (!["SUCCESS", "ABORTED", "FAILED"].includes(job.state));
|
||||
|
||||
return job;
|
||||
}
|
||||
@@ -754,7 +761,38 @@ class Api {
|
||||
response = await httpClient.post(endpoint, data);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return;
|
||||
return response.body;
|
||||
}
|
||||
|
||||
throw new Error(JSON.stringify(response.body));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} data
|
||||
*/
|
||||
async FilesystemChown(data) {
|
||||
/*
|
||||
{
|
||||
"path": "string",
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"options": {
|
||||
"recursive": false,
|
||||
"traverse": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
const httpClient = await this.getHttpClient(false);
|
||||
let response;
|
||||
let endpoint;
|
||||
|
||||
endpoint = `/filesystem/chown`;
|
||||
response = await httpClient.post(endpoint, data);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return response.body;
|
||||
}
|
||||
|
||||
throw new Error(JSON.stringify(response.body));
|
||||
|
||||
@@ -122,6 +122,9 @@ class Client {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
delete options.httpAgent;
|
||||
delete options.httpsAgent;
|
||||
|
||||
this.logger.debug("FREENAS HTTP REQUEST: " + stringify(options));
|
||||
this.logger.debug("FREENAS HTTP ERROR: " + error);
|
||||
this.logger.debug("FREENAS HTTP STATUS: " + response.statusCode);
|
||||
|
||||
@@ -4,6 +4,7 @@ const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const registry = require("../../utils/registry");
|
||||
const SshClient = require("../../utils/ssh").SshClient;
|
||||
const HttpClient = require("./http").Client;
|
||||
const TrueNASApiClient = require("./http/api").Api;
|
||||
const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs");
|
||||
const { sleep, stringify } = require("../../utils/general");
|
||||
|
||||
@@ -112,6 +113,13 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
);
|
||||
}
|
||||
|
||||
async getTrueNASHttpApiClient() {
|
||||
return registry.getAsync(`${__REGISTRY_NS__}:api_client`, async () => {
|
||||
const httpClient = await this.getHttpClient();
|
||||
return new TrueNASApiClient(httpClient, this.ctx.cache);
|
||||
});
|
||||
}
|
||||
|
||||
getDriverShareType() {
|
||||
switch (this.options.driver) {
|
||||
case "freenas-nfs":
|
||||
@@ -1716,6 +1724,7 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
async setFilesystemMode(path, mode) {
|
||||
const httpClient = await this.getHttpClient();
|
||||
const apiVersion = httpClient.getApiVersion();
|
||||
const httpApiClient = await this.getTrueNASHttpApiClient();
|
||||
|
||||
switch (apiVersion) {
|
||||
case 1:
|
||||
@@ -1747,6 +1756,7 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
response = await httpClient.post(endpoint, perms);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
await httpApiClient.CoreWaitForJob(response.body, 30);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1764,6 +1774,7 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
async setFilesystemOwnership(path, user = false, group = false) {
|
||||
const httpClient = await this.getHttpClient();
|
||||
const apiVersion = httpClient.getApiVersion();
|
||||
const httpApiClient = await this.getTrueNASHttpApiClient();
|
||||
|
||||
if (user === false || typeof user == "undefined" || user === null) {
|
||||
user = "";
|
||||
@@ -1832,6 +1843,7 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
response = await httpClient.post(endpoint, perms);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
await httpApiClient.CoreWaitForJob(response.body, 30);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1855
-852
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user