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:
parent
68022bb4e5
commit
78d50b4836
|
|
@ -550,6 +550,7 @@ class CsiBaseDriver {
|
||||||
const iscsi = driver.getDefaultISCSIInstance();
|
const iscsi = driver.getDefaultISCSIInstance();
|
||||||
let result;
|
let result;
|
||||||
let device;
|
let device;
|
||||||
|
let block_device_info;
|
||||||
|
|
||||||
const volume_id = call.request.volume_id;
|
const volume_id = call.request.volume_id;
|
||||||
if (!volume_id) {
|
if (!volume_id) {
|
||||||
|
|
@ -978,6 +979,27 @@ class CsiBaseDriver {
|
||||||
fs_type = "ext4";
|
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)) {
|
if (await filesystem.isBlockDevice(device)) {
|
||||||
// format
|
// format
|
||||||
result = await filesystem.deviceIsFormatted(device);
|
result = await filesystem.deviceIsFormatted(device);
|
||||||
|
|
@ -1043,10 +1065,39 @@ class CsiBaseDriver {
|
||||||
staging_target_path
|
staging_target_path
|
||||||
);
|
);
|
||||||
if (!result) {
|
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(
|
await mount.mount(
|
||||||
device,
|
device,
|
||||||
staging_target_path,
|
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)) {
|
if (await filesystem.isBlockDevice(device)) {
|
||||||
// go ahead and expand fs (this covers cloned setups where expand is not explicitly invoked)
|
// go ahead and expand fs (this covers cloned setups where expand is not explicitly invoked)
|
||||||
switch (fs_type) {
|
switch (fs_type) {
|
||||||
case "ext4":
|
|
||||||
case "ext3":
|
case "ext3":
|
||||||
|
case "ext4":
|
||||||
case "ext4dev":
|
case "ext4dev":
|
||||||
//await filesystem.checkFilesystem(device, fs_info.type);
|
//await filesystem.checkFilesystem(device, fs_info.type);
|
||||||
try {
|
try {
|
||||||
|
|
@ -1094,6 +1145,11 @@ class CsiBaseDriver {
|
||||||
fs_type
|
fs_type
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case "exfat":
|
||||||
|
case "ntfs":
|
||||||
|
case "vfat":
|
||||||
|
// noop
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// unsupported filesystem
|
// unsupported filesystem
|
||||||
throw new GrpcError(
|
throw new GrpcError(
|
||||||
|
|
@ -1613,7 +1669,11 @@ class CsiBaseDriver {
|
||||||
|
|
||||||
// TODO: this could be made async to detach all simultaneously
|
// TODO: this could be made async to detach all simultaneously
|
||||||
for (const block_device_info_i of realBlockDeviceInfos) {
|
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
|
// figure out which iscsi session this belongs to and logout
|
||||||
// scan /dev/disk/by-path/ip-*?
|
// scan /dev/disk/by-path/ip-*?
|
||||||
// device = `/dev/disk/by-path/ip-${volume_context.portal}-iscsi-${volume_context.iqn}-lun-${volume_context.lun}`;
|
// 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(
|
session.attached_scsi_devices.host.devices.some(
|
||||||
(device) => {
|
(device) => {
|
||||||
if (
|
if (
|
||||||
device.attached_scsi_disk == block_device_info_i.name
|
device.attached_scsi_disk == parent_block_device.name
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -2439,8 +2499,8 @@ class CsiBaseDriver {
|
||||||
fs_type = fs_info.type;
|
fs_type = fs_info.type;
|
||||||
if (fs_type) {
|
if (fs_type) {
|
||||||
switch (fs_type) {
|
switch (fs_type) {
|
||||||
case "ext4":
|
|
||||||
case "ext3":
|
case "ext3":
|
||||||
|
case "ext4":
|
||||||
case "ext4dev":
|
case "ext4dev":
|
||||||
//await filesystem.checkFilesystem(device, fs_info.type);
|
//await filesystem.checkFilesystem(device, fs_info.type);
|
||||||
await filesystem.expandFilesystem(device, fs_type);
|
await filesystem.expandFilesystem(device, fs_type);
|
||||||
|
|
@ -2453,6 +2513,13 @@ class CsiBaseDriver {
|
||||||
await filesystem.expandFilesystem(device_path, fs_type);
|
await filesystem.expandFilesystem(device_path, fs_type);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
// unsupported filesystem
|
// unsupported filesystem
|
||||||
throw new GrpcError(
|
throw new GrpcError(
|
||||||
|
|
|
||||||
|
|
@ -303,7 +303,7 @@ class Filesystem {
|
||||||
async getBlockDevice(device) {
|
async getBlockDevice(device) {
|
||||||
const filesystem = this;
|
const filesystem = this;
|
||||||
device = await filesystem.realpath(device);
|
device = await filesystem.realpath(device);
|
||||||
let args = ["-a", "-b", "-l", "-J", "-O"];
|
let args = ["-a", "-b", "-J", "-O"];
|
||||||
args.push(device);
|
args.push(device);
|
||||||
let result;
|
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
|
* @param {*} device
|
||||||
*/
|
*/
|
||||||
async deviceIsFormatted(device) {
|
async deviceIsFormatted(device) {
|
||||||
const filesystem = this;
|
const filesystem = this;
|
||||||
let args = ["-p", "-o", "export", device];
|
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = await filesystem.exec("blkid", args);
|
result = await filesystem.getBlockDevice(device);
|
||||||
|
return result.fstype ? true : false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code == 2 && err.stderr.includes("No such device or address")) {
|
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err.code == 2) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
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";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
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 = args.concat(["filesystem", "resize", "max"]);
|
||||||
args.push(device); // in this case should be a mounted path
|
args.push(device); // in this case should be a mounted path
|
||||||
break;
|
break;
|
||||||
|
case "exfat":
|
||||||
|
// https://github.com/exfatprogs/exfatprogs/issues/134
|
||||||
|
return;
|
||||||
case "ext4":
|
case "ext4":
|
||||||
case "ext3":
|
case "ext3":
|
||||||
case "ext4dev":
|
case "ext4dev":
|
||||||
|
|
@ -470,6 +564,13 @@ class Filesystem {
|
||||||
args = args.concat(options);
|
args = args.concat(options);
|
||||||
args.push(device);
|
args.push(device);
|
||||||
break;
|
break;
|
||||||
|
case "ntfs":
|
||||||
|
// must be unmounted
|
||||||
|
command = "ntfsresize";
|
||||||
|
args = args.concat(options);
|
||||||
|
//args = args.concat(["-s", "max"]);
|
||||||
|
args.push(device);
|
||||||
|
break;
|
||||||
case "xfs":
|
case "xfs":
|
||||||
command = "xfs_growfs";
|
command = "xfs_growfs";
|
||||||
args = args.concat(options);
|
args = args.concat(options);
|
||||||
|
|
@ -526,6 +627,14 @@ class Filesystem {
|
||||||
args.push("-f");
|
args.push("-f");
|
||||||
args.push("-p");
|
args.push("-p");
|
||||||
break;
|
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":
|
case "xfs":
|
||||||
command = "xfs_repair";
|
command = "xfs_repair";
|
||||||
args = args.concat(["-o", "force_geometry"]);
|
args = args.concat(["-o", "force_geometry"]);
|
||||||
|
|
@ -612,6 +721,12 @@ class Filesystem {
|
||||||
//options.timeout = DEFAULT_TIMEOUT;
|
//options.timeout = DEFAULT_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let stdin;
|
||||||
|
if (options.stdin) {
|
||||||
|
stdin = options.stdin;
|
||||||
|
delete options.stdin;
|
||||||
|
}
|
||||||
|
|
||||||
const filesystem = this;
|
const filesystem = this;
|
||||||
args = args || [];
|
args = args || [];
|
||||||
|
|
||||||
|
|
@ -619,13 +734,27 @@ class Filesystem {
|
||||||
args.unshift(command);
|
args.unshift(command);
|
||||||
command = filesystem.options.paths.sudo;
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = filesystem.options.executor.spawn(command, args, options);
|
const child = filesystem.options.executor.spawn(command, args, options);
|
||||||
let stdout = "";
|
let stdout = "";
|
||||||
let stderr = "";
|
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) {
|
child.stdout.on("data", function (data) {
|
||||||
stdout = stdout + data;
|
stdout = stdout + data;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ function stringify(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function default_supported_block_filesystems() {
|
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() {
|
function default_supported_file_filesystems() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue