support templatized/deterministic iqns
This commit is contained in:
parent
ee3cb6af14
commit
f5ba51c9b8
|
|
@ -20,7 +20,7 @@ ENV PATH=/usr/local/lib/nodejs/bin:$PATH
|
|||
|
||||
# node service requirements
|
||||
RUN apt-get update && \
|
||||
apt-get install -y xfsprogs fatresize dosfstools open-iscsi lsscsi sg3-utils multipath-tools scsitools nfs-common sudo && \
|
||||
apt-get install -y xfsprogs fatresize dosfstools open-iscsi lsscsi sg3-utils multipath-tools scsitools nfs-common cifs-utils sudo && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# controller requirements
|
||||
|
|
|
|||
|
|
@ -52,6 +52,11 @@ iscsi:
|
|||
targetPortals: []
|
||||
# leave empty to omit usage of -I with iscsiadm
|
||||
interface:
|
||||
|
||||
# MUST ensure uniqueness
|
||||
# full iqn limit is 223 bytes, plan accordingly
|
||||
# default is "{{ name }}"
|
||||
#nameTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
|
||||
namePrefix: csi-
|
||||
nameSuffix: "-clustera"
|
||||
# add as many as needed
|
||||
|
|
|
|||
|
|
@ -72,5 +72,10 @@ iscsi:
|
|||
targetPortal: "server address"
|
||||
targetPortals: []
|
||||
interface: ""
|
||||
|
||||
# MUST ensure uniqueness
|
||||
# full iqn limit is 223 bytes, plan accordingly
|
||||
# default is "{{ name }}"
|
||||
#nameTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
|
||||
namePrefix:
|
||||
nameSuffix:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
const { ControllerZfsSshBaseDriver } = require("../controller-zfs-ssh");
|
||||
const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
|
||||
const Handlebars = require("handlebars");
|
||||
|
||||
class ControllerZfsGenericDriver extends ControllerZfsSshBaseDriver {
|
||||
/**
|
||||
* cannot make this a storage class parameter as storage class/etc context is *not* sent
|
||||
|
|
@ -44,7 +46,7 @@ class ControllerZfsGenericDriver extends ControllerZfsSshBaseDriver {
|
|||
) {
|
||||
await zb.zfs.set(datasetName, {
|
||||
[key]: this.options.nfs.shareStrategySetDatasetProperties
|
||||
.properties[key]
|
||||
.properties[key],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -61,13 +63,23 @@ class ControllerZfsGenericDriver extends ControllerZfsSshBaseDriver {
|
|||
volume_context = {
|
||||
node_attach_driver: "nfs",
|
||||
server: this.options.nfs.shareHost,
|
||||
share: properties.mountpoint.value
|
||||
share: properties.mountpoint.value,
|
||||
};
|
||||
return volume_context;
|
||||
|
||||
case "zfs-generic-iscsi":
|
||||
let basename;
|
||||
let iscsiName = zb.helpers.extractLeafName(datasetName);
|
||||
let iscsiName;
|
||||
|
||||
if (this.options.iscsi.nameTemplate) {
|
||||
iscsiName = Handlebars.compile(this.options.iscsi.nameTemplate)({
|
||||
name: call.request.name,
|
||||
parameters: call.request.parameters,
|
||||
});
|
||||
} else {
|
||||
iscsiName = zb.helpers.extractLeafName(datasetName);
|
||||
}
|
||||
|
||||
if (this.options.iscsi.namePrefix) {
|
||||
iscsiName = this.options.iscsi.namePrefix + iscsiName;
|
||||
}
|
||||
|
|
@ -153,7 +165,7 @@ create /backstores/block/${iscsiName}
|
|||
portals: this.options.iscsi.targetPortals.join(","),
|
||||
interface: this.options.iscsi.interface,
|
||||
iqn: iqn,
|
||||
lun: 0
|
||||
lun: 0,
|
||||
};
|
||||
return volume_context;
|
||||
|
||||
|
|
|
|||
|
|
@ -291,6 +291,10 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: avoid the urge to templatize this given the name length limits for zvols
|
||||
* ie: namespace-name may quite easily exceed 58 chars
|
||||
*/
|
||||
const datasetName = datasetParentName + "/" + name;
|
||||
let capacity_bytes =
|
||||
call.request.capacity_range.required_bytes ||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ const { ControllerZfsSshBaseDriver } = require("../controller-zfs-ssh");
|
|||
const { GrpcError, grpc } = require("../../utils/grpc");
|
||||
const HttpClient = require("./http").Client;
|
||||
|
||||
const Handlebars = require("handlebars");
|
||||
|
||||
// freenas properties
|
||||
const FREENAS_NFS_SHARE_PROPERTY_NAME = "democratic-csi:freenas_nfs_share_id";
|
||||
const FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME =
|
||||
|
|
@ -19,8 +21,10 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
getDriverZfsResourceType() {
|
||||
switch (this.options.driver) {
|
||||
case "freenas-nfs":
|
||||
case "truenas-nfs":
|
||||
return "filesystem";
|
||||
case "freenas-iscsi":
|
||||
case "truenas-iscsi":
|
||||
return "volume";
|
||||
default:
|
||||
throw new Error("unknown driver: " + this.ctx.args.driver);
|
||||
|
|
@ -36,8 +40,10 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
getDriverShareType() {
|
||||
switch (this.options.driver) {
|
||||
case "freenas-nfs":
|
||||
case "truenas-nfs":
|
||||
return "nfs";
|
||||
case "freenas-iscsi":
|
||||
case "truenas-iscsi":
|
||||
return "iscsi";
|
||||
default:
|
||||
throw new Error("unknown driver: " + this.ctx.args.driver);
|
||||
|
|
@ -74,7 +80,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
if (response.body.length < 1) {
|
||||
break;
|
||||
}
|
||||
response.body.some(i => {
|
||||
response.body.some((i) => {
|
||||
let isMatch = true;
|
||||
for (let property in match) {
|
||||
if (match[property] != i[property]) {
|
||||
|
|
@ -124,7 +130,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
case "nfs":
|
||||
properties = await zb.zfs.get(datasetName, [
|
||||
"mountpoint",
|
||||
FREENAS_NFS_SHARE_PROPERTY_NAME
|
||||
FREENAS_NFS_SHARE_PROPERTY_NAME,
|
||||
]);
|
||||
properties = properties[datasetName];
|
||||
this.ctx.logger.debug("zfs props data: %j", properties);
|
||||
|
|
@ -154,7 +160,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
nfs_maproot_group: this.options.nfs.shareMaprootGroup,
|
||||
nfs_mapall_user: this.options.nfs.shareMapallUser,
|
||||
nfs_mapall_group: this.options.nfs.shareMapallGroup,
|
||||
nfs_security: []
|
||||
nfs_security: [],
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
|
|
@ -170,7 +176,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
maproot_group: this.options.nfs.shareMaprootGroup,
|
||||
mapall_user: this.options.nfs.shareMapallUser,
|
||||
mapall_group: this.options.nfs.shareMapallGroup,
|
||||
security: []
|
||||
security: [],
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
|
@ -184,7 +190,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
if ([200, 201].includes(response.statusCode)) {
|
||||
//set zfs property
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_NFS_SHARE_PROPERTY_NAME]: response.body.id
|
||||
[FREENAS_NFS_SHARE_PROPERTY_NAME]: response.body.id,
|
||||
});
|
||||
} else {
|
||||
/**
|
||||
|
|
@ -209,7 +215,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
let volume_context = {
|
||||
node_attach_driver: "nfs",
|
||||
server: this.options.nfs.shareHost,
|
||||
share: properties.mountpoint.value
|
||||
share: properties.mountpoint.value,
|
||||
};
|
||||
return volume_context;
|
||||
|
||||
|
|
@ -223,7 +229,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
let volume_context = {
|
||||
node_attach_driver: "nfs",
|
||||
server: this.options.nfs.shareHost,
|
||||
share: properties.mountpoint.value
|
||||
share: properties.mountpoint.value,
|
||||
};
|
||||
return volume_context;
|
||||
}
|
||||
|
|
@ -232,13 +238,23 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
properties = await zb.zfs.get(datasetName, [
|
||||
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
|
||||
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
|
||||
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME
|
||||
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
|
||||
]);
|
||||
properties = properties[datasetName];
|
||||
this.ctx.logger.debug("zfs props data: %j", properties);
|
||||
|
||||
let basename;
|
||||
let iscsiName = zb.helpers.extractLeafName(datasetName);
|
||||
let iscsiName;
|
||||
|
||||
if (this.options.iscsi.nameTemplate) {
|
||||
iscsiName = Handlebars.compile(this.options.iscsi.nameTemplate)({
|
||||
name: call.request.name,
|
||||
parameters: call.request.parameters,
|
||||
});
|
||||
} else {
|
||||
iscsiName = zb.helpers.extractLeafName(datasetName);
|
||||
}
|
||||
|
||||
if (this.options.iscsi.namePrefix) {
|
||||
iscsiName = this.options.iscsi.namePrefix + iscsiName;
|
||||
}
|
||||
|
|
@ -247,6 +263,9 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
iscsiName += this.options.iscsi.nameSuffix;
|
||||
}
|
||||
|
||||
// According to RFC3270, 'Each iSCSI node, whether an initiator or target, MUST have an iSCSI name. Initiators and targets MUST support the receipt of iSCSI names of up to the maximum length of 223 bytes.'
|
||||
// https://kb.netapp.com/Advice_and_Troubleshooting/Miscellaneous/What_is_the_maximum_length_of_a_iSCSI_iqn_name
|
||||
// https://tools.ietf.org/html/rfc3720
|
||||
iscsiName = iscsiName.toLowerCase();
|
||||
|
||||
let extentDiskName = "zvol/" + datasetName;
|
||||
|
|
@ -323,7 +342,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
// create target
|
||||
let target = {
|
||||
iscsi_target_name: iscsiName,
|
||||
iscsi_target_alias: ""
|
||||
iscsi_target_alias: "",
|
||||
};
|
||||
|
||||
response = await httpClient.post("/services/iscsi/target", target);
|
||||
|
|
@ -340,7 +359,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
target = await this.findResourceByProperties(
|
||||
"/services/iscsi/target",
|
||||
{
|
||||
iscsi_target_name: iscsiName
|
||||
iscsi_target_name: iscsiName,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -366,7 +385,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
|
||||
// set target.id on zvol
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id
|
||||
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
|
||||
});
|
||||
|
||||
// create targetgroup(s)
|
||||
|
|
@ -382,7 +401,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
targetGroupConfig.targetGroupPortalGroup,
|
||||
iscsi_target_initiatorgroup:
|
||||
targetGroupConfig.targetGroupInitiatorGroup,
|
||||
iscsi_target_initialdigest: "Auto"
|
||||
iscsi_target_initialdigest: "Auto",
|
||||
};
|
||||
response = await httpClient.post(
|
||||
"/services/iscsi/targetgroup",
|
||||
|
|
@ -421,7 +440,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
iscsi_target_portalgroup:
|
||||
targetGroupConfig.targetGroupPortalGroup,
|
||||
iscsi_target_initiatorgroup:
|
||||
targetGroupConfig.targetGroupInitiatorGroup
|
||||
targetGroupConfig.targetGroupInitiatorGroup,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -463,7 +482,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
iscsi_target_extent_rpm: isNaN(Number(extentRpm))
|
||||
? "SSD"
|
||||
: Number(extentRpm),
|
||||
iscsi_target_extent_ro: false
|
||||
iscsi_target_extent_ro: false,
|
||||
};
|
||||
response = await httpClient.post("/services/iscsi/extent", extent);
|
||||
|
||||
|
|
@ -501,14 +520,14 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
this.ctx.logger.verbose("FreeNAS ISCSI EXTENT: %j", extent);
|
||||
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id
|
||||
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
|
||||
});
|
||||
|
||||
// create targettoextent
|
||||
let targetToExtent = {
|
||||
iscsi_target: target.id,
|
||||
iscsi_extent: extent.id,
|
||||
iscsi_lunid: 0
|
||||
iscsi_lunid: 0,
|
||||
};
|
||||
response = await httpClient.post(
|
||||
"/services/iscsi/targettoextent",
|
||||
|
|
@ -535,7 +554,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
{
|
||||
iscsi_target: target.id,
|
||||
iscsi_extent: extent.id,
|
||||
iscsi_lunid: 0
|
||||
iscsi_lunid: 0,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -562,7 +581,8 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
);
|
||||
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]: targetToExtent.id
|
||||
[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]:
|
||||
targetToExtent.id,
|
||||
});
|
||||
|
||||
break;
|
||||
|
|
@ -596,14 +616,14 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
? targetGroupConfig.targetGroupAuthType
|
||||
.toUpperCase()
|
||||
.replace(" ", "_")
|
||||
: "NONE"
|
||||
: "NONE",
|
||||
});
|
||||
}
|
||||
let target = {
|
||||
name: iscsiName,
|
||||
alias: null, // cannot send "" error: handler error - driver: FreeNASDriver method: CreateVolume error: {"name":"GrpcError","code":2,"message":"received error creating iscsi target - code: 422 body: {\"iscsi_target_create.alias\":[{\"message\":\"Alias already exists\",\"errno\":22}]}"}
|
||||
mode: "ISCSI",
|
||||
groups: targetGroups
|
||||
groups: targetGroups,
|
||||
};
|
||||
|
||||
response = await httpClient.post("/iscsi/target", target);
|
||||
|
|
@ -618,7 +638,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
)
|
||||
) {
|
||||
target = await this.findResourceByProperties("/iscsi/target", {
|
||||
name: iscsiName
|
||||
name: iscsiName,
|
||||
});
|
||||
} else {
|
||||
throw new GrpcError(
|
||||
|
|
@ -643,7 +663,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
|
||||
// set target.id on zvol
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id
|
||||
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
|
||||
});
|
||||
|
||||
let extent = {
|
||||
|
|
@ -658,7 +678,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
blocksize: Number(extentBlocksize),
|
||||
pblocksize: extentDisablePhysicalBlocksize,
|
||||
rpm: "" + extentRpm, // should be a string
|
||||
ro: false
|
||||
ro: false,
|
||||
};
|
||||
|
||||
response = await httpClient.post("/iscsi/extent", extent);
|
||||
|
|
@ -673,7 +693,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
)
|
||||
) {
|
||||
extent = await this.findResourceByProperties("/iscsi/extent", {
|
||||
name: iscsiName
|
||||
name: iscsiName,
|
||||
});
|
||||
} else {
|
||||
throw new GrpcError(
|
||||
|
|
@ -696,14 +716,14 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
this.ctx.logger.verbose("FreeNAS ISCSI EXTENT: %j", extent);
|
||||
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id
|
||||
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
|
||||
});
|
||||
|
||||
// create targettoextent
|
||||
let targetToExtent = {
|
||||
target: target.id,
|
||||
extent: extent.id,
|
||||
lunid: 0
|
||||
lunid: 0,
|
||||
};
|
||||
response = await httpClient.post(
|
||||
"/iscsi/targetextent",
|
||||
|
|
@ -729,7 +749,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
{
|
||||
target: target.id,
|
||||
extent: extent.id,
|
||||
lunid: 0
|
||||
lunid: 0,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
@ -756,7 +776,8 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
);
|
||||
|
||||
await zb.zfs.set(datasetName, {
|
||||
[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]: targetToExtent.id
|
||||
[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]:
|
||||
targetToExtent.id,
|
||||
});
|
||||
|
||||
break;
|
||||
|
|
@ -793,7 +814,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
//chapDiscoveryEnabled: this.options.iscsi.chapDiscoveryEnabled,
|
||||
//chapSessionEnabled: this.options.iscsi.chapSessionEnabled,
|
||||
iqn: iqn,
|
||||
lun: 0
|
||||
lun: 0,
|
||||
};
|
||||
return volume_context;
|
||||
|
||||
|
|
@ -819,7 +840,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
case "nfs":
|
||||
try {
|
||||
properties = await zb.zfs.get(datasetName, [
|
||||
FREENAS_NFS_SHARE_PROPERTY_NAME
|
||||
FREENAS_NFS_SHARE_PROPERTY_NAME,
|
||||
]);
|
||||
} catch (err) {
|
||||
if (err.toString().includes("dataset does not exist")) {
|
||||
|
|
@ -884,7 +905,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
|||
properties = await zb.zfs.get(datasetName, [
|
||||
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
|
||||
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
|
||||
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME
|
||||
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
|
||||
]);
|
||||
} catch (err) {
|
||||
if (err.toString().includes("dataset does not exist")) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue