From 5763ccf05c00230dbf87a4f0aee9d4f15ac7e9fa Mon Sep 17 00:00:00 2001 From: madhukirans Date: Thu, 24 Sep 2020 01:54:56 -0400 Subject: [PATCH 1/3] csi-unity 1.3 --- .gitignore | 1 - ...river for Dell EMC Unity Product Guide.pdf | Bin 166632 -> 222469 bytes ...river for Dell EMC Unity Release Notes.pdf | Bin 66369 -> 83430 bytes Dockerfile | 52 +- Makefile | 12 +- README.md | 655 +++++++------ build.sh | 70 ++ dell-csi-helm-installer/README.md | 157 ++++ ....storage.k8s.io_volumesnapshotclasses.yaml | 85 ++ ...storage.k8s.io_volumesnapshotcontents.yaml | 233 +++++ ...apshot.storage.k8s.io_volumesnapshots.yaml | 188 ++++ dell-csi-helm-installer/common.sh | 114 +++ dell-csi-helm-installer/csi-install.sh | 391 ++++++++ dell-csi-helm-installer/csi-uninstall.sh | 130 +++ dell-csi-helm-installer/verify.sh | 605 ++++++++++++ docker.mk | 36 - env.sh | 7 +- go.mod | 18 +- go.sum | 287 +++++- helm/README.md | 11 - helm/common.bash | 28 - helm/csi-unity/Chart.yaml | 4 +- helm/csi-unity/driver-image.yaml | 4 + helm/csi-unity/k8s-1.16-values.yaml | 7 +- ...-1.14-values.yaml => k8s-1.17-values.yaml} | 12 +- helm/csi-unity/k8s-1.18-values.yaml | 22 + helm/csi-unity/k8s-1.19-values.yaml | 22 + helm/csi-unity/templates/controller.yaml | 18 + helm/csi-unity/templates/node.yaml | 5 +- helm/csi-unity/templates/storageclass.yaml | 3 + .../templates/volumesnapshotclass.yaml | 9 + helm/csi-unity/values.yaml | 6 +- helm/install.unity | 58 -- ...ot-crd.yaml => snapshot-crd-v1alpha1.yaml} | 0 helm/uninstall.unity | 24 - helm/upgrade.unity | 54 -- helm/verify.kubernetes | 54 -- licenses/LICENSE | 201 ++++ service/controller.go | 884 ++++++++++++++---- service/controller_test.go | 28 +- service/identity.go | 21 +- service/mount.go | 37 +- service/node.go | 196 +++- service/service.go | 37 +- service/utils/emcutils.go | 45 +- service/validator.go | 41 + .../features/integration.feature | 211 +++++ .../integration-test/integration_main_test.go | 27 + test/integration-test/integration_test.go | 5 +- test/unit-test/features/unit.feature | 750 +++++++++++++++ test/unit-test/unit_main_test.go | 34 +- test/unit-test/unit_test.go | 241 ++--- 52 files changed, 5165 insertions(+), 975 deletions(-) create mode 100644 build.sh create mode 100644 dell-csi-helm-installer/README.md create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml create mode 100644 dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml create mode 100644 dell-csi-helm-installer/common.sh create mode 100755 dell-csi-helm-installer/csi-install.sh create mode 100755 dell-csi-helm-installer/csi-uninstall.sh create mode 100755 dell-csi-helm-installer/verify.sh delete mode 100644 docker.mk delete mode 100644 helm/README.md delete mode 100644 helm/common.bash create mode 100644 helm/csi-unity/driver-image.yaml rename helm/csi-unity/{k8s-1.14-values.yaml => k8s-1.17-values.yaml} (62%) create mode 100644 helm/csi-unity/k8s-1.18-values.yaml create mode 100644 helm/csi-unity/k8s-1.19-values.yaml delete mode 100755 helm/install.unity rename helm/{snapshot-crd.yaml => snapshot-crd-v1alpha1.yaml} (100%) delete mode 100755 helm/uninstall.unity delete mode 100755 helm/upgrade.unity delete mode 100755 helm/verify.kubernetes create mode 100644 licenses/LICENSE create mode 100644 test/integration-test/features/integration.feature create mode 100644 test/unit-test/features/unit.feature diff --git a/.gitignore b/.gitignore index 4429697..64210fc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ builds/ *.exe vendor/ bin/ -csi-unity semver.mk go.sum ./csi-unity diff --git a/CSI Driver for Dell EMC Unity Product Guide.pdf b/CSI Driver for Dell EMC Unity Product Guide.pdf index be46facf650c47085326608d5e69d7d76801eed6..3b01261fec89266237fe6658ffb29d5479914d84 100644 GIT binary patch literal 222469 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 |(^rxlQ6^%*`>0A7(%|S$`OVN;pu}GU?5yL

|@m4faOW4&Z1Dle|o3E>bFB|xOf zJ?iE~>iP|5fWuxF;Fbzf3S7*?C^F~o5I>CiP4P4+5$O{&&NMMuMtLm;gHFfJp%6hR z5nbR=qEb6@fxp8OP78j;H$C%*E+oK2=}&(kNb6q)X%hK^wL|HK@_JG)s7dn)U1!FQj&AI6 z2JSfY@IP{VoxE!Q#roJvGwqT#_nad2TO8PRChV1ePlCT)A_bZ%C zDEBpuGY{bRbev+)YS^vafrS7%8L|`ANq`OqUtXU5S3ZM?lOI5ggp&nkpcKv?JkT*W zT}JOJUizip2%>HdpC`3zU}6ajVCx%j6uN6$>@GZa$lTX^-pX6htTpY$Z8+X3y#4!v z)gR7e^?XI}4?yZS;PDig=ug1&dS-7~|KbZX;zXNX%w|e*s&lP-@ZMKo>3=+%Amk6% zeh-4x0F^7UlZ^a8D9(pydOuz^si?~g6N)+l3*UIPZoGpOZ<%WPbWU~$80%- z#*pc|^juf6j(rW2<^eO!`8inb?};e`HOQ7Oey~-&`n7t9;O_*nj~)gP1=&A<4K&FK zawi`K@EcBmdy=46G4Pf@3?K|S*ai+TRvN(+8>re5!Z1t7KLt*}+7Y6@pCFtD4se+h zq+y+)mop4sl?!C`7(vz4Kno|3{SZOFNQj-=A0+GNVi#dI0M4L2t%HqyeYz*k3dF%5xIh(L=Hck`Vm0BJ%A$tk+=~^b`3ng zJ`TWwMR}l&r?a*w{%xRt`F8D*Ispkw9*4d~!n`#p{t2ufHr1~5ha+KcJww4xsx^+; z^WH1B{zBVq(BvPtfhY_9u`U%+yx4J|wke8UTiLaJw|OJ8%0DwVwW~y$x9tEndf>EvC4jE01pu5r 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�t14|g71WM+Gn)@g>4LL$57M-PdNu8j= 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 diff --git a/CSI Driver for Dell EMC Unity Release Notes.pdf b/CSI Driver for Dell EMC Unity Release Notes.pdf index 4133037bcb0c2cbe2f6b378f2ce8b20e6d01bfd0..1df0b5323bcbb452eea72e47a7f4709263dde9ea 100644 GIT binary patch literal 83430 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 literal 66369 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%0Do3heis+=b`3A=tT}xcPr+b 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 X=<<$%AaHVUva=#kQht#WMMn4^;P>Zx diff --git a/Dockerfile b/Dockerfile index 9f393cd..e1ebac3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,50 @@ -# Dockerfile to build PowerStore CSI Driver -FROM centos:7.6.1810 +# Stage to build the driver +FROM golang:1.13 as builder +RUN mkdir -p /go/src +COPY csi-unity/ /go/src/csi-unity +#//@TODO remove gofsutil before release +COPY gounity /go/src/gounity +WORKDIR /go/src/csi-unity +RUN mkdir -p bin +RUN go generate +RUN GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o bin/csi-unity +# Print the version +RUN go run core/semver/semver.go -f mk + +# Dockerfile to build Unity CSI Driver +FROM registry.access.redhat.com/ubi7/ubi-minimal:7.8-328 as driver # dependencies, following by cleaning the cache -RUN yum install -y e2fsprogs xfsprogs which nfs-utils device-mapper-multipath \ +RUN microdnf install -y --enablerepo=rhel-7-server-rpms e2fsprogs xfsprogs nfs-utils device-mapper-multipath \ && \ - yum clean all \ + microdnf clean all \ && \ rm -rf /var/cache/run +COPY --from=builder /go/src/csi-unity/bin/csi-unity / +COPY csi-unity/scripts/run.sh / +RUN chmod 777 /run.sh +ENTRYPOINT ["/run.sh"] -# validate some cli utilities are found -RUN which mkfs.ext4 -RUN which mkfs.xfs +# Stage to check for critical and high CVE issues via Trivy (https://github.com/aquasecurity/trivy) +# will break image build if CRITICAL issues found +# will print out all HIGH issues found +FROM driver as trivy-ubi7m +RUN microdnf install -y tar -COPY "bin/csi-unity" / -COPY "scripts/run.sh" / +FROM trivy-ubi7m as trivy +RUN curl https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh +RUN trivy fs -s CRITICAL --exit-code 1 / && \ + trivy fs -s HIGH / && \ + trivy image --reset && \ + rm ./bin/trivy -RUN chmod 777 /run.sh +# final stage +FROM driver as final -ENTRYPOINT ["/run.sh"] +LABEL vendor="Dell Inc." \ + name="csi-unity" \ + summary="CSI Driver for Dell EMC Unity" \ + description="CSI Driver for provisioning persistent storage from Dell EMC Unity" \ + version="1.3.0" \ + license="Apache-2.0" +COPY csi-unity/licenses /licenses \ No newline at end of file diff --git a/Makefile b/Makefile index 9a5e67a..32913a4 100644 --- a/Makefile +++ b/Makefile @@ -30,18 +30,16 @@ unit-test: # Docker-related tasks # # Generates the docker container (but does not push) -docker-build: go-build - cd core && go generate - go run core/semver/semver.go -f mk >semver.mk - make -f docker.mk docker-build +podman-build: go-build + sh build.sh -docker-push: - make -f docker.mk docker-push +podman-push: go-build + sh build.sh -p version: go generate go run core/semver/semver.go -f mk >semver.mk - make -f docker.mk version + sh build.sh -h .PHONY: clean clean: diff --git a/README.md b/README.md index e819f2c..e8bb31d 100644 --- a/README.md +++ b/README.md @@ -1,48 +1,60 @@ # Unity CSI -This repo contains [Container Storage Interface(CSI)] -() Unity CSI driver for DellEMC. +[![Go Report Card](https://goreportcard.com/badge/github.com/dell/csi-unity)](https://goreportcard.com/report/github.com/dell/csi-unity) +[![License](https://img.shields.io/github/license/dell/csi-unity)](https://github.com/dell/csi-unity/blob/master/LICENSE) +[![Docker](https://img.shields.io/docker/pulls/dellemc/csi-unity.svg?logo=docker)](https://hub.docker.com/r/dellemc/csi-unity) +[![Last Release](https://img.shields.io/github/v/release/dell/csi-unity?label=latest&style=flat-square)](https://github.com/dell/csi-unity/releases) + +This repo contains [Container Storage Interface(CSI)]() Unity CSI driver for DellEMC. ## Overview -Unity CSI plugins implement an interface between CSI enabled Container Orchestrator(CO) and Unity Storage Array. It allows dynamically provisioning Unity volumes and attaching them to workloads. +Unity CSI plugins implement an interface between CSI enabled Container Orchestrator(CO) and Unity Storage Array. It allows static and dynamic provisioning of Unity volumes and attaching them to workloads. + +## Support + +The CSI Driver for Dell EMC Unity image, which is the built driver code, is available on Dockerhub and is officially supported by Dell EMC. +The source code for CSI Driver for Dell EMC Unity available on Github is unsupported and provided solely under the terms of the license attached to the source code. For clarity, Dell EMC does not provide support for any source code modifications. +For any CSI driver issues, questions or feedback, join the [Dell EMC Container community]() ## Introduction The CSI Driver For Dell EMC Unity conforms to CSI spec 1.1 - * Support for Kubernetes 1.14 and 1.16 + * Support for Kubernetes v1.17, v1.18 and v1.19 * Will add support for other orchestrators over time - * The CSI specification is documented here: https://github.com/container-storage-interface/spec. The driver uses CSI v1.1. + * The CSI specification is documented here: https://github.com/container-storage-interface/spec/tree/release-1.1. The driver uses CSI v1.1.` ## CSI Driver For Dell EMC Unity Capabilities | Capability | Supported | Not supported | |------------|-----------| --------------| -|Provisioning | Persistent volumes creation, deletion, mounting, unmounting, listing | Volume expand | +|Provisioning | Persistent volumes creation, deletion, mounting, unmounting, expansion | | |Export, Mount | Mount volume as file system | Raw volumes, Topology| -|Data protection | Creation of snapshots, Create volume from snapshots(FC/iSCSI) | Cloning volume, Create volume from snapshots(NFS) | +|Data protection | Creation of snapshots, Create volume from snapshots, Volume Cloning | | |Types of volumes | Static, Dynamic| | |Access mode | RWO(FC/iSCSI), RWO/RWX/ROX(NFS) | RWX/ROX(FC/iSCSI)| -|Kubernetes | v1.14, v1.16 | V1.13 or previous versions| -|Installer | Helm v3.x,v2.x | Operator | -|OpenShift | v4.3 (Helm installation only) | v4.2 | -|OS | RHEL 7.6, RHEL 7.7, CentOS 7.6, CentOS 7.7 | Ubuntu, other Linux variants| +|Kubernetes | v1.17, v1.18, v1.19 | V1.16 or previous versions| +|Docker EE | v3.1 | Other versions| +|Installer | Helm v3.x, Operator | | +|OpenShift | v4.3 (except snapshot), v4.4 | Other versions | +|OS | RHEL 7.6, RHEL 7.7, RHEL 7.8, CentOS 7.6, CentOS 7.7, CentOS 7.8 | Ubuntu, other Linux variants| |Unity | OE 5.0.0, 5.0.1, 5.0.2, 5.0.3 | Previous versions and Later versions| |Protocol | FC, iSCSI, NFS | | ## Installation overview -The Helm chart installs CSI Driver for Unity using a shell script (helm/install.unity). This script installs the CSI driver container image along with the required Kubernetes sidecar containers. +Installation in a Kubernetes cluster should be done using the scripts within the `dell-csi-helm-installer` directory. -** Note: Linux user should have root privileges to install this CSI Driver.** +For more information, consult the [README.md](dell-csi-helm-installer/README.md) -The controller section of the Helm chart installs the following components in a Stateful Set in the namespace unity: +The controller section of the Helm chart installs the following components in a Stateful Set: * CSI Driver for Unity * Kubernetes Provisioner, which provisions the provisioning volumes * Kubernetes Attacher, which attaches the volumes to the containers * Kubernetes Snapshotter, which provides snapshot support +* Kubernetes Resizer, which provides volume expansion support -The node section of the Helm chart installs the following component in a Daemon Set in the namespace unity: +The node section of the Helm chart installs the following component in a Daemon Set: * CSI Driver for Unity * Kubernetes Registrar, which handles the driver registration @@ -54,54 +66,11 @@ Before you install CSI Driver for Unity, verify the requirements that are mentio #### Requirements * Install Kubernetes -* Enable the Kubernetes feature gates * Configure Docker service -* Install Helm v2 with Tiller with a service account or Helm v3 -* Deploy Unity using Helm +* Install Helm v3 +* To use FC protocol, host must be zoned with Unity array * To use iSCSI and NFS protocol, iSCSI initiator and NFS utility packages need to be installed -## Enable Kubernetes feature gates - -The Kubernetes feature gates must be enabled before installing CSI Driver for Unity. - -#### About Enabling Kubernetes feature gates - -The Feature Gates section of Kubernetes home page lists the Kubernetes feature gates. The following Kubernetes feature gates must be enabled: - -* VolumeSnapshotDataSource - -### Procedure - - 1. On each master and node of Kubernetes, edit /var/lib/kubelet/config.yaml and append the following lines at the end to set feature-gate settings for the kubelets: - */var/lib/kubelet/config.yaml* - - ``` - VolumeSnapshotDataSource: true - ``` - -2. On the master node, set the feature gate settings of the kube-apiserver.yaml, kube-controllermanager.yaml and kube-scheduler.yaml file as follows: - - */etc/kubernetes/manifests/kube-apiserver.yaml - /etc/kubernetes/manifests/kube-controller-manager.yaml - /etc/kubernetes/manifests/kube-scheduler.yaml* - - ``` - - --feature-gates=VolumeSnapshotDataSource=true - ``` - -3. On each node (including master), edit the variable **KUBELET_KUBECONFIG_ARGS** of /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf file as follows: - - ``` - Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --feature-gates=VolumeSnapshotDataSource=true" - ``` - -4. Restart the kublet on all nodes. - - ``` - systemctl daemon-reload - systemctl restart kubelet - ``` - ## Configure Docker service The mount propagation in Docker must be configured on all Kubernetes nodes before installing CSI Driver for Unity. @@ -129,7 +98,7 @@ Install CSI Driver for Unity using this procedure. *Before you begin* * You must have the downloaded files, including the Helm chart from the source [git repository](https://github.com/dell/csi-unity), ready for this procedure. - * In the top-level helm directory, there should be two shell scripts, *install.unity* and *uninstall.unity*. These scripts handle some of the pre and post operations that cannot be performed in the helm chart, such as creating Custom Resource Definitions (CRDs), if needed. + * In the top-level dell-csi-helm-installer directory, there should be two scripts, *csi-install.sh* and *csi-uninstall.sh*. These scripts handle some of the pre and post operations that cannot be performed in the helm chart, such as creating Custom Resource Definitions (CRDs), if needed. * Make sure "unity" namespace exists in kubernetes cluster. Use `kubectl create namespace unity` command to create the namespace, if the namespace is not present. @@ -137,7 +106,7 @@ Procedure 1. Collect information from the Unity Systems like Unique ArrayId, IP address, username and password. Make a note of the value for these parameters as they must be entered in the secret.json and myvalues.yaml file. -2. Copy the csi-unity/values.yaml into a file in the same directory as the install.unity named myvalues.yaml, to customize settings for installation. +2. Copy the csi-unity/values.yaml into a file named myvalues.yaml in the same directory of csi-install.sh, to customize settings for installation. 3. Edit myvalues.yaml to set the following parameters for your installation: @@ -145,7 +114,7 @@ Procedure | Parameter | Description | Required | Default | | --------- | ----------- | -------- |-------- | - | certSecretCount | Represents number of certificate secrets, which user is going to create for ssl authentication. (unity-cert-0..unity-cert-n). Value should be between 1 and 10 | false | 1 | + | certSecretCount | Represents number of certificate secrets, which user is going to create for ssl authentication. (unity-cert-0..unity-cert-n). Minimum value should be 1 | false | 1 | | syncNodeInfoInterval | Time interval to add node info to array. Default 15 minutes. Minimum value should be 1 minute | false | 15 | | volumeNamePrefix | String to prepend to any volumes created by the driver | false | csivol | | snapNamePrefix | String to prepend to any snapshot created by the driver | false | csi-snap | @@ -167,7 +136,7 @@ Procedure | ***Snapshot Class parameters*** | Following parameters are not present in values.yaml | | storageArrayList[i] .snapshotClass.retentionDuration | TO set snapshot retention duration. Format:"1:23:52:50" (number of days:hours:minutes:sec)| false | "" | - Note: User should provide all boolean values with double quotes. This applicable only for myvalues.yaml. Ex: "true"/"false" + **Note**: User should provide all boolean values with double quotes. This applicable only for myvalues.yaml. Ex: "true"/"false" Example *myvalues.yaml* @@ -203,7 +172,9 @@ Procedure nasServer: "nasserver_2" ``` -4. Prepare the secret.json for driver configuration. +4. Create an empty secret by navigating to helm folder that contains emptysecret.yaml file and running the kubectl create -f emptysecret.yaml command. + +5. Prepare the secret.json for driver configuration. The following table lists driver configuration parameters for multiple storage arrays. | Parameter | Description | Required | Default | @@ -243,51 +214,88 @@ Procedure `kubectl create secret generic unity-creds -n unity --from-file=config=secret.json -o yaml --dry-run | kubectl replace -f -` - Note: The user needs to validate the JSON syntax and array related key/values while replacing the unity-creds secret. + **Note**: The user needs to validate the JSON syntax and array related key/values while replacing the unity-creds secret. The driver will continue to use previous values in case of an error found in the JSON file. -4. Run the `sh install.unity` command to proceed with the installation. + **Note**: "isDefaultArray" parameter in values.yaml and secret.json should match each other. + +6. Setup for snapshots + + The Kubernetes Volume Snapshot feature is now beta in Kubernetes v1.17. + + * The following section summarizes the changes in the **[beta]()** release. + + In order to use the Kubernetes Volume Snapshot feature, you must ensure the following components have been deployed on your Kubernetes cluster. + + * [Install Snapshot Beta CRDs using the following command]() + ```shell script + kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-2.0/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml + kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-2.0/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml + kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/release-2.0/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml + + * [Volume snapshot controller]() + ```shell script + kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/rbac-snapshot-controller.yaml + kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/master/deploy/kubernetes/snapshot-controller/setup-snapshot-controller.yaml + ``` + After executing these commands, a snapshot-controller pod should be up and running. + +7. Run the `./csi-install.sh --namespace unity --values ./myvalues.yaml` command to proceed with the installation. A successful installation should emit messages that look similar to the following samples: ``` - sh install.unity - Kubernetes version v1.16.8 - Kubernetes master nodes: 10.*.*.* - Kubernetes minion nodes: - Verifying the feature gates. - Installing using helm version 3 - NAME: unity - LAST DEPLOYED: Thu May 14 05:05:42 2020 - NAMESPACE: unity - STATUS: deployed - REVISION: 1 - TEST SUITE: None - Thu May 14 05:05:53 EDT 2020 - running 2 / 2 - NAME READY STATUS RESTARTS AGE - unity-controller-0 4/4 Running 0 11s - unity-node-mkbxc 2/2 Running 0 11s - CSIDrivers: - NAME CREATED AT - unity 2020-05-14T09:05:42Z - CSINodes: - NAME CREATED AT - 2020-04-16T20:59:16Z - StorageClasses: - NAME PROVISIONER AGE - unity (default) csi-unity.dellemc.com 11s - unity-iscsi csi-unity.dellemc.com 11s - unity-nfs csi-unity.dellemc.com 11s - unity--fc csi-unity.dellemc.com 11s - unity--iscsi csi-unity.dellemc.com 11s - unity--nfs csi-unity.dellemc.com 11s + ------------------------------------------------------ + > Installing CSI Driver: csi-unity on 1.18 + ------------------------------------------------------ + ------------------------------------------------------ + > Checking to see if CSI Driver is already installed + ------------------------------------------------------ + ------------------------------------------------------ + > Verifying Kubernetes and driver configuration + ------------------------------------------------------ + |- Kubernetes Version: 1.18 + | + |- Driver: csi-unity + | + |- Verifying Kubernetes versions + | + |--> Verifying minimum Kubernetes version Success + | + |--> Verifying maximum Kubernetes version Success + | + |- Verifying that required namespaces have been created Success + | + |- Verifying that required secrets have been created Success + | + |- Verifying that required secrets have been created Success + | + |- Verifying snapshot support + | + |--> Verifying that beta snapshot CRDs are available Success + | + |--> Verifying that beta snapshot controller is available Success + | + |- Verifying helm version Success + + ------------------------------------------------------ + > Verification Complete + ------------------------------------------------------ + | + |- Installing Driver Success + | + |--> Waiting for statefulset unity-controller to be ready Success + | + |--> Waiting for daemonset unity-node to be ready Success + ------------------------------------------------------ + > Operation complete + ------------------------------------------------------ ``` Results - At the end of the script, the kubectl get pods -n unity is called to GET the status of the pods and you will see the following: - * unity-controller-0 with 4/4 containers ready, and status displayed as Running. + At the end of the script statefulset unity-controller and daemonset unity-node will be ready, execute command **kubectl get pods -n unity** to get the status of the pods and you will see the following: + * unity-controller-0 with 5/5 containers ready, and status displayed as Running. * Agent pods with 2/2 containers and the status displayed as Running. - Finally, the script lists the created storageclasses such as, "unity". Additional storage classes can be created for different combinations of file system types and Unity storage pools. The script also creates volumesnapshotclass "unity-snapclass". + Finally, the script creates storageclasses such as, "unity". Additional storage classes can be created for different combinations of file system types and Unity storage pools. The script also creates volumesnapshotclass "unity-snapclass". ## Certificate validation for Unisphere REST API calls @@ -320,92 +328,41 @@ If the Unisphere certificate is self-signed or if you are using an embedded Unis `kubectl create secret generic unity-certs-0 -n unity --from-file=cert-0=ca_cert_0.pem -o yaml --dry-run | kubectl replace -f -` 3. Repeat step-1 & 2 to create multiple cert secrets with incremental index (ex: unity-certs-1, unity-certs-2, etc) -Note: User can add multiple certificates in the same secret. The certificate file should not exceed more than 1Mb due to kubernetes secret size limitation. +**Note**: "unity" is the namespace for helm based installation but namespace can be user defined in operator based installation. + +**Note**: User can add multiple certificates in the same secret. The certificate file should not exceed more than 1Mb due to kubernetes secret size limitation. -Note: Whenever certSecretCount parameter changes in myvalues.yaml user needs to uninstall and install the driver. +**Note**: Whenever certSecretCount parameter changes in myvalues.yaml user needs to uninstall and install the driver. ## Upgrade CSI Driver for Unity Preparing myvalues.yaml is the same as explained above. -**Note** Supported upgrade path is from CSI Driver for Dell EMC Unity v1.1.0.1 to CSI Driver for Dell EMC Unity v1.2. If user is in v1.0 or v1.1, please upgrade to v1.1.0.1 before upgrading to v1.2 to avoid problems. +To upgrade the driver from csi-unity v1.2.1 in k8s 1.16 to csi-unity 1.3 in k8s 1.17: +1. Remove all volume snapshots, volume snapshot content and volume snapshot class objects. +2. Upgrade the Kubernetes version to 1.17 first before upgrading CSI driver. +3. Uninstall existing driver. +4. Uninstall alpha snapshot CRDs. +5. Verify all pre-reqs to install csi-unity v1.3 are fulfilled. +6. Install the driver using installation steps from [here](#install-csi-driver-for-unity) -Delete the unity-creds secret and recreate again using secret.json as explained above. +**Note**: User has to re-create existing custom-storage classes (if any) according to latest (v1.3) format. - -Execute the following command to not to delete the unity-creds secret by helm - -```kubectl annotate secret unity-creds -n unity "helm.sh/resource-policy"=keep``` - -Make sure unity-certs-* secrets are created properly before upgrading the driver. - -Run the `sh upgrade.unity` command to proceed with the upgrading process. - -**Note**: Upgrading CSI Unity driver is possible within the same version of Helm. (Ex: Helm V2 to Helm V2) - -**Note**: Sometimes user might get a warning saying "updates to parameters are forbidden" when we try to upgrade from previous versions. Delete the storage classes and upgrade the driver. - -A successful upgrade should emit messages that look similar to the following samples: - - ``` - $ ./upgrade.unity - Kubernetes version v1.16.8 - Kubernetes master nodes: 10.*.*.* - Kubernetes minion nodes: - Verifying the feature gates. - node-1's password: - lifecycle present :2 - Removing lifecycle hooks from daemonset - daemonset.extensions/unity-node patched - daemonset.extensions/unity-node patched - daemonset.extensions/unity-node patched - warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely. - pod "unity-node-t1j5h" force deleted - Thu May 14 05:05:53 EDT 2020 - running 2 / 2 - NAME READY STATUS RESTARTS AGE - unity-controller-0 4/4 Running 0 12s - unity-node-n14gj 2/2 Running 0 12s - Upgrading using helm version 3 - Release "unity" has been upgraded. Happy Helming! - NAME: unity - LAST DEPLOYED: Thu May 14 05:05:53 2020 - NAMESPACE: unity - STATUS: deployed - REVISION: 2 - TEST SUITE: None - Thu May 14 05:06:02 EDT 2020 - running 2 / 2 - NAME READY STATUS RESTARTS AGE - unity-controller-0 4/4 Running 0 11s - unity-node-rn6px 2/2 Running 0 11s - CSIDrivers: - NAME CREATED AT - unity 2020-04-23T09:25:01Z - CSINodes: - NAME CREATED AT - 2020-04-16T20:59:16Z - StorageClasses: - NAME PROVISIONER AGE - unity (default) csi-unity.dellemc.com 11s - unity-iscsi csi-unity.dellemc.com 11s - unity-nfs csi-unity.dellemc.com 11s - unity--fc csi-unity.dellemc.com 11s - unity--iscsi csi-unity.dellemc.com 11s - unity--nfs csi-unity.dellemc.com 11s - ``` - - User has to re-create existing custom-storage classes (if any) according to latest (v1.2) format. - -## Migrate from Helm 2 to Helm 3 -1. Get the latest code from github.com/dell/csi-unity by executing the following command. - `git clone -b v1.1.0.1 https://github.com/dell/csi-unity.git` -2. Uninstall the CSI Driver for Dell EMC Unity v1.0 or v1.1 using the uninstall.unity script under csi-unity/helm using Helm 2. -3. Go to https://helm.sh/docs/topics/v2_v3_migration/ and follow the instructions to migrate from Helm 2 to Helm 3. -4. Once Helm 3 is ready, install the CSI Driver for Dell EMC Unity v1.1.0.1 using install.unity script under csi-unity/helm. -5. List the pods with the following command (to verify the status) - - `kubectl get pods -n unity` +## Building the driver image (UBI) +**NOTE** : Only RHEL host can be used to build the driver image. +1. Make sure podman is installed in node. +2. Add the fully-qualified name of the image repository to the [registries.insecure] + section of the /etc/containers/registries.conf file. For example: + ``` + [registries.insecure] + registries = ['myregistry.example.com'] + ``` +2. Inside csi-unity directory, execute this command to build the image and this image can be used locally:\ + `make podman-build` +3. Tag the image generated to the desired repository with command:\ + `podman tag IMAGE_NAME:IMAGE_TAG IMAGE_REPO/IMAGE_REPO_NAMESPACE/IMAGE_NAME:IMAGE_TAG` +4. To push the image to the repository, execute command:\ + `podman push IMAGE_REPO/IMAGE_REPO_NAMESPACE/IMAGE_NAME:IMAGE_TAG` ## Test deploying a simple pod with Unity storage Test the deployment workflow of a simple pod on Unity storage. @@ -481,21 +438,21 @@ Test the deployment workflow of a simple pod on Unity storage. **Note**: Verify unity system for volume to be attached to the Host where the nginx container is running 4. **Create Snapshot** - - The following procedure will create a snapshot of the volume in the container using VolumeSnapshot objects defined in snap.yaml. The following are the contents of snap.yaml. + The following procedure will create a snapshot of the volume in the container using VolumeSnapshot objects defined in snap.yaml. + The following are the contents of snap.yaml. *snap.yaml* ``` - apiVersion: snapshot.storage.k8s.io/v1alpha1 + apiVersion: snapshot.storage.k8s.io/v1beta1 kind: VolumeSnapshot metadata: - name: testvolclaim1-snap1 + name: testvolclaim1-snap1 + namespace: default spec: - snapshotClassName: unity-snapclass - source: - name: testvolclaim1 - kind: PersistentVolumeClaim + volumeSnapshotClassName: unity-snapclass + source: + persistentVolumeClaimName: testvolclaim1 ``` Execute the following command to create snapshot @@ -524,6 +481,7 @@ Test the deployment workflow of a simple pod on Unity storage. Delete the Nginx application to unattach the volume from host `kubectl delete -f nginx.yaml` + 7. **To delete the volume** ``` @@ -531,7 +489,89 @@ Test the deployment workflow of a simple pod on Unity storage. kubectl delete pvc testvolclaim1 kubectl get pvc ``` -## Static volume creation + +8. **Volume Expansion** + + To expand a volume, execute the following command to edit the pvc: + ``` + kubectl edit pvc pvc-name + ``` + Then, edit the "storage" field in spec section with required new size: + ``` + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi #This field is updated from 5Gi to 10Gi which is required new size + ``` + **Note**: Make sure the storage class used to create the pvc have allowVolumeExpansion field set to true. The new size cannot be less than the existing size of pvc. + +9. **Create Volume Clone** + + Create a file (`clonepvc.yaml`) with the following content. + + ``` + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: clone-pvc + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + dataSource: + kind: PersistentVolumeClaim + name: source-pvc + storageClassName: unity + ``` + + Execute the following command to create volume clone + ``` + kubectl create -f $PWD/clonepvc.yaml + ``` + **Note**: Size of clone pvc must be equal to size of source pvc. + + **Note**: For NFS protocol, user cannot expand cloned pvc. + + **Note**: For NFS protocol, deletion of source pvc is not permitted if cloned pvc exists. + +10. **Create Volume From Snapshot** + + Create a file (`pvcfromsnap.yaml`) with the following content. + + ``` + apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: pvcfromsnap + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + dataSource: + kind: VolumeSnapshot + name: source-snapshot + apiGroup: snapshot.storage.k8s.io + storageClassName: unity + ``` + + Execute the following command to create volume clone + ``` + kubectl create -f $PWD/pvcfromsnap.yaml + ``` + **Note**: Size of created pvc from snapshot must be equal to size of source snapshot. + + **Note**: For NFS protocol, pvc created from snapshot can not be expanded. + + **Note**: For NFS protocol, deletion of source pvc is not permitted if created pvc from snapshot exists. + +## Static volume creation (Volume ingestion) + Static provisioning is a feature that is native to Kubernetes and that allows cluster administrators to make existing storage devices available to a cluster. As a cluster administrator, you must know the details of the storage device, its supported configurations, and mount options. @@ -545,6 +585,8 @@ apiVersion: v1 kind: PersistentVolume metadata: name: static-pv + annotations: + pv.kubernetes.io/provisioned-by: csi-unity.dellemc.com spec: accessModes: - ReadWriteOnce @@ -553,6 +595,7 @@ spec: csi: driver: csi-unity.dellemc.com volumeHandle: csivol-vol-name-FC-apm001234567-sv_12 + fsType: xfs persistentVolumeReclaimPolicy: Delete claimRef: namespace: default @@ -565,7 +608,7 @@ spec: *\-\-\-\* * volume-name: Name of the volume. Can have any number of "-" -* Possible values for "Protocol" are "FC", "ISCSI" and "NFS" +* Possible values for "Protocol" are "FC", "iSCSI" and "NFS" * arrayid: arrayid defined in lower case * volume id: Represents the the LUN cli-id or Filesystem ID (not the resource-id incase of filesystem) @@ -581,6 +624,7 @@ spec: resources: requests: storage: 5Gi + storageClassName: unity ``` 4. Create Pod @@ -606,22 +650,86 @@ spec: claimName: myclaim ``` +## Snapshot ingestion +Snapshot ingestion is a feature that allows cluster administrators to make existing snapshot on array, created by user available to a cluster. + +To make existing snapshot available to a cluster user, user must manually create or use existing snapshot in Unisphere for PV. + +1. Create a snapshot or identify existing snapshot using Unisphere + +2. Create a VolumeSnapshotContent explained below +```yaml +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshotContent +metadata: + name: manual-snapshot-content +spec: + deletionPolicy: Delete + driver: csi-unity.dellemc.com + volumeSnapshotClassName: unity-snapclass + source: + snapshotHandle: snap1-FC-apm00175000000-38654806278 + volumeSnapshotRef: + name: manual-snapshot + namespace: default +``` + +**"snapshotHandle"** is the key parameter that contains four sections. + + 1. Snapshot name (unused) + 2. Type of snapshot (unused and if specified it should be FC/iSCSI/NFS) + 3. Arrays id ex: apm00175000000 + 4. Snapshot id ex:38654806278 + + +3. Create a VolumeSnapshot + +```yaml +apiVersion: snapshot.storage.k8s.io/v1beta1 +kind: VolumeSnapshot +metadata: + name: manual-snapshot +spec: + volumeSnapshotClassName: unity-snapclass + source: + volumeSnapshotContentName: manual-snapshot-content +``` + +4. Ingestion is completed in the above steps and user can perform Clone volume or Create Volume from Snapshot from VolumeSnapshot created from VolumeSnapshotContent. + +Ex: Create volume from VolumeSnapshot + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: restore-pvc-from-snap +spec: + storageClassName: unity + dataSource: + name: manual-snapshot + kind: VolumeSnapshot + apiGroup: snapshot.storage.k8s.io + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi +``` ## Dynamically update the unity-creds secrets Users can dynamically add delete array information from secret. Whenever an update happens the driver updates the "Host" information in an array. User can update secret using the following command. - `kubectl create secret generic unity-creds -n unity --from-file=config=secret.json -o yaml --dry-run | kubectl replace -f - ` + `kubectl create secret generic unity-creds -n unity --from-file=config=secret.json -o yaml --dry-run=client | kubectl replace -f - ` -* Note: * Updating unity-certs-x secrets is a manual process, unlike unity-creds. Users have to re-install the driver in case of updating/adding the SSL certificates or changing the certSecretCount parameter. +**Note**: Updating unity-certs-x secrets is a manual process, unlike unity-creds. Users have to re-install the driver in case of updating/adding the SSL certificates or changing the certSecretCount parameter. -## Install CSI-Unity driver using dell-csi-operator in OpenShift +## Install CSI-Unity driver using dell-csi-operator in OpenShift / upstream Kubernetes CSI Driver for Dell EMC Unity can also be installed via the new Dell EMC Storage Operator. -Note: Currently, csi-unity v1.1.0.1 is supported using csi-operator. Use helm-v3 to install csi-driver v1.2 for OpenShift - -The Dell EMC Storage CSI Operator is a Kubernetes Operator, which can be used to install and manage the CSI Drivers provided by Dell EMC for various storage platforms. This operator is available as a community operator for upstream Kubernetes and can be deployed using OperatorHub.io. It is also available as a community operator for OpenShift clusters and can be deployed using OpenShift Container Platform. Both these methods of installation use OLM (Operator Lifecycle Manager). +The Dell EMC Storage CSI Operator is a Kubernetes Operator, which can be used to install and manage the CSI Drivers provided by Dell EMC for various storage platforms. This operator is available as a community operator for upstream Kubernetes and can be deployed using https://operatorhub.io/operator/dell-csi-operator . It is also available as a community operator for OpenShift clusters and can be deployed using OpenShift Container Platform. Both upstream kubernetes and openshift uses OLM(Operator Lifecycle Manager) as well as manual installation. The operator can also be deployed directly by following the instructions available here - https://github.com/dell/dell-csi-operator @@ -629,86 +737,81 @@ There are sample manifests provided, which can be edited to do an easy installat Kubernetes Operators make it easy to deploy and manage the entire lifecycle of complex Kubernetes applications. Operators use Custom Resource Definitions (CRD), which represents the application and use custom controllers to manage them. -### Listing CSI-Unity drivers -User can query for csi-unity driver using the following command -`kubectl get csiunity --all-namespaces` - ### Procedure to create new CSI-Unity driver 1. Create namespace - Run `kubectl create namespace unity` to create the unity namespace. + Run `kubectl create namespace test-unity` to create the a namespace called test-unity. It can be any user-defined name. 2. Create *unity-creds* - Create a file called unity-creds.yaml with the following content - ```yaml - apiVersion: v1 - kind: Secret - metadata: - name: unity-creds - namespace: unity - type: Opaque - data: - # set username to the base64 encoded username - username: - # set password to the base64 encoded password - password: - ``` + Create secret mentioned in [Install csi-driver](#install-csi-driver-for-unity) section. The secret should be created in user-defined namespace (test-unity, in this case) + +3. Create certificate secrets + + As part of the CSI driver installation, the CSI driver requires a secret with the name unity-certs-0 to unity-certs-n in the user-defined namespace (test-unity, in this case) + Create certificate procedure explained in the [link](#certificate-validation-for-unisphere-rest-api-calls) - Replace the values for the username and password parameters. These values can be optioned using base64 encoding as described in the following example: - ``` - echo -n "myusername" | base64 - echo -n "mypassword" | base64 - ``` + **Note**: *'certSecretCount'* parameter is not required for operator. Based on secret name pattern (unity-certs-*) operator reads all the secrets. + Secret name suffix should have 0 to N order to read the secrets. Secrets will not be considered, if any number missing in suffix. - Run `kubectl create -f unity-creds.yaml` command to create the secret - -3. Create a CR (Custom Resource) for unity using the sample provided below -Create a new file `csiunity.yaml` with the following content. + Ex: If unity-certs-0, unity-certs-1, unity-certs-3 are present in the namespace, then only first two secrets are considered for SSL verification. + +4. Create a CR (Custom Resource) for unity using the sample provided below + +Create a new file `csiunity.yaml` by referring the following content. Replace the given sample values according to your environment. You can find may CRDs under deploy/crds folder when you install dell-csi-operator ```yaml apiVersion: storage.dell.com/v1 kind: CSIUnity metadata: - name: unity - namespace: unity + name: test-unity + namespace: test-unity spec: driver: - configVersion: v1 + configVersion: v2 + certSecretCount: 1 replicas: 1 + sideCars: + - + name: snapshotter + snapshotClass: + - + name: test-snap + parameters: + retentionDuration: "" common: - image: "dellemc/csi-unity:v1.1.0.000R" + image: "dellemc/csi-unity:v1.3.0.000R" imagePullPolicy: IfNotPresent envs: - name: X_CSI_UNITY_DEBUG value: "true" - - name: X_CSI_UNITY_ENDPOINT - value: "https://" - - name: X_CSI_UNITY_INSECURE - value: "true" storageClass: - - name: fc + - name: virt2016****-fc default: true reclaimPolicy: "Delete" parameters: storagePool: pool_1 + arrayId: "VIRT2016****" protocol: "FC" - - name: iscsi + - name: virt2017****-iscsi reclaimPolicy: "Delete" parameters: storagePool: pool_1 + arrayId: "VIRT2017****" protocol: "iSCSI" snapshotClass: - - name: snapshot - parameters: - retentionDuration: "1:1:1:1" + - name: test-snap + parameters: + retentionDuration: "" ``` -4. Execute the following command to create unity custom resource +5. Execute the following command to create unity custom resource ```kubectl create -f csiunity.yaml``` - The above command will deploy the csi-unity driver + The above command will deploy the csi-unity driver in the test-unity namespace. + +6. Any deployment error can be found out by loggin the operator pod which is in default namespace (e.g., kubectl logs dell-csi-operator-64c58559f6-cbgv7) -5. User can configure the following parameters in CR +7. User can configure the following parameters in CR The following table lists the primary configurable parameters of the Unity driver chart and their default values. @@ -717,8 +820,6 @@ Create a new file `csiunity.yaml` with the following content. | ***Common parameters for node and controller*** | | CSI_ENDPOINT | Specifies the HTTP endpoint for Unity. | No | /var/run/csi/csi.sock | | X_CSI_DEBUG | To enable debug mode | No | false | - | X_CSI_UNITY_ENDPOINT | Must provide a UNITY HTTPS unisphere url. | Yes | | - | X_CSI_UNITY_INSECURE | Specifies that the Unity's hostname and certificate chain | No | true | | GOUNITY_DEBUG | To enable debug mode for gounity library| No | false | | ***Controller parameters*** | | X_CSI_MODE | Driver starting mode | No | controller| @@ -727,63 +828,23 @@ Create a new file `csiunity.yaml` with the following content. | X_CSI_MODE | Driver starting mode | No | node| | X_CSI_ISCSI_CHROOT | Path to which the driver will chroot before running any iscsi commands. | No | /noderoot | -## Install csi-unity driver in OpenShift using HELM v3.x - -1. Clone the git repository. ( `git clone https://github.com/dell/csi-unity.git`) - -2. Change the directory to ./helm - -3. Create a namespace "unity" in kubernetes cluster - -4. Create unity-cert-0 to unity-cert-n secrets as explained in the previous sections. - -5. Create unity-creds secret using the secret.json explained in the previous sections. - -6. Create clusterrole (unity-node) with the following yaml - -```yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: unity-node -rules: - - apiGroups: - - security.openshift.io - resourceNames: - - privileged - resources: - - securitycontextconstraints - verbs: - - use -``` - -7. Create clusterrolebinding (unity-node) with the following yaml -```yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: unity-node -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: unity-node -subjects: - - kind: ServiceAccount - name: unity-node - namespace: unity -``` +### Listing CSI-Unity drivers + User can query for csi-unity driver using the following commands + `kubectl get csiunity --all-namespaces` + `kubectl get pods -n ` -8. Execute the following command to install the driver. + In addition , user can enter the following command to make sure operator is running -`helm install unity --values myvalues.yaml --values csi-unity/k8s-1.16-values.yaml -n unity ./csi-unity` + `kubectl get pods` -Note: Preparing myvalues.yaml and secret.json is same as explained in the previous sections + The above command should display a pod whose name starts with dell-csi-operator running on a default namespace. -## Support -The CSI Driver for Dell EMC Unity image available on Dockerhub is officially supported by Dell EMC. - -The source code available on Github is unsupported and provided solely under the terms of the license attached to the source code. For clarity, Dell EMC does not provide support for any source code modifications. - -For any CSI driver setup, configuration issues, questions or feedback, join the Dell EMC Container community at https://www.dell.com/community/Containers/bd-p/Containers - -For any Dell EMC storage issues, please contact Dell support at: https://www.dell.com/support. + To upgrade the driver from csi-unity v1.2.1 in OpenShift 4.3 (Installed using Helm) to csi-unity v1.3 in OpenShift 4.3: + 1. Uninstall the existing csi-unity v1.2.1 driver using Helm's uninstall.unity script. + 2. Install operator using the instructions provided in https://github.com/dell/dell-csi-operator. + 3. Create CR by taking the reference from /deploy/crds/unity_v130_ops_43.yaml. + 4. User can install csi-unity v1.3 in previous namespace (unity) or user can install in the new namespace. + 5. Install csi-unity v1.3 driver using the operator v1.1 by creating the object (E.g., kubectl create -f + unity_v130_ops_43.yaml). + 6. Please note that , volumesnapshotclass will not be created as part of this installation and no volume + snapshot related operation can be performed on this combination (csi-unity v1.3 and OpenShift 4.3). \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..934f50b --- /dev/null +++ b/build.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# This script will build an image for the Unity CSI Driver +# Before running this script, make sure that you have podman installed on your system +# If you are going to push the image to an image repo, make sure that you are logged in +# sh build.sh: build the image +# sh build.sh -p: build and push the image + +function git_version { + local gitdesc=$(git describe --long) + local version="${gitdesc%%-*}" + MAJOR_VERSION=$(echo $version | cut -d. -f1) + MINOR_VERSION=$(echo $version | cut -d. -f2) + PATCH_NUMBER=$(echo $version | cut -d. -f3) + BUILD_NUMBER_FROM_GIT=$(sed -e 's#.*-\(\)#\1#' <<< "${gitdesc%-*}") + echo MAJOR_VERSION=$MAJOR_VERSION MINOR_VERSION=$MINOR_VERSION PATCH_NUMBER=$PATCH_NUMBER BUILD_NUMBER_FROM_GIT=$BUILD_NUMBER_FROM_GIT + echo Target Version=$VERSION +} + +function build_image { + echo $BUILDCMD build -t ${IMAGE_NAME}:${IMAGE_TAG} . + (cd .. && $BUILDCMD build -t ${IMAGE_NAME}:${IMAGE_TAG} --build-arg GOPROXY=$GOPROXY -f csi-unity/Dockerfile . --format=docker) + echo $BUILDCMD tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_REPO}/${IMAGE_REPO_NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} + $BUILDCMD tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_REPO}/${IMAGE_REPO_NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} +} + +function push_image { + echo $BUILDCMD push ${IMAGE_REPO}/${IMAGE_REPO_NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} + $BUILDCMD push ${IMAGE_REPO}/${IMAGE_REPO_NAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG} +} + +NAME=csi-unity +IMAGE_NAME=${NAME}-${USER} +VERSION=$(date +%Y%m%d%H%M%S) +BIN_DIR=bin +BIN_NAME=${NAME} +IMAGE_REPO=amaas-eos-mw1.cec.lab.emc.com:5028 +IMAGE_REPO_NAMESPACE=csi-unity +IMAGE_TAG=${VERSION} + +# Read options +while getopts 'ph' flag; do + case "${flag}" in + p) PUSH_IMAGE='true' ;; + h) git_version + exit 0 ;; + *) git_version + exit 0 ;; + esac +done + +BUILDCMD="podman" +DOCKEROPT="--format=docker" +set -e + +command -v podman +if [ $? -eq 0 ]; then + echo "Using podman for building image" +else + echo "podman must be installed for building UBI based image" + exit 1 +fi + +# Build the image +build_image + +if [ "$PUSH_IMAGE" = true ]; then + push_image +fi + +exit 0 \ No newline at end of file diff --git a/dell-csi-helm-installer/README.md b/dell-csi-helm-installer/README.md new file mode 100644 index 0000000..698e391 --- /dev/null +++ b/dell-csi-helm-installer/README.md @@ -0,0 +1,157 @@ +# Helm Installer for Dell EMC CSI Storage Providers + +## Description + +This directory provides scripts to install, upgrade, uninstall the CSI drivers, and to verify the Kubernetes environment. +These same scripts are present in all Dell EMC Container Storage Interface ([CSI](https://github.com/container-storage-interface/spec)) drivers. This includes the drivers for: +* [PowerFlex](https://github.com/dell/csi-vxflexos) +* [PowerMax](https://github.com/dell/csi-powermax) +* [PowerScale](https://github.com/dell/csi-powerscale) +* [PowerStore](https://github.com/dell/csi-powerstore) +* [Unity](https://github.com/dell/csi-unity) + +NOTE: This documentation uses the Unity driver as an example. If working with a different driver, substitute the name as appropriate. + +## Dependencies + +Installing any of the Dell EMC CSI Drivers requires a few utilities to be installed on the system running the installation. + +| Dependency | Usage | +| ------------- | ----- | +| `kubectl` | Kubectl is used to validate that the Kubernetes system meets the requirements of the driver. | +| `helm` | Helm v3 is used as the deployment tool for Charts. See, [Install HELM 3](https://helm.sh/docs/intro/install/) for instructions to install HELM 3. | + + +In order to use these tools, a valid `KUBECONFIG` is required. Ensure that either a valid configuration is in the default location or that the `KUBECONFIG` environment variable points to a valid confiugration before using these tools. + +## Capabilities + +This project provides the following capabilitites, each one is discussed in detail later in this document. + +* Install a driver. When installing a driver, options are provided to specify the target namespace as well as options to control the types of verifications to be performed on the target system. +* Upgrade a driver. Upgrading a driver is an effective way to either deploy a new version of the driver or to modify the parameters used in an initial deployment. +* Uninstall a driver. This removes the driver and any installed storage classes. +* Verify a Kubernetes system for suitability with a driver. These verification steps differ, slightly, from driver to driver but include verifiying version compatibility, namespace availability, existance of required secrets, and validating worker node compatibility with driver protocols such as iSCSI, Fibre Channel, NFS, etc + + +Most of these usages require the creation/specification of a values file. These files specify configuration settings that are passed into the driver and configure it for use. To create one of these files, the following steps should be followed: +1. Copy a template file for the driver to a new location, naming this new file is at the users discretion. The template files are always found within the driver repo at `helm/csi-/values.yaml` +2. Edit the file such that it contains the proper configuration settings for the specific environment. These files are yaml formatted so maintaining the file structure is important. + +For example, to create a values file for the Unity driver the following steps can be executed +``` +# cd to the installation script directory +cd dell-csi-helm-installer + +# copy the template file +cp ../helm/csi-unity/values.yaml ./my-unity-settings.yaml + +# edit the newly created values file +vi my-unity-settings.yaml +``` + +These values files can then be archived for later reference or for usage when upgrading the driver. + + +### Install A Driver + +Installing a driver is performed via the `csi-install.sh` script. This script requires a few arguments: the target namespace and the user created values file. By default, this will verify the Kubernetes environment and present a list of warnings and/or errors. Errors must be addressed before installing, warning should be examined for their applicability. For example, in order to install the Unity driver into a namespace called "unity", the following command should be run: +``` +./csi-install.sh --namespace unity --values ./my-unity-settings.yaml +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-install.sh -h +Help for ./csi-install.sh + +Usage: ./csi-install.sh options... +Options: + Required + --namespace[=] Kubernetes namespace containing the CSI driver + --values[=] Values file, which defines configuration values + Optional + --release[=] Name to register with helm, default value will match the driver name + --upgrade Perform an upgrade of the specified driver, default is false + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification + --skip-verify-node Skip worker node verification checks + --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes. + -h Help +``` + +### Upgrade A Driver + +Upgrading a driver is very similar to installation. The `csi-install.sh` script is run, with the same required arguments, along with a `--upgrade` argument. For example, to upgrade the previously installed Unity driver, the following command can be supplied: + +``` +./csi-install.sh --namespace unity --values ./my-unity-settings.yaml --upgrade +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-install.sh -h +Help for ./csi-install.sh + +Usage: ./csi-install.sh options... +Options: + Required + --namespace[=] Kubernetes namespace containing the CSI driver + --values[=] Values file, which defines configuration values + Optional + --release[=] Name to register with helm, default value will match the driver name + --upgrade Perform an upgrade of the specified driver, default is false + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification + --skip-verify-node Skip worker node verification checks + --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes. + -h Help +``` + +### Uninstall A Driver + +To uninstall a driver, the `csi-uninstall.sh` script provides a handy wrapper around the `helm` utility. The only required argument for uninstallation is the namespace name. To uninstall the Unity driver: + +``` +./csi-uninstall.sh --namespace unity +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./csi-uninstall.sh -h +Help for ./csi-uninstall.sh + +Usage: ./csi-uninstall.sh options... +Options: + Required + --namespace[=] Kubernetes namespace to uninstall the CSI driver from + Optional + --release[=] Name to register with helm, default value will match the driver name + -h Help +``` + +### Verify A Kubernetes Environment + +The `verify.sh` script is run, automatically, as part of the installation and upgrade procedures and can also be run by itself. This provides a handy means to validate a Kubernetes system without meaning to actually perform the installation. To verify an environment, run `verify.sh` with the namespace name and values file options. + +``` +./verify.sh --namespace unity --values ./my-unity-settings.yaml +``` + +For usage information: +``` +[dell-csi-helm-installer]# ./verify.sh -h +Help for ./verify.sh + +Usage: ./verify.sh options... +Options: + Required + --namespace[=] Kubernetes namespace to install the CSI driver + --values[=] Values file, which defines configuration values + Optional + --skip-verify-node Skip worker node verification checks + --release[=] Name to register with helm, default value will match the driver name + --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root + -h Help Help +``` + diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml new file mode 100644 index 0000000..4aa980c --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml @@ -0,0 +1,85 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .driver + name: Driver + type: string + - JSONPath: .deletionPolicy + description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass + should be deleted when its bound VolumeSnapshot is deleted. + name: DeletionPolicy + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + singular: volumesnapshotclass + preserveUnknownFields: false + scope: Cluster + subresources: {} + validation: + openAPIV3Schema: + description: VolumeSnapshotClass specifies parameters that a underlying storage + system uses when creating a volume snapshot. A specific VolumeSnapshotClass + is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses + are non-namespaced + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + deletionPolicy: + description: deletionPolicy determines whether a VolumeSnapshotContent created + through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot + is deleted. Supported values are "Retain" and "Delete". "Retain" means + that the VolumeSnapshotContent and its physical snapshot on underlying + storage system are kept. "Delete" means that the VolumeSnapshotContent + and its physical snapshot on underlying storage system are deleted. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the storage driver that handles this + VolumeSnapshotClass. Required. + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + parameters: + additionalProperties: + type: string + description: parameters is a key-value map with storage driver specific + parameters for creating snapshots. These values are opaque to Kubernetes. + type: object + required: + - deletionPolicy + - driver + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml new file mode 100644 index 0000000..34c51ad --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml @@ -0,0 +1,233 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.readyToUse + description: Indicates if a snapshot is ready to be used to restore a volume. + name: ReadyToUse + type: boolean + - JSONPath: .status.restoreSize + description: Represents the complete size of the snapshot in bytes + name: RestoreSize + type: integer + - JSONPath: .spec.deletionPolicy + description: Determines whether this VolumeSnapshotContent and its physical snapshot + on the underlying storage system should be deleted when its bound VolumeSnapshot + is deleted. + name: DeletionPolicy + type: string + - JSONPath: .spec.driver + description: Name of the CSI driver used to create the physical snapshot on the + underlying storage system. + name: Driver + type: string + - JSONPath: .spec.volumeSnapshotClassName + description: Name of the VolumeSnapshotClass to which this snapshot belongs. + name: VolumeSnapshotClass + type: string + - JSONPath: .spec.volumeSnapshotRef.name + description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent + object is bound. + name: VolumeSnapshot + type: string + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + singular: volumesnapshotcontent + preserveUnknownFields: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: VolumeSnapshotContent represents the actual "on-disk" snapshot + object in the underlying storage system + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + spec: + description: spec defines properties of a VolumeSnapshotContent created + by the underlying storage system. Required. + properties: + deletionPolicy: + description: deletionPolicy determines whether this VolumeSnapshotContent + and its physical snapshot on the underlying storage system should + be deleted when its bound VolumeSnapshot is deleted. Supported values + are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent + and its physical snapshot on underlying storage system are kept. "Delete" + means that the VolumeSnapshotContent and its physical snapshot on + underlying storage system are deleted. In dynamic snapshot creation + case, this field will be filled in with the "DeletionPolicy" field + defined in the VolumeSnapshotClass the VolumeSnapshot refers to. For + pre-existing snapshots, users MUST specify this field when creating + the VolumeSnapshotContent object. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the CSI driver used to create the + physical snapshot on the underlying storage system. This MUST be the + same as the name returned by the CSI GetPluginName() call for that + driver. Required. + type: string + source: + description: source specifies from where a snapshot will be created. + This field is immutable after creation. Required. + properties: + snapshotHandle: + description: snapshotHandle specifies the CSI "snapshot_id" of a + pre-existing snapshot on the underlying storage system. This field + is immutable. + type: string + volumeHandle: + description: volumeHandle specifies the CSI "volume_id" of the volume + from which a snapshot should be dynamically taken from. This field + is immutable. + type: string + type: object + volumeSnapshotClassName: + description: name of the VolumeSnapshotClass to which this snapshot + belongs. + type: string + volumeSnapshotRef: + description: volumeSnapshotRef specifies the VolumeSnapshot object to + which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName + field must reference to this VolumeSnapshotContent's name for the + bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent + object, name and namespace of the VolumeSnapshot object MUST be provided + for binding to happen. This field is immutable after creation. Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an + entire object, this string should contain a valid JSON/Go field + access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen only + to have some well-defined way of referencing a part of an object. + TODO: this design is not final and this field is subject to change + in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is + made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + required: + - deletionPolicy + - driver + - source + - volumeSnapshotRef + type: object + status: + description: status represents the current information of a snapshot. + properties: + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot + is taken by the underlying storage system. In dynamic snapshot creation + case, this field will be filled in with the "creation_time" value + returned from CSI "CreateSnapshotRequest" gRPC call. For a pre-existing + snapshot, this field will be filled with the "creation_time" value + returned from the CSI "ListSnapshots" gRPC call if the driver supports + it. If not specified, it indicates the creation time is unknown. The + format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command `date +%s%N` returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. + format: int64 + type: integer + error: + description: error is the latest observed error during snapshot creation, + if any. + properties: + message: + description: 'message is a string detailing the encountered error + during snapshot creation if specified. NOTE: message may be logged, + and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if a snapshot is ready to be used + to restore a volume. In dynamic snapshot creation case, this field + will be filled in with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" gRPC call. For a pre-existing snapshot, this + field will be filled with the "ready_to_use" value returned from the + CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, + this field will be set to "True". If not specified, it means the readiness + of a snapshot is unknown. + type: boolean + restoreSize: + description: restoreSize represents the complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be filled + in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + gRPC call. For a pre-existing snapshot, this field will be filled + with the "size_bytes" value returned from the CSI "ListSnapshots" + gRPC call if the driver supports it. When restoring a volume from + this snapshot, the size of the volume MUST NOT be smaller than the + restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + format: int64 + minimum: 0 + type: integer + snapshotHandle: + description: snapshotHandle is the CSI "snapshot_id" of a snapshot on + the underlying storage system. If not specified, it indicates that + dynamic snapshot creation has either failed or it is still in progress. + type: string + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml new file mode 100644 index 0000000..483706f --- /dev/null +++ b/dell-csi-helm-installer/beta-snapshot-crd/snapshot.storage.k8s.io_volumesnapshots.yaml @@ -0,0 +1,188 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/260" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + additionalPrinterColumns: + - JSONPath: .status.readyToUse + description: Indicates if a snapshot is ready to be used to restore a volume. + name: ReadyToUse + type: boolean + - JSONPath: .spec.source.persistentVolumeClaimName + description: Name of the source PVC from where a dynamically taken snapshot will + be created. + name: SourcePVC + type: string + - JSONPath: .spec.source.volumeSnapshotContentName + description: Name of the VolumeSnapshotContent which represents a pre-provisioned + snapshot. + name: SourceSnapshotContent + type: string + - JSONPath: .status.restoreSize + description: Represents the complete size of the snapshot. + name: RestoreSize + type: string + - JSONPath: .spec.volumeSnapshotClassName + description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. + name: SnapshotClass + type: string + - JSONPath: .status.boundVolumeSnapshotContentName + description: The name of the VolumeSnapshotContent to which this VolumeSnapshot + is bound. + name: SnapshotContent + type: string + - JSONPath: .status.creationTime + description: Timestamp when the point-in-time snapshot is taken by the underlying + storage system. + name: CreationTime + type: date + - JSONPath: .metadata.creationTimestamp + name: Age + type: date + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + singular: volumesnapshot + preserveUnknownFields: false + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: VolumeSnapshot is a user's request for either creating a point-in-time + snapshot of a persistent volume, or binding to a pre-existing snapshot. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + spec: + description: 'spec defines the desired characteristics of a snapshot requested + by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots + Required.' + properties: + source: + description: source specifies where a snapshot will be created from. + This field is immutable after creation. Required. + properties: + persistentVolumeClaimName: + description: persistentVolumeClaimName specifies the name of the + PersistentVolumeClaim object in the same namespace as the VolumeSnapshot + object where the snapshot should be dynamically taken from. This + field is immutable. + type: string + volumeSnapshotContentName: + description: volumeSnapshotContentName specifies the name of a pre-existing + VolumeSnapshotContent object. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: 'volumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. If not specified, the default snapshot + class will be used if one exists. If not specified, and there is no + default snapshot class, dynamic snapshot creation will fail. Empty + string is not allowed for this field. TODO(xiangqian): a webhook validation + on empty string. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshot-classes' + type: string + required: + - source + type: object + status: + description: 'status represents the current information of a snapshot. NOTE: + status can be modified by sources other than system controllers, and must + not be depended upon for accuracy. Controllers should only use information + from the VolumeSnapshotContent object after verifying that the binding + is accurate and complete.' + properties: + boundVolumeSnapshotContentName: + description: 'boundVolumeSnapshotContentName represents the name of + the VolumeSnapshotContent object to which the VolumeSnapshot object + is bound. If not specified, it indicates that the VolumeSnapshot object + has not been successfully bound to a VolumeSnapshotContent object + yet. NOTE: Specified boundVolumeSnapshotContentName alone does not + mean binding is valid. Controllers MUST always verify bidirectional + binding between VolumeSnapshot and VolumeSnapshotContent to + avoid possible security issues.' + type: string + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot + is taken by the underlying storage system. In dynamic snapshot creation + case, this field will be filled in with the "creation_time" value + returned from CSI "CreateSnapshotRequest" gRPC call. For a pre-existing + snapshot, this field will be filled with the "creation_time" value + returned from the CSI "ListSnapshots" gRPC call if the driver supports + it. If not specified, it indicates that the creation time of the snapshot + is unknown. + format: date-time + type: string + error: + description: error is the last observed error during snapshot creation, + if any. This field could be helpful to upper level controllers(i.e., + application controller) to decide whether they should continue on + waiting for the snapshot to be created based on the type of error + reported. + properties: + message: + description: 'message is a string detailing the encountered error + during snapshot creation if specified. NOTE: message may be logged, + and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if a snapshot is ready to be used + to restore a volume. In dynamic snapshot creation case, this field + will be filled in with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" gRPC call. For a pre-existing snapshot, this + field will be filled with the "ready_to_use" value returned from the + CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, + this field will be set to "True". If not specified, it means the readiness + of a snapshot is unknown. + type: boolean + restoreSize: + anyOf: + - type: integer + - type: string + description: restoreSize represents the complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be filled + in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + gRPC call. For a pre-existing snapshot, this field will be filled + with the "size_bytes" value returned from the CSI "ListSnapshots" + gRPC call if the driver supports it. When restoring a volume from + this snapshot, the size of the volume MUST NOT be smaller than the + restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/dell-csi-helm-installer/common.sh b/dell-csi-helm-installer/common.sh new file mode 100644 index 0000000..f4b8730 --- /dev/null +++ b/dell-csi-helm-installer/common.sh @@ -0,0 +1,114 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +DRIVERDIR="${SCRIPTDIR}/../helm" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +DARK_GRAY='\033[1;30m' +NC='\033[0m' # No Color + +function log() { + case $1 in + separator) + echo "------------------------------------------------------" + ;; + error) + echo + log separator + printf "${RED}Error: $2\n" + printf "${RED}Installation cannot continue${NC}\n" + exit 1 + ;; + step) + printf "|\n|- %-65s" "$2" + ;; + small_step) + printf "%-61s" "$2" + ;; + section) + log separator + printf "> %s\n" "$2" + log separator + ;; + smart_step) + if [[ $3 == "small" ]]; then + log small_step "$2" + else + log step "$2" + fi + ;; + arrow) + printf " %s\n %s" "|" "|--> " + ;; + step_success) + printf "${GREEN}Success${NC}\n" + ;; + step_failure) + printf "${RED}Failed${NC}\n" + ;; + step_warning) + printf "${YELLOW}Warning${NC}\n" + ;; + info) + printf "${DARK_GRAY}%s${NC}\n" "$2" + ;; + passed) + printf "${GREEN}Success${NC}\n" + ;; + warnings) + printf "${YELLOW}Warnings:${NC}\n" + ;; + errors) + printf "${RED}Errors:${NC}\n" + ;; + *) + echo -n "Unknown" + ;; + esac +} + +function check_error() { + if [[ $1 -ne 0 ]]; then + log step_failure + else + log step_success + fi +} + +# +# get_drivers will populate an array of drivers found by +# enumerating the directories in drivers/ that contain a helm chart +function get_drivers() { + D="${1}" + TTT=$(pwd) + while read -r line; do + DDD=$(echo $line | awk -F '/' '{print $(NF-1)}') + VALIDDRIVERS+=("$DDD") + done < <(find "${D}" -maxdepth 2 -type f -name Chart.yaml | sort) +} + +# +# get_release will determine the helm release name to use +# If ${RELEASE} is set, use that +# Otherwise, use the driver name minus any "csi-" prefix +# argument 1: Driver name +function get_release_name() { + local D="${1}" + if [ ! -z "${RELEASE}" ]; then + echo "${RELEASE}" + return + fi + + local PREFIX="csi-" + R=${D#"$PREFIX"} + echo "${R}" +} diff --git a/dell-csi-helm-installer/csi-install.sh b/dell-csi-helm-installer/csi-install.sh new file mode 100755 index 0000000..5445960 --- /dev/null +++ b/dell-csi-helm-installer/csi-install.sh @@ -0,0 +1,391 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +DRIVERDIR="${SCRIPTDIR}/../helm" +VERIFYSCRIPT="${SCRIPTDIR}/verify.sh" +SNAPCLASSDIR="${SCRIPTDIR}/beta-snapshot-crd" +PROG="${0}" +NODE_VERIFY=1 +VERIFY=1 +MODE="install" +# version of Snapshot CRD to install. Default is none ("") +INSTALL_CRD="" + +declare -a VALIDDRIVERS + +source "$SCRIPTDIR"/common.sh + + +# +# usage will print command execution help and then exit +function usage() { + echo + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace containing the CSI driver" + echo " --values[=] Values file, which defines configuration values" + + echo " Optional" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " --upgrade Perform an upgrade of the specified driver, default is false" + echo " --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root" + echo " --skip-verify Skip the kubernetes configuration verification to use the CSI driver, default will run verification" + echo " --skip-verify-node Skip worker node verification checks" + echo " --snapshot-crd Install snapshot CRDs. Default will not install Snapshot classes." + echo " -h Help" + echo + + exit 0 +} + +# warning, with an option for users to continue +function warning() { + log separator + printf "${YELLOW}WARNING:${NC}\n" + for N in "$@"; do + echo $N + done + echo + if [ "${ASSUMEYES}" == "true" ]; then + echo "Continuing as '-Y' argument was supplied" + return + fi + read -n 1 -p "Press 'y' to continue or any other key to exit: " CONT + echo + if [ "${CONT}" != "Y" -a "${CONT}" != "y" ]; then + echo "quitting at user request" + exit 2 + fi +} + + +# print header information +function header() { + log section "Installing CSI Driver: ${DRIVER} on ${kMajorVersion}.${kMinorVersion}" +} + +# +# check_for_driver will see if the driver is already installed within the namespace provided +function check_for_driver() { + log section "Checking to see if CSI Driver is already installed" + NUM=$(helm list --namespace "${NS}" | grep "^${RELEASE}\b" | wc -l) + if [ "${1}" == "install" -a "${NUM}" != "0" ]; then + log error "The CSI Driver is already installed" + fi + if [ "${1}" == "upgrade" -a "${NUM}" == "0" ]; then + log error "The CSI Driver is not installed" + fi +} + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + usage + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + usage + exit 1 + fi + # the namespace is required + if [ -z "${NS}" ]; then + echo "No namespace specified" + usage + exit 1 + fi + # values file + if [ -z "${VALUES}" ]; then + echo "No values file was specified" + usage + exit 1 + fi + if [ ! -f "${VALUES}" ]; then + echo "Unable to read values file at: ${VALUES}" + usage + exit 1 + fi +} + +# +# install_driver uses helm to install the driver with a given name +function install_driver() { + if [ "${1}" == "upgrade" ]; then + log step "Upgrading Driver" + else + log step "Installing Driver" + fi + + HELMOUTPUT="/tmp/csi-install.$$.out" + helm ${1} --values "${DRIVERDIR}/${DRIVER}/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml" --values "${DRIVERDIR}/${DRIVER}/driver-image.yaml" --values "${VALUES}" --namespace ${NS} "${RELEASE}" "${DRIVERDIR}/${DRIVER}" >"${HELMOUTPUT}" 2>&1 + if [ $? -ne 0 ]; then + cat "${HELMOUTPUT}" + log error "Helm operation failed, output can be found in ${HELMOUTPUT}. The failure should be examined, before proceeding. Additionally, running csi-uninstall.sh may be needed to clean up partial deployments." + fi + log step_success + # wait for the deployment to finish, use the default timeout + waitOnRunning "${NS}" "statefulset ${RELEASE}-controller,daemonset ${RELEASE}-node" + if [ $? -eq 1 ]; then + warning "Timed out waiting for the operation to complete." \ + "This does not indicate a fatal error, pods may take a while to start." \ + "Progress can be checked by running \"kubectl get pods -n ${NS}\"" + fi +} + +# Print a nice summary at the end +function summary() { + log section "Operation complete" +} + +# waitOnRunning +# will wait, for a timeout period, for a number of pods to go into Running state within a namespace +# arguments: +# $1: required: namespace to watch +# $2: required: comma seperated list of deployment type and name pairs +# for example: "statefulset mystatefulset,daemonset mydaemonset" +# $3: optional: timeout value, 300 seconds is the default. +function waitOnRunning() { + if [ -z "${2}" ]; then + echo "No namespace and/or list of deployments was supplied. This field is required for waitOnRunning" + return 1 + fi + # namespace + local NS="${1}" + # pods + IFS="," read -r -a PODS <<<"${2}" + # timeout value passed in, or 300 seconds as a default + local TIMEOUT="300" + if [ -n "${3}" ]; then + TIMEOUT="${3}" + fi + + error=0 + for D in "${PODS[@]}"; do + log arrow + log smart_step "Waiting for $D to be ready" "small" + kubectl -n "${NS}" rollout status --timeout=${TIMEOUT}s ${D} >/dev/null 2>&1 + if [ $? -ne 0 ]; then + error=1 + log step_failure + else + log step_success + fi + done + + if [ $error -ne 0 ]; then + return 1 + fi + return 0 +} + +function kubectl_safe() { + eval "kubectl $1" + exitcode=$? + if [[ $exitcode != 0 ]]; then + echo "$2" + exit $exitcode + fi +} + +# +# install_snapshot_crds +# Downloads and installs snapshot CRDs +function install_snapshot_crd() { + if [ "${INSTALL_CRD}" == "" ]; then + return + fi + log step "Checking and installing snapshot crds" + + declare -A SNAPCLASSES=( + ["volumesnapshotclasses"]="snapshot.storage.k8s.io_volumesnapshotclasses.yaml" + ["volumesnapshotcontents"]="snapshot.storage.k8s.io_volumesnapshotcontents.yaml" + ["volumesnapshots"]="snapshot.storage.k8s.io_volumesnapshots.yaml" + ) + + for C in "${!SNAPCLASSES[@]}"; do + F="${SNAPCLASSES[$C]}" + # check if custom resource exists + kubectl_safe "get customresourcedefinitions" "Failed to get crds" | grep "${C}" --quiet + + if [[ $? -ne 0 ]]; then + # make sure CRD exists + if [ ! -f "${SNAPCLASSDIR}/${SNAPCLASSES[$C]}" ]; then + echo "Unable to to find Snapshot Classes at ${SNAPCLASSDIR}" + exit 1 + fi + # create the custom resource + kubectl_safe "create -f ${SNAPCLASSDIR}/${SNAPCLASSES[$C]}" "Failed to create Volume Snapshot Beta CRD: ${C}" + fi + done + + sleep 10s + log step_success +} + +# +# verify_kubernetes +# will run a driver specific function to verify environmental requirements +function verify_kubernetes() { + EXTRA_OPTS="" + if [ $VERIFY -eq 0 ]; then + echo "Skipping verification at user request" + else + if [ $NODE_VERIFY -eq 0 ]; then + EXTRA_OPTS="$EXTRA_OPTS --skip-verify-node" + fi + if [ "${INSTALL_CRD}" == "yes" ]; then + EXTRA_OPTS="$EXTRA_OPTS --snapshot-crd" + fi + "${VERIFYSCRIPT}" --namespace "${NS}" --release "${RELEASE}" --values "${VALUES}" --node-verify-user "${NODEUSER}" ${EXTRA_OPTS} + VERIFYRC=$? + case $VERIFYRC in + 0) ;; + + 1) + warning "Kubernetes validation failed but installation can continue. " \ + "This may affect driver installation." + ;; + *) + log error "Kubernetes validation failed." + ;; + esac + fi +} + +# +# main +# +VERIFYOPTS="" +ASSUMEYES="false" + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${DRIVERDIR}" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + skip-verify) + VERIFY=0 + ;; + skip-verify-node) + NODE_VERIFY=0 + ;; + # SNAPSHOT_CRD + snapshot-crd) + INSTALL_CRD="yes" + ;; + upgrade) + MODE="upgrade" + ;; + # NAMESPACE + namespace) + NS="${!OPTIND}" + if [[ -z ${NS} || ${NS} == "--skip-verify" ]]; then + NS=${DEFAULT_NS} + else + OPTIND=$((OPTIND + 1)) + fi + ;; + namespace=*) + NS=${OPTARG#*=} + if [[ -z ${NS} ]]; then NS=${DEFAULT_NS}; fi + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + # VALUES + values) + VALUES="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + values=*) + VALUES=${OPTARG#*=} + ;; + # NODEUSER + node-verify-user) + NODEUSER="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + node-verify-user=*) + HODEUSER=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") +# by default, NODEUSER is root +NODEUSER="${NODEUSER:-root}" + +# make sure kubectl is available +kubectl --help >&/dev/null || { + echo "kubectl required for installation... exiting" + exit 2 +} +# make sure helm is available +helm --help >&/dev/null || { + echo "helm required for installation... exiting" + exit 2 +} + +# Get the kubernetes major and minor version numbers. +kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/[^0-9].*//g') +kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/[^0-9].*//g') + +# validate the parameters passed in +validate_params "${MODE}" + +header +check_for_driver "${MODE}" +verify_kubernetes + +if [[ "${INSTALL_CRD}" != "" ]]; then + install_snapshot_crd +fi + + +# all good, keep processing +install_driver "${MODE}" + +summary diff --git a/dell-csi-helm-installer/csi-uninstall.sh b/dell-csi-helm-installer/csi-uninstall.sh new file mode 100755 index 0000000..e3e8e5c --- /dev/null +++ b/dell-csi-helm-installer/csi-uninstall.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +DRIVERDIR="${SCRIPTDIR}/../helm" +PROG="${0}" + +declare -a VALIDDRIVERS + +source "$SCRIPTDIR"/common.sh + +# +# usage will print command execution help and then exit +function usage() { + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace to uninstall the CSI driver from" + + echo " Optional" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " -h Help" + echo + + exit 0 +} + + + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + exit 1 + fi + # the namespace is required + if [ -z "${NAMESPACE}" ]; then + echo "No namespace specified" + exit 1 + fi +} + + +# check_for_driver will see if the driver is installed within the namespace provided +function check_for_driver() { + NUM=$(helm list --namespace "${NAMESPACE}" | grep "^${RELEASE}\b" | wc -l) + if [ "${NUM}" == "0" ]; then + echo "The CSI Driver is not installed." + exit 1 + fi +} + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${DRIVERDIR}" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + # NAMESPACE + namespace) + NAMESPACE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + namespace=*) + NAMESPACE=${OPTARG#*=} + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit 1 + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") + +# validate the parameters passed in +validate_params + +check_for_driver +helm delete -n "${NAMESPACE}" "${RELEASE}" +if [ $? -ne 0 ]; then + echo "Removal of the CSI Driver was unsuccessful" + exit 1 +fi + +echo "Removal of the CSI Driver is in progress." +echo "It may take a few minutes for all pods to terminate." + diff --git a/dell-csi-helm-installer/verify.sh b/dell-csi-helm-installer/verify.sh new file mode 100755 index 0000000..4ec05f8 --- /dev/null +++ b/dell-csi-helm-installer/verify.sh @@ -0,0 +1,605 @@ +#!/bin/bash +# +# Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +SCRIPTDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" +PROG="${0}" +source "$SCRIPTDIR"/common.sh + +declare -a VALIDDRIVERS + +# verify-csi-powermax method +function verify-csi-powermax() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_optional_secrets "${RELEASE}-certs" + verify_optional_secrets "csirevproxy-tls-secret" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_iscsi_installation + verify_helm_3 +} + +# +# verify-csi-isilon method +function verify-csi-isilon() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_optional_secrets "${RELEASE}-certs" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# +# verify-csi-vxflexos method +function verify-csi-vxflexos() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_sdc_installation + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# verify-csi-powerstore method +function verify-csi-powerstore() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_powerstore_node_configuration + verify_helm_3 +} + +# verify-csi-unity method +function verify-csi-unity() { + verify_k8s_versions "1" "17" "1" "19" + verify_namespace "${NS}" + verify_required_secrets "${RELEASE}-creds" + verify_required_secrets "${RELEASE}-certs-0" + verify_alpha_snap_resources + verify_beta_snap_requirements + verify_helm_3 +} + +# +# verify-driver will call the proper method to verify a specific driver +function verify-driver() { + if [ -z "${1}" ]; then + echo "Expected one argument, the driver name, to verify-driver. Received none." + exit $EXIT_ERROR + fi + local D="${1}" + # check if a verify-$DRIVER function exists + # if not, error and exit + # if yes, check to see if it should be run and run it + FNTYPE=$(type -t verify-$D) + if [ "$FNTYPE" != "function" ]; then + echo "ERROR: verify-$D function does not exist" + exit $EXIT_ERROR + else + header + log step "Driver: ${D}" + echo + verify-$D + summary + fi +} + +# Print usage information +function usage() { + echo + echo "Help for $PROG" + echo + echo "Usage: $PROG options..." + echo "Options:" + echo " Required" + echo " --namespace[=] Kubernetes namespace to install the CSI driver" + echo " --values[=] Values file, which defines configuration values" + + echo " Optional" + echo " --skip-verify-node Skip worker node verification checks" + echo " --release[=] Name to register with helm, default value will match the driver name" + echo " --node-verify-user[=] Username to SSH to worker nodes as, used to validate node requirements. Default is root" + echo " --snapshot-crd Signifies that the Snapshot CRDs will be installed as part of installation." + echo " -h Help" + echo + + exit $EXIT_WARNING +} + +# print header information +function header() { + log section "Verifying Kubernetes and driver configuration" + echo "|- Kubernetes Version: ${kMajorVersion}.${kMinorVersion}" +} + +# Check if the SDC is installed and the kernel module loaded +function verify_sdc_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + log step "Verifying the SDC installation" + + error=0 + missing=() + for node in $MINION_NODES; do + # check is the scini kernel module is loaded + ssh ${NODEUSER}@$node "/sbin/lsmod | grep scini" >/dev/null 2>&1 + rv=$? + if [ $rv -ne 0 ]; then + missing+=($node) + error=1 + found_warning "SDC was not found on node: $node" + fi + done + check_error error +} + +function verify_powerstore_node_configuration() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log step "Verifying PowerStore node configuration" + echo + + if ls "${VALUES}" >/dev/null; then + if grep -c "scsiProtocol:[[:blank:]]\+FC" "${VALUES}" >/dev/null; then + log arrow + verify_fc_installation + elif grep -c "scsiProtocol:[[:blank:]]\+ISCSI" "${VALUES}" >/dev/null; then + log arrow + verify_iscsi_installation "small" + elif grep -c "scsiProtocol:[[:blank:]]\+auto" "${VALUES}" >/dev/null; then + log arrow + verify_iscsi_installation "small" + log arrow + verify_fc_installation "small" + elif grep -c "scsiProtocol:[[:blank:]]\+None" "${VALUES}" >/dev/null; then + log step_warning + found_warning "Neither FC nor iSCSI connection is activated, please be sure that NFS settings are correct" + else + log step_failure + found_error "Incorrect scsiProtocol value, must be 'FC', 'ISCSI', 'auto' or 'None'" + fi + else + log step_failure + found_error "${VALUES} doesn't exists" + fi +} + +# Check if the iSCSI client is installed +function verify_iscsi_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log smart_step "Verifying iSCSI installation" "$1" + + error=0 + for node in $MINION_NODES; do + # check if the iSCSI client is installed + ssh ${NODEUSER}@"${node}" "cat /etc/iscsi/initiatorname.iscsi" >/dev/null 2>&1 + rv=$? + if [ $rv -ne 0 ]; then + error=1 + found_warning "iSCSI client was not found on node: $node" + fi + ssh ${NODEUSER}@"${node}" pgrep iscsid &>/dev/null + rv=$? + if [ $rv -ne 0 ]; then + error=1 + found_warning "iscsid is not running on node: $node" + fi + done + + check_error error +} + +# Check if the fc is installed +function verify_fc_installation() { + if [ ${NODE_VERIFY} -eq 0 ]; then + return + fi + + log smart_step "Verifying FC installation" "$1" + + error=0 + for node in $MINION_NODES; do + # check if FC hosts are available + ssh ${NODEUSER}@${node} 'ls --hide=* /sys/class/fc_host/* 1>/dev/null' &>/dev/null + rv=$? + if [[ ${rv} -ne 0 ]]; then + error=1 + found_warning "can't find any FC hosts on node: $node" + fi + done + + check_error error +} + +# verify secrets exist +function verify_required_secrets() { + log step "Verifying that required secrets have been created" + + error=0 + for N in "${@}"; do + # Make sure the secret has already been established + kubectl get secrets -n "${NS}" 2>/dev/null | grep "${N}" --quiet + if [ $? -ne 0 ]; then + error=1 + found_error "Required secret, ${N}, does not exist." + fi + done + check_error error +} + +function verify_optional_secrets() { + log step "Verifying that optional secrets have been created" + + error=0 + for N in "${@}"; do + # Make sure the secret has already been established + kubectl get secrets -n "${NS}" 2>/dev/null | grep "${N}" --quiet + if [ $? -ne 0 ]; then + error=1 + found_warning "Optional secret, ${N}, does not exist." + fi + done + check_error error +} + +# verify minimum and maximum k8s versions +function verify_k8s_versions() { + log step "Verifying Kubernetes versions" + echo + log arrow + verify_min_k8s_version "$1" "$2" "small" + log arrow + verify_max_k8s_version "$3" "$4" "small" +} + +# verify minimum k8s version +function verify_min_k8s_version() { + log smart_step "Verifying minimum Kubernetes version" "$3" + + error=0 + if [[ "${1}" -gt "${kMajorVersion}" ]]; then + error=1 + found_error "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is too old. Minimum required version is: ${1}.${2}" + fi + if [[ "${2}" -gt "${kMinorVersion}" ]]; then + error=1 + found_error "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is too old. Minimum required version is: ${1}.${2}" + fi + + check_error error +} + +# verify maximum k8s version +function verify_max_k8s_version() { + log smart_step "Verifying maximum Kubernetes version" "$3" + + error=0 + if [[ "${1}" -lt "${kMajorVersion}" ]]; then + error=1 + found_warning "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is newer than has been tested. Last tested version is: ${1}.${2}" + fi + if [[ "${2}" -lt "${kMinorVersion}" ]]; then + error=1 + found_warning "Kubernetes version, ${kMajorVersion}.${kMinorVersion}, is newer than has been tested. Last tested version is: ${1}.${2}" + fi + + check_error error +} + +# verify namespace +function verify_namespace() { + log step "Verifying that required namespaces have been created" + + error=0 + for N in "${@}"; do + # Make sure the namespace exists + kubectl describe namespace "${N}" >/dev/null 2>&1 + if [ $? -ne 0 ]; then + error=1 + found_error "Namespace does not exist: ${N}" + fi + done + + check_error error +} + +# verify that the no alpha version of volume snapshot resource is present on the system +function verify_alpha_snap_resources() { + log step "Verifying alpha snapshot resources" + echo + log arrow + log smart_step "Verifying that alpha snapshot CRDs are not installed" "small" + + error=0 + # check for the alpha snapshot CRDs. These shouldn't be present for installation to proceed with + CRDS=("VolumeSnapshotClasses" "VolumeSnapshotContents" "VolumeSnapshots") + for C in "${CRDS[@]}"; do + # Verify that alpha snapshot related CRDs/CRs are not there on the system. + kubectl explain ${C} 2> /dev/null | grep "^VERSION.*v1alpha1$" --quiet + if [ $? -eq 0 ]; then + error=1 + found_error "The alhpa CRD for ${C} is installed. Please uninstall it" + if [[ $(kubectl get ${C} -A --no-headers 2>/dev/null | wc -l) -ne 0 ]]; then + found_error " Found CR for alpha CRD ${C}. Please delete it" + fi + fi + done + check_error error +} + +# verify that the requirements for beta snapshot support exist +function verify_beta_snap_requirements() { + log step "Verifying beta snapshot support" + echo + log arrow + log smart_step "Verifying that beta snapshot CRDs are available" "small" + + error=0 + # check for the CRDs. These are required for installation + CRDS=("VolumeSnapshotClasses" "VolumeSnapshotContents" "VolumeSnapshots") + for C in "${CRDS[@]}"; do + # Verify if snapshot related CRDs are there on the system. If not install them. + kubectl explain ${C} 2> /dev/null | grep "^VERSION.*v1beta1$" --quiet + if [ $? -ne 0 ]; then + error=1 + if [ "${INSTALL_CRD}" == "yes" ]; then + found_warning "The beta CRD for ${C} is not installed. They will be installed because --snapshot-crd was specified" + else + found_error "The beta CRD for ${C} is not installed. These can be installed by specifying --snapshot-crd during installation" + fi + fi + done + check_error error + + log arrow + log smart_step "Verifying that beta snapshot controller is available" "small" + + error=0 + # check for the snapshot-controller. These are strongly suggested but not required + kubectl get pods -A | grep snapshot-controller --quiet + if [ $? -ne 0 ]; then + error=1 + found_warning "The Snapshot Controller does not seem to be deployed. The Snapshot Controller should be provided by the Kubernetes vendor or administrator." + fi + + check_error error +} + +# verify that helm is v3 or above +function verify_helm_3() { + log step "Verifying helm version" + + error=0 + # Check helm installer version + helm --help >&/dev/null || { + found_error "helm is required for installation" + log step_failure + return + } + + helm version | grep "v3." --quiet + if [ $? -ne 0 ]; then + error=1 + found_error "Driver installation is supported only using helm 3" + fi + + check_error error +} + +# found_error, installation will not continue +function found_error() { + for N in "$@"; do + ERRORS+=("${N}") + done +} + +# found_warning, installation can continue +function found_warning() { + for N in "$@"; do + WARNINGS+=("${N}") + done +} + +# Print a nice summary at the end +function summary() { + echo + log section "Verification Complete" + # print all the WARNINGS + NON_CRD_WARNINGS=0 + if [ "${#WARNINGS[@]}" -ne 0 ]; then + log warnings + for E in "${WARNINGS[@]}"; do + echo "- ${E}" + echo ${E} | grep --quiet "^The beta CRD for VolumeSnapshot" + if [ $? -ne 0 ]; then + NON_CRD_WARNINGS=1 + fi + done + RC=$EXIT_WARNING + if [ "${INSTALL_CRD}" == "yes" -a ${NON_CRD_WARNINGS} -eq 0 ]; then + RC=$EXIT_SUCCESS + fi + fi + + # print all the ERRORS + if [ "${#ERRORS[@]}" -ne 0 ]; then + log errors + for E in "${ERRORS[@]}"; do + echo "- ${E}" + done + RC=$EXIT_ERROR + fi + + return $RC +} + +# +# validate_params will validate the parameters passed in +function validate_params() { + # make sure the driver was specified + if [ -z "${DRIVER}" ]; then + echo "No driver specified" + usage + exit 1 + fi + # make sure the driver name is valid + if [[ ! "${VALIDDRIVERS[@]}" =~ "${DRIVER}" ]]; then + echo "Driver: ${DRIVER} is invalid." + echo "Valid options are: ${VALIDDRIVERS[@]}" + usage + exit 1 + fi + # the namespace is required + if [ -z "${NS}" ]; then + echo "No namespace specified" + usage + exit 1 + fi + # values file + if [ -z "${VALUES}" ]; then + echo "No values file was specified" + usage + exit 1 + fi + if [ ! -f "${VALUES}" ]; then + echo "Unable to read values file at: ${VALUES}" + usage + exit 1 + fi +} + +# +# main +# +# default values + +NODE_VERIFY=1 + +# exit codes +EXIT_SUCCESS=0 +EXIT_WARNING=1 +EXIT_ERROR=99 + +# arrays of messages +WARNINGS=() +ERRORS=() + +INSTALL_CRD="no" + +# make sure kubectl is available +kubectl --help >&/dev/null || { + echo "kubectl required for verification... exiting" + exit $EXIT_ERROR +} + +# Determine the nodes +MINION_NODES=$(kubectl get nodes -o wide | grep -v -e master -e INTERNAL | awk ' { print $6; }') +MASTER_NODES=$(kubectl get nodes -o wide | awk ' /master/{ print $6; }') +# Get the kubernetes major and minor version numbers. +kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/[^0-9].*//g') +kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/[^0-9].*//g') + +# get the list of valid CSI Drivers, this will be the list of directories in drivers/ that contain helm charts +get_drivers "${SCRIPTDIR}/../helm" +# if only one driver was found, set the DRIVER to that one +if [ ${#VALIDDRIVERS[@]} -eq 1 ]; then + DRIVER="${VALIDDRIVERS[0]}" +fi + +while getopts ":h-:" optchar; do + case "${optchar}" in + -) + case "${OPTARG}" in + # INSTALL_CRD. Signifies that we were asked to install the CRDs + snapshot-crd) + INSTALL_CRD="yes" + ;; + skip-verify-node) + NODE_VERIFY=0 + ;; + # NAMESPACE + namespace) + NS="${!OPTIND}" + if [[ -z ${NS} || ${NS} == "--skip-verify" ]]; then + NS=${DEFAULT_NS} + else + OPTIND=$((OPTIND + 1)) + fi + ;; + namespace=*) + NS=${OPTARG#*=} + if [[ -z ${NS} ]]; then NS=${DEFAULT_NS}; fi + ;; + # RELEASE + release) + RELEASE="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + release=*) + RELEASE=${OPTARG#*=} + ;; + # VALUES + values) + VALUES="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + values=*) + VALUES=${OPTARG#*=} + ;; + # NODEUSER + node-verify-user) + NODEUSER="${!OPTIND}" + OPTIND=$((OPTIND + 1)) + ;; + node-verify-user=*) + HODEUSER=${OPTARG#*=} + ;; + *) + echo "Unknown option --${OPTARG}" + echo "For help, run $PROG -h" + exit $EXIT_ERROR + ;; + esac + ;; + h) + usage + ;; + *) + echo "Unknown option -${OPTARG}" + echo "For help, run $PROG -h" + exit $EXIT_ERROR + ;; + esac +done + +# by default the NAME of the helm release of the driver is the same as the driver name +RELEASE=$(get_release_name "${DRIVER}") + +#"${RELEASE:-$DRIVER}" +# by default, NODEUSER is root +NODEUSER="${NODEUSER:-root}" + +# validate the parameters passed in +validate_params "${MODE}" + +verify-driver "${DRIVER}" +exit $? diff --git a/docker.mk b/docker.mk deleted file mode 100644 index 29e27ca..0000000 --- a/docker.mk +++ /dev/null @@ -1,36 +0,0 @@ -# Includes the following generated file to get semantic version information -include semver.mk -ifdef NOTES - RELNOTE="-$(NOTES)" -else - RELNOTE= -endif - -# local build, use user and timestamp it -NAME:=csi-unity -DOCKER_IMAGE_NAME ?= ${NAME}-${USER} -VERSION:=$(shell date +%Y%m%d%H%M%S) -BIN_DIR:=bin -BIN_NAME:=${NAME} -DOCKER_REPO ?= amaas-eos-mw1.cec.lab.emc.com:5028 -DOCKER_NAMESPACE ?= csi-unity -DOCKER_IMAGE_TAG ?= ${VERSION} - -.PHONY: docker-build -docker-build: - echo ${VERSION} ${GITLAB_CI} ${CI_COMMIT_TAG} ${CI_COMMIT_SHA} - rm -f core/core_generated.go - cd core && go generate - go run core/semver/semver.go -f mk >semver.mk - mkdir -p ${BIN_DIR} - GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o ${BIN_DIR}/${BIN_NAME} - docker build -t ${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG} . - docker tag ${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG} ${DOCKER_REPO}/${DOCKER_NAMESPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG} - -.PHONY: docker-push -docker-push: docker-build - docker push ${DOCKER_REPO}/${DOCKER_NAMESPACE}/${DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_TAG} - -version: - @echo "MAJOR $(MAJOR) MINOR $(MINOR) PATCH $(PATCH) BUILD ${BUILD} TYPE ${TYPE} RELNOTE $(RELNOTE) SEMVER $(SEMVER)" - @echo "Target Version: $(VERSION)" diff --git a/env.sh b/env.sh index 3dc8f5a..0739664 100644 --- a/env.sh +++ b/env.sh @@ -1,16 +1,11 @@ #!/bin/sh -export X_CSI_UNITY_ENDPOINT=https://0.0.0.0 -export X_CSI_UNITY_USER= -export X_CSI_UNITY_PASSWORD= -export X_CSI_UNITY_INSECURE=true export X_CSI_UNITY_NODENAME= -export X_CSI_PRIVATE_MOUNT_DIR= export X_CSI_STAGING_TARGET_PATH= export X_CSI_PUBLISH_TARGET_PATH= export CSI_ENDPOINT= export X_CSI_DEBUG= export STORAGE_POOL= -export STORAGE_POOL_NAME= +export NAS_SERVER= export X_CSI_REQ_LOGGING="true" export X_CSI_REP_LOGGING="true" export GOUNITY_DEBUG="true" diff --git a/go.mod b/go.mod index 9502ebb..ef75fda 100644 --- a/go.mod +++ b/go.mod @@ -2,21 +2,21 @@ module github.com/dell/csi-unity go 1.13 +// TODO: Remove these replace lines before releasing +replace github.com/dell/gounity => ../gounity + require ( github.com/DATA-DOG/godog v0.7.13 github.com/container-storage-interface/spec v1.1.0 github.com/dell/gobrick v1.0.0 - github.com/dell/gofsutil v1.2.0 + github.com/dell/gofsutil v1.3.0 github.com/dell/goiscsi v1.1.0 - github.com/dell/gounity v1.2.1 + github.com/dell/gounity v1.3.0 github.com/fsnotify/fsnotify v1.4.9 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.4.2 github.com/rexray/gocsi v1.1.0 - github.com/sirupsen/logrus v1.4.2 + github.com/sirupsen/logrus v1.6.0 github.com/stretchr/testify v1.4.0 - golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 // indirect - golang.org/x/net v0.0.0-20190620200207-3b0461eec859 - golang.org/x/text v0.3.2 // indirect - google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect - google.golang.org/grpc v1.21.1 + golang.org/x/net v0.0.0-20200625001655-4c5254603344 + google.golang.org/grpc v1.26.0 ) diff --git a/go.sum b/go.sum index 526801d..821ae6c 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,44 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DATA-DOG/godog v0.7.13 h1:JmgpKcra7Vf3yzI9vPsWyoQRx13tyKziHtXWDCUUgok= github.com/DATA-DOG/godog v0.7.13/go.mod h1:z2OZ6a3X0/YAKVqLfVzYBwFt3j6uSt3Xrqa7XTtcQE0= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/akutz/gosync v0.1.0 h1:naxPT/aDYDh79PMwM3XmencmNQeYmpNFSZy4ZE9zIW0= github.com/akutz/gosync v0.1.0/go.mod h1:I8I4aiqJI1nqaeYOOB1WS+CgRJVVPqhct9Y4njywM84= github.com/akutz/memconn v0.1.0/go.mod h1:Jo8rI7m0NieZyLI5e2CDlRdRqRRB4S7Xp77ukDjH+Fw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/container-storage-interface/spec v1.1.0 h1:qPsTqtR1VUPvMPeK0UnCZMtXaKGyyLPG8gj/wG6VqMs= github.com/container-storage-interface/spec v1.1.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= github.com/container-storage-interface/spec v1.2.0 h1:bD9KIVgaVKKkQ/UbVUY9kCaH/CJbhNxe0eeB4JeJV2s= @@ -19,9 +46,14 @@ github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93C github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190612170431-362f06ec6bc1/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,23 +61,44 @@ github.com/dell/gobrick v1.0.0 h1:/l5uRqFxmrTBnNtswj3jm1uSsBxUK0y0RqtzhpoO8g0= github.com/dell/gobrick v1.0.0/go.mod h1:pYN9r3XvIjct/QkEg5mEM+k2L3QBLVaHUZeAMzQgwRg= github.com/dell/gofsutil v1.2.0 h1:FLvXjNm/mA7y0zpIVgzU61wYIJmNd4VNj8PuY7AR2kw= github.com/dell/gofsutil v1.2.0/go.mod h1:48eHpMRl0+07uGEnQ7/RE6pTOAVEl74utlGjd0QX/Os= -github.com/dell/goiscsi v1.0.0 h1:z3hXDIUiVYrrqksWJfJ1mI8Gx6mhQrBidi/LAJwIAyM= -github.com/dell/goiscsi v1.0.0/go.mod h1:MfuMjbKWsh/MOb0VDW20C+LFYRIOfWKGiAxWkeM5TKo= -github.com/dell/goiscsi v1.1.0 h1:ByULW5hzYnDLCEC/7E2B03KhTLt/RpeMIwfGszmTe7U= +github.com/dell/gofsutil v1.3.0 h1:6iDzLAdvrusB5p1yxsW45D2bC9+PUX64tJhH3tgGBN8= +github.com/dell/gofsutil v1.3.0/go.mod h1:48eHpMRl0+07uGEnQ7/RE6pTOAVEl74utlGjd0QX/Os= +github.com/dell/goiscsi v1.1.0 h1:0/eHKWhEjuk1AFfyBtiOqY4acW1HrC7FUyB++n2S520= github.com/dell/goiscsi v1.1.0/go.mod h1:MfuMjbKWsh/MOb0VDW20C+LFYRIOfWKGiAxWkeM5TKo= -github.com/dell/gounity v1.2.1 h1:HI7co+i5EYYykpwMmbTRw8bQfoO4+61ZgabijPh+fug= -github.com/dell/gounity v1.2.1/go.mod h1:es7wIQepk+bz5UgDS5Foxv37bCf/0hW5OKAWovBnNp4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -53,51 +106,189 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.1/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.4/go.mod h1:oCXIBxdI62A4cR6aTRJCgetEjecSIYzOEaeAn4iYEpM= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.12.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rexray/gocsi v1.1.0 h1:MkstGTZ1x4uf9AtwhOwzovYYYkPM5ZCRFU8ek9+rAy0= github.com/rexray/gocsi v1.1.0/go.mod h1:kr6L70GxUU6Gu8ehq2dWQmwdILR1tmE05c/OYaTvlx0= github.com/rexray/gocsi v1.2.1 h1:9e15bmlOLxgEVi2MyruU0dxLotULoE4g/zimPsqEkEM= github.com/rexray/gocsi v1.2.1/go.mod h1:5V3YEu+6P8HFTSzUjldYM1abIb/4mLnW/3qWzu8yD0Y= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v0.0.0-20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -106,67 +297,152 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/thecodeteam/gosync v0.1.0/go.mod h1:43QHsngcnWc8GE1aCmi7PEypslflHjCzXFleuWKEb00= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20171023145632-2509b142fb2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20171028101351-661970f62f58/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= @@ -174,3 +450,4 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/helm/README.md b/helm/README.md deleted file mode 100644 index 6c04cd5..0000000 --- a/helm/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Dell EMC Unity Helm Chart for Kubernetes - -For detailed installation instructions, please check the doc directory - -The general outline is: - - 1. Satisfy the pre-requsites outlined in the Release and Installation Notes in the doc directory. - - 2. Copy the `csi-unity/values.yaml` to a file `myvalues.yaml` in this directory and fill in various installation parameters. - - 3. Invoke the `install.unity` shell script which deploys the helm chart in csi-unity. \ No newline at end of file diff --git a/helm/common.bash b/helm/common.bash deleted file mode 100644 index 6dd2833..0000000 --- a/helm/common.bash +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -# Verify kubeadm and kubectl present -kubectl --help >&/dev/null || { - echo "kubectl required for installation... exiting"; exit 2 -} -kubeadm --help >&/dev/null || { - echo "kubeadm required for installation... exiting"; exit 2 -} - -waitOnRunning() { - TARGET=$(kubectl get pods -n ${NS} | grep ${NS} | wc -l) - RUNNING=0 - while [ $RUNNING -ne $TARGET ]; - do - sleep 10 - TARGET=$(kubectl get pods -n ${NS} | grep ${NS} | wc -l) - RUNNING=$(kubectl get pods -n ${NS} | grep "Running" | wc -l) - date - echo running $RUNNING / $TARGET - kubectl get pods -n ${NS} - done -} - -# Get the kubernetes major and minor version numbers. -kMajorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Major:"//' -e 's/",.*//') -kMinorVersion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*Minor:"//' -e 's/",.*//') - diff --git a/helm/csi-unity/Chart.yaml b/helm/csi-unity/Chart.yaml index 2b01ab1..c8bb0ca 100644 --- a/helm/csi-unity/Chart.yaml +++ b/helm/csi-unity/Chart.yaml @@ -1,6 +1,6 @@ name: csi-unity -version: 1.2.1 -appVersion: 1.2.1 +version: 1.3.0 +appVersion: 1.3.0 description: | Unity CSI (Container Storage Interface) driver Kubernetes integration. This chart includes everything required to provision via CSI as diff --git a/helm/csi-unity/driver-image.yaml b/helm/csi-unity/driver-image.yaml new file mode 100644 index 0000000..f53057b --- /dev/null +++ b/helm/csi-unity/driver-image.yaml @@ -0,0 +1,4 @@ +# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. +images: + # "images.driver" defines the container images used for the driver container. + driver: dellemc/csi-unity:v1.3.0.000R diff --git a/helm/csi-unity/k8s-1.16-values.yaml b/helm/csi-unity/k8s-1.16-values.yaml index 56123dc..ef9d66b 100644 --- a/helm/csi-unity/k8s-1.16-values.yaml +++ b/helm/csi-unity/k8s-1.16-values.yaml @@ -8,12 +8,15 @@ images: # "images.provisioner" defines the container images used for the csi provisioner # container. - provisioner: quay.io/k8scsi/csi-provisioner:v1.4.0 + provisioner: quay.io/k8scsi/csi-provisioner:v1.4.0 # "images.snapshotter" defines the container image used for the csi snapshotter snapshotter: quay.io/k8scsi/csi-snapshotter:v1.2.2 # "images.registrar" defines the container images used for the csi registrar # container. - registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + # "images.resizer" defines the container images used for the csi resizer + # container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-unity/k8s-1.14-values.yaml b/helm/csi-unity/k8s-1.17-values.yaml similarity index 62% rename from helm/csi-unity/k8s-1.14-values.yaml rename to helm/csi-unity/k8s-1.17-values.yaml index b267b3f..7a95aa7 100644 --- a/helm/csi-unity/k8s-1.14-values.yaml +++ b/helm/csi-unity/k8s-1.17-values.yaml @@ -1,20 +1,22 @@ # IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. -kubeversion: "v1.14" +kubeversion: "v1.17" images: # "images.attacher" defines the container images used for the csi attacher # container. - attacher: quay.io/k8scsi/csi-attacher:v1.2.1 + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 # "images.provisioner" defines the container images used for the csi provisioner # container. - #provisioner: quay.io/k8scsi/csi-provisioner:v0.4.2 #for CSI 0.3.0 only (obsolete) - provisioner: quay.io/k8scsi/csi-provisioner:v1.2.1 + provisioner: quay.io/k8scsi/csi-provisioner:v1.5.0 # "images.snapshotter" defines the container image used for the csi snapshotter - snapshotter: quay.io/k8scsi/csi-snapshotter:v1.2.2 + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 # "images.registrar" defines the container images used for the csi registrar # container. registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + # "images.resizer" defines the container images used for the csi resizer + # container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-unity/k8s-1.18-values.yaml b/helm/csi-unity/k8s-1.18-values.yaml new file mode 100644 index 0000000..0bb2343 --- /dev/null +++ b/helm/csi-unity/k8s-1.18-values.yaml @@ -0,0 +1,22 @@ +# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. +kubeversion: "v1.18" + +images: + # "images.attacher" defines the container images used for the csi attacher + # container. + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 + + # "images.provisioner" defines the container images used for the csi provisioner + # container. + provisioner: quay.io/k8scsi/csi-provisioner:v1.6.0 + + # "images.snapshotter" defines the container image used for the csi snapshotter + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 + + # "images.registrar" defines the container images used for the csi registrar + # container. + registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + + # "images.resizer" defines the container images used for the csi resizer + # container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-unity/k8s-1.19-values.yaml b/helm/csi-unity/k8s-1.19-values.yaml new file mode 100644 index 0000000..83281e8 --- /dev/null +++ b/helm/csi-unity/k8s-1.19-values.yaml @@ -0,0 +1,22 @@ +# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. +kubeversion: "v1.19" + +images: + # "images.attacher" defines the container images used for the csi attacher + # container. + attacher: quay.io/k8scsi/csi-attacher:v2.2.0 + + # "images.provisioner" defines the container images used for the csi provisioner + # container. + provisioner: quay.io/k8scsi/csi-provisioner:v1.6.0 + + # "images.snapshotter" defines the container image used for the csi snapshotter + snapshotter: quay.io/k8scsi/csi-snapshotter:v2.1.1 + + # "images.registrar" defines the container images used for the csi registrar + # container. + registrar: quay.io/k8scsi/csi-node-driver-registrar:v1.2.0 + + # "images.resizer" defines the container images used for the csi resizer + # container. + resizer: quay.io/k8scsi/csi-resizer:v0.5.0 diff --git a/helm/csi-unity/templates/controller.yaml b/helm/csi-unity/templates/controller.yaml index 5226fe3..32a1e07 100644 --- a/helm/csi-unity/templates/controller.yaml +++ b/helm/csi-unity/templates/controller.yaml @@ -49,6 +49,13 @@ rules: - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] verbs: ["create", "list", "watch", "delete"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotcontents/status"] + verbs: ["update"] + # below for resizer + - apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update", "patch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 @@ -124,6 +131,17 @@ spec: volumeMounts: - name: socket-dir mountPath: /var/run/csi + - name: resizer + image: {{ required "Must provide the CSI resizer container image." .Values.images.resizer }} + args: + - "--csi-address=$(ADDRESS)" + - "--v=5" + env: + - name: ADDRESS + value: /var/run/csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /var/run/csi - name: driver image: {{ required "Must provide the Unity driver container image." .Values.images.driver }} args: diff --git a/helm/csi-unity/templates/node.yaml b/helm/csi-unity/templates/node.yaml index 6a12255..945ff74 100644 --- a/helm/csi-unity/templates/node.yaml +++ b/helm/csi-unity/templates/node.yaml @@ -74,7 +74,8 @@ spec: - name: driver-path mountPath: /var/lib/kubelet/plugins/unity.emc.dell.com - name: volumedevices-path - mountPath: /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices + mountPath: /var/lib/kubelet/plugins/kubernetes.io/csi/pv + mountPropagation: "Bidirectional" - name: pods-path mountPath: /var/lib/kubelet/pods mountPropagation: "Bidirectional" @@ -117,7 +118,7 @@ spec: type: DirectoryOrCreate - name: volumedevices-path hostPath: - path: /var/lib/kubelet/plugins/kubernetes.io/csi/volumeDevices + path: /var/lib/kubelet/plugins/kubernetes.io/csi/pv type: DirectoryOrCreate - name: pods-path hostPath: diff --git a/helm/csi-unity/templates/storageclass.yaml b/helm/csi-unity/templates/storageclass.yaml index 8b460a4..f3b8f84 100644 --- a/helm/csi-unity/templates/storageclass.yaml +++ b/helm/csi-unity/templates/storageclass.yaml @@ -14,6 +14,7 @@ metadata: {{- end }} provisioner: csi-unity.dellemc.com reclaimPolicy: {{ $v.storageClass.reclaimPolicy | default $global.Values.storageClass.reclaimPolicy | quote }} +allowVolumeExpansion: true parameters: protocol: FC arrayId: {{ required "Must provide a arrayId" $v.name | quote }} @@ -36,6 +37,7 @@ metadata: {{- end }} provisioner: csi-unity.dellemc.com reclaimPolicy: {{ $v.storageClass.reclaimPolicy | default $global.Values.storageClass.reclaimPolicy | quote }} +allowVolumeExpansion: true parameters: protocol: iSCSI arrayId: {{ required "Must provide a arrayId" $v.name | quote }} @@ -59,6 +61,7 @@ metadata: {{- end }} provisioner: csi-unity.dellemc.com reclaimPolicy: {{ $v.storageClass.reclaimPolicy | default $global.Values.storageClass.reclaimPolicy | quote }} +allowVolumeExpansion: true parameters: protocol: NFS arrayId: {{ required "Must provide a arrayId" $v.name | quote }} diff --git a/helm/csi-unity/templates/volumesnapshotclass.yaml b/helm/csi-unity/templates/volumesnapshotclass.yaml index 84a98fc..22348e0 100644 --- a/helm/csi-unity/templates/volumesnapshotclass.yaml +++ b/helm/csi-unity/templates/volumesnapshotclass.yaml @@ -1,6 +1,10 @@ {{ $global := . }} {{- range $i, $v := .Values.storageArrayList }} +{{- if eq $global.Values.kubeversion "v1.16" }} apiVersion: snapshot.storage.k8s.io/v1alpha1 +{{- else }} +apiVersion: snapshot.storage.k8s.io/v1beta1 +{{- end }} kind: VolumeSnapshotClass metadata: {{- if $v.isDefaultArray }} @@ -10,7 +14,12 @@ metadata: {{ else }} name: {{ "unity" }}-{{ $v.name | lower }}-snapclass {{- end }} +{{- if eq $global.Values.kubeversion "v1.16" }} snapshotter: csi-unity.dellemc.com +{{- else }} +driver: csi-unity.dellemc.com +deletionPolicy: Delete +{{- end }} parameters: retentionDuration: {{ $v.snapshotClass.retentionDuration | default "" | quote }} --- diff --git a/helm/csi-unity/values.yaml b/helm/csi-unity/values.yaml index 265f20f..d43f66c 100644 --- a/helm/csi-unity/values.yaml +++ b/helm/csi-unity/values.yaml @@ -1,4 +1,5 @@ # Represents number of certificate secrets, which user is going to create for ssl authentication. (unity-cert-0..unity-cert-n) +# Minimum value should be 1 certSecretCount: 1 # Time interval to add node info to array. Default 15 minutes. Minimum value should be 1. @@ -70,7 +71,4 @@ storageClassProtocols: - protocol: "NFS" - protocol: "iSCSI" -# IT IS RECOMMENDED YOU DO NOT CHANGE THE IMAGES TO BE DOWNLOADED. -images: - # "images.driver" defines the container images used for the driver container. - driver: dellemc/csi-unity:v1.2.1.000R \ No newline at end of file + diff --git a/helm/install.unity b/helm/install.unity deleted file mode 100755 index 3ef84ae..0000000 --- a/helm/install.unity +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -NS="unity" - -# Use relative path of script invocation -cd "`dirname \"$0\"`" - -source ./common.bash - -# Only k8s 1.14 and k8s 1.16 are supported -if ! [ ${kMajorVersion} -eq 1 -a \( ${kMinorVersion} -eq 14 -o ${kMinorVersion} -eq 16 \) ] -then - echo "Only Kubernetes 1.14 and 1.16 versions are supported" - exit 0 -fi - -# Verify the kubernetes installation has the feature gates needed. -sh ./verify.kubernetes -rc=$? -if [ $rc -ne 0 ] -then - echo "*******************************************************************************" - echo "Warning: Kubernetes --feature-gates not correctly configured... it may not work" - echo "*******************************************************************************" - sleep 5 -fi - -# Check if unity-certs-0 exists. If not, then create it -kubectl get secrets -n "$NS" | grep unity-certs-0 --quiet -if [ $? -ne 0 ]; - then echo "*** Couldn't find unity-certs. Creating an empty secret. Delete it and re-create it if you want to validate unisphere certificates ***" - kubectl create -f ./emptysecret.yaml -fi - -kubectl get customresourcedefinitions | grep snapshot --quiet -if [ $? -ne 0 ] -then - echo "installing snapshot CRD"; kubectl create -f snapshot-crd.yaml -fi - -helm version | grep "v3." --quiet -if [ $? -eq 0 ] -then - echo "Installing using helm version 3" - helm install unity --values myvalues.yaml --values csi-unity/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml -n "$NS" ./csi-unity -else - echo "Installing using helm version 2" - helm install --values myvalues.yaml --values csi-unity/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml --name unity --namespace unity ./csi-unity -fi - -waitOnRunning - -echo "CSIDrivers:" -kubectl get csidrivers -echo "CSINodes:" -kubectl get csinode -echo "StorageClasses:" -kubectl get storageclass - diff --git a/helm/snapshot-crd.yaml b/helm/snapshot-crd-v1alpha1.yaml similarity index 100% rename from helm/snapshot-crd.yaml rename to helm/snapshot-crd-v1alpha1.yaml diff --git a/helm/uninstall.unity b/helm/uninstall.unity deleted file mode 100755 index d308eb6..0000000 --- a/helm/uninstall.unity +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -lifecyclePresent=$(kubectl get daemonset unity-node -n unity -o yaml | grep -c lifecycle) -if [ $lifecyclePresent -gt 0 ]; then - echo "Removing lifecycle hooks from daemonset" - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "replace", "path": "/spec/updateStrategy", "type":"OnDelete"}]' - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/lifecycle"}]' - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/1/lifecycle"}]' - sleep 5 - kubectl delete pod -l app=unity-node -n unity --force --grace-period=0 -fi - -helm version | grep "v3." --quiet -if [ $? -eq 0 ] -then - echo "Uninstalling using helm version 3" - helm delete -n unity unity -else - echo "Uninstalling using helm version 2" - helm delete --purge unity -fi - -sleep 10 -kubectl get pods -n unity diff --git a/helm/upgrade.unity b/helm/upgrade.unity deleted file mode 100755 index bde12dc..0000000 --- a/helm/upgrade.unity +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -NS="unity" - -# Use relative path of script invocation -cd "`dirname \"$0\"`" - -source ./common.bash -# Verify the kubernetes installation has the feature gates needed. -sh ./verify.kubernetes - -# Check if unity-certs-0 exists. If not, then create it -kubectl get secrets -n "$NS" | grep unity-certs-0 --quiet -if [ $? -ne 0 ]; - then echo "*** Couldn't find unity-certs. Creating an empty secret. Delete it and re-create it if you want to validate unisphere certificates ***" - kubectl create -f ./emptysecret.yaml -fi - -kubectl get customresourcedefinitions | grep snapshot --quiet -if [ $? -ne 0 ] -then - echo "installing snapshot CRD"; kubectl create -f snapshot-crd.yaml -fi - -lifecyclePresent=$(kubectl get daemonset unity-node -n unity -o yaml | grep -c lifecycle) -echo "lifecycle present :${lifecyclePresent}" -if [ $lifecyclePresent -gt 0 ]; then - echo "Removing lifecycle hooks from daemonset" - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "replace", "path": "/spec/updateStrategy", "type":"OnDelete"}]' - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/0/lifecycle"}]' - kubectl patch daemonset unity-node -n unity --type json -p='[{"op": "remove", "path": "/spec/template/spec/containers/1/lifecycle"}]' - sleep 5 - kubectl delete pod -l app=unity-node -n unity --force --grace-period=0 - waitOnRunning -fi - -helm version | grep "v3." --quiet -if [ $? -eq 0 ] -then - echo "Upgrading using helm version 3" - helm upgrade --values myvalues.yaml --values csi-unity/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml --namespace "$NS" unity ./csi-unity -else - echo "Upgrading using helm version 2" - kubectl delete csidriver unity - helm upgrade --values myvalues.yaml --values csi-unity/k8s-${kMajorVersion}.${kMinorVersion}-values.yaml unity --namespace unity ./csi-unity -fi - -waitOnRunning - -echo "CSIDrivers:" -kubectl get csidrivers -echo "CSINodes:" -kubectl get csinode -echo "StorageClasses:" -kubectl get storageclass diff --git a/helm/verify.kubernetes b/helm/verify.kubernetes deleted file mode 100755 index 3ff3756..0000000 --- a/helm/verify.kubernetes +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -# Determine the kubernetes version -kubeversion=$(kubectl version | grep 'Server Version' | sed -e 's/^.*GitVersion:"//' -e 's/",.*//') -echo Kubernetes version $kubeversion - -# Determine the nodes -MINION_NODES=$(kubectl get nodes -o wide | grep -v -e master -e INTERNAL | awk ' { print $6; }') -MASTER_NODES=$(kubectl get nodes -o wide | awk ' /master/{ print $6; }') -echo Kubernetes master nodes: $MASTER_NODES -echo Kubernetes minion nodes: $MINION_NODES - -# Variables used for verification -FEATURE_GATES="VolumeSnapshotDataSource=true" -MASTER_PROCS="/kubelet kube-apiserver kube-scheduler kube-controller-manager" -MINION_PROCS="/kubelet" -fail=0 - -echo Verifying the feature gates. -for node in $MASTER_NODES -do - echo ssh $node ps -ef >.ps.out - ssh $node ps -ef >.ps.out - for gate in $FEATURE_GATES - do - #echo checking $node for $gate ... - for proc in $MASTER_PROCS - do - #echo proc $proc - count=$(grep $proc .ps.out | grep -c $gate) - #echo $node $gate $proc $count - [ $count -ne "1" ] && { echo "node $node proc $proc gate $gate failed"; fail=1; } - done - done -done - -for node in $MINION_NODES -do - echo ssh $node ps -ef >.ps.out - ssh $node ps -ef >.ps.out - for gate in $FEATURE_GATES - do - #echo checking $node for $gate ... - for proc in $MINION_PROCS - do - #echo proc $proc - count=$(grep $proc .ps.out | grep -c $gate) - #echo $node $gate $proc $count - [ $count -ne "1" ] && { echo "node $node proc $proc gate $gate failed"; fail=1; } - done - done -done - -exit $fail diff --git a/licenses/LICENSE b/licenses/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/licenses/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/service/controller.go b/service/controller.go index 536cc68..a75e111 100644 --- a/service/controller.go +++ b/service/controller.go @@ -6,12 +6,13 @@ package service import ( "fmt" + "strconv" + "strings" + "github.com/dell/gounity/api" "github.com/dell/gounity/util" "github.com/golang/protobuf/ptypes" "github.com/golang/protobuf/ptypes/timestamp" - "strconv" - "strings" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/dell/csi-unity/service/utils" @@ -132,23 +133,28 @@ func (s *service) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest thin, err := strconv.ParseBool(params[keyThinProvisioned]) if err != nil { thin = true - log.Debugf("Parameter %s is set to [%s]", keyThinProvisioned, thin) + log.Debugf("Parameter %s is set to [%t]", keyThinProvisioned, thin) } dataReduction, err := strconv.ParseBool(params[keyDataReductionEnabled]) if err != nil { - log.Debugf("Parameter %s is set to [%s]", keyDataReductionEnabled, dataReduction) + log.Debugf("Parameter %s is set to [%t]", keyDataReductionEnabled, dataReduction) } - tieringPolicy, err := strconv.ParseInt(params[keyTieringPolicy], 0, 32) + tieringPolicy, err := strconv.ParseInt(params[keyTieringPolicy], 0, 64) if err != nil { tieringPolicy = 0 - log.Debugf("Parameter %s is set to [%s]", keyTieringPolicy, tieringPolicy) + log.Debugf("Parameter %s is set to [%d]", keyTieringPolicy, tieringPolicy) } hostIOLimitName := strings.TrimSpace(params[keyHostIOLimitName]) - unity, err := s.getUnityClient(arrayId) + hostIoSize, err := strconv.ParseInt(params[keyHostIoSize], 0, 64) + if err != nil { + hostIoSize = 8192 + } + + unity, err := s.getUnityClient(ctx, arrayId) if err != nil { return nil, err } @@ -157,8 +163,147 @@ func (s *service) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest contentSource := req.GetVolumeContentSource() if contentSource != nil { volumeSource := contentSource.GetVolume() + if volumeSource != nil { - return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Volume clone is not supported")) + sourceVolId := volumeSource.VolumeId + sourceVolId, _, sourceArrayId, _, err := s.validateAndGetResourceDetails(ctx, volumeSource.VolumeId, volumeType) + if err != nil { + return nil, err + } + if sourceVolId == "" { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume ID cannot be empty")) + } + + log.Debugf("Cloning Volume: %s", sourceVolId) + if arrayId != sourceArrayId { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume array id: %s is different than required volume array id: %s", sourceArrayId, arrayId)) + } + if protocol == NFS { + + snapApi := gounity.NewSnapshot(unity) + fileAPI := gounity.NewFilesystem(unity) + filesystem, err := fileAPI.FindFilesystemById(ctx, sourceVolId) + isSnapshot := false + var snapResp *types.Snapshot + var snapErr error + if err != nil { + //Filesystem not found - Check if PVC exists as a snapshot [Cloned volume in case of NFS] + snapResp, snapErr = snapApi.FindSnapshotById(ctx, sourceVolId) + if snapErr != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find source filesystem: %s Failed. Error: %v ", sourceVolId, err)) + } + isSnapshot = true + filesystem, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayId) + if err != nil { + return nil, err + } + } + + err = validateCreateFsFromSnapshot(ctx, filesystem, storagePool, tieringPolicy, hostIoSize, thin, dataReduction) + if err != nil { + return nil, err + } + + if isSnapshot { + // Validate the size parameter + snapSize := int64(snapResp.SnapshotContent.Size - AdditionalFilesystemSize) + if snapSize != size { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d should be same as source filesystem size %d", size, snapSize)) + } + //Idempotency check + snapResp, err := snapApi.FindSnapshotByName(ctx, volName) + if snapResp == nil { + //Create Volume from Snapshot(Copy snapshot on array) + snapResp, err = s.createFilesystemFromSnapshot(ctx, sourceVolId, volName, arrayId) + if err != nil { + return nil, err + } + } else if snapResp.SnapshotContent.Size != int64(size+AdditionalFilesystemSize) { + return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Snapshot with same name %s already exists in different size.", volName)) + } + snapResp.SnapshotContent.Size -= AdditionalFilesystemSize + csiVolResp := utils.GetVolumeResponseFromSnapshot(snapResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } else { + fsSize := int64(filesystem.FileContent.SizeTotal - AdditionalFilesystemSize) + if size != fsSize { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d should be same as source volume size %d", + size, fsSize)) + } + + snap, err := s.createIdempotentSnapshot(ctx, req.Name, sourceVolId, desc, "", protocol, arrayId, true) + if err != nil { + return nil, err + } + csiVolResp := utils.GetVolumeResponseFromSnapshot(snap, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + } else { + + volumeApi := gounity.NewVolume(unity) + sourceVolResp, err := volumeApi.FindVolumeById(ctx, sourceVolId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source volume not found: %s. Error: %v", sourceVolId, err)) + } + // Validate the size parameter + if int64(sourceVolResp.VolumeContent.SizeTotal) != size { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d should be same as source volume size %d", + size, int64(sourceVolResp.VolumeContent.SizeTotal))) + } + // Validate the storagePool parameter + if sourceVolResp.VolumeContent.Pool.Id != storagePool { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume storage pool %s is different than the requested storage pool %s", + sourceVolResp.VolumeContent.Pool.Id, storagePool)) + } + //Validate the thinProvisioned parameter + if sourceVolResp.VolumeContent.IsThinEnabled != thin { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume thin provision %v is different than the requested thin provision %v", + sourceVolResp.VolumeContent.IsThinEnabled, thin)) + } + //Validate the dataReduction parameter + if sourceVolResp.VolumeContent.IsDataReductionEnabled != dataReduction { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume data reduction %v is different than the requested data reduction %v", + sourceVolResp.VolumeContent.IsDataReductionEnabled, dataReduction)) + } + //Validate the tieringPolicy parameter + if int64(sourceVolResp.VolumeContent.TieringPolicy) != tieringPolicy { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume tiering policy %v is different than the requested tiering policy %v", + sourceVolResp.VolumeContent.TieringPolicy, tieringPolicy)) + } + + volResp, _ := volumeApi.FindVolumeByName(ctx, volName) + if volResp != nil { + //Idempotency Check + if volResp.VolumeContent.IsThinClone && len(volResp.VolumeContent.ParentVolume.Id) > 0 && volResp.VolumeContent.ParentVolume.Id == sourceVolId && + volResp.VolumeContent.SizeTotal == sourceVolResp.VolumeContent.SizeTotal { + log.Infof("Volume %s exists in the requested state as a clone of volume %s", volName, sourceVolResp.VolumeContent.Name) + csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Volume with same name %s already exists", volName)) + } + + //Perform volume cloning + volResp, err = volumeApi.CreateCloneFromVolume(ctx, volName, sourceVolId) + if err != nil { + if err == gounity.CreateSnapshotFailedError { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Unable to Create Snapshot for Volume Cloning for source volume: %s", sourceVolId)) + } else if err == gounity.CloningFailedError { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Volume cloning for source volume: %s failed.", sourceVolId)) + } + } + + volResp, err = volumeApi.FindVolumeByName(ctx, volName) + if volResp != nil { + csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Volume not found after create. %v", err)) + } } snapshotSource := contentSource.GetSnapshot() if snapshotSource != nil { @@ -166,106 +311,147 @@ func (s *service) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest if snapId == "" { return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source snapshot ID cannot be empty")) } - snapId, _, _, _, err := s.validateAndGetResourceDetails(ctx, snapId, snapshotType) + snapId, _, sourceArrayId, _, err := s.validateAndGetResourceDetails(ctx, snapId, snapshotType) if err != nil { return nil, err } - if protocol == NFS { - return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Create Volume from snapshot not supported for NFS protocol")) - } - log.Debugf("Creating the volume from snapshot: %s", snapId) + if arrayId != sourceArrayId { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source snapshot array id: %s is different than required volume array id: %s", sourceArrayId, arrayId)) + } snapApi := gounity.NewSnapshot(unity) snapResp, err := snapApi.FindSnapshotById(ctx, snapId) if err != nil { return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source snapshot not found: %s", snapId)) } - volumeApi := gounity.NewVolume(unity) - volId := snapResp.SnapshotContent.StorageResource.Id - volId, _, _, _, err = s.validateAndGetResourceDetails(ctx, volId, volumeType) - if err != nil { - return nil, err - } + if protocol == NFS { - sourceVolResp, err := volumeApi.FindVolumeById(ctx, volId) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source volume not found: %s", volId)) - } - // Validate the size is the same. - if int64(sourceVolResp.VolumeContent.SizeTotal) != size { - return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d is incompatible with source volume size %d", - size, int64(sourceVolResp.VolumeContent.SizeTotal))) - } + sourceFilesystemResp, err := s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayId) + if err != nil { + return nil, err + } - // Validate the storagePool is the same. - if sourceVolResp.VolumeContent.Pool.Id != storagePool { - return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume storage pool %s is different than the requested storage pool %s", - sourceVolResp.VolumeContent.Pool.Id, storagePool)) - } + err = validateCreateFsFromSnapshot(ctx, sourceFilesystemResp, storagePool, tieringPolicy, hostIoSize, thin, dataReduction) + if err != nil { + return nil, err + } + // Validate the size parameter + snapSize := int64(snapResp.SnapshotContent.Size - AdditionalFilesystemSize) + if snapSize != size { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d should be same as source snapshot size %d", size, snapSize)) + } - //Validate the thinProvisioned parameter - if sourceVolResp.VolumeContent.IsThinEnabled != thin { - return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume thin provision %v is different than the requested thin provision %v", - sourceVolResp.VolumeContent.IsThinEnabled, thin)) - } + snapshotApi := gounity.NewSnapshot(unity) + snapResp, err := snapshotApi.FindSnapshotByName(ctx, volName) + if snapResp != nil { + //Idempotency check + if snapResp.SnapshotContent.ParentSnap.Id == snapId && snapResp.SnapshotContent.AccessType == int(gounity.ProtocolAccessType) { + log.Infof("Filesystem %s exists in the requested state as a volume from snapshot(snapshot on array) %s", volName, snapId) + snapResp.SnapshotContent.Size -= AdditionalFilesystemSize + csiVolResp := utils.GetVolumeResponseFromSnapshot(snapResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Filesystem with same name %s already exists", volName)) + } - //Validate the dataReduction parameter - if sourceVolResp.VolumeContent.IsDataReductionEnabled != dataReduction { - return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume data reduction %v is different than the requested data reduction %v", - sourceVolResp.VolumeContent.IsDataReductionEnabled, dataReduction)) - } + //Create Volume from Snapshot(Copy snapshot on array) + snapResp, err = s.createFilesystemFromSnapshot(ctx, snapId, volName, arrayId) + if err != nil { + return nil, err + } - volResp, _ := volumeApi.FindVolumeByName(ctx, volName) - if volResp != nil { - //Idempotency Check - if volResp.VolumeContent.IsThinClone == true && len(volResp.VolumeContent.ParentSnap.Id) > 0 && volResp.VolumeContent.ParentSnap.Id == snapId { - log.Info("Volume exists in the requested state") - csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) + if snapResp != nil { + snapResp.SnapshotContent.Size -= AdditionalFilesystemSize + csiVolResp := utils.GetVolumeResponseFromSnapshot(snapResp, arrayId, protocol) csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() return csiVolResp, nil } - return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Volume with same name %s already exists", volName)) - } - - if snapResp.SnapshotContent.IsAutoDelete == true { - err = snapApi.ModifySnapshotAutoDeleteParameter(ctx, snapId) + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Filesystem: %s not found after create. Error: %v", volName, err)) + } else { + volId := snapResp.SnapshotContent.StorageResource.Id + volumeApi := gounity.NewVolume(unity) + sourceVolResp, err := volumeApi.FindVolumeById(ctx, volId) if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Unable to modify auto-delete parameter for snapshot %s", snapId)) + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source volume not found: %s", volId)) } - } - volResp, err = volumeApi.CreteLunThinClone(ctx, volName, snapId, volId) - if err != nil { - return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create volume from snapshot failed with error %v", err)) - } - volResp, err = volumeApi.FindVolumeByName(ctx, volName) - if err != nil { - log.Debugf("Find Volume response: %v Error: %v", volResp, err) - } + // Validate the size parameter + if snapResp.SnapshotContent.Size != size { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Requested size %d should be same as source snapshot size %d", size, snapResp.SnapshotContent.Size)) + } + + // Validate the storagePool is the same. + if sourceVolResp.VolumeContent.Pool.Id != storagePool { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume storage pool %s is different than the requested storage pool %s", + sourceVolResp.VolumeContent.Pool.Id, storagePool)) + } + + //Validate the thinProvisioned parameter + if sourceVolResp.VolumeContent.IsThinEnabled != thin { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume thin provision %v is different than the requested thin provision %v", + sourceVolResp.VolumeContent.IsThinEnabled, thin)) + } + + //Validate the dataReduction parameter + if sourceVolResp.VolumeContent.IsDataReductionEnabled != dataReduction { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume data reduction %v is different than the requested data reduction %v", + sourceVolResp.VolumeContent.IsDataReductionEnabled, dataReduction)) + } - if volResp != nil { - csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) - csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() - return csiVolResp, nil + //Validate the tieringPolicy parameter + if int64(sourceVolResp.VolumeContent.TieringPolicy) != tieringPolicy { + return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source volume tiering policy %v is different than the requested tiering policy %v", + sourceVolResp.VolumeContent.TieringPolicy, tieringPolicy)) + } + + volResp, _ := volumeApi.FindVolumeByName(ctx, volName) + if volResp != nil { + //Idempotency Check + if volResp.VolumeContent.IsThinClone == true && len(volResp.VolumeContent.ParentSnap.Id) > 0 && volResp.VolumeContent.ParentSnap.Id == snapId { + log.Info("Volume exists in the requested state") + csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Volume with same name %s already exists", volName)) + } + + if snapResp.SnapshotContent.IsAutoDelete == true { + err = snapApi.ModifySnapshotAutoDeleteParameter(ctx, snapId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Unable to modify auto-delete parameter for snapshot %s", snapId)) + } + } + + volResp, err = volumeApi.CreteLunThinClone(ctx, volName, snapId, volId) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create volume from snapshot failed with error %v", err)) + } + volResp, err = volumeApi.FindVolumeByName(ctx, volName) + if err != nil { + log.Debugf("Find Volume response: %v Error: %v", volResp, err) + } + + if volResp != nil { + csiVolResp := utils.GetVolumeResponseFromVolume(volResp, arrayId, protocol) + csiVolResp.Volume.ContentSource = req.GetVolumeContentSource() + return csiVolResp, nil + } + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Volume not found after create. %v", err)) } - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Volume not found after create. %v", err)) } } if protocol == NFS { + nasServer, ok := params[keyNasServer] if !ok { return nil, status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "`%s` is a required parameter", keyNasServer)) } - hostIoSize, err := strconv.ParseInt(params[keyHostIoSize], 0, 32) - if err != nil { - log.Debug("Host IO Size for NFS has not been provided and hence setting default value 8192") - hostIoSize = 8192 - } - //Add AdditionalFilesystemSize in size as Unity use this much size for metadata in filesystem size += AdditionalFilesystemSize @@ -368,6 +554,7 @@ func (s *service) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest resp, err = volumeApi.FindVolumeByName(ctx, volName) if resp != nil { volumeResp := utils.GetVolumeResponseFromVolume(resp, arrayId, protocol) + log.Debugf("CreateVolume successful for volid: [%s]", volumeResp.Volume.VolumeId) return volumeResp, nil } } @@ -390,9 +577,32 @@ func (s *service) DeleteVolume( return nil, err } deleteVolumeResp := &csi.DeleteVolumeResponse{} - + var snapErr error //Not validating protocol here to support deletion of pvcs from v1.0 if protocol != NFS { + //Check stale snapshots used for volume cloning and delete if exist + snapshotApi := gounity.NewSnapshot(unity) + snapsResp, _, snapshotErr := snapshotApi.ListSnapshots(ctx, 0, 0, volId, "") + if snapshotErr != nil { + return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "List snapshots for volume %s failed with error: %v", volId, snapshotErr)) + } + totalSnaps := len(snapsResp) + for _, snapResp := range snapsResp { + snapshotName := snapResp.SnapshotContent.Name + if strings.Contains(snapshotName, gounity.SnapForClone) { + reqDeleteSnapshot := new(csi.DeleteSnapshotRequest) + reqDeleteSnapshot.SnapshotId = snapResp.SnapshotContent.ResourceId + _, snapshotErr = s.DeleteSnapshot(ctx, reqDeleteSnapshot) + if snapshotErr != nil { + return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "Volume %s can not be deleted as it has associated snapshots.", volId)) + } + totalSnaps -= 1 + } + } + if totalSnaps > 0 { + return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "Volume %s can not be deleted as it has associated snapshots.", volId)) + } + //Delete the block volume volumeAPI := gounity.NewVolume(unity) err = volumeAPI.DeleteVolume(ctx, volId) } else { @@ -404,14 +614,38 @@ func (s *service) DeleteVolume( return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "Filesystem %s can not be deleted as it has associated NFS or SMB shares.", volId)) } err = fileAPI.DeleteFilesystem(ctx, volId) + } else { + //Do not reuse err as it is used for idempotency check + snapshotApi := gounity.NewSnapshot(unity) + snapResp, fsSnapErr := snapshotApi.FindSnapshotById(ctx, volId) + snapErr = fsSnapErr + if fsSnapErr == nil { + //Validate if snapshot has any nfs shares + sourceVolId, err := fileAPI.GetFilesystemIdFromResId(ctx, snapResp.SnapshotContent.StorageResource.Id) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Source storage resource: %s filesystem Id not found. Error: %v", snapResp.SnapshotContent.StorageResource.Id, err)) + } + filesystemResp, err = fileAPI.FindFilesystemById(ctx, sourceVolId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find source filesystem: %s failed with error: %v", sourceVolId, err)) + } + for _, nfsShare := range filesystemResp.FileContent.NFSShare { + if nfsShare.ParentSnap.Id == volId { + return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "Snapshot %s can not be deleted as it has associated NFS or SMB shares.", volId)) + } + } + err = snapshotApi.DeleteSnapshot(ctx, volId) + } } } //Idempotency check if err == nil { + log.Debugf("DeleteVolume successful for volid: [%s]", req.VolumeId) return deleteVolumeResp, nil - } else if err == gounity.FilesystemNotFoundError || err == gounity.VolumeNotFoundError { + } else if err == gounity.FilesystemNotFoundError || err == gounity.VolumeNotFoundError || snapErr == gounity.SnapshotNotFoundError { log.Debug("Volume not found on array") + log.Debugf("DeleteVolume successful for volid: [%s]", req.VolumeId) return deleteVolumeResp, nil } return nil, status.Error(codes.FailedPrecondition, utils.GetMessageWithRunID(rid, "Delete Volume %s failed with error: %v", volId, err)) @@ -510,29 +744,61 @@ func (s *service) ControllerPublishVolume( if err != nil { return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Export Volume Failed %v", err)) } - + log.Debugf("ControllerPublishVolume successful for volid: [%s]", req.GetVolumeId()) return &csi.ControllerPublishVolumeResponse{PublishContext: pinfo}, nil } else { pinfo["filesystem"] = volID fileAPI := gounity.NewFilesystem(unity) + isSnapshot := false filesystemResp, err := fileAPI.FindFilesystemById(ctx, volID) + var snapResp *types.Snapshot if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find Filesystem Failed with error: %v", err)) + snapshotApi := gounity.NewSnapshot(unity) + snapResp, err = snapshotApi.FindSnapshotById(ctx, volID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find filesystem: %s failed with error: %v", volID, err)) + } + isSnapshot = true + + filesystemResp, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayId) + if err != nil { + return nil, err + } } //Create NFS Share if not already present on array nfsShareName := NFSShareNamePrefix + filesystemResp.FileContent.Name + if isSnapshot { + nfsShareName = NFSShareNamePrefix + snapResp.SnapshotContent.Name + } nfsShareExist := false var nfsShareID string for _, nfsShare := range filesystemResp.FileContent.NFSShare { - if nfsShare.Name == nfsShareName { - nfsShareExist = true - nfsShareID = nfsShare.Id + if isSnapshot { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == volID { + nfsShareExist = true + nfsShareName = nfsShare.Name + nfsShareID = nfsShare.Id + } + } else { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == "" { + nfsShareExist = true + nfsShareName = nfsShare.Name + nfsShareID = nfsShare.Id + } } } if !nfsShareExist { - filesystemResp, err = fileAPI.CreateNFSShare(ctx, nfsShareName, NFSShareLocalPath, volID, gounity.NoneDefaultAccess) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Create NFS Share failed. Error: %v", err)) + if isSnapshot { + nfsShareResp, err := fileAPI.CreateNFSShareFromSnapshot(ctx, nfsShareName, NFSShareLocalPath, volID, gounity.NoneDefaultAccess) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Create NFS Share failed. Error: %v", err)) + } + nfsShareID = nfsShareResp.NFSShareContent.Id + } else { + filesystemResp, err = fileAPI.CreateNFSShare(ctx, nfsShareName, NFSShareLocalPath, volID, gounity.NoneDefaultAccess) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Create NFS Share failed. Error: %v", err)) + } } for _, nfsShare := range filesystemResp.FileContent.NFSShare { if nfsShare.Name == nfsShareName { @@ -542,7 +808,10 @@ func (s *service) ControllerPublishVolume( } //Allocate host access to NFS Share with appropriate access mode - nfsShareResp, _ := fileAPI.FindNFSShareById(ctx, nfsShareID) + nfsShareResp, err := fileAPI.FindNFSShareById(ctx, nfsShareID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find NFS Share: %s failed. Error: %v", nfsShareID, err)) + } readOnlyHosts := nfsShareResp.NFSShareContent.ReadOnlyHosts readWriteHosts := nfsShareResp.NFSShareContent.ReadWriteHosts readOnlyRootHosts := nfsShareResp.NFSShareContent.ReadOnlyRootAccessHosts @@ -607,15 +876,24 @@ func (s *service) ControllerPublishVolume( } if am.Mode == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { readHostIDList = append(readHostIDList, hostID) - err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + if isSnapshot { + err = fileAPI.ModifyNFSShareCreatedFromSnapshotHostAccess(ctx, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + } else { + err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + } } else { readWriteHostIDList = append(readWriteHostIDList, hostID) - err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + if isSnapshot { + err = fileAPI.ModifyNFSShareCreatedFromSnapshotHostAccess(ctx, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + } else { + err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + } } if err != nil { return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Allocating host %s access to NFS Share failed. Error: %v", nodeID, err)) } log.Debugf("NFS Share: %s is accessible to host: %s with access mode: %s", nfsShareID, nodeID, am.Mode) + log.Debugf("ControllerPublishVolume successful for volid: [%s]", req.GetVolumeId()) return &csi.ControllerPublishVolumeResponse{PublishContext: pinfo}, nil } } @@ -673,28 +951,60 @@ func (s *service) ControllerUnpublishVolume( } else { log.Info(fmt.Sprintf("The given Node %s does not have access on the given volume %s. Already in Unpublished state.", hostID, volID)) } - + log.Debugf("ControllerUnpublishVolume successful for volid: [%s]", req.GetVolumeId()) return &csi.ControllerUnpublishVolumeResponse{}, nil } else { fileAPI := gounity.NewFilesystem(unity) + isSnapshot := false filesystem, err := fileAPI.FindFilesystemById(ctx, volID) + var snapResp *types.Snapshot if err != nil { - // If the filesysten isn't found, k8s will retry Controller Unpublish forever so... - // There is no way back if filesystem isn't found and so considering this scenario idempotent - if err == gounity.FilesystemNotFoundError { - log.Debugf("Filesystem %s not found on the array %s during Controller Unpublish. Hence considering the call to be idempotent", volID, arrayId) - return &csi.ControllerUnpublishVolumeResponse{}, nil + snapshotApi := gounity.NewSnapshot(unity) + snapResp, err = snapshotApi.FindSnapshotById(ctx, volID) + if err != nil { + // If the filesysten isn't found, k8s will retry Controller Unpublish forever so... + // There is no way back if filesystem isn't found and so considering this scenario idempotent + if err == gounity.FilesystemNotFoundError || err == gounity.SnapshotNotFoundError { + log.Debugf("Filesystem %s not found on the array %s during Controller Unpublish. Hence considering the call to be idempotent", volID, arrayId) + return &csi.ControllerUnpublishVolumeResponse{}, nil + } + return nil, status.Error(codes.Internal, utils.GetMessageWithRunID(rid, "Find filesystem %s failed with error: %v", volID, err)) + } + isSnapshot = true + filesystem, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayId) + if err != nil { + return nil, err } - return nil, status.Error(codes.Internal, utils.GetMessageWithRunID(rid, "%v", err)) } //Remove host access from NFS Share nfsShareName := NFSShareNamePrefix + filesystem.FileContent.Name + if isSnapshot { + nfsShareName = NFSShareNamePrefix + snapResp.SnapshotContent.Name + } shareExists := false + deleteShare := true var nfsShareID string for _, nfsShare := range filesystem.FileContent.NFSShare { - if nfsShare.Name == nfsShareName { - shareExists = true - nfsShareID = nfsShare.Id + if isSnapshot { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == volID { + shareExists = true + if nfsShare.Name != nfsShareName { + //This means that share was created manually on array, hence don't delete via driver + deleteShare = false + nfsShareName = nfsShare.Name + } + nfsShareID = nfsShare.Id + } + } else { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == "" { + shareExists = true + if nfsShare.Name != nfsShareName { + //This means that share was created manually on array, hence don't delete via driver + deleteShare = false + nfsShareName = nfsShare.Name + } + nfsShareID = nfsShare.Id + } } } if !shareExists { @@ -702,7 +1012,10 @@ func (s *service) ControllerUnpublishVolume( return &csi.ControllerUnpublishVolumeResponse{}, nil } - nfsShareResp, _ := fileAPI.FindNFSShareById(ctx, nfsShareID) + nfsShareResp, err := fileAPI.FindNFSShareById(ctx, nfsShareID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find NFS Share: %s failed. Error: %v", nfsShareID, err)) + } readOnlyHosts := nfsShareResp.NFSShareContent.ReadOnlyHosts readWriteHosts := nfsShareResp.NFSShareContent.ReadWriteHosts readOnlyRootHosts := nfsShareResp.NFSShareContent.ReadOnlyRootAccessHosts @@ -754,9 +1067,17 @@ func (s *service) ControllerUnpublishVolume( return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Cannot remove host access. Host: %s has access on NFS Share: %s with incompatible access mode.", nodeID, nfsShareID)) } if foundReadOnly { - err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + if isSnapshot { + err = fileAPI.ModifyNFSShareCreatedFromSnapshotHostAccess(ctx, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + } else { + err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readHostIDList, gounity.ReadOnlyRootAccessType) + } } else if foundReadWrite { - err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + if isSnapshot { + err = fileAPI.ModifyNFSShareCreatedFromSnapshotHostAccess(ctx, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + } else { + err = fileAPI.ModifyNFSShareHostAccess(ctx, volID, nfsShareID, readWriteHostIDList, gounity.ReadWriteRootAccessType) + } } else { //Idempotent case log.Infof("Host: %s has no access on NFS Share: %s", nodeID, nfsShareID) @@ -767,16 +1088,21 @@ func (s *service) ControllerUnpublishVolume( log.Debugf("Host: %s access is removed from NFS Share: %s", nodeID, nfsShareID) //Delete NFS Share - if otherHostsWithAccess > 0 { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "NFS Share: %s can not be deleted as other hosts have access on it.", nfsShareID)) - } - - err = fileAPI.DeleteNFSShare(ctx, filesystem.FileContent.Id, nfsShareID) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Delete NFS Share: %s Failed with error: %v", nfsShareID, err)) + if deleteShare { + if otherHostsWithAccess > 0 { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "NFS Share: %s can not be deleted as other hosts have access on it.", nfsShareID)) + } + if isSnapshot { + err = fileAPI.DeleteNFSShareCreatedFromSnapshot(ctx, nfsShareID) + } else { + err = fileAPI.DeleteNFSShare(ctx, filesystem.FileContent.Id, nfsShareID) + } + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Delete NFS Share: %s Failed with error: %v", nfsShareID, err)) + } + log.Debugf("NFS Share: %s deleted successfully.", nfsShareID) } - - log.Debugf("NFS Share: %s deleted successfully.", nfsShareID) + log.Debugf("ControllerUnpublishVolume successful for volid: [%s]", req.GetVolumeId()) return &csi.ControllerUnpublishVolumeResponse{}, nil } } @@ -847,48 +1173,22 @@ func (s *service) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotReq } //Source volume is for volume clone or snapshot clone - volId, protocol, arrayId, unity, err := s.validateAndGetResourceDetails(ctx, req.SourceVolumeId, volumeType) + volId, protocol, arrayId, _, err := s.validateAndGetResourceDetails(ctx, req.SourceVolumeId, volumeType) if err != nil { return nil, err } + ctx, log = setArrayIdContext(ctx, arrayId) if err := s.requireProbe(ctx, arrayId); err != nil { return nil, err } - var filesystem *types.Filesystem - fileAPI := gounity.NewFilesystem(unity) - var sourceStorageResId string - if protocol == NFS { - filesystem, err = fileAPI.FindFilesystemById(ctx, volId) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find source filesystem: %s Failed. Error: %v ", volId, err)) - } - sourceStorageResId = filesystem.FileContent.StorageResource.Id - } else { - sourceStorageResId = volId - } - - snapApi := gounity.NewSnapshot(unity) - //Idempotenc check - snap, _ := snapApi.FindSnapshotByName(ctx, req.Name) - if snap != nil { - if snap.SnapshotContent.StorageResource.Id == sourceStorageResId { - log.Infof("Snapshot already exists with same name %s for same storage resource %s", req.Name, req.SourceVolumeId) - return utils.GetSnapshotResponseFromSnapshot(snap, protocol, arrayId), nil - } - return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Snapshot with same name %s already exists for storage resource %s", req.Name, snap.SnapshotContent.StorageResource.Id)) - } - newSnapshot, err := snapApi.CreateSnapshot(ctx, sourceStorageResId, req.Name, req.Parameters["description"], req.Parameters["retentionDuration"]) + //Idempotency check + snap, err := s.createIdempotentSnapshot(ctx, req.Name, volId, req.Parameters["description"], req.Parameters["retentionDuration"], protocol, arrayId, false) if err != nil { - return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create Snapshot error: %v", err)) - } - newSnapshot, _ = snapApi.FindSnapshotByName(ctx, req.Name) - if newSnapshot != nil { - return utils.GetSnapshotResponseFromSnapshot(newSnapshot, protocol, arrayId), nil - } else { - return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Find Snapshot error after create. %v", err)) + return nil, err } + return utils.GetSnapshotResponseFromSnapshot(snap, protocol, arrayId), nil } func (s *service) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error) { @@ -920,11 +1220,59 @@ func (s *service) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotReq } delSnapResponse := &csi.DeleteSnapshotResponse{} + log.Debugf("Delete snapshot successful [%s]", req.SnapshotId) return delSnapResponse, nil } func (s *service) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error) { - return nil, status.Error(codes.Unimplemented, "ListSnapshots is not implemented") + ctx, log, rid := GetRunidLog(ctx) + log.Infof("Executing ListSnapshot with args: %+v", *req) + + var ( + startToken int + err error + maxEntries = int(req.MaxEntries) + ) + snapId, protocol, arrayId, unity, err := s.validateAndGetResourceDetails(ctx, req.SnapshotId, snapshotType) + if err != nil { + return nil, err + } + + ctx, log = setArrayIdContext(ctx, arrayId) + if err := s.requireProbe(ctx, arrayId); err != nil { + return nil, err + } + + snapApi := gounity.NewSnapshot(unity) + + //Limiting the number of snapshots to 100 to avoid timeout issues + if maxEntries > MAX_ENTRIES_SNAPSHOT || maxEntries == 0 { + maxEntries = MAX_ENTRIES_SNAPSHOT + } + + if req.StartingToken != "" { + i, err := strconv.ParseInt(req.StartingToken, 10, 64) + if err != nil { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Unable to parse StartingToken: %v into uint32", req.StartingToken)) + } + startToken = int(i) + } + + snaps, nextToken, err := snapApi.ListSnapshots(ctx, startToken, maxEntries, "", snapId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Unable to get the snapshots: %v", err)) + } + + // Process the source snapshots and make CSI Snapshot + entries, err := s.getCSISnapshots(snaps, req.SourceVolumeId, protocol, arrayId) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, err.Error())) + } + log.Debugf("ListSnapshot successful for snapid: [%s]", req.SnapshotId) + return &csi.ListSnapshotsResponse{ + Entries: entries, + NextToken: strconv.Itoa(nextToken), + }, nil } func (s *service) controllerProbe(ctx context.Context, arrayId string) error { @@ -935,7 +1283,7 @@ func (s *service) controllerProbe(ctx context.Context, arrayId string) error { // Default supports all capabilities func (cs *service) ControllerGetCapabilities(ctx context.Context, req *csi.ControllerGetCapabilitiesRequest) (*csi.ControllerGetCapabilitiesResponse, error) { ctx, log, _ := GetRunidLog(ctx) - log.Debug("Executing ControllerGetCapabilities with args: %+v", *req) + log.Debugf("Executing ControllerGetCapabilities with args: %+v", *req) return &csi.ControllerGetCapabilitiesResponse{ Capabilities: []*csi.ControllerServiceCapability{ &csi.ControllerServiceCapability{ @@ -980,6 +1328,20 @@ func (cs *service) ControllerGetCapabilities(ctx context.Context, req *csi.Contr }, }, }, + &csi.ControllerServiceCapability{ + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_EXPAND_VOLUME, + }, + }, + }, + &csi.ControllerServiceCapability{ + Type: &csi.ControllerServiceCapability_Rpc{ + Rpc: &csi.ControllerServiceCapability_RPC{ + Type: csi.ControllerServiceCapability_RPC_CLONE_VOLUME, + }, + }, + }, }, }, nil } @@ -992,10 +1354,11 @@ func (s *service) ControllerExpandVolume(ctx context.Context, req *csi.Controlle return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "volumeId is mandatory parameter")) } - volId, _, arrayId, unity, err := s.validateAndGetResourceDetails(ctx, req.VolumeId, volumeType) + volId, protocol, arrayId, unity, err := s.validateAndGetResourceDetails(ctx, req.VolumeId, volumeType) if err != nil { return nil, err } + ctx, log = setArrayIdContext(ctx, arrayId) if err := s.requireProbe(ctx, arrayId); err != nil { return nil, err @@ -1011,41 +1374,86 @@ func (s *service) ControllerExpandVolume(ctx context.Context, req *csi.Controlle } } if capacity <= 0 { - return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "required bytes can not be 0 or less")) + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Required bytes can not be 0 or less")) } - volumeApi := gounity.NewVolume(unity) - //Idempotency check - volume, err := volumeApi.FindVolumeById(ctx, volId) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "unable to find the volume")) + expandVolumeResp := &csi.ControllerExpandVolumeResponse{ + CapacityBytes: capacity, } - if volume.VolumeContent.SizeTotal > uint64(capacity) { - return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "requested new capacity smaller than existing capacity")) - } + if protocol == NFS { + //Adding Additional size used for metadata + capacity += AdditionalFilesystemSize + filesystemApi := gounity.NewFilesystem(unity) - volumeResp := &csi.ControllerExpandVolumeResponse{ - CapacityBytes: capacity, - } - if volume.VolumeContent.SizeTotal == uint64(capacity) { - log.Infof("New Volume size (%d) is same as existing Volume size. Ignoring expand volume operation.", volume.VolumeContent.SizeTotal) - volumeResp.NodeExpansionRequired = false - return volumeResp, nil - } + filesystem, err := filesystemApi.FindFilesystemById(ctx, volId) + if err != nil { + snapshotApi := gounity.NewSnapshot(unity) + _, err = snapshotApi.FindSnapshotById(ctx, volId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find filesystem %s failed with error: %v", volId, err)) + } + return nil, status.Error(codes.Unimplemented, utils.GetMessageWithRunID(rid, "Expand Volume not supported for cloned filesystems(snapshot on array)")) + } - err = volumeApi.ExpandVolume(ctx, volId, uint64(capacity)) - if err != nil { - return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "unable to expand volume. Error %v", err)) - } + //Idempotency check + if filesystem.FileContent.SizeTotal >= uint64(capacity) { + log.Infof("New Filesystem size (%d) is same as existing Filesystem size. Ignoring expand volume operation.", filesystem.FileContent.SizeTotal) + expandVolumeResp := &csi.ControllerExpandVolumeResponse{ + CapacityBytes: 0, + } + expandVolumeResp.NodeExpansionRequired = false + return expandVolumeResp, nil + } - volume, err = volumeApi.FindVolumeById(ctx, volId) - if err != nil { - return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "unable to find the volume")) + err = filesystemApi.ExpandFilesystem(ctx, volId, uint64(capacity)) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Expand filesystem failed with error: %v", err)) + } + + filesystem, err = filesystemApi.FindFilesystemById(ctx, volId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find filesystem failed with error: %v", err)) + } + expandVolumeResp.CapacityBytes = int64(filesystem.FileContent.SizeTotal) - AdditionalFilesystemSize + expandVolumeResp.NodeExpansionRequired = false + return expandVolumeResp, err + } else { + volumeApi := gounity.NewVolume(unity) + //Idempotency check + volume, err := volumeApi.FindVolumeById(ctx, volId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find volume failed with error: %v", err)) + } + + nodeExpansionRequired := false + content := volume.VolumeContent + if len(content.HostAccessResponse) >= 1 { //If the volume has 1 or more host access then set nodeExpansionRequired as true + nodeExpansionRequired = true + } + + if volume.VolumeContent.SizeTotal >= uint64(capacity) { + log.Infof("New Volume size (%d) is same as existing Volume size. Ignoring expand volume operation.", volume.VolumeContent.SizeTotal) + expandVolumeResp := &csi.ControllerExpandVolumeResponse{ + CapacityBytes: 0, + } + expandVolumeResp.NodeExpansionRequired = nodeExpansionRequired + return expandVolumeResp, nil + } + + err = volumeApi.ExpandVolume(ctx, volId, uint64(capacity)) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Expand volume failed with error: %v", err)) + } + + volume, err = volumeApi.FindVolumeById(ctx, volId) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find volume failed with error: %v", err)) + } + expandVolumeResp.CapacityBytes = int64(volume.VolumeContent.SizeTotal) + expandVolumeResp.NodeExpansionRequired = nodeExpansionRequired + return expandVolumeResp, err } - volumeResp.CapacityBytes = int64(volume.VolumeContent.SizeTotal) - volumeResp.NodeExpansionRequired = true - return volumeResp, err } func (s *service) getCSIVolumes(volumes []types.Volume) ([]*csi.ListVolumesResponse_Entry, error) { @@ -1073,7 +1481,7 @@ func (s *service) getCSIVolumes(volumes []types.Volume) ([]*csi.ListVolumesRespo return entries, nil } -func (s *service) getCSISnapshots(snaps []types.Snapshot) ([]*csi.ListSnapshotsResponse_Entry, error) { +func (s *service) getCSISnapshots(snaps []types.Snapshot, volId, protocol, arrayId string) ([]*csi.ListSnapshotsResponse_Entry, error) { entries := make([]*csi.ListSnapshotsResponse_Entry, len(snaps)) for i, snap := range snaps { isReady := false @@ -1085,11 +1493,17 @@ func (s *service) getCSISnapshots(snaps []types.Snapshot) ([]*csi.ListSnapshotsR timestamp, _ = ptypes.TimestampProto(snap.SnapshotContent.CreationTime) } + snapId := fmt.Sprintf("%s-%s-%s-%s", snap.SnapshotContent.Name, protocol, arrayId, snap.SnapshotContent.ResourceId) + + size := snap.SnapshotContent.Size + if protocol == NFS { + size -= AdditionalFilesystemSize + } //Create CSI Snapshot vi := &csi.Snapshot{ - SizeBytes: snap.SnapshotContent.Size, - SnapshotId: snap.SnapshotContent.ResourceId, - SourceVolumeId: snap.SnapshotContent.StorageResource.Id, + SizeBytes: size, + SnapshotId: snapId, + SourceVolumeId: volId, CreationTime: timestamp, ReadyToUse: isReady, } @@ -1113,3 +1527,121 @@ func (s *service) validateAndGetProtocol(ctx context.Context, protocol, scProtoc } return protocol, nil } + +func (s *service) getFilesystemByResourceID(ctx context.Context, resourceID, arrayID string) (*types.Filesystem, error) { + ctx, _, rid := GetRunidLog(ctx) + unity, err := s.getUnityClient(ctx, arrayID) + if err != nil { + return nil, err + } + filesystemAPI := gounity.NewFilesystem(unity) + + filesystemID, err := filesystemAPI.GetFilesystemIdFromResId(ctx, resourceID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Storage resource: %s filesystem Id not found. Error: %v", resourceID, err)) + } + sourceFilesystemResp, err := filesystemAPI.FindFilesystemById(ctx, filesystemID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Filesystem: %s not found. Error: %v", filesystemID, err)) + } + return sourceFilesystemResp, nil +} + +//Create Volume from Snapshot(Copy snapshot on array) +func (s *service) createFilesystemFromSnapshot(ctx context.Context, snapID, volumeName, arrayID string) (*types.Snapshot, error) { + ctx, _, rid := GetRunidLog(ctx) + unity, err := s.getUnityClient(ctx, arrayID) + if err != nil { + return nil, err + } + snapshotAPI := gounity.NewSnapshot(unity) + + snapResp, err := snapshotAPI.CopySnapshot(ctx, snapID, volumeName) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create Filesystem from snapshot failed with error. Error: %v", err)) + } + + snapResp, err = snapshotAPI.FindSnapshotByName(ctx, volumeName) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create Filesystem from snapshot failed with error. Error: %v", err)) + } + + return snapResp, nil +} + +func (s *service) createIdempotentSnapshot(ctx context.Context, snapshotName, sourceVolID, description, retentionDuration, protocol, arrayID string, isClone bool) (*types.Snapshot, error) { + ctx, log, rid := GetRunidLog(ctx) + unity, err := s.getUnityClient(ctx, arrayID) + if err != nil { + return nil, err + } + snapshotAPI := gounity.NewSnapshot(unity) + + isSnapshot := false + var snapResp *types.Snapshot + var filesystemResp *types.Filesystem + if protocol == NFS { + fileAPI := gounity.NewFilesystem(unity) + filesystemResp, err = fileAPI.FindFilesystemById(ctx, sourceVolID) + if err != nil { + snapshotApi := gounity.NewSnapshot(unity) + snapResp, err = snapshotApi.FindSnapshotById(ctx, sourceVolID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find source filesystem: %s failed with error: %v", sourceVolID, err)) + } + isSnapshot = true + filesystemResp, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayID) + if err != nil { + return nil, err + } + } + } + + if protocol == NFS && !isSnapshot { + sourceVolID = filesystemResp.FileContent.StorageResource.Id + } + + snap, _ := snapshotAPI.FindSnapshotByName(ctx, snapshotName) + if snap != nil { + if snap.SnapshotContent.StorageResource.Id == sourceVolID || (isSnapshot && snap.SnapshotContent.StorageResource.Id == filesystemResp.FileContent.StorageResource.Id) { + //Subtract AdditionalFilesystemSize for Filesystem snapshots + if protocol == NFS { + snap.SnapshotContent.Size -= AdditionalFilesystemSize + } + log.Infof("Snapshot already exists with same name %s for same storage resource %s", snapshotName, sourceVolID) + return snap, nil + } + return nil, status.Error(codes.AlreadyExists, utils.GetMessageWithRunID(rid, "Snapshot with same name %s already exists for storage resource %s", snapshotName, snap.SnapshotContent.StorageResource.Id)) + } + + var newSnapshot *types.Snapshot + if isSnapshot { + newSnapshot, err = snapshotAPI.CopySnapshot(ctx, sourceVolID, snapshotName) + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create Snapshot error: %v", err)) + } + err = snapshotAPI.ModifySnapshot(ctx, newSnapshot.SnapshotContent.ResourceId, description, retentionDuration) + if err != nil { + log.Infof("Unable to modify description and retention duration in created snapshot %s. Error: %s", newSnapshot.SnapshotContent.ResourceId, err) + } + } else { + if isClone { + newSnapshot, err = snapshotAPI.CreateSnapshotWithFsAccesType(ctx, sourceVolID, snapshotName, description, retentionDuration, gounity.ProtocolAccessType) + } else { + newSnapshot, err = snapshotAPI.CreateSnapshot(ctx, sourceVolID, snapshotName, description, retentionDuration) + } + if err != nil { + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Create Snapshot error: %v", err)) + } + } + + newSnapshot, _ = snapshotAPI.FindSnapshotByName(ctx, snapshotName) + if newSnapshot != nil { + //Subtract AdditionalFilesystemSize for Filesystem snapshots{ + if protocol == NFS { + newSnapshot.SnapshotContent.Size -= AdditionalFilesystemSize + } + return newSnapshot, nil + } + return nil, status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Find Snapshot error after create. %v", err)) +} diff --git a/service/controller_test.go b/service/controller_test.go index 76c7774..677cffa 100644 --- a/service/controller_test.go +++ b/service/controller_test.go @@ -1,18 +1,26 @@ package service import ( + "context" + "github.com/dell/csi-unity/service/utils" + "github.com/stretchr/testify/assert" "testing" ) func TestControllerProbe(t *testing.T) { - //DriverConfig = testConf.unityConfig - //fmt.Println("----", testConf.unityConfig) - //config, err := getDriverConfig(context.Background()) - //if err != nil { - // t.Fatalf("TestBeforeServe failed with error %v", err) - //} - // - //if len(config) == 0 { - // t.Fatalf("Credentials are empty") - //} + DriverConfig = testConf.unityConfig + err := testConf.service.syncDriverConfig(context.Background()) + if err != nil { + t.Fatalf("TestBeforeServe failed with error %v", err) + } + if testConf.service.getStorageArrayLength() == 0 { + t.Fatalf("Credentials are empty") + } + log := utils.GetLogger() + ctx := context.Background() + entry := log.WithField(utils.RUNID, "1111") + ctx = context.WithValue(ctx, utils.UnityLogger, entry) + + err = testConf.service.probe(ctx, "controller", "") + assert.True(t, err != nil, "probe failed") } diff --git a/service/identity.go b/service/identity.go index b2b9cc4..bb28427 100644 --- a/service/identity.go +++ b/service/identity.go @@ -13,16 +13,19 @@ func (s *service) Probe( *csi.ProbeResponse, error) { ctx, log, _ := GetRunidLog(ctx) log.Infof("Executing Probe with args: %+v", *req) - if !strings.EqualFold(s.mode, "node") { + if strings.EqualFold(s.mode, "controller") { if err := s.controllerProbe(ctx, ""); err != nil { + log.Error("Identity probe failed:", err) return nil, err } } - if !strings.EqualFold(s.mode, "controller") { + if strings.EqualFold(s.mode, "node") { if err := s.nodeProbe(ctx, ""); err != nil { + log.Error("Identity probe failed:", err) return nil, err } } + log.Info("Identity probe success") return &csi.ProbeResponse{}, nil } @@ -53,6 +56,20 @@ func (s *service) GetPluginCapabilities( }, }, }, + { + Type: &csi.PluginCapability_VolumeExpansion_{ + VolumeExpansion: &csi.PluginCapability_VolumeExpansion{ + Type: csi.PluginCapability_VolumeExpansion_ONLINE, + }, + }, + }, + { + Type: &csi.PluginCapability_VolumeExpansion_{ + VolumeExpansion: &csi.PluginCapability_VolumeExpansion{ + Type: csi.PluginCapability_VolumeExpansion_OFFLINE, + }, + }, + }, }, }, nil } diff --git a/service/mount.go b/service/mount.go index deb9643..8fa6b01 100644 --- a/service/mount.go +++ b/service/mount.go @@ -32,6 +32,9 @@ func stagePublishNFS(ctx context.Context, req *csi.NodeStageVolumeRequest, expor accMode := req.GetVolumeCapability().GetAccessMode() + volCap := req.GetVolumeCapability() + mntVol := volCap.GetMount() + mntFlags := mntVol.GetMountFlags() // make sure target is created err := createDirIfNotExist(ctx, stagingTargetPath, arrayId) if err != nil { @@ -42,6 +45,7 @@ func stagePublishNFS(ctx context.Context, req *csi.NodeStageVolumeRequest, expor if accMode.GetMode() == csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY { rwo = "ro" } + mntFlags = append(mntFlags, rwo) mnts, err := gofsutil.GetMounts(ctx) if err != nil { @@ -74,7 +78,7 @@ func stagePublishNFS(ctx context.Context, req *csi.NodeStageVolumeRequest, expor if nfsv4 { nfsv4 = false for _, exportPathURL := range exportPaths { - err = gofsutil.Mount(ctx, exportPathURL, stagingTargetPath, "nfs", rwo) + err = gofsutil.Mount(ctx, exportPathURL, stagingTargetPath, "nfs", mntFlags...) if err == nil { nfsv4 = true break @@ -85,7 +89,7 @@ func stagePublishNFS(ctx context.Context, req *csi.NodeStageVolumeRequest, expor if !nfsv4 && nfsv3 { rwo += ",vers=3" for _, exportPathURL := range exportPaths { - err = gofsutil.Mount(ctx, exportPathURL, stagingTargetPath, "nfs", rwo) + err = gofsutil.Mount(ctx, exportPathURL, stagingTargetPath, "nfs", mntFlags...) if err == nil { break } @@ -99,7 +103,7 @@ func stagePublishNFS(ctx context.Context, req *csi.NodeStageVolumeRequest, expor return nil } -func publishNFS(ctx context.Context, req *csi.NodePublishVolumeRequest, exportPaths []string, arrayId string, nfsv3, nfsv4 bool) error { +func publishNFS(ctx context.Context, req *csi.NodePublishVolumeRequest, exportPaths []string, arrayId, chroot string, nfsv3, nfsv4 bool) error { ctx, log, rid := GetRunidLog(ctx) ctx, log = setArrayIdContext(ctx, arrayId) @@ -120,7 +124,9 @@ func publishNFS(ctx context.Context, req *csi.NodePublishVolumeRequest, exportPa rwo = "ro" } rwoArray = append(rwoArray, rwo) - + mntVol := volCap.GetMount() + mntFlags := mntVol.GetMountFlags() + rwoArray = append(rwoArray, mntFlags...) //Check if stage target mount exists var stageExportPathURL string stageMountExists := false @@ -164,7 +170,7 @@ func publishNFS(ctx context.Context, req *csi.NodePublishVolumeRequest, exportPa } else { return status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Target path: %s is already mounted to export path: %s with conflicting access modes", targetPath, stageExportPathURL)) } - } else if m.Path == stagingTargetPath { + } else if m.Path == stagingTargetPath || m.Path == chroot+stagingTargetPath { continue } else { if accMode.Mode == csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER { @@ -261,6 +267,10 @@ func stageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest, stagingPa return status.Error(codes.Unavailable, utils.GetMessageWithRunID(rid, "Fs type %s not supported", fs)) } + if fs == "xfs" { + mntFlags = append(mntFlags, "nouuid") + } + if err := handleStageMount(ctx, mntFlags, sysDevice, fs, stagingPath); err != nil { return status.Error(codes.Internal, utils.GetMessageWithRunID(rid, "Staging mount failed: %v", err)) } @@ -298,7 +308,7 @@ func stageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest, stagingPa return nil } -func publishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest, targetPath, symlinkPath string) error { +func publishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest, targetPath, symlinkPath, chroot string) error { rid, log := utils.GetRunidAndLogger(ctx) stagingPath := req.GetStagingTargetPath() @@ -336,7 +346,7 @@ func publishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest, targe // Existing mount satisfies request log.Debug("volume already published to target") return nil - } else if m.Path == stagingPath { + } else if m.Path == stagingPath || m.Path == chroot+stagingPath { continue } else { //Device has been mounted aleady to another target @@ -451,7 +461,7 @@ func unpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) e } //unstage volume removes staging mount and makes sure no other mounts are left for the given device path -func unstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest, deviceWWN string) (bool, string, error) { +func unstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest, deviceWWN, chroot string) (bool, string, error) { rid, log := utils.GetRunidAndLogger(ctx) lastUnmounted := false id := req.GetVolumeId() @@ -518,20 +528,20 @@ func unstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest, devic for _, m := range mnts { if m.Source == sysDevice.FullPath || m.Device == sysDevice.FullPath { - if m.Path == stagingTarget { + if m.Path == stagingTarget || m.Path == chroot+stagingTarget { stgMnt = true break } else { log.Infof("Device %s has been mounted outside staging target on %s", sysDevice.FullPath, m.Path) } - } else if m.Path == stagingTarget && !(m.Source == sysDevice.FullPath || m.Device == sysDevice.FullPath) { + } else if (m.Path == stagingTarget || m.Path == chroot+stagingTarget) && !(m.Source == sysDevice.FullPath || m.Device == sysDevice.FullPath) { log.Infof("Staging path %s has been mounted by foreign device %s", stagingTarget, m.Device) } } if stgMnt { log.Debugf("Unmount sysDevice: %v staging target: %s", sysDevice, stagingTarget) - if lastUnmounted, err = unmountStagingMount(ctx, sysDevice, stagingTarget); err != nil { + if lastUnmounted, err = unmountStagingMount(ctx, sysDevice, stagingTarget, chroot); err != nil { return lastUnmounted, "", status.Error(codes.Internal, utils.GetMessageWithRunID(rid, "Error unmounting staging mount %s: %s", stagingTarget, err.Error())) } log.Debugf("Device %s unmounted from private mount path %s successfully", sysDevice.Name, stagingTarget) @@ -701,7 +711,7 @@ func GetDevice(ctx context.Context, path string) (*Device, error) { func unmountStagingMount( ctx context.Context, dev *Device, - target string) (bool, error) { + target, chroot string) (bool, error) { log := utils.GetRunidLogger(ctx) lastUnmounted := false @@ -722,7 +732,8 @@ func unmountStagingMount( } // remove private mount if we can (if there are no other mounts - if len(mnts) == 1 && mnts[0].Path == target { + // mnts length will be 1 for coreos and 2 for other operating systems + if (len(mnts) == 1 || len(mnts) == 2) && (mnts[0].Path == target || mnts[0].Path == chroot+target) { if err := gofsutil.Unmount(ctx, target); err != nil { return lastUnmounted, err } diff --git a/service/node.go b/service/node.go index 9779644..46f2fc1 100644 --- a/service/node.go +++ b/service/node.go @@ -28,6 +28,7 @@ import ( var ( targetMountRecheckSleepTime = 3 * time.Second disconnectVolumeRetryTime = 1 * time.Second + nodeStartTimeout = 3 * time.Second lunzMutex sync.Mutex LUNZHLU = 0 nodeMutex sync.Mutex @@ -172,7 +173,7 @@ func (s *service) NodeStageVolume( wwn := utils.GetFcPortWwnFromVolumeContentWwn(fcPort.FcPortContent.Wwn) if !utils.ArrayContains(targetWwns, wwn) { - log.Debugf("Found Target wwn: ", wwn) + log.Debug("Found Target wwn: ", wwn) targetWwns = append(targetWwns, wwn) } } @@ -185,7 +186,7 @@ func (s *service) NodeStageVolume( } } - log.Debugf("Connect context data: ", publishContextData) + log.Debug("Connect context data: ", publishContextData) devicePath, err := s.connectDevice(ctx, publishContextData, useFC) if err != nil { return nil, err @@ -282,7 +283,7 @@ func (s *service) NodeUnstageVolume( } volumeWwn := utils.GetWwnFromVolumeContentWwn(volume.VolumeContent.Wwn) - lastMounted, devicePath, err := unstageVolume(ctx, req, volumeWwn) + lastMounted, devicePath, err := unstageVolume(ctx, req, volumeWwn, s.opts.Chroot) if err != nil { return nil, err } @@ -383,7 +384,7 @@ func (s *service) NodePublishVolume( if len(exportPaths) == 0 { return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Export paths not exist on NFS Share: %s", nfsShare.NFSShareContent.Id)) } - err = publishNFS(ctx, req, exportPaths, arrayId, nfsv3, nfsv4) + err = publishNFS(ctx, req, exportPaths, arrayId, s.opts.Chroot, nfsv3, nfsv4) if err != nil { return nil, err } @@ -391,10 +392,6 @@ func (s *service) NodePublishVolume( return &csi.NodePublishVolumeResponse{}, nil } - if req.GetReadonly() == true { - return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "readonly must be false, because the supported mode only SINGLE_NODE_WRITER")) - } - volumeApi := gounity.NewVolume(unity) volume, err := volumeApi.FindVolumeById(ctx, volID) if err != nil { @@ -408,7 +405,7 @@ func (s *service) NodePublishVolume( return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Disk path not found. Error: %v", err)) } - if err := publishVolume(ctx, req, targetPath, symlinkPath); err != nil { + if err := publishVolume(ctx, req, targetPath, symlinkPath, s.opts.Chroot); err != nil { return nil, err } @@ -592,6 +589,8 @@ func (s *service) NodeGetInfo( log.Debugf("Executing NodeGetInfo with args: %+v", *req) atleastOneArraySuccess := false + //Sleep for a while and wait untill iscsi discovery is completed + time.Sleep(nodeStartTimeout) for _, array := range s.getStorageArrayList() { if array.IsHostAdded { atleastOneArraySuccess = true @@ -632,6 +631,13 @@ func (s *service) NodeGetCapabilities( }, }, }, + { + Type: &csi.NodeServiceCapability_Rpc{ + Rpc: &csi.NodeServiceCapability_RPC{ + Type: csi.NodeServiceCapability_RPC_EXPAND_VOLUME, + }, + }, + }, }, }, nil } @@ -643,8 +649,103 @@ func (s *service) NodeGetVolumeStats( return nil, status.Error(codes.Unimplemented, "NodeGetVolumeStats not supported") } -func (s *service) NodeExpandVolume(context.Context, *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { - return nil, status.Error(codes.Unimplemented, "NodeExpandVolume not supported") +func (s *service) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandVolumeRequest) (*csi.NodeExpandVolumeResponse, error) { + ctx, log, rid := GetRunidLog(ctx) + log.Debugf("Executing NodeExpandVolume with args: %+v", *req) + + if req.VolumeId == "" { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "volumeId is mandatory parameter")) + } + + volID, _, arrayID, unity, err := s.validateAndGetResourceDetails(ctx, req.VolumeId, volumeType) + if err != nil { + return nil, err + } + + size := req.GetCapacityRange().GetRequiredBytes() + + ctx, log = setArrayIdContext(ctx, arrayID) + if err := s.requireProbe(ctx, arrayID); err != nil { + log.Debug("AutoProbe has not been called. Executing manual probe") + err = s.nodeProbe(ctx, arrayID) + if err != nil { + return nil, err + } + } + + // We are getting target path that points to mounted path on "/" + // This doesn't help us, though we should trace the path received + volumePath := req.GetVolumePath() + if volumePath == "" { + return nil, status.Error(codes.InvalidArgument, + utils.GetMessageWithRunID(rid, "Volume path required")) + } + + volumeAPI := gounity.NewVolume(unity) + volume, err := volumeAPI.FindVolumeById(ctx, volID) + if err != nil { + return nil, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Find volume Failed %v", err)) + } + + volName := volume.VolumeContent.Name + + //Locate and fetch all (multipath/regular) mounted paths using this volume + devMnt, err := gofsutil.GetMountInfoFromDevice(ctx, volName) + if err != nil { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to find mount info for (%s) with error %v", volName, err)) + } + + log.Debugf("Mount info for volume %s: %+v", volName, devMnt) + + // Rescan the device for the volume expanded on the array + for _, device := range devMnt.DeviceNames { + log.Debug("Begin rescan for :", device) + devicePath := sysBlock + "/" + device + err = gofsutil.DeviceRescan(ctx, devicePath) + if err != nil { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to rescan device (%s) with error %v", devicePath, err)) + } + } + // Expand the filesystem with the actual expanded volume size. + if devMnt.MPathName != "" { + err = gofsutil.ResizeMultipath(ctx, devMnt.MPathName) + if err != nil { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to resize filesystem: device (%s) with error %v", devMnt.MountPoint, err)) + } + } + //For a regular device, get the device path (devMnt.DeviceNames[1]) where the filesystem is mounted + //PublishVolume creates devMnt.DeviceNames[0] but is left unused for regular devices + var devicePath string + if len(devMnt.DeviceNames) > 1 { + devicePath = "/dev/" + devMnt.DeviceNames[1] + } else if len(devMnt.DeviceNames) == 1 { + devicePath = "/dev/" + devMnt.DeviceNames[0] + } else if devicePath == "" { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to resize filesystem: device name not found for (%s)", devMnt.MountPoint)) + } + + fsType, err := gofsutil.FindFSType(ctx, devMnt.MountPoint) + if err != nil { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to fetch filesystem for volume (%s) with error %v", devMnt.MountPoint, err)) + } + + log.Infof("Found %s filesystem mounted on volume %s", fsType, devMnt.MountPoint) + + //Resize the filesystem + err = gofsutil.ResizeFS(ctx, devMnt.MountPoint, devicePath, devMnt.MPathName, fsType) + if err != nil { + return nil, status.Error(codes.Internal, + utils.GetMessageWithRunID(rid, "Failed to resize filesystem: mountpoint (%s) device (%s) with error %v", + devMnt.MountPoint, devicePath, err)) + } + + log.Debug("Node Expand completed successfully") + return &csi.NodeExpandVolumeResponse{CapacityBytes: size}, nil } func (s *service) nodeProbe(ctx context.Context, arrayId string) error { @@ -656,26 +757,44 @@ func (s *service) getNFSShare(ctx context.Context, filesystemId, arrayId string) ctx, _, rid := GetRunidLog(ctx) ctx, _ = setArrayIdContext(ctx, arrayId) - unity, err := s.getUnityClient(arrayId) + unity, err := s.getUnityClient(ctx, arrayId) if err != nil { return nil, false, false, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "Get Unity client for array %s failed. Error: %v ", arrayId, err)) } + isSnapshot := false fileApi := gounity.NewFilesystem(unity) filesystem, err := fileApi.FindFilesystemById(ctx, filesystemId) + var snapResp *types.Snapshot if err != nil { - return nil, false, false, err + snapshotApi := gounity.NewSnapshot(unity) + snapResp, err = snapshotApi.FindSnapshotById(ctx, filesystemId) + if err != nil { + return nil, false, false, err + } + isSnapshot = true + filesystem, err = s.getFilesystemByResourceID(ctx, snapResp.SnapshotContent.StorageResource.Id, arrayId) + if err != nil { + return nil, false, false, err + } } var nfsShareId string - nfsShareName := NFSShareNamePrefix + filesystem.FileContent.Name + for _, nfsShare := range filesystem.FileContent.NFSShare { - if nfsShare.Name == nfsShareName { - nfsShareId = nfsShare.Id + if isSnapshot { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == filesystemId { + nfsShareId = nfsShare.Id + } + } else { + if nfsShare.Path == NFSShareLocalPath && nfsShare.ParentSnap.Id == "" { + nfsShareId = nfsShare.Id + } } } + if nfsShareId == "" { - return nil, false, false, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "NFS Share: %s not found. Error: %v", nfsShareName, err)) + return nil, false, false, status.Error(codes.NotFound, utils.GetMessageWithRunID(rid, "NFS Share for filesystem: %s not found. Error: %v", filesystemId, err)) } nfsShare, err := fileApi.FindNFSShareById(ctx, nfsShareId) @@ -699,7 +818,7 @@ func (s *service) getNFSShare(ctx context.Context, filesystemId, arrayId string) func (s *service) checkFilesystemMapping(ctx context.Context, nfsShare *types.NFSShare, am *csi.VolumeCapability_AccessMode, arrayId string) error { ctx, _, rid := GetRunidLog(ctx) ctx, _ = setArrayIdContext(ctx, arrayId) - unity, err := s.getUnityClient(arrayId) + unity, err := s.getUnityClient(ctx, arrayId) var accessType gounity.AccessType if err != nil { return err @@ -740,7 +859,7 @@ func (s *service) checkVolumeMapping(ctx context.Context, volume *types.Volume, rid, log := utils.GetRunidAndLogger(ctx) //Get Host Name hostName := s.opts.NodeName - unity, err := s.getUnityClient(arrayId) + unity, err := s.getUnityClient(ctx, arrayId) if err != nil { return 0, err } @@ -819,7 +938,7 @@ func getTargetMount(ctx context.Context, target string) (gofsutil.Info, error) { func (s *service) getArrayHostInitiators(ctx context.Context, host *types.Host, arrayId string) ([]string, error) { var hostInitiatorWwns []string hostContent := host.HostContent - unity, err := s.getUnityClient(arrayId) + unity, err := s.getUnityClient(ctx, arrayId) if err != nil { return nil, err } @@ -1094,6 +1213,12 @@ func (s *service) addNodeInformationIntoArray(ctx context.Context, array *Storag if errFc != nil && errIscsi != nil { log.Infof("Node %s does not have FC or iSCSI initiators and can only be used for NFS exports", s.opts.NodeName) } + + nodeIps, err := utils.GetHostIP() + if err != nil { + return status.Error(codes.Unknown, utils.GetMessageWithRunID(rid, "Unable to get node IP. Error: %v", err)) + } + //Find Host on the Array host, err := hostApi.FindHostByName(ctx, s.opts.NodeName) if err != nil { @@ -1112,6 +1237,12 @@ func (s *service) addNodeInformationIntoArray(ctx context.Context, array *Storag if err != nil { return err } + for _, nodeIp := range nodeIps { + _, err = hostApi.CreateHostIpPort(ctx, hostContent.ID, nodeIp) + if err != nil { + return err + } + } if len(wwns) > 0 { //Create Host FC Initiators @@ -1139,7 +1270,7 @@ func (s *service) addNodeInformationIntoArray(ctx context.Context, array *Storag return err } } else { - log.Debug("Host %s exists on the array", s.opts.NodeName) + log.Debugf("Host %s exists on the array", s.opts.NodeName) hostContent := host.HostContent arrayHostWwns, err := s.getArrayHostInitiators(ctx, host, array.ArrayId) if err != nil { @@ -1174,25 +1305,40 @@ func (s *service) addNodeInformationIntoArray(ctx context.Context, array *Storag } //Check Ip of the host with Host IP Port - findHostIpPort := false + findHostNamePort := false for _, ipPort := range hostContent.IpPorts { hostIpPort, err := hostApi.FindHostIpPortById(ctx, ipPort.Id) if err != nil { continue } if hostIpPort != nil && hostIpPort.HostIpContent.Address == s.opts.LongNodeName { - findHostIpPort = true - break + findHostNamePort = true + continue + } + if hostIpPort != nil { + for i, nodeIp := range nodeIps { + if hostIpPort.HostIpContent.Address == nodeIp { + nodeIps[i] = nodeIps[len(nodeIps)-1] + nodeIps = nodeIps[:len(nodeIps)-1] + break + } + } } } - if findHostIpPort == false { + if findHostNamePort == false { //Create Host Ip Port _, err = hostApi.CreateHostIpPort(ctx, hostContent.ID, s.opts.LongNodeName) if err != nil { return err } } + for _, nodeIp := range nodeIps { + _, err = hostApi.CreateHostIpPort(ctx, hostContent.ID, nodeIp) + if err != nil { + return err + } + } } if len(iqns) > 0 { diff --git a/service/service.go b/service/service.go index 63cc555..1fa75ed 100644 --- a/service/service.go +++ b/service/service.go @@ -251,7 +251,12 @@ func (s *service) getStorageArrayList() []*StorageArrayConfig { } // To get the UnityClient for a specific array -func (s *service) getUnityClient(arrayID string) (*gounity.Client, error) { +func (s *service) getUnityClient(ctx context.Context, arrayID string) (*gounity.Client, error) { + _, _, rid := GetRunidLog(ctx) + if s.getStorageArrayLength() == 0 { + return nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Invalid driver csi-driver configuration provided. At least one array should present or invalid json format. ")) + } + array := s.getStorageArray(arrayID) if array != nil && array.UnityClient != nil { return array.UnityClient, nil @@ -318,7 +323,12 @@ func (s *service) loadDynamicConfig(ctx context.Context, configFile string) erro } if event.Op&fsnotify.Create == fsnotify.Create && event.Name == parentFolder+"/..data" { log.Infof("****************Driver config file modified. Loading the config file:%s****************", event.Name) - s.syncDriverConfig(ctx) + err := s.syncDriverConfig(ctx) + if err != nil { + log.Debug("Driver configuration array length:", s.getStorageArrayLength()) + log.Error("Invalid configuration in secret.json. Error:", err) + //return + } if s.mode == "node" { syncNodeInfoChan <- true } @@ -364,6 +374,12 @@ var syncMutex sync.Mutex func (s *service) syncDriverConfig(ctx context.Context) error { ctx, log, _ := GetRunidLog(ctx) log.Info("*************Synchronizing driver config**************") + syncMutex.Lock() + defer syncMutex.Unlock() + s.arrays.Range(func(key interface{}, value interface{}) bool { + s.arrays.Delete(key) + return true + }) configBytes, err := ioutil.ReadFile(DriverConfig) if err != nil { return errors.New(fmt.Sprintf("File ('%s') error: %v", DriverConfig, err)) @@ -380,12 +396,6 @@ func (s *service) syncDriverConfig(ctx context.Context) error { return errors.New("Arrays details are not provided in unity-creds secret") } - if len(jsonConfig.StorageArrayList) > 10 { - return errors.New("Total number of Arrays should be less than or equal to 10 in 'storageArrayList' parameter") - } - - syncMutex.Lock() - defer syncMutex.Unlock() s.arrays.Range(func(key interface{}, value interface{}) bool { s.arrays.Delete(key) return true @@ -526,6 +536,8 @@ func GetRunidLog(ctx context.Context) (context.Context, *logrus.Entry, string) { fields[utils.RUNID] = rid } + logMutex.Lock() + defer logMutex.Unlock() l := utils.GetLogger() log := l.WithFields(fields) ctx = context.WithValue(ctx, utils.UnityLogger, log) @@ -614,6 +626,7 @@ func singleArrayProbe(ctx context.Context, probeType string, array *StorageArray Password: array.Password, }) if err != nil { + log.Errorf("Unity authentication failed for array %s error: %v", array.ArrayId, err) if e, ok := status.FromError(err); ok { if e.Code() == codes.Unauthenticated { array.IsProbeSuccess = false @@ -645,6 +658,9 @@ func (s *service) probe(ctx context.Context, probeType string, arrayId string) e err := singleArrayProbe(ctx, probeType, array) if err == nil { atleastOneArraySuccess = true + break + } else { + log.Errorf("Probe failed for array %s error:%v", array, err) } } @@ -658,6 +674,9 @@ func (s *service) probe(ctx context.Context, probeType string, arrayId string) e func (s *service) validateAndGetResourceDetails(ctx context.Context, resourceContextId string, resourceType resourceType) (resourceId, protocol, arrayId string, unity *gounity.Client, err error) { ctx, _, rid := GetRunidLog(ctx) + if s.getStorageArrayLength() == 0 { + return "", "", "", nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Invalid driver csi-driver configuration provided. At least one array should present or invalid json format. ")) + } resourceId = getVolumeIdFromVolumeContext(resourceContextId) if resourceId == "" { return "", "", "", nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "%sId can't be empty.", resourceType)) @@ -672,7 +691,7 @@ func (s *service) validateAndGetResourceDetails(ctx context.Context, resourceCon return "", "", "", nil, status.Error(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "[%s] [%s] error:[%v]", resourceType, resourceId, err)) } - unity, err = s.getUnityClient(arrayId) + unity, err = s.getUnityClient(ctx, arrayId) if err != nil { return "", "", "", nil, err } diff --git a/service/utils/emcutils.go b/service/utils/emcutils.go index fb1ae9b..41cca74 100644 --- a/service/utils/emcutils.go +++ b/service/utils/emcutils.go @@ -10,6 +10,7 @@ import ( "fmt" "io/ioutil" "net" + "os" "os/exec" "strings" "time" @@ -33,6 +34,25 @@ func GetVolumeResponseFromFilesystem(filesystem *types.Filesystem, arrayId, prot return getVolumeResponse(content.Name, protocol, arrayId, content.Id, content.SizeTotal) } +func GetVolumeResponseFromSnapshot(snapshot *types.Snapshot, arrayId, protocol string) *csi.CreateVolumeResponse { + volId := fmt.Sprintf("%s-%s-%s-%s", snapshot.SnapshotContent.Name, protocol, arrayId, snapshot.SnapshotContent.ResourceId) + VolumeContext := make(map[string]string) + VolumeContext["protocol"] = protocol + VolumeContext["arrayId"] = arrayId + VolumeContext["volumeId"] = snapshot.SnapshotContent.ResourceId + + volumeReq := &csi.Volume{ + VolumeId: volId, + CapacityBytes: int64(snapshot.SnapshotContent.Size), + VolumeContext: VolumeContext, + } + + volumeResp := &csi.CreateVolumeResponse{ + Volume: volumeReq, + } + return volumeResp +} + func getVolumeResponse(name, protocol, arrayId, resourceId string, size uint64) *csi.CreateVolumeResponse { volId := fmt.Sprintf("%s-%s-%s-%s", name, protocol, arrayId, resourceId) VolumeContext := make(map[string]string) @@ -109,7 +129,7 @@ func GetFCInitiators(ctx context.Context) ([]string, error) { } //Utility method to extract Host IP -func GetHostIP() (string, error) { +func GetHostIP() ([]string, error) { cmd := exec.Command("hostname", "-I") cmdOutput := &bytes.Buffer{} cmd.Stdout = cmdOutput @@ -120,13 +140,28 @@ func GetHostIP() (string, error) { cmd.Stdout = cmdOutput err = cmd.Run() if err != nil { - return "", err + return nil, err } } - output := string(cmdOutput.Bytes()) - ip := strings.Split(output, " ")[0] - return ip, nil + ips := strings.Split(strings.TrimSpace(output), " ") + + hostname, err := os.Hostname() + if err != nil { + return nil, err + } + + var lookup_ips []string + for _, ip := range ips { + lookupResp, err := net.LookupAddr(ip) + if err == nil && strings.Contains(lookupResp[0], hostname) { + lookup_ips = append(lookup_ips, ip) + } + } + if len(lookup_ips) == 0 { + lookup_ips = append(lookup_ips, ips[0]) + } + return lookup_ips, nil } //Utility method to convert Unity Rest type Snapshot to CSI standard Snapshot Response diff --git a/service/validator.go b/service/validator.go index a3c2bc1..fc181f9 100644 --- a/service/validator.go +++ b/service/validator.go @@ -4,6 +4,9 @@ import ( "fmt" "github.com/container-storage-interface/spec/lib/go/csi" + "github.com/dell/csi-unity/service/utils" + "github.com/dell/gounity/types" + "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -98,3 +101,41 @@ func valVolumeCaps(vcs []*csi.VolumeCapability, protocol string) (bool, string) return supported, reason } + +//Validates idempotency of an existing snapshot created from a filesystem +func validateCreateFsFromSnapshot(ctx context.Context, sourceFilesystemResp *types.Filesystem, storagePool string, tieringPolicy, hostIoSize int64, thin, dataReduction bool) error { + + rid, _ := utils.GetRunidAndLogger(ctx) + + // Validate the storagePool parameter + if sourceFilesystemResp.FileContent.Pool.Id != storagePool { + return status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source filesystem storage pool %s is different than the requested storage pool %s", + sourceFilesystemResp.FileContent.Pool.Id, storagePool)) + } + + //Validate the thinProvisioned parameter + if sourceFilesystemResp.FileContent.IsThinEnabled != thin { + return status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source filesystem thin provision %v is different than the requested thin provision %v", + sourceFilesystemResp.FileContent.IsThinEnabled, thin)) + } + + //Validate the dataReduction parameter + if sourceFilesystemResp.FileContent.IsDataReductionEnabled != dataReduction { + return status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source filesystem data reduction %v is different than the requested data reduction %v", + sourceFilesystemResp.FileContent.IsDataReductionEnabled, dataReduction)) + } + + //Validate the tieringPolicy parameter + if int64(sourceFilesystemResp.FileContent.TieringPolicy) != tieringPolicy { + return status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source filesystem tiering policy %v is different than the requested tiering policy %v", + sourceFilesystemResp.FileContent.TieringPolicy, tieringPolicy)) + } + + //Validate the hostIOSize parameter + if sourceFilesystemResp.FileContent.HostIOSize != hostIoSize { + return status.Errorf(codes.InvalidArgument, utils.GetMessageWithRunID(rid, "Source filesystem host IO size %v is different than the requested host IO size %v", + sourceFilesystemResp.FileContent.HostIOSize, hostIoSize)) + } + + return nil +} diff --git a/test/integration-test/features/integration.feature b/test/integration-test/features/integration.feature new file mode 100644 index 0000000..cbe2319 --- /dev/null +++ b/test/integration-test/features/integration.feature @@ -0,0 +1,211 @@ +Feature: CSI interface + As a consumer of the CSI interface + I want to run a system test + So that I know the service functions correctly. + + Scenario: Controller get capabilities, create, validate capabilities and delete basic volume + Given a CSI service + When I call Controller Get Capabilities + Then there are no errors + And a basic block volume request name "gditest-vol1" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + Then there are no errors + When I call validate volume capabilities with protocol "FC" with same access mode + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create, validate capabilities and delete basic volume + Given a CSI service + And a basic block volume request name "gditest-vol2" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + Then there are no errors + When I call validate volume capabilities with protocol "FC" with different access mode + Then the error message should contain "Unsupported capability" + And when I call DeleteVolume + Then there are no errors + + Scenario: Create, expand and delete basic volume + Given a CSI service + And a basic block volume request name "gditest-vol3" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "3" + Then there are no errors + And a basic block volume request name "gditest-vol3" arrayId "Array1-Id" protocol "FC" size "3" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume with smaller new size + Given a CSI service + And a basic block volume request name "gditest-vol4" arrayId "Array1-Id" protocol "FC" size "3" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "2" + Then the error message should contain "requested new capacity smaller than existing capacity" + And when I call DeleteVolume + Then there are no errors + + Scenario: Idempotent create and delete basic volume + Given a CSI service + And a basic block volume request name "gditest-vol5" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And I call CreateVolume + And when I call DeleteVolume + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume from snapshot of thin volume + Given a CSI service + And a basic block volume request name "gditest-vol6" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_volforsnap" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source with name "gditest-vol7" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Create, publish, unpublish, and delete basic volume with idempotency check for publish and unpublish + Given a CSI service + And a basic block volume request name "gditest-vol8" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create and delete basic 264000G volume + Given a CSI service + And a basic block volume request name "gditest-vol9" arrayId "Array1-Id" protocol "FC" size "264000" + When I call CreateVolume + Then the error message should contain "The system could not create the LUNs because specified size is too big." + And when I call DeleteVolume + Then there are no errors + + Scenario: Create and delete basic 96G volume + Given a CSI service + And a basic block volume request name "gditest-vol10" arrayId "Array1-Id" protocol "FC" size "96" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create volume, create snapshot, delete snapshot and delete volume + Given a CSI service + And a basic block volume request name "gditest-vol11" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_integration1" + When I call CreateSnapshot + And there are no errors + Given a delete snapshot request + And I call DeleteSnapshot + And there are no errors + And when I call DeleteVolume + And there are no errors + + Scenario: Create volume, idempotent create snapshot, idempotent delete snapshot delete volume + Given a CSI service + And a basic block volume request name "gditest-vol12" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_integration1" + When I call CreateSnapshot + And there are no errors + Given a create snapshot request "snap_integration1" + When I call CreateSnapshot + And there are no errors + Given a delete snapshot request + And I call DeleteSnapshot + And there are no errors + Given a delete snapshot request + And I call DeleteSnapshot + And there are no errors + And when I call DeleteVolume + And there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume with idempotency + Given a CSI service + And a basic block volume request name "gditest-vol13" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnPublishVolume + Then there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume for iSCSI + Given a CSI service + And a basic block volume request name "gditest-vol14" arrayId "Array1-Id" protocol "iSCSI" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume for NFS + Given a CSI service + And a basic block volume request name "gditest-vol15" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors \ No newline at end of file diff --git a/test/integration-test/integration_main_test.go b/test/integration-test/integration_main_test.go index 73adf98..f4a012f 100644 --- a/test/integration-test/integration_main_test.go +++ b/test/integration-test/integration_main_test.go @@ -2,8 +2,11 @@ package integration_test import ( "context" + "encoding/json" "fmt" + "io/ioutil" "os" + "strconv" "testing" "time" @@ -17,9 +20,33 @@ import ( var grpcClient *grpc.ClientConn +//To parse the secret json file +type StorageArrayList struct { + StorageArrayList []StorageArrayConfig `json:"storageArrayList"` +} + +type StorageArrayConfig struct { + ArrayId string `json:"arrayId"` +} + func TestMain(m *testing.M) { var stop func() os.Setenv("X_CSI_MODE", "") + + file, err := ioutil.ReadFile(os.Getenv("DRIVER_CONFIG")) + if err != nil { + panic("Driver Config missing") + } + arrayIdList := StorageArrayList{} + _ = json.Unmarshal([]byte(file), &arrayIdList) + if len(arrayIdList.StorageArrayList) == 0 { + panic("Array Info not provided") + } + for i := 0; i < len(arrayIdList.StorageArrayList); i++ { + arrayIdvar := "Array" + strconv.Itoa(i+1) + "-Id" + os.Setenv(arrayIdvar, arrayIdList.StorageArrayList[i].ArrayId) + } + ctx := context.Background() fmt.Printf("calling startServer") grpcClient, stop = startServer(ctx) diff --git a/test/integration-test/integration_test.go b/test/integration-test/integration_test.go index edc2406..152aefb 100644 --- a/test/integration-test/integration_test.go +++ b/test/integration-test/integration_test.go @@ -88,8 +88,9 @@ func (f *feature) aBasicBlockVolumeRequest(volumeName, arrayId, protocol string, params["isDataReductionEnabled"] = "false" params["tieringPolicy"] = "0" params["description"] = "CSI Volume Unit Test" - params["arrayId"] = arrayId + params["arrayId"] = os.Getenv(arrayId) params["protocol"] = protocol + params["nasServer"] = os.Getenv("NAS_SERVER") req.Parameters = params req.Name = volumeName capacityRange := new(csi.CapacityRange) @@ -117,7 +118,7 @@ func (f *feature) aBasicBlockVolumeRequestWithVolumeContentSource(volumeName, ar req := new(csi.CreateVolumeRequest) params := make(map[string]string) params["storagePool"] = os.Getenv("STORAGE_POOL") - params["arrayId"] = arrayId + params["arrayId"] = os.Getenv(arrayId) params["protocol"] = protocol req.Parameters = params req.Name = volumeName diff --git a/test/unit-test/features/unit.feature b/test/unit-test/features/unit.feature new file mode 100644 index 0000000..01ab76e --- /dev/null +++ b/test/unit-test/features/unit.feature @@ -0,0 +1,750 @@ +Feature: CSI interface + As a consumer of the CSI interface + I want to run a system test + So that I know the service functions correctly. + + Scenario: Add node info to array + Given a CSI service with node + Given a CSI service with node + Then there are no errors + + Scenario: Create and Delete snapshot successfully + Given a CSI service + And a basic block volume request name "gdtest-vol1" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + Given a create snapshot request "csi_snapshot_test" + When I call CreateSnapshot + Then there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create snapshot with a name that already exists + Given a CSI service + And a basic block volume request name "gdtest-vol2" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + And a create snapshot request "snap1" + When I call CreateSnapshot + Then there are no errors + When I call CreateSnapshot + Then there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create snapshot without giving storage resource name + Given a CSI service + And a create snapshot request "snapshot_test1" + When I call CreateSnapshot + Then the error message should contain "Storage Resource ID cannot be empty" + + Scenario: Create snapshot with invalid name + Given a CSI service + And a basic block volume request name "gdtest-vol3" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + And a create snapshot request "snap_#$" + When I call CreateSnapshot + Then the error message should contain "invalid snapshot name" + And when I call DeleteVolume + Then there are no errors + + Scenario: Delete snapshot without giving ID + Given a CSI service + And a delete snapshot request + When I call DeleteSnapshot + Then the error message should contain "snapshotId can't be empty" + + Scenario: Delete snapshot with incorrect ID + Given a CSI service + And a delete snapshot request "snap_not_exist_id" + When I call DeleteSnapshot + Then there are no errors + + Scenario: Create and delete basic volume successfully and idempotency test + Given a CSI service + And a basic block volume request name "gdtest-vol4" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create and delete basic volume with default protocol successfully + Given a CSI service + And a basic block volume request name "gdtest-vol39" arrayId "Array1-Id" protocol "" size "2" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create volume with 0 size + Given a CSI service + And a basic block volume request name "gdtest-zerosizevol" arrayId "Array1-Id" protocol "" size "0" + When I call CreateVolume + Then the error message should contain "RequiredBytes should be greater then 0" + + Scenario: Create and delete existing filesystem with same and different size + Given a CSI service + And a basic block volume request name "gdtest-vol40" arrayId "Array1-Id" protocol "NFS" size "3" + When I call CreateVolume + Then there are no errors + Given a basic block volume request name "gdtest-vol40" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + Then the error message should contain "already exists" + And a basic block volume request name "gdtest-vol40" arrayId "Array1-Id" protocol "NFS" size "3" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create an existing volume with different and same size + Given a CSI service + And a basic block volume request name "gdtest-vol6" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + And a basic block volume request name "gdtest-vol6" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + Then the error message should contain "'Volume name' already exists and size is different" + And a basic block volume request name "gdtest-vol6" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume without thinProvisioned parameter + Given a CSI service + And a basic block volume request with volumeName "gdtest-vol7" arrayId "Array1-Id" protocol "FC" size "2" storagepool "pool_1" thinProvisioned "" isDataReductionEnabled "false" tieringPolicy "0" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume without isCompressionEnabled parameter + Given a CSI service + And a basic block volume request with volumeName "gdtest-vol8" arrayId "Array1-Id" protocol "FC" size "2" storagepool "pool_1" thinProvisioned "true" isDataReductionEnabled "false" tieringPolicy "0" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume without isDataReductionEnabled parameter + Given a CSI service + And a basic block volume request with volumeName "gdtest-vol9" arrayId "Array1-Id" protocol "FC" size "2" storagepool "pool_1" thinProvisioned "true" isDataReductionEnabled "" tieringPolicy "0" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume without isDataReductionEnabled parameter + Given a CSI service + And a basic block volume request with volumeName "gdtest-vol10" arrayId "Array1-Id" protocol "FC" size "2" storagepool "pool_1" thinProvisioned "true" isDataReductionEnabled "false" tieringPolicy "" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Create a volume with incorrect storage_pool + Given a CSI service + And a basic block volume request with volumeName "gdtest-vol11" arrayId "Array1-Id" protocol "FC" size "2" storagepool "abcd" thinProvisioned "true" isDataReductionEnabled "false" tieringPolicy "0" + When I call CreateVolume + Then the error message should contain "Unable to get PoolID" + + Scenario: Create a volume without volume name + Given a CSI service + And a basic block volume request with volumeName "" arrayId "Array1-Id" protocol "FC" size "2" storagepool "abcd" thinProvisioned "true" isDataReductionEnabled "false" tieringPolicy "0" + When I call CreateVolume + Then the error message should contain "required: Name" + + Scenario: Create a volume from snapshot of thin volume with idempotency + Given a CSI service + And a basic block volume request name "gdtest-vol12" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_volforsnap" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-vol13" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Create a volume from snapshot of filesystem and create snapshot of cloned filesystem + Given a CSI service + And a basic block volume request name "gdtest-fssource" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_fs-gdtest-fssource" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-fsclone" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + Given a create snapshot request "snap_fs-gdtest-fssource-1" + When I call CreateSnapshot + And there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Create a volume from snaphot for NFS protocol with incompatible size + Given a CSI service + And a basic block volume request name "gdtest-fssource-1" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_fs-gdtest-fssource-2" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-fsclone" arrayId "Array1-Id" protocol "NFS" size "8" + When I call CreateVolume + Then the error message should contain "size" + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Create a volume from snapshot that does not exist + Given a CSI service + And a basic block volume request name "gdtest-vol14" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_volforsnap" + When I call CreateSnapshot + And there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-vol15" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then the error message should contain "snapshot not found" + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Create a volume from snapshot and passing an existing name for new volume + Given a CSI service + And a basic block volume request name "gdtest-vol16" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_volforsnap" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-vol16" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then the error message should contain "already exists" + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Clone a volume successfully with idempotency + Given a CSI service + And a basic block volume request name "gdtest-sourcevol1" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + And there are no errors + Given a basic block volume request with volume content source as volume with name "gdtest-clonevol" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + Given a basic block volume request name "gdtest-sourcevol1" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + And there are no errors + Given a basic block volume request with volume content source as volume with name "gdtest-clonevol" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Publish and unpublish a volume to host + Given a CSI service + And a basic block volume request name "gdtest-vol17" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Publish a volume to host with readonly as true + Given a CSI service + And a basic block volume request name "gdtest-vol18" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume with host "host" readonly "true" + Then the error message should contain "Readonly must be false" + And when I call DeleteVolume + Then there are no errors + + Scenario: Publish and unpublish a volume to host without giving hostname + Given a CSI service + And a basic block volume request name "gdtest-vol19" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume with host "" readonly "false" + Then the error message should contain "required: NodeID" + And when I call UnpublishVolume + Then the error message should contain "Node ID is required" + And when I call DeleteVolume + Then there are no errors + + Scenario: Publish a volume to host with VolumeCapability_AccessMode other than SINGLE_NODE_WRITER + Given a CSI service + And a basic block volume request name "gdtest-vol20" arrayId "Array1-Id" protocol "FC" size "5" + When I change volume capability accessmode + When I call CreateVolume + Then the error message should contain "not supported" + And when I call PublishVolume + Then the error message should contain "Access mode MULTI_NODE_SINGLE_WRITER is not supported" + And when I call DeleteVolume + Then there are no errors + + Scenario: Publish and unpublish a volume to host with incorrect hostname + Given a CSI service + And a basic block volume request name "gdtest-vol21" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume with host "host" readonly "false" + Then the error message should contain "unable to find host" + And when I call UnpublishVolume + Then the error message should contain "unable to find host" + And when I call DeleteVolume + Then there are no errors + + Scenario: Publish and unpublish a volume to host without giving volume id + Given a CSI service + And when I call PublishVolume with volumeId "" + Then the error message should contain "required: VolumeID" + When I call UnpublishVolume with volumeId "" + Then the error message should contain "required: VolumeID" + + Scenario: Publish and unpublish a volume to host with deleted volume + Given a CSI service + And a basic block volume request name "gdtest-vol41" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + And when I call PublishVolume + Then the error message should contain "Find volume Failed" + And when I call UnpublishVolume + Then there are no errors + + Scenario: Publish and unpublish a volume to host with deleted filesystem + Given a CSI service + And a basic block volume request name "gdtest-vol42" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + And when I call PublishVolume + Then the error message should contain "failed" + And when I call UnpublishVolume + Then there are no errors + + Scenario: Publish and unpublish volume idempotency + Given a CSI service + And a basic block volume request name "gdtest-vol22" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call PublishVolume + Then there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Validate volume capabilities with same access mode + Given a CSI service + And a basic block volume request name "gdtest-vol24" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call validate volume capabilities with protocol "FC" with same access mode + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Validate volume capabilities with different access mode + Given a CSI service + And a basic block volume request name "gdtest-vol25" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call validate volume capabilities with protocol "FC" with different access mode + Then the error message should contain "Unsupported capability" + And when I call DeleteVolume + Then there are no errors + + Scenario: Validate volume capabilities with incorrect volume Id + Given a CSI service + When I call validate volume capabilities with protocol "FC" with volume ID "xyz" + Then the error message should contain "Volume not found" + + Scenario: Controller get capabilities + Given a CSI service + When I call Controller Get Capabilities + Then there are no errors + + Scenario: Controller expand volume + Given a CSI service + And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "3" + Then there are no errors + And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "FC" size "3" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume for NFS protocol + Given a CSI service + And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "8" + Then there are no errors + And a basic block volume request name "gdtest-vol26" arrayId "Array1-Id" protocol "NFS" size "8" + When I call CreateVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume for cloned NFS volume + Given a CSI service + And a basic block volume request name "gdtest-snapofclonevol" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + Given a create snapshot request "snap_volforsnap_1" + When I call CreateSnapshot + And there are no errors + Given a basic block volume request with volume content source as snapshot with name "gdtest-vol13_1" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "8" + Then the error message should contain "snapshot" + And when I call DeleteVolume + Then there are no errors + Given a delete snapshot request + When I call DeleteSnapshot + Then there are no errors + And When I call DeleteAllCreatedVolumes + Then there are no errors + + Scenario: Controller expand volume with same new size + Given a CSI service + And a basic block volume request name "gdtest-vol27" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "2" + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume with smaller new size + Given a CSI service + And a basic block volume request name "gdtest-vol28" arrayId "Array1-Id" protocol "FC" size "3" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "2" + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume with new size as 0 + Given a CSI service + And a basic block volume request name "gdtest-vol29" arrayId "Array1-Id" protocol "FC" size "2" + When I call CreateVolume + Then there are no errors + When I call Controller Expand Volume "0" + Then the error message should contain "Required bytes can not be 0 or less" + And when I call DeleteVolume + Then there are no errors + + Scenario: Controller expand volume with volume that does not exist + Given a CSI service + When I call Controller Expand Volume "2" with volume "abcd" + Then the error message should contain "Unable to find volume" + + Scenario: Controller expand volume without giving volume + Given a CSI service + When I call Controller Expand Volume "2" with volume "" + Then the error message should contain "required" + + Scenario: Node stage, publish, unpublish and unstage volume + Given a CSI service + And a basic block volume request name "gdtest-vol30" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node publish volume with readonly as true + Given a CSI service + And a basic block volume request name "gdtest-vol31" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "true" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node publish volume without volume id + Given a CSI service + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then the error message should contain "required: VolumeID" + + Scenario: Node publish volume without controller publish volume + Given a CSI service + And a basic block volume request name "gdtest-vol33" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then the error message should contain "no such file or directory" + And when I call DeleteVolume + Then there are no errors + + Scenario: Node unpublish when node publish never hapened + Given a CSI service + And a basic block volume request name "gdtest-vol34" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then the error message should contain "no such file or directory" + And when I call NodeUnPublishVolume + Then there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node Get Capabilities + Given a CSI service + And When I call NodeGetCapabilities + Then there are no errors + + Scenario: Node publish volume without volume capabilities + Given a CSI service + And a basic block volume request name "gdtest-vol35" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodePublishVolume without accessmode and fsType "ext4" + Then the error message should contain "required: AccessMode" + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume idempotency + Given a CSI service + And a basic block volume request name "gdtest-vol36" arrayId "Array1-Id" protocol "FC" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnPublishVolume + Then there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Get Plugin capabilities + Given a CSI service + And When I call GetPluginCapabilities + Then there are no errors + + Scenario: Get Plugin info + Given a CSI service + And When I call GetPluginInfo + Then there are no errors + + Scenario: NodeGetInfo + Given a CSI service + And When I call NodeGetInfo + Then the error message should contain "not added" + + Scenario: Node stage, publish, unpublish and unstage volume for iSCSI + Given a CSI service + And a basic block volume request name "gdtest-vol37" arrayId "Array1-Id" protocol "iSCSI" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "ext4" + And there are no errors + And when I call NodePublishVolume fsType "ext4" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume for NFS with idempotency + Given a CSI service + And a basic block volume request name "gdtest-vol38" arrayId "Array1-Id" protocol "NFS" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume for NFS with accessmode "ROX" + Given a CSI service + And a basic filesystem request name "gdtest-vol43" arrayId "Array1-Id" protocol "NFS" accessMode "ROX" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + + Scenario: Node stage, publish, unpublish and unstage volume for NFS with accessmode "RWX" + Given a CSI service + And a basic filesystem request name "gdtest-vol44" arrayId "Array1-Id" protocol "NFS" accessMode "RWX" size "5" + When I call CreateVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call PublishVolume + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodeStageVolume fsType "" + And there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodePublishVolume fsType "" readonly "false" + Then there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnPublishVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors + And when I call DeleteVolume + Then there are no errors + And when I call NodeUnstageVolume + And there are no errors + And when I call UnpublishVolume + And there are no errors \ No newline at end of file diff --git a/test/unit-test/unit_main_test.go b/test/unit-test/unit_main_test.go index 71bb1e5..c5be6c4 100644 --- a/test/unit-test/unit_main_test.go +++ b/test/unit-test/unit_main_test.go @@ -2,23 +2,51 @@ package unit_test import ( "context" + "encoding/json" "fmt" + "io/ioutil" + "os" + "strconv" + "testing" + "time" + "github.com/DATA-DOG/godog" "github.com/container-storage-interface/spec/lib/go/csi" "github.com/dell/csi-unity/provider" "github.com/dell/csi-unity/service" "github.com/rexray/gocsi/utils" "google.golang.org/grpc" - "os" - "testing" - "time" ) var grpcClient *grpc.ClientConn var stop func() +//To parse the secret json file +type StorageArrayList struct { + StorageArrayList []StorageArrayConfig `json:"storageArrayList"` +} + +type StorageArrayConfig struct { + ArrayId string `json:"arrayId"` +} + func TestMain(m *testing.M) { os.Setenv("X_CSI_MODE", "") + + file, err := ioutil.ReadFile(os.Getenv("DRIVER_CONFIG")) + if err != nil { + panic("Driver Config missing") + } + arrayIdList := StorageArrayList{} + _ = json.Unmarshal([]byte(file), &arrayIdList) + if len(arrayIdList.StorageArrayList) == 0 { + panic("Array Info not provided") + } + for i := 0; i < len(arrayIdList.StorageArrayList); i++ { + arrayIdvar := "Array" + strconv.Itoa(i+1) + "-Id" + os.Setenv(arrayIdvar, arrayIdList.StorageArrayList[i].ArrayId) + } + ctx := context.Background() fmt.Printf("calling startServer") grpcClient, stop = startServer(ctx) diff --git a/test/unit-test/unit_test.go b/test/unit-test/unit_test.go index 24035c6..c45955d 100644 --- a/test/unit-test/unit_test.go +++ b/test/unit-test/unit_test.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "os" + "path" "strconv" "strings" "time" @@ -79,6 +80,35 @@ func (f *feature) aCSIService() error { return nil } +//aCSIServiceWithNode method is used to add node and initiators on array +func (f *feature) aCSIServiceWithNode() error { + stop() + time.Sleep(10 * time.Second) + os.Setenv("X_CSI_MODE", "node") + ctx := context.Background() + grpcClient, stop = startServer(ctx) + time.Sleep(5 * time.Second) + + ctx = context.Background() + fmt.Printf("testing Identity Probe\n") + client := csi.NewIdentityClient(grpcClient) + probeResp, err := client.Probe(ctx, &csi.ProbeRequest{}) + time.Sleep(120 * time.Second) + if err != nil { + fmt.Printf("Probe failed with error: %s:\n", err.Error()) + } else { + fmt.Printf("Probe passed: %s\n", probeResp.Ready) + } + + stop() + time.Sleep(10 * time.Second) + os.Setenv("X_CSI_MODE", "") + ctx = context.Background() + grpcClient, stop = startServer(ctx) + time.Sleep(5 * time.Second) + return nil +} + //aBasicBlockVolumeRequest method is used to build a Create volume request func (f *feature) aBasicBlockVolumeRequest(volumeName, arrayId, protocol string, size int) error { f.createVolumeRequest = nil @@ -89,8 +119,9 @@ func (f *feature) aBasicBlockVolumeRequest(volumeName, arrayId, protocol string, params["isDataReductionEnabled"] = "false" params["tieringPolicy"] = "0" params["description"] = "CSI Volume Unit Test" - params["arrayId"] = arrayId + params["arrayId"] = os.Getenv(arrayId) params["protocol"] = protocol + params["nasServer"] = os.Getenv("NAS_SERVER") req.Parameters = params req.Name = volumeName capacityRange := new(csi.CapacityRange) @@ -112,6 +143,48 @@ func (f *feature) aBasicBlockVolumeRequest(volumeName, arrayId, protocol string, return nil } +//aBasicFilesystemRequest method is used to build a Create volume request for filesystem +func (f *feature) aBasicFilesystemRequest(volumeName, arrayId, protocol, am string, size int) error { + f.createVolumeRequest = nil + req := new(csi.CreateVolumeRequest) + params := make(map[string]string) + params["storagePool"] = os.Getenv("STORAGE_POOL") + params["thinProvisioned"] = "true" + params["isDataReductionEnabled"] = "false" + params["tieringPolicy"] = "0" + params["description"] = "CSI Volume Unit Test" + params["arrayId"] = os.Getenv(arrayId) + params["protocol"] = protocol + params["nasServer"] = os.Getenv("NAS_SERVER") + req.Parameters = params + req.Name = volumeName + capacityRange := new(csi.CapacityRange) + capacityRange.RequiredBytes = int64(size * 1024 * 1024 * 1024) + req.CapacityRange = capacityRange + capability := new(csi.VolumeCapability) + mount := new(csi.VolumeCapability_MountVolume) + mountType := new(csi.VolumeCapability_Mount) + mountType.Mount = mount + capability.AccessType = mountType + accessMode := new(csi.VolumeCapability_AccessMode) + if am == "ROX" { + accessMode.Mode = csi.VolumeCapability_AccessMode_MULTI_NODE_READER_ONLY + } else if am == "RWX" { + accessMode.Mode = csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER + } else if am == "RWO" { + accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + } else { + accessMode.Mode = csi.VolumeCapability_AccessMode_UNKNOWN + } + capability.AccessMode = accessMode + f.capability = capability + capabilities := make([]*csi.VolumeCapability, 0) + capabilities = append(capabilities, capability) + req.VolumeCapabilities = capabilities + f.createVolumeRequest = req + return nil +} + //aBasicBlockVolumeRequestWithParameters method is used to build a Create volume request with parameters func (f *feature) aBasicBlockVolumeRequestWithParameters(volumeName, arrayId, protocol string, size int, storagepool, thinProvisioned, isDataReductionEnabled, tieringPolicy string) error { f.createVolumeRequest = nil @@ -119,8 +192,6 @@ func (f *feature) aBasicBlockVolumeRequestWithParameters(volumeName, arrayId, pr params := make(map[string]string) if storagepool == "id" { params["storagePool"] = os.Getenv("STORAGE_POOL") - } else if storagepool == "name" { - params["storagePool"] = os.Getenv("STORAGE_POOL_NAME") } else { params["storagePool"] = storagepool } @@ -128,8 +199,9 @@ func (f *feature) aBasicBlockVolumeRequestWithParameters(volumeName, arrayId, pr params["isDataReductionEnabled"] = isDataReductionEnabled params["tieringPolicy"] = tieringPolicy params["description"] = "CSI Volume Unit Test" - params["arrayId"] = arrayId + params["arrayId"] = os.Getenv(arrayId) params["protocol"] = protocol + params["nasServer"] = os.Getenv("NAS_SERVER") req.Parameters = params req.Name = volumeName capacityRange := new(csi.CapacityRange) @@ -157,7 +229,7 @@ func (f *feature) aBasicBlockVolumeRequestWithVolumeContentSource(volumeName, ar req := new(csi.CreateVolumeRequest) params := make(map[string]string) params["storagePool"] = os.Getenv("STORAGE_POOL") - params["arrayId"] = arrayId + params["arrayId"] = os.Getenv(arrayId) params["protocol"] = protocol req.Parameters = params req.Name = volumeName @@ -187,6 +259,42 @@ func (f *feature) aBasicBlockVolumeRequestWithVolumeContentSource(volumeName, ar return nil } +//aBasicBlockVolumeRequest method with volume content source as volume +func (f *feature) aBasicBlockVolumeRequestWithVolumeContentSourceAsVolume(volumeName, arrayId, protocol string, size int) error { + f.createVolumeRequest = nil + req := new(csi.CreateVolumeRequest) + params := make(map[string]string) + params["storagePool"] = os.Getenv("STORAGE_POOL") + params["arrayId"] = os.Getenv(arrayId) + params["protocol"] = protocol + req.Parameters = params + req.Name = volumeName + capacityRange := new(csi.CapacityRange) + capacityRange.RequiredBytes = int64(size * 1024 * 1024 * 1024) + req.CapacityRange = capacityRange + capability := new(csi.VolumeCapability) + mount := new(csi.VolumeCapability_MountVolume) + mountType := new(csi.VolumeCapability_Mount) + mountType.Mount = mount + capability.AccessType = mountType + accessMode := new(csi.VolumeCapability_AccessMode) + accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + capability.AccessMode = accessMode + f.capability = capability + capabilities := make([]*csi.VolumeCapability, 0) + capabilities = append(capabilities, capability) + req.VolumeCapabilities = capabilities + volumeContentSource_VolumeSource := new(csi.VolumeContentSource_VolumeSource) + volumeContentSource_VolumeSource.VolumeId = f.createVolumeResponse.GetVolume().GetVolumeId() + volumeContentSource_Volume := new(csi.VolumeContentSource_Volume) + volumeContentSource_Volume.Volume = volumeContentSource_VolumeSource + volumeContentSource := new(csi.VolumeContentSource) + volumeContentSource.Type = volumeContentSource_Volume + req.VolumeContentSource = volumeContentSource + f.createVolumeRequest = req + return nil +} + //iChangeVolumeCapabilityAccessmode is a method to change volume capabilities access mode func (f *feature) iChangeVolumeCapabilityAccessmode() error { f.createVolumeRequest.VolumeCapabilities[0].AccessMode.Mode = 4 @@ -631,8 +739,8 @@ func (f *feature) whenICallNodePublishVolume(fsType, readonly string) error { } else { req.VolumeId = "" } - req.StagingTargetPath = os.Getenv("X_CSI_STAGING_TARGET_PATH") - req.TargetPath = os.Getenv("X_CSI_PUBLISH_TARGET_PATH") + req.StagingTargetPath = path.Join(os.Getenv("X_CSI_STAGING_TARGET_PATH"), f.volID) + req.TargetPath = path.Join(os.Getenv("X_CSI_PUBLISH_TARGET_PATH"), f.volID) capability := new(csi.VolumeCapability) mount := new(csi.VolumeCapability_MountVolume) mount.FsType = fsType @@ -640,7 +748,7 @@ func (f *feature) whenICallNodePublishVolume(fsType, readonly string) error { mountType.Mount = mount capability.AccessType = mountType accessMode := new(csi.VolumeCapability_AccessMode) - accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + accessMode.Mode = f.capability.AccessMode.Mode capability.AccessMode = accessMode req.VolumeCapability = capability read, _ := strconv.ParseBool(readonly) @@ -668,7 +776,7 @@ func (f *feature) whenICallNodePublishVolumeWithTargetPath(target_path, fsType s } else { req.VolumeId = "" } - req.StagingTargetPath = os.Getenv("X_CSI_STAGING_TARGET_PATH") + req.StagingTargetPath = path.Join(os.Getenv("X_CSI_STAGING_TARGET_PATH"), f.volID) req.TargetPath = target_path capability := new(csi.VolumeCapability) mount := new(csi.VolumeCapability_MountVolume) @@ -677,7 +785,7 @@ func (f *feature) whenICallNodePublishVolumeWithTargetPath(target_path, fsType s mountType.Mount = mount capability.AccessType = mountType accessMode := new(csi.VolumeCapability_AccessMode) - accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + accessMode.Mode = f.capability.AccessMode.Mode capability.AccessMode = accessMode req.VolumeCapability = capability req.Readonly = false @@ -704,7 +812,7 @@ func (f *feature) whenICallNodePublishVolumeWithoutAccessmode(fsType string) err } else { req.VolumeId = "" } - req.StagingTargetPath = os.Getenv("X_CSI_STAGING_TARGET_PATH") + req.StagingTargetPath = path.Join(os.Getenv("X_CSI_STAGING_TARGET_PATH"), f.volID) capability := new(csi.VolumeCapability) mount := new(csi.VolumeCapability_MountVolume) mount.FsType = fsType @@ -713,7 +821,7 @@ func (f *feature) whenICallNodePublishVolumeWithoutAccessmode(fsType string) err capability.AccessType = mountType capability.AccessMode = nil req.VolumeCapability = capability - req.TargetPath = os.Getenv("X_CSI_PUBLISH_TARGET_PATH") + req.TargetPath = path.Join(os.Getenv("X_CSI_PUBLISH_TARGET_PATH"), f.volID) req.Readonly = false f.nodePublishVolumeRequest = req @@ -765,7 +873,7 @@ func (f *feature) whenICallNodeStageVolume(fsType string) error { if f.createVolumeResponse == nil { req.VolumeId = "NoID" } - req.StagingTargetPath = os.Getenv("X_CSI_STAGING_TARGET_PATH") + req.StagingTargetPath = path.Join(os.Getenv("X_CSI_STAGING_TARGET_PATH"), f.volID) capability := new(csi.VolumeCapability) mount := new(csi.VolumeCapability_MountVolume) mount.FsType = fsType @@ -773,7 +881,7 @@ func (f *feature) whenICallNodeStageVolume(fsType string) error { mountType.Mount = mount capability.AccessType = mountType accessMode := new(csi.VolumeCapability_AccessMode) - accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + accessMode.Mode = f.capability.AccessMode.Mode capability.AccessMode = accessMode req.VolumeCapability = capability f.nodeStageVolumeRequest = req @@ -806,7 +914,7 @@ func (f *feature) whenICallNodeStageVolumeWithTargetPath(fsType, target_path str mountType.Mount = mount capability.AccessType = mountType accessMode := new(csi.VolumeCapability_AccessMode) - accessMode.Mode = csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER + accessMode.Mode = f.capability.AccessMode.Mode capability.AccessMode = accessMode req.VolumeCapability = capability f.nodeStageVolumeRequest = req @@ -915,110 +1023,16 @@ func (f *feature) whenICallGetPluginInfo() error { return nil } -//aCSIServiceWithoutCSIUnityEndpoint - Test case to call probe without CSI Unity endpoint -func (f *feature) aCSIServiceWithoutCSIUnityEndpoint() error { - stop() - time.Sleep(10 * time.Second) - os.Setenv("X_CSI_UNITY_ENDPOINT", "") - os.Setenv("X_CSI_MODE", "controller") - ctx := context.Background() - grpcClient, stop = startServer(ctx) - time.Sleep(5 * time.Second) - client := csi.NewIdentityClient(grpcClient) - probeResp, err := client.Probe(ctx, &csi.ProbeRequest{}) - if err != nil { - fmt.Printf("Controller Probe failed with error: %s:\n", err.Error()) - f.addError(err) - } else { - fmt.Printf("Controller Probe passed: %s\n", probeResp.Ready) - } - stop() - time.Sleep(10 * time.Second) - os.Setenv("X_CSI_MODE", "node") - ctx = context.Background() - grpcClient, stop = startServer(ctx) - time.Sleep(10 * time.Second) - client = csi.NewIdentityClient(grpcClient) - probeResp, err = client.Probe(ctx, &csi.ProbeRequest{}) - if err != nil { - fmt.Printf("Node Probe failed with error: %s:\n", err.Error()) - f.addError(err) - } else { - fmt.Printf("Node Probe passed: %s\n", probeResp.Ready) - } - - os.Setenv("X_CSI_UNITY_ENDPOINT", "https://1.1.1.1") - os.Setenv("X_CSI_MODE", "") - return nil -} - -//aCSIServiceWithCSIUnityPassword - Test case to call probe with CSI Unity password as parameter -func (f *feature) aCSIServiceWithCSIUnityPassword(password string) error { - stop() - time.Sleep(10 * time.Second) - os.Setenv("X_CSI_UNITY_PASSWORD", password) - os.Setenv("X_CSI_MODE", "controller") - ctx := context.Background() - grpcClient, stop = startServer(ctx) - time.Sleep(10 * time.Second) - client := csi.NewIdentityClient(grpcClient) - probeResp, err := client.Probe(ctx, &csi.ProbeRequest{}) - if err != nil { - fmt.Printf("Controller Probe failed with error: %s:\n", err.Error()) - f.addError(err) - } else { - fmt.Printf("Controller Probe passed: %s\n", probeResp.Ready) - } - stop() - time.Sleep(10 * time.Second) - os.Setenv("X_CSI_MODE", "node") - ctx = context.Background() - grpcClient, stop = startServer(ctx) - time.Sleep(10 * time.Second) - client = csi.NewIdentityClient(grpcClient) - probeResp, err = client.Probe(ctx, &csi.ProbeRequest{}) - if err != nil { - fmt.Printf("Node Probe failed with error: %s:\n", err.Error()) - f.addError(err) - } else { - fmt.Printf("Node Probe passed: %s\n", probeResp.Ready) - } - - os.Setenv("X_CSI_UNITY_PASSWORD", "Password123!") - os.Setenv("X_CSI_MODE", "") - return nil -} - -//whenICallNodeGetInfoHostname - Test case to call node get info with hostname -func (f *feature) whenICallNodeGetInfoHostname(hostname string) error { - stop() - time.Sleep(10 * time.Second) - os.Setenv("X_CSI_UNITY_NODENAME", hostname) - ctx := context.Background() - grpcClient, stop = startServer(ctx) - time.Sleep(5 * time.Second) - client := csi.NewNodeClient(grpcClient) - _, err := client.NodeGetInfo(ctx, &csi.NodeGetInfoRequest{}) - if err != nil { - fmt.Printf("Node get info failed with error: %s:\n", err.Error()) - f.addError(err) - } else { - fmt.Printf("Node get info passed\n") - } - - os.Setenv("X_CSI_UNITY_NODENAME", "lgloc183") - return nil -} - func FeatureContext(s *godog.Suite) { f := &feature{} s.Step(`^a CSI service$`, f.aCSIService) - s.Step(`^a CSI service without CSI Unity Endpoint$`, f.aCSIServiceWithoutCSIUnityEndpoint) - s.Step(`^a CSI service with CSI Unity Password "([^"]*)"$`, f.aCSIServiceWithCSIUnityPassword) + s.Step(`^a CSI service with node$`, f.aCSIServiceWithNode) s.Step(`^a basic block volume request name "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" size "(\d+)"$`, f.aBasicBlockVolumeRequest) + s.Step(`^a basic filesystem request name "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" accessMode "([^"]*)" size "(\d+)"$`, f.aBasicFilesystemRequest) s.Step(`^I change volume capability accessmode$`, f.iChangeVolumeCapabilityAccessmode) s.Step(`^a basic block volume request with volumeName "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" size "([^"]*)" storagepool "([^"]*)" thinProvisioned "([^"]*)" isDataReductionEnabled "([^"]*)" tieringPolicy "([^"]*)"$`, f.aBasicBlockVolumeRequestWithParameters) - s.Step(`^a basic block volume request with volume content source with name "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" size "([^"]*)"$`, f.aBasicBlockVolumeRequestWithVolumeContentSource) + s.Step(`^a basic block volume request with volume content source as snapshot with name "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" size "([^"]*)"$`, f.aBasicBlockVolumeRequestWithVolumeContentSource) + s.Step(`^a basic block volume request with volume content source as volume with name "([^"]*)" arrayId "([^"]*)" protocol "([^"]*)" size "([^"]*)"$`, f.aBasicBlockVolumeRequestWithVolumeContentSourceAsVolume) s.Step(`^I call CreateVolume$`, f.iCallCreateVolume) s.Step(`^when I call DeleteVolume$`, f.whenICallDeleteVolume) s.Step(`^When I call DeleteAllCreatedVolumes$`, f.whenICallDeleteAllCreatedVolumes) @@ -1047,7 +1061,6 @@ func FeatureContext(s *godog.Suite) { s.Step(`^when I call NodeStageVolume fsType "([^"]*)" with StagingTargetPath "([^"]*)"$`, f.whenICallNodeStageVolumeWithTargetPath) s.Step(`^when I call NodeUnstageVolume$`, f.whenICallNodeUnstageVolume) s.Step(`^When I call NodeGetInfo$`, f.whenICallNodeGetInfo) - s.Step(`^When I call NodeGetInfo hostname "([^"]*)"$`, f.whenICallNodeGetInfoHostname) s.Step(`^When I call NodeGetCapabilities$`, f.whenICallNodeGetCapabilities) s.Step(`^when I call NodePublishVolume without accessmode and fsType "([^"]*)"$`, f.whenICallNodePublishVolumeWithoutAccessmode) s.Step(`^When I call GetPluginCapabilities$`, f.whenICallGetPluginCapabilities) From 3dd05d381e43585670d580e42cb35c6ebd64aa6c Mon Sep 17 00:00:00 2001 From: infa-mseelam Date: Thu, 24 Sep 2020 11:10:42 +0530 Subject: [PATCH 2/3] Modified for gounity library --- Dockerfile | 2 -- go.mod | 3 --- 2 files changed, 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index e1ebac3..82a01f5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,6 @@ FROM golang:1.13 as builder RUN mkdir -p /go/src COPY csi-unity/ /go/src/csi-unity -#//@TODO remove gofsutil before release -COPY gounity /go/src/gounity WORKDIR /go/src/csi-unity RUN mkdir -p bin RUN go generate diff --git a/go.mod b/go.mod index ef75fda..04bcab7 100644 --- a/go.mod +++ b/go.mod @@ -2,9 +2,6 @@ module github.com/dell/csi-unity go 1.13 -// TODO: Remove these replace lines before releasing -replace github.com/dell/gounity => ../gounity - require ( github.com/DATA-DOG/godog v0.7.13 github.com/container-storage-interface/spec v1.1.0 From d261af065f528b71b9a57a0165ddadf0289b3271 Mon Sep 17 00:00:00 2001 From: madhukirans Date: Thu, 24 Sep 2020 02:02:47 -0400 Subject: [PATCH 3/3] modified go.sum for gounity module --- go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.sum b/go.sum index 821ae6c..eafa736 100644 --- a/go.sum +++ b/go.sum @@ -65,6 +65,8 @@ github.com/dell/gofsutil v1.3.0 h1:6iDzLAdvrusB5p1yxsW45D2bC9+PUX64tJhH3tgGBN8= github.com/dell/gofsutil v1.3.0/go.mod h1:48eHpMRl0+07uGEnQ7/RE6pTOAVEl74utlGjd0QX/Os= github.com/dell/goiscsi v1.1.0 h1:0/eHKWhEjuk1AFfyBtiOqY4acW1HrC7FUyB++n2S520= github.com/dell/goiscsi v1.1.0/go.mod h1:MfuMjbKWsh/MOb0VDW20C+LFYRIOfWKGiAxWkeM5TKo= +github.com/dell/gounity v1.3.0 h1:jU8enKbzkizunYA1GLO+XuOB4I644IkDGG1VUx2DFWo= +github.com/dell/gounity v1.3.0/go.mod h1:FLT3tB1iqGQmK7TxmJZ4Qkfb7faZoaXs9c4gtuBlSTo= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=