mirror of
https://github.com/democratic-csi/democratic-csi.git
synced 2026-10-21 22:36:45 +02:00
more robust code for setting filesystem mode/ownership, use TrueNAS api when available to facilitate sudo-less ssh user
Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
const _ = require("lodash");
|
||||
const { CsiBaseDriver } = require("../index");
|
||||
const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const sleep = require("../../utils/general").sleep;
|
||||
@@ -453,6 +454,64 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
}
|
||||
}
|
||||
|
||||
async setFilesystemMode(path, mode) {
|
||||
const driver = this;
|
||||
const execClient = this.getExecClient();
|
||||
|
||||
let command = execClient.buildCommand("chmod", [mode, path]);
|
||||
if ((await driver.getWhoAmI()) != "root") {
|
||||
command = (await driver.getSudoPath()) + " " + command;
|
||||
}
|
||||
|
||||
driver.ctx.logger.verbose("set permission command: %s", command);
|
||||
|
||||
let response = await execClient.exec(command);
|
||||
if (response.code != 0) {
|
||||
throw new GrpcError(
|
||||
grpc.status.UNKNOWN,
|
||||
`error setting permissions on dataset: ${JSON.stringify(response)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async setFilesystemOwnership(path, user = false, group = false) {
|
||||
const driver = this;
|
||||
const execClient = this.getExecClient();
|
||||
|
||||
if (user === false || typeof user == "undefined" || user === null) {
|
||||
user = "";
|
||||
}
|
||||
|
||||
if (group === false || typeof group == "undefined" || group === null) {
|
||||
group = "";
|
||||
}
|
||||
|
||||
user = String(user);
|
||||
group = String(group);
|
||||
|
||||
if (user.length < 1 && group.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let command = execClient.buildCommand("chown", [
|
||||
(user.length > 0 ? user : "") + ":" + (group.length > 0 ? group : ""),
|
||||
path,
|
||||
]);
|
||||
if ((await driver.getWhoAmI()) != "root") {
|
||||
command = (await driver.getSudoPath()) + " " + command;
|
||||
}
|
||||
|
||||
driver.ctx.logger.verbose("set ownership command: %s", command);
|
||||
|
||||
let response = await execClient.exec(command);
|
||||
if (response.code != 0) {
|
||||
throw new GrpcError(
|
||||
grpc.status.UNKNOWN,
|
||||
`error setting ownership on dataset: ${JSON.stringify(response)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure sane options are used etc
|
||||
* true = ready
|
||||
@@ -1013,10 +1072,6 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
await zb.zfs.set(datasetName, properties);
|
||||
}
|
||||
|
||||
//datasetPermissionsMode: 0777,
|
||||
//datasetPermissionsUser: "root",
|
||||
//datasetPermissionsGroup: "wheel",
|
||||
|
||||
// get properties needed for remaining calls
|
||||
properties = await zb.zfs.get(datasetName, [
|
||||
"mountpoint",
|
||||
@@ -1031,53 +1086,24 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
||||
|
||||
// set mode
|
||||
if (this.options.zfs.datasetPermissionsMode) {
|
||||
command = execClient.buildCommand("chmod", [
|
||||
this.options.zfs.datasetPermissionsMode,
|
||||
await driver.setFilesystemMode(
|
||||
properties.mountpoint.value,
|
||||
]);
|
||||
if ((await this.getWhoAmI()) != "root") {
|
||||
command = (await this.getSudoPath()) + " " + command;
|
||||
}
|
||||
|
||||
driver.ctx.logger.verbose("set permission command: %s", command);
|
||||
response = await execClient.exec(command);
|
||||
if (response.code != 0) {
|
||||
throw new GrpcError(
|
||||
grpc.status.UNKNOWN,
|
||||
`error setting permissions on dataset: ${JSON.stringify(
|
||||
response
|
||||
)}`
|
||||
);
|
||||
}
|
||||
this.options.zfs.datasetPermissionsMode
|
||||
);
|
||||
}
|
||||
|
||||
// set ownership
|
||||
if (
|
||||
this.options.zfs.datasetPermissionsUser ||
|
||||
this.options.zfs.datasetPermissionsGroup
|
||||
String(_.get(this.options, "zfs.datasetPermissionsUser", "")).length >
|
||||
0 ||
|
||||
String(_.get(this.options, "zfs.datasetPermissionsGroup", ""))
|
||||
.length > 0
|
||||
) {
|
||||
command = execClient.buildCommand("chown", [
|
||||
(this.options.zfs.datasetPermissionsUser
|
||||
? this.options.zfs.datasetPermissionsUser
|
||||
: "") +
|
||||
":" +
|
||||
(this.options.zfs.datasetPermissionsGroup
|
||||
? this.options.zfs.datasetPermissionsGroup
|
||||
: ""),
|
||||
await driver.setFilesystemOwnership(
|
||||
properties.mountpoint.value,
|
||||
]);
|
||||
if ((await this.getWhoAmI()) != "root") {
|
||||
command = (await this.getSudoPath()) + " " + command;
|
||||
}
|
||||
|
||||
driver.ctx.logger.verbose("set ownership command: %s", command);
|
||||
response = await execClient.exec(command);
|
||||
if (response.code != 0) {
|
||||
throw new GrpcError(
|
||||
grpc.status.UNKNOWN,
|
||||
`error setting ownership on dataset: ${JSON.stringify(response)}`
|
||||
);
|
||||
}
|
||||
this.options.zfs.datasetPermissionsUser,
|
||||
this.options.zfs.datasetPermissionsGroup
|
||||
);
|
||||
}
|
||||
|
||||
// set acls
|
||||
|
||||
+167
-2
@@ -1657,9 +1657,143 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
}
|
||||
}
|
||||
|
||||
async setFilesystemMode(path, mode) {
|
||||
const httpClient = await this.getHttpClient();
|
||||
const apiVersion = httpClient.getApiVersion();
|
||||
|
||||
switch (apiVersion) {
|
||||
case 1:
|
||||
return super.setFilesystemMode(...arguments);
|
||||
case 2:
|
||||
let perms = {
|
||||
path,
|
||||
mode: String(mode),
|
||||
};
|
||||
|
||||
/*
|
||||
{
|
||||
"path": "string",
|
||||
"mode": "string",
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"options": {
|
||||
"stripacl": false,
|
||||
"recursive": false,
|
||||
"traverse": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
let response;
|
||||
let endpoint;
|
||||
|
||||
endpoint = `/filesystem/setperm`;
|
||||
response = await httpClient.post(endpoint, perms);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(JSON.stringify(response.body));
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new GrpcError(
|
||||
grpc.status.FAILED_PRECONDITION,
|
||||
`invalid configuration: unknown apiVersion ${apiVersion}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async setFilesystemOwnership(path, user = false, group = false) {
|
||||
const httpClient = await this.getHttpClient();
|
||||
const apiVersion = httpClient.getApiVersion();
|
||||
|
||||
if (user === false || typeof user == "undefined" || user === null) {
|
||||
user = "";
|
||||
}
|
||||
|
||||
if (group === false || typeof group == "undefined" || group === null) {
|
||||
group = "";
|
||||
}
|
||||
|
||||
user = String(user);
|
||||
group = String(group);
|
||||
|
||||
if (user.length < 1 && group.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (apiVersion) {
|
||||
case 1:
|
||||
return super.setFilesystemOwnership(...arguments);
|
||||
case 2:
|
||||
let perms = {
|
||||
path,
|
||||
};
|
||||
// set ownership
|
||||
|
||||
// user
|
||||
if (user.length > 0) {
|
||||
if (String(user).match(/^[0-9]+$/) == null) {
|
||||
throw new GrpcError(
|
||||
grpc.status.FAILED_PRECONDITION,
|
||||
`datasetPermissionsUser must be numeric: ${user}`
|
||||
);
|
||||
}
|
||||
perms.uid = Number(user);
|
||||
}
|
||||
|
||||
// group
|
||||
if (group.length > 0) {
|
||||
if (String(group).match(/^[0-9]+$/) == null) {
|
||||
throw new GrpcError(
|
||||
grpc.status.FAILED_PRECONDITION,
|
||||
`datasetPermissionsGroup must be numeric: ${group}`
|
||||
);
|
||||
}
|
||||
perms.gid = Number(group);
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"path": "string",
|
||||
"mode": "string",
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"options": {
|
||||
"stripacl": false,
|
||||
"recursive": false,
|
||||
"traverse": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
let response;
|
||||
let endpoint;
|
||||
|
||||
endpoint = `/filesystem/setperm`;
|
||||
response = await httpClient.post(endpoint, perms);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(JSON.stringify(response.body));
|
||||
break;
|
||||
default:
|
||||
throw new GrpcError(
|
||||
grpc.status.FAILED_PRECONDITION,
|
||||
`invalid configuration: unknown apiVersion ${apiVersion}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async expandVolume(call, datasetName) {
|
||||
const driverShareType = this.getDriverShareType();
|
||||
const execClient = this.getExecClient();
|
||||
const httpClient = await this.getHttpClient();
|
||||
const apiVersion = httpClient.getApiVersion();
|
||||
const zb = await this.getZetabyte();
|
||||
|
||||
switch (driverShareType) {
|
||||
@@ -1696,8 +1830,39 @@ class FreeNASSshDriver extends ControllerZfsBaseDriver {
|
||||
]);
|
||||
reload = true;
|
||||
} else {
|
||||
command = execClient.buildCommand("/etc/rc.d/ctld", ["reload"]);
|
||||
reload = true;
|
||||
switch (apiVersion) {
|
||||
case 1:
|
||||
// use cli for now
|
||||
command = execClient.buildCommand("/etc/rc.d/ctld", ["reload"]);
|
||||
reload = true;
|
||||
break;
|
||||
case 2:
|
||||
this.ctx.logger.verbose(
|
||||
"FreeNAS reloading iscsi daemon using api"
|
||||
);
|
||||
// POST /service/reload
|
||||
let payload = {
|
||||
service: "iscsitarget", // api version of ctld, same name in SCALE as well
|
||||
"service-control": {
|
||||
ha_propagate: true,
|
||||
},
|
||||
};
|
||||
let response = await httpClient.post("/service/reload", payload);
|
||||
if (![200, 204].includes(response.statusCode)) {
|
||||
throw new GrpcError(
|
||||
grpc.status.UNKNOWN,
|
||||
`error reloading iscsi daemon - code: ${
|
||||
response.statusCode
|
||||
} body: ${JSON.stringify(response.body)}`
|
||||
);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
throw new GrpcError(
|
||||
grpc.status.FAILED_PRECONDITION,
|
||||
`invalid configuration: unknown apiVersion ${apiVersion}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (reload) {
|
||||
|
||||
Reference in New Issue
Block a user