smb support
This commit is contained in:
		
							parent
							
								
									5ae0248ba8
								
							
						
					
					
						commit
						8c0d67a56e
					
				
							
								
								
									
										15
									
								
								README.md
								
								
								
								
							
							
						
						
									
										15
									
								
								README.md
								
								
								
								
							|  | @ -14,6 +14,7 @@ have access to resizing, snapshots, clones, etc functionality. | ||||||
| - several implementations of `csi` drivers | - several implementations of `csi` drivers | ||||||
|   - `freenas-nfs` (manages zfs datasets to share over nfs) |   - `freenas-nfs` (manages zfs datasets to share over nfs) | ||||||
|   - `freenas-iscsi` (manages zfs zvols to share over iscsi) |   - `freenas-iscsi` (manages zfs zvols to share over iscsi) | ||||||
|  |   - `freenas-smb` (manages zfs datasets to share over smb) | ||||||
|   - `zfs-generic-nfs` (works with any ZoL installation...ie: Ubuntu) |   - `zfs-generic-nfs` (works with any ZoL installation...ie: Ubuntu) | ||||||
|   - `zfs-generic-iscsi` (works with any ZoL installation...ie: Ubuntu) |   - `zfs-generic-iscsi` (works with any ZoL installation...ie: Ubuntu) | ||||||
|   - `zfs-local-ephemeral-inline` (provisions node-local zfs datasets) |   - `zfs-local-ephemeral-inline` (provisions node-local zfs datasets) | ||||||
|  | @ -43,6 +44,16 @@ If you are running Kubernetes with rancher/rke please see the following: | ||||||
| 
 | 
 | ||||||
| - https://github.com/rancher/rke/issues/1846 | - https://github.com/rancher/rke/issues/1846 | ||||||
| 
 | 
 | ||||||
|  | ### freenas-smb | ||||||
|  | 
 | ||||||
|  | If using with Windows based machines you may need to enable guest access (even | ||||||
|  | if you are connecting with credentiasl) | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters AllowInsecureGuestAuth -Value 1 | ||||||
|  | Restart-Service LanmanWorkstation -Force | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ### zfs-local-ephemeral-inline | ### zfs-local-ephemeral-inline | ||||||
| 
 | 
 | ||||||
| This `driver` provisions node-local ephemeral storage on a per-pod basis. Each | This `driver` provisions node-local ephemeral storage on a per-pod basis. Each | ||||||
|  | @ -58,13 +69,15 @@ necessary. | ||||||
| 
 | 
 | ||||||
| Server preparation depends slightly on which `driver` you are using. | Server preparation depends slightly on which `driver` you are using. | ||||||
| 
 | 
 | ||||||
| ### FreeNAS (freenas-nfs, freenas-iscsi) | ### FreeNAS (freenas-nfs, freenas-iscsi, freenas-smb) | ||||||
| 
 | 
 | ||||||
| Ensure the following services are configurged and running: | Ensure the following services are configurged and running: | ||||||
| 
 | 
 | ||||||
| - ssh (if you use a password for authentication make sure it is allowed) | - ssh (if you use a password for authentication make sure it is allowed) | ||||||
|  | - ensure `zsh`, `bash`, or `sh` is set as the root shell, `csh` gives false errors due to quoting | ||||||
| - nfs | - nfs | ||||||
| - iscsi | - iscsi | ||||||
|  | - smb | ||||||
| 
 | 
 | ||||||
| ### ZoL (zfs-generic-nfs, zfs-generic-iscsi) | ### ZoL (zfs-generic-nfs, zfs-generic-iscsi) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -41,6 +41,10 @@ zfs: | ||||||
|   datasetPermissionsMode: "0777" |   datasetPermissionsMode: "0777" | ||||||
|   datasetPermissionsUser: root |   datasetPermissionsUser: root | ||||||
|   datasetPermissionsGroup: wheel |   datasetPermissionsGroup: wheel | ||||||
|  |   #datasetPermissionsAcls: | ||||||
|  |   #- "-m everyone@:full_set:allow" | ||||||
|  |   #- "-m u:kube:full_set:allow" | ||||||
|  | 
 | ||||||
| nfs: | nfs: | ||||||
|   shareHost: server address |   shareHost: server address | ||||||
|   shareAlldirs: false |   shareAlldirs: false | ||||||
|  |  | ||||||
|  | @ -38,6 +38,10 @@ zfs: | ||||||
|   datasetPermissionsMode: "0777" |   datasetPermissionsMode: "0777" | ||||||
|   datasetPermissionsUser: root |   datasetPermissionsUser: root | ||||||
|   datasetPermissionsGroup: root |   datasetPermissionsGroup: root | ||||||
|  |   #datasetPermissionsAcls: | ||||||
|  |   #- "-m everyone@:full_set:allow" | ||||||
|  |   #- "-m u:kube:full_set:allow" | ||||||
|  | 
 | ||||||
| nfs: | nfs: | ||||||
|   # https://docs.oracle.com/cd/E23824_01/html/821-1448/gayne.html |   # https://docs.oracle.com/cd/E23824_01/html/821-1448/gayne.html | ||||||
|   # https://www.hiroom2.com/2016/05/18/ubuntu-16-04-share-zfs-storage-via-nfs-smb/ |   # https://www.hiroom2.com/2016/05/18/ubuntu-16-04-share-zfs-storage-via-nfs-smb/ | ||||||
|  |  | ||||||
|  | @ -696,6 +696,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver { | ||||||
| 
 | 
 | ||||||
|         // set acls
 |         // set acls
 | ||||||
|         // TODO: this is unsfafe approach, make it better
 |         // TODO: this is unsfafe approach, make it better
 | ||||||
|  |         // probably could see if ^-.*\s and split and then shell escape
 | ||||||
|         if (this.options.zfs.datasetPermissionsAcls) { |         if (this.options.zfs.datasetPermissionsAcls) { | ||||||
|           for (const acl of this.options.zfs.datasetPermissionsAcls) { |           for (const acl of this.options.zfs.datasetPermissionsAcls) { | ||||||
|             command = sshClient.buildCommand("setfacl", [ |             command = sshClient.buildCommand("setfacl", [ | ||||||
|  |  | ||||||
|  | @ -45,12 +45,12 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver { | ||||||
|       case "freenas-nfs": |       case "freenas-nfs": | ||||||
|       case "truenas-nfs": |       case "truenas-nfs": | ||||||
|         return "nfs"; |         return "nfs"; | ||||||
|       case "freenas-iscsi": |  | ||||||
|       case "truenas-iscsi": |  | ||||||
|         return "iscsi"; |  | ||||||
|       case "freenas-smb": |       case "freenas-smb": | ||||||
|       case "truenas-smb": |       case "truenas-smb": | ||||||
|         return "smb"; |         return "smb"; | ||||||
|  |       case "freenas-iscsi": | ||||||
|  |       case "truenas-iscsi": | ||||||
|  |         return "iscsi"; | ||||||
|       default: |       default: | ||||||
|         throw new Error("unknown driver: " + this.ctx.args.driver); |         throw new Error("unknown driver: " + this.ctx.args.driver); | ||||||
|     } |     } | ||||||
|  | @ -301,7 +301,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver { | ||||||
|               }; |               }; | ||||||
| 
 | 
 | ||||||
|               let propertyMapping = { |               let propertyMapping = { | ||||||
|                 shareTemplate: "auxsmbconf", |                 shareAuxiliaryConfigurationTemplate: "auxsmbconf", | ||||||
|                 shareHome: "home", |                 shareHome: "home", | ||||||
|                 shareAllowedHosts: "hostsallow", |                 shareAllowedHosts: "hostsallow", | ||||||
|                 shareDeniedHosts: "hostsdeny", |                 shareDeniedHosts: "hostsdeny", | ||||||
|  | @ -320,9 +320,9 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver { | ||||||
|                 if (this.options.smb.hasOwnProperty(key)) { |                 if (this.options.smb.hasOwnProperty(key)) { | ||||||
|                   let value; |                   let value; | ||||||
|                   switch (key) { |                   switch (key) { | ||||||
|                     case "shareTemplate": |                     case "shareAuxiliaryConfigurationTemplate": | ||||||
|                       value = Handlebars.compile( |                       value = Handlebars.compile( | ||||||
|                         this.options.smb.shareTemplate |                         this.options.smb.shareAuxiliaryConfigurationTemplate | ||||||
|                       )({ |                       )({ | ||||||
|                         name: call.request.name, |                         name: call.request.name, | ||||||
|                         parameters: call.request.parameters, |                         parameters: call.request.parameters, | ||||||
|  |  | ||||||
|  | @ -272,9 +272,19 @@ class CsiBaseDriver { | ||||||
|     const bind_mount_flags = []; |     const bind_mount_flags = []; | ||||||
|     bind_mount_flags.push("defaults"); |     bind_mount_flags.push("defaults"); | ||||||
| 
 | 
 | ||||||
|  |     const normalizedSecrets = this.getNormalizedParameters( | ||||||
|  |       call.request.secrets, | ||||||
|  |       call.request.volume_context.provisioner_driver, | ||||||
|  |       call.request.volume_context.provisioner_driver_instance_id | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|     if (access_type == "mount") { |     if (access_type == "mount") { | ||||||
|       fs_type = capability.mount.fs_type; |       fs_type = capability.mount.fs_type; | ||||||
|       mount_flags = capability.mount.mount_flags || []; |       mount_flags = capability.mount.mount_flags || []; | ||||||
|  |       // add secrets mount_flags
 | ||||||
|  |       if (normalizedSecrets.mount_flags) { | ||||||
|  |         mount_flags.push(normalizedSecrets.mount_flags); | ||||||
|  |       } | ||||||
|       mount_flags.push("defaults"); |       mount_flags.push("defaults"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -307,11 +317,6 @@ class CsiBaseDriver { | ||||||
|           "node.startup": "manual", |           "node.startup": "manual", | ||||||
|         }; |         }; | ||||||
|         const nodeDBKeyPrefix = "node-db."; |         const nodeDBKeyPrefix = "node-db."; | ||||||
|         const normalizedSecrets = this.getNormalizedParameters( |  | ||||||
|           call.request.secrets, |  | ||||||
|           call.request.volume_context.provisioner_driver, |  | ||||||
|           call.request.volume_context.provisioner_driver_instance_id |  | ||||||
|         ); |  | ||||||
|         for (const key in normalizedSecrets) { |         for (const key in normalizedSecrets) { | ||||||
|           if (key.startsWith(nodeDBKeyPrefix)) { |           if (key.startsWith(nodeDBKeyPrefix)) { | ||||||
|             nodeDB[key.substr(nodeDBKeyPrefix.length)] = normalizedSecrets[key]; |             nodeDB[key.substr(nodeDBKeyPrefix.length)] = normalizedSecrets[key]; | ||||||
|  | @ -355,24 +360,31 @@ class CsiBaseDriver { | ||||||
| 
 | 
 | ||||||
|     switch (access_type) { |     switch (access_type) { | ||||||
|       case "mount": |       case "mount": | ||||||
|         if (await filesystem.isBlockDevice(device)) { |         switch (node_attach_driver) { | ||||||
|           // format
 |           // block specific logic
 | ||||||
|           result = await filesystem.deviceIsFormatted(device); |           case "iscsi": | ||||||
|           if (!result) { |             if (await filesystem.isBlockDevice(device)) { | ||||||
|             await filesystem.formatDevice(device, fs_type); |               // format
 | ||||||
|           } |               result = await filesystem.deviceIsFormatted(device); | ||||||
|  |               if (!result) { | ||||||
|  |                 await filesystem.formatDevice(device, fs_type); | ||||||
|  |               } | ||||||
| 
 | 
 | ||||||
|           let fs_info = await filesystem.getDeviceFilesystemInfo(device); |               let fs_info = await filesystem.getDeviceFilesystemInfo(device); | ||||||
|           fs_type = fs_info.type; |               fs_type = fs_info.type; | ||||||
| 
 | 
 | ||||||
|           // fsck
 |               // fsck
 | ||||||
|           result = await mount.deviceIsMountedAtPath( |               result = await mount.deviceIsMountedAtPath( | ||||||
|             device, |                 device, | ||||||
|             staging_target_path |                 staging_target_path | ||||||
|           ); |               ); | ||||||
|           if (!result) { |               if (!result) { | ||||||
|             await filesystem.checkFilesystem(device, fs_type); |                 await filesystem.checkFilesystem(device, fs_type); | ||||||
|           } |               } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |           default: | ||||||
|  |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         result = await mount.deviceIsMountedAtPath(device, staging_target_path); |         result = await mount.deviceIsMountedAtPath(device, staging_target_path); | ||||||
|  | @ -614,6 +626,7 @@ class CsiBaseDriver { | ||||||
| 
 | 
 | ||||||
|     switch (node_attach_driver) { |     switch (node_attach_driver) { | ||||||
|       case "nfs": |       case "nfs": | ||||||
|  |       case "smb": | ||||||
|       case "iscsi": |       case "iscsi": | ||||||
|         // ensure appropriate directories/files
 |         // ensure appropriate directories/files
 | ||||||
|         switch (access_type) { |         switch (access_type) { | ||||||
|  |  | ||||||
|  | @ -22,7 +22,7 @@ class Filesystem { | ||||||
| 
 | 
 | ||||||
|     if (!options.executor) { |     if (!options.executor) { | ||||||
|       options.executor = { |       options.executor = { | ||||||
|         spawn: cp.spawn |         spawn: cp.spawn, | ||||||
|       }; |       }; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -35,13 +35,20 @@ class Filesystem { | ||||||
|   async isBlockDevice(device) { |   async isBlockDevice(device) { | ||||||
|     const filesystem = this; |     const filesystem = this; | ||||||
| 
 | 
 | ||||||
|  |     // nfs paths
 | ||||||
|     if (!device.startsWith("/")) { |     if (!device.startsWith("/")) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     // smb paths
 | ||||||
|  |     if (device.startsWith("//")) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const device_path = await filesystem.realpath(device); |     const device_path = await filesystem.realpath(device); | ||||||
|     const blockdevices = await filesystem.getAllBlockDevices(); |     const blockdevices = await filesystem.getAllBlockDevices(); | ||||||
| 
 | 
 | ||||||
|     return blockdevices.some(i => { |     return blockdevices.some((i) => { | ||||||
|       if (i.path == device_path) { |       if (i.path == device_path) { | ||||||
|         return true; |         return true; | ||||||
|       } |       } | ||||||
|  | @ -192,7 +199,7 @@ class Filesystem { | ||||||
|       const entries = result.stdout.trim().split("\n"); |       const entries = result.stdout.trim().split("\n"); | ||||||
|       const properties = {}; |       const properties = {}; | ||||||
|       let fields, key, value; |       let fields, key, value; | ||||||
|       entries.forEach(entry => { |       entries.forEach((entry) => { | ||||||
|         fields = entry.split("="); |         fields = entry.split("="); | ||||||
|         key = fields[0].toLowerCase(); |         key = fields[0].toLowerCase(); | ||||||
|         value = fields[1]; |         value = fields[1]; | ||||||
|  | @ -440,15 +447,15 @@ class Filesystem { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return new Promise((resolve, reject) => { |     return new Promise((resolve, reject) => { | ||||||
|       child.stdout.on("data", function(data) { |       child.stdout.on("data", function (data) { | ||||||
|         stdout = stdout + data; |         stdout = stdout + data; | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       child.stderr.on("data", function(data) { |       child.stderr.on("data", function (data) { | ||||||
|         stderr = stderr + data; |         stderr = stderr + data; | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       child.on("close", function(code) { |       child.on("close", function (code) { | ||||||
|         const result = { code, stdout, stderr }; |         const result = { code, stdout, stderr }; | ||||||
|         if (timeout) { |         if (timeout) { | ||||||
|           clearTimeout(timeout); |           clearTimeout(timeout); | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ class Mount { | ||||||
|    */ |    */ | ||||||
|   async deviceIsMountedAtPath(device, path) { |   async deviceIsMountedAtPath(device, path) { | ||||||
|     const filesystem = new Filesystem(); |     const filesystem = new Filesystem(); | ||||||
|     if (device.startsWith("/")) { |     if (device.startsWith("/") && !device.startsWith("//")) { | ||||||
|       device = await filesystem.realpath(device); |       device = await filesystem.realpath(device); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue