mirror of
https://github.com/democratic-csi/democratic-csi.git
synced 2026-10-18 00:33:08 +02:00
foundations for more flexible iscsi connections
Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
+51
-9
@@ -298,6 +298,14 @@ class CsiBaseDriver {
|
||||
call.request.volume_context.provisioner_driver_instance_id
|
||||
);
|
||||
|
||||
/*
|
||||
let mount_options = await mount.getMountOptions(staging_target_path);
|
||||
console.log(mount_options);
|
||||
console.log(await mount.getMountOptionValue(mount_options, "stripe"));
|
||||
console.log(await mount.getMountOptionPresent(mount_options, "stripee"));
|
||||
throw new Error("foobar");
|
||||
*/
|
||||
|
||||
if (access_type == "mount") {
|
||||
fs_type = capability.mount.fs_type;
|
||||
mount_flags = capability.mount.mount_flags || [];
|
||||
@@ -307,6 +315,10 @@ class CsiBaseDriver {
|
||||
}
|
||||
mount_flags.push("defaults");
|
||||
|
||||
// https://github.com/karelzak/util-linux/issues/1429
|
||||
//mount_flags.push("x-democratic-csi.managed");
|
||||
//mount_flags.push("x-democratic-csi.staged");
|
||||
|
||||
if (
|
||||
semver.satisfies(driver.ctx.csiVersion, ">=1.5.0") &&
|
||||
driver.options.service.node.capabilities.rpc.includes(
|
||||
@@ -373,9 +385,27 @@ class CsiBaseDriver {
|
||||
// ensure unique entries only
|
||||
portals = [...new Set(portals)];
|
||||
|
||||
// stores actual device paths after iscsi login
|
||||
let iscsiDevices = [];
|
||||
|
||||
// stores configuration of targets/iqn/luns to connect to
|
||||
let iscsiConnections = [];
|
||||
for (let portal of portals) {
|
||||
iscsiConnections.push({
|
||||
portal,
|
||||
iqn: volume_context.iqn,
|
||||
lun: volume_context.lun,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: allow sending in iscsiConnection in a raw/manual format
|
||||
* TODO: allow option to determine if send_targets should be invoked
|
||||
* TODO: allow option to control whether nodedb entry should be created by driver
|
||||
* TODO: allow option to control whether nodedb entry should be deleted by driver
|
||||
*/
|
||||
|
||||
for (let iscsiConnection of iscsiConnections) {
|
||||
// create DB entry
|
||||
// https://library.netapp.com/ecmdocs/ECMP1654943/html/GUID-8EC685B4-8CB6-40D8-A8D5-031A3899BCDC.html
|
||||
// put these options in place to force targets managed by csi to be explicitly attached (in the case of unclearn shutdown etc)
|
||||
@@ -391,24 +421,27 @@ class CsiBaseDriver {
|
||||
}
|
||||
}
|
||||
await iscsi.iscsiadm.createNodeDBEntry(
|
||||
volume_context.iqn,
|
||||
portal,
|
||||
iscsiConnection.iqn,
|
||||
iscsiConnection.portal,
|
||||
nodeDB
|
||||
);
|
||||
// login
|
||||
await iscsi.iscsiadm.login(volume_context.iqn, portal);
|
||||
await iscsi.iscsiadm.login(
|
||||
iscsiConnection.iqn,
|
||||
iscsiConnection.portal
|
||||
);
|
||||
|
||||
// get associated session
|
||||
let session = await iscsi.iscsiadm.getSession(
|
||||
volume_context.iqn,
|
||||
portal
|
||||
iscsiConnection.iqn,
|
||||
iscsiConnection.portal
|
||||
);
|
||||
|
||||
// rescan in scenarios when login previously occurred but volumes never appeared
|
||||
await iscsi.iscsiadm.rescanSession(session);
|
||||
|
||||
// find device name
|
||||
device = `/dev/disk/by-path/ip-${portal}-iscsi-${volume_context.iqn}-lun-${volume_context.lun}`;
|
||||
device = `/dev/disk/by-path/ip-${iscsiConnection.portal}-iscsi-${iscsiConnection.iqn}-lun-${iscsiConnection.lun}`;
|
||||
let deviceByPath = device;
|
||||
|
||||
// can take some time for device to show up, loop for some period
|
||||
@@ -439,7 +472,7 @@ class CsiBaseDriver {
|
||||
iscsiDevices.push(device);
|
||||
|
||||
driver.ctx.logger.info(
|
||||
`successfully logged into portal ${portal} and created device ${deviceByPath} with realpath ${device}`
|
||||
`successfully logged into portal ${iscsiConnection.portal} and created device ${deviceByPath} with realpath ${device}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -461,7 +494,7 @@ class CsiBaseDriver {
|
||||
);
|
||||
}
|
||||
|
||||
if (iscsiDevices.length != portals.length) {
|
||||
if (iscsiDevices.length != iscsiConnections.length) {
|
||||
driver.ctx.logger.warn(
|
||||
`failed to attach all iscsi devices/targets/portals`
|
||||
);
|
||||
@@ -484,7 +517,8 @@ class CsiBaseDriver {
|
||||
iscsiDevices.includes(value)
|
||||
);
|
||||
|
||||
const useMultipath = portals.length > 1 || commonDevices.length > 0;
|
||||
const useMultipath =
|
||||
iscsiConnections.length > 1 || commonDevices.length > 0;
|
||||
|
||||
// discover multipath device to use
|
||||
if (useMultipath) {
|
||||
@@ -679,6 +713,8 @@ class CsiBaseDriver {
|
||||
//result = await mount.pathIsMounted(block_path);
|
||||
//result = await mount.pathIsMounted(staging_target_path)
|
||||
|
||||
// TODO: use the x-* mount options to detect if we should delete target
|
||||
|
||||
try {
|
||||
result = await mount.pathIsMounted(block_path);
|
||||
} catch (err) {
|
||||
@@ -900,7 +936,13 @@ class CsiBaseDriver {
|
||||
}
|
||||
|
||||
bind_mount_flags.push("defaults");
|
||||
|
||||
// https://github.com/karelzak/util-linux/issues/1429
|
||||
//bind_mount_flags.push("x-democratic-csi.managed");
|
||||
//bind_mount_flags.push("x-democratic-csi.published");
|
||||
|
||||
if (readonly) bind_mount_flags.push("ro");
|
||||
// , "x-democratic-csi.ro"
|
||||
|
||||
switch (node_attach_driver) {
|
||||
case "nfs":
|
||||
|
||||
@@ -326,9 +326,14 @@ class Filesystem {
|
||||
try {
|
||||
result = await filesystem.exec("blkid", args);
|
||||
} catch (err) {
|
||||
if (err.code == 2 && err.stderr.includes("No such device or address")) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (err.code == 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
|
||||
+90
-1
@@ -145,7 +145,7 @@ class Mount {
|
||||
*
|
||||
* @param {*} path
|
||||
*/
|
||||
async getMountDetails(path, extraOutputProperties = []) {
|
||||
async getMountDetails(path, extraOutputProperties = [], extraArgs = []) {
|
||||
const mount = this;
|
||||
let args = [];
|
||||
const common_options = JSON.parse(JSON.stringify(FINDMNT_COMMON_OPTIONS));
|
||||
@@ -156,6 +156,7 @@ class Mount {
|
||||
|
||||
args = args.concat(["--mountpoint", path]);
|
||||
args = args.concat(common_options);
|
||||
args = args.concat(extraArgs);
|
||||
let result;
|
||||
|
||||
try {
|
||||
@@ -167,6 +168,94 @@ class Mount {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse a mount options string into an array
|
||||
*
|
||||
* @param {*} options
|
||||
* @returns
|
||||
*/
|
||||
async parseMountOptions(options) {
|
||||
if (!options) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (Array.isArray(options)) {
|
||||
return options;
|
||||
}
|
||||
|
||||
options = options.split(",");
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the set of mount options and sought after option, return true if the option is present
|
||||
*
|
||||
* @param {*} options
|
||||
* @param {*} option
|
||||
* @returns
|
||||
*/
|
||||
async getMountOptionPresent(options, option) {
|
||||
const mount = this;
|
||||
|
||||
if (!Array.isArray(options)) {
|
||||
options = await mount.parseMountOptions(options);
|
||||
}
|
||||
|
||||
for (let i of options) {
|
||||
let parts = i.split("=", 2);
|
||||
if (parts[0] == option) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the given mount option
|
||||
*
|
||||
* if the mount option is present by has no value null is returned
|
||||
* if the mount option is NOT present undefined is returned
|
||||
* is the mount option has a value that value is returned
|
||||
*
|
||||
* @param {*} options
|
||||
* @param {*} option
|
||||
* @returns
|
||||
*/
|
||||
async getMountOptionValue(options, option) {
|
||||
const mount = this;
|
||||
|
||||
if (!Array.isArray(options)) {
|
||||
options = await mount.parseMountOptions(options);
|
||||
}
|
||||
|
||||
for (let i of options) {
|
||||
let parts = i.split("=", 2);
|
||||
if (parts[0] == option) {
|
||||
if (typeof parts[1] === "undefined") {
|
||||
return null;
|
||||
} else {
|
||||
return parts[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mount optsion for a given path
|
||||
*
|
||||
* @param {*} path
|
||||
* @returns Array
|
||||
*/
|
||||
async getMountOptions(path) {
|
||||
const mount = this;
|
||||
let details = await mount.getMountDetails(path, [], ["-m"]);
|
||||
|
||||
return await mount.parseMountOptions(details.options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the device (source) at the given mount point
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user