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
|
||||
- `freenas-nfs` (manages zfs datasets to share over nfs)
|
||||
- `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-iscsi` (works with any ZoL installation...ie: Ubuntu)
|
||||
- `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
|
||||
|
||||
### 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
|
||||
|
||||
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.
|
||||
|
||||
### FreeNAS (freenas-nfs, freenas-iscsi)
|
||||
### FreeNAS (freenas-nfs, freenas-iscsi, freenas-smb)
|
||||
|
||||
Ensure the following services are configurged and running:
|
||||
|
||||
- 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
|
||||
- iscsi
|
||||
- smb
|
||||
|
||||
### ZoL (zfs-generic-nfs, zfs-generic-iscsi)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ zfs:
|
|||
datasetPermissionsMode: "0777"
|
||||
datasetPermissionsUser: root
|
||||
datasetPermissionsGroup: wheel
|
||||
#datasetPermissionsAcls:
|
||||
#- "-m everyone@:full_set:allow"
|
||||
#- "-m u:kube:full_set:allow"
|
||||
|
||||
nfs:
|
||||
shareHost: server address
|
||||
shareAlldirs: false
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ zfs:
|
|||
datasetPermissionsMode: "0777"
|
||||
datasetPermissionsUser: root
|
||||
datasetPermissionsGroup: root
|
||||
#datasetPermissionsAcls:
|
||||
#- "-m everyone@:full_set:allow"
|
||||
#- "-m u:kube:full_set:allow"
|
||||
|
||||
nfs:
|
||||
# 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/
|
||||
|
|
|
|||
|
|
@ -696,6 +696,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
|||
|
||||
// set acls
|
||||
// TODO: this is unsfafe approach, make it better
|
||||
// probably could see if ^-.*\s and split and then shell escape
|
||||
if (this.options.zfs.datasetPermissionsAcls) {
|
||||
for (const acl of this.options.zfs.datasetPermissionsAcls) {
|
||||
command = sshClient.buildCommand("setfacl", [
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
case "freenas-nfs":
|
||||
case "truenas-nfs":
|
||||
return "nfs";
|
||||
case "freenas-iscsi":
|
||||
case "truenas-iscsi":
|
||||
return "iscsi";
|
||||
case "freenas-smb":
|
||||
case "truenas-smb":
|
||||
return "smb";
|
||||
case "freenas-iscsi":
|
||||
case "truenas-iscsi":
|
||||
return "iscsi";
|
||||
default:
|
||||
throw new Error("unknown driver: " + this.ctx.args.driver);
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
};
|
||||
|
||||
let propertyMapping = {
|
||||
shareTemplate: "auxsmbconf",
|
||||
shareAuxiliaryConfigurationTemplate: "auxsmbconf",
|
||||
shareHome: "home",
|
||||
shareAllowedHosts: "hostsallow",
|
||||
shareDeniedHosts: "hostsdeny",
|
||||
|
|
@ -320,9 +320,9 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
if (this.options.smb.hasOwnProperty(key)) {
|
||||
let value;
|
||||
switch (key) {
|
||||
case "shareTemplate":
|
||||
case "shareAuxiliaryConfigurationTemplate":
|
||||
value = Handlebars.compile(
|
||||
this.options.smb.shareTemplate
|
||||
this.options.smb.shareAuxiliaryConfigurationTemplate
|
||||
)({
|
||||
name: call.request.name,
|
||||
parameters: call.request.parameters,
|
||||
|
|
|
|||
|
|
@ -272,9 +272,19 @@ class CsiBaseDriver {
|
|||
const bind_mount_flags = [];
|
||||
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") {
|
||||
fs_type = capability.mount.fs_type;
|
||||
mount_flags = capability.mount.mount_flags || [];
|
||||
// add secrets mount_flags
|
||||
if (normalizedSecrets.mount_flags) {
|
||||
mount_flags.push(normalizedSecrets.mount_flags);
|
||||
}
|
||||
mount_flags.push("defaults");
|
||||
}
|
||||
|
||||
|
|
@ -307,11 +317,6 @@ class CsiBaseDriver {
|
|||
"node.startup": "manual",
|
||||
};
|
||||
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) {
|
||||
if (key.startsWith(nodeDBKeyPrefix)) {
|
||||
nodeDB[key.substr(nodeDBKeyPrefix.length)] = normalizedSecrets[key];
|
||||
|
|
@ -355,24 +360,31 @@ class CsiBaseDriver {
|
|||
|
||||
switch (access_type) {
|
||||
case "mount":
|
||||
if (await filesystem.isBlockDevice(device)) {
|
||||
// format
|
||||
result = await filesystem.deviceIsFormatted(device);
|
||||
if (!result) {
|
||||
await filesystem.formatDevice(device, fs_type);
|
||||
}
|
||||
switch (node_attach_driver) {
|
||||
// block specific logic
|
||||
case "iscsi":
|
||||
if (await filesystem.isBlockDevice(device)) {
|
||||
// format
|
||||
result = await filesystem.deviceIsFormatted(device);
|
||||
if (!result) {
|
||||
await filesystem.formatDevice(device, fs_type);
|
||||
}
|
||||
|
||||
let fs_info = await filesystem.getDeviceFilesystemInfo(device);
|
||||
fs_type = fs_info.type;
|
||||
let fs_info = await filesystem.getDeviceFilesystemInfo(device);
|
||||
fs_type = fs_info.type;
|
||||
|
||||
// fsck
|
||||
result = await mount.deviceIsMountedAtPath(
|
||||
device,
|
||||
staging_target_path
|
||||
);
|
||||
if (!result) {
|
||||
await filesystem.checkFilesystem(device, fs_type);
|
||||
}
|
||||
// fsck
|
||||
result = await mount.deviceIsMountedAtPath(
|
||||
device,
|
||||
staging_target_path
|
||||
);
|
||||
if (!result) {
|
||||
await filesystem.checkFilesystem(device, fs_type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
result = await mount.deviceIsMountedAtPath(device, staging_target_path);
|
||||
|
|
@ -614,6 +626,7 @@ class CsiBaseDriver {
|
|||
|
||||
switch (node_attach_driver) {
|
||||
case "nfs":
|
||||
case "smb":
|
||||
case "iscsi":
|
||||
// ensure appropriate directories/files
|
||||
switch (access_type) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class Filesystem {
|
|||
|
||||
if (!options.executor) {
|
||||
options.executor = {
|
||||
spawn: cp.spawn
|
||||
spawn: cp.spawn,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -35,13 +35,20 @@ class Filesystem {
|
|||
async isBlockDevice(device) {
|
||||
const filesystem = this;
|
||||
|
||||
// nfs paths
|
||||
if (!device.startsWith("/")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// smb paths
|
||||
if (device.startsWith("//")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const device_path = await filesystem.realpath(device);
|
||||
const blockdevices = await filesystem.getAllBlockDevices();
|
||||
|
||||
return blockdevices.some(i => {
|
||||
return blockdevices.some((i) => {
|
||||
if (i.path == device_path) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -192,7 +199,7 @@ class Filesystem {
|
|||
const entries = result.stdout.trim().split("\n");
|
||||
const properties = {};
|
||||
let fields, key, value;
|
||||
entries.forEach(entry => {
|
||||
entries.forEach((entry) => {
|
||||
fields = entry.split("=");
|
||||
key = fields[0].toLowerCase();
|
||||
value = fields[1];
|
||||
|
|
@ -440,15 +447,15 @@ class Filesystem {
|
|||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.stdout.on("data", function(data) {
|
||||
child.stdout.on("data", function (data) {
|
||||
stdout = stdout + data;
|
||||
});
|
||||
|
||||
child.stderr.on("data", function(data) {
|
||||
child.stderr.on("data", function (data) {
|
||||
stderr = stderr + data;
|
||||
});
|
||||
|
||||
child.on("close", function(code) {
|
||||
child.on("close", function (code) {
|
||||
const result = { code, stdout, stderr };
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class Mount {
|
|||
*/
|
||||
async deviceIsMountedAtPath(device, path) {
|
||||
const filesystem = new Filesystem();
|
||||
if (device.startsWith("/")) {
|
||||
if (device.startsWith("/") && !device.startsWith("//")) {
|
||||
device = await filesystem.realpath(device);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue