Rename all FreeNAS references to TrueNAS

- Renamed src/driver/freenas/ directory to src/driver/truenas/
- Renamed FreeNASApiDriver class to TrueNASApiDriver
- Updated all FREENAS_* constants to TRUENAS_*
- Updated registry namespace from FreeNASApiDriver to TrueNASApiDriver
- Updated driver factory to import TrueNASApiDriver from truenas directory
- Rewrote example configurations for TrueNAS SCALE 25.04+ WebSocket API:
  - truenas-nfs.yaml: Clean NFS configuration
  - truenas-iscsi.yaml: Clean iSCSI configuration
  - truenas-nvmeof.yaml: New NVMe-oF configuration
- Removed freenas-api-smb.yaml (SMB not supported)
- All driver names updated: truenas-nfs, truenas-iscsi, truenas-nvmeof
This commit is contained in:
Claude 2025-11-24 19:18:59 +00:00
parent c84339ff93
commit 3810363066
No known key found for this signature in database
10 changed files with 339 additions and 309 deletions

View File

@ -1,91 +0,0 @@
driver: freenas-api-iscsi
instance_id:
httpConnection:
protocol: http
host: server address
port: 80
# use only 1 of apiKey or username/password
# if both are present, apiKey is preferred
# apiKey is only available starting in TrueNAS-12
#apiKey:
username: root
password:
allowInsecure: true
# 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
zfs:
# can be used to override defaults if necessary
# the example below is useful for TrueNAS 12
#cli:
# sudoEnabled: true
#
# leave paths unset for auto-detection
# paths:
# zfs: /usr/local/sbin/zfs
# zpool: /usr/local/sbin/zpool
# sudo: /usr/local/bin/sudo
# chroot: /usr/sbin/chroot
# can be used to set arbitrary values on the dataset/zvol
# can use handlebars templates with the parameters from the storage class/CO
#datasetProperties:
# "org.freenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.freenas:test": "{{ parameters.foo }}"
# "org.freenas:test2": "some value"
# total volume name (zvol/<datasetParentName>/<pvc name>) length cannot exceed 63 chars
# https://www.ixsystems.com/documentation/freenas/11.2-U5/storage.html#zfs-zvol-config-opts-tab
# standard volume naming overhead is 46 chars
# datasetParentName should therefore be 17 chars or less when using TrueNAS 12 or below (SCALE and 13+ do not have the same limits)
# for work-arounds see https://github.com/democratic-csi/democratic-csi/issues/54
datasetParentName: tank/k8s/b/vols
# do NOT make datasetParentName and detachedSnapshotsDatasetParentName overlap
# they may be siblings, but neither should be nested in the other
# do NOT comment this option out even if you don't plan to use snapshots, just leave it with dummy value
detachedSnapshotsDatasetParentName: tanks/k8s/b/snaps
# "" (inherit), lz4, gzip-9, etc
zvolCompression:
# "" (inherit), on, off, verify
zvolDedup:
zvolEnableReservation: false
# 512, 1K, 2K, 4K, 8K, 16K, 64K, 128K default is 16K
zvolBlocksize:
iscsi:
targetPortal: "server[:port]"
# for multipath
targetPortals: [] # [ "server[:port]", "server[:port]", ... ]
# 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
targetGroups:
# get the correct ID from the "portal" section in the UI
# https://github.com/democratic-csi/democratic-csi/issues/302
# NOTE: the ID in the UI does NOT always match the ID in the DB, you must use the DB value
- targetGroupPortalGroup: 1
# get the correct ID from the "initiators" section in the UI
targetGroupInitiatorGroup: 1
# None, CHAP, or CHAP Mutual
targetGroupAuthType: None
# get the correct ID from the "Authorized Access" section of the UI
# only required if using Chap
targetGroupAuthGroup:
#extentCommentTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
extentInsecureTpc: true
extentXenCompat: false
extentDisablePhysicalBlocksize: true
# 512, 1024, 2048, or 4096,
extentBlocksize: 512
# "" (let FreeNAS decide, currently defaults to SSD), Unknown, SSD, 5400, 7200, 10000, 15000
extentRpm: "SSD"
# 0-100 (0 == ignore)
extentAvailThreshold: 0

View File

@ -1,62 +0,0 @@
driver: freenas-api-nfs
instance_id:
httpConnection:
protocol: http
host: server address
port: 80
# use only 1 of apiKey or username/password
# if both are present, apiKey is preferred
# apiKey is only available starting in TrueNAS-12
#apiKey:
username: root
password:
allowInsecure: true
# 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
zfs:
# can be used to override defaults if necessary
# the example below is useful for TrueNAS 12
#cli:
# sudoEnabled: true
#
# leave paths unset for auto-detection
# paths:
# zfs: /usr/local/sbin/zfs
# zpool: /usr/local/sbin/zpool
# sudo: /usr/local/bin/sudo
# chroot: /usr/sbin/chroot
# can be used to set arbitrary values on the dataset/zvol
# can use handlebars templates with the parameters from the storage class/CO
#datasetProperties:
# "org.freenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.freenas:test": "{{ parameters.foo }}"
# "org.freenas:test2": "some value"
datasetParentName: tank/k8s/a/vols
# do NOT make datasetParentName and detachedSnapshotsDatasetParentName overlap
# they may be siblings, but neither should be nested in the other
# do NOT comment this option out even if you don't plan to use snapshots, just leave it with dummy value
detachedSnapshotsDatasetParentName: tank/k8s/a/snaps
datasetEnableQuotas: true
datasetEnableReservation: false
datasetPermissionsMode: "0777"
datasetPermissionsUser: 0
datasetPermissionsGroup: 0
# not supported yet
#datasetPermissionsAcls:
#- "-m everyone@:full_set:allow"
#- "-m u:kube:full_set:allow"
nfs:
#shareCommentTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
shareHost: server address
shareAlldirs: false
shareAllowedHosts: []
shareAllowedNetworks: []
shareMaprootUser: root
shareMaprootGroup: root
shareMapallUser: ""
shareMapallGroup: ""

View File

@ -1,81 +0,0 @@
driver: freenas-api-smb
instance_id:
httpConnection:
protocol: http
host: server address
port: 80
# use only 1 of apiKey or username/password
# if both are present, apiKey is preferred
# apiKey is only available starting in TrueNAS-12
#apiKey:
username: root
password:
allowInsecure: true
# 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
zfs:
# can be used to override defaults if necessary
# the example below is useful for TrueNAS 12
#cli:
# sudoEnabled: true
#
# leave paths unset for auto-detection
# paths:
# zfs: /usr/local/sbin/zfs
# zpool: /usr/local/sbin/zpool
# sudo: /usr/local/bin/sudo
# chroot: /usr/sbin/chroot
# can be used to set arbitrary values on the dataset/zvol
# can use handlebars templates with the parameters from the storage class/CO
#datasetProperties:
# "org.freenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.freenas:test": "{{ parameters.foo }}"
# "org.freenas:test2": "some value"
# these are managed automatically via the volume creation process when flagged as an smb volume
#datasetProperties:
# aclmode: restricted
# casesensitivity: mixed
datasetParentName: tank/k8s/a/vols
# do NOT make datasetParentName and detachedSnapshotsDatasetParentName overlap
# they may be siblings, but neither should be nested in the other
# do NOT comment this option out even if you don't plan to use snapshots, just leave it with dummy value
detachedSnapshotsDatasetParentName: tank/k8s/a/snaps
datasetEnableQuotas: true
datasetEnableReservation: false
datasetPermissionsMode: "0777"
datasetPermissionsUser: 0
datasetPermissionsGroup: 0
# not supported yet in api
#datasetPermissionsAcls:
#- "-m everyone@:full_set:allow"
#- "-m u:kube:full_set:allow"
smb:
shareHost: server address
nameTemplate: ""
namePrefix: ""
nameSuffix: ""
# if any of the shareFoo parameters do not work with your version of FreeNAS
# simply comment the param (and use the configuration template if necessary)
shareAuxiliaryConfigurationTemplate: |
#guest ok = yes
#guest only = yes
shareHome: false
shareAllowedHosts: []
shareDeniedHosts: []
#shareDefaultPermissions: true
shareGuestOk: true
#shareGuestOnly: true
#shareShowHiddenFiles: true
shareRecycleBin: true
shareBrowsable: false
shareAccessBasedEnumeration: true
shareTimeMachine: false
#shareStorageTask:

106
examples/truenas-iscsi.yaml Normal file
View File

@ -0,0 +1,106 @@
# TrueNAS SCALE 25.04+ iSCSI Driver Configuration
# Uses WebSocket JSON-RPC 2.0 API (no SSH required)
driver: truenas-iscsi
instance_id:
# WebSocket connection to TrueNAS SCALE 25.04+
httpConnection:
protocol: https
host: truenas.example.com
port: 443
# Use API key for authentication (recommended)
# Generate API key in TrueNAS UI: Settings -> API Keys
apiKey: 1-xxxxxxxxxxxxxxxxxxxxx
# OR use username/password (less secure)
#username: root
#password: your-password
# Allow self-signed certificates (not recommended for production)
allowInsecure: true
# ZFS zvol configuration
zfs:
# Parent dataset for volumes (zvols)
datasetParentName: tank/k8s/volumes
# Parent dataset for detached snapshots
# IMPORTANT: Do NOT nest these datasets - they should be siblings
detachedSnapshotsDatasetParentName: tank/k8s/snapshots
# Enable reservations for zvols (recommended for iSCSI)
zvolEnableReservation: true
# Compression: "" (inherit), lz4, gzip-9, etc.
zvolCompression: lz4
# Deduplication: "" (inherit), on, off, verify
zvolDedup: ""
# Block size: 512, 1K, 2K, 4K, 8K, 16K, 64K, 128K (default: 16K)
zvolBlocksize: 16K
# Set custom ZFS properties using Handlebars templates
#datasetProperties:
# "org.truenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.truenas:pvc-name": "{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# iSCSI configuration
iscsi:
# Target portal (TrueNAS iSCSI server)
targetPortal: "truenas.example.com:3260"
# For multipath support, specify multiple portals
targetPortals: []
# Example: ["truenas1.example.com:3260", "truenas2.example.com:3260"]
# iSCSI interface for iscsiadm (leave empty to omit -I flag)
interface: ""
# Target naming
# Full IQN limit is 223 bytes, plan accordingly
# Default template is "{{ name }}"
#nameTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
namePrefix: csi-
nameSuffix: "-k8s"
# Target groups configuration
# Add as many as needed for your storage classes
targetGroups:
# Portal Group ID from TrueNAS UI: Sharing -> iSCSI -> Portals
# NOTE: Use the DB ID, not the UI display value
- targetGroupPortalGroup: 1
# Initiator Group ID from TrueNAS UI: Sharing -> iSCSI -> Initiators
targetGroupInitiatorGroup: 1
# Authentication type: None, CHAP, or CHAP Mutual
targetGroupAuthType: None
# Authorized Access ID (only required if using CHAP)
# From TrueNAS UI: Sharing -> iSCSI -> Authorized Access
targetGroupAuthGroup:
# Extent configuration
# Custom comment template for extents
#extentCommentTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# Insecure TPC (Tape Priority Commands)
extentInsecureTpc: true
# Xen compatibility mode
extentXenCompat: false
# Disable physical block size reporting
extentDisablePhysicalBlocksize: true
# Logical block size: 512, 1024, 2048, or 4096
extentBlocksize: 512
# RPM: "" (let TrueNAS decide, defaults to SSD), Unknown, SSD, 5400, 7200, 10000, 15000
extentRpm: "SSD"
# Available space threshold (0-100, 0 = ignore)
extentAvailThreshold: 0

65
examples/truenas-nfs.yaml Normal file
View File

@ -0,0 +1,65 @@
# TrueNAS SCALE 25.04+ NFS Driver Configuration
# Uses WebSocket JSON-RPC 2.0 API (no SSH required)
driver: truenas-nfs
instance_id:
# WebSocket connection to TrueNAS SCALE 25.04+
httpConnection:
protocol: https
host: truenas.example.com
port: 443
# Use API key for authentication (recommended)
# Generate API key in TrueNAS UI: Settings -> API Keys
apiKey: 1-xxxxxxxxxxxxxxxxxxxxx
# OR use username/password (less secure)
#username: root
#password: your-password
# Allow self-signed certificates (not recommended for production)
allowInsecure: true
# ZFS dataset configuration
zfs:
# Parent dataset for volumes
datasetParentName: tank/k8s/volumes
# Parent dataset for detached snapshots
# IMPORTANT: Do NOT nest these datasets - they should be siblings
detachedSnapshotsDatasetParentName: tank/k8s/snapshots
# Enable quotas on datasets (recommended for NFS)
datasetEnableQuotas: true
# Enable reservations (not recommended - wastes space)
datasetEnableReservation: false
# Default permissions
datasetPermissionsMode: "0777"
datasetPermissionsUser: 0
datasetPermissionsGroup: 0
# Set custom ZFS properties using Handlebars templates
#datasetProperties:
# "org.truenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.truenas:pvc-name": "{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# NFS share configuration
nfs:
# NFS server hostname/IP (should match TrueNAS system)
shareHost: truenas.example.com
# Custom share comment template
#shareCommentTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# NFS export options
shareAllowedHosts: []
shareAllowedNetworks: []
# User/group mapping (root squashing)
shareMaprootUser: root
shareMaprootGroup: wheel
shareMapallUser: ""
shareMapallGroup: ""

View File

@ -0,0 +1,99 @@
# TrueNAS SCALE 25.04+ NVMe-oF Driver Configuration
# Uses WebSocket JSON-RPC 2.0 API (no SSH required)
driver: truenas-nvmeof
instance_id:
# WebSocket connection to TrueNAS SCALE 25.04+
httpConnection:
protocol: https
host: truenas.example.com
port: 443
# Use API key for authentication (recommended)
# Generate API key in TrueNAS UI: Settings -> API Keys
apiKey: 1-xxxxxxxxxxxxxxxxxxxxx
# OR use username/password (less secure)
#username: root
#password: your-password
# Allow self-signed certificates (not recommended for production)
allowInsecure: true
# ZFS zvol configuration
zfs:
# Parent dataset for volumes (zvols)
datasetParentName: tank/k8s/volumes
# Parent dataset for detached snapshots
# IMPORTANT: Do NOT nest these datasets - they should be siblings
detachedSnapshotsDatasetParentName: tank/k8s/snapshots
# Enable reservations for zvols (recommended for NVMe-oF)
zvolEnableReservation: true
# Compression: "" (inherit), lz4, gzip-9, etc.
zvolCompression: lz4
# Deduplication: "" (inherit), on, off, verify
zvolDedup: ""
# Block size: 512, 1K, 2K, 4K, 8K, 16K, 64K, 128K (default: 16K)
zvolBlocksize: 16K
# Set custom ZFS properties using Handlebars templates
#datasetProperties:
# "org.truenas:description": "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# "org.truenas:pvc-name": "{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
# NVMe-oF configuration
nvmeof:
# NVMe-oF target address (TrueNAS NVMe-oF server)
targetAddress: truenas.example.com
# NVMe-oF transport protocol
# Supported: tcp, rdma
transport: tcp
# Port for NVMe-oF target (default: 4420 for TCP, 4420 for RDMA)
port: 4420
# NQN (NVMe Qualified Name) prefix
# Full NQN format: nqn.2014-08.org.nvmexpress:uuid:<namespace-uuid>
nqnPrefix: "nqn.2014-08.com.example"
# Subsystem naming
# Default template is "{{ name }}"
#nameTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}-{{ parameters.[csi.storage.k8s.io/pvc/name] }}"
namePrefix: csi-
nameSuffix: "-k8s"
# Subsystem configuration
subsystem:
# Allow any host to connect (true) or restrict to specific hosts (false)
allowAnyHost: true
# Serial number for the subsystem (auto-generated if not specified)
#serialNumber: ""
# Namespace configuration
namespace:
# Namespace ID (1-based, auto-assigned if not specified)
#nsid: 1
# UUID for the namespace (auto-generated if not specified)
#uuid: ""
# Enable NGUID (Namespace Globally Unique Identifier)
enableNguid: true
# Host access configuration (only used if allowAnyHost is false)
hosts:
# List of allowed host NQNs
# Example:
# - "nqn.2014-08.org.nvmexpress:uuid:12345678-1234-1234-1234-123456789abc"
# - "nqn.2014-08.org.nvmexpress:uuid:87654321-4321-4321-4321-cba987654321"
# Custom comment template for subsystems/namespaces
#commentTemplate: "{{ parameters.[csi.storage.k8s.io/pvc/namespace] }}/{{ parameters.[csi.storage.k8s.io/pvc/name] }}"

View File

@ -1,4 +1,4 @@
const { FreeNASApiDriver } = require("./freenas/api");
const { TrueNASApiDriver } = require("./truenas/api");
function factory(ctx, options) {
switch (options.driver) {
@ -6,7 +6,7 @@ function factory(ctx, options) {
case "truenas-nfs":
case "truenas-iscsi":
case "truenas-nvmeof":
return new FreeNASApiDriver(ctx, options);
return new TrueNASApiDriver(ctx, options);
default:
throw new Error("invalid csi driver: " + options.driver + ". Only truenas-nfs, truenas-iscsi, and truenas-nvmeof are supported.");
}

View File

@ -11,16 +11,16 @@ const uuidv4 = require("uuid").v4;
const semver = require("semver");
// TrueNAS SCALE share properties
const FREENAS_NFS_SHARE_PROPERTY_NAME = "democratic-csi:truenas_nfs_share_id";
const FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME =
const TRUENAS_NFS_SHARE_PROPERTY_NAME = "democratic-csi:truenas_nfs_share_id";
const TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME =
"democratic-csi:truenas_iscsi_target_id";
const FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME =
const TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME =
"democratic-csi:truenas_iscsi_extent_id";
const FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME =
const TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME =
"democratic-csi:truenas_iscsi_targetextent_id";
const FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME =
const TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME =
"democratic-csi:truenas_nvmeof_subsystem_id";
const FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME =
const TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME =
"democratic-csi:truenas_nvmeof_namespace_id";
// zfs common properties
@ -44,9 +44,9 @@ const VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME =
const VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME =
"democratic-csi:volume_context_provisioner_instance_id";
const __REGISTRY_NS__ = "FreeNASApiDriver";
const __REGISTRY_NS__ = "TrueNASApiDriver";
class FreeNASApiDriver extends CsiBaseDriver {
class TrueNASApiDriver extends CsiBaseDriver {
constructor(ctx, options) {
super(...arguments);
@ -218,13 +218,13 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Get dataset properties
const properties = await httpApiClient.DatasetGet(datasetName, [
"mountpoint",
FREENAS_NFS_SHARE_PROPERTY_NAME,
TRUENAS_NFS_SHARE_PROPERTY_NAME,
]);
this.ctx.logger.debug("Dataset properties: %j", properties);
const mountpoint = properties.mountpoint.value;
const shareId = properties[FREENAS_NFS_SHARE_PROPERTY_NAME].value;
const shareId = properties[TRUENAS_NFS_SHARE_PROPERTY_NAME].value;
// Check if share already exists
if (!zb.helpers.isPropertyValueSet(shareId)) {
@ -270,7 +270,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Store share ID in ZFS property
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_NFS_SHARE_PROPERTY_NAME]: share.id,
[TRUENAS_NFS_SHARE_PROPERTY_NAME]: share.id,
});
} catch (error) {
// Check if share already exists for this path
@ -287,7 +287,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Store existing share ID
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_NFS_SHARE_PROPERTY_NAME]: existingShare.id,
[TRUENAS_NFS_SHARE_PROPERTY_NAME]: existingShare.id,
});
} else {
throw new GrpcError(
@ -313,14 +313,14 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Get dataset properties
const properties = await httpApiClient.DatasetGet(datasetName, [
"name",
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
]);
const targetId = properties[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const extentId = properties[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const targetExtentId = properties[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME].value;
const targetId = properties[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const extentId = properties[TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const targetExtentId = properties[TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME].value;
// Check if already fully configured
if (zb.helpers.isPropertyValueSet(targetExtentId)) {
@ -366,7 +366,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
this.ctx.logger.info(`iSCSI target created with ID: ${target.id}`);
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
});
} catch (error) {
if (error.message && error.message.includes("already exists")) {
@ -375,7 +375,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
if (targets && targets.length > 0) {
target = targets[0];
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME]: target.id,
});
} else {
throw new GrpcError(
@ -436,7 +436,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
this.ctx.logger.info(`iSCSI extent created with ID: ${extent.id}`);
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
[TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
});
} catch (error) {
if (error.message && error.message.includes("already exists")) {
@ -445,7 +445,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
if (extents && extents.length > 0) {
extent = extents[0];
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
[TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME]: extent.id,
});
} else {
throw new GrpcError(
@ -463,12 +463,12 @@ class FreeNASApiDriver extends CsiBaseDriver {
if (!zb.helpers.isPropertyValueSet(targetExtentId)) {
// Get current target and extent IDs from properties
const currentProps = await httpApiClient.DatasetGet(datasetName, [
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
]);
const finalTargetId = currentProps[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const finalExtentId = currentProps[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const finalTargetId = currentProps[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const finalExtentId = currentProps[TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const targetExtentConfig = {
target: parseInt(finalTargetId),
@ -480,16 +480,16 @@ class FreeNASApiDriver extends CsiBaseDriver {
this.ctx.logger.info(`iSCSI target-extent created with ID: ${targetExtent.id}`);
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]: targetExtent.id,
[TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME]: targetExtent.id,
});
}
}
// Get final target name for volume context
const finalProps = await httpApiClient.DatasetGet(datasetName, [
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
]);
const finalTargetId = finalProps[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const finalTargetId = finalProps[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const targets = await httpApiClient.ISCSITargetQuery([["id", "=", parseInt(finalTargetId)]]);
const targetName = targets[0].name;
@ -514,12 +514,12 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Get dataset properties
const properties = await httpApiClient.DatasetGet(datasetName, [
"name",
FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME,
]);
const subsystemId = properties[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const namespaceId = properties[FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME].value;
const subsystemId = properties[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const namespaceId = properties[TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME].value;
// Check if already fully configured
if (zb.helpers.isPropertyValueSet(namespaceId)) {
@ -560,7 +560,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
this.ctx.logger.info(`NVMe-oF subsystem created with ID: ${subsystem.id}`);
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME]: subsystem.id,
[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME]: subsystem.id,
});
} catch (error) {
if (error.message && error.message.includes("already exists")) {
@ -569,7 +569,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
if (subsystems && subsystems.length > 0) {
subsystem = subsystems[0];
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME]: subsystem.id,
[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME]: subsystem.id,
});
} else {
throw new GrpcError(
@ -586,9 +586,9 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Create namespace
if (!zb.helpers.isPropertyValueSet(namespaceId)) {
const currentProps = await httpApiClient.DatasetGet(datasetName, [
FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
]);
const finalSubsystemId = currentProps[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const finalSubsystemId = currentProps[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const namespacePath = `/dev/zvol/${datasetName}`;
@ -602,16 +602,16 @@ class FreeNASApiDriver extends CsiBaseDriver {
this.ctx.logger.info(`NVMe-oF namespace created with ID: ${namespace.id}`);
await httpApiClient.DatasetSet(datasetName, {
[FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME]: namespace.id,
[TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME]: namespace.id,
});
}
}
// Get final subsystem NQN for volume context
const finalProps = await httpApiClient.DatasetGet(datasetName, [
FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
]);
const finalSubsystemId = finalProps[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const finalSubsystemId = finalProps[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const subsystems = await httpApiClient.NVMeOFSubsystemQuery([["id", "=", parseInt(finalSubsystemId)]]);
const subsystemNqn = subsystems[0].nqn;
@ -677,10 +677,10 @@ class FreeNASApiDriver extends CsiBaseDriver {
async deleteNFSShare(datasetName, httpApiClient, zb) {
try {
const properties = await httpApiClient.DatasetGet(datasetName, [
FREENAS_NFS_SHARE_PROPERTY_NAME,
TRUENAS_NFS_SHARE_PROPERTY_NAME,
]);
const shareId = properties[FREENAS_NFS_SHARE_PROPERTY_NAME].value;
const shareId = properties[TRUENAS_NFS_SHARE_PROPERTY_NAME].value;
if (zb.helpers.isPropertyValueSet(shareId)) {
this.ctx.logger.debug(`Deleting NFS share ID: ${shareId}`);
@ -689,7 +689,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
// Remove property
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_NFS_SHARE_PROPERTY_NAME
TRUENAS_NFS_SHARE_PROPERTY_NAME
);
}
} catch (error) {
@ -706,14 +706,14 @@ class FreeNASApiDriver extends CsiBaseDriver {
async deleteISCSIShare(datasetName, httpApiClient, zb) {
try {
const properties = await httpApiClient.DatasetGet(datasetName, [
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME,
TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME,
TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME,
]);
const targetId = properties[FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const extentId = properties[FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const targetExtentId = properties[FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME].value;
const targetId = properties[TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME].value;
const extentId = properties[TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME].value;
const targetExtentId = properties[TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME].value;
// Delete target-extent association first
if (zb.helpers.isPropertyValueSet(targetExtentId)) {
@ -721,7 +721,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
await httpApiClient.ISCSITargetExtentDelete(parseInt(targetExtentId), true);
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME
TRUENAS_ISCSI_TARGETTOEXTENT_ID_PROPERTY_NAME
);
}
@ -731,7 +731,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
await httpApiClient.ISCSIExtentDelete(parseInt(extentId), false, true);
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_ISCSI_EXTENT_ID_PROPERTY_NAME
TRUENAS_ISCSI_EXTENT_ID_PROPERTY_NAME
);
}
@ -741,7 +741,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
await httpApiClient.ISCSITargetDelete(parseInt(targetId), true);
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_ISCSI_TARGET_ID_PROPERTY_NAME
TRUENAS_ISCSI_TARGET_ID_PROPERTY_NAME
);
}
} catch (error) {
@ -758,12 +758,12 @@ class FreeNASApiDriver extends CsiBaseDriver {
async deleteNVMeOFShare(datasetName, httpApiClient, zb) {
try {
const properties = await httpApiClient.DatasetGet(datasetName, [
FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME,
TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME,
]);
const subsystemId = properties[FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const namespaceId = properties[FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME].value;
const subsystemId = properties[TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME].value;
const namespaceId = properties[TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME].value;
// Delete namespace first
if (zb.helpers.isPropertyValueSet(namespaceId)) {
@ -771,7 +771,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
await httpApiClient.NVMeOFNamespaceDelete(parseInt(namespaceId));
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME
TRUENAS_NVMEOF_NAMESPACE_ID_PROPERTY_NAME
);
}
@ -781,7 +781,7 @@ class FreeNASApiDriver extends CsiBaseDriver {
await httpApiClient.NVMeOFSubsystemDelete(parseInt(subsystemId));
await httpApiClient.DatasetInherit(
datasetName,
FREENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME
TRUENAS_NVMEOF_SUBSYSTEM_ID_PROPERTY_NAME
);
}
} catch (error) {
@ -927,13 +927,10 @@ class FreeNASApiDriver extends CsiBaseDriver {
*/
getDriverZfsResourceType() {
switch (this.options.driver) {
case "freenas-api-nfs":
case "truenas-api-nfs":
case "freenas-api-smb":
case "truenas-api-smb":
case "truenas-nfs":
return "filesystem";
case "freenas-api-iscsi":
case "truenas-api-iscsi":
case "truenas-iscsi":
case "truenas-nvmeof":
return "volume";
default:
throw new Error("unknown driver: " + this.ctx.args.driver);
@ -942,15 +939,12 @@ class FreeNASApiDriver extends CsiBaseDriver {
getDriverShareType() {
switch (this.options.driver) {
case "freenas-api-nfs":
case "truenas-api-nfs":
case "truenas-nfs":
return "nfs";
case "freenas-api-smb":
case "truenas-api-smb":
return "smb";
case "freenas-api-iscsi":
case "truenas-api-iscsi":
case "truenas-iscsi":
return "iscsi";
case "truenas-nvmeof":
return "nvmeof";
default:
throw new Error("unknown driver: " + this.ctx.args.driver);
}
@ -3416,4 +3410,4 @@ class FreeNASApiDriver extends CsiBaseDriver {
}
}
module.exports.FreeNASApiDriver = FreeNASApiDriver;
module.exports.TrueNASApiDriver = TrueNASApiDriver;

View File

@ -10,7 +10,7 @@ const __REGISTRY_NS__ = "TrueNASWebSocketApi";
* This class provides a clean interface to TrueNAS SCALE 25.04+ API
* using WebSocket JSON-RPC 2.0 protocol only.
*
* All legacy support for FreeNAS and old TrueNAS versions has been removed.
* All legacy support for TrueNAS and old TrueNAS versions has been removed.
*
* API Documentation: https://api.truenas.com/v25.04.2/
*/