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; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (err.code == 2) { |  | ||||||
|         return false; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       throw err; |       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 = 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