upgrade to node v16, support btrfs, images based on bullseye
Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
parent
c5556d2e89
commit
e0657190ed
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -1,3 +1,17 @@
|
|||
# v1.6.0
|
||||
|
||||
Released 2022-03-
|
||||
|
||||
- update `nodejs` version to `v16`
|
||||
- remove dependency on `grpc-uds` package (replaced entirely by
|
||||
`@grpc/grpc-js`)
|
||||
- remove dependency on `request` package (replaced by `axios`)
|
||||
- use native `timeout` functionality for `spawn` operations
|
||||
- update http clients to use `keep-alive` logic
|
||||
- add a default 30s `timeout` to `iscsi` commands
|
||||
- base docker image on `bullseye`
|
||||
- support for `btrfs` as a `fs_type`
|
||||
|
||||
# v1.5.4
|
||||
|
||||
Released 2022-03-03
|
||||
|
|
|
|||
11
Dockerfile
11
Dockerfile
|
|
@ -1,4 +1,4 @@
|
|||
FROM debian:10-slim AS build
|
||||
FROM debian:11-slim AS build
|
||||
#FROM --platform=$BUILDPLATFORM debian:10-slim AS build
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
|
@ -12,8 +12,9 @@ RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/*
|
|||
&& localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8
|
||||
|
||||
ENV LANG=en_US.utf8
|
||||
ENV NODE_VERSION=v12.22.6
|
||||
#ENV NODE_VERSION=v12.22.6
|
||||
#ENV NODE_VERSION=v14.15.1
|
||||
ENV NODE_VERSION=v16.4.0
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# install build deps
|
||||
|
|
@ -32,7 +33,7 @@ RUN useradd --create-home csi \
|
|||
WORKDIR /home/csi/app
|
||||
USER csi
|
||||
|
||||
COPY package*.json ./
|
||||
COPY --chown=csi:csi package*.json ./
|
||||
RUN npm install --grpc_node_binary_host_mirror=https://grpc-uds-binaries.s3-us-west-2.amazonaws.com/debian-buster
|
||||
COPY --chown=csi:csi . .
|
||||
RUN rm -rf docker
|
||||
|
|
@ -41,7 +42,7 @@ RUN rm -rf docker
|
|||
######################
|
||||
# actual image
|
||||
######################
|
||||
FROM debian:10-slim
|
||||
FROM debian:11-slim
|
||||
|
||||
LABEL org.opencontainers.image.source https://github.com/democratic-csi/democratic-csi
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ COPY --from=build /usr/local/lib/nodejs/bin/node /usr/local/bin/node
|
|||
# netbase is required by rpcbind/rpcinfo to work properly
|
||||
# /etc/{services,rpc} are required
|
||||
RUN apt-get update && \
|
||||
apt-get install -y netbase socat e2fsprogs xfsprogs fatresize dosfstools nfs-common cifs-utils sudo && \
|
||||
apt-get install -y netbase socat e2fsprogs xfsprogs btrfs-progs fatresize dosfstools nfs-common cifs-utils sudo && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# controller requirements
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ node:
|
|||
enabled: false
|
||||
customOptions: []
|
||||
customFilesystemOptions: []
|
||||
btrfs:
|
||||
enabled: false
|
||||
customOptions: []
|
||||
customFilesystemOptions: []
|
||||
format:
|
||||
xfs:
|
||||
customOptions: []
|
||||
|
|
@ -21,3 +25,5 @@ node:
|
|||
#- -E
|
||||
#- nodiscard
|
||||
# ...
|
||||
btrfs:
|
||||
customOptions: []
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "democratic-csi",
|
||||
"version": "1.5.5",
|
||||
"version": "1.6.0",
|
||||
"description": "kubernetes csi driver framework",
|
||||
"main": "bin/democratic-csi",
|
||||
"scripts": {
|
||||
|
|
@ -22,14 +22,13 @@
|
|||
"@grpc/proto-loader": "^0.6.0",
|
||||
"@kubernetes/client-node": "^0.16.3",
|
||||
"async-mutex": "^0.3.1",
|
||||
"axios": "^0.26.1",
|
||||
"bunyan": "^1.8.15",
|
||||
"grpc-uds": "^0.1.6",
|
||||
"handlebars": "^4.7.7",
|
||||
"js-yaml": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^7.4.0",
|
||||
"prompt": "^1.2.2",
|
||||
"request": "^2.88.2",
|
||||
"semver": "^7.3.4",
|
||||
"ssh2": "^1.1.0",
|
||||
"uri-js": "^4.4.1",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
const request = require("request");
|
||||
const _ = require("lodash");
|
||||
const http = require("http");
|
||||
const https = require("https");
|
||||
const { axios_request, stringify } = require("../../../utils/general");
|
||||
const Mutex = require("async-mutex").Mutex;
|
||||
|
||||
const USER_AGENT = "democratic-csi";
|
||||
|
|
@ -18,34 +21,57 @@ class SynologyHttpClient {
|
|||
}
|
||||
}
|
||||
|
||||
async login() {
|
||||
if (!this.sid) {
|
||||
// See https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf
|
||||
const data = {
|
||||
api: "SYNO.API.Auth",
|
||||
version: "6",
|
||||
method: "login",
|
||||
account: this.options.username,
|
||||
passwd: this.options.password,
|
||||
session: this.options.session,
|
||||
format: "sid",
|
||||
};
|
||||
|
||||
let response = await this.do_request("GET", "auth.cgi", data);
|
||||
this.sid = response.body.data.sid;
|
||||
getHttpAgent() {
|
||||
if (!this.httpAgent) {
|
||||
this.httpAgent = new http.Agent({
|
||||
keepAlive: true,
|
||||
maxSockets: Infinity,
|
||||
rejectUnauthorized: !!!this.options.allowInsecure,
|
||||
});
|
||||
}
|
||||
|
||||
return this.sid;
|
||||
return this.httpAgent;
|
||||
}
|
||||
|
||||
getHttpsAgent() {
|
||||
if (!this.httpsAgent) {
|
||||
this.httpsAgent = new https.Agent({
|
||||
keepAlive: true,
|
||||
maxSockets: Infinity,
|
||||
rejectUnauthorized: !!!this.options.allowInsecure,
|
||||
});
|
||||
}
|
||||
|
||||
return this.httpsAgent;
|
||||
}
|
||||
|
||||
log_response(error, response, body, options) {
|
||||
this.logger.debug("SYNOLOGY HTTP REQUEST: " + JSON.stringify(options));
|
||||
let prop;
|
||||
let val;
|
||||
|
||||
prop = "auth.username";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
prop = "auth.password";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
prop = "headers.Authorization";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
this.logger.debug("SYNOLOGY HTTP REQUEST: " + stringify(options));
|
||||
this.logger.debug("SYNOLOGY HTTP ERROR: " + error);
|
||||
this.logger.debug("SYNOLOGY HTTP STATUS: " + response.statusCode);
|
||||
this.logger.debug(
|
||||
"SYNOLOGY HTTP HEADERS: " + JSON.stringify(response.headers)
|
||||
);
|
||||
this.logger.debug("SYNOLOGY HTTP BODY: " + JSON.stringify(body));
|
||||
this.logger.debug("SYNOLOGY HTTP HEADERS: " + stringify(response.headers));
|
||||
this.logger.debug("SYNOLOGY HTTP BODY: " + stringify(body));
|
||||
}
|
||||
|
||||
async do_request(method, path, data = {}, options = {}) {
|
||||
|
|
@ -82,10 +108,10 @@ class SynologyHttpClient {
|
|||
? "application/x-www-form-urlencoded"
|
||||
: "application/json",
|
||||
},
|
||||
json: invoke_options.use_form_encoded ? false : true,
|
||||
agentOptions: {
|
||||
rejectUnauthorized: !!!client.options.allowInsecure,
|
||||
},
|
||||
responseType: "json",
|
||||
httpAgent: this.getHttpAgent(),
|
||||
httpsAgent: this.getHttpsAgent(),
|
||||
timeout: 60 * 1000,
|
||||
};
|
||||
|
||||
switch (method) {
|
||||
|
|
@ -96,20 +122,19 @@ class SynologyHttpClient {
|
|||
qsData[p] = JSON.stringify(qsData[p]);
|
||||
}
|
||||
}
|
||||
options.qs = qsData;
|
||||
options.params = qsData;
|
||||
break;
|
||||
default:
|
||||
if (invoke_options.use_form_encoded) {
|
||||
//options.body = URLSearchParams(data);
|
||||
options.form = data;
|
||||
options.data = URLSearchParams(data).toString();
|
||||
} else {
|
||||
options.body = data;
|
||||
options.data = data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
request(options, function (error, response, body) {
|
||||
axios_request(options, function (error, response, body) {
|
||||
client.log_response(...arguments, options);
|
||||
|
||||
if (error) {
|
||||
|
|
@ -147,6 +172,26 @@ class SynologyHttpClient {
|
|||
});
|
||||
}
|
||||
|
||||
async login() {
|
||||
if (!this.sid) {
|
||||
// See https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf
|
||||
const data = {
|
||||
api: "SYNO.API.Auth",
|
||||
version: "6",
|
||||
method: "login",
|
||||
account: this.options.username,
|
||||
passwd: this.options.password,
|
||||
session: this.options.session,
|
||||
format: "sid",
|
||||
};
|
||||
|
||||
let response = await this.do_request("GET", "auth.cgi", data);
|
||||
this.sid = response.body.data.sid;
|
||||
}
|
||||
|
||||
return this.sid;
|
||||
}
|
||||
|
||||
async GetLuns() {
|
||||
const lun_list = {
|
||||
api: "SYNO.Core.ISCSI.LUN",
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class ControllerSynologyDriver extends CsiBaseDriver {
|
|||
if (capability.access_type == "mount") {
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
!["btrfs", "ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class ControllerZfsLocalDriver extends ControllerZfsBaseDriver {
|
|||
case "filesystem":
|
||||
return ["zfs"];
|
||||
case "volume":
|
||||
return ["ext3", "ext4", "ext4dev", "xfs"];
|
||||
return ["btrfs", "ext3", "ext4", "ext4dev", "xfs"];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ class ControllerZfsBaseDriver extends CsiBaseDriver {
|
|||
case "filesystem":
|
||||
return ["nfs", "cifs"];
|
||||
case "volume":
|
||||
return ["ext3", "ext4", "ext4dev", "xfs"];
|
||||
return ["btrfs", "ext3", "ext4", "ext4dev", "xfs"];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1929,7 +1929,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
|
|||
if (capability.access_type == "mount") {
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
!["btrfs", "ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
const request = require("request");
|
||||
const _ = require("lodash");
|
||||
const http = require("http");
|
||||
const https = require("https");
|
||||
const URI = require("uri-js");
|
||||
const { axios_request, stringify } = require("../../../utils/general");
|
||||
const USER_AGENT = "democratic-csi-driver";
|
||||
|
||||
class Client {
|
||||
|
|
@ -12,6 +15,31 @@ class Client {
|
|||
this.options.apiVersion = 1;
|
||||
}
|
||||
}
|
||||
|
||||
getHttpAgent() {
|
||||
if (!this.httpAgent) {
|
||||
this.httpAgent = new http.Agent({
|
||||
keepAlive: true,
|
||||
maxSockets: Infinity,
|
||||
rejectUnauthorized: !!!this.options.allowInsecure,
|
||||
});
|
||||
}
|
||||
|
||||
return this.httpAgent;
|
||||
}
|
||||
|
||||
getHttpsAgent() {
|
||||
if (!this.httpsAgent) {
|
||||
this.httpsAgent = new https.Agent({
|
||||
keepAlive: true,
|
||||
maxSockets: Infinity,
|
||||
rejectUnauthorized: !!!this.options.allowInsecure,
|
||||
});
|
||||
}
|
||||
|
||||
return this.httpsAgent;
|
||||
}
|
||||
|
||||
getBaseURL() {
|
||||
const server = this.options;
|
||||
if (!server.protocol) {
|
||||
|
|
@ -46,14 +74,59 @@ class Client {
|
|||
return this.options.apiVersion;
|
||||
}
|
||||
|
||||
getRequestCommonOptions() {
|
||||
const client = this;
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
responseType: "json",
|
||||
httpAgent: this.getHttpAgent(),
|
||||
httpsAgent: this.getHttpsAgent(),
|
||||
timeout: 60 * 1000,
|
||||
};
|
||||
|
||||
if (client.options.apiKey) {
|
||||
options.headers.Authorization = `Bearer ${client.options.apiKey}`;
|
||||
} else if (client.options.username && client.options.password) {
|
||||
options.auth = {
|
||||
username: client.options.username,
|
||||
password: client.options.password,
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
log_repsonse(error, response, body, options) {
|
||||
this.logger.debug("FREENAS HTTP REQUEST: " + JSON.stringify(options));
|
||||
let prop;
|
||||
let val;
|
||||
|
||||
prop = "auth.username";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
prop = "auth.password";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
prop = "headers.Authorization";
|
||||
val = _.get(options, prop, false);
|
||||
if (val) {
|
||||
_.set(options, prop, "redacted");
|
||||
}
|
||||
|
||||
this.logger.debug("FREENAS HTTP REQUEST: " + stringify(options));
|
||||
this.logger.debug("FREENAS HTTP ERROR: " + error);
|
||||
this.logger.debug("FREENAS HTTP STATUS: " + response.statusCode);
|
||||
this.logger.debug(
|
||||
"FREENAS HTTP HEADERS: " + JSON.stringify(response.headers)
|
||||
);
|
||||
this.logger.debug("FREENAS HTTP BODY: " + JSON.stringify(body));
|
||||
this.logger.debug("FREENAS HTTP HEADERS: " + stringify(response.headers));
|
||||
this.logger.debug("FREENAS HTTP BODY: " + stringify(body));
|
||||
}
|
||||
|
||||
async get(endpoint, data) {
|
||||
|
|
@ -63,33 +136,18 @@ class Client {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
method: "GET",
|
||||
url: this.getBaseURL() + endpoint,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
json: true,
|
||||
qs: data,
|
||||
agentOptions: {
|
||||
rejectUnauthorized: !!!client.options.allowInsecure,
|
||||
},
|
||||
};
|
||||
request(options, function (err, res, body) {
|
||||
const options = client.getRequestCommonOptions();
|
||||
options.method = "GET";
|
||||
options.url = this.getBaseURL() + endpoint;
|
||||
options.params = data;
|
||||
|
||||
axios_request(options, function (err, res, body) {
|
||||
client.log_repsonse(...arguments, options);
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(res);
|
||||
}).auth(
|
||||
client.options.username,
|
||||
client.options.password,
|
||||
true,
|
||||
client.options.apiKey
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -100,33 +158,19 @@ class Client {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
method: "POST",
|
||||
url: this.getBaseURL() + endpoint,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
json: true,
|
||||
body: data,
|
||||
agentOptions: {
|
||||
rejectUnauthorized: !!!client.options.allowInsecure,
|
||||
},
|
||||
};
|
||||
request(options, function (err, res, body) {
|
||||
const options = client.getRequestCommonOptions();
|
||||
options.method = "POST";
|
||||
options.url = this.getBaseURL() + endpoint;
|
||||
options.data = data;
|
||||
|
||||
axios_request(options, function (err, res, body) {
|
||||
client.log_repsonse(...arguments, options);
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(res);
|
||||
}).auth(
|
||||
client.options.username,
|
||||
client.options.password,
|
||||
true,
|
||||
client.options.apiKey
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -137,33 +181,19 @@ class Client {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
method: "PUT",
|
||||
url: this.getBaseURL() + endpoint,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
json: true,
|
||||
body: data,
|
||||
agentOptions: {
|
||||
rejectUnauthorized: !!!client.options.allowInsecure,
|
||||
},
|
||||
};
|
||||
request(options, function (err, res, body) {
|
||||
const options = client.getRequestCommonOptions();
|
||||
options.method = "PUT";
|
||||
options.url = this.getBaseURL() + endpoint;
|
||||
options.data = data;
|
||||
|
||||
axios_request(options, function (err, res, body) {
|
||||
client.log_repsonse(...arguments, options);
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(res);
|
||||
}).auth(
|
||||
client.options.username,
|
||||
client.options.password,
|
||||
true,
|
||||
client.options.apiKey
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -174,33 +204,19 @@ class Client {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
method: "DELETE",
|
||||
url: this.getBaseURL() + endpoint,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
json: true,
|
||||
body: data,
|
||||
agentOptions: {
|
||||
rejectUnauthorized: !!!client.options.allowInsecure,
|
||||
},
|
||||
};
|
||||
request(options, function (err, res, body) {
|
||||
const options = client.getRequestCommonOptions();
|
||||
options.method = "DELETE";
|
||||
options.url = this.getBaseURL() + endpoint;
|
||||
options.data = data;
|
||||
|
||||
axios_request(options, function (err, res, body) {
|
||||
client.log_repsonse(...arguments, options);
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
resolve(res);
|
||||
}).auth(
|
||||
client.options.username,
|
||||
client.options.password,
|
||||
true,
|
||||
client.options.apiKey
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,6 +461,9 @@ class CsiBaseDriver {
|
|||
normalizedSecrets[key];
|
||||
}
|
||||
}
|
||||
|
||||
// create 'DB' entry
|
||||
// TODO: fix flake - Could not execute operation on all records: encountered iSCSI database failure
|
||||
await iscsi.iscsiadm.createNodeDBEntry(
|
||||
iscsiConnection.iqn,
|
||||
iscsiConnection.portal,
|
||||
|
|
@ -804,6 +807,7 @@ class CsiBaseDriver {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case "btrfs":
|
||||
case "xfs":
|
||||
//await filesystem.checkFilesystem(device, fs_info.type);
|
||||
await filesystem.expandFilesystem(staging_target_path, fs_type);
|
||||
|
|
@ -1493,9 +1497,10 @@ class CsiBaseDriver {
|
|||
//await filesystem.checkFilesystem(device, fs_info.type);
|
||||
await filesystem.expandFilesystem(device, fs_type);
|
||||
break;
|
||||
case "btrfs":
|
||||
case "xfs":
|
||||
let mount_info = await mount.getMountDetails(device_path);
|
||||
if (mount_info.fstype == "xfs") {
|
||||
if (["btrfs", "xfs"].includes(mount_info.fstype)) {
|
||||
//await filesystem.checkFilesystem(device, fs_info.type);
|
||||
await filesystem.expandFilesystem(device_path, fs_type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,11 +130,11 @@ class NodeManualDriver extends CsiBaseDriver {
|
|||
break;
|
||||
case "iscsi":
|
||||
driverResourceType = "volume";
|
||||
fs_types = ["ext3", "ext4", "ext4dev", "xfs"];
|
||||
fs_types = ["btrfs", "ext3", "ext4", "ext4dev", "xfs"];
|
||||
break;
|
||||
case "zfs-local":
|
||||
driverResourceType = "volume";
|
||||
fs_types = ["ext3", "ext4", "ext4dev", "xfs", "zfs"];
|
||||
fs_types = ["btrfs", "ext3", "ext4", "ext4dev", "xfs", "zfs"];
|
||||
access_modes = [
|
||||
"UNKNOWN",
|
||||
"SINGLE_NODE_WRITER",
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ class ZfsLocalEphemeralInlineDriver extends CsiBaseDriver {
|
|||
if (capability.access_type == "mount") {
|
||||
if (
|
||||
capability.mount.fs_type &&
|
||||
!["ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
!["btrfs", "ext3", "ext4", "ext4dev", "xfs"].includes(
|
||||
capability.mount.fs_type
|
||||
)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
const cp = require("child_process");
|
||||
const fs = require("fs");
|
||||
|
||||
const DEFAULT_TIMEOUT = process.env.FILESYSTEM_DEFAULT_TIMEOUT || 30000;
|
||||
|
||||
/**
|
||||
* https://github.com/kubernetes/kubernetes/tree/master/pkg/util/mount
|
||||
* https://github.com/kubernetes/kubernetes/blob/master/pkg/util/mount/mount_linux.go
|
||||
|
|
@ -16,10 +18,6 @@ class Filesystem {
|
|||
options.paths.sudo = "/usr/bin/sudo";
|
||||
}
|
||||
|
||||
if (!options.timeout) {
|
||||
options.timeout = 10 * 60 * 1000;
|
||||
}
|
||||
|
||||
if (!options.executor) {
|
||||
options.executor = {
|
||||
spawn: cp.spawn,
|
||||
|
|
@ -454,6 +452,12 @@ class Filesystem {
|
|||
let result;
|
||||
|
||||
switch (fstype.toLowerCase()) {
|
||||
case "btrfs":
|
||||
command = "btrfs";
|
||||
//args = args.concat(options);
|
||||
args = args.concat(["filesystem", "resize", "max"]);
|
||||
args.push(device); // in this case should be a mounted path
|
||||
break;
|
||||
case "ext4":
|
||||
case "ext3":
|
||||
case "ext4dev":
|
||||
|
|
@ -500,6 +504,12 @@ class Filesystem {
|
|||
let result;
|
||||
|
||||
switch (fstype.toLowerCase()) {
|
||||
case "btrfs":
|
||||
command = "btrfs";
|
||||
args = args.concat(options);
|
||||
args.push("check");
|
||||
args.push(device);
|
||||
break;
|
||||
case "ext4":
|
||||
case "ext3":
|
||||
case "ext4dev":
|
||||
|
|
@ -591,11 +601,15 @@ class Filesystem {
|
|||
return true;
|
||||
}
|
||||
|
||||
exec(command, args, options) {
|
||||
exec(command, args, options = {}) {
|
||||
if (!options.hasOwnProperty("timeout")) {
|
||||
// TODO: cannot use this as fsck etc are too risky to kill
|
||||
//options.timeout = DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
const filesystem = this;
|
||||
args = args || [];
|
||||
|
||||
let timeout;
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
|
|
@ -606,14 +620,6 @@ class Filesystem {
|
|||
console.log("executing filesystem command: %s %s", command, args.join(" "));
|
||||
const child = filesystem.options.executor.spawn(command, args, options);
|
||||
|
||||
let didTimeout = false;
|
||||
if (options && options.timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
didTimeout = true;
|
||||
child.kill(options.killSignal || "SIGTERM");
|
||||
}, options.timeout);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.stdout.on("data", function (data) {
|
||||
stdout = stdout + data;
|
||||
|
|
@ -625,10 +631,8 @@ class Filesystem {
|
|||
|
||||
child.on("close", function (code) {
|
||||
const result = { code, stdout, stderr, timeout: false };
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
// timeout scenario
|
||||
if (code === null) {
|
||||
result.timeout = true;
|
||||
reject(result);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
const axios = require("axios");
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
|
|
@ -51,6 +53,46 @@ function getLargestNumber() {
|
|||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* transition function to replicate `request` style requests using axios
|
||||
*
|
||||
* @param {*} options
|
||||
* @param {*} callback
|
||||
*/
|
||||
function axios_request(options, callback = function () {}) {
|
||||
function prep_response(res) {
|
||||
res["statusCode"] = res["status"];
|
||||
delete res["status"];
|
||||
|
||||
res["body"] = res["data"];
|
||||
delete res["data"];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
axios(options)
|
||||
.then((res) => {
|
||||
res = prep_response(res);
|
||||
callback(null, res, res.body);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response) {
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
let res = prep_response(err.response);
|
||||
callback(null, res, res.body);
|
||||
} else if (err.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
callback(err, null, null);
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
callback(err, null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function stringify(value) {
|
||||
const getCircularReplacer = () => {
|
||||
const seen = new WeakSet();
|
||||
|
|
@ -64,11 +106,12 @@ function stringify(value) {
|
|||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
return JSON.stringify(value, getCircularReplacer());
|
||||
}
|
||||
|
||||
module.exports.sleep = sleep;
|
||||
module.exports.lockKeysFromRequest = lockKeysFromRequest;
|
||||
module.exports.getLargestNumber = getLargestNumber;
|
||||
module.exports.stringify = stringify;
|
||||
module.exports.stringify = stringify;
|
||||
module.exports.axios_request = axios_request;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@ class GrpcError {
|
|||
|
||||
module.exports.GrpcError = GrpcError;
|
||||
|
||||
const grpcImplementation = process.env.GRPC_IMPLEMENTATION || "grpc-uds";
|
||||
const grpcImplementation = process.env.GRPC_IMPLEMENTATION || "@grpc/grpc-js";
|
||||
console.log(`grpc implementation: ${grpcImplementation}`);
|
||||
module.exports.grpc = require(grpcImplementation);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ function getIscsiValue(value) {
|
|||
return value;
|
||||
}
|
||||
|
||||
const DEFAULT_TIMEOUT = process.env.ISCSI_DEFAULT_TIMEOUT || 30000;
|
||||
|
||||
class ISCSI {
|
||||
constructor(options = {}) {
|
||||
const iscsi = this;
|
||||
|
|
@ -19,10 +21,6 @@ class ISCSI {
|
|||
options.paths.sudo = "/usr/bin/sudo";
|
||||
}
|
||||
|
||||
if (!options.timeout) {
|
||||
options.timeout = 10 * 60 * 1000;
|
||||
}
|
||||
|
||||
if (!options.executor) {
|
||||
options.executor = {
|
||||
spawn: cp.spawn,
|
||||
|
|
@ -155,10 +153,7 @@ class ISCSI {
|
|||
|
||||
let session = false;
|
||||
sessions.every((i_session) => {
|
||||
if (
|
||||
`${i_session.iqn}` == tgtIQN &&
|
||||
portal == i_session.portal
|
||||
) {
|
||||
if (`${i_session.iqn}` == tgtIQN && portal == i_session.portal) {
|
||||
session = i_session;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -493,11 +488,14 @@ class ISCSI {
|
|||
};
|
||||
}
|
||||
|
||||
exec(command, args, options) {
|
||||
exec(command, args, options = {}) {
|
||||
if (!options.hasOwnProperty("timeout")) {
|
||||
options.timeout = DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
const iscsi = this;
|
||||
args = args || [];
|
||||
|
||||
let timeout;
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
|
|
@ -508,14 +506,6 @@ class ISCSI {
|
|||
console.log("executing iscsi command: %s %s", command, args.join(" "));
|
||||
const child = iscsi.options.executor.spawn(command, args, options);
|
||||
|
||||
let didTimeout = false;
|
||||
if (options && options.timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
didTimeout = true;
|
||||
child.kill(options.killSignal || "SIGTERM");
|
||||
}, options.timeout);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.stdout.on("data", function (data) {
|
||||
stdout = stdout + data;
|
||||
|
|
@ -526,10 +516,14 @@ class ISCSI {
|
|||
});
|
||||
|
||||
child.on("close", function (code) {
|
||||
const result = { code, stdout, stderr };
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
const result = { code, stdout, stderr, timeout: false };
|
||||
|
||||
// timeout scenario
|
||||
if (code === null) {
|
||||
result.timeout = true;
|
||||
reject(result);
|
||||
}
|
||||
|
||||
if (code) {
|
||||
reject(result);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ FINDMNT_COMMON_OPTIONS = [
|
|||
"--nofsroot", // prevents unwanted behavior with cifs volumes
|
||||
];
|
||||
|
||||
DEFAULT_TIMEOUT = process.env.MOUNT_DEFAULT_TIMEOUT || 30000;
|
||||
const DEFAULT_TIMEOUT = process.env.MOUNT_DEFAULT_TIMEOUT || 30000;
|
||||
|
||||
class Mount {
|
||||
constructor(options = {}) {
|
||||
|
|
@ -38,10 +38,6 @@ class Mount {
|
|||
options.paths.chroot = "/usr/sbin/chroot";
|
||||
}
|
||||
|
||||
if (!options.timeout) {
|
||||
options.timeout = 10 * 60 * 1000;
|
||||
}
|
||||
|
||||
if (!options.executor) {
|
||||
options.executor = {
|
||||
spawn: cp.spawn,
|
||||
|
|
@ -389,7 +385,6 @@ class Mount {
|
|||
const mount = this;
|
||||
args = args || [];
|
||||
|
||||
let timeout;
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
|
|
@ -409,18 +404,6 @@ class Mount {
|
|||
console.log("executing mount command: %s", cleansedLog);
|
||||
const child = mount.options.executor.spawn(command, args, options);
|
||||
|
||||
/**
|
||||
* timeout option natively supported since v16
|
||||
* TODO: properly handle this based on nodejs version
|
||||
*/
|
||||
let didTimeout = false;
|
||||
if (options && options.timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
didTimeout = true;
|
||||
child.kill(options.killSignal || "SIGTERM");
|
||||
}, options.timeout);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.stdout.on("data", function (data) {
|
||||
stdout = stdout + data;
|
||||
|
|
@ -433,10 +416,6 @@ class Mount {
|
|||
child.on("close", function (code) {
|
||||
const result = { code, stdout, stderr, timeout: false };
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
// timeout scenario
|
||||
if (code === null) {
|
||||
result.timeout = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const cp = require("child_process");
|
||||
|
||||
DEFAULT_TIMEOUT = process.env.MOUNT_DEFAULT_TIMEOUT || 30000;
|
||||
const DEFAULT_TIMEOUT = process.env.MOUNT_DEFAULT_TIMEOUT || 30000;
|
||||
|
||||
/**
|
||||
* - https://github.com/onedata/oneclient
|
||||
|
|
@ -23,10 +23,6 @@ class OneClient {
|
|||
options.paths.chroot = "/usr/sbin/chroot";
|
||||
}
|
||||
|
||||
if (!options.timeout) {
|
||||
options.timeout = 10 * 60 * 1000;
|
||||
}
|
||||
|
||||
if (!options.executor) {
|
||||
options.executor = {
|
||||
spawn: cp.spawn,
|
||||
|
|
@ -81,7 +77,6 @@ class OneClient {
|
|||
const oneclient = this;
|
||||
args = args || [];
|
||||
|
||||
let timeout;
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
|
|
@ -100,18 +95,6 @@ class OneClient {
|
|||
console.log("executing oneclient command: %s", cleansedLog);
|
||||
const child = oneclient.options.executor.spawn(command, args, options);
|
||||
|
||||
/**
|
||||
* timeout option natively supported since v16
|
||||
* TODO: properly handle this based on nodejs version
|
||||
*/
|
||||
let didTimeout = false;
|
||||
if (options && options.timeout) {
|
||||
timeout = setTimeout(() => {
|
||||
didTimeout = true;
|
||||
child.kill(options.killSignal || "SIGTERM");
|
||||
}, options.timeout);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.stdout.on("data", function (data) {
|
||||
stdout = stdout + data;
|
||||
|
|
@ -124,10 +107,6 @@ class OneClient {
|
|||
child.on("close", function (code) {
|
||||
const result = { code, stdout, stderr, timeout: false };
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
// timeout scenario
|
||||
if (code === null) {
|
||||
result.timeout = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue