many fixes, support auto-detection of truenas binary paths and apiVersion, fix config typo, better support for potential race conditions with deleting shares
This commit is contained in:
parent
6c79b32f9b
commit
c4a36750cd
|
|
@ -12,6 +12,7 @@ httpConnection:
|
||||||
password:
|
password:
|
||||||
allowInsecure: true
|
allowInsecure: true
|
||||||
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
||||||
|
# leave unset for auto-detection
|
||||||
#apiVersion: 2
|
#apiVersion: 2
|
||||||
sshConnection:
|
sshConnection:
|
||||||
host: server address
|
host: server address
|
||||||
|
|
@ -28,6 +29,8 @@ zfs:
|
||||||
# the example below is useful for TrueNAS 12
|
# the example below is useful for TrueNAS 12
|
||||||
#cli:
|
#cli:
|
||||||
# sudoEnabled: true
|
# sudoEnabled: true
|
||||||
|
#
|
||||||
|
# leave paths unset for auto-detection
|
||||||
# paths:
|
# paths:
|
||||||
# zfs: /usr/local/sbin/zfs
|
# zfs: /usr/local/sbin/zfs
|
||||||
# zpool: /usr/local/sbin/zpool
|
# zpool: /usr/local/sbin/zpool
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ httpConnection:
|
||||||
password:
|
password:
|
||||||
allowInsecure: true
|
allowInsecure: true
|
||||||
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
||||||
|
# leave unset for auto-detection
|
||||||
#apiVersion: 2
|
#apiVersion: 2
|
||||||
sshConnection:
|
sshConnection:
|
||||||
host: server address
|
host: server address
|
||||||
|
|
@ -28,6 +29,8 @@ zfs:
|
||||||
# the example below is useful for TrueNAS 12
|
# the example below is useful for TrueNAS 12
|
||||||
#cli:
|
#cli:
|
||||||
# sudoEnabled: true
|
# sudoEnabled: true
|
||||||
|
#
|
||||||
|
# leave paths unset for auto-detection
|
||||||
# paths:
|
# paths:
|
||||||
# zfs: /usr/local/sbin/zfs
|
# zfs: /usr/local/sbin/zfs
|
||||||
# zpool: /usr/local/sbin/zpool
|
# zpool: /usr/local/sbin/zpool
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ httpConnection:
|
||||||
password:
|
password:
|
||||||
allowInsecure: true
|
allowInsecure: true
|
||||||
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
# use apiVersion 2 for TrueNAS-12 and up (will work on 11.x in some scenarios as well)
|
||||||
|
# leave unset for auto-detection
|
||||||
#apiVersion: 2
|
#apiVersion: 2
|
||||||
sshConnection:
|
sshConnection:
|
||||||
host: server address
|
host: server address
|
||||||
|
|
@ -28,6 +29,8 @@ zfs:
|
||||||
# the example below is useful for TrueNAS 12
|
# the example below is useful for TrueNAS 12
|
||||||
#cli:
|
#cli:
|
||||||
# sudoEnabled: true
|
# sudoEnabled: true
|
||||||
|
#
|
||||||
|
# leave paths unset for auto-detection
|
||||||
# paths:
|
# paths:
|
||||||
# zfs: /usr/local/sbin/zfs
|
# zfs: /usr/local/sbin/zfs
|
||||||
# zpool: /usr/local/sbin/zpool
|
# zpool: /usr/local/sbin/zpool
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ iscsi:
|
||||||
# http://www.linux-iscsi.org/wiki/ISCSI
|
# http://www.linux-iscsi.org/wiki/ISCSI
|
||||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1659195
|
# https://bugzilla.redhat.com/show_bug.cgi?id=1659195
|
||||||
# http://atodorov.org/blog/2015/04/07/how-to-configure-iscsi-target-on-red-hat-enterprise-linux-7/
|
# http://atodorov.org/blog/2015/04/07/how-to-configure-iscsi-target-on-red-hat-enterprise-linux-7/
|
||||||
shareStragetyTargetCli:
|
shareStrategyTargetCli:
|
||||||
#sudoEnabled: true
|
#sudoEnabled: true
|
||||||
basename: "iqn.2003-01.org.linux-iscsi.ubuntu-19.x8664"
|
basename: "iqn.2003-01.org.linux-iscsi.ubuntu-19.x8664"
|
||||||
tpg:
|
tpg:
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class ControllerZfsGenericDriver extends ControllerZfsSshBaseDriver {
|
||||||
* @param {*} datasetName
|
* @param {*} datasetName
|
||||||
*/
|
*/
|
||||||
async createShare(call, datasetName) {
|
async createShare(call, datasetName) {
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
const sshClient = this.getSshClient();
|
const sshClient = this.getSshClient();
|
||||||
|
|
||||||
let properties;
|
let properties;
|
||||||
|
|
@ -105,25 +105,25 @@ class ControllerZfsGenericDriver extends ControllerZfsSshBaseDriver {
|
||||||
|
|
||||||
switch (this.options.iscsi.shareStrategy) {
|
switch (this.options.iscsi.shareStrategy) {
|
||||||
case "targetCli":
|
case "targetCli":
|
||||||
basename = this.options.iscsi.shareStragetyTargetCli.basename;
|
basename = this.options.iscsi.shareStrategyTargetCli.basename;
|
||||||
let setAttributesText = "";
|
let setAttributesText = "";
|
||||||
let setAuthText = "";
|
let setAuthText = "";
|
||||||
if (this.options.iscsi.shareStragetyTargetCli.tpg) {
|
if (this.options.iscsi.shareStrategyTargetCli.tpg) {
|
||||||
if (this.options.iscsi.shareStragetyTargetCli.tpg.attributes) {
|
if (this.options.iscsi.shareStrategyTargetCli.tpg.attributes) {
|
||||||
for (const attributeName in this.options.iscsi
|
for (const attributeName in this.options.iscsi
|
||||||
.shareStragetyTargetCli.tpg.attributes) {
|
.shareStrategyTargetCli.tpg.attributes) {
|
||||||
const attributeValue = this.options.iscsi
|
const attributeValue = this.options.iscsi
|
||||||
.shareStragetyTargetCli.tpg.attributes[attributeName];
|
.shareStrategyTargetCli.tpg.attributes[attributeName];
|
||||||
setAttributesText += "\n";
|
setAttributesText += "\n";
|
||||||
setAttributesText += `set attribute ${attributeName}=${attributeValue}`;
|
setAttributesText += `set attribute ${attributeName}=${attributeValue}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.iscsi.shareStragetyTargetCli.tpg.auth) {
|
if (this.options.iscsi.shareStrategyTargetCli.tpg.auth) {
|
||||||
for (const attributeName in this.options.iscsi
|
for (const attributeName in this.options.iscsi
|
||||||
.shareStragetyTargetCli.tpg.auth) {
|
.shareStrategyTargetCli.tpg.auth) {
|
||||||
const attributeValue = this.options.iscsi
|
const attributeValue = this.options.iscsi
|
||||||
.shareStragetyTargetCli.tpg.auth[attributeName];
|
.shareStrategyTargetCli.tpg.auth[attributeName];
|
||||||
setAttributesText += "\n";
|
setAttributesText += "\n";
|
||||||
setAttributesText += `set auth ${attributeName}=${attributeValue}`;
|
setAttributesText += `set auth ${attributeName}=${attributeValue}`;
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +178,7 @@ create /backstores/block/${iscsiName}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteShare(call, datasetName) {
|
async deleteShare(call, datasetName) {
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
const sshClient = this.getSshClient();
|
const sshClient = this.getSshClient();
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
|
|
@ -210,7 +210,7 @@ create /backstores/block/${iscsiName}
|
||||||
iscsiName = iscsiName.toLowerCase();
|
iscsiName = iscsiName.toLowerCase();
|
||||||
switch (this.options.iscsi.shareStrategy) {
|
switch (this.options.iscsi.shareStrategy) {
|
||||||
case "targetCli":
|
case "targetCli":
|
||||||
basename = this.options.iscsi.shareStragetyTargetCli.basename;
|
basename = this.options.iscsi.shareStrategyTargetCli.basename;
|
||||||
response = await this.targetCliCommand(
|
response = await this.targetCliCommand(
|
||||||
`
|
`
|
||||||
cd /iscsi
|
cd /iscsi
|
||||||
|
|
@ -267,7 +267,7 @@ delete ${iscsiName}
|
||||||
taregetCliCommand.push("|");
|
taregetCliCommand.push("|");
|
||||||
taregetCliCommand.push("targetcli");
|
taregetCliCommand.push("targetcli");
|
||||||
|
|
||||||
if (this.options.iscsi.shareStragetyTargetCli.sudoEnabled) {
|
if (this.options.iscsi.shareStrategyTargetCli.sudoEnabled) {
|
||||||
command = "sudo";
|
command = "sudo";
|
||||||
args.unshift("sh");
|
args.unshift("sh");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getZetabyte() {
|
async getZetabyte() {
|
||||||
const sshClient = this.getSshClient();
|
const sshClient = this.getSshClient();
|
||||||
const options = {};
|
const options = {};
|
||||||
options.executor = new ZfsSshProcessManager(sshClient);
|
options.executor = new ZfsSshProcessManager(sshClient);
|
||||||
|
|
@ -130,6 +130,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.options.zfs.hasOwnProperty("cli") &&
|
this.options.zfs.hasOwnProperty("cli") &&
|
||||||
|
this.options.zfs.cli &&
|
||||||
this.options.zfs.cli.hasOwnProperty("paths")
|
this.options.zfs.cli.hasOwnProperty("paths")
|
||||||
) {
|
) {
|
||||||
options.paths = this.options.zfs.cli.paths;
|
options.paths = this.options.zfs.cli.paths;
|
||||||
|
|
@ -137,20 +138,26 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.options.zfs.hasOwnProperty("cli") &&
|
this.options.zfs.hasOwnProperty("cli") &&
|
||||||
|
this.options.zfs.cli &&
|
||||||
this.options.zfs.cli.hasOwnProperty("sudoEnabled")
|
this.options.zfs.cli.hasOwnProperty("sudoEnabled")
|
||||||
) {
|
) {
|
||||||
options.sudo = this.getSudoEnabled();
|
options.sudo = this.getSudoEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof this.setZetabyteCustomOptions === "function") {
|
||||||
|
await this.setZetabyteCustomOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
return new Zetabyte(options);
|
return new Zetabyte(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSudoEnabled() {
|
getSudoEnabled() {
|
||||||
return this.options.zfs.cli.sudoEnabled === true;
|
return this.options.zfs.cli && this.options.zfs.cli.sudoEnabled === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSudoPath() {
|
async getSudoPath() {
|
||||||
return this.options.zfs.cli.paths.sudo || "/usr/bin/sudo";
|
const zb = await this.getZetabyte();
|
||||||
|
return zb.options.paths.sudo || "/usr/bin/sudo";
|
||||||
}
|
}
|
||||||
|
|
||||||
getDatasetParentName() {
|
getDatasetParentName() {
|
||||||
|
|
@ -175,7 +182,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeSnapshotsFromDatatset(datasetName, options = {}) {
|
async removeSnapshotsFromDatatset(datasetName, options = {}) {
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
await zb.zfs.destroy(datasetName + "@%", options);
|
await zb.zfs.destroy(datasetName + "@%", options);
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +272,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||||
const sshClient = this.getSshClient();
|
const sshClient = this.getSshClient();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let datasetParentName = this.getVolumeParentDatasetName();
|
let datasetParentName = this.getVolumeParentDatasetName();
|
||||||
let snapshotParentDatasetName = this.getDetachedSnapshotParentDatasetName();
|
let snapshotParentDatasetName = this.getDetachedSnapshotParentDatasetName();
|
||||||
|
|
@ -687,7 +694,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
properties.mountpoint.value,
|
properties.mountpoint.value,
|
||||||
]);
|
]);
|
||||||
if (this.getSudoEnabled()) {
|
if (this.getSudoEnabled()) {
|
||||||
command = this.getSudoPath() + " " + command;
|
command = (await this.getSudoPath()) + " " + command;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver.ctx.logger.verbose("set permission command: %s", command);
|
driver.ctx.logger.verbose("set permission command: %s", command);
|
||||||
|
|
@ -710,7 +717,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
properties.mountpoint.value,
|
properties.mountpoint.value,
|
||||||
]);
|
]);
|
||||||
if (this.getSudoEnabled()) {
|
if (this.getSudoEnabled()) {
|
||||||
command = this.getSudoPath() + " " + command;
|
command = (await this.getSudoPath()) + " " + command;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver.ctx.logger.verbose("set ownership command: %s", command);
|
driver.ctx.logger.verbose("set ownership command: %s", command);
|
||||||
|
|
@ -727,7 +734,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
properties.mountpoint.value,
|
properties.mountpoint.value,
|
||||||
]);
|
]);
|
||||||
if (this.getSudoEnabled()) {
|
if (this.getSudoEnabled()) {
|
||||||
command = this.getSudoPath() + " " + command;
|
command = (await this.getSudoPath()) + " " + command;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver.ctx.logger.verbose("set acl command: %s", command);
|
driver.ctx.logger.verbose("set acl command: %s", command);
|
||||||
|
|
@ -799,7 +806,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
*/
|
*/
|
||||||
async DeleteVolume(call) {
|
async DeleteVolume(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let datasetParentName = this.getVolumeParentDatasetName();
|
let datasetParentName = this.getVolumeParentDatasetName();
|
||||||
let name = call.request.volume_id;
|
let name = call.request.volume_id;
|
||||||
|
|
@ -904,7 +911,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
async ControllerExpandVolume(call) {
|
async ControllerExpandVolume(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let datasetParentName = this.getVolumeParentDatasetName();
|
let datasetParentName = this.getVolumeParentDatasetName();
|
||||||
let name = call.request.volume_id;
|
let name = call.request.volume_id;
|
||||||
|
|
@ -1017,7 +1024,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
*/
|
*/
|
||||||
async GetCapacity(call) {
|
async GetCapacity(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let datasetParentName = this.getVolumeParentDatasetName();
|
let datasetParentName = this.getVolumeParentDatasetName();
|
||||||
|
|
||||||
|
|
@ -1054,7 +1061,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
async ListVolumes(call) {
|
async ListVolumes(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let datasetParentName = this.getVolumeParentDatasetName();
|
let datasetParentName = this.getVolumeParentDatasetName();
|
||||||
let entries = [];
|
let entries = [];
|
||||||
|
|
@ -1239,7 +1246,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
async ListSnapshots(call) {
|
async ListSnapshots(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let entries = [];
|
let entries = [];
|
||||||
let entries_length = 0;
|
let entries_length = 0;
|
||||||
|
|
@ -1471,7 +1478,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
async CreateSnapshot(call) {
|
async CreateSnapshot(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const driverZfsResourceType = this.getDriverZfsResourceType();
|
const driverZfsResourceType = this.getDriverZfsResourceType();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let detachedSnapshot = false;
|
let detachedSnapshot = false;
|
||||||
try {
|
try {
|
||||||
|
|
@ -1705,7 +1712,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
|
||||||
*/
|
*/
|
||||||
async DeleteSnapshot(call) {
|
async DeleteSnapshot(call) {
|
||||||
const driver = this;
|
const driver = this;
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
const snapshot_id = call.request.snapshot_id;
|
const snapshot_id = call.request.snapshot_id;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ const USER_AGENT = "democratic-csi-driver";
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
this.options = options;
|
this.options = JSON.parse(JSON.stringify(options));
|
||||||
this.logger = console;
|
this.logger = console;
|
||||||
|
|
||||||
// default to v1.0 for now
|
// default to v1.0 for now
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ const FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME =
|
||||||
"democratic-csi:freenas_iscsi_targettoextent_id";
|
"democratic-csi:freenas_iscsi_targettoextent_id";
|
||||||
const FREENAS_ISCSI_ASSETS_NAME_PROPERTY_NAME =
|
const FREENAS_ISCSI_ASSETS_NAME_PROPERTY_NAME =
|
||||||
"democratic-csi:freenas_iscsi_assets_name";
|
"democratic-csi:freenas_iscsi_assets_name";
|
||||||
|
|
||||||
class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
/**
|
/**
|
||||||
* cannot make this a storage class parameter as storage class/etc context is *not* sent
|
* cannot make this a storage class parameter as storage class/etc context is *not* sent
|
||||||
|
|
@ -36,9 +35,30 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getHttpClient() {
|
async setZetabyteCustomOptions(options) {
|
||||||
|
if (!options.hasOwnProperty("paths")) {
|
||||||
|
const majorMinor = await this.getSystemVersionMajorMinor();
|
||||||
|
const isScale = await this.getIsScale();
|
||||||
|
if (!isScale && Number(majorMinor) >= 12) {
|
||||||
|
options.paths = {
|
||||||
|
zfs: "/usr/local/sbin/zfs",
|
||||||
|
zpool: "/usr/local/sbin/zpool",
|
||||||
|
sudo: "/usr/local/bin/sudo",
|
||||||
|
chroot: "/usr/sbin/chroot",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getHttpClient(autoDetectVersion = true) {
|
||||||
const client = new HttpClient(this.options.httpConnection);
|
const client = new HttpClient(this.options.httpConnection);
|
||||||
client.logger = this.ctx.logger;
|
client.logger = this.ctx.logger;
|
||||||
|
|
||||||
|
if (autoDetectVersion && !!!this.options.httpConnection.apiVersion) {
|
||||||
|
const apiVersion = await this.getApiVersion();
|
||||||
|
client.setApiVersion(apiVersion);
|
||||||
|
}
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,7 +82,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
if (!match || Object.keys(match).length < 1) {
|
if (!match || Object.keys(match).length < 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const httpClient = this.getHttpClient();
|
const httpClient = await this.getHttpClient();
|
||||||
let target;
|
let target;
|
||||||
let page = 0;
|
let page = 0;
|
||||||
|
|
||||||
|
|
@ -126,9 +146,9 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
*/
|
*/
|
||||||
async createShare(call, datasetName) {
|
async createShare(call, datasetName) {
|
||||||
const driverShareType = this.getDriverShareType();
|
const driverShareType = this.getDriverShareType();
|
||||||
const httpClient = this.getHttpClient();
|
const httpClient = await this.getHttpClient();
|
||||||
const apiVersion = httpClient.getApiVersion();
|
const apiVersion = httpClient.getApiVersion();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let properties;
|
let properties;
|
||||||
let endpoint;
|
let endpoint;
|
||||||
|
|
@ -1017,19 +1037,22 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
|
|
||||||
async deleteShare(call, datasetName) {
|
async deleteShare(call, datasetName) {
|
||||||
const driverShareType = this.getDriverShareType();
|
const driverShareType = this.getDriverShareType();
|
||||||
const httpClient = this.getHttpClient();
|
const httpClient = await this.getHttpClient();
|
||||||
const apiVersion = httpClient.getApiVersion();
|
const apiVersion = httpClient.getApiVersion();
|
||||||
const zb = this.getZetabyte();
|
const zb = await this.getZetabyte();
|
||||||
|
|
||||||
let properties;
|
let properties;
|
||||||
let response;
|
let response;
|
||||||
let endpoint;
|
let endpoint;
|
||||||
let shareId;
|
let shareId;
|
||||||
|
let deleteAsset;
|
||||||
|
let sharePaths;
|
||||||
|
|
||||||
switch (driverShareType) {
|
switch (driverShareType) {
|
||||||
case "nfs":
|
case "nfs":
|
||||||
try {
|
try {
|
||||||
properties = await zb.zfs.get(datasetName, [
|
properties = await zb.zfs.get(datasetName, [
|
||||||
|
"mountpoint",
|
||||||
FREENAS_NFS_SHARE_PROPERTY_NAME,
|
FREENAS_NFS_SHARE_PROPERTY_NAME,
|
||||||
]);
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1063,6 +1086,20 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
// assume share is gone for now
|
// assume share is gone for now
|
||||||
if ([404, 500].includes(response.statusCode)) {
|
if ([404, 500].includes(response.statusCode)) {
|
||||||
} else {
|
} else {
|
||||||
|
switch (apiVersion) {
|
||||||
|
case 1:
|
||||||
|
sharePaths = response.body.nfs_paths;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sharePaths = response.body.paths;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAsset = sharePaths.some((value) => {
|
||||||
|
return value == properties.mountpoint.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (deleteAsset) {
|
||||||
response = await httpClient.delete(endpoint);
|
response = await httpClient.delete(endpoint);
|
||||||
|
|
||||||
// returns a 500 if does not exist
|
// returns a 500 if does not exist
|
||||||
|
|
@ -1077,6 +1114,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new GrpcError(
|
throw new GrpcError(
|
||||||
|
|
@ -1089,6 +1127,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
case "smb":
|
case "smb":
|
||||||
try {
|
try {
|
||||||
properties = await zb.zfs.get(datasetName, [
|
properties = await zb.zfs.get(datasetName, [
|
||||||
|
"mountpoint",
|
||||||
FREENAS_SMB_SHARE_PROPERTY_NAME,
|
FREENAS_SMB_SHARE_PROPERTY_NAME,
|
||||||
]);
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -1125,6 +1164,20 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
// assume share is gone for now
|
// assume share is gone for now
|
||||||
if ([404, 500].includes(response.statusCode)) {
|
if ([404, 500].includes(response.statusCode)) {
|
||||||
} else {
|
} else {
|
||||||
|
switch (apiVersion) {
|
||||||
|
case 1:
|
||||||
|
sharePaths = [response.body.cifs_path];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sharePaths = [response.body.path];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAsset = sharePaths.some((value) => {
|
||||||
|
return value == properties.mountpoint.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (deleteAsset) {
|
||||||
response = await httpClient.delete(endpoint);
|
response = await httpClient.delete(endpoint);
|
||||||
|
|
||||||
// returns a 500 if does not exist
|
// returns a 500 if does not exist
|
||||||
|
|
@ -1139,6 +1192,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new GrpcError(
|
throw new GrpcError(
|
||||||
|
|
@ -1175,7 +1229,6 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
let iscsiName =
|
let iscsiName =
|
||||||
properties[FREENAS_ISCSI_ASSETS_NAME_PROPERTY_NAME].value;
|
properties[FREENAS_ISCSI_ASSETS_NAME_PROPERTY_NAME].value;
|
||||||
let assetName;
|
let assetName;
|
||||||
let deleteAsset;
|
|
||||||
|
|
||||||
switch (apiVersion) {
|
switch (apiVersion) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
@ -1310,10 +1363,18 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
|
|
||||||
switch (driverShareType) {
|
switch (driverShareType) {
|
||||||
case "iscsi":
|
case "iscsi":
|
||||||
|
const isScale = this.getIsScale();
|
||||||
|
if (isScale) {
|
||||||
|
this.ctx.logger.verbose("FreeNAS reloading scst");
|
||||||
|
await sshClient.exec(
|
||||||
|
sshClient.buildCommand("systemctl", ["reload", "scst"])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
this.ctx.logger.verbose("FreeNAS reloading ctld");
|
this.ctx.logger.verbose("FreeNAS reloading ctld");
|
||||||
await sshClient.exec(
|
await sshClient.exec(
|
||||||
sshClient.buildCommand("/etc/rc.d/ctld", ["reload"])
|
sshClient.buildCommand("/etc/rc.d/ctld", ["reload"])
|
||||||
);
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1321,11 +1382,120 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
async getApiVersion() {
|
async getApiVersion() {
|
||||||
const systemVersion = await this.getSystemVersion();
|
const systemVersion = await this.getSystemVersion();
|
||||||
|
|
||||||
|
if (systemVersion.v2) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getIsFreeNAS() {
|
||||||
|
const systemVersion = await this.getSystemVersion();
|
||||||
|
let version;
|
||||||
|
|
||||||
|
if (systemVersion.v2) {
|
||||||
|
version = systemVersion.v2;
|
||||||
|
} else {
|
||||||
|
version = systemVersion.v1.fullversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.toLowerCase().includes("freenas")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getIsTrueNAS() {
|
||||||
|
const systemVersion = await this.getSystemVersion();
|
||||||
|
let version;
|
||||||
|
|
||||||
|
if (systemVersion.v2) {
|
||||||
|
version = systemVersion.v2;
|
||||||
|
} else {
|
||||||
|
version = systemVersion.v1.fullversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version.toLowerCase().includes("truenas")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getIsScale() {
|
||||||
|
const systemVersion = await this.getSystemVersion();
|
||||||
|
|
||||||
|
if (systemVersion.v2 && systemVersion.v2.toLowerCase().includes("scale")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSystemVersionMajorMinor() {
|
||||||
|
const systemVersion = await this.getSystemVersion();
|
||||||
|
let parts;
|
||||||
|
let parts_i;
|
||||||
|
let version;
|
||||||
|
|
||||||
|
/*
|
||||||
|
systemVersion.v2 = "FreeNAS-11.2-U5";
|
||||||
|
systemVersion.v2 = "TrueNAS-SCALE-20.11-MASTER-20201127-092915";
|
||||||
|
systemVersion.v1 = {
|
||||||
|
fullversion: "FreeNAS-9.3-STABLE-201503200528",
|
||||||
|
fullversion: "FreeNAS-11.2-U5 (c129415c52)",
|
||||||
|
};
|
||||||
|
|
||||||
|
systemVersion.v2 = null;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (systemVersion.v2) {
|
||||||
|
version = systemVersion.v2;
|
||||||
|
} else {
|
||||||
|
version = systemVersion.v1.fullversion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version) {
|
||||||
|
parts = version.split("-");
|
||||||
|
parts_i = [];
|
||||||
|
parts.forEach((value) => {
|
||||||
|
let i = value.replace(/[^\d.]/g, "");
|
||||||
|
if (i.length > 0) {
|
||||||
|
parts_i.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// join and resplit to deal with single elements which contain a decimal
|
||||||
|
parts_i = parts_i.join(".").split(".");
|
||||||
|
parts_i.splice(2);
|
||||||
|
return parts_i.join(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getSystemVersionMajor() {
|
||||||
|
const majorMinor = await this.getSystemVersionMajorMinor();
|
||||||
|
return majorMinor.split(".")[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
async setVersionInfoCache(versionInfo) {
|
||||||
|
const driver = this;
|
||||||
|
this.cache = this.cache || {};
|
||||||
|
this.cache.versionInfo = versionInfo;
|
||||||
|
|
||||||
|
// crude timeout
|
||||||
|
setTimeout(function () {
|
||||||
|
driver.cache.versionInfo = null;
|
||||||
|
}, 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
async getSystemVersion() {
|
async getSystemVersion() {
|
||||||
const httpClient = this.getHttpClient();
|
this.cache = this.cache || {};
|
||||||
|
if (this.cache.versionInfo) {
|
||||||
|
return this.cache.versionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const httpClient = await this.getHttpClient(false);
|
||||||
const endpoint = "/system/version/";
|
const endpoint = "/system/version/";
|
||||||
let response;
|
let response;
|
||||||
const startApiVersion = httpClient.getApiVersion();
|
const startApiVersion = httpClient.getApiVersion();
|
||||||
|
|
@ -1334,12 +1504,18 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
httpClient.setApiVersion(2);
|
httpClient.setApiVersion(2);
|
||||||
/**
|
/**
|
||||||
* FreeNAS-11.2-U5
|
* FreeNAS-11.2-U5
|
||||||
|
* TrueNAS-12.0-RELEASE
|
||||||
|
* TrueNAS-SCALE-20.11-MASTER-20201127-092915
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
response = await httpClient.get(endpoint);
|
response = await httpClient.get(endpoint);
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
versionInfo.v2 = response.body;
|
versionInfo.v2 = response.body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return immediately to save on resources and silly requests
|
||||||
|
await this.setVersionInfoCache(versionInfo);
|
||||||
|
return versionInfo;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
httpClient.setApiVersion(1);
|
httpClient.setApiVersion(1);
|
||||||
|
|
@ -1357,6 +1533,7 @@ class FreeNASDriver extends ControllerZfsSshBaseDriver {
|
||||||
// reset apiVersion
|
// reset apiVersion
|
||||||
httpClient.setApiVersion(startApiVersion);
|
httpClient.setApiVersion(startApiVersion);
|
||||||
|
|
||||||
|
await this.setVersionInfoCache(versionInfo);
|
||||||
return versionInfo;
|
return versionInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue