support ntfs, more robust detection of device formatting, more robust logic for iscsi device detection

Signed-off-by: Travis Glenn Hansen <travisghansen@yahoo.com>
This commit is contained in:
Travis Glenn Hansen 2022-04-24 08:38:11 -06:00
parent 68022bb4e5
commit 78d50b4836
3 changed files with 216 additions and 20 deletions

View File

@ -550,6 +550,7 @@ class CsiBaseDriver {
const iscsi = driver.getDefaultISCSIInstance();
let result;
let device;
let block_device_info;
const volume_id = call.request.volume_id;
if (!volume_id) {
@ -978,6 +979,27 @@ class CsiBaseDriver {
fs_type = "ext4";
}
if (fs_type == "ntfs") {
block_device_info = await filesystem.getBlockDevice(device);
let partition_count =
await filesystem.getBlockDevicePartitionCount(device);
if (partition_count > 0) {
device = await filesystem.getBlockDeviceLargestPartition(
device
);
} else {
// partion/gpt
await filesystem.partitionDevice(
device,
"gpt",
"EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"
);
device = await filesystem.getBlockDeviceLargestPartition(
device
);
}
}
if (await filesystem.isBlockDevice(device)) {
// format
result = await filesystem.deviceIsFormatted(device);
@ -1043,10 +1065,39 @@ class CsiBaseDriver {
staging_target_path
);
if (!result) {
// expand fs if necessary
if (await filesystem.isBlockDevice(device)) {
// go ahead and expand fs (this covers cloned setups where expand is not explicitly invoked)
switch (fs_type) {
case "exfat":
case "ntfs":
case "vfat":
//await filesystem.checkFilesystem(device, fs_info.type);
await filesystem.expandFilesystem(device, fs_type);
break;
}
}
let mount_fs_type = fs_type;
if (mount_fs_type == "ntfs") {
mount_fs_type = "ntfs3";
}
// handle volume_mount_group where appropriate
if (volume_mount_group) {
switch (fs_type) {
case "exfat":
case "ntfs":
case "vfat":
mount_flags.push(`gid=${volume_mount_group}`);
break;
}
}
await mount.mount(
device,
staging_target_path,
["-t", fs_type].concat(["-o", mount_flags.join(",")])
["-t", mount_fs_type].concat(["-o", mount_flags.join(",")])
);
}
@ -1054,8 +1105,8 @@ class CsiBaseDriver {
if (await filesystem.isBlockDevice(device)) {
// go ahead and expand fs (this covers cloned setups where expand is not explicitly invoked)
switch (fs_type) {
case "ext4":
case "ext3":
case "ext4":
case "ext4dev":
//await filesystem.checkFilesystem(device, fs_info.type);
try {
@ -1094,6 +1145,11 @@ class CsiBaseDriver {
fs_type
);
break;
case "exfat":
case "ntfs":
case "vfat":
// noop
break;
default:
// unsupported filesystem
throw new GrpcError(
@ -1613,7 +1669,11 @@ class CsiBaseDriver {
// TODO: this could be made async to detach all simultaneously
for (const block_device_info_i of realBlockDeviceInfos) {
if (block_device_info_i.tran == "iscsi") {
if (await filesystem.deviceIsIscsi(block_device_info_i.path)) {
let parent_block_device = await filesystem.getBlockDeviceParent(
block_device_info_i.path
);
// figure out which iscsi session this belongs to and logout
// scan /dev/disk/by-path/ip-*?
// device = `/dev/disk/by-path/ip-${volume_context.portal}-iscsi-${volume_context.iqn}-lun-${volume_context.lun}`;
@ -1632,7 +1692,7 @@ class CsiBaseDriver {
session.attached_scsi_devices.host.devices.some(
(device) => {
if (
device.attached_scsi_disk == block_device_info_i.name
device.attached_scsi_disk == parent_block_device.name
) {
return true;
}
@ -2439,8 +2499,8 @@ class CsiBaseDriver {
fs_type = fs_info.type;
if (fs_type) {
switch (fs_type) {
case "ext4":
case "ext3":
case "ext4":
case "ext4dev":
//await filesystem.checkFilesystem(device, fs_info.type);
await filesystem.expandFilesystem(device, fs_type);
@ -2453,6 +2513,13 @@ class CsiBaseDriver {
await filesystem.expandFilesystem(device_path, fs_type);
}
break;
case "exfat":
case "ntfs":
case "vfat":
// TODO: return error here, cannot be expanded while online
//await filesystem.checkFilesystem(device, fs_info.type);
//await filesystem.expandFilesystem(device, fs_type);
break;
default:
// unsupported filesystem
throw new GrpcError(

View File

@ -303,7 +303,7 @@ class Filesystem {
async getBlockDevice(device) {
const filesystem = this;
device = await filesystem.realpath(device);
let args = ["-a", "-b", "-l", "-J", "-O"];
let args = ["-a", "-b", "-J", "-O"];
args.push(device);
let result;
@ -317,30 +317,121 @@ class Filesystem {
}
/**
* blkid -p -o export <device>
*
* @param {*} device
* @returns
*/
async getBlockDeviceLargestPartition(device) {
const filesystem = this;
let block_device_info = await filesystem.getBlockDevice(device);
if (block_device_info.children) {
let child;
for (const child_i of block_device_info.children) {
if (child_i.type == "part") {
if (!child) {
child = child_i;
} else {
if (child_i.size > child.size) {
child = child_i;
}
}
}
}
return `${child.path}`;
}
}
/**
*
* @param {*} device
* @returns
*/
async getBlockDevicePartitionCount(device) {
const filesystem = this;
let count = 0;
let block_device_info = await filesystem.getBlockDevice(device);
if (block_device_info.children) {
for (const child_i of block_device_info.children) {
if (child_i.type == "part") {
count++;
}
}
}
return count;
}
/**
* type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 = linux
* type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 = ntfs
* type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B = EFI
*
* @param {*} device
* @param {*} label
* @param {*} type
*/
async partitionDevice(
device,
label = "gpt",
type = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"
) {
const filesystem = this;
let args = [device];
let result;
try {
result = await filesystem.exec("sfdisk", args, {
stdin: `label: ${label}\n`,
});
result = await filesystem.exec("sfdisk", args, {
stdin: `type=${type}\n`,
});
} catch (err) {
throw err;
}
}
/**
*
* @param {*} device
*/
async deviceIsFormatted(device) {
const filesystem = this;
let args = ["-p", "-o", "export", device];
let result;
try {
result = await filesystem.exec("blkid", args);
result = await filesystem.getBlockDevice(device);
return result.fstype ? true : false;
} catch (err) {
if (err.code == 2 && err.stderr.includes("No such device or address")) {
throw err;
}
if (err.code == 2) {
return false;
}
throw err;
}
}
return true;
async deviceIsIscsi(device) {
const filesystem = this;
let result;
do {
if (result) {
device = `/dev/${result.pkname}`;
}
result = await filesystem.getBlockDevice(device);
} while (result.pkname);
return result && result.tran == "iscsi";
}
async getBlockDeviceParent(device) {
const filesystem = this;
let result;
do {
if (result) {
device = `/dev/${result.pkname}`;
}
result = await filesystem.getBlockDevice(device);
} while (result.pkname);
return result;
}
/**
@ -463,6 +554,9 @@ class Filesystem {
args = args.concat(["filesystem", "resize", "max"]);
args.push(device); // in this case should be a mounted path
break;
case "exfat":
// https://github.com/exfatprogs/exfatprogs/issues/134
return;
case "ext4":
case "ext3":
case "ext4dev":
@ -470,6 +564,13 @@ class Filesystem {
args = args.concat(options);
args.push(device);
break;
case "ntfs":
// must be unmounted
command = "ntfsresize";
args = args.concat(options);
//args = args.concat(["-s", "max"]);
args.push(device);
break;
case "xfs":
command = "xfs_growfs";
args = args.concat(options);
@ -526,6 +627,14 @@ class Filesystem {
args.push("-f");
args.push("-p");
break;
case "ntfs":
/**
* -b, --clear-bad-sectors Clear the bad sector list
* -d, --clear-dirty Clear the volume dirty flag
*/
command = "ntfsfix";
args.push(device);
break;
case "xfs":
command = "xfs_repair";
args = args.concat(["-o", "force_geometry"]);
@ -612,6 +721,12 @@ class Filesystem {
//options.timeout = DEFAULT_TIMEOUT;
}
let stdin;
if (options.stdin) {
stdin = options.stdin;
delete options.stdin;
}
const filesystem = this;
args = args || [];
@ -619,13 +734,27 @@ class Filesystem {
args.unshift(command);
command = filesystem.options.paths.sudo;
}
console.log("executing filesystem command: %s %s", command, args.join(" "));
let command_log = `${command} ${args.join(" ")}`.trim();
if (stdin) {
command_log = `echo '${stdin}' | ${command_log}`
.trim()
.replace(/\n/, "\\n");
}
console.log("executing filesystem command: %s", command_log);
return new Promise((resolve, reject) => {
const child = filesystem.options.executor.spawn(command, args, options);
let stdout = "";
let stderr = "";
child.on("spawn", function () {
if (stdin) {
child.stdin.setEncoding("utf-8");
child.stdin.write(stdin);
child.stdin.end();
}
});
child.stdout.on("data", function (data) {
stdout = stdout + data;
});

View File

@ -170,7 +170,7 @@ function stringify(value) {
}
function default_supported_block_filesystems() {
return ["btrfs", "ext3", "ext4", "ext4dev", "xfs", "ntfs"];
return ["btrfs", "exfat", "ext3", "ext4", "ext4dev", "ntfs", "vfat", "xfs"];
}
function default_supported_file_filesystems() {