Merge pull request #57 from democratic-csi/next

Next
This commit is contained in:
Travis Glenn Hansen 2021-02-21 21:19:03 -07:00 committed by GitHub
commit 8e4c2a9df8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 350 additions and 119 deletions

View File

@ -1,3 +1,10 @@
# v1.1.0
Released 2021-02-21
- support for csi-v1.3.0
- fix a snapshot issue when requested with specific `snapshot_id`
# v1.0.1 # v1.0.1
Released 2021-01-29 Released 2021-01-29

View File

@ -45,7 +45,17 @@ Predominantly 3 things are needed:
You should install/configure the requirements for both nfs and iscsi. You should install/configure the requirements for both nfs and iscsi.
Follow the instructions here: https://netapp-trident.readthedocs.io/en/stable-v20.04/kubernetes/operations/tasks/worker.html ### nfs
```
RHEL / CentOS
sudo yum install -y nfs-utils
Ubuntu / Debian
sudo apt-get install -y nfs-common
```
### iscsi
Note that `multipath` is supported for the `iscsi`-based drivers. Simply setup Note that `multipath` is supported for the `iscsi`-based drivers. Simply setup
multipath to your liking and set multiple portals in the config as appropriate. multipath to your liking and set multiple portals in the config as appropriate.
@ -54,10 +64,51 @@ 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
```
RHEL / CentOS
# Install the following system packages
sudo yum install -y lsscsi iscsi-initiator-utils sg3_utils device-mapper-multipath
# Enable multipathing
sudo mpathconf --enable --with_multipathd y
# Ensure that iscsid and multipathd are running
sudo systemctl enable iscsid multipathd
sudo systemctl start iscsid multipathd
# Start and enable iscsi
sudo systemctl enable iscsi
sudo systemctl start iscsi
Ubuntu / Debian
# Install the following system packages
sudo apt-get install -y open-iscsi lsscsi sg3-utils multipath-tools scsitools
# Enable multipathing
sudo tee /etc/multipath.conf <<-'EOF'
defaults {
user_friendly_names yes
find_multipaths yes
}
EOF
sudo systemctl enable multipath-tools.service
sudo service multipath-tools restart
# Ensure that open-iscsi and multipath-tools are enabled and running
sudo systemctl status multipath-tools
sudo systemctl enable open-iscsi.service
sudo service open-iscsi start
sudo systemctl status open-iscsi
```
### freenas-smb ### freenas-smb
If using with Windows based machines you may need to enable guest access (even If using with Windows based machines you may need to enable guest access (even
if you are connecting with credentiasl) if you are connecting with credentials)
``` ```
Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters AllowInsecureGuestAuth -Value 1 Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters AllowInsecureGuestAuth -Value 1
@ -81,7 +132,7 @@ Server preparation depends slightly on which `driver` you are using.
### FreeNAS (freenas-nfs, freenas-iscsi, freenas-smb) ### FreeNAS (freenas-nfs, freenas-iscsi, freenas-smb)
The recommended version of FreeNAS is 11.3+, however the driver should work The recommended version of FreeNAS is 12.0-U2+, however the driver should work
with much older versions as well. with much older versions as well.
Ensure the following services are configurged and running: Ensure the following services are configurged and running:
@ -90,12 +141,20 @@ Ensure the following services are configurged and running:
- ensure `zsh`, `bash`, or `sh` is set as the root shell, `csh` gives false errors due to quoting - ensure `zsh`, `bash`, or `sh` is set as the root shell, `csh` gives false errors due to quoting
- nfs - nfs
- iscsi - iscsi
- when using the FreeNAS API concurrently the `/etc/ctl.conf` file on the - (fixed in 12.0-U2+) when using the FreeNAS API concurrently the
server can become invalid, some sample scripts are provided in the `/etc/ctl.conf` file on the server can become invalid, some sample scripts
`contrib` directory to clean things up are provided in the `contrib` directory to clean things up ie: copy the
ie: copy the script to the server and directly and run - `./ctld-config-watchdog-db.sh | logger -t ctld-config-watchdog-db.sh &` script to the server and directly and run - `./ctld-config-watchdog-db.sh | logger -t ctld-config-watchdog-db.sh &`
please read the scripts and set the variables as appropriate for your server. please read the scripts and set the variables as appropriate for your server.
- ensure you have pre-emptively created portal, group, auth - ensure you have pre-emptively created portals, initatior groups, auths
- make note of the respective IDs (the true ID may not reflect what is
visible in the UI)
- IDs can be visible by clicking the the `Edit` link and finding the ID in the
browser address bar
- Optionally you may use the following to retrieve appropiate IDs:
- `curl --header "Accept: application/json" --user root:<password> 'http(s)://<ip>/api/v2.0/iscsi/portal'`
- `curl --header "Accept: application/json" --user root:<password> 'http(s)://<ip>/api/v2.0/iscsi/initiator'`
- `curl --header "Accept: application/json" --user root:<password> 'http(s)://<ip>/api/v2.0/iscsi/auth'`
- smb - smb
In addition, if you want to use a non-root user for the ssh operations you may In addition, if you want to use a non-root user for the ssh operations you may
@ -223,6 +282,11 @@ Install `democratic-csi` as usual with `volumeSnapshotClasses` defined as approp
- https://kubernetes.io/docs/concepts/storage/volume-snapshots/ - https://kubernetes.io/docs/concepts/storage/volume-snapshots/
- https://github.com/kubernetes-csi/external-snapshotter#usage - https://github.com/kubernetes-csi/external-snapshotter#usage
# Sponsors
A special shout out to the wonderful sponsors of the project!
[![ixSystems](https://www.ixsystems.com/wp-content/uploads/sites/13/2015/08/ix_logo_200x47.png "ixSystems")](http://ixsystems.com/)
# Related # Related
- https://github.com/nmaupu/freenas-provisioner - https://github.com/nmaupu/freenas-provisioner

View File

@ -81,7 +81,8 @@ const GeneralUtils = require("../src/utils/general");
if (args.logLevel) { if (args.logLevel) {
logger.level = args.logLevel; logger.level = args.logLevel;
} }
const csiVersion = process.env.CSI_VERSION || "1.2.0";
const csiVersion = process.env.CSI_VERSION || args.csiVersion || "1.2.0";
const PROTO_PATH = __dirname + "/../csi_proto/csi-v" + csiVersion + ".proto"; const PROTO_PATH = __dirname + "/../csi_proto/csi-v" + csiVersion + ".proto";
// Suggested options for similarity to existing grpc.load behavior // Suggested options for similarity to existing grpc.load behavior
@ -101,7 +102,7 @@ logger.info("initializing csi driver: %s", options.driver);
let driver; let driver;
try { try {
driver = require("../src/driver/factory").factory( driver = require("../src/driver/factory").factory(
{ logger, args, cache, package }, { logger, args, cache, package, csiVersion },
options options
); );
} catch (err) { } catch (err) {
@ -239,6 +240,9 @@ function getServer() {
async ValidateVolumeCapabilities(call, callback) { async ValidateVolumeCapabilities(call, callback) {
requestHandlerProxy(call, callback, arguments.callee.name); requestHandlerProxy(call, callback, arguments.callee.name);
}, },
async ControllerGetVolume(call, callback) {
requestHandlerProxy(call, callback, arguments.callee.name);
},
async ListVolumes(call, callback) { async ListVolumes(call, callback) {
requestHandlerProxy(call, callback, arguments.callee.name); requestHandlerProxy(call, callback, arguments.callee.name);
}, },

View File

@ -5,12 +5,12 @@ const fs = require("fs");
let options; let options;
const args = require("yargs") const args = require("yargs")
.env("DEMOCRATIC_CSI") .env("DEMOCRATIC_CSI_LIVENESS_PROBE")
.scriptName("democratic-csi") .scriptName("liveness-probe")
.usage("$0 [options]") .usage("$0 [options]")
.option("csi-version", { .option("csi-version", {
describe: "versin of the csi spec to load", describe: "versin of the csi spec to load",
choices: ["0.2.0", "0.3.0", "1.0.0", "1.1.0", "1.2.0"], choices: ["0.2.0", "0.3.0", "1.0.0", "1.1.0", "1.2.0", "1.3.0"],
}) })
.demandOption(["csi-version"], "csi-version is required") .demandOption(["csi-version"], "csi-version is required")
.option("csi-address", { .option("csi-address", {
@ -27,7 +27,7 @@ args.version = package.version;
//const grpc = require("grpc"); //const grpc = require("grpc");
const grpc = require("grpc-uds"); const grpc = require("grpc-uds");
const protoLoader = require("@grpc/proto-loader"); const protoLoader = require("@grpc/proto-loader");
const csiVersion = process.env.CSI_VERSION || "1.1.0"; const csiVersion = process.env.CSI_VERSION || args.csiVersion || "1.2.0";
const PROTO_PATH = __dirname + "/../csi_proto/csi-v" + csiVersion + ".proto"; const PROTO_PATH = __dirname + "/../csi_proto/csi-v" + csiVersion + ".proto";
// Suggested options for similarity to existing grpc.load behavior // Suggested options for similarity to existing grpc.load behavior

56
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "democratic-csi", "name": "democratic-csi",
"version": "1.0.0", "version": "1.1.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -18,11 +18,11 @@
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
}, },
"@babel/highlight": { "@babel/highlight": {
"version": "7.10.4", "version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.10.4", "@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0", "chalk": "^2.0.0",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
}, },
@ -567,11 +567,11 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
}, },
"eslint": { "eslint": {
"version": "7.18.0", "version": "7.20.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz",
"integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==", "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==",
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.3.0", "@eslint/eslintrc": "^0.3.0",
"ajv": "^6.10.0", "ajv": "^6.10.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
@ -583,7 +583,7 @@
"eslint-utils": "^2.1.0", "eslint-utils": "^2.1.0",
"eslint-visitor-keys": "^2.0.0", "eslint-visitor-keys": "^2.0.0",
"espree": "^7.3.1", "espree": "^7.3.1",
"esquery": "^1.2.0", "esquery": "^1.4.0",
"esutils": "^2.0.2", "esutils": "^2.0.2",
"file-entry-cache": "^6.0.0", "file-entry-cache": "^6.0.0",
"functional-red-black-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1",
@ -681,9 +681,9 @@
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
}, },
"esquery": { "esquery": {
"version": "1.3.1", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
"integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
"requires": { "requires": {
"estraverse": "^5.1.0" "estraverse": "^5.1.0"
}, },
@ -756,9 +756,9 @@
"integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg=="
}, },
"file-entry-cache": { "file-entry-cache": {
"version": "6.0.0", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
"integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"requires": { "requires": {
"flat-cache": "^3.0.4" "flat-cache": "^3.0.4"
} }
@ -1279,9 +1279,9 @@
} }
}, },
"handlebars": { "handlebars": {
"version": "4.7.6", "version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
"requires": { "requires": {
"minimist": "^1.2.5", "minimist": "^1.2.5",
"neo-async": "^2.6.0", "neo-async": "^2.6.0",
@ -1477,9 +1477,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.20", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"lodash.camelcase": { "lodash.camelcase": {
"version": "4.3.0", "version": "4.3.0",
@ -2052,9 +2052,9 @@
}, },
"dependencies": { "dependencies": {
"ajv": { "ajv": {
"version": "7.0.3", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.1.1.tgz",
"integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", "integrity": "sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==",
"requires": { "requires": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0", "json-schema-traverse": "^1.0.0",
@ -2120,9 +2120,9 @@
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
}, },
"uglify-js": { "uglify-js": {
"version": "3.10.3", "version": "3.12.8",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.3.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz",
"integrity": "sha512-Lh00i69Uf6G74mvYpHCI9KVVXLcHW/xu79YTvH7Mkc9zyKUeSPz0owW0dguj0Scavns3ZOh3wY63J0Zb97Za2g==", "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==",
"optional": true "optional": true
}, },
"uri-js": { "uri-js": {

View File

@ -1,6 +1,6 @@
{ {
"name": "democratic-csi", "name": "democratic-csi",
"version": "1.0.1", "version": "1.1.0",
"description": "kubernetes csi driver framework", "description": "kubernetes csi driver framework",
"main": "bin/democratic-csi", "main": "bin/democratic-csi",
"scripts": { "scripts": {
@ -20,12 +20,13 @@
"dependencies": { "dependencies": {
"@grpc/proto-loader": "^0.5.6", "@grpc/proto-loader": "^0.5.6",
"bunyan": "^1.8.15", "bunyan": "^1.8.15",
"eslint": "^7.18.0", "eslint": "^7.20.0",
"grpc-uds": "^0.1.6", "grpc-uds": "^0.1.6",
"handlebars": "^4.7.6", "handlebars": "^4.7.7",
"js-yaml": "^4.0.0", "js-yaml": "^4.0.0",
"lru-cache": "^6.0.0", "lru-cache": "^6.0.0",
"request": "^2.88.2", "request": "^2.88.2",
"semver": "^7.3.4",
"ssh2": "^0.8.9", "ssh2": "^0.8.9",
"uri-js": "^4.4.1", "uri-js": "^4.4.1",
"uuid": "^8.3.2", "uuid": "^8.3.2",

View File

@ -6,6 +6,7 @@ const { Zetabyte, ZfsSshProcessManager } = require("../../utils/zfs");
const Handlebars = require("handlebars"); const Handlebars = require("handlebars");
const uuidv4 = require("uuid").v4; const uuidv4 = require("uuid").v4;
const semver = require("semver");
// zfs common properties // zfs common properties
const MANAGED_PROPERTY_NAME = "democratic-csi:managed_resource"; const MANAGED_PROPERTY_NAME = "democratic-csi:managed_resource";
@ -81,6 +82,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
//"UNKNOWN", //"UNKNOWN",
"CREATE_DELETE_VOLUME", "CREATE_DELETE_VOLUME",
//"PUBLISH_UNPUBLISH_VOLUME", //"PUBLISH_UNPUBLISH_VOLUME",
//"LIST_VOLUMES_PUBLISHED_NODES",
"LIST_VOLUMES", "LIST_VOLUMES",
"GET_CAPACITY", "GET_CAPACITY",
"CREATE_DELETE_SNAPSHOT", "CREATE_DELETE_SNAPSHOT",
@ -88,6 +90,8 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
"CLONE_VOLUME", "CLONE_VOLUME",
//"PUBLISH_READONLY", //"PUBLISH_READONLY",
"EXPAND_VOLUME", "EXPAND_VOLUME",
//"VOLUME_CONDITION", // added in v1.3.0
//"GET_VOLUME", // added in v1.3.0
]; ];
} }
@ -100,7 +104,8 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
//"UNKNOWN", //"UNKNOWN",
"STAGE_UNSTAGE_VOLUME", "STAGE_UNSTAGE_VOLUME",
"GET_VOLUME_STATS", "GET_VOLUME_STATS",
//"EXPAND_VOLUME" //"EXPAND_VOLUME",
//"VOLUME_CONDITION",
]; ];
break; break;
case "volume": case "volume":
@ -109,6 +114,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
"STAGE_UNSTAGE_VOLUME", "STAGE_UNSTAGE_VOLUME",
"GET_VOLUME_STATS", "GET_VOLUME_STATS",
"EXPAND_VOLUME", "EXPAND_VOLUME",
//"VOLUME_CONDITION",
]; ];
break; break;
} }
@ -257,6 +263,108 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
return { valid, message }; return { valid, message };
} }
async getVolumeStatus(volume_id) {
const driver = this;
if (!!!semver.satisfies(driver.ctx.csiVersion, ">=1.2.0")) {
return;
}
let abnormal = false;
let message = "OK";
let volume_status = {};
//LIST_VOLUMES_PUBLISHED_NODES
if (
semver.satisfies(driver.ctx.csiVersion, ">=1.2.0") &&
driver.options.service.controller.capabilities.rpc.includes(
"LIST_VOLUMES_PUBLISHED_NODES"
)
) {
// TODO: let drivers fill this in
volume_status.published_node_ids = [];
}
//VOLUME_CONDITION
if (
semver.satisfies(driver.ctx.csiVersion, ">=1.3.0") &&
driver.options.service.controller.capabilities.rpc.includes(
"VOLUME_CONDITION"
)
) {
// TODO: let drivers fill ths in
volume_condition = { abnormal, message };
volume_status.volume_condition = volume_condition;
}
return volume_status;
}
async populateCsiVolumeFromData(row) {
const driver = this;
const zb = await this.getZetabyte();
const driverZfsResourceType = this.getDriverZfsResourceType();
let datasetName = this.getVolumeParentDatasetName();
// ignore rows were csi_name is empty
if (row[MANAGED_PROPERTY_NAME] != "true") {
return;
}
let volume_content_source;
let volume_context = JSON.parse(row[SHARE_VOLUME_CONTEXT_PROPERTY_NAME]);
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME]
)
) {
volume_context["provisioner_driver"] =
row[VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME];
}
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME]
)
) {
volume_context["provisioner_driver_instance_id"] =
row[VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME];
}
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME]
)
) {
volume_content_source = {};
switch (row[VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME]) {
case "snapshot":
volume_content_source.snapshot = {};
volume_content_source.snapshot.snapshot_id =
row[VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME];
break;
case "volume":
volume_content_source.volume = {};
volume_content_source.volume.volume_id =
row[VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME];
break;
}
}
let volume = {
// remove parent dataset info
volume_id: row["name"].replace(new RegExp("^" + datasetName + "/"), ""),
capacity_bytes:
driverZfsResourceType == "filesystem"
? row["refquota"]
: row["volsize"],
content_source: volume_content_source,
volume_context,
};
return volume;
}
/** /**
* Ensure sane options are used etc * Ensure sane options are used etc
* true = ready * true = ready
@ -1107,6 +1215,86 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
return { available_capacity: properties.available.value }; return { available_capacity: properties.available.value };
} }
/**
* Get a single volume
*
* @param {*} call
*/
async ControllerGetVolume(call) {
const driver = this;
const driverZfsResourceType = this.getDriverZfsResourceType();
const zb = await this.getZetabyte();
let datasetParentName = this.getVolumeParentDatasetName();
let response;
let name = call.request.volume_id;
if (!datasetParentName) {
throw new GrpcError(
grpc.status.FAILED_PRECONDITION,
`invalid configuration: missing datasetParentName`
);
}
if (!name) {
throw new GrpcError(
grpc.status.INVALID_ARGUMENT,
`volume_id is required`
);
}
const datasetName = datasetParentName + "/" + name;
let types = [];
switch (driverZfsResourceType) {
case "filesystem":
types = ["filesystem"];
break;
case "volume":
types = ["volume"];
break;
}
try {
response = await zb.zfs.list(
datasetName,
[
"name",
"mountpoint",
"refquota",
"avail",
"used",
VOLUME_CSI_NAME_PROPERTY_NAME,
VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME,
VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME,
"volsize",
MANAGED_PROPERTY_NAME,
SHARE_VOLUME_CONTEXT_PROPERTY_NAME,
SUCCESS_PROPERTY_NAME,
VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME,
VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME,
],
{ types, recurse: false }
);
} catch (err) {
if (err.toString().includes("dataset does not exist")) {
throw new GrpcError(grpc.status.NOT_FOUND, `volume_id is missing`);
}
throw err;
}
driver.ctx.logger.debug("list volumes result: %j", response);
let volume = await driver.populateCsiVolumeFromData(response.indexed[0]);
let status = await driver.getVolumeStatus(datasetName);
let res = { volume };
if (status) {
res.status = status;
}
return res;
}
/** /**
* *
* TODO: check capability to ensure not asking about block volumes * TODO: check capability to ensure not asking about block volumes
@ -1213,68 +1401,20 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
} }
entries = []; entries = [];
response.indexed.forEach((row) => { for (let row of response.indexed) {
// ignore rows were csi_name is empty // ignore rows were csi_name is empty
if (row[MANAGED_PROPERTY_NAME] != "true") { if (row[MANAGED_PROPERTY_NAME] != "true") {
return; return;
} }
let volume_content_source; let volume = await driver.populateCsiVolumeFromData(row);
let volume_context = JSON.parse(row[SHARE_VOLUME_CONTEXT_PROPERTY_NAME]); let status = await driver.getVolumeStatus(datasetName);
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME]
)
) {
volume_context["provisioner_driver"] =
row[VOLUME_CONTEXT_PROVISIONER_DRIVER_PROPERTY_NAME];
}
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME]
)
) {
volume_context["provisioner_driver_instance_id"] =
row[VOLUME_CONTEXT_PROVISIONER_INSTANCE_ID_PROPERTY_NAME];
}
if (
zb.helpers.isPropertyValueSet(
row[VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME]
)
) {
volume_content_source = {};
switch (row[VOLUME_CONTENT_SOURCE_TYPE_PROPERTY_NAME]) {
case "snapshot":
volume_content_source.snapshot = {};
volume_content_source.snapshot.snapshot_id =
row[VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME];
break;
case "volume":
volume_content_source.volume = {};
volume_content_source.volume.volume_id =
row[VOLUME_CONTENT_SOURCE_ID_PROPERTY_NAME];
break;
}
}
entries.push({ entries.push({
volume: { volume,
// remove parent dataset info status,
volume_id: row["name"].replace(
new RegExp("^" + datasetName + "/"),
""
),
capacity_bytes:
driverZfsResourceType == "filesystem"
? row["refquota"]
: row["volsize"],
content_source: volume_content_source,
volume_context,
},
}); });
}); }
if (max_entries && entries.length > max_entries) { if (max_entries && entries.length > max_entries) {
uuid = uuidv4(); uuid = uuidv4();
@ -1365,7 +1505,7 @@ class ControllerZfsSshBaseDriver extends CsiBaseDriver {
// should only send 1 of snapshot_id or source_volume_id, preferring the former if sent // should only send 1 of snapshot_id or source_volume_id, preferring the former if sent
if (snapshot_id) { if (snapshot_id) {
if (!zb.helpers.isZfsSnapshot(snapshot_id)) { if (!zb.helpers.isZfsSnapshot(snapshot_id)) {
return; continue;
} }
operativeFilesystem = volumeParentDatasetName + "/" + snapshot_id; operativeFilesystem = volumeParentDatasetName + "/" + snapshot_id;
operativeFilesystemType = 3; operativeFilesystemType = 3;

View File

@ -4,6 +4,7 @@ const { GrpcError, grpc } = require("../utils/grpc");
const { Mount } = require("../utils/mount"); const { Mount } = require("../utils/mount");
const { Filesystem } = require("../utils/filesystem"); const { Filesystem } = require("../utils/filesystem");
const { ISCSI } = require("../utils/iscsi"); const { ISCSI } = require("../utils/iscsi");
const semver = require("semver");
const sleep = require("../utils/general").sleep; const sleep = require("../utils/general").sleep;
/** /**
@ -867,6 +868,7 @@ class CsiBaseDriver {
} }
async NodeGetVolumeStats(call) { async NodeGetVolumeStats(call) {
const driver = this;
const mount = new Mount(); const mount = new Mount();
const filesystem = new Filesystem(); const filesystem = new Filesystem();
let result; let result;
@ -880,6 +882,19 @@ class CsiBaseDriver {
throw new GrpcError(grpc.status.INVALID_ARGUMENT, `missing volume_path`); throw new GrpcError(grpc.status.INVALID_ARGUMENT, `missing volume_path`);
} }
let res = {};
//VOLUME_CONDITION
if (
semver.satisfies(driver.ctx.csiVersion, ">=1.3.0") &&
options.service.node.capabilities.rpc.includes("VOLUME_CONDITION")
) {
// TODO: let drivers fill ths in
let abnormal = false;
let message = "OK";
res.volume_condition = { abnormal, message };
}
if ( if (
(await mount.isBindMountedBlockDevice(volume_path)) || (await mount.isBindMountedBlockDevice(volume_path)) ||
(await mount.isBindMountedBlockDevice(block_path)) (await mount.isBindMountedBlockDevice(block_path))
@ -895,33 +910,33 @@ class CsiBaseDriver {
case "mount": case "mount":
result = await mount.getMountDetails(device_path); result = await mount.getMountDetails(device_path);
return { res.usage = [
usage: [ {
{ available: result.avail,
available: result.avail, total: result.size,
total: result.size, used: result.used,
used: result.used, unit: "BYTES",
unit: "BYTES", },
}, ];
], break;
};
case "block": case "block":
result = await filesystem.getBlockDevice(device_path); result = await filesystem.getBlockDevice(device_path);
return { res.usage = [
usage: [ {
{ total: result.size,
total: result.size, unit: "BYTES",
unit: "BYTES", },
}, ];
], break;
};
default: default:
throw new GrpcError( throw new GrpcError(
grpc.status.INVALID_ARGUMENT, grpc.status.INVALID_ARGUMENT,
`unsupported/unknown access_type ${access_type}` `unsupported/unknown access_type ${access_type}`
); );
} }
return res;
} }
/** /**