From bc216b9e227666bcdbca4dec73518e2182f283d0 Mon Sep 17 00:00:00 2001 From: Arbel Nathan Date: Thu, 16 Dec 2021 16:52:09 +0200 Subject: [PATCH] GA v1.8.0 merge develop to master branch (#422) --- Dockerfile-csi-controller | 23 +- Dockerfile-csi-controller.test | 21 +- Dockerfile-csi-node | 5 +- Dockerfile-csi-test | 2 +- NOTICES | 542 +++------ common/config.yaml | 2 +- controller/array_action/array_action_types.py | 5 +- .../array_action/array_mediator_abstract.py | 33 +- .../array_action/array_mediator_ds8k.py | 2 +- .../array_action/array_mediator_interface.py | 3 +- controller/array_action/array_mediator_svc.py | 204 ++-- controller/array_action/array_mediator_xiv.py | 2 +- controller/array_action/config.py | 18 +- controller/array_action/utils.py | 16 + controller/common/node_info.py | 26 +- controller/controller_server/config.py | 2 - .../csi_controller_server.py | 24 +- controller/controller_server/utils.py | 32 +- controller/csi_general/csi_pb2.py | 1036 ++++++++++++----- controller/csi_general/csi_pb2_grpc.py | 380 +++--- controller/requirements.txt | 4 +- controller/scripts/csi_pb2.sh | 2 +- .../ds8k/test_array_mediator_ds8k.py | 17 +- .../svc/array_mediator_svc_test.py | 398 ++++--- .../xiv/array_mediator_xiv_tests.py | 37 +- .../tests/controller_server/utils_test.py | 91 +- .../demo-storageclass-config-secret.yaml | 2 +- ...emo-volumesnapshotclass-config-secret.yaml | 2 +- docs/SUMMARY.md | 107 +- ..._block_storage_CSI_driver_1.7.0_RN.ditamap | 47 - ..._block_storage_CSI_driver_1.7.0_UG.ditamap | 57 - docs/book_files/csi_block_storage_kc_pdfs.md | 11 +- docs/book_files/csi_block_storage_kc_rn.md | 2 +- .../csi_block_storage_kc_welcome.md | 2 +- .../csi_block_storage_kc_whatsnew.md | 4 +- docs/book_files/csi_bookconventions.dita | 18 - .../csi_gettinginfohelpandservice.dita | 20 - docs/book_files/csi_howtoorderpubs.dita | 14 - docs/book_files/csi_relatedpubs.dita | 94 -- docs/book_files/csi_rn_content.ditamap | 33 - docs/book_files/csi_rn_edition_notice.dita | 11 - docs/book_files/csi_ug_about_this_guide.dita | 15 - docs/book_files/csi_ug_audience.dita | 16 - docs/book_files/csi_ug_content.ditamap | 83 +- docs/book_files/csi_ug_edition_notice.dita | 14 - docs/book_files/csi_ug_special_notice.dita | 12 - docs/book_files/sending_comments.dita | 48 - ..._advanced.md => advanced_configuration.md} | 2 +- docs/content/configuration/configuring.md | 19 + .../configuration/configuring_topology.md | 9 + ...g_config_create_pvc.md => creating_pvc.md} | 16 +- ...ig_create_secret.md => creating_secret.md} | 4 +- ...y.md => creating_secret_topology_aware.md} | 2 +- ...statefulset.md => creating_statefulset.md} | 9 +- ...> creating_storageclass_topology_aware.md} | 46 +- ...ation.md => creating_volumereplication.md} | 6 +- ....md => creating_volumereplicationclass.md} | 4 +- ...napshots.md => creating_volumesnapshot.md} | 6 +- ...ass.md => creating_volumesnapshotclass.md} | 4 +- ...ing_volumesnapshotclass_topology_aware.md} | 4 +- .../creating_volumestorageclass.md | 69 ++ docs/content/configuration/csi_ug_config.md | 19 - .../csi_ug_config_create_storageclasses.md | 59 - .../configuration/csi_ug_config_topology.md | 9 - ..._config_expand_pvc.md => expanding_pvc.md} | 4 +- ...n_find_systemid.md => finding_systemid.md} | 0 ...ortvol.md => importing_existing_volume.md} | 14 +- .../installation/csi_ug_install_intro.md | 11 - ... => install_compatibility_requirements.md} | 53 +- ...tor_github.md => install_driver_github.md} | 6 +- ...ift.md => install_driver_openshift_web.md} | 0 ...orhub.md => install_driver_operatorhub.md} | 0 ...operator.md => install_operator_driver.md} | 6 +- docs/content/installation/installation.md | 11 + ...l_github.md => uninstall_driver_github.md} | 0 ...t.md => uninstall_driver_openshift_web.md} | 3 +- ...hub.md => uninstall_driver_operatorhub.md} | 0 .../{csi_ug_uninstall.md => uninstalling.md} | 6 +- .../{csi_ug_upgrade.md => upgrade.md} | 4 +- ..._manual.md => upgrade_manual_openshift.md} | 0 docs/content/{csi_overview.md => overview.md} | 0 .../{csi_rn_changelog.md => change_log.md} | 0 ..._changelog_1.0.0.md => changelog_1.0.0.md} | 0 ..._changelog_1.1.0.md => changelog_1.1.0.md} | 2 +- ..._changelog_1.2.0.md => changelog_1.2.0.md} | 0 ..._changelog_1.3.0.md => changelog_1.3.0.md} | 2 +- ..._changelog_1.4.0.md => changelog_1.4.0.md} | 2 +- ..._changelog_1.5.0.md => changelog_1.5.0.md} | 0 ..._changelog_1.5.1.md => changelog_1.5.1.md} | 0 ..._changelog_1.6.0.md => changelog_1.6.0.md} | 0 ..._changelog_1.7.0.md => changelog_1.7.0.md} | 4 +- docs/content/release_notes/changelog_1.8.0.md | 10 + ...ility.md => compatibility_requirements.md} | 2 +- .../release_notes/csi_rn_edition_notice.md | 4 - docs/content/release_notes/csi_rn_whatsnew.md | 22 - ...{csi_rn_knownissues.md => known_issues.md} | 6 +- .../{csi_rn_limitations.md => limitations.md} | 40 +- ...stration.md => supported_orchestration.md} | 4 +- ...csi_rn_supported_os.md => supported_os.md} | 2 +- ...ported_storage.md => supported_storage.md} | 12 +- docs/content/release_notes/whats_new.md | 25 + .../csi_ug_troubleshooting_logs.md | 41 - .../troubleshooting/log_status_collect.md | 105 ++ ...d => recovering_vol_attach_crashed_k8s.md} | 0 ..._troubleshooting.md => troubleshooting.md} | 3 +- ...ooting_misc.md => troubleshooting_misc.md} | 6 +- ...sample.md => sample_stateful_container.md} | 16 +- .../using/{csi_ug_using.md => using.md} | 0 go.mod | 2 +- go.sum | 5 +- .../device_connectivity_helper_scsigeneric.go | 101 +- ...ce_connectivity_helper_scsigeneric_test.go | 72 +- .../device_connectivity_nvmeofc.go | 52 + node/pkg/driver/driver.go | 6 +- node/pkg/driver/messages.go | 4 +- node/pkg/driver/node.go | 65 +- node/pkg/driver/node_test.go | 201 ++-- node/pkg/driver/node_utils.go | 174 +-- node/pkg/driver/node_utils_test.go | 209 +++- node/pkg/driver/version_test.go | 4 +- scripts/ci/Jenkinsfile | 8 +- 121 files changed, 2848 insertions(+), 2307 deletions(-) delete mode 100644 docs/book_files/IBM_block_storage_CSI_driver_1.7.0_RN.ditamap delete mode 100644 docs/book_files/IBM_block_storage_CSI_driver_1.7.0_UG.ditamap delete mode 100644 docs/book_files/csi_bookconventions.dita delete mode 100644 docs/book_files/csi_gettinginfohelpandservice.dita delete mode 100644 docs/book_files/csi_howtoorderpubs.dita delete mode 100644 docs/book_files/csi_relatedpubs.dita delete mode 100644 docs/book_files/csi_rn_content.ditamap delete mode 100644 docs/book_files/csi_rn_edition_notice.dita delete mode 100644 docs/book_files/csi_ug_about_this_guide.dita delete mode 100644 docs/book_files/csi_ug_audience.dita delete mode 100644 docs/book_files/csi_ug_edition_notice.dita delete mode 100644 docs/book_files/csi_ug_special_notice.dita delete mode 100644 docs/book_files/sending_comments.dita rename docs/content/configuration/{csi_ug_config_advanced.md => advanced_configuration.md} (65%) create mode 100644 docs/content/configuration/configuring.md create mode 100644 docs/content/configuration/configuring_topology.md rename docs/content/configuration/{csi_ug_config_create_pvc.md => creating_pvc.md} (86%) rename docs/content/configuration/{csi_ug_config_create_secret.md => creating_secret.md} (88%) rename docs/content/configuration/{csi_ug_config_create_secret_topology.md => creating_secret_topology_aware.md} (96%) rename docs/content/configuration/{csi_ug_config_create_statefulset.md => creating_statefulset.md} (89%) rename docs/content/configuration/{csi_ug_config_create_storageclasses_topology.md => creating_storageclass_topology_aware.md} (52%) rename docs/content/configuration/{csi_ug_config_create_replication.md => creating_volumereplication.md} (92%) rename docs/content/configuration/{csi_ug_config_create_vol_replicationclass.md => creating_volumereplicationclass.md} (88%) rename docs/content/configuration/{csi_ug_config_create_snapshots.md => creating_volumesnapshot.md} (90%) rename docs/content/configuration/{csi_ug_config_create_vol_snapshotclass.md => creating_volumesnapshotclass.md} (92%) rename docs/content/configuration/{csi_ug_config_create_vol_snapshotclass_topology.md => creating_volumesnapshotclass_topology_aware.md} (92%) create mode 100644 docs/content/configuration/creating_volumestorageclass.md delete mode 100644 docs/content/configuration/csi_ug_config.md delete mode 100644 docs/content/configuration/csi_ug_config_create_storageclasses.md delete mode 100644 docs/content/configuration/csi_ug_config_topology.md rename docs/content/configuration/{csi_ug_config_expand_pvc.md => expanding_pvc.md} (72%) rename docs/content/configuration/{csi_ug_config_replication_find_systemid.md => finding_systemid.md} (100%) rename docs/content/configuration/{csi_ug_config_advanced_importvol.md => importing_existing_volume.md} (90%) delete mode 100644 docs/content/installation/csi_ug_install_intro.md rename docs/content/installation/{csi_ug_requirements.md => install_compatibility_requirements.md} (61%) rename docs/content/installation/{csi_ug_install_operator_github.md => install_driver_github.md} (92%) rename docs/content/installation/{csi_ug_install_operator_openshift.md => install_driver_openshift_web.md} (100%) rename docs/content/installation/{csi_ug_install_operator_operatorhub.md => install_driver_operatorhub.md} (100%) rename docs/content/installation/{csi_ug_install_operator.md => install_operator_driver.md} (71%) create mode 100644 docs/content/installation/installation.md rename docs/content/installation/{csi_ug_uninstall_github.md => uninstall_driver_github.md} (100%) rename docs/content/installation/{csi_ug_uninstall_openshift.md => uninstall_driver_openshift_web.md} (84%) rename docs/content/installation/{csi_ug_uninstall_operatorhub.md => uninstall_driver_operatorhub.md} (100%) rename docs/content/installation/{csi_ug_uninstall.md => uninstalling.md} (77%) rename docs/content/installation/{csi_ug_upgrade.md => upgrade.md} (86%) rename docs/content/installation/{csi_ug_upgrade_ocp_manual.md => upgrade_manual_openshift.md} (100%) rename docs/content/{csi_overview.md => overview.md} (100%) rename docs/content/release_notes/{csi_rn_changelog.md => change_log.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.0.0.md => changelog_1.0.0.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.1.0.md => changelog_1.1.0.md} (83%) rename docs/content/release_notes/{csi_rn_changelog_1.2.0.md => changelog_1.2.0.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.3.0.md => changelog_1.3.0.md} (92%) rename docs/content/release_notes/{csi_rn_changelog_1.4.0.md => changelog_1.4.0.md} (93%) rename docs/content/release_notes/{csi_rn_changelog_1.5.0.md => changelog_1.5.0.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.5.1.md => changelog_1.5.1.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.6.0.md => changelog_1.6.0.md} (100%) rename docs/content/release_notes/{csi_rn_changelog_1.7.0.md => changelog_1.7.0.md} (61%) create mode 100644 docs/content/release_notes/changelog_1.8.0.md rename docs/content/release_notes/{csi_rn_compatibility.md => compatibility_requirements.md} (68%) delete mode 100644 docs/content/release_notes/csi_rn_edition_notice.md delete mode 100644 docs/content/release_notes/csi_rn_whatsnew.md rename docs/content/release_notes/{csi_rn_knownissues.md => known_issues.md} (90%) rename docs/content/release_notes/{csi_rn_limitations.md => limitations.md} (51%) rename docs/content/release_notes/{csi_rn_supported_orchestration.md => supported_orchestration.md} (82%) rename docs/content/release_notes/{csi_rn_supported_os.md => supported_os.md} (91%) rename docs/content/release_notes/{csi_rn_supported_storage.md => supported_storage.md} (69%) create mode 100644 docs/content/release_notes/whats_new.md delete mode 100644 docs/content/troubleshooting/csi_ug_troubleshooting_logs.md create mode 100644 docs/content/troubleshooting/log_status_collect.md rename docs/content/troubleshooting/{csi_ug_troubleshooting_node_crash.md => recovering_vol_attach_crashed_k8s.md} (100%) rename docs/content/troubleshooting/{csi_ug_troubleshooting.md => troubleshooting.md} (57%) rename docs/content/troubleshooting/{csi_ug_troubleshooting_misc.md => troubleshooting_misc.md} (92%) rename docs/content/using/{csi_ug_using_sample.md => sample_stateful_container.md} (54%) rename docs/content/using/{csi_ug_using.md => using.md} (100%) create mode 100644 node/pkg/driver/device_connectivity/device_connectivity_nvmeofc.go diff --git a/Dockerfile-csi-controller b/Dockerfile-csi-controller index 9d371c215..1b169b436 100644 --- a/Dockerfile-csi-controller +++ b/Dockerfile-csi-controller @@ -12,10 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +FROM registry.access.redhat.com/ubi8/python-38:1-75.1638364053 as builder +COPY controller/requirements.txt /tmp/ +USER root +RUN if [[ "$(uname -m)" != "x86"* ]]; then yum install -y rust-toolset; fi +USER default +RUN pip3 install --ignore-installed --default-timeout=100 --upgrade pip==21.2.4 +# avoid default boringssl lib, since it does not support z systems +ENV GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=True +RUN pip3 install -r /tmp/requirements.txt + + FROM registry.access.redhat.com/ubi8/python-38:1-68 MAINTAINER IBM Storage -ARG VERSION=1.7.0 +ARG VERSION=1.8.0 ARG BUILD_NUMBER=0 ###Required Labels @@ -29,13 +40,7 @@ LABEL name="IBM block storage CSI driver controller" \ io.k8s.description="The IBM block storage CSI driver enables container orchestrators, such as Kubernetes and OpenShift, to manage the life-cycle of persistent storage." \ io.openshift.tags=ibm,csi,ibm-block-csi-driver,ibm-block-csi-node -COPY controller/requirements.txt /driver/controller/ -RUN pip3 install --default-timeout=100 --upgrade pip==19.3.1 -# avoid default boringssl lib, since it does not support z systems -ENV GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=True -ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1 -RUN pip3 install -r /driver/controller/requirements.txt - +COPY --from=builder /opt/app-root /opt/app-root COPY ./common /driver/common COPY ./controller /driver/controller COPY ./LICENSE /licenses/ @@ -47,5 +52,3 @@ ENV PYTHONPATH=/driver # Note: UBI runs with app-user by default. ENTRYPOINT ["/driver/controller/scripts/entrypoint.sh"] - - diff --git a/Dockerfile-csi-controller.test b/Dockerfile-csi-controller.test index 2c4e616f7..663815857 100644 --- a/Dockerfile-csi-controller.test +++ b/Dockerfile-csi-controller.test @@ -16,19 +16,24 @@ # This Dockerfile.test is for running the csi controller local tests inside a container. # Its similar to the Dockerfile, but with additional requirements-tests.txt and ENTRYPOINT to run the local tests. -FROM registry.access.redhat.com/ubi8/python-38:1-68 - -COPY controller/requirements.txt /driver/controller/ -RUN pip3 install --upgrade pip==19.3.1 +FROM registry.access.redhat.com/ubi8/python-38:1-75.1638364053 as builder +COPY controller/requirements.txt /tmp/ +USER root +RUN if [[ "$(uname -m)" != "x86"* ]]; then yum install -y rust-toolset; fi +USER default +RUN pip3 install --ignore-installed --default-timeout=100 --upgrade pip==21.2.4 # avoid default boringssl lib, since it does not support z systems ENV GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=True -ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1 -RUN pip3 install -r /driver/controller/requirements.txt +RUN pip3 install -r /tmp/requirements.txt # Requires to run local testing -COPY controller/requirements-tests.txt /driver/controller/ -RUN pip3 install -r /driver/controller/requirements-tests.txt +COPY controller/requirements-tests.txt /tmp/ +RUN pip3 install -r /tmp/requirements-tests.txt + + +FROM registry.access.redhat.com/ubi8/python-38:1-68 +COPY --from=builder /opt/app-root /opt/app-root COPY ./common /driver/common COPY ./controller /driver/controller USER root diff --git a/Dockerfile-csi-node b/Dockerfile-csi-node index ead546680..1bb7f72f1 100644 --- a/Dockerfile-csi-node +++ b/Dockerfile-csi-node @@ -27,10 +27,10 @@ COPY . . RUN make ibm-block-csi-driver # Final stage -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4-208 +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5-204 MAINTAINER IBM Storage -ARG VERSION=1.7.0 +ARG VERSION=1.8.0 ARG BUILD_NUMBER=0 LABEL name="IBM block storage CSI driver node" \ @@ -67,6 +67,7 @@ RUN ln -s /chroot/chroot-host-wrapper.sh /chroot/blkid \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/multipath \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/multipathd \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/mount \ + && ln -s /chroot/chroot-host-wrapper.sh /chroot/nvme \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/resize2fs \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/sg_inq \ && ln -s /chroot/chroot-host-wrapper.sh /chroot/umount \ diff --git a/Dockerfile-csi-test b/Dockerfile-csi-test index 5422847ab..cb347ca5c 100644 --- a/Dockerfile-csi-test +++ b/Dockerfile-csi-test @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM golang:1.11 +FROM golang:1.16 ARG CSI_PARAMS=csi_params diff --git a/NOTICES b/NOTICES index 70e3f39be..add01a259 100644 --- a/NOTICES +++ b/NOTICES @@ -5,7 +5,7 @@ This file details additional third party software license agreements and third party notices and information that are required to be reproduced for the following programs: -IBM Block Storage CSI Driver version 1.7.0 +IBM Block Storage CSI Driver version 1.8.0 @@ -1409,7 +1409,7 @@ End of GNU GPL Version 3.0 License =========================================================================== END OF TERMS AND CONDITIONS FOR SEPARATELY LICENSED CODE for IBM Block -Storage CSI Driver version 1.7.0 +Storage CSI Driver version 1.8.0 =========================================================================== @@ -1420,7 +1420,7 @@ Storage CSI Driver version 1.7.0 GNU GPL and / or LGPL Source Code for: -IBM Block Storage CSI Driver 1.7.0 +IBM Block Storage CSI Driver 1.8.0 =========================================================================== @@ -1439,7 +1439,7 @@ General Public License 2.0. Red Hat Universal Base Image 8 Python 3.8 Source code to any of the above-listed packages distributed with IBM -Block Storage CSI Driver 1.7.0 is available at the website below, when +Block Storage CSI Driver 1.8.0 is available at the website below, when a URL is provided, or by sending a request to the following address or email: @@ -1468,7 +1468,7 @@ General Public License 3.0. Red Hat Universal Base Image 8 Python 3.8 Source code to any of the above-listed packages distributed with IBM -Block Storage CSI Driver 1.7.0 is available at the website below, when +Block Storage CSI Driver 1.8.0 is available at the website below, when a URL is provided, or by sending a request to the following address or email: @@ -1516,9 +1516,10 @@ the following software which IBM obtained under the terms and conditions of the Apache License Version 2.0: k8s.io/client-go version 0.18.0 -grpc-1.27.1 -grpcio version 1.20.1 -grpcio-tools version 1.20.1 +grpc-1.41.1 +grpcio version 1.41.1 +grpcio-tools version 1.41.1 +spec 1.5.0 kubernetes/apimachinery-0.18.0 kubernetes/utils-4140de9 mock-1.3.1 @@ -1740,7 +1741,7 @@ End of Apache Software License Version 2.0 =========================================================================== NOTICE file corresponding to section 4(d) of the Apache License, -Version 2.0, in this case for the grpc-1.27.1 distribution +Version 2.0, in this case for the grpc-1.41.1 distribution =========================================================================== Copyright 2014 gRPC authors. @@ -1757,6 +1758,7 @@ See the License for the specific language governing permissions and limitations under the License. + =========================================================================== NOTICE file corresponding to section 4(d) of the Apache License, Version 2.0, in this case for the yaml version 2.27.1 distribution @@ -1816,66 +1818,45 @@ END OF base58-2.0.0 NOTICES AND INFORMATION @@@@@@@@@@@@ =========================================================================== -grpc-1.27.1: The Program includes grpc-1.27.1 software. IBM obtained -portions of the grpc-1.27.1 software under the terms and conditions of +grpc-1.41.1: The Program includes grpc-1.41.1 software. IBM obtained +portions of the grpc-1.41.1 software under the terms and conditions of the following license(s): --------------------------------------------------------------------------- -Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the project nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ---------------------------------------------------------------------------- - -Copyright (c) 2015 Lars Kanis - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---------------------------------------------------------------------------- -Copyright (c) 2009-2011, Google Inc. +# Copyright 2019, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +==================================================================================== + + +Copyright (c) 2009-2021, Google LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -1886,14 +1867,14 @@ modification, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of any other + * Neither the name of Google LLC nor the names of any other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -EVENT SHALL GOOGLE INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +EVENT SHALL GOOGLE LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER @@ -1901,11 +1882,63 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- +==================================================================================== + +xxHash Library +Copyright (c) 2012-2020 Yann Collet +All rights reserved. + +BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + +==================================================================================== + +/* Copyright (C) 2009 - 2013 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +==================================================================================== Lunit License ------------- +Lunit is written by Michael Roth and is licensed +under the terms of the MIT license reproduced below. + +======================================================================== + Copyright (c) 2004-2010 Michael Roth Permission is hereby granted, free of charge, to any person @@ -1927,325 +1960,56 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -=========================================================================== -END OF grpc-1.27.1 NOTICES AND INFORMATION -=========================================================================== - - -@@@@@@@@@@@@ -=========================================================================== -grpcio version 1.20.1: The Program includes grpcio version 1.20.1 -software. IBM obtained portions of the grpcio version 1.20.1 software -under the terms and conditions of the following license(s): ---------------------------------------------------------------------------- - -Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. Neither the name of the project nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ---------------------------------------------------------------------------- - -Copyright (c) 2011 Petteri Aimonen - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in -a product, an acknowledgment in the product documentation would be -appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not -be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - ---------------------------------------------------------------------------- - -Copyright (c) 2011 Petteri Aimonen - -This software is provided 'as-is', without any express or -implied warranty. In no event will the authors be held liable -for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you - must not claim that you wrote the original software. If you use - this software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source - distribution. - ---------------------------------------------------------------------------- - -Copyright 2015, Google Inc. -Copyright 2016, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------- - -Copyright (c) 2015, Google Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ---------------------------------------------------------------------------- - -Protocol Buffers - Google's data interchange format -Copyright 2008 Google Inc. All rights reserved. -https://developers.google.com/protocol-buffers/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ---------------------------------------------------------------------------- - -Copyright 2009 Kitware, Inc. -Copyright 2009-2011 Philip Lowman -Copyright 2008 Esben Mose Hansen, Ange Optimization ApS - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -* Neither the names of Kitware, Inc., the Insight Software Consortium, - nor the names of their contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -=========================================================================== -END OF grpcio version 1.20.1 NOTICES AND INFORMATION -=========================================================================== - - -@@@@@@@@@@@@ -=========================================================================== -grpcio-tools version 1.20.1: The Program includes grpcio-tools version -1.20.1 software. IBM obtained portions of the grpcio-tools version -1.20.1 software under the terms and conditions of the following -license(s): ---------------------------------------------------------------------------- - -Copyright 2005 Google Inc. All rights reserved. -Copyright 2006 Google Inc. All rights reserved. -Copyright 2007 Google Inc. All rights reserved. -Copyright 2008 Google Inc. All rights reserved. -Copyright 2012 Google Inc. All rights reserved. -Copyright 2014 Google Inc. All rights reserved. -https://developers.google.com/protocol-buffers/ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -=========================================================================== -END OF grpcio-tools version 1.20.1 NOTICES AND INFORMATION -=========================================================================== - - -@@@@@@@@@@@@ -=========================================================================== -logrus version 1.4.2: The Program includes logrus version 1.4.2 -software. IBM obtained the logrus version 1.4.2 software under the -terms and conditions of the following license(s): ---------------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Simon Eskildsen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -=========================================================================== -END OF logrus version 1.4.2 NOTICES AND INFORMATION -=========================================================================== - - -@@@@@@@@@@@@ -=========================================================================== -munch version 2.3.2: The Program includes munch version 2.3.2 software. -IBM obtained the munch version 2.3.2 software under the terms and -conditions of the following license(s): ---------------------------------------------------------------------------- - -Copyright (c) 2010 David Schoonover - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -=========================================================================== -END OF munch version 2.3.2 NOTICES AND INFORMATION +======================================================================== + +==================================================================================== + + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * This is an adaptation of Android's implementation of RFC 6724 + * (in Android's getaddrinfo.c). It has some cosmetic differences + * from Android's getaddrinfo.c, but Android's getaddrinfo.c was + * used as a guide or example of a way to implement the RFC 6724 spec when + * this was written. + */ + +==================================================================================== + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +=========================================================================== +END OF grpc-1.41.1 NOTICES AND INFORMATION =========================================================================== @@ -2302,7 +2066,6 @@ IBM obtained the pyyaml version 5.4 software under the terms and conditions of the following license(s): --------------------------------------------------------------------------- - Copyright (c) 2017-2021 Ingy döt Net Copyright (c) 2006-2016 Kirill Simonov @@ -2325,7 +2088,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - =========================================================================== END OF pyyaml version 5.4 NOTICES AND INFORMATION =========================================================================== @@ -2498,6 +2260,6 @@ END OF yaml-2.2.8 NOTICES AND INFORMATION =========================================================================== END OF NOTICES AND INFORMATION FOR IBM Block Storage CSI -Driver 1.7.0 +Driver 1.8.0 =========================================================================== diff --git a/common/config.yaml b/common/config.yaml index 448edec09..ee1f12efc 100644 --- a/common/config.yaml +++ b/common/config.yaml @@ -1,6 +1,6 @@ identity: name: block.csi.ibm.com - version: 1.7.0 + version: 1.8.0 capabilities: Service: [CONTROLLER_SERVICE, VOLUME_ACCESSIBILITY_CONSTRAINTS] VolumeExpansion: ONLINE diff --git a/controller/array_action/array_action_types.py b/controller/array_action/array_action_types.py index 4a91cd1a9..922a85653 100644 --- a/controller/array_action/array_action_types.py +++ b/controller/array_action/array_action_types.py @@ -28,11 +28,12 @@ class Snapshot: class Host: - def __init__(self, host_id, host_name, iscsi_names, wwns): + def __init__(self, host_id, host_name, nqn, wwns, iscsi_names): self.id = host_id self.name = host_name - self.iscsi_names = iscsi_names + self.nqn = nqn self.wwns = wwns + self.iscsi_names = iscsi_names class Replication: diff --git a/controller/array_action/array_mediator_abstract.py b/controller/array_action/array_mediator_abstract.py index 8c78914cb..262566b48 100644 --- a/controller/array_action/array_mediator_abstract.py +++ b/controller/array_action/array_mediator_abstract.py @@ -3,8 +3,9 @@ import controller.array_action.errors as array_errors from controller.array_action.array_mediator_interface import ArrayMediator -from controller.array_action.config import FC_CONNECTIVITY_TYPE, ISCSI_CONNECTIVITY_TYPE +from controller.array_action.config import NVME_OVER_FC_CONNECTIVITY_TYPE, FC_CONNECTIVITY_TYPE, ISCSI_CONNECTIVITY_TYPE from controller.array_action.errors import NoConnectionAvailableException, UnsupportedConnectivityTypeError +from controller.array_action.utils import convert_scsi_id_to_nguid from controller.common.csi_logger import get_stdout_logger from controller.controller_server import utils @@ -17,13 +18,12 @@ class ArrayMediatorAbstract(ArrayMediator, ABC): def map_volume_by_initiators(self, vol_id, initiators): host_name, connectivity_types = self.get_host_by_host_identifiers(initiators) - logger.debug( - "hostname : {}, connectivity_types : {}".format(host_name, - connectivity_types)) + logger.debug("hostname : {}, connectivity_types : {}".format(host_name, connectivity_types)) connectivity_type = utils.choose_connectivity_type(connectivity_types) - - if FC_CONNECTIVITY_TYPE == connectivity_type: + if NVME_OVER_FC_CONNECTIVITY_TYPE == connectivity_type: + array_initiators = [] + elif FC_CONNECTIVITY_TYPE == connectivity_type: array_initiators = self.get_array_fc_wwns(host_name) elif ISCSI_CONNECTIVITY_TYPE == connectivity_type: array_initiators = self.get_iscsi_targets_by_iqn(host_name) @@ -41,25 +41,20 @@ def map_volume_by_initiators(self, vol_id, initiators): return mappings[mapping], connectivity_type, array_initiators raise array_errors.VolumeMappedToMultipleHostsError(mappings) - logger.debug( - "no mappings were found for volume. mapping volume : {0} to host : {1}".format( - vol_id, host_name)) + logger.debug("no mappings were found for volume. mapping volume : {0} to host : {1}".format(vol_id, host_name)) try: - lun = self.map_volume(vol_id, host_name) + lun = self.map_volume(vol_id, host_name, connectivity_type) logger.debug("lun : {}".format(lun)) except array_errors.LunAlreadyInUseError as ex: - logger.warning( - "Lun was already in use. re-trying the operation. {0}".format( - ex)) + logger.warning("Lun was already in use. re-trying the operation. {0}".format(ex)) for i in range(self.max_lun_retries - 1): try: - lun = self.map_volume(vol_id, host_name) + lun = self.map_volume(vol_id, host_name, connectivity_type) break except array_errors.LunAlreadyInUseError as inner_ex: logger.warning( - "re-trying map volume. try #{0}. {1}".format(i, - inner_ex)) + "re-trying map volume. try #{0}. {1}".format(i, inner_ex)) else: # will get here only if the for statement is false. raise ex @@ -67,6 +62,8 @@ def map_volume_by_initiators(self, vol_id, initiators): @retry(NoConnectionAvailableException, tries=11, delay=1) def unmap_volume_by_initiators(self, vol_id, initiators): - host_name, _ = self.get_host_by_host_identifiers(initiators) - + host_name, connectivity_types = self.get_host_by_host_identifiers(initiators) + connectivity_type = utils.choose_connectivity_type(connectivity_types) + if connectivity_type == NVME_OVER_FC_CONNECTIVITY_TYPE: + vol_id = convert_scsi_id_to_nguid(vol_id) self.unmap_volume(vol_id, host_name) diff --git a/controller/array_action/array_mediator_ds8k.py b/controller/array_action/array_mediator_ds8k.py index 1b4e0c3b2..7b744e3f5 100644 --- a/controller/array_action/array_mediator_ds8k.py +++ b/controller/array_action/array_mediator_ds8k.py @@ -401,7 +401,7 @@ def get_volume_mappings(self, volume_id): raise ex @convert_scsi_ids_to_array_ids() - def map_volume(self, volume_id, host_name): + def map_volume(self, volume_id, host_name, connectivity_type): logger.debug("Mapping volume {} to host {}".format(volume_id, host_name)) try: mapping = self.client.map_volume_to_host(host_name, volume_id) diff --git a/controller/array_action/array_mediator_interface.py b/controller/array_action/array_mediator_interface.py index c22d2010d..67df425bf 100644 --- a/controller/array_action/array_mediator_interface.py +++ b/controller/array_action/array_mediator_interface.py @@ -151,13 +151,14 @@ def get_volume_mappings(self, volume_id): raise NotImplementedError @abstractmethod - def map_volume(self, volume_id, host_name): + def map_volume(self, volume_id, host_name, connectivity_type): """ This function will find the next available lun for the host and map the volume to it. Args: volume_id : the volume WWN. host_name : the name of the host to map the volume to. + connectivity_type : connectivity type (e.g. iscsi, fc, etc...) Returns: lun : the lun_id the volume was mapped to. diff --git a/controller/array_action/array_mediator_svc.py b/controller/array_action/array_mediator_svc.py index ef01f2577..18875de07 100644 --- a/controller/array_action/array_mediator_svc.py +++ b/controller/array_action/array_mediator_svc.py @@ -1,5 +1,6 @@ from collections import defaultdict from io import StringIO +from random import choice from pysvc import errors as svc_errors from pysvc.unified.client import connect @@ -12,7 +13,7 @@ from controller.array_action.array_action_types import Volume, Snapshot, Host, Replication from controller.array_action.array_mediator_abstract import ArrayMediatorAbstract from controller.array_action.svc_cli_result_reader import SVCListResultsReader -from controller.array_action.utils import classproperty, bytes_to_string +from controller.array_action.utils import classproperty, bytes_to_string, convert_scsi_id_to_nguid from controller.common import settings from controller.common.csi_logger import get_stdout_logger @@ -42,11 +43,14 @@ LIST_HOSTS_CMD_FORMAT = 'lshost {HOST_ID};' HOST_ID_PARAM = 'id' HOST_NAME_PARAM = 'name' -HOST_ISCSI_NAMES_PARAM = 'iscsi_name' +HOST_NQN_PARAM = 'nqn' HOST_WWPNS_PARAM = 'WWPN' +HOST_ISCSI_NAMES_PARAM = 'iscsi_name' HOST_PORTSET_ID = 'portset_id' HOSTS_LIST_ERR_MSG_MAX_LENGTH = 300 +LUN_INTERVAL = 128 + FCMAP_STATUS_DONE = 'idle_or_copied' RCRELATIONSHIP_STATE_IDLE = 'idling' RCRELATIONSHIP_STATE_READY = 'consistent_synchronized' @@ -71,6 +75,21 @@ def is_warning_message(ex): return False +def _get_space_efficiency_kwargs(space_efficiency): + if space_efficiency: + space_efficiency = space_efficiency.lower() + if space_efficiency == config.SPACE_EFFICIENCY_THIN: + return {'thin': True} + if space_efficiency == config.SPACE_EFFICIENCY_COMPRESSED: + return {'compressed': True} + if space_efficiency == config.SPACE_EFFICIENCY_DEDUPLICATED_THIN: + return {'deduplicated': True, 'thin': True} + if space_efficiency in (config.SPACE_EFFICIENCY_DEDUPLICATED, + config.SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED): + return {'deduplicated': True, 'compressed': True} + return {} + + def build_kwargs_from_parameters(space_efficiency, pool_name, volume_name, volume_size): cli_kwargs = {} @@ -80,16 +99,8 @@ def build_kwargs_from_parameters(space_efficiency, pool_name, volume_name, 'size': volume_size, 'pool': pool_name }) - # if space efficiency == None, create default space efficiency volume thick - if space_efficiency: - space_efficiency = space_efficiency.lower() - if space_efficiency == config.SPACE_EFFICIENCY_THIN: - cli_kwargs.update({'thin': True}) - elif space_efficiency == config.SPACE_EFFICIENCY_COMPRESSED: - cli_kwargs.update({'compressed': True}) - elif space_efficiency == config.SPACE_EFFICIENCY_DEDUPLICATED: - cli_kwargs.update({'compressed': True, 'deduplicated': True}) - + space_efficiency_kwargs = _get_space_efficiency_kwargs(space_efficiency) + cli_kwargs.update(space_efficiency_kwargs) return cli_kwargs @@ -128,7 +139,10 @@ def _get_cli_volume_space_efficiency(cli_volume): space_efficiency = config.SPACE_EFFICIENCY_COMPRESSED if hasattr(cli_volume, "deduplicated_copy"): if cli_volume.deduplicated_copy == YES: - space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED + if cli_volume.se_copy == YES: + space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED_THIN + else: + space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED return space_efficiency @@ -291,6 +305,8 @@ def _get_source_volume_wwn_if_exists(self, target_cli_object): fcmap = self._get_fcmap_as_target_if_exists(target_cli_object.name) if not fcmap: return None + if self._is_in_remote_copy_relationship(fcmap): + return None source_volume_name = fcmap.source_vdisk_name return self._get_wwn_by_volume_name_if_exists(source_volume_name) @@ -306,10 +322,13 @@ def _get_object_fcmaps(self, object_name): all_fcmaps.extend(self._get_fcmaps_as_source_if_exist(object_name)) return all_fcmaps - def _expand_cli_volume(self, cli_volume, increase_in_bytes): + def _expand_cli_volume(self, cli_volume, increase_in_bytes, is_hyperswap): volume_name = cli_volume.name try: - self.client.svctask.expandvdisksize(vdisk_id=volume_name, unit='b', size=increase_in_bytes) + if is_hyperswap: + self.client.svctask.expandvolume(object_id=volume_name, unit='b', size=increase_in_bytes) + else: + self.client.svctask.expandvdisksize(vdisk_id=volume_name, unit='b', size=increase_in_bytes) except (svc_errors.CommandExecutionError, CLIFailureError) as ex: if not is_warning_message(ex.my_message): logger.warning("Failed to expand volume {}".format(volume_name)) @@ -325,11 +344,12 @@ def expand_volume(self, volume_id, required_bytes): volume_name = cli_volume.name fcmaps = self._get_object_fcmaps(volume_name) self._safe_delete_fcmaps(volume_name, fcmaps) + is_hyperswap = any(self._is_in_remote_copy_relationship(fcmap) for fcmap in fcmaps) current_size = int(cli_volume.capacity) final_size = self._convert_size_bytes(required_bytes) increase_in_bytes = final_size - current_size - self._expand_cli_volume(cli_volume, increase_in_bytes) + self._expand_cli_volume(cli_volume, increase_in_bytes, is_hyperswap) logger.info( "Finished volume expansion. id : {0}. volume increased by {1} bytes".format(volume_id, increase_in_bytes)) @@ -344,11 +364,12 @@ def _get_fcmaps(self, volume_name, endpoint_type): def validate_supported_space_efficiency(self, space_efficiency): logger.debug("validate_supported_space_efficiency for " "space efficiency : {0}".format(space_efficiency)) - if (space_efficiency and space_efficiency.lower() not in [config.SPACE_EFFICIENCY_THIN, config.SPACE_EFFICIENCY_THICK, config.SPACE_EFFICIENCY_COMPRESSED, - config.SPACE_EFFICIENCY_DEDUPLICATED]): + config.SPACE_EFFICIENCY_DEDUPLICATED, + config.SPACE_EFFICIENCY_DEDUPLICATED_THIN, + config.SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED]): logger.error("space efficiency value is not " "supported {0}".format(space_efficiency)) raise array_errors.SpaceEfficiencyNotSupported( @@ -372,15 +393,22 @@ def _get_wwn_by_volume_name_if_exists(self, volume_name): logger.debug("found wwn : {0}".format(wwn)) return wwn - def _get_cli_volume_by_wwn(self, volume_id, not_exist_err=False): - filter_value = 'vdisk_UID=' + volume_id + def _lsvdisk_by_uid(self, vdisk_uid): + filter_value = 'vdisk_UID=' + vdisk_uid try: - cli_volume = self.client.svcinfo.lsvdisk(bytes=True, filtervalue=filter_value).as_single_element + return self.client.svcinfo.lsvdisk(bytes=True, filtervalue=filter_value).as_single_element except (svc_errors.CommandExecutionError, CLIFailureError) as ex: if not is_warning_message(ex.my_message): if any(msg_id in ex.my_message for msg_id in (NON_ASCII_CHARS, INVALID_FILTER_VALUE)): raise array_errors.IllegalObjectID(ex.my_message) raise ex + return None + + def _get_cli_volume_by_wwn(self, volume_id, not_exist_err=False): + cli_volume = self._lsvdisk_by_uid(volume_id) + if not cli_volume: + volume_nguid = convert_scsi_id_to_nguid(volume_id) + cli_volume = self._lsvdisk_by_uid(volume_nguid) if not cli_volume and not_exist_err: raise array_errors.ObjectNotFoundError(volume_id) return cli_volume @@ -607,10 +635,39 @@ def _create_snapshot(self, target_volume_name, source_cli_volume, space_efficien self._rollback_create_snapshot(target_volume_name) raise ex + def _get_pool_site(self, pool): + filter_value = 'name={}'.format(pool) + cli_pool = self.client.svcinfo.lsmdiskgrp(filtervalue=filter_value).as_single_element + if cli_pool: + return cli_pool.site_name + raise array_errors.PoolDoesNotExist(pool, self.endpoint) + + def _is_cli_volume_in_site(self, cli_volume, site_name): + volume_site_name = self._get_pool_site(cli_volume.mdisk_grp_name) + return volume_site_name == site_name + + def _get_rcrelationships_as_master_in_cluster(self, volume_name): + filter_value = 'master_vdisk_name={}:aux_cluster_id={}'.format(volume_name, self.identifier) + return self._lsrcrelationship(filter_value).as_list + + def _get_cli_volume_in_pool_site(self, volume_name, pool_name): + cli_volume = self._get_cli_volume(volume_name) + if not pool_name: + return cli_volume + pool_site_name = self._get_pool_site(pool_name) + if self._is_cli_volume_in_site(cli_volume, pool_site_name): + return cli_volume + rcrelationships = self._get_rcrelationships_as_master_in_cluster(volume_name) + for rcrelationship in rcrelationships: + other_cli_volume = self._get_cli_volume(rcrelationship.aux_vdisk_name) + if self._is_cli_volume_in_site(other_cli_volume, pool_site_name): + return other_cli_volume + raise RuntimeError('could not find a volume for {} in site {}'.format(volume_name, pool_site_name)) + def create_snapshot(self, volume_id, snapshot_name, space_efficiency, pool): logger.info("creating snapshot '{0}' from volume '{1}'".format(snapshot_name, volume_id)) source_volume_name = self._get_volume_name_by_wwn(volume_id) - source_cli_volume = self._get_cli_volume(source_volume_name) + source_cli_volume = self._get_cli_volume_in_pool_site(source_volume_name, pool) target_cli_volume = self._create_snapshot(snapshot_name, source_cli_volume, space_efficiency, pool) logger.info("finished creating snapshot '{0}' from volume '{1}'".format(snapshot_name, volume_id)) return self._generate_snapshot_response(target_cli_volume, source_cli_volume.vdisk_UID) @@ -626,29 +683,31 @@ def delete_snapshot(self, snapshot_id): def get_host_by_host_identifiers(self, initiators): logger.debug("Getting host name for initiators : {0}".format(initiators)) detailed_hosts_list = self._get_detailed_hosts_list() - iscsi_host, fc_host = None, None + nvme_host, fc_host, iscsi_host = None, None, None + connectivity_types = set() for host in detailed_hosts_list: - if initiators.is_array_iscsi_iqns_match(host.iscsi_names): - iscsi_host = host.name - logger.debug("found iscsi iqn in list : {0} for host : " - "{1}".format(initiators.iscsi_iqn, iscsi_host)) + if initiators.is_array_nvme_nqn_match(host.nqn): + nvme_host = host.name + connectivity_types.add(config.NVME_OVER_FC_CONNECTIVITY_TYPE) + logger.debug("found nvme nqn in list : {0} for host : " + "{1}".format(initiators.nvme_nqn, nvme_host)) if initiators.is_array_wwns_match(host.wwns): fc_host = host.name + connectivity_types.add(config.FC_CONNECTIVITY_TYPE) logger.debug("found fc wwns in list : {0} for host : " "{1}".format(initiators.fc_wwns, fc_host)) - if iscsi_host and fc_host: - if iscsi_host == fc_host: - return fc_host, [config.ISCSI_CONNECTIVITY_TYPE, - config.FC_CONNECTIVITY_TYPE] + if initiators.is_array_iscsi_iqns_match(host.iscsi_names): + iscsi_host = host.name + connectivity_types.add(config.ISCSI_CONNECTIVITY_TYPE) + logger.debug("found iscsi iqn in list : {0} for host : " + "{1}".format(initiators.iscsi_iqn, iscsi_host)) + if not connectivity_types: + logger.debug("could not find host by using initiators: {0} ".format(initiators)) + raise array_errors.HostNotFoundError(initiators) + host_name = self._get_host_name_if_equal(nvme_host, fc_host, iscsi_host) + if not host_name: raise array_errors.MultipleHostsFoundError(initiators, fc_host) - if iscsi_host: - logger.debug("found host : {0} with iqn : {1}".format(iscsi_host, initiators.iscsi_iqn)) - return iscsi_host, [config.ISCSI_CONNECTIVITY_TYPE] - if fc_host: - logger.debug("found host : {0} with fc wwn : {1}".format(fc_host, initiators.fc_wwns)) - return fc_host, [config.FC_CONNECTIVITY_TYPE] - logger.debug("can not found host by using initiators: {0} ".format(initiators)) - raise array_errors.HostNotFoundError(initiators) + return host_name, list(connectivity_types) def _get_detailed_hosts_list(self): logger.debug("Getting detailed hosts list on array {0}".format(self.endpoint)) @@ -672,9 +731,10 @@ def _get_detailed_hosts_by_raw_output(self, detailed_hosts_list_raw_output): for host_details in hosts_reader: host_id = host_details.get(HOST_ID_PARAM) host_name = host_details.get(HOST_NAME_PARAM) - iscsi_names = host_details.get_as_list(HOST_ISCSI_NAMES_PARAM) + nqn = host_details.get_as_list(HOST_NQN_PARAM) wwns = host_details.get_as_list(HOST_WWPNS_PARAM) - host = Host(host_id, host_name, iscsi_names, wwns) + iscsi_names = host_details.get_as_list(HOST_ISCSI_NAMES_PARAM) + host = Host(host_id, host_name, nqn, wwns, iscsi_names) res.append(host) return res @@ -728,8 +788,8 @@ def _get_used_lun_ids_from_host(self, host_name): return luns_in_use - def get_first_free_lun(self, host_name): - logger.debug("getting first free lun id for " + def _get_free_lun(self, host_name): + logger.debug("getting random free lun id for " "host :{0}".format(host_name)) lun = None luns_in_use = self._get_used_lun_ids_from_host(host_name) @@ -739,18 +799,18 @@ def get_first_free_lun(self, host_name): # can be mapped to a single host. (Note that some hosts such as linux # do not support more than 255 or 511 mappings today irrespective of # our constraint). - for candidate in range(self.MIN_LUN_NUMBER, self.MAX_LUN_NUMBER + 1): - if str(candidate) not in luns_in_use: - logger.debug("First available LUN number for {0} is " - "{1}".format(host_name, str(candidate))) - lun = str(candidate) - break - if not lun: + lun_range_gen = range(self.MIN_LUN_NUMBER, self.MAX_LUN_NUMBER + 1) + lun_range = [str(lun) for lun in lun_range_gen] + free_luns = [lun for lun in lun_range if lun not in luns_in_use] + free_luns_in_interval = free_luns[:LUN_INTERVAL] + if free_luns: + lun = choice(free_luns_in_interval) + else: raise array_errors.NoAvailableLunError(host_name) - logger.debug("The first available lun is : {0}".format(lun)) + logger.debug("The chosen available lun is : {0}".format(lun)) return lun - def map_volume(self, volume_id, host_name): + def map_volume(self, volume_id, host_name, connectivity_type): logger.debug("mapping volume : {0} to host : " "{1}".format(volume_id, host_name)) vol_name = self._get_volume_name_by_wwn(volume_id) @@ -759,10 +819,11 @@ def map_volume(self, volume_id, host_name): 'object_id': vol_name, 'force': True } - + lun = "" try: - lun = self.get_first_free_lun(host_name) - cli_kwargs.update({'scsi': lun}) + if connectivity_type != config.NVME_OVER_FC_CONNECTIVITY_TYPE: + lun = self._get_free_lun(host_name) + cli_kwargs.update({'scsi': lun}) self.client.svctask.mkvdiskhostmap(**cli_kwargs) except (svc_errors.CommandExecutionError, CLIFailureError) as ex: if not is_warning_message(ex.my_message): @@ -892,7 +953,7 @@ def _get_host_portset_id(self, host_name): return cli_host.get(HOST_PORTSET_ID) def _get_replication_endpoint_type(self, rcrelationship): - if self._identifier == rcrelationship.master_cluster_id: + if self.identifier == rcrelationship.master_cluster_id: return ENDPOINT_TYPE_MASTER return ENDPOINT_TYPE_AUX @@ -942,12 +1003,12 @@ def _generate_replication_response(self, rcrelationship, volume_internal_id, oth is_ready=is_ready, is_primary=is_primary) - def _get_lsrcrelationship(self, filter_value): + def _lsrcrelationship(self, filter_value): return self.client.svcinfo.lsrcrelationship(filtervalue=filter_value) def _get_rcrelationship_by_name(self, replication_name, not_exist_error=True): filter_value = 'RC_rel_name={0}'.format(replication_name) - rcrelationship = self._get_lsrcrelationship(filter_value).as_single_element + rcrelationship = self._lsrcrelationship(filter_value).as_single_element if not rcrelationship and not_exist_error: raise array_errors.ObjectNotFoundError(replication_name) return rcrelationship @@ -964,21 +1025,23 @@ def _get_rcrelationships(self, cli_volume_id, other_cli_volume_id, other_system_ OTHER_END=other_endpoint_type, OTHER_VDISK_ID=other_cli_volume_id, OTHER_CLUSTER_ID=other_system_id) - return self._get_lsrcrelationship(filter_value).as_list + return self._lsrcrelationship(filter_value).as_list def _get_rcrelationship(self, cli_volume_id, other_cli_volume_id, other_system_id): rcrelationships = self._get_rcrelationships(cli_volume_id, other_cli_volume_id, other_system_id, as_master=True) rcrelationships.extend(self._get_rcrelationships(cli_volume_id, other_cli_volume_id, other_system_id, as_master=False)) - if len(rcrelationships) != 1: - logger.warning('found {0} rcrelationships for volume id {1} ' - 'with volume id {2} of system {3}'.format(len(rcrelationships), - cli_volume_id, - other_cli_volume_id, - other_system_id)) - return None - return rcrelationships[0] + if len(rcrelationships) > 1: + error_message = ('found {0} rcrelationships for volume id {1} ' + 'with volume id {2} of system {3}: {4}'.format(len(rcrelationships), + cli_volume_id, + other_cli_volume_id, + other_system_id, + rcrelationships)) + logger.error(error_message) + raise RuntimeError(error_message) + return rcrelationships[0] if rcrelationships else None def get_replication(self, volume_internal_id, other_volume_internal_id, other_system_id): rcrelationship = self._get_rcrelationship(volume_internal_id, other_volume_internal_id, other_system_id) @@ -1087,3 +1150,10 @@ def demote_replication_volume(self, replication_name): rcrelationship = self._get_rcrelationship_by_name(replication_name) endpoint_type_to_promote = self._get_replication_other_endpoint_type(rcrelationship) self._ensure_endpoint_is_primary(rcrelationship, endpoint_type_to_promote) + + def _get_host_name_if_equal(self, nvme_host, fc_host, iscsi_host): + unique_names = {nvme_host, iscsi_host, fc_host} + unique_names.discard(None) + if len(unique_names) == 1: + return unique_names.pop() + return None diff --git a/controller/array_action/array_mediator_xiv.py b/controller/array_action/array_mediator_xiv.py index 6864ab1c3..c359e4d14 100644 --- a/controller/array_action/array_mediator_xiv.py +++ b/controller/array_action/array_mediator_xiv.py @@ -423,7 +423,7 @@ def _get_next_available_lun(self, host_name): logger.debug("next random available lun is : {0}".format(lun)) return lun - def map_volume(self, volume_id, host_name): + def map_volume(self, volume_id, host_name, connectivity_type): logger.debug("mapping volume : {0} to host : {1}".format(volume_id, host_name)) vol_name = self._get_object_name_by_wwn(volume_id) lun = self._get_next_available_lun(host_name) diff --git a/controller/array_action/config.py b/controller/array_action/config.py index d41f1ba89..7e6429864 100644 --- a/controller/array_action/config.py +++ b/controller/array_action/config.py @@ -1,13 +1,19 @@ -ISCSI_CONNECTIVITY_TYPE = "iscsi" +NVME_OVER_FC_CONNECTIVITY_TYPE = "nvmeofc" FC_CONNECTIVITY_TYPE = "fc" -SPACE_EFFICIENCY_THIN = 'thin' -SPACE_EFFICIENCY_COMPRESSED = 'compressed' -SPACE_EFFICIENCY_DEDUPLICATED = 'deduplicated' -SPACE_EFFICIENCY_THICK = 'thick' -SPACE_EFFICIENCY_NONE = 'none' +ISCSI_CONNECTIVITY_TYPE = "iscsi" +SPACE_EFFICIENCY_THIN = "thin" +SPACE_EFFICIENCY_COMPRESSED = "compressed" +SPACE_EFFICIENCY_DEDUPLICATED = "deduplicated" +SPACE_EFFICIENCY_DEDUPLICATED_THIN = "dedup_thin" +SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED = "dedup_compressed" +SPACE_EFFICIENCY_THICK = "thick" +SPACE_EFFICIENCY_NONE = "none" REPLICATION_COPY_TYPE_SYNC = "sync" REPLICATION_COPY_TYPE_ASYNC = "async" REPLICATION_DEFAULT_COPY_TYPE = REPLICATION_COPY_TYPE_SYNC # volume context CONTEXT_POOL = "pool" + +WWN_OUI_END = 7 +WWN_VENDOR_IDENTIFIER_END = 16 diff --git a/controller/array_action/utils.py b/controller/array_action/utils.py index eb5b78114..09c1eb7c9 100644 --- a/controller/array_action/utils.py +++ b/controller/array_action/utils.py @@ -1,11 +1,27 @@ import encodings + +from controller.array_action.config import WWN_OUI_END, WWN_VENDOR_IDENTIFIER_END +from controller.common.csi_logger import get_stdout_logger + UTF_8 = encodings.utf_8.getregentry().name +logger = get_stdout_logger() + def bytes_to_string(input_as_bytes): return input_as_bytes.decode(UTF_8) if input_as_bytes else "" +def convert_scsi_id_to_nguid(volume_id): + logger.debug("Converting scsi uuid : {} to nguid".format(volume_id)) + oui = volume_id[1:WWN_OUI_END] + vendor_identifier = volume_id[WWN_OUI_END:WWN_VENDOR_IDENTIFIER_END] + vendor_identifier_extension = volume_id[WWN_VENDOR_IDENTIFIER_END:] + final_nguid = ''.join((vendor_identifier_extension, oui, '0', vendor_identifier)) + logger.debug("Nguid is : {}".format(final_nguid)) + return final_nguid + + class classproperty: def __init__(self, function): diff --git a/controller/common/node_info.py b/controller/common/node_info.py index 70e328c5f..cebff84b4 100644 --- a/controller/common/node_info.py +++ b/controller/common/node_info.py @@ -8,10 +8,10 @@ def __init__(self, node_id): Args: node_id: ,, """ - node_name, fc_wwns_str, iscsi_iqn = utils.get_node_id_info(node_id) + node_name, nvme_nqn, fc_wwns_str, iscsi_iqn = utils.get_node_id_info(node_id) fc_wwns = fc_wwns_str.split(config.PARAMETERS_FC_WWN_DELIMITER) self.node_name = node_name - self.initiators = Initiators(iscsi_iqn.strip(), fc_wwns) + self.initiators = Initiators(nvme_nqn.strip(), fc_wwns, iscsi_iqn.strip()) class Initiators: @@ -19,14 +19,17 @@ class Initiators: Object containing node initiators (e.g. iqn, fc_wwns) """ - def __init__(self, iscsi_iqn, fc_wwns): + def __init__(self, nvme_nqn, fc_wwns, iscsi_iqn): """ Args: - iscsi_iqn : iqn + nvme_nqn: nqn fc_wwns : list of fc wwns + iscsi_iqn : iqn """ - self.iscsi_iqn = iscsi_iqn + self.nvme_nqn = nvme_nqn self.fc_wwns = fc_wwns + self.iscsi_iqn = iscsi_iqn + self._nvme_nqn_lowercase = nvme_nqn.lower() self._fc_wwns_lowercase_set = set(wwn.lower() for wwn in fc_wwns) self._iscsi_iqn_lowercase = iscsi_iqn.lower() @@ -52,5 +55,16 @@ def is_array_iscsi_iqns_match(self, host_iqns): host_iqns_lower = [iqn.lower() for iqn in host_iqns] return self._iscsi_iqn_lowercase in host_iqns_lower + def is_array_nvme_nqn_match(self, host_nqns): + """ + Args: + host_nqns: storage host nqns list + + Returns: + Is current host nqns matches + """ + host_nqns_lower = [nqn.lower() for nqn in host_nqns] + return self._nvme_nqn_lowercase in host_nqns_lower + def __str__(self): - return "iscsi_iqn: " + self.iscsi_iqn + ", fc_wwns: " + ",".join(self.fc_wwns) + return "nvme_nqn: {}, fc_wwns : {}, iscsi_iqn : {} ".format(self.nvme_nqn, self.fc_wwns, self.iscsi_iqn) diff --git a/controller/controller_server/config.py b/controller/controller_server/config.py index b85697722..97b8a0121 100644 --- a/controller/controller_server/config.py +++ b/controller/controller_server/config.py @@ -47,8 +47,6 @@ REQUEST_ACCESSIBILITY_REQUIREMENTS_FIELD = "accessibility_requirements" -SUPPORTED_CONNECTIVITY_TYPES = 2 - SNAPSHOT_TYPE_NAME = "snapshot" VOLUME_TYPE_NAME = "volume" VOLUME_SOURCE_ID_FIELDS = {SNAPSHOT_TYPE_NAME: 'snapshot_id', VOLUME_TYPE_NAME: 'volume_id'} diff --git a/controller/controller_server/csi_controller_server.py b/controller/controller_server/csi_controller_server.py index 086df758b..da6114801 100755 --- a/controller/controller_server/csi_controller_server.py +++ b/controller/controller_server/csi_controller_server.py @@ -165,25 +165,31 @@ def _handle_existing_volume_source(self, volume, source_id, source_type, system_ If volume is a copy of another source - set context status to INTERNAL and return CreateVolumeResponse. In any other case return None. """ - volume_name = volume.name volume_copy_source_id = volume.copy_source_id if not source_id and not volume_copy_source_id: return None if volume_copy_source_id == source_id: - return self._handle_volume_exists_with_same_source(context, source_id, source_type, volume_name, volume, + return self._handle_volume_exists_with_same_source(context, source_id, source_type, volume, system_id) - return self._handle_volume_exists_with_different_source(context, source_id, source_type, volume_name) + return self._handle_volume_exists_with_different_source(context, source_id, source_type, volume) - def _handle_volume_exists_with_same_source(self, context, source_id, source_type, volume_name, volume, system_id): + def _handle_volume_exists_with_same_source(self, context, source_id, source_type, volume, system_id): logger.debug( - "Volume {0} exists and it is a copy of {1} {2}.".format(volume_name, source_type, source_id)) + "Volume {0} exists and it is a copy of {1} {2}.".format(volume.name, source_type, source_id)) context.set_code(grpc.StatusCode.OK) return utils.generate_csi_create_volume_response(volume, system_id, source_type) - def _handle_volume_exists_with_different_source(self, context, source_id, source_type, volume_name): - logger.debug( - "Volume {0} exists but it is not a copy of {1} {2}.".format(volume_name, source_type, source_id)) - message = "Volume already exists but it was created from a different source." + def _handle_volume_exists_with_different_source(self, context, source_id, source_type, volume): + if source_id: + message = ("Volume {0} already exists but was not created from the " + "requested source {1} {2}. actual source: {3}".format(volume.name, + source_type, + source_id, + volume.copy_source_id)) + else: + message = "Volume {0} already exists but was created from a source: {1}".format(volume.name, + volume.copy_source_id) + logger.debug(message) return build_error_response(message, context, grpc.StatusCode.ALREADY_EXISTS, csi_pb2.CreateVolumeResponse) @handle_common_exceptions(csi_pb2.DeleteVolumeResponse) diff --git a/controller/controller_server/utils.py b/controller/controller_server/utils.py index 7d54a0e2c..09f2e3890 100644 --- a/controller/controller_server/utils.py +++ b/controller/controller_server/utils.py @@ -9,8 +9,8 @@ import controller.array_action.errors as array_errors import controller.controller_server.config as config import controller.controller_server.messages as messages -from controller.array_action.config import FC_CONNECTIVITY_TYPE, ISCSI_CONNECTIVITY_TYPE, \ - REPLICATION_COPY_TYPE_SYNC, REPLICATION_COPY_TYPE_ASYNC +from controller.array_action.config import NVME_OVER_FC_CONNECTIVITY_TYPE, FC_CONNECTIVITY_TYPE, \ + ISCSI_CONNECTIVITY_TYPE, REPLICATION_COPY_TYPE_SYNC, REPLICATION_COPY_TYPE_ASYNC from controller.common.csi_logger import get_stdout_logger from controller.common.settings import NAME_PREFIX_SEPARATOR from controller.controller_server.controller_types import ArrayConnectionInfo, ObjectIdInfo, ObjectParameters @@ -483,21 +483,25 @@ def get_object_id_info(full_object_id, object_type): def get_node_id_info(node_id): logger.debug("getting node info for node id : {0}".format(node_id)) split_node = node_id.split(config.PARAMETERS_NODE_ID_DELIMITER) - hostname, fc_wwns, iscsi_iqn = "", "", "" - if len(split_node) == config.SUPPORTED_CONNECTIVITY_TYPES + 1: - hostname, fc_wwns, iscsi_iqn = split_node + hostname, nvme_nqn, fc_wwns, iscsi_iqn = "", "", "", "" + if len(split_node) == 4: + hostname, nvme_nqn, fc_wwns, iscsi_iqn = split_node + elif len(split_node) == 3: + hostname, nvme_nqn, fc_wwns = split_node elif len(split_node) == 2: - hostname, fc_wwns = split_node + hostname, nvme_nqn = split_node else: raise array_errors.HostNotFoundError(node_id) - logger.debug("node name : {0}, iscsi_iqn : {1}, fc_wwns : {2} ".format( - hostname, iscsi_iqn, fc_wwns)) - return hostname, fc_wwns, iscsi_iqn + logger.debug("node name : {0}, nvme_nqn: {1}, fc_wwns : {2}, iscsi_iqn : {3} ".format( + hostname, nvme_nqn, fc_wwns, iscsi_iqn)) + return hostname, nvme_nqn, fc_wwns, iscsi_iqn def choose_connectivity_type(connectivity_types): - # If connectivity type support FC and iSCSI at the same time, chose FC logger.debug("choosing connectivity type for connectivity types : {0}".format(connectivity_types)) + if NVME_OVER_FC_CONNECTIVITY_TYPE in connectivity_types: + logger.debug("connectivity type is : {0}".format(NVME_OVER_FC_CONNECTIVITY_TYPE)) + return NVME_OVER_FC_CONNECTIVITY_TYPE if FC_CONNECTIVITY_TYPE in connectivity_types: logger.debug("connectivity type is : {0}".format(FC_CONNECTIVITY_TYPE)) return FC_CONNECTIVITY_TYPE @@ -519,15 +523,15 @@ def generate_csi_publish_volume_response(lun, connectivity_type, config, array_i connectivity_param: connectivity_type } - if connectivity_type == ISCSI_CONNECTIVITY_TYPE: + if connectivity_type == FC_CONNECTIVITY_TYPE: + array_initiators_param = config["controller"]["publish_context_fc_initiators"] + publish_context[array_initiators_param] = separator.join(array_initiators) + elif connectivity_type == ISCSI_CONNECTIVITY_TYPE: for iqn, ips in array_initiators.items(): publish_context[iqn] = separator.join(ips) array_initiators_param = config["controller"]["publish_context_array_iqn"] publish_context[array_initiators_param] = separator.join(array_initiators.keys()) - else: - array_initiators_param = config["controller"]["publish_context_fc_initiators"] - publish_context[array_initiators_param] = separator.join(array_initiators) res = csi_pb2.ControllerPublishVolumeResponse(publish_context=publish_context) diff --git a/controller/csi_general/csi_pb2.py b/controller/csi_general/csi_pb2.py index cfea5f6cf..ceeaffca4 100644 --- a/controller/csi_general/csi_pb2.py +++ b/controller/csi_general/csi_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: csi.proto - +# source: controller/csi_general/csi.proto +"""Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection @@ -17,24 +17,72 @@ DESCRIPTOR = _descriptor.FileDescriptor( - name='csi.proto', + name='controller/csi_general/csi.proto', package='csi.v1', syntax='proto3', serialized_options=b'Z\003csi', create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\tcsi.proto\x12\x06\x63si.v1\x1a google/protobuf/descriptor.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\x16\n\x14GetPluginInfoRequest\"\xad\x01\n\x15GetPluginInfoResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0evendor_version\x18\x02 \x01(\t\x12=\n\x08manifest\x18\x03 \x03(\x0b\x32+.csi.v1.GetPluginInfoResponse.ManifestEntry\x1a/\n\rManifestEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1e\n\x1cGetPluginCapabilitiesRequest\"O\n\x1dGetPluginCapabilitiesResponse\x12.\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32\x18.csi.v1.PluginCapability\"\xa7\x03\n\x10PluginCapability\x12\x33\n\x07service\x18\x01 \x01(\x0b\x32 .csi.v1.PluginCapability.ServiceH\x00\x12\x44\n\x10volume_expansion\x18\x02 \x01(\x0b\x32(.csi.v1.PluginCapability.VolumeExpansionH\x00\x1a\x91\x01\n\x07Service\x12\x33\n\x04type\x18\x01 \x01(\x0e\x32%.csi.v1.PluginCapability.Service.Type\"Q\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x16\n\x12\x43ONTROLLER_SERVICE\x10\x01\x12$\n VOLUME_ACCESSIBILITY_CONSTRAINTS\x10\x02\x1a|\n\x0fVolumeExpansion\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.csi.v1.PluginCapability.VolumeExpansion.Type\",\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06ONLINE\x10\x01\x12\x0b\n\x07OFFLINE\x10\x02\x42\x06\n\x04type\"\x0e\n\x0cProbeRequest\":\n\rProbeResponse\x12)\n\x05ready\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\"\xea\x03\n\x13\x43reateVolumeRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x02 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12\x35\n\x13volume_capabilities\x18\x03 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12?\n\nparameters\x18\x04 \x03(\x0b\x32+.csi.v1.CreateVolumeRequest.ParametersEntry\x12>\n\x07secrets\x18\x05 \x03(\x0b\x32(.csi.v1.CreateVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12:\n\x15volume_content_source\x18\x06 \x01(\x0b\x32\x1b.csi.v1.VolumeContentSource\x12?\n\x1a\x61\x63\x63\x65ssibility_requirements\x18\x07 \x01(\x0b\x32\x1b.csi.v1.TopologyRequirement\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe3\x01\n\x13VolumeContentSource\x12>\n\x08snapshot\x18\x01 \x01(\x0b\x32*.csi.v1.VolumeContentSource.SnapshotSourceH\x00\x12:\n\x06volume\x18\x02 \x01(\x0b\x32(.csi.v1.VolumeContentSource.VolumeSourceH\x00\x1a%\n\x0eSnapshotSource\x12\x13\n\x0bsnapshot_id\x18\x01 \x01(\t\x1a!\n\x0cVolumeSource\x12\x11\n\tvolume_id\x18\x01 \x01(\tB\x06\n\x04type\"6\n\x14\x43reateVolumeResponse\x12\x1e\n\x06volume\x18\x01 \x01(\x0b\x32\x0e.csi.v1.Volume\"\xf6\x03\n\x10VolumeCapability\x12\x35\n\x05\x62lock\x18\x01 \x01(\x0b\x32$.csi.v1.VolumeCapability.BlockVolumeH\x00\x12\x35\n\x05mount\x18\x02 \x01(\x0b\x32$.csi.v1.VolumeCapability.MountVolumeH\x00\x12\x38\n\x0b\x61\x63\x63\x65ss_mode\x18\x03 \x01(\x0b\x32#.csi.v1.VolumeCapability.AccessMode\x1a\r\n\x0b\x42lockVolume\x1a\x33\n\x0bMountVolume\x12\x0f\n\x07\x66s_type\x18\x01 \x01(\t\x12\x13\n\x0bmount_flags\x18\x02 \x03(\t\x1a\xe6\x01\n\nAccessMode\x12\x36\n\x04mode\x18\x01 \x01(\x0e\x32(.csi.v1.VolumeCapability.AccessMode.Mode\"\x9f\x01\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x16\n\x12SINGLE_NODE_WRITER\x10\x01\x12\x1b\n\x17SINGLE_NODE_READER_ONLY\x10\x02\x12\x1a\n\x16MULTI_NODE_READER_ONLY\x10\x03\x12\x1c\n\x18MULTI_NODE_SINGLE_WRITER\x10\x04\x12\x1b\n\x17MULTI_NODE_MULTI_WRITER\x10\x05\x42\r\n\x0b\x61\x63\x63\x65ss_type\"<\n\rCapacityRange\x12\x16\n\x0erequired_bytes\x18\x01 \x01(\x03\x12\x13\n\x0blimit_bytes\x18\x02 \x01(\x03\"\x88\x02\n\x06Volume\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x12\x11\n\tvolume_id\x18\x02 \x01(\t\x12\x39\n\x0evolume_context\x18\x03 \x03(\x0b\x32!.csi.v1.Volume.VolumeContextEntry\x12\x33\n\x0e\x63ontent_source\x18\x04 \x01(\x0b\x32\x1b.csi.v1.VolumeContentSource\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x05 \x03(\x0b\x32\x10.csi.v1.Topology\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\x13TopologyRequirement\x12#\n\trequisite\x18\x01 \x03(\x0b\x32\x10.csi.v1.Topology\x12#\n\tpreferred\x18\x02 \x03(\x0b\x32\x10.csi.v1.Topology\"m\n\x08Topology\x12\x30\n\x08segments\x18\x01 \x03(\x0b\x32\x1e.csi.v1.Topology.SegmentsEntry\x1a/\n\rSegmentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x98\x01\n\x13\x44\x65leteVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12>\n\x07secrets\x18\x02 \x03(\x0b\x32(.csi.v1.DeleteVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x16\n\x14\x44\x65leteVolumeResponse\"\x8f\x03\n\x1e\x43ontrollerPublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12\x33\n\x11volume_capability\x18\x03 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x10\n\x08readonly\x18\x04 \x01(\x08\x12I\n\x07secrets\x18\x05 \x03(\x0b\x32\x33.csi.v1.ControllerPublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12Q\n\x0evolume_context\x18\x06 \x03(\x0b\x32\x39.csi.v1.ControllerPublishVolumeRequest.VolumeContextEntry\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xae\x01\n\x1f\x43ontrollerPublishVolumeResponse\x12T\n\x0fpublish_context\x18\x01 \x03(\x0b\x32;.csi.v1.ControllerPublishVolumeResponse.PublishContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc3\x01\n ControllerUnpublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12K\n\x07secrets\x18\x03 \x03(\x0b\x32\x35.csi.v1.ControllerUnpublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"#\n!ControllerUnpublishVolumeResponse\"\xf9\x03\n!ValidateVolumeCapabilitiesRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12T\n\x0evolume_context\x18\x02 \x03(\x0b\x32<.csi.v1.ValidateVolumeCapabilitiesRequest.VolumeContextEntry\x12\x35\n\x13volume_capabilities\x18\x03 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12M\n\nparameters\x18\x04 \x03(\x0b\x32\x39.csi.v1.ValidateVolumeCapabilitiesRequest.ParametersEntry\x12L\n\x07secrets\x18\x05 \x03(\x0b\x32\x36.csi.v1.ValidateVolumeCapabilitiesRequest.SecretsEntryB\x03\x98\x42\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe7\x03\n\"ValidateVolumeCapabilitiesResponse\x12G\n\tconfirmed\x18\x01 \x01(\x0b\x32\x34.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed\x12\x0f\n\x07message\x18\x02 \x01(\t\x1a\xe6\x02\n\tConfirmed\x12_\n\x0evolume_context\x18\x01 \x03(\x0b\x32G.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.VolumeContextEntry\x12\x35\n\x13volume_capabilities\x18\x02 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12X\n\nparameters\x18\x03 \x03(\x0b\x32\x44.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.ParametersEntry\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"A\n\x12ListVolumesRequest\x12\x13\n\x0bmax_entries\x18\x01 \x01(\x05\x12\x16\n\x0estarting_token\x18\x02 \x01(\t\"\xec\x01\n\x13ListVolumesResponse\x12\x32\n\x07\x65ntries\x18\x01 \x03(\x0b\x32!.csi.v1.ListVolumesResponse.Entry\x12\x12\n\nnext_token\x18\x02 \x01(\t\x1a*\n\x0cVolumeStatus\x12\x1a\n\x12published_node_ids\x18\x01 \x03(\t\x1a\x61\n\x05\x45ntry\x12\x1e\n\x06volume\x18\x01 \x01(\x0b\x32\x0e.csi.v1.Volume\x12\x38\n\x06status\x18\x02 \x01(\x0b\x32(.csi.v1.ListVolumesResponse.VolumeStatus\"\xed\x01\n\x12GetCapacityRequest\x12\x35\n\x13volume_capabilities\x18\x01 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12>\n\nparameters\x18\x02 \x03(\x0b\x32*.csi.v1.GetCapacityRequest.ParametersEntry\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x03 \x01(\x0b\x32\x10.csi.v1.Topology\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"1\n\x13GetCapacityResponse\x12\x1a\n\x12\x61vailable_capacity\x18\x01 \x01(\x03\"\"\n ControllerGetCapabilitiesRequest\"^\n!ControllerGetCapabilitiesResponse\x12\x39\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32#.csi.v1.ControllerServiceCapability\"\xa0\x03\n\x1b\x43ontrollerServiceCapability\x12\x36\n\x03rpc\x18\x01 \x01(\x0b\x32\'.csi.v1.ControllerServiceCapability.RPCH\x00\x1a\xc0\x02\n\x03RPC\x12:\n\x04type\x18\x01 \x01(\x0e\x32,.csi.v1.ControllerServiceCapability.RPC.Type\"\xfc\x01\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x18\n\x14\x43REATE_DELETE_VOLUME\x10\x01\x12\x1c\n\x18PUBLISH_UNPUBLISH_VOLUME\x10\x02\x12\x10\n\x0cLIST_VOLUMES\x10\x03\x12\x10\n\x0cGET_CAPACITY\x10\x04\x12\x1a\n\x16\x43REATE_DELETE_SNAPSHOT\x10\x05\x12\x12\n\x0eLIST_SNAPSHOTS\x10\x06\x12\x10\n\x0c\x43LONE_VOLUME\x10\x07\x12\x14\n\x10PUBLISH_READONLY\x10\x08\x12\x11\n\rEXPAND_VOLUME\x10\t\x12 \n\x1cLIST_VOLUMES_PUBLISHED_NODES\x10\nB\x06\n\x04type\"\xa7\x02\n\x15\x43reateSnapshotRequest\x12\x18\n\x10source_volume_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12@\n\x07secrets\x18\x03 \x03(\x0b\x32*.csi.v1.CreateSnapshotRequest.SecretsEntryB\x03\x98\x42\x01\x12\x41\n\nparameters\x18\x04 \x03(\x0b\x32-.csi.v1.CreateSnapshotRequest.ParametersEntry\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"<\n\x16\x43reateSnapshotResponse\x12\"\n\x08snapshot\x18\x01 \x01(\x0b\x32\x10.csi.v1.Snapshot\"\x96\x01\n\x08Snapshot\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03\x12\x13\n\x0bsnapshot_id\x18\x02 \x01(\t\x12\x18\n\x10source_volume_id\x18\x03 \x01(\t\x12\x31\n\rcreation_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cready_to_use\x18\x05 \x01(\x08\"\x9e\x01\n\x15\x44\x65leteSnapshotRequest\x12\x13\n\x0bsnapshot_id\x18\x01 \x01(\t\x12@\n\x07secrets\x18\x02 \x03(\x0b\x32*.csi.v1.DeleteSnapshotRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x18\n\x16\x44\x65leteSnapshotResponse\"\xe3\x01\n\x14ListSnapshotsRequest\x12\x13\n\x0bmax_entries\x18\x01 \x01(\x05\x12\x16\n\x0estarting_token\x18\x02 \x01(\t\x12\x18\n\x10source_volume_id\x18\x03 \x01(\t\x12\x13\n\x0bsnapshot_id\x18\x04 \x01(\t\x12?\n\x07secrets\x18\x05 \x03(\x0b\x32).csi.v1.ListSnapshotsRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8e\x01\n\x15ListSnapshotsResponse\x12\x34\n\x07\x65ntries\x18\x01 \x03(\x0b\x32#.csi.v1.ListSnapshotsResponse.Entry\x12\x12\n\nnext_token\x18\x02 \x01(\t\x1a+\n\x05\x45ntry\x12\"\n\x08snapshot\x18\x01 \x01(\x0b\x32\x10.csi.v1.Snapshot\"\x90\x02\n\x1d\x43ontrollerExpandVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x02 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12H\n\x07secrets\x18\x03 \x03(\x0b\x32\x32.csi.v1.ControllerExpandVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12\x33\n\x11volume_capability\x18\x04 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"Y\n\x1e\x43ontrollerExpandVolumeResponse\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x12\x1f\n\x17node_expansion_required\x18\x02 \x01(\x08\"\xf5\x03\n\x16NodeStageVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12K\n\x0fpublish_context\x18\x02 \x03(\x0b\x32\x32.csi.v1.NodeStageVolumeRequest.PublishContextEntry\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\x12\x33\n\x11volume_capability\x18\x04 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x41\n\x07secrets\x18\x05 \x03(\x0b\x32+.csi.v1.NodeStageVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12I\n\x0evolume_context\x18\x06 \x03(\x0b\x32\x31.csi.v1.NodeStageVolumeRequest.VolumeContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x19\n\x17NodeStageVolumeResponse\"J\n\x18NodeUnstageVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x1b\n\x13staging_target_path\x18\x02 \x01(\t\"\x1b\n\x19NodeUnstageVolumeResponse\"\xa4\x04\n\x18NodePublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12M\n\x0fpublish_context\x18\x02 \x03(\x0b\x32\x34.csi.v1.NodePublishVolumeRequest.PublishContextEntry\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\x12\x13\n\x0btarget_path\x18\x04 \x01(\t\x12\x33\n\x11volume_capability\x18\x05 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x10\n\x08readonly\x18\x06 \x01(\x08\x12\x43\n\x07secrets\x18\x07 \x03(\x0b\x32-.csi.v1.NodePublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12K\n\x0evolume_context\x18\x08 \x03(\x0b\x32\x33.csi.v1.NodePublishVolumeRequest.VolumeContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1b\n\x19NodePublishVolumeResponse\"D\n\x1aNodeUnpublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0btarget_path\x18\x02 \x01(\t\"\x1d\n\x1bNodeUnpublishVolumeResponse\"`\n\x19NodeGetVolumeStatsRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0bvolume_path\x18\x02 \x01(\t\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\"@\n\x1aNodeGetVolumeStatsResponse\x12\"\n\x05usage\x18\x01 \x03(\x0b\x32\x13.csi.v1.VolumeUsage\"\x91\x01\n\x0bVolumeUsage\x12\x11\n\tavailable\x18\x01 \x01(\x03\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0c\n\x04used\x18\x03 \x01(\x03\x12&\n\x04unit\x18\x04 \x01(\x0e\x32\x18.csi.v1.VolumeUsage.Unit\"*\n\x04Unit\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\n\n\x06INODES\x10\x02\"\x1c\n\x1aNodeGetCapabilitiesRequest\"R\n\x1bNodeGetCapabilitiesResponse\x12\x33\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32\x1d.csi.v1.NodeServiceCapability\"\xe7\x01\n\x15NodeServiceCapability\x12\x30\n\x03rpc\x18\x01 \x01(\x0b\x32!.csi.v1.NodeServiceCapability.RPCH\x00\x1a\x93\x01\n\x03RPC\x12\x34\n\x04type\x18\x01 \x01(\x0e\x32&.csi.v1.NodeServiceCapability.RPC.Type\"V\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x18\n\x14STAGE_UNSTAGE_VOLUME\x10\x01\x12\x14\n\x10GET_VOLUME_STATS\x10\x02\x12\x11\n\rEXPAND_VOLUME\x10\x03\x42\x06\n\x04type\"\x14\n\x12NodeGetInfoRequest\"s\n\x13NodeGetInfoResponse\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x1c\n\x14max_volumes_per_node\x18\x02 \x01(\x03\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x03 \x01(\x0b\x32\x10.csi.v1.Topology\"\xc2\x01\n\x17NodeExpandVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0bvolume_path\x18\x02 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x03 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12\x1b\n\x13staging_target_path\x18\x04 \x01(\t\x12\x33\n\x11volume_capability\x18\x05 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\"2\n\x18NodeExpandVolumeResponse\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x32\xfa\x01\n\x08Identity\x12N\n\rGetPluginInfo\x12\x1c.csi.v1.GetPluginInfoRequest\x1a\x1d.csi.v1.GetPluginInfoResponse\"\x00\x12\x66\n\x15GetPluginCapabilities\x12$.csi.v1.GetPluginCapabilitiesRequest\x1a%.csi.v1.GetPluginCapabilitiesResponse\"\x00\x12\x36\n\x05Probe\x12\x14.csi.v1.ProbeRequest\x1a\x15.csi.v1.ProbeResponse\"\x00\x32\xe8\x08\n\nController\x12K\n\x0c\x43reateVolume\x12\x1b.csi.v1.CreateVolumeRequest\x1a\x1c.csi.v1.CreateVolumeResponse\"\x00\x12K\n\x0c\x44\x65leteVolume\x12\x1b.csi.v1.DeleteVolumeRequest\x1a\x1c.csi.v1.DeleteVolumeResponse\"\x00\x12l\n\x17\x43ontrollerPublishVolume\x12&.csi.v1.ControllerPublishVolumeRequest\x1a\'.csi.v1.ControllerPublishVolumeResponse\"\x00\x12r\n\x19\x43ontrollerUnpublishVolume\x12(.csi.v1.ControllerUnpublishVolumeRequest\x1a).csi.v1.ControllerUnpublishVolumeResponse\"\x00\x12u\n\x1aValidateVolumeCapabilities\x12).csi.v1.ValidateVolumeCapabilitiesRequest\x1a*.csi.v1.ValidateVolumeCapabilitiesResponse\"\x00\x12H\n\x0bListVolumes\x12\x1a.csi.v1.ListVolumesRequest\x1a\x1b.csi.v1.ListVolumesResponse\"\x00\x12H\n\x0bGetCapacity\x12\x1a.csi.v1.GetCapacityRequest\x1a\x1b.csi.v1.GetCapacityResponse\"\x00\x12r\n\x19\x43ontrollerGetCapabilities\x12(.csi.v1.ControllerGetCapabilitiesRequest\x1a).csi.v1.ControllerGetCapabilitiesResponse\"\x00\x12Q\n\x0e\x43reateSnapshot\x12\x1d.csi.v1.CreateSnapshotRequest\x1a\x1e.csi.v1.CreateSnapshotResponse\"\x00\x12Q\n\x0e\x44\x65leteSnapshot\x12\x1d.csi.v1.DeleteSnapshotRequest\x1a\x1e.csi.v1.DeleteSnapshotResponse\"\x00\x12N\n\rListSnapshots\x12\x1c.csi.v1.ListSnapshotsRequest\x1a\x1d.csi.v1.ListSnapshotsResponse\"\x00\x12i\n\x16\x43ontrollerExpandVolume\x12%.csi.v1.ControllerExpandVolumeRequest\x1a&.csi.v1.ControllerExpandVolumeResponse\"\x00\x32\xda\x05\n\x04Node\x12T\n\x0fNodeStageVolume\x12\x1e.csi.v1.NodeStageVolumeRequest\x1a\x1f.csi.v1.NodeStageVolumeResponse\"\x00\x12Z\n\x11NodeUnstageVolume\x12 .csi.v1.NodeUnstageVolumeRequest\x1a!.csi.v1.NodeUnstageVolumeResponse\"\x00\x12Z\n\x11NodePublishVolume\x12 .csi.v1.NodePublishVolumeRequest\x1a!.csi.v1.NodePublishVolumeResponse\"\x00\x12`\n\x13NodeUnpublishVolume\x12\".csi.v1.NodeUnpublishVolumeRequest\x1a#.csi.v1.NodeUnpublishVolumeResponse\"\x00\x12]\n\x12NodeGetVolumeStats\x12!.csi.v1.NodeGetVolumeStatsRequest\x1a\".csi.v1.NodeGetVolumeStatsResponse\"\x00\x12W\n\x10NodeExpandVolume\x12\x1f.csi.v1.NodeExpandVolumeRequest\x1a .csi.v1.NodeExpandVolumeResponse\"\x00\x12`\n\x13NodeGetCapabilities\x12\".csi.v1.NodeGetCapabilitiesRequest\x1a#.csi.v1.NodeGetCapabilitiesResponse\"\x00\x12H\n\x0bNodeGetInfo\x12\x1a.csi.v1.NodeGetInfoRequest\x1a\x1b.csi.v1.NodeGetInfoResponse\"\x00:2\n\ncsi_secret\x12\x1d.google.protobuf.FieldOptions\x18\xa3\x08 \x01(\x08\x42\x05Z\x03\x63sib\x06proto3' + serialized_pb=b'\n controller/csi_general/csi.proto\x12\x06\x63si.v1\x1a google/protobuf/descriptor.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\x16\n\x14GetPluginInfoRequest\"\xad\x01\n\x15GetPluginInfoResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0evendor_version\x18\x02 \x01(\t\x12=\n\x08manifest\x18\x03 \x03(\x0b\x32+.csi.v1.GetPluginInfoResponse.ManifestEntry\x1a/\n\rManifestEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1e\n\x1cGetPluginCapabilitiesRequest\"O\n\x1dGetPluginCapabilitiesResponse\x12.\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32\x18.csi.v1.PluginCapability\"\xa7\x03\n\x10PluginCapability\x12\x33\n\x07service\x18\x01 \x01(\x0b\x32 .csi.v1.PluginCapability.ServiceH\x00\x12\x44\n\x10volume_expansion\x18\x02 \x01(\x0b\x32(.csi.v1.PluginCapability.VolumeExpansionH\x00\x1a\x91\x01\n\x07Service\x12\x33\n\x04type\x18\x01 \x01(\x0e\x32%.csi.v1.PluginCapability.Service.Type\"Q\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x16\n\x12\x43ONTROLLER_SERVICE\x10\x01\x12$\n VOLUME_ACCESSIBILITY_CONSTRAINTS\x10\x02\x1a|\n\x0fVolumeExpansion\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.csi.v1.PluginCapability.VolumeExpansion.Type\",\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06ONLINE\x10\x01\x12\x0b\n\x07OFFLINE\x10\x02\x42\x06\n\x04type\"\x0e\n\x0cProbeRequest\":\n\rProbeResponse\x12)\n\x05ready\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\"\xea\x03\n\x13\x43reateVolumeRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x02 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12\x35\n\x13volume_capabilities\x18\x03 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12?\n\nparameters\x18\x04 \x03(\x0b\x32+.csi.v1.CreateVolumeRequest.ParametersEntry\x12>\n\x07secrets\x18\x05 \x03(\x0b\x32(.csi.v1.CreateVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12:\n\x15volume_content_source\x18\x06 \x01(\x0b\x32\x1b.csi.v1.VolumeContentSource\x12?\n\x1a\x61\x63\x63\x65ssibility_requirements\x18\x07 \x01(\x0b\x32\x1b.csi.v1.TopologyRequirement\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe3\x01\n\x13VolumeContentSource\x12>\n\x08snapshot\x18\x01 \x01(\x0b\x32*.csi.v1.VolumeContentSource.SnapshotSourceH\x00\x12:\n\x06volume\x18\x02 \x01(\x0b\x32(.csi.v1.VolumeContentSource.VolumeSourceH\x00\x1a%\n\x0eSnapshotSource\x12\x13\n\x0bsnapshot_id\x18\x01 \x01(\t\x1a!\n\x0cVolumeSource\x12\x11\n\tvolume_id\x18\x01 \x01(\tB\x06\n\x04type\"6\n\x14\x43reateVolumeResponse\x12\x1e\n\x06volume\x18\x01 \x01(\x0b\x32\x0e.csi.v1.Volume\"\xde\x04\n\x10VolumeCapability\x12\x35\n\x05\x62lock\x18\x01 \x01(\x0b\x32$.csi.v1.VolumeCapability.BlockVolumeH\x00\x12\x35\n\x05mount\x18\x02 \x01(\x0b\x32$.csi.v1.VolumeCapability.MountVolumeH\x00\x12\x38\n\x0b\x61\x63\x63\x65ss_mode\x18\x03 \x01(\x0b\x32#.csi.v1.VolumeCapability.AccessMode\x1a\r\n\x0b\x42lockVolume\x1aT\n\x0bMountVolume\x12\x0f\n\x07\x66s_type\x18\x01 \x01(\t\x12\x13\n\x0bmount_flags\x18\x02 \x03(\t\x12\x1f\n\x12volume_mount_group\x18\x03 \x01(\tB\x03\xa0\x42\x01\x1a\xad\x02\n\nAccessMode\x12\x36\n\x04mode\x18\x01 \x01(\x0e\x32(.csi.v1.VolumeCapability.AccessMode.Mode\"\xe6\x01\n\x04Mode\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x16\n\x12SINGLE_NODE_WRITER\x10\x01\x12\x1b\n\x17SINGLE_NODE_READER_ONLY\x10\x02\x12\x1a\n\x16MULTI_NODE_READER_ONLY\x10\x03\x12\x1c\n\x18MULTI_NODE_SINGLE_WRITER\x10\x04\x12\x1b\n\x17MULTI_NODE_MULTI_WRITER\x10\x05\x12\"\n\x19SINGLE_NODE_SINGLE_WRITER\x10\x06\x1a\x03\xa0\x42\x01\x12!\n\x18SINGLE_NODE_MULTI_WRITER\x10\x07\x1a\x03\xa0\x42\x01\x42\r\n\x0b\x61\x63\x63\x65ss_type\"<\n\rCapacityRange\x12\x16\n\x0erequired_bytes\x18\x01 \x01(\x03\x12\x13\n\x0blimit_bytes\x18\x02 \x01(\x03\"\x88\x02\n\x06Volume\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x12\x11\n\tvolume_id\x18\x02 \x01(\t\x12\x39\n\x0evolume_context\x18\x03 \x03(\x0b\x32!.csi.v1.Volume.VolumeContextEntry\x12\x33\n\x0e\x63ontent_source\x18\x04 \x01(\x0b\x32\x1b.csi.v1.VolumeContentSource\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x05 \x03(\x0b\x32\x10.csi.v1.Topology\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\x13TopologyRequirement\x12#\n\trequisite\x18\x01 \x03(\x0b\x32\x10.csi.v1.Topology\x12#\n\tpreferred\x18\x02 \x03(\x0b\x32\x10.csi.v1.Topology\"m\n\x08Topology\x12\x30\n\x08segments\x18\x01 \x03(\x0b\x32\x1e.csi.v1.Topology.SegmentsEntry\x1a/\n\rSegmentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x98\x01\n\x13\x44\x65leteVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12>\n\x07secrets\x18\x02 \x03(\x0b\x32(.csi.v1.DeleteVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x16\n\x14\x44\x65leteVolumeResponse\"\x8f\x03\n\x1e\x43ontrollerPublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12\x33\n\x11volume_capability\x18\x03 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x10\n\x08readonly\x18\x04 \x01(\x08\x12I\n\x07secrets\x18\x05 \x03(\x0b\x32\x33.csi.v1.ControllerPublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12Q\n\x0evolume_context\x18\x06 \x03(\x0b\x32\x39.csi.v1.ControllerPublishVolumeRequest.VolumeContextEntry\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xae\x01\n\x1f\x43ontrollerPublishVolumeResponse\x12T\n\x0fpublish_context\x18\x01 \x03(\x0b\x32;.csi.v1.ControllerPublishVolumeResponse.PublishContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc3\x01\n ControllerUnpublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x0f\n\x07node_id\x18\x02 \x01(\t\x12K\n\x07secrets\x18\x03 \x03(\x0b\x32\x35.csi.v1.ControllerUnpublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"#\n!ControllerUnpublishVolumeResponse\"\xf9\x03\n!ValidateVolumeCapabilitiesRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12T\n\x0evolume_context\x18\x02 \x03(\x0b\x32<.csi.v1.ValidateVolumeCapabilitiesRequest.VolumeContextEntry\x12\x35\n\x13volume_capabilities\x18\x03 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12M\n\nparameters\x18\x04 \x03(\x0b\x32\x39.csi.v1.ValidateVolumeCapabilitiesRequest.ParametersEntry\x12L\n\x07secrets\x18\x05 \x03(\x0b\x32\x36.csi.v1.ValidateVolumeCapabilitiesRequest.SecretsEntryB\x03\x98\x42\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xe7\x03\n\"ValidateVolumeCapabilitiesResponse\x12G\n\tconfirmed\x18\x01 \x01(\x0b\x32\x34.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed\x12\x0f\n\x07message\x18\x02 \x01(\t\x1a\xe6\x02\n\tConfirmed\x12_\n\x0evolume_context\x18\x01 \x03(\x0b\x32G.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.VolumeContextEntry\x12\x35\n\x13volume_capabilities\x18\x02 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12X\n\nparameters\x18\x03 \x03(\x0b\x32\x44.csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.ParametersEntry\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"A\n\x12ListVolumesRequest\x12\x13\n\x0bmax_entries\x18\x01 \x01(\x05\x12\x16\n\x0estarting_token\x18\x02 \x01(\t\"\xa4\x02\n\x13ListVolumesResponse\x12\x32\n\x07\x65ntries\x18\x01 \x03(\x0b\x32!.csi.v1.ListVolumesResponse.Entry\x12\x12\n\nnext_token\x18\x02 \x01(\t\x1a\x62\n\x0cVolumeStatus\x12\x1a\n\x12published_node_ids\x18\x01 \x03(\t\x12\x36\n\x10volume_condition\x18\x02 \x01(\x0b\x32\x17.csi.v1.VolumeConditionB\x03\xa0\x42\x01\x1a\x61\n\x05\x45ntry\x12\x1e\n\x06volume\x18\x01 \x01(\x0b\x32\x0e.csi.v1.Volume\x12\x38\n\x06status\x18\x02 \x01(\x0b\x32(.csi.v1.ListVolumesResponse.VolumeStatus\"4\n\x1a\x43ontrollerGetVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t:\x03\xa0\x42\x01\"\xe3\x01\n\x1b\x43ontrollerGetVolumeResponse\x12\x1e\n\x06volume\x18\x01 \x01(\x0b\x32\x0e.csi.v1.Volume\x12@\n\x06status\x18\x02 \x01(\x0b\x32\x30.csi.v1.ControllerGetVolumeResponse.VolumeStatus\x1a]\n\x0cVolumeStatus\x12\x1a\n\x12published_node_ids\x18\x01 \x03(\t\x12\x31\n\x10volume_condition\x18\x02 \x01(\x0b\x32\x17.csi.v1.VolumeCondition:\x03\xa0\x42\x01\"\xed\x01\n\x12GetCapacityRequest\x12\x35\n\x13volume_capabilities\x18\x01 \x03(\x0b\x32\x18.csi.v1.VolumeCapability\x12>\n\nparameters\x18\x02 \x03(\x0b\x32*.csi.v1.GetCapacityRequest.ParametersEntry\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x03 \x01(\x0b\x32\x10.csi.v1.Topology\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xaf\x01\n\x13GetCapacityResponse\x12\x1a\n\x12\x61vailable_capacity\x18\x01 \x01(\x03\x12=\n\x13maximum_volume_size\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.Int64ValueB\x03\xa0\x42\x01\x12=\n\x13minimum_volume_size\x18\x03 \x01(\x0b\x32\x1b.google.protobuf.Int64ValueB\x03\xa0\x42\x01\"\"\n ControllerGetCapabilitiesRequest\"^\n!ControllerGetCapabilitiesResponse\x12\x39\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32#.csi.v1.ControllerServiceCapability\"\xf3\x03\n\x1b\x43ontrollerServiceCapability\x12\x36\n\x03rpc\x18\x01 \x01(\x0b\x32\'.csi.v1.ControllerServiceCapability.RPCH\x00\x1a\x93\x03\n\x03RPC\x12:\n\x04type\x18\x01 \x01(\x0e\x32,.csi.v1.ControllerServiceCapability.RPC.Type\"\xcf\x02\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x18\n\x14\x43REATE_DELETE_VOLUME\x10\x01\x12\x1c\n\x18PUBLISH_UNPUBLISH_VOLUME\x10\x02\x12\x10\n\x0cLIST_VOLUMES\x10\x03\x12\x10\n\x0cGET_CAPACITY\x10\x04\x12\x1a\n\x16\x43REATE_DELETE_SNAPSHOT\x10\x05\x12\x12\n\x0eLIST_SNAPSHOTS\x10\x06\x12\x10\n\x0c\x43LONE_VOLUME\x10\x07\x12\x14\n\x10PUBLISH_READONLY\x10\x08\x12\x11\n\rEXPAND_VOLUME\x10\t\x12 \n\x1cLIST_VOLUMES_PUBLISHED_NODES\x10\n\x12\x19\n\x10VOLUME_CONDITION\x10\x0b\x1a\x03\xa0\x42\x01\x12\x13\n\nGET_VOLUME\x10\x0c\x1a\x03\xa0\x42\x01\x12!\n\x18SINGLE_NODE_MULTI_WRITER\x10\r\x1a\x03\xa0\x42\x01\x42\x06\n\x04type\"\xa7\x02\n\x15\x43reateSnapshotRequest\x12\x18\n\x10source_volume_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12@\n\x07secrets\x18\x03 \x03(\x0b\x32*.csi.v1.CreateSnapshotRequest.SecretsEntryB\x03\x98\x42\x01\x12\x41\n\nparameters\x18\x04 \x03(\x0b\x32-.csi.v1.CreateSnapshotRequest.ParametersEntry\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x31\n\x0fParametersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"<\n\x16\x43reateSnapshotResponse\x12\"\n\x08snapshot\x18\x01 \x01(\x0b\x32\x10.csi.v1.Snapshot\"\x96\x01\n\x08Snapshot\x12\x12\n\nsize_bytes\x18\x01 \x01(\x03\x12\x13\n\x0bsnapshot_id\x18\x02 \x01(\t\x12\x18\n\x10source_volume_id\x18\x03 \x01(\t\x12\x31\n\rcreation_time\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x14\n\x0cready_to_use\x18\x05 \x01(\x08\"\x9e\x01\n\x15\x44\x65leteSnapshotRequest\x12\x13\n\x0bsnapshot_id\x18\x01 \x01(\t\x12@\n\x07secrets\x18\x02 \x03(\x0b\x32*.csi.v1.DeleteSnapshotRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x18\n\x16\x44\x65leteSnapshotResponse\"\xe3\x01\n\x14ListSnapshotsRequest\x12\x13\n\x0bmax_entries\x18\x01 \x01(\x05\x12\x16\n\x0estarting_token\x18\x02 \x01(\t\x12\x18\n\x10source_volume_id\x18\x03 \x01(\t\x12\x13\n\x0bsnapshot_id\x18\x04 \x01(\t\x12?\n\x07secrets\x18\x05 \x03(\x0b\x32).csi.v1.ListSnapshotsRequest.SecretsEntryB\x03\x98\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x8e\x01\n\x15ListSnapshotsResponse\x12\x34\n\x07\x65ntries\x18\x01 \x03(\x0b\x32#.csi.v1.ListSnapshotsResponse.Entry\x12\x12\n\nnext_token\x18\x02 \x01(\t\x1a+\n\x05\x45ntry\x12\"\n\x08snapshot\x18\x01 \x01(\x0b\x32\x10.csi.v1.Snapshot\"\x90\x02\n\x1d\x43ontrollerExpandVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x02 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12H\n\x07secrets\x18\x03 \x03(\x0b\x32\x32.csi.v1.ControllerExpandVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12\x33\n\x11volume_capability\x18\x04 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"Y\n\x1e\x43ontrollerExpandVolumeResponse\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x12\x1f\n\x17node_expansion_required\x18\x02 \x01(\x08\"\xf5\x03\n\x16NodeStageVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12K\n\x0fpublish_context\x18\x02 \x03(\x0b\x32\x32.csi.v1.NodeStageVolumeRequest.PublishContextEntry\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\x12\x33\n\x11volume_capability\x18\x04 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x41\n\x07secrets\x18\x05 \x03(\x0b\x32+.csi.v1.NodeStageVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12I\n\x0evolume_context\x18\x06 \x03(\x0b\x32\x31.csi.v1.NodeStageVolumeRequest.VolumeContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x19\n\x17NodeStageVolumeResponse\"J\n\x18NodeUnstageVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x1b\n\x13staging_target_path\x18\x02 \x01(\t\"\x1b\n\x19NodeUnstageVolumeResponse\"\xa4\x04\n\x18NodePublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12M\n\x0fpublish_context\x18\x02 \x03(\x0b\x32\x34.csi.v1.NodePublishVolumeRequest.PublishContextEntry\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\x12\x13\n\x0btarget_path\x18\x04 \x01(\t\x12\x33\n\x11volume_capability\x18\x05 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x10\n\x08readonly\x18\x06 \x01(\x08\x12\x43\n\x07secrets\x18\x07 \x03(\x0b\x32-.csi.v1.NodePublishVolumeRequest.SecretsEntryB\x03\x98\x42\x01\x12K\n\x0evolume_context\x18\x08 \x03(\x0b\x32\x33.csi.v1.NodePublishVolumeRequest.VolumeContextEntry\x1a\x35\n\x13PublishContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x34\n\x12VolumeContextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\x1b\n\x19NodePublishVolumeResponse\"D\n\x1aNodeUnpublishVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0btarget_path\x18\x02 \x01(\t\"\x1d\n\x1bNodeUnpublishVolumeResponse\"`\n\x19NodeGetVolumeStatsRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0bvolume_path\x18\x02 \x01(\t\x12\x1b\n\x13staging_target_path\x18\x03 \x01(\t\"x\n\x1aNodeGetVolumeStatsResponse\x12\"\n\x05usage\x18\x01 \x03(\x0b\x32\x13.csi.v1.VolumeUsage\x12\x36\n\x10volume_condition\x18\x02 \x01(\x0b\x32\x17.csi.v1.VolumeConditionB\x03\xa0\x42\x01\"\x91\x01\n\x0bVolumeUsage\x12\x11\n\tavailable\x18\x01 \x01(\x03\x12\r\n\x05total\x18\x02 \x01(\x03\x12\x0c\n\x04used\x18\x03 \x01(\x03\x12&\n\x04unit\x18\x04 \x01(\x0e\x32\x18.csi.v1.VolumeUsage.Unit\"*\n\x04Unit\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\n\n\x06INODES\x10\x02\"9\n\x0fVolumeCondition\x12\x10\n\x08\x61\x62normal\x18\x01 \x01(\x08\x12\x0f\n\x07message\x18\x02 \x01(\t:\x03\xa0\x42\x01\"\x1c\n\x1aNodeGetCapabilitiesRequest\"R\n\x1bNodeGetCapabilitiesResponse\x12\x33\n\x0c\x63\x61pabilities\x18\x01 \x03(\x0b\x32\x1d.csi.v1.NodeServiceCapability\"\xc3\x02\n\x15NodeServiceCapability\x12\x30\n\x03rpc\x18\x01 \x01(\x0b\x32!.csi.v1.NodeServiceCapability.RPCH\x00\x1a\xef\x01\n\x03RPC\x12\x34\n\x04type\x18\x01 \x01(\x0e\x32&.csi.v1.NodeServiceCapability.RPC.Type\"\xb1\x01\n\x04Type\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x18\n\x14STAGE_UNSTAGE_VOLUME\x10\x01\x12\x14\n\x10GET_VOLUME_STATS\x10\x02\x12\x11\n\rEXPAND_VOLUME\x10\x03\x12\x19\n\x10VOLUME_CONDITION\x10\x04\x1a\x03\xa0\x42\x01\x12!\n\x18SINGLE_NODE_MULTI_WRITER\x10\x05\x1a\x03\xa0\x42\x01\x12\x1b\n\x12VOLUME_MOUNT_GROUP\x10\x06\x1a\x03\xa0\x42\x01\x42\x06\n\x04type\"\x14\n\x12NodeGetInfoRequest\"s\n\x13NodeGetInfoResponse\x12\x0f\n\x07node_id\x18\x01 \x01(\t\x12\x1c\n\x14max_volumes_per_node\x18\x02 \x01(\x03\x12-\n\x13\x61\x63\x63\x65ssible_topology\x18\x03 \x01(\x0b\x32\x10.csi.v1.Topology\"\xb9\x02\n\x17NodeExpandVolumeRequest\x12\x11\n\tvolume_id\x18\x01 \x01(\t\x12\x13\n\x0bvolume_path\x18\x02 \x01(\t\x12-\n\x0e\x63\x61pacity_range\x18\x03 \x01(\x0b\x32\x15.csi.v1.CapacityRange\x12\x1b\n\x13staging_target_path\x18\x04 \x01(\t\x12\x33\n\x11volume_capability\x18\x05 \x01(\x0b\x32\x18.csi.v1.VolumeCapability\x12\x45\n\x07secrets\x18\x06 \x03(\x0b\x32,.csi.v1.NodeExpandVolumeRequest.SecretsEntryB\x06\x98\x42\x01\xa0\x42\x01\x1a.\n\x0cSecretsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"2\n\x18NodeExpandVolumeResponse\x12\x16\n\x0e\x63\x61pacity_bytes\x18\x01 \x01(\x03\x32\xfa\x01\n\x08Identity\x12N\n\rGetPluginInfo\x12\x1c.csi.v1.GetPluginInfoRequest\x1a\x1d.csi.v1.GetPluginInfoResponse\"\x00\x12\x66\n\x15GetPluginCapabilities\x12$.csi.v1.GetPluginCapabilitiesRequest\x1a%.csi.v1.GetPluginCapabilitiesResponse\"\x00\x12\x36\n\x05Probe\x12\x14.csi.v1.ProbeRequest\x1a\x15.csi.v1.ProbeResponse\"\x00\x32\xcd\t\n\nController\x12K\n\x0c\x43reateVolume\x12\x1b.csi.v1.CreateVolumeRequest\x1a\x1c.csi.v1.CreateVolumeResponse\"\x00\x12K\n\x0c\x44\x65leteVolume\x12\x1b.csi.v1.DeleteVolumeRequest\x1a\x1c.csi.v1.DeleteVolumeResponse\"\x00\x12l\n\x17\x43ontrollerPublishVolume\x12&.csi.v1.ControllerPublishVolumeRequest\x1a\'.csi.v1.ControllerPublishVolumeResponse\"\x00\x12r\n\x19\x43ontrollerUnpublishVolume\x12(.csi.v1.ControllerUnpublishVolumeRequest\x1a).csi.v1.ControllerUnpublishVolumeResponse\"\x00\x12u\n\x1aValidateVolumeCapabilities\x12).csi.v1.ValidateVolumeCapabilitiesRequest\x1a*.csi.v1.ValidateVolumeCapabilitiesResponse\"\x00\x12H\n\x0bListVolumes\x12\x1a.csi.v1.ListVolumesRequest\x1a\x1b.csi.v1.ListVolumesResponse\"\x00\x12H\n\x0bGetCapacity\x12\x1a.csi.v1.GetCapacityRequest\x1a\x1b.csi.v1.GetCapacityResponse\"\x00\x12r\n\x19\x43ontrollerGetCapabilities\x12(.csi.v1.ControllerGetCapabilitiesRequest\x1a).csi.v1.ControllerGetCapabilitiesResponse\"\x00\x12Q\n\x0e\x43reateSnapshot\x12\x1d.csi.v1.CreateSnapshotRequest\x1a\x1e.csi.v1.CreateSnapshotResponse\"\x00\x12Q\n\x0e\x44\x65leteSnapshot\x12\x1d.csi.v1.DeleteSnapshotRequest\x1a\x1e.csi.v1.DeleteSnapshotResponse\"\x00\x12N\n\rListSnapshots\x12\x1c.csi.v1.ListSnapshotsRequest\x1a\x1d.csi.v1.ListSnapshotsResponse\"\x00\x12i\n\x16\x43ontrollerExpandVolume\x12%.csi.v1.ControllerExpandVolumeRequest\x1a&.csi.v1.ControllerExpandVolumeResponse\"\x00\x12\x63\n\x13\x43ontrollerGetVolume\x12\".csi.v1.ControllerGetVolumeRequest\x1a#.csi.v1.ControllerGetVolumeResponse\"\x03\xa0\x42\x01\x32\xda\x05\n\x04Node\x12T\n\x0fNodeStageVolume\x12\x1e.csi.v1.NodeStageVolumeRequest\x1a\x1f.csi.v1.NodeStageVolumeResponse\"\x00\x12Z\n\x11NodeUnstageVolume\x12 .csi.v1.NodeUnstageVolumeRequest\x1a!.csi.v1.NodeUnstageVolumeResponse\"\x00\x12Z\n\x11NodePublishVolume\x12 .csi.v1.NodePublishVolumeRequest\x1a!.csi.v1.NodePublishVolumeResponse\"\x00\x12`\n\x13NodeUnpublishVolume\x12\".csi.v1.NodeUnpublishVolumeRequest\x1a#.csi.v1.NodeUnpublishVolumeResponse\"\x00\x12]\n\x12NodeGetVolumeStats\x12!.csi.v1.NodeGetVolumeStatsRequest\x1a\".csi.v1.NodeGetVolumeStatsResponse\"\x00\x12W\n\x10NodeExpandVolume\x12\x1f.csi.v1.NodeExpandVolumeRequest\x1a .csi.v1.NodeExpandVolumeResponse\"\x00\x12`\n\x13NodeGetCapabilities\x12\".csi.v1.NodeGetCapabilitiesRequest\x1a#.csi.v1.NodeGetCapabilitiesResponse\"\x00\x12H\n\x0bNodeGetInfo\x12\x1a.csi.v1.NodeGetInfoRequest\x1a\x1b.csi.v1.NodeGetInfoResponse\"\x00:1\n\nalpha_enum\x12\x1c.google.protobuf.EnumOptions\x18\xa4\x08 \x01(\x08:<\n\x10\x61lpha_enum_value\x12!.google.protobuf.EnumValueOptions\x18\xa4\x08 \x01(\x08:2\n\ncsi_secret\x12\x1d.google.protobuf.FieldOptions\x18\xa3\x08 \x01(\x08:3\n\x0b\x61lpha_field\x12\x1d.google.protobuf.FieldOptions\x18\xa4\x08 \x01(\x08:7\n\ralpha_message\x12\x1f.google.protobuf.MessageOptions\x18\xa4\x08 \x01(\x08:5\n\x0c\x61lpha_method\x12\x1e.google.protobuf.MethodOptions\x18\xa4\x08 \x01(\x08:7\n\ralpha_service\x12\x1f.google.protobuf.ServiceOptions\x18\xa4\x08 \x01(\x08\x42\x05Z\x03\x63sib\x06proto3' , dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,]) +ALPHA_ENUM_FIELD_NUMBER = 1060 +alpha_enum = _descriptor.FieldDescriptor( + name='alpha_enum', full_name='csi.v1.alpha_enum', index=0, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) +ALPHA_ENUM_VALUE_FIELD_NUMBER = 1060 +alpha_enum_value = _descriptor.FieldDescriptor( + name='alpha_enum_value', full_name='csi.v1.alpha_enum_value', index=1, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) CSI_SECRET_FIELD_NUMBER = 1059 csi_secret = _descriptor.FieldDescriptor( - name='csi_secret', full_name='csi.v1.csi_secret', index=0, + name='csi_secret', full_name='csi.v1.csi_secret', index=2, number=1059, type=8, cpp_type=7, label=1, has_default_value=False, default_value=False, message_type=None, enum_type=None, containing_type=None, is_extension=True, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) +ALPHA_FIELD_FIELD_NUMBER = 1060 +alpha_field = _descriptor.FieldDescriptor( + name='alpha_field', full_name='csi.v1.alpha_field', index=3, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) +ALPHA_MESSAGE_FIELD_NUMBER = 1060 +alpha_message = _descriptor.FieldDescriptor( + name='alpha_message', full_name='csi.v1.alpha_message', index=4, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) +ALPHA_METHOD_FIELD_NUMBER = 1060 +alpha_method = _descriptor.FieldDescriptor( + name='alpha_method', full_name='csi.v1.alpha_method', index=5, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) +ALPHA_SERVICE_FIELD_NUMBER = 1060 +alpha_service = _descriptor.FieldDescriptor( + name='alpha_service', full_name='csi.v1.alpha_service', index=6, + number=1060, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key) _PLUGINCAPABILITY_SERVICE_TYPE = _descriptor.EnumDescriptor( name='Type', @@ -61,8 +109,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=642, - serialized_end=723, + serialized_start=665, + serialized_end=746, ) _sym_db.RegisterEnumDescriptor(_PLUGINCAPABILITY_SERVICE_TYPE) @@ -91,8 +139,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=805, - serialized_end=849, + serialized_start=828, + serialized_end=872, ) _sym_db.RegisterEnumDescriptor(_PLUGINCAPABILITY_VOLUMEEXPANSION_TYPE) @@ -133,11 +181,21 @@ serialized_options=None, type=None, create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SINGLE_NODE_SINGLE_WRITER', index=6, number=6, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SINGLE_NODE_MULTI_WRITER', index=7, number=7, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), ], containing_type=None, serialized_options=None, - serialized_start=2043, - serialized_end=2202, + serialized_start=2099, + serialized_end=2329, ) _sym_db.RegisterEnumDescriptor(_VOLUMECAPABILITY_ACCESSMODE_MODE) @@ -203,11 +261,26 @@ serialized_options=None, type=None, create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='VOLUME_CONDITION', index=11, number=11, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='GET_VOLUME', index=12, number=12, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SINGLE_NODE_MULTI_WRITER', index=13, number=13, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), ], containing_type=None, serialized_options=None, - serialized_start=5633, - serialized_end=5885, + serialized_start=6227, + serialized_end=6562, ) _sym_db.RegisterEnumDescriptor(_CONTROLLERSERVICECAPABILITY_RPC_TYPE) @@ -236,8 +309,8 @@ ], containing_type=None, serialized_options=None, - serialized_start=8921, - serialized_end=8963, + serialized_start=9654, + serialized_end=9696, ) _sym_db.RegisterEnumDescriptor(_VOLUMEUSAGE_UNIT) @@ -268,11 +341,26 @@ serialized_options=None, type=None, create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='VOLUME_CONDITION', index=4, number=4, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SINGLE_NODE_MULTI_WRITER', index=5, number=5, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='VOLUME_MOUNT_GROUP', index=6, number=6, + serialized_options=b'\240B\001', + type=None, + create_key=_descriptor._internal_create_key), ], containing_type=None, serialized_options=None, - serialized_start=9217, - serialized_end=9303, + serialized_start=10010, + serialized_end=10187, ) _sym_db.RegisterEnumDescriptor(_NODESERVICECAPABILITY_RPC_TYPE) @@ -297,8 +385,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=120, - serialized_end=142, + serialized_start=143, + serialized_end=165, ) @@ -336,8 +424,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=271, - serialized_end=318, + serialized_start=294, + serialized_end=341, ) _GETPLUGININFORESPONSE = _descriptor.Descriptor( @@ -381,8 +469,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=145, - serialized_end=318, + serialized_start=168, + serialized_end=341, ) @@ -406,8 +494,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=320, - serialized_end=350, + serialized_start=343, + serialized_end=373, ) @@ -438,8 +526,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=352, - serialized_end=431, + serialized_start=375, + serialized_end=454, ) @@ -471,8 +559,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=578, - serialized_end=723, + serialized_start=601, + serialized_end=746, ) _PLUGINCAPABILITY_VOLUMEEXPANSION = _descriptor.Descriptor( @@ -503,8 +591,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=725, - serialized_end=849, + serialized_start=748, + serialized_end=872, ) _PLUGINCAPABILITY = _descriptor.Descriptor( @@ -546,8 +634,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=434, - serialized_end=857, + serialized_start=457, + serialized_end=880, ) @@ -571,8 +659,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=859, - serialized_end=873, + serialized_start=882, + serialized_end=896, ) @@ -603,8 +691,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=875, - serialized_end=933, + serialized_start=898, + serialized_end=956, ) @@ -642,8 +730,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1329, - serialized_end=1378, + serialized_start=1352, + serialized_end=1401, ) _CREATEVOLUMEREQUEST_SECRETSENTRY = _descriptor.Descriptor( @@ -680,8 +768,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _CREATEVOLUMEREQUEST = _descriptor.Descriptor( @@ -753,8 +841,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=936, - serialized_end=1426, + serialized_start=959, + serialized_end=1449, ) @@ -785,8 +873,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1576, - serialized_end=1613, + serialized_start=1599, + serialized_end=1636, ) _VOLUMECONTENTSOURCE_VOLUMESOURCE = _descriptor.Descriptor( @@ -816,8 +904,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1615, - serialized_end=1648, + serialized_start=1638, + serialized_end=1671, ) _VOLUMECONTENTSOURCE = _descriptor.Descriptor( @@ -859,8 +947,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=1429, - serialized_end=1656, + serialized_start=1452, + serialized_end=1679, ) @@ -891,8 +979,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1658, - serialized_end=1712, + serialized_start=1681, + serialized_end=1735, ) @@ -916,8 +1004,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1903, - serialized_end=1916, + serialized_start=1926, + serialized_end=1939, ) _VOLUMECAPABILITY_MOUNTVOLUME = _descriptor.Descriptor( @@ -942,6 +1030,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume_mount_group', full_name='csi.v1.VolumeCapability.MountVolume.volume_mount_group', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -954,8 +1049,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1918, - serialized_end=1969, + serialized_start=1941, + serialized_end=2025, ) _VOLUMECAPABILITY_ACCESSMODE = _descriptor.Descriptor( @@ -986,8 +1081,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1972, - serialized_end=2202, + serialized_start=2028, + serialized_end=2329, ) _VOLUMECAPABILITY = _descriptor.Descriptor( @@ -1036,8 +1131,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=1715, - serialized_end=2217, + serialized_start=1738, + serialized_end=2344, ) @@ -1075,8 +1170,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2219, - serialized_end=2279, + serialized_start=2346, + serialized_end=2406, ) @@ -1114,8 +1209,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _VOLUME = _descriptor.Descriptor( @@ -1173,8 +1268,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2282, - serialized_end=2546, + serialized_start=2409, + serialized_end=2673, ) @@ -1212,8 +1307,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2548, - serialized_end=2643, + serialized_start=2675, + serialized_end=2770, ) @@ -1251,8 +1346,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2707, - serialized_end=2754, + serialized_start=2834, + serialized_end=2881, ) _TOPOLOGY = _descriptor.Descriptor( @@ -1282,8 +1377,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2645, - serialized_end=2754, + serialized_start=2772, + serialized_end=2881, ) @@ -1321,8 +1416,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _DELETEVOLUMEREQUEST = _descriptor.Descriptor( @@ -1359,8 +1454,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2757, - serialized_end=2909, + serialized_start=2884, + serialized_end=3036, ) @@ -1384,8 +1479,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2911, - serialized_end=2933, + serialized_start=3038, + serialized_end=3060, ) @@ -1423,8 +1518,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _CONTROLLERPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY = _descriptor.Descriptor( @@ -1461,8 +1556,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _CONTROLLERPUBLISHVOLUMEREQUEST = _descriptor.Descriptor( @@ -1527,8 +1622,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2936, - serialized_end=3335, + serialized_start=3063, + serialized_end=3462, ) @@ -1566,8 +1661,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3459, - serialized_end=3512, + serialized_start=3586, + serialized_end=3639, ) _CONTROLLERPUBLISHVOLUMERESPONSE = _descriptor.Descriptor( @@ -1597,8 +1692,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3338, - serialized_end=3512, + serialized_start=3465, + serialized_end=3639, ) @@ -1636,8 +1731,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _CONTROLLERUNPUBLISHVOLUMEREQUEST = _descriptor.Descriptor( @@ -1681,8 +1776,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3515, - serialized_end=3710, + serialized_start=3642, + serialized_end=3837, ) @@ -1706,8 +1801,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3712, - serialized_end=3747, + serialized_start=3839, + serialized_end=3874, ) @@ -1745,8 +1840,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _VALIDATEVOLUMECAPABILITIESREQUEST_PARAMETERSENTRY = _descriptor.Descriptor( @@ -1783,8 +1878,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1329, - serialized_end=1378, + serialized_start=1352, + serialized_end=1401, ) _VALIDATEVOLUMECAPABILITIESREQUEST_SECRETSENTRY = _descriptor.Descriptor( @@ -1821,8 +1916,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _VALIDATEVOLUMECAPABILITIESREQUEST = _descriptor.Descriptor( @@ -1880,8 +1975,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3750, - serialized_end=4255, + serialized_start=3877, + serialized_end=4382, ) @@ -1919,8 +2014,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_PARAMETERSENTRY = _descriptor.Descriptor( @@ -1957,8 +2052,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1329, - serialized_end=1378, + serialized_start=1352, + serialized_end=1401, ) _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED = _descriptor.Descriptor( @@ -2002,8 +2097,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4387, - serialized_end=4745, + serialized_start=4514, + serialized_end=4872, ) _VALIDATEVOLUMECAPABILITIESRESPONSE = _descriptor.Descriptor( @@ -2040,8 +2135,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4258, - serialized_end=4745, + serialized_start=4385, + serialized_end=4872, ) @@ -2079,8 +2174,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4747, - serialized_end=4812, + serialized_start=4874, + serialized_end=4939, ) @@ -2099,6 +2194,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume_condition', full_name='csi.v1.ListVolumesResponse.VolumeStatus.volume_condition', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -2111,8 +2213,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4910, - serialized_end=4952, + serialized_start=5037, + serialized_end=5135, ) _LISTVOLUMESRESPONSE_ENTRY = _descriptor.Descriptor( @@ -2149,8 +2251,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4954, - serialized_end=5051, + serialized_start=5137, + serialized_end=5234, ) _LISTVOLUMESRESPONSE = _descriptor.Descriptor( @@ -2187,8 +2289,117 @@ extension_ranges=[], oneofs=[ ], - serialized_start=4815, - serialized_end=5051, + serialized_start=4942, + serialized_end=5234, +) + + +_CONTROLLERGETVOLUMEREQUEST = _descriptor.Descriptor( + name='ControllerGetVolumeRequest', + full_name='csi.v1.ControllerGetVolumeRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='volume_id', full_name='csi.v1.ControllerGetVolumeRequest.volume_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'\240B\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5236, + serialized_end=5288, +) + + +_CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS = _descriptor.Descriptor( + name='VolumeStatus', + full_name='csi.v1.ControllerGetVolumeResponse.VolumeStatus', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='published_node_ids', full_name='csi.v1.ControllerGetVolumeResponse.VolumeStatus.published_node_ids', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume_condition', full_name='csi.v1.ControllerGetVolumeResponse.VolumeStatus.volume_condition', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5420, + serialized_end=5513, +) + +_CONTROLLERGETVOLUMERESPONSE = _descriptor.Descriptor( + name='ControllerGetVolumeResponse', + full_name='csi.v1.ControllerGetVolumeResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='volume', full_name='csi.v1.ControllerGetVolumeResponse.volume', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='status', full_name='csi.v1.ControllerGetVolumeResponse.status', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS, ], + enum_types=[ + ], + serialized_options=b'\240B\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5291, + serialized_end=5518, ) @@ -2226,8 +2437,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1329, - serialized_end=1378, + serialized_start=1352, + serialized_end=1401, ) _GETCAPACITYREQUEST = _descriptor.Descriptor( @@ -2271,8 +2482,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5054, - serialized_end=5291, + serialized_start=5521, + serialized_end=5758, ) @@ -2291,6 +2502,20 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='maximum_volume_size', full_name='csi.v1.GetCapacityResponse.maximum_volume_size', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='minimum_volume_size', full_name='csi.v1.GetCapacityResponse.minimum_volume_size', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -2303,8 +2528,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5293, - serialized_end=5342, + serialized_start=5761, + serialized_end=5936, ) @@ -2328,8 +2553,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5344, - serialized_end=5378, + serialized_start=5938, + serialized_end=5972, ) @@ -2360,8 +2585,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5380, - serialized_end=5474, + serialized_start=5974, + serialized_end=6068, ) @@ -2393,8 +2618,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5565, - serialized_end=5885, + serialized_start=6159, + serialized_end=6562, ) _CONTROLLERSERVICECAPABILITY = _descriptor.Descriptor( @@ -2429,8 +2654,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=5477, - serialized_end=5893, + serialized_start=6071, + serialized_end=6570, ) @@ -2468,8 +2693,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _CREATESNAPSHOTREQUEST_PARAMETERSENTRY = _descriptor.Descriptor( @@ -2506,8 +2731,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1329, - serialized_end=1378, + serialized_start=1352, + serialized_end=1401, ) _CREATESNAPSHOTREQUEST = _descriptor.Descriptor( @@ -2558,8 +2783,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=5896, - serialized_end=6191, + serialized_start=6573, + serialized_end=6868, ) @@ -2590,8 +2815,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6193, - serialized_end=6253, + serialized_start=6870, + serialized_end=6930, ) @@ -2650,8 +2875,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6256, - serialized_end=6406, + serialized_start=6933, + serialized_end=7083, ) @@ -2689,8 +2914,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _DELETESNAPSHOTREQUEST = _descriptor.Descriptor( @@ -2727,8 +2952,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6409, - serialized_end=6567, + serialized_start=7086, + serialized_end=7244, ) @@ -2752,8 +2977,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6569, - serialized_end=6593, + serialized_start=7246, + serialized_end=7270, ) @@ -2791,8 +3016,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _LISTSNAPSHOTSREQUEST = _descriptor.Descriptor( @@ -2850,8 +3075,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6596, - serialized_end=6823, + serialized_start=7273, + serialized_end=7500, ) @@ -2882,8 +3107,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6925, - serialized_end=6968, + serialized_start=7602, + serialized_end=7645, ) _LISTSNAPSHOTSRESPONSE = _descriptor.Descriptor( @@ -2920,8 +3145,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6826, - serialized_end=6968, + serialized_start=7503, + serialized_end=7645, ) @@ -2959,8 +3184,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _CONTROLLEREXPANDVOLUMEREQUEST = _descriptor.Descriptor( @@ -3011,8 +3236,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6971, - serialized_end=7243, + serialized_start=7648, + serialized_end=7920, ) @@ -3050,8 +3275,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7245, - serialized_end=7334, + serialized_start=7922, + serialized_end=8011, ) @@ -3089,8 +3314,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3459, - serialized_end=3512, + serialized_start=3586, + serialized_end=3639, ) _NODESTAGEVOLUMEREQUEST_SECRETSENTRY = _descriptor.Descriptor( @@ -3127,8 +3352,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _NODESTAGEVOLUMEREQUEST_VOLUMECONTEXTENTRY = _descriptor.Descriptor( @@ -3165,8 +3390,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _NODESTAGEVOLUMEREQUEST = _descriptor.Descriptor( @@ -3231,8 +3456,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7337, - serialized_end=7838, + serialized_start=8014, + serialized_end=8515, ) @@ -3256,8 +3481,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7840, - serialized_end=7865, + serialized_start=8517, + serialized_end=8542, ) @@ -3295,8 +3520,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7867, - serialized_end=7941, + serialized_start=8544, + serialized_end=8618, ) @@ -3320,8 +3545,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7943, - serialized_end=7970, + serialized_start=8620, + serialized_end=8647, ) @@ -3359,8 +3584,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=3459, - serialized_end=3512, + serialized_start=3586, + serialized_end=3639, ) _NODEPUBLISHVOLUMEREQUEST_SECRETSENTRY = _descriptor.Descriptor( @@ -3397,8 +3622,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1380, - serialized_end=1426, + serialized_start=1403, + serialized_end=1449, ) _NODEPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY = _descriptor.Descriptor( @@ -3435,8 +3660,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2494, - serialized_end=2546, + serialized_start=2621, + serialized_end=2673, ) _NODEPUBLISHVOLUMEREQUEST = _descriptor.Descriptor( @@ -3515,8 +3740,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7973, - serialized_end=8521, + serialized_start=8650, + serialized_end=9198, ) @@ -3540,8 +3765,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8523, - serialized_end=8550, + serialized_start=9200, + serialized_end=9227, ) @@ -3579,8 +3804,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8552, - serialized_end=8620, + serialized_start=9229, + serialized_end=9297, ) @@ -3604,8 +3829,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8622, - serialized_end=8651, + serialized_start=9299, + serialized_end=9328, ) @@ -3650,8 +3875,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8653, - serialized_end=8749, + serialized_start=9330, + serialized_end=9426, ) @@ -3670,6 +3895,13 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume_condition', full_name='csi.v1.NodeGetVolumeStatsResponse.volume_condition', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], @@ -3682,8 +3914,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8751, - serialized_end=8815, + serialized_start=9428, + serialized_end=9548, ) @@ -3736,8 +3968,47 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8818, - serialized_end=8963, + serialized_start=9551, + serialized_end=9696, +) + + +_VOLUMECONDITION = _descriptor.Descriptor( + name='VolumeCondition', + full_name='csi.v1.VolumeCondition', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='abnormal', full_name='csi.v1.VolumeCondition.abnormal', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='message', full_name='csi.v1.VolumeCondition.message', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'\240B\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=9698, + serialized_end=9755, ) @@ -3761,8 +4032,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8965, - serialized_end=8993, + serialized_start=9757, + serialized_end=9785, ) @@ -3793,8 +4064,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8995, - serialized_end=9077, + serialized_start=9787, + serialized_end=9869, ) @@ -3826,8 +4097,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9156, - serialized_end=9303, + serialized_start=9948, + serialized_end=10187, ) _NODESERVICECAPABILITY = _descriptor.Descriptor( @@ -3862,8 +4133,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=9080, - serialized_end=9311, + serialized_start=9872, + serialized_end=10195, ) @@ -3887,8 +4158,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9313, - serialized_end=9333, + serialized_start=10197, + serialized_end=10217, ) @@ -3933,11 +4204,49 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9335, - serialized_end=9450, + serialized_start=10219, + serialized_end=10334, ) +_NODEEXPANDVOLUMEREQUEST_SECRETSENTRY = _descriptor.Descriptor( + name='SecretsEntry', + full_name='csi.v1.NodeExpandVolumeRequest.SecretsEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='csi.v1.NodeExpandVolumeRequest.SecretsEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='csi.v1.NodeExpandVolumeRequest.SecretsEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1403, + serialized_end=1449, +) + _NODEEXPANDVOLUMEREQUEST = _descriptor.Descriptor( name='NodeExpandVolumeRequest', full_name='csi.v1.NodeExpandVolumeRequest', @@ -3981,10 +4290,17 @@ message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='secrets', full_name='csi.v1.NodeExpandVolumeRequest.secrets', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=b'\230B\001\240B\001', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), ], extensions=[ ], - nested_types=[], + nested_types=[_NODEEXPANDVOLUMEREQUEST_SECRETSENTRY, ], enum_types=[ ], serialized_options=None, @@ -3993,8 +4309,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9453, - serialized_end=9647, + serialized_start=10337, + serialized_end=10650, ) @@ -4025,8 +4341,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=9649, - serialized_end=9699, + serialized_start=10652, + serialized_end=10702, ) _GETPLUGININFORESPONSE_MANIFESTENTRY.containing_type = _GETPLUGININFORESPONSE @@ -4113,15 +4429,22 @@ _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED.fields_by_name['parameters'].message_type = _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_PARAMETERSENTRY _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED.containing_type = _VALIDATEVOLUMECAPABILITIESRESPONSE _VALIDATEVOLUMECAPABILITIESRESPONSE.fields_by_name['confirmed'].message_type = _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED +_LISTVOLUMESRESPONSE_VOLUMESTATUS.fields_by_name['volume_condition'].message_type = _VOLUMECONDITION _LISTVOLUMESRESPONSE_VOLUMESTATUS.containing_type = _LISTVOLUMESRESPONSE _LISTVOLUMESRESPONSE_ENTRY.fields_by_name['volume'].message_type = _VOLUME _LISTVOLUMESRESPONSE_ENTRY.fields_by_name['status'].message_type = _LISTVOLUMESRESPONSE_VOLUMESTATUS _LISTVOLUMESRESPONSE_ENTRY.containing_type = _LISTVOLUMESRESPONSE _LISTVOLUMESRESPONSE.fields_by_name['entries'].message_type = _LISTVOLUMESRESPONSE_ENTRY +_CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS.fields_by_name['volume_condition'].message_type = _VOLUMECONDITION +_CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS.containing_type = _CONTROLLERGETVOLUMERESPONSE +_CONTROLLERGETVOLUMERESPONSE.fields_by_name['volume'].message_type = _VOLUME +_CONTROLLERGETVOLUMERESPONSE.fields_by_name['status'].message_type = _CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS _GETCAPACITYREQUEST_PARAMETERSENTRY.containing_type = _GETCAPACITYREQUEST _GETCAPACITYREQUEST.fields_by_name['volume_capabilities'].message_type = _VOLUMECAPABILITY _GETCAPACITYREQUEST.fields_by_name['parameters'].message_type = _GETCAPACITYREQUEST_PARAMETERSENTRY _GETCAPACITYREQUEST.fields_by_name['accessible_topology'].message_type = _TOPOLOGY +_GETCAPACITYRESPONSE.fields_by_name['maximum_volume_size'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_GETCAPACITYRESPONSE.fields_by_name['minimum_volume_size'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE _CONTROLLERGETCAPABILITIESRESPONSE.fields_by_name['capabilities'].message_type = _CONTROLLERSERVICECAPABILITY _CONTROLLERSERVICECAPABILITY_RPC.fields_by_name['type'].enum_type = _CONTROLLERSERVICECAPABILITY_RPC_TYPE _CONTROLLERSERVICECAPABILITY_RPC.containing_type = _CONTROLLERSERVICECAPABILITY @@ -4162,6 +4485,7 @@ _NODEPUBLISHVOLUMEREQUEST.fields_by_name['secrets'].message_type = _NODEPUBLISHVOLUMEREQUEST_SECRETSENTRY _NODEPUBLISHVOLUMEREQUEST.fields_by_name['volume_context'].message_type = _NODEPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY _NODEGETVOLUMESTATSRESPONSE.fields_by_name['usage'].message_type = _VOLUMEUSAGE +_NODEGETVOLUMESTATSRESPONSE.fields_by_name['volume_condition'].message_type = _VOLUMECONDITION _VOLUMEUSAGE.fields_by_name['unit'].enum_type = _VOLUMEUSAGE_UNIT _VOLUMEUSAGE_UNIT.containing_type = _VOLUMEUSAGE _NODEGETCAPABILITIESRESPONSE.fields_by_name['capabilities'].message_type = _NODESERVICECAPABILITY @@ -4173,8 +4497,10 @@ _NODESERVICECAPABILITY.fields_by_name['rpc']) _NODESERVICECAPABILITY.fields_by_name['rpc'].containing_oneof = _NODESERVICECAPABILITY.oneofs_by_name['type'] _NODEGETINFORESPONSE.fields_by_name['accessible_topology'].message_type = _TOPOLOGY +_NODEEXPANDVOLUMEREQUEST_SECRETSENTRY.containing_type = _NODEEXPANDVOLUMEREQUEST _NODEEXPANDVOLUMEREQUEST.fields_by_name['capacity_range'].message_type = _CAPACITYRANGE _NODEEXPANDVOLUMEREQUEST.fields_by_name['volume_capability'].message_type = _VOLUMECAPABILITY +_NODEEXPANDVOLUMEREQUEST.fields_by_name['secrets'].message_type = _NODEEXPANDVOLUMEREQUEST_SECRETSENTRY DESCRIPTOR.message_types_by_name['GetPluginInfoRequest'] = _GETPLUGININFOREQUEST DESCRIPTOR.message_types_by_name['GetPluginInfoResponse'] = _GETPLUGININFORESPONSE DESCRIPTOR.message_types_by_name['GetPluginCapabilitiesRequest'] = _GETPLUGINCAPABILITIESREQUEST @@ -4200,6 +4526,8 @@ DESCRIPTOR.message_types_by_name['ValidateVolumeCapabilitiesResponse'] = _VALIDATEVOLUMECAPABILITIESRESPONSE DESCRIPTOR.message_types_by_name['ListVolumesRequest'] = _LISTVOLUMESREQUEST DESCRIPTOR.message_types_by_name['ListVolumesResponse'] = _LISTVOLUMESRESPONSE +DESCRIPTOR.message_types_by_name['ControllerGetVolumeRequest'] = _CONTROLLERGETVOLUMEREQUEST +DESCRIPTOR.message_types_by_name['ControllerGetVolumeResponse'] = _CONTROLLERGETVOLUMERESPONSE DESCRIPTOR.message_types_by_name['GetCapacityRequest'] = _GETCAPACITYREQUEST DESCRIPTOR.message_types_by_name['GetCapacityResponse'] = _GETCAPACITYRESPONSE DESCRIPTOR.message_types_by_name['ControllerGetCapabilitiesRequest'] = _CONTROLLERGETCAPABILITIESREQUEST @@ -4225,6 +4553,7 @@ DESCRIPTOR.message_types_by_name['NodeGetVolumeStatsRequest'] = _NODEGETVOLUMESTATSREQUEST DESCRIPTOR.message_types_by_name['NodeGetVolumeStatsResponse'] = _NODEGETVOLUMESTATSRESPONSE DESCRIPTOR.message_types_by_name['VolumeUsage'] = _VOLUMEUSAGE +DESCRIPTOR.message_types_by_name['VolumeCondition'] = _VOLUMECONDITION DESCRIPTOR.message_types_by_name['NodeGetCapabilitiesRequest'] = _NODEGETCAPABILITIESREQUEST DESCRIPTOR.message_types_by_name['NodeGetCapabilitiesResponse'] = _NODEGETCAPABILITIESRESPONSE DESCRIPTOR.message_types_by_name['NodeServiceCapability'] = _NODESERVICECAPABILITY @@ -4232,12 +4561,18 @@ DESCRIPTOR.message_types_by_name['NodeGetInfoResponse'] = _NODEGETINFORESPONSE DESCRIPTOR.message_types_by_name['NodeExpandVolumeRequest'] = _NODEEXPANDVOLUMEREQUEST DESCRIPTOR.message_types_by_name['NodeExpandVolumeResponse'] = _NODEEXPANDVOLUMERESPONSE +DESCRIPTOR.extensions_by_name['alpha_enum'] = alpha_enum +DESCRIPTOR.extensions_by_name['alpha_enum_value'] = alpha_enum_value DESCRIPTOR.extensions_by_name['csi_secret'] = csi_secret +DESCRIPTOR.extensions_by_name['alpha_field'] = alpha_field +DESCRIPTOR.extensions_by_name['alpha_message'] = alpha_message +DESCRIPTOR.extensions_by_name['alpha_method'] = alpha_method +DESCRIPTOR.extensions_by_name['alpha_service'] = alpha_service _sym_db.RegisterFileDescriptor(DESCRIPTOR) GetPluginInfoRequest = _reflection.GeneratedProtocolMessageType('GetPluginInfoRequest', (_message.Message,), { 'DESCRIPTOR' : _GETPLUGININFOREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetPluginInfoRequest) }) _sym_db.RegisterMessage(GetPluginInfoRequest) @@ -4246,12 +4581,12 @@ 'ManifestEntry' : _reflection.GeneratedProtocolMessageType('ManifestEntry', (_message.Message,), { 'DESCRIPTOR' : _GETPLUGININFORESPONSE_MANIFESTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetPluginInfoResponse.ManifestEntry) }) , 'DESCRIPTOR' : _GETPLUGININFORESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetPluginInfoResponse) }) _sym_db.RegisterMessage(GetPluginInfoResponse) @@ -4259,14 +4594,14 @@ GetPluginCapabilitiesRequest = _reflection.GeneratedProtocolMessageType('GetPluginCapabilitiesRequest', (_message.Message,), { 'DESCRIPTOR' : _GETPLUGINCAPABILITIESREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetPluginCapabilitiesRequest) }) _sym_db.RegisterMessage(GetPluginCapabilitiesRequest) GetPluginCapabilitiesResponse = _reflection.GeneratedProtocolMessageType('GetPluginCapabilitiesResponse', (_message.Message,), { 'DESCRIPTOR' : _GETPLUGINCAPABILITIESRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetPluginCapabilitiesResponse) }) _sym_db.RegisterMessage(GetPluginCapabilitiesResponse) @@ -4275,19 +4610,19 @@ 'Service' : _reflection.GeneratedProtocolMessageType('Service', (_message.Message,), { 'DESCRIPTOR' : _PLUGINCAPABILITY_SERVICE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.PluginCapability.Service) }) , 'VolumeExpansion' : _reflection.GeneratedProtocolMessageType('VolumeExpansion', (_message.Message,), { 'DESCRIPTOR' : _PLUGINCAPABILITY_VOLUMEEXPANSION, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.PluginCapability.VolumeExpansion) }) , 'DESCRIPTOR' : _PLUGINCAPABILITY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.PluginCapability) }) _sym_db.RegisterMessage(PluginCapability) @@ -4296,14 +4631,14 @@ ProbeRequest = _reflection.GeneratedProtocolMessageType('ProbeRequest', (_message.Message,), { 'DESCRIPTOR' : _PROBEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ProbeRequest) }) _sym_db.RegisterMessage(ProbeRequest) ProbeResponse = _reflection.GeneratedProtocolMessageType('ProbeResponse', (_message.Message,), { 'DESCRIPTOR' : _PROBERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ProbeResponse) }) _sym_db.RegisterMessage(ProbeResponse) @@ -4312,19 +4647,19 @@ 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { 'DESCRIPTOR' : _CREATEVOLUMEREQUEST_PARAMETERSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateVolumeRequest.ParametersEntry) }) , 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _CREATEVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateVolumeRequest.SecretsEntry) }) , 'DESCRIPTOR' : _CREATEVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateVolumeRequest) }) _sym_db.RegisterMessage(CreateVolumeRequest) @@ -4335,19 +4670,19 @@ 'SnapshotSource' : _reflection.GeneratedProtocolMessageType('SnapshotSource', (_message.Message,), { 'DESCRIPTOR' : _VOLUMECONTENTSOURCE_SNAPSHOTSOURCE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeContentSource.SnapshotSource) }) , 'VolumeSource' : _reflection.GeneratedProtocolMessageType('VolumeSource', (_message.Message,), { 'DESCRIPTOR' : _VOLUMECONTENTSOURCE_VOLUMESOURCE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeContentSource.VolumeSource) }) , 'DESCRIPTOR' : _VOLUMECONTENTSOURCE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeContentSource) }) _sym_db.RegisterMessage(VolumeContentSource) @@ -4356,7 +4691,7 @@ CreateVolumeResponse = _reflection.GeneratedProtocolMessageType('CreateVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _CREATEVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateVolumeResponse) }) _sym_db.RegisterMessage(CreateVolumeResponse) @@ -4365,26 +4700,26 @@ 'BlockVolume' : _reflection.GeneratedProtocolMessageType('BlockVolume', (_message.Message,), { 'DESCRIPTOR' : _VOLUMECAPABILITY_BLOCKVOLUME, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeCapability.BlockVolume) }) , 'MountVolume' : _reflection.GeneratedProtocolMessageType('MountVolume', (_message.Message,), { 'DESCRIPTOR' : _VOLUMECAPABILITY_MOUNTVOLUME, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeCapability.MountVolume) }) , 'AccessMode' : _reflection.GeneratedProtocolMessageType('AccessMode', (_message.Message,), { 'DESCRIPTOR' : _VOLUMECAPABILITY_ACCESSMODE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeCapability.AccessMode) }) , 'DESCRIPTOR' : _VOLUMECAPABILITY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeCapability) }) _sym_db.RegisterMessage(VolumeCapability) @@ -4394,7 +4729,7 @@ CapacityRange = _reflection.GeneratedProtocolMessageType('CapacityRange', (_message.Message,), { 'DESCRIPTOR' : _CAPACITYRANGE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CapacityRange) }) _sym_db.RegisterMessage(CapacityRange) @@ -4403,12 +4738,12 @@ 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _VOLUME_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.Volume.VolumeContextEntry) }) , 'DESCRIPTOR' : _VOLUME, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.Volume) }) _sym_db.RegisterMessage(Volume) @@ -4416,7 +4751,7 @@ TopologyRequirement = _reflection.GeneratedProtocolMessageType('TopologyRequirement', (_message.Message,), { 'DESCRIPTOR' : _TOPOLOGYREQUIREMENT, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.TopologyRequirement) }) _sym_db.RegisterMessage(TopologyRequirement) @@ -4425,12 +4760,12 @@ 'SegmentsEntry' : _reflection.GeneratedProtocolMessageType('SegmentsEntry', (_message.Message,), { 'DESCRIPTOR' : _TOPOLOGY_SEGMENTSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.Topology.SegmentsEntry) }) , 'DESCRIPTOR' : _TOPOLOGY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.Topology) }) _sym_db.RegisterMessage(Topology) @@ -4440,12 +4775,12 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _DELETEVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteVolumeRequest.SecretsEntry) }) , 'DESCRIPTOR' : _DELETEVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteVolumeRequest) }) _sym_db.RegisterMessage(DeleteVolumeRequest) @@ -4453,7 +4788,7 @@ DeleteVolumeResponse = _reflection.GeneratedProtocolMessageType('DeleteVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _DELETEVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteVolumeResponse) }) _sym_db.RegisterMessage(DeleteVolumeResponse) @@ -4462,19 +4797,19 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERPUBLISHVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerPublishVolumeRequest.SecretsEntry) }) , 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerPublishVolumeRequest.VolumeContextEntry) }) , 'DESCRIPTOR' : _CONTROLLERPUBLISHVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerPublishVolumeRequest) }) _sym_db.RegisterMessage(ControllerPublishVolumeRequest) @@ -4485,12 +4820,12 @@ 'PublishContextEntry' : _reflection.GeneratedProtocolMessageType('PublishContextEntry', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERPUBLISHVOLUMERESPONSE_PUBLISHCONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerPublishVolumeResponse.PublishContextEntry) }) , 'DESCRIPTOR' : _CONTROLLERPUBLISHVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerPublishVolumeResponse) }) _sym_db.RegisterMessage(ControllerPublishVolumeResponse) @@ -4500,12 +4835,12 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERUNPUBLISHVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerUnpublishVolumeRequest.SecretsEntry) }) , 'DESCRIPTOR' : _CONTROLLERUNPUBLISHVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerUnpublishVolumeRequest) }) _sym_db.RegisterMessage(ControllerUnpublishVolumeRequest) @@ -4513,7 +4848,7 @@ ControllerUnpublishVolumeResponse = _reflection.GeneratedProtocolMessageType('ControllerUnpublishVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERUNPUBLISHVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerUnpublishVolumeResponse) }) _sym_db.RegisterMessage(ControllerUnpublishVolumeResponse) @@ -4522,26 +4857,26 @@ 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESREQUEST_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesRequest.VolumeContextEntry) }) , 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESREQUEST_PARAMETERSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesRequest.ParametersEntry) }) , 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesRequest.SecretsEntry) }) , 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesRequest) }) _sym_db.RegisterMessage(ValidateVolumeCapabilitiesRequest) @@ -4555,24 +4890,24 @@ 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.VolumeContextEntry) }) , 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_PARAMETERSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed.ParametersEntry) }) , 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesResponse.Confirmed) }) , 'DESCRIPTOR' : _VALIDATEVOLUMECAPABILITIESRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ValidateVolumeCapabilitiesResponse) }) _sym_db.RegisterMessage(ValidateVolumeCapabilitiesResponse) @@ -4582,7 +4917,7 @@ ListVolumesRequest = _reflection.GeneratedProtocolMessageType('ListVolumesRequest', (_message.Message,), { 'DESCRIPTOR' : _LISTVOLUMESREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListVolumesRequest) }) _sym_db.RegisterMessage(ListVolumesRequest) @@ -4591,35 +4926,57 @@ 'VolumeStatus' : _reflection.GeneratedProtocolMessageType('VolumeStatus', (_message.Message,), { 'DESCRIPTOR' : _LISTVOLUMESRESPONSE_VOLUMESTATUS, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListVolumesResponse.VolumeStatus) }) , 'Entry' : _reflection.GeneratedProtocolMessageType('Entry', (_message.Message,), { 'DESCRIPTOR' : _LISTVOLUMESRESPONSE_ENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListVolumesResponse.Entry) }) , 'DESCRIPTOR' : _LISTVOLUMESRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListVolumesResponse) }) _sym_db.RegisterMessage(ListVolumesResponse) _sym_db.RegisterMessage(ListVolumesResponse.VolumeStatus) _sym_db.RegisterMessage(ListVolumesResponse.Entry) +ControllerGetVolumeRequest = _reflection.GeneratedProtocolMessageType('ControllerGetVolumeRequest', (_message.Message,), { + 'DESCRIPTOR' : _CONTROLLERGETVOLUMEREQUEST, + '__module__' : 'controller.csi_general.csi_pb2' + # @@protoc_insertion_point(class_scope:csi.v1.ControllerGetVolumeRequest) + }) +_sym_db.RegisterMessage(ControllerGetVolumeRequest) + +ControllerGetVolumeResponse = _reflection.GeneratedProtocolMessageType('ControllerGetVolumeResponse', (_message.Message,), { + + 'VolumeStatus' : _reflection.GeneratedProtocolMessageType('VolumeStatus', (_message.Message,), { + 'DESCRIPTOR' : _CONTROLLERGETVOLUMERESPONSE_VOLUMESTATUS, + '__module__' : 'controller.csi_general.csi_pb2' + # @@protoc_insertion_point(class_scope:csi.v1.ControllerGetVolumeResponse.VolumeStatus) + }) + , + 'DESCRIPTOR' : _CONTROLLERGETVOLUMERESPONSE, + '__module__' : 'controller.csi_general.csi_pb2' + # @@protoc_insertion_point(class_scope:csi.v1.ControllerGetVolumeResponse) + }) +_sym_db.RegisterMessage(ControllerGetVolumeResponse) +_sym_db.RegisterMessage(ControllerGetVolumeResponse.VolumeStatus) + GetCapacityRequest = _reflection.GeneratedProtocolMessageType('GetCapacityRequest', (_message.Message,), { 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { 'DESCRIPTOR' : _GETCAPACITYREQUEST_PARAMETERSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetCapacityRequest.ParametersEntry) }) , 'DESCRIPTOR' : _GETCAPACITYREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetCapacityRequest) }) _sym_db.RegisterMessage(GetCapacityRequest) @@ -4627,21 +4984,21 @@ GetCapacityResponse = _reflection.GeneratedProtocolMessageType('GetCapacityResponse', (_message.Message,), { 'DESCRIPTOR' : _GETCAPACITYRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.GetCapacityResponse) }) _sym_db.RegisterMessage(GetCapacityResponse) ControllerGetCapabilitiesRequest = _reflection.GeneratedProtocolMessageType('ControllerGetCapabilitiesRequest', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERGETCAPABILITIESREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerGetCapabilitiesRequest) }) _sym_db.RegisterMessage(ControllerGetCapabilitiesRequest) ControllerGetCapabilitiesResponse = _reflection.GeneratedProtocolMessageType('ControllerGetCapabilitiesResponse', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERGETCAPABILITIESRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerGetCapabilitiesResponse) }) _sym_db.RegisterMessage(ControllerGetCapabilitiesResponse) @@ -4650,12 +5007,12 @@ 'RPC' : _reflection.GeneratedProtocolMessageType('RPC', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLERSERVICECAPABILITY_RPC, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerServiceCapability.RPC) }) , 'DESCRIPTOR' : _CONTROLLERSERVICECAPABILITY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerServiceCapability) }) _sym_db.RegisterMessage(ControllerServiceCapability) @@ -4665,19 +5022,19 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _CREATESNAPSHOTREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateSnapshotRequest.SecretsEntry) }) , 'ParametersEntry' : _reflection.GeneratedProtocolMessageType('ParametersEntry', (_message.Message,), { 'DESCRIPTOR' : _CREATESNAPSHOTREQUEST_PARAMETERSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateSnapshotRequest.ParametersEntry) }) , 'DESCRIPTOR' : _CREATESNAPSHOTREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateSnapshotRequest) }) _sym_db.RegisterMessage(CreateSnapshotRequest) @@ -4686,14 +5043,14 @@ CreateSnapshotResponse = _reflection.GeneratedProtocolMessageType('CreateSnapshotResponse', (_message.Message,), { 'DESCRIPTOR' : _CREATESNAPSHOTRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.CreateSnapshotResponse) }) _sym_db.RegisterMessage(CreateSnapshotResponse) Snapshot = _reflection.GeneratedProtocolMessageType('Snapshot', (_message.Message,), { 'DESCRIPTOR' : _SNAPSHOT, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.Snapshot) }) _sym_db.RegisterMessage(Snapshot) @@ -4702,12 +5059,12 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _DELETESNAPSHOTREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteSnapshotRequest.SecretsEntry) }) , 'DESCRIPTOR' : _DELETESNAPSHOTREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteSnapshotRequest) }) _sym_db.RegisterMessage(DeleteSnapshotRequest) @@ -4715,7 +5072,7 @@ DeleteSnapshotResponse = _reflection.GeneratedProtocolMessageType('DeleteSnapshotResponse', (_message.Message,), { 'DESCRIPTOR' : _DELETESNAPSHOTRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.DeleteSnapshotResponse) }) _sym_db.RegisterMessage(DeleteSnapshotResponse) @@ -4724,12 +5081,12 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _LISTSNAPSHOTSREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListSnapshotsRequest.SecretsEntry) }) , 'DESCRIPTOR' : _LISTSNAPSHOTSREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListSnapshotsRequest) }) _sym_db.RegisterMessage(ListSnapshotsRequest) @@ -4739,12 +5096,12 @@ 'Entry' : _reflection.GeneratedProtocolMessageType('Entry', (_message.Message,), { 'DESCRIPTOR' : _LISTSNAPSHOTSRESPONSE_ENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListSnapshotsResponse.Entry) }) , 'DESCRIPTOR' : _LISTSNAPSHOTSRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ListSnapshotsResponse) }) _sym_db.RegisterMessage(ListSnapshotsResponse) @@ -4754,12 +5111,12 @@ 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLEREXPANDVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerExpandVolumeRequest.SecretsEntry) }) , 'DESCRIPTOR' : _CONTROLLEREXPANDVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerExpandVolumeRequest) }) _sym_db.RegisterMessage(ControllerExpandVolumeRequest) @@ -4767,7 +5124,7 @@ ControllerExpandVolumeResponse = _reflection.GeneratedProtocolMessageType('ControllerExpandVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _CONTROLLEREXPANDVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.ControllerExpandVolumeResponse) }) _sym_db.RegisterMessage(ControllerExpandVolumeResponse) @@ -4776,26 +5133,26 @@ 'PublishContextEntry' : _reflection.GeneratedProtocolMessageType('PublishContextEntry', (_message.Message,), { 'DESCRIPTOR' : _NODESTAGEVOLUMEREQUEST_PUBLISHCONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeStageVolumeRequest.PublishContextEntry) }) , 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _NODESTAGEVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeStageVolumeRequest.SecretsEntry) }) , 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _NODESTAGEVOLUMEREQUEST_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeStageVolumeRequest.VolumeContextEntry) }) , 'DESCRIPTOR' : _NODESTAGEVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeStageVolumeRequest) }) _sym_db.RegisterMessage(NodeStageVolumeRequest) @@ -4805,21 +5162,21 @@ NodeStageVolumeResponse = _reflection.GeneratedProtocolMessageType('NodeStageVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _NODESTAGEVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeStageVolumeResponse) }) _sym_db.RegisterMessage(NodeStageVolumeResponse) NodeUnstageVolumeRequest = _reflection.GeneratedProtocolMessageType('NodeUnstageVolumeRequest', (_message.Message,), { 'DESCRIPTOR' : _NODEUNSTAGEVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeUnstageVolumeRequest) }) _sym_db.RegisterMessage(NodeUnstageVolumeRequest) NodeUnstageVolumeResponse = _reflection.GeneratedProtocolMessageType('NodeUnstageVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEUNSTAGEVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeUnstageVolumeResponse) }) _sym_db.RegisterMessage(NodeUnstageVolumeResponse) @@ -4828,26 +5185,26 @@ 'PublishContextEntry' : _reflection.GeneratedProtocolMessageType('PublishContextEntry', (_message.Message,), { 'DESCRIPTOR' : _NODEPUBLISHVOLUMEREQUEST_PUBLISHCONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodePublishVolumeRequest.PublishContextEntry) }) , 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { 'DESCRIPTOR' : _NODEPUBLISHVOLUMEREQUEST_SECRETSENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodePublishVolumeRequest.SecretsEntry) }) , 'VolumeContextEntry' : _reflection.GeneratedProtocolMessageType('VolumeContextEntry', (_message.Message,), { 'DESCRIPTOR' : _NODEPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodePublishVolumeRequest.VolumeContextEntry) }) , 'DESCRIPTOR' : _NODEPUBLISHVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodePublishVolumeRequest) }) _sym_db.RegisterMessage(NodePublishVolumeRequest) @@ -4857,56 +5214,63 @@ NodePublishVolumeResponse = _reflection.GeneratedProtocolMessageType('NodePublishVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEPUBLISHVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodePublishVolumeResponse) }) _sym_db.RegisterMessage(NodePublishVolumeResponse) NodeUnpublishVolumeRequest = _reflection.GeneratedProtocolMessageType('NodeUnpublishVolumeRequest', (_message.Message,), { 'DESCRIPTOR' : _NODEUNPUBLISHVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeUnpublishVolumeRequest) }) _sym_db.RegisterMessage(NodeUnpublishVolumeRequest) NodeUnpublishVolumeResponse = _reflection.GeneratedProtocolMessageType('NodeUnpublishVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEUNPUBLISHVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeUnpublishVolumeResponse) }) _sym_db.RegisterMessage(NodeUnpublishVolumeResponse) NodeGetVolumeStatsRequest = _reflection.GeneratedProtocolMessageType('NodeGetVolumeStatsRequest', (_message.Message,), { 'DESCRIPTOR' : _NODEGETVOLUMESTATSREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetVolumeStatsRequest) }) _sym_db.RegisterMessage(NodeGetVolumeStatsRequest) NodeGetVolumeStatsResponse = _reflection.GeneratedProtocolMessageType('NodeGetVolumeStatsResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEGETVOLUMESTATSRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetVolumeStatsResponse) }) _sym_db.RegisterMessage(NodeGetVolumeStatsResponse) VolumeUsage = _reflection.GeneratedProtocolMessageType('VolumeUsage', (_message.Message,), { 'DESCRIPTOR' : _VOLUMEUSAGE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.VolumeUsage) }) _sym_db.RegisterMessage(VolumeUsage) +VolumeCondition = _reflection.GeneratedProtocolMessageType('VolumeCondition', (_message.Message,), { + 'DESCRIPTOR' : _VOLUMECONDITION, + '__module__' : 'controller.csi_general.csi_pb2' + # @@protoc_insertion_point(class_scope:csi.v1.VolumeCondition) + }) +_sym_db.RegisterMessage(VolumeCondition) + NodeGetCapabilitiesRequest = _reflection.GeneratedProtocolMessageType('NodeGetCapabilitiesRequest', (_message.Message,), { 'DESCRIPTOR' : _NODEGETCAPABILITIESREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetCapabilitiesRequest) }) _sym_db.RegisterMessage(NodeGetCapabilitiesRequest) NodeGetCapabilitiesResponse = _reflection.GeneratedProtocolMessageType('NodeGetCapabilitiesResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEGETCAPABILITIESRESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetCapabilitiesResponse) }) _sym_db.RegisterMessage(NodeGetCapabilitiesResponse) @@ -4915,12 +5279,12 @@ 'RPC' : _reflection.GeneratedProtocolMessageType('RPC', (_message.Message,), { 'DESCRIPTOR' : _NODESERVICECAPABILITY_RPC, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeServiceCapability.RPC) }) , 'DESCRIPTOR' : _NODESERVICECAPABILITY, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeServiceCapability) }) _sym_db.RegisterMessage(NodeServiceCapability) @@ -4928,39 +5292,56 @@ NodeGetInfoRequest = _reflection.GeneratedProtocolMessageType('NodeGetInfoRequest', (_message.Message,), { 'DESCRIPTOR' : _NODEGETINFOREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetInfoRequest) }) _sym_db.RegisterMessage(NodeGetInfoRequest) NodeGetInfoResponse = _reflection.GeneratedProtocolMessageType('NodeGetInfoResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEGETINFORESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeGetInfoResponse) }) _sym_db.RegisterMessage(NodeGetInfoResponse) NodeExpandVolumeRequest = _reflection.GeneratedProtocolMessageType('NodeExpandVolumeRequest', (_message.Message,), { + + 'SecretsEntry' : _reflection.GeneratedProtocolMessageType('SecretsEntry', (_message.Message,), { + 'DESCRIPTOR' : _NODEEXPANDVOLUMEREQUEST_SECRETSENTRY, + '__module__' : 'controller.csi_general.csi_pb2' + # @@protoc_insertion_point(class_scope:csi.v1.NodeExpandVolumeRequest.SecretsEntry) + }) + , 'DESCRIPTOR' : _NODEEXPANDVOLUMEREQUEST, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeExpandVolumeRequest) }) _sym_db.RegisterMessage(NodeExpandVolumeRequest) +_sym_db.RegisterMessage(NodeExpandVolumeRequest.SecretsEntry) NodeExpandVolumeResponse = _reflection.GeneratedProtocolMessageType('NodeExpandVolumeResponse', (_message.Message,), { 'DESCRIPTOR' : _NODEEXPANDVOLUMERESPONSE, - '__module__' : 'csi_pb2' + '__module__' : 'controller.csi_general.csi_pb2' # @@protoc_insertion_point(class_scope:csi.v1.NodeExpandVolumeResponse) }) _sym_db.RegisterMessage(NodeExpandVolumeResponse) +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(alpha_enum) +google_dot_protobuf_dot_descriptor__pb2.EnumValueOptions.RegisterExtension(alpha_enum_value) google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(csi_secret) +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(alpha_field) +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(alpha_message) +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(alpha_method) +google_dot_protobuf_dot_descriptor__pb2.ServiceOptions.RegisterExtension(alpha_service) DESCRIPTOR._options = None _GETPLUGININFORESPONSE_MANIFESTENTRY._options = None _CREATEVOLUMEREQUEST_PARAMETERSENTRY._options = None _CREATEVOLUMEREQUEST_SECRETSENTRY._options = None _CREATEVOLUMEREQUEST.fields_by_name['secrets']._options = None +_VOLUMECAPABILITY_MOUNTVOLUME.fields_by_name['volume_mount_group']._options = None +_VOLUMECAPABILITY_ACCESSMODE_MODE.values_by_name["SINGLE_NODE_SINGLE_WRITER"]._options = None +_VOLUMECAPABILITY_ACCESSMODE_MODE.values_by_name["SINGLE_NODE_MULTI_WRITER"]._options = None _VOLUME_VOLUMECONTEXTENTRY._options = None _TOPOLOGY_SEGMENTSENTRY._options = None _DELETEVOLUMEREQUEST_SECRETSENTRY._options = None @@ -4977,7 +5358,15 @@ _VALIDATEVOLUMECAPABILITIESREQUEST.fields_by_name['secrets']._options = None _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_VOLUMECONTEXTENTRY._options = None _VALIDATEVOLUMECAPABILITIESRESPONSE_CONFIRMED_PARAMETERSENTRY._options = None +_LISTVOLUMESRESPONSE_VOLUMESTATUS.fields_by_name['volume_condition']._options = None +_CONTROLLERGETVOLUMEREQUEST._options = None +_CONTROLLERGETVOLUMERESPONSE._options = None _GETCAPACITYREQUEST_PARAMETERSENTRY._options = None +_GETCAPACITYRESPONSE.fields_by_name['maximum_volume_size']._options = None +_GETCAPACITYRESPONSE.fields_by_name['minimum_volume_size']._options = None +_CONTROLLERSERVICECAPABILITY_RPC_TYPE.values_by_name["VOLUME_CONDITION"]._options = None +_CONTROLLERSERVICECAPABILITY_RPC_TYPE.values_by_name["GET_VOLUME"]._options = None +_CONTROLLERSERVICECAPABILITY_RPC_TYPE.values_by_name["SINGLE_NODE_MULTI_WRITER"]._options = None _CREATESNAPSHOTREQUEST_SECRETSENTRY._options = None _CREATESNAPSHOTREQUEST_PARAMETERSENTRY._options = None _CREATESNAPSHOTREQUEST.fields_by_name['secrets']._options = None @@ -4995,6 +5384,13 @@ _NODEPUBLISHVOLUMEREQUEST_SECRETSENTRY._options = None _NODEPUBLISHVOLUMEREQUEST_VOLUMECONTEXTENTRY._options = None _NODEPUBLISHVOLUMEREQUEST.fields_by_name['secrets']._options = None +_NODEGETVOLUMESTATSRESPONSE.fields_by_name['volume_condition']._options = None +_VOLUMECONDITION._options = None +_NODESERVICECAPABILITY_RPC_TYPE.values_by_name["VOLUME_CONDITION"]._options = None +_NODESERVICECAPABILITY_RPC_TYPE.values_by_name["SINGLE_NODE_MULTI_WRITER"]._options = None +_NODESERVICECAPABILITY_RPC_TYPE.values_by_name["VOLUME_MOUNT_GROUP"]._options = None +_NODEEXPANDVOLUMEREQUEST_SECRETSENTRY._options = None +_NODEEXPANDVOLUMEREQUEST.fields_by_name['secrets']._options = None _IDENTITY = _descriptor.ServiceDescriptor( name='Identity', @@ -5003,8 +5399,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=9702, - serialized_end=9952, + serialized_start=10705, + serialized_end=10955, methods=[ _descriptor.MethodDescriptor( name='GetPluginInfo', @@ -5049,8 +5445,8 @@ index=1, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=9955, - serialized_end=11083, + serialized_start=10958, + serialized_end=12187, methods=[ _descriptor.MethodDescriptor( name='CreateVolume', @@ -5172,6 +5568,16 @@ serialized_options=None, create_key=_descriptor._internal_create_key, ), + _descriptor.MethodDescriptor( + name='ControllerGetVolume', + full_name='csi.v1.Controller.ControllerGetVolume', + index=12, + containing_service=None, + input_type=_CONTROLLERGETVOLUMEREQUEST, + output_type=_CONTROLLERGETVOLUMERESPONSE, + serialized_options=b'\240B\001', + create_key=_descriptor._internal_create_key, + ), ]) _sym_db.RegisterServiceDescriptor(_CONTROLLER) @@ -5185,8 +5591,8 @@ index=2, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=11086, - serialized_end=11816, + serialized_start=12190, + serialized_end=12920, methods=[ _descriptor.MethodDescriptor( name='NodeStageVolume', diff --git a/controller/csi_general/csi_pb2_grpc.py b/controller/csi_general/csi_pb2_grpc.py index bd6a036f6..9f4de3f67 100644 --- a/controller/csi_general/csi_pb2_grpc.py +++ b/controller/csi_general/csi_pb2_grpc.py @@ -2,7 +2,7 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -import controller.csi_general.csi_pb2 as csi__pb2 +from controller.csi_general import csi_pb2 as controller_dot_csi__general_dot_csi__pb2 class IdentityStub(object): @@ -16,18 +16,18 @@ def __init__(self, channel): """ self.GetPluginInfo = channel.unary_unary( '/csi.v1.Identity/GetPluginInfo', - request_serializer=csi__pb2.GetPluginInfoRequest.SerializeToString, - response_deserializer=csi__pb2.GetPluginInfoResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.GetPluginInfoRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.GetPluginInfoResponse.FromString, ) self.GetPluginCapabilities = channel.unary_unary( '/csi.v1.Identity/GetPluginCapabilities', - request_serializer=csi__pb2.GetPluginCapabilitiesRequest.SerializeToString, - response_deserializer=csi__pb2.GetPluginCapabilitiesResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesResponse.FromString, ) self.Probe = channel.unary_unary( '/csi.v1.Identity/Probe', - request_serializer=csi__pb2.ProbeRequest.SerializeToString, - response_deserializer=csi__pb2.ProbeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ProbeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ProbeResponse.FromString, ) @@ -57,18 +57,18 @@ def add_IdentityServicer_to_server(servicer, server): rpc_method_handlers = { 'GetPluginInfo': grpc.unary_unary_rpc_method_handler( servicer.GetPluginInfo, - request_deserializer=csi__pb2.GetPluginInfoRequest.FromString, - response_serializer=csi__pb2.GetPluginInfoResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.GetPluginInfoRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.GetPluginInfoResponse.SerializeToString, ), 'GetPluginCapabilities': grpc.unary_unary_rpc_method_handler( servicer.GetPluginCapabilities, - request_deserializer=csi__pb2.GetPluginCapabilitiesRequest.FromString, - response_serializer=csi__pb2.GetPluginCapabilitiesResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesResponse.SerializeToString, ), 'Probe': grpc.unary_unary_rpc_method_handler( servicer.Probe, - request_deserializer=csi__pb2.ProbeRequest.FromString, - response_serializer=csi__pb2.ProbeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ProbeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ProbeResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -86,15 +86,16 @@ def GetPluginInfo(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Identity/GetPluginInfo', - csi__pb2.GetPluginInfoRequest.SerializeToString, - csi__pb2.GetPluginInfoResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.GetPluginInfoRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.GetPluginInfoResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def GetPluginCapabilities(request, @@ -102,15 +103,16 @@ def GetPluginCapabilities(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Identity/GetPluginCapabilities', - csi__pb2.GetPluginCapabilitiesRequest.SerializeToString, - csi__pb2.GetPluginCapabilitiesResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.GetPluginCapabilitiesResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def Probe(request, @@ -118,15 +120,16 @@ def Probe(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Identity/Probe', - csi__pb2.ProbeRequest.SerializeToString, - csi__pb2.ProbeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ProbeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ProbeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) class ControllerStub(object): @@ -140,63 +143,68 @@ def __init__(self, channel): """ self.CreateVolume = channel.unary_unary( '/csi.v1.Controller/CreateVolume', - request_serializer=csi__pb2.CreateVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.CreateVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.CreateVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.CreateVolumeResponse.FromString, ) self.DeleteVolume = channel.unary_unary( '/csi.v1.Controller/DeleteVolume', - request_serializer=csi__pb2.DeleteVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.DeleteVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.DeleteVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.DeleteVolumeResponse.FromString, ) self.ControllerPublishVolume = channel.unary_unary( '/csi.v1.Controller/ControllerPublishVolume', - request_serializer=csi__pb2.ControllerPublishVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.ControllerPublishVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeResponse.FromString, ) self.ControllerUnpublishVolume = channel.unary_unary( '/csi.v1.Controller/ControllerUnpublishVolume', - request_serializer=csi__pb2.ControllerUnpublishVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.ControllerUnpublishVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeResponse.FromString, ) self.ValidateVolumeCapabilities = channel.unary_unary( '/csi.v1.Controller/ValidateVolumeCapabilities', - request_serializer=csi__pb2.ValidateVolumeCapabilitiesRequest.SerializeToString, - response_deserializer=csi__pb2.ValidateVolumeCapabilitiesResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesResponse.FromString, ) self.ListVolumes = channel.unary_unary( '/csi.v1.Controller/ListVolumes', - request_serializer=csi__pb2.ListVolumesRequest.SerializeToString, - response_deserializer=csi__pb2.ListVolumesResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ListVolumesRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ListVolumesResponse.FromString, ) self.GetCapacity = channel.unary_unary( '/csi.v1.Controller/GetCapacity', - request_serializer=csi__pb2.GetCapacityRequest.SerializeToString, - response_deserializer=csi__pb2.GetCapacityResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.GetCapacityRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.GetCapacityResponse.FromString, ) self.ControllerGetCapabilities = channel.unary_unary( '/csi.v1.Controller/ControllerGetCapabilities', - request_serializer=csi__pb2.ControllerGetCapabilitiesRequest.SerializeToString, - response_deserializer=csi__pb2.ControllerGetCapabilitiesResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesResponse.FromString, ) self.CreateSnapshot = channel.unary_unary( '/csi.v1.Controller/CreateSnapshot', - request_serializer=csi__pb2.CreateSnapshotRequest.SerializeToString, - response_deserializer=csi__pb2.CreateSnapshotResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.CreateSnapshotRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.CreateSnapshotResponse.FromString, ) self.DeleteSnapshot = channel.unary_unary( '/csi.v1.Controller/DeleteSnapshot', - request_serializer=csi__pb2.DeleteSnapshotRequest.SerializeToString, - response_deserializer=csi__pb2.DeleteSnapshotResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotResponse.FromString, ) self.ListSnapshots = channel.unary_unary( '/csi.v1.Controller/ListSnapshots', - request_serializer=csi__pb2.ListSnapshotsRequest.SerializeToString, - response_deserializer=csi__pb2.ListSnapshotsResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ListSnapshotsRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ListSnapshotsResponse.FromString, ) self.ControllerExpandVolume = channel.unary_unary( '/csi.v1.Controller/ControllerExpandVolume', - request_serializer=csi__pb2.ControllerExpandVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.ControllerExpandVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeResponse.FromString, + ) + self.ControllerGetVolume = channel.unary_unary( + '/csi.v1.Controller/ControllerGetVolume', + request_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeResponse.FromString, ) @@ -275,68 +283,79 @@ def ControllerExpandVolume(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def ControllerGetVolume(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_ControllerServicer_to_server(servicer, server): rpc_method_handlers = { 'CreateVolume': grpc.unary_unary_rpc_method_handler( servicer.CreateVolume, - request_deserializer=csi__pb2.CreateVolumeRequest.FromString, - response_serializer=csi__pb2.CreateVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.CreateVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.CreateVolumeResponse.SerializeToString, ), 'DeleteVolume': grpc.unary_unary_rpc_method_handler( servicer.DeleteVolume, - request_deserializer=csi__pb2.DeleteVolumeRequest.FromString, - response_serializer=csi__pb2.DeleteVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.DeleteVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.DeleteVolumeResponse.SerializeToString, ), 'ControllerPublishVolume': grpc.unary_unary_rpc_method_handler( servicer.ControllerPublishVolume, - request_deserializer=csi__pb2.ControllerPublishVolumeRequest.FromString, - response_serializer=csi__pb2.ControllerPublishVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeResponse.SerializeToString, ), 'ControllerUnpublishVolume': grpc.unary_unary_rpc_method_handler( servicer.ControllerUnpublishVolume, - request_deserializer=csi__pb2.ControllerUnpublishVolumeRequest.FromString, - response_serializer=csi__pb2.ControllerUnpublishVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeResponse.SerializeToString, ), 'ValidateVolumeCapabilities': grpc.unary_unary_rpc_method_handler( servicer.ValidateVolumeCapabilities, - request_deserializer=csi__pb2.ValidateVolumeCapabilitiesRequest.FromString, - response_serializer=csi__pb2.ValidateVolumeCapabilitiesResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesResponse.SerializeToString, ), 'ListVolumes': grpc.unary_unary_rpc_method_handler( servicer.ListVolumes, - request_deserializer=csi__pb2.ListVolumesRequest.FromString, - response_serializer=csi__pb2.ListVolumesResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ListVolumesRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ListVolumesResponse.SerializeToString, ), 'GetCapacity': grpc.unary_unary_rpc_method_handler( servicer.GetCapacity, - request_deserializer=csi__pb2.GetCapacityRequest.FromString, - response_serializer=csi__pb2.GetCapacityResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.GetCapacityRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.GetCapacityResponse.SerializeToString, ), 'ControllerGetCapabilities': grpc.unary_unary_rpc_method_handler( servicer.ControllerGetCapabilities, - request_deserializer=csi__pb2.ControllerGetCapabilitiesRequest.FromString, - response_serializer=csi__pb2.ControllerGetCapabilitiesResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesResponse.SerializeToString, ), 'CreateSnapshot': grpc.unary_unary_rpc_method_handler( servicer.CreateSnapshot, - request_deserializer=csi__pb2.CreateSnapshotRequest.FromString, - response_serializer=csi__pb2.CreateSnapshotResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.CreateSnapshotRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.CreateSnapshotResponse.SerializeToString, ), 'DeleteSnapshot': grpc.unary_unary_rpc_method_handler( servicer.DeleteSnapshot, - request_deserializer=csi__pb2.DeleteSnapshotRequest.FromString, - response_serializer=csi__pb2.DeleteSnapshotResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotResponse.SerializeToString, ), 'ListSnapshots': grpc.unary_unary_rpc_method_handler( servicer.ListSnapshots, - request_deserializer=csi__pb2.ListSnapshotsRequest.FromString, - response_serializer=csi__pb2.ListSnapshotsResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ListSnapshotsRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ListSnapshotsResponse.SerializeToString, ), 'ControllerExpandVolume': grpc.unary_unary_rpc_method_handler( servicer.ControllerExpandVolume, - request_deserializer=csi__pb2.ControllerExpandVolumeRequest.FromString, - response_serializer=csi__pb2.ControllerExpandVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeResponse.SerializeToString, + ), + 'ControllerGetVolume': grpc.unary_unary_rpc_method_handler( + servicer.ControllerGetVolume, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -354,15 +373,16 @@ def CreateVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/CreateVolume', - csi__pb2.CreateVolumeRequest.SerializeToString, - csi__pb2.CreateVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.CreateVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.CreateVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def DeleteVolume(request, @@ -370,15 +390,16 @@ def DeleteVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/DeleteVolume', - csi__pb2.DeleteVolumeRequest.SerializeToString, - csi__pb2.DeleteVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.DeleteVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.DeleteVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ControllerPublishVolume(request, @@ -386,15 +407,16 @@ def ControllerPublishVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ControllerPublishVolume', - csi__pb2.ControllerPublishVolumeRequest.SerializeToString, - csi__pb2.ControllerPublishVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ControllerPublishVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ControllerUnpublishVolume(request, @@ -402,15 +424,16 @@ def ControllerUnpublishVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ControllerUnpublishVolume', - csi__pb2.ControllerUnpublishVolumeRequest.SerializeToString, - csi__pb2.ControllerUnpublishVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ControllerUnpublishVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ValidateVolumeCapabilities(request, @@ -418,15 +441,16 @@ def ValidateVolumeCapabilities(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ValidateVolumeCapabilities', - csi__pb2.ValidateVolumeCapabilitiesRequest.SerializeToString, - csi__pb2.ValidateVolumeCapabilitiesResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ValidateVolumeCapabilitiesResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ListVolumes(request, @@ -434,15 +458,16 @@ def ListVolumes(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ListVolumes', - csi__pb2.ListVolumesRequest.SerializeToString, - csi__pb2.ListVolumesResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ListVolumesRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ListVolumesResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def GetCapacity(request, @@ -450,15 +475,16 @@ def GetCapacity(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/GetCapacity', - csi__pb2.GetCapacityRequest.SerializeToString, - csi__pb2.GetCapacityResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.GetCapacityRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.GetCapacityResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ControllerGetCapabilities(request, @@ -466,15 +492,16 @@ def ControllerGetCapabilities(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ControllerGetCapabilities', - csi__pb2.ControllerGetCapabilitiesRequest.SerializeToString, - csi__pb2.ControllerGetCapabilitiesResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ControllerGetCapabilitiesResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def CreateSnapshot(request, @@ -482,15 +509,16 @@ def CreateSnapshot(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/CreateSnapshot', - csi__pb2.CreateSnapshotRequest.SerializeToString, - csi__pb2.CreateSnapshotResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.CreateSnapshotRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.CreateSnapshotResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def DeleteSnapshot(request, @@ -498,15 +526,16 @@ def DeleteSnapshot(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/DeleteSnapshot', - csi__pb2.DeleteSnapshotRequest.SerializeToString, - csi__pb2.DeleteSnapshotResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.DeleteSnapshotResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ListSnapshots(request, @@ -514,15 +543,16 @@ def ListSnapshots(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ListSnapshots', - csi__pb2.ListSnapshotsRequest.SerializeToString, - csi__pb2.ListSnapshotsResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ListSnapshotsRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ListSnapshotsResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def ControllerExpandVolume(request, @@ -530,15 +560,33 @@ def ControllerExpandVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ControllerExpandVolume', - csi__pb2.ControllerExpandVolumeRequest.SerializeToString, - csi__pb2.ControllerExpandVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ControllerExpandVolumeResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def ControllerGetVolume(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/csi.v1.Controller/ControllerGetVolume', + controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.ControllerGetVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) class NodeStub(object): @@ -552,43 +600,43 @@ def __init__(self, channel): """ self.NodeStageVolume = channel.unary_unary( '/csi.v1.Node/NodeStageVolume', - request_serializer=csi__pb2.NodeStageVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.NodeStageVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeResponse.FromString, ) self.NodeUnstageVolume = channel.unary_unary( '/csi.v1.Node/NodeUnstageVolume', - request_serializer=csi__pb2.NodeUnstageVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.NodeUnstageVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeResponse.FromString, ) self.NodePublishVolume = channel.unary_unary( '/csi.v1.Node/NodePublishVolume', - request_serializer=csi__pb2.NodePublishVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.NodePublishVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeResponse.FromString, ) self.NodeUnpublishVolume = channel.unary_unary( '/csi.v1.Node/NodeUnpublishVolume', - request_serializer=csi__pb2.NodeUnpublishVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.NodeUnpublishVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeResponse.FromString, ) self.NodeGetVolumeStats = channel.unary_unary( '/csi.v1.Node/NodeGetVolumeStats', - request_serializer=csi__pb2.NodeGetVolumeStatsRequest.SerializeToString, - response_deserializer=csi__pb2.NodeGetVolumeStatsResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsResponse.FromString, ) self.NodeExpandVolume = channel.unary_unary( '/csi.v1.Node/NodeExpandVolume', - request_serializer=csi__pb2.NodeExpandVolumeRequest.SerializeToString, - response_deserializer=csi__pb2.NodeExpandVolumeResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeResponse.FromString, ) self.NodeGetCapabilities = channel.unary_unary( '/csi.v1.Node/NodeGetCapabilities', - request_serializer=csi__pb2.NodeGetCapabilitiesRequest.SerializeToString, - response_deserializer=csi__pb2.NodeGetCapabilitiesResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesResponse.FromString, ) self.NodeGetInfo = channel.unary_unary( '/csi.v1.Node/NodeGetInfo', - request_serializer=csi__pb2.NodeGetInfoRequest.SerializeToString, - response_deserializer=csi__pb2.NodeGetInfoResponse.FromString, + request_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetInfoRequest.SerializeToString, + response_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetInfoResponse.FromString, ) @@ -648,43 +696,43 @@ def add_NodeServicer_to_server(servicer, server): rpc_method_handlers = { 'NodeStageVolume': grpc.unary_unary_rpc_method_handler( servicer.NodeStageVolume, - request_deserializer=csi__pb2.NodeStageVolumeRequest.FromString, - response_serializer=csi__pb2.NodeStageVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeResponse.SerializeToString, ), 'NodeUnstageVolume': grpc.unary_unary_rpc_method_handler( servicer.NodeUnstageVolume, - request_deserializer=csi__pb2.NodeUnstageVolumeRequest.FromString, - response_serializer=csi__pb2.NodeUnstageVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeResponse.SerializeToString, ), 'NodePublishVolume': grpc.unary_unary_rpc_method_handler( servicer.NodePublishVolume, - request_deserializer=csi__pb2.NodePublishVolumeRequest.FromString, - response_serializer=csi__pb2.NodePublishVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeResponse.SerializeToString, ), 'NodeUnpublishVolume': grpc.unary_unary_rpc_method_handler( servicer.NodeUnpublishVolume, - request_deserializer=csi__pb2.NodeUnpublishVolumeRequest.FromString, - response_serializer=csi__pb2.NodeUnpublishVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeResponse.SerializeToString, ), 'NodeGetVolumeStats': grpc.unary_unary_rpc_method_handler( servicer.NodeGetVolumeStats, - request_deserializer=csi__pb2.NodeGetVolumeStatsRequest.FromString, - response_serializer=csi__pb2.NodeGetVolumeStatsResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsResponse.SerializeToString, ), 'NodeExpandVolume': grpc.unary_unary_rpc_method_handler( servicer.NodeExpandVolume, - request_deserializer=csi__pb2.NodeExpandVolumeRequest.FromString, - response_serializer=csi__pb2.NodeExpandVolumeResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeResponse.SerializeToString, ), 'NodeGetCapabilities': grpc.unary_unary_rpc_method_handler( servicer.NodeGetCapabilities, - request_deserializer=csi__pb2.NodeGetCapabilitiesRequest.FromString, - response_serializer=csi__pb2.NodeGetCapabilitiesResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesResponse.SerializeToString, ), 'NodeGetInfo': grpc.unary_unary_rpc_method_handler( servicer.NodeGetInfo, - request_deserializer=csi__pb2.NodeGetInfoRequest.FromString, - response_serializer=csi__pb2.NodeGetInfoResponse.SerializeToString, + request_deserializer=controller_dot_csi__general_dot_csi__pb2.NodeGetInfoRequest.FromString, + response_serializer=controller_dot_csi__general_dot_csi__pb2.NodeGetInfoResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -702,15 +750,16 @@ def NodeStageVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeStageVolume', - csi__pb2.NodeStageVolumeRequest.SerializeToString, - csi__pb2.NodeStageVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeStageVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeUnstageVolume(request, @@ -718,15 +767,16 @@ def NodeUnstageVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeUnstageVolume', - csi__pb2.NodeUnstageVolumeRequest.SerializeToString, - csi__pb2.NodeUnstageVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeUnstageVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodePublishVolume(request, @@ -734,15 +784,16 @@ def NodePublishVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodePublishVolume', - csi__pb2.NodePublishVolumeRequest.SerializeToString, - csi__pb2.NodePublishVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodePublishVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeUnpublishVolume(request, @@ -750,15 +801,16 @@ def NodeUnpublishVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeUnpublishVolume', - csi__pb2.NodeUnpublishVolumeRequest.SerializeToString, - csi__pb2.NodeUnpublishVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeUnpublishVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeGetVolumeStats(request, @@ -766,15 +818,16 @@ def NodeGetVolumeStats(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeGetVolumeStats', - csi__pb2.NodeGetVolumeStatsRequest.SerializeToString, - csi__pb2.NodeGetVolumeStatsResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeGetVolumeStatsResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeExpandVolume(request, @@ -782,15 +835,16 @@ def NodeExpandVolume(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeExpandVolume', - csi__pb2.NodeExpandVolumeRequest.SerializeToString, - csi__pb2.NodeExpandVolumeResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeExpandVolumeResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeGetCapabilities(request, @@ -798,15 +852,16 @@ def NodeGetCapabilities(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeGetCapabilities', - csi__pb2.NodeGetCapabilitiesRequest.SerializeToString, - csi__pb2.NodeGetCapabilitiesResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeGetCapabilitiesResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) @staticmethod def NodeGetInfo(request, @@ -814,12 +869,13 @@ def NodeGetInfo(request, options=(), channel_credentials=None, call_credentials=None, + insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None): return grpc.experimental.unary_unary(request, target, '/csi.v1.Node/NodeGetInfo', - csi__pb2.NodeGetInfoRequest.SerializeToString, - csi__pb2.NodeGetInfoResponse.FromString, + controller_dot_csi__general_dot_csi__pb2.NodeGetInfoRequest.SerializeToString, + controller_dot_csi__general_dot_csi__pb2.NodeGetInfoResponse.FromString, options, channel_credentials, - call_credentials, compression, wait_for_ready, timeout, metadata) + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/controller/requirements.txt b/controller/requirements.txt index 990aa3ef2..a166d396c 100644 --- a/controller/requirements.txt +++ b/controller/requirements.txt @@ -1,5 +1,5 @@ -grpcio==1.20.1 -grpcio-tools==1.20.1 +grpcio==1.41.1 +grpcio-tools==1.41.1 protobuf==3.13.0 pyyaml==5.4 munch==2.3.2 diff --git a/controller/scripts/csi_pb2.sh b/controller/scripts/csi_pb2.sh index cb0026121..fa878d82f 100644 --- a/controller/scripts/csi_pb2.sh +++ b/controller/scripts/csi_pb2.sh @@ -1,7 +1,7 @@ #!/bin/bash -e set -x -CSI_VERSION="v1.2.0" +CSI_VERSION="v1.5.0" ADDONS_VERSION="v0.1.1" PB2_DIR="controller/csi_general" diff --git a/controller/tests/array_action/ds8k/test_array_mediator_ds8k.py b/controller/tests/array_action/ds8k/test_array_mediator_ds8k.py index 432cf07f7..6ee1c07dd 100644 --- a/controller/tests/array_action/ds8k/test_array_mediator_ds8k.py +++ b/controller/tests/array_action/ds8k/test_array_mediator_ds8k.py @@ -303,28 +303,29 @@ def test_get_volume_mappings(self): def test_map_volume_host_not_found(self): self.client_mock.map_volume_to_host.side_effect = NotFound("404") with self.assertRaises(array_errors.HostNotFoundError): - self.array.map_volume("fake_name", "fake_host") + self.array.map_volume("fake_name", "fake_host", "fake_connectivity_type") def test_map_volume_volume_not_found(self): self.client_mock.map_volume_to_host.side_effect = ClientException("500", "[BE586015]") with self.assertRaises(array_errors.ObjectNotFoundError): - self.array.map_volume("fake_name", "fake_host") + self.array.map_volume("fake_name", "fake_host", "fake_connectivity_type") def test_map_volume_no_available_lun(self): self.client_mock.map_volume_to_host.side_effect = InternalServerError("500", "[BE74121B]") with self.assertRaises(array_errors.NoAvailableLunError): - self.array.map_volume("fake_name", "fake_host") + self.array.map_volume("fake_name", "fake_host", "fake_connectivity_type") def test_map_volume_fail_with_ClientException(self): self.client_mock.map_volume_to_host.side_effect = ClientException("500") with self.assertRaises(array_errors.MappingError): - self.array.map_volume("fake_name", "fake_host") + self.array.map_volume("fake_name", "fake_host", "fake_connectivity_type") def test_map_volume(self): scsi_id = "6005076306FFD3010000000000000001" host_name = "test_name" + connectivity_type = "fake_connectivity_type" self.client_mock.map_volume_to_host.return_value = Munch({"lunid": "01"}) - lun = self.array.map_volume(scsi_id, host_name) + lun = self.array.map_volume(scsi_id, host_name, connectivity_type) self.assertEqual(lun, 1) self.client_mock.map_volume_to_host.assert_called_once_with(host_name, scsi_id[-4:]) @@ -416,7 +417,7 @@ def test_get_host_by_identifiers(self): }) ] host, connectivity_type = self.array.get_host_by_host_identifiers( - Initiators('', [wwpn1, wwpn2]) + Initiators('', [wwpn1, wwpn2], '') ) self.assertEqual(host, host_name) self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_type) @@ -432,7 +433,7 @@ def test_get_host_by_identifiers_partial_match(self): }) ] host, connectivity_type = self.array.get_host_by_host_identifiers( - Initiators('', [wwpn1, "another_wwpn"]) + Initiators('', [wwpn1, "another_wwpn"], '') ) self.assertEqual(host, host_name) self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_type) @@ -449,7 +450,7 @@ def test_get_host_by_identifiers_not_found(self): ] with self.assertRaises(array_errors.HostNotFoundError): self.array.get_host_by_host_identifiers( - Initiators('', ["new_wwpn", "another_wwpn"]) + Initiators('', ["new_wwpn", "another_wwpn"], '') ) def test_get_snapshot_not_exist_return_none(self): diff --git a/controller/tests/array_action/svc/array_mediator_svc_test.py b/controller/tests/array_action/svc/array_mediator_svc_test.py index ee8f56a86..af32ffa2f 100644 --- a/controller/tests/array_action/svc/array_mediator_svc_test.py +++ b/controller/tests/array_action/svc/array_mediator_svc_test.py @@ -8,7 +8,8 @@ import controller.array_action.config as config import controller.array_action.errors as array_errors from controller.array_action.array_mediator_svc import SVCArrayMediator, build_kwargs_from_parameters, \ - HOST_ID_PARAM, HOST_NAME_PARAM, HOST_ISCSI_NAMES_PARAM, HOST_WWPNS_PARAM, FCMAP_STATUS_DONE, YES, HOST_PORTSET_ID + HOST_ID_PARAM, HOST_NAME_PARAM, HOST_NQN_PARAM, HOST_WWPNS_PARAM, HOST_ISCSI_NAMES_PARAM, FCMAP_STATUS_DONE, YES, \ + HOST_PORTSET_ID from controller.array_action.svc_cli_result_reader import SVCListResultsElement from controller.common.node_info import Initiators @@ -22,6 +23,7 @@ def setUp(self): with patch("controller.array_action.array_mediator_svc.SVCArrayMediator._connect"): self.svc = SVCArrayMediator("user", "password", self.endpoint) self.svc.client = Mock() + self.svc.client.svcinfo.lssystem.return_value = [Munch({'location': 'local', 'id_alias': 'fake_identifier'})] node = Munch({'id': '1', 'name': 'node1', 'iscsi_name': 'iqn.1986-03.com.ibm:2145.v7k1.node1', 'status': 'online'}) self.svc.client.svcinfo.lsnode.return_value = [node] @@ -102,6 +104,15 @@ def test_get_volume_return_correct_value(self): self.assertEqual(volume.pool, 'pool_name') self.assertEqual(volume.array_type, 'SVC') + def test_get_volume_hyperswap_has_no_source(self): + target_cli_volume = self._get_mapped_target_cli_volume() + self.svc.client.svcinfo.lsvdisk.return_value = self._mock_cli_object(target_cli_volume) + self._prepare_fcmaps_for_hyperswap() + + volume = self.svc.get_volume("volume_name") + + self.assertIsNone(volume.copy_source_id) + def test_get_volume_raise_exception(self): self._test_mediator_method_client_error(self.svc.get_volume, ("volume",), self.svc.client.svcinfo.lsvdisk, Exception, Exception) @@ -151,7 +162,17 @@ def test_create_volume_with_compressed_space_efficiency_success(self): self.svc.client.svctask.mkvolume.assert_called_with(name="test_volume", unit="b", size=1024, pool="pool_name", compressed=True) - def test_create_volume_with_deduplicated_space_efficiency_success(self): + def test_create_volume_with_deduplicated_thin_space_efficiency_success(self): + self._test_create_volume_success(config.SPACE_EFFICIENCY_DEDUPLICATED_THIN) + self.svc.client.svctask.mkvolume.assert_called_with(name="test_volume", unit="b", size=1024, pool="pool_name", + thin=True, deduplicated=True) + + def test_create_volume_with_deduplicated_compressed_space_efficiency_success(self): + self._test_create_volume_success(config.SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED) + self.svc.client.svctask.mkvolume.assert_called_with(name="test_volume", unit="b", size=1024, pool="pool_name", + compressed=True, deduplicated=True) + + def test_create_volume_with_deduplicated_backward_compatibility_space_efficiency_success(self): self._test_create_volume_success(config.SPACE_EFFICIENCY_DEDUPLICATED) self.svc.client.svctask.mkvolume.assert_called_with(name="test_volume", unit="b", size=1024, pool="pool_name", compressed=True, deduplicated=True) @@ -206,11 +227,10 @@ def _prepare_fcmaps_for_hyperswap(self): fcmaps_as_target = Mock(as_list=self.fcmaps_as_target) self.fcmaps[0].rc_controlled = "yes" fcmaps_as_source = Mock(as_list=self.fcmaps) - return fcmaps_as_source, fcmaps_as_target + self.svc.client.svcinfo.lsfcmap.side_effect = [fcmaps_as_target, fcmaps_as_source] def test_delete_volume_does_not_remove_hyperswap_fcmap(self): - fcmaps_as_source, fcmaps_as_target = self._prepare_fcmaps_for_hyperswap() - self.svc.client.svcinfo.lsfcmap.side_effect = [fcmaps_as_target, fcmaps_as_source] + self._prepare_fcmaps_for_hyperswap() self.svc.delete_volume("volume") self.svc.client.svctask.rmfcmap.assert_not_called() @@ -244,7 +264,7 @@ def test_copy_to_existing_volume_from_source_success(self): @patch("controller.array_action.array_mediator_svc.is_warning_message") def _test_copy_to_existing_volume_raise_errors(self, mock_warning, client_return_value, expected_error): mock_warning.return_value = False - self.svc.client.svcinfo.lsvdisk.side_effect = [client_return_value] + self.svc.client.svcinfo.lsvdisk.side_effect = [client_return_value, client_return_value] with self.assertRaises(expected_error): self.svc.copy_to_existing_volume_from_source("a", "b", 1, 1) @@ -262,8 +282,12 @@ def test_copy_to_existing_volume_raise_illegal_object_id(self): def _mock_cli_object(cli_object): return Mock(as_single_element=cli_object) + @classmethod + def _mock_cli_objects(cls, cli_objects): + return map(cls._mock_cli_object, cli_objects) + @staticmethod - def _get_cli_volume(with_deduplicated_copy=True): + def _get_cli_volume(with_deduplicated_copy=True, name='source_volume', pool_name='pool_name'): se_copy = YES deduplicated_copy = 'no' compressed_copy = 'no' @@ -273,9 +297,9 @@ def _get_cli_volume(with_deduplicated_copy=True): compressed_copy = YES return Munch({'vdisk_UID': 'vol_id', 'id': 'test_id', - 'name': 'source_volume', + 'name': name, 'capacity': '1024', - 'mdisk_grp_name': 'pool_name', + 'mdisk_grp_name': pool_name, 'FC_id': '', 'se_copy': se_copy, 'deduplicated_copy': deduplicated_copy, @@ -395,20 +419,46 @@ def test_get_object_by_id_volume_success(self): volume = self.svc.get_object_by_id("volume_id", "volume") self.assertEqual(volume.name, "volume_id") - def _prepare_mocks_for_create_snapshot(self, support_deduplicated_copy=True, source_has_deduplicated_copy=False): - self.svc.client.svctask.mkvolume.return_value = Mock() - self.svc.client.svctask.mkfcmap.return_value = Mock() - source_vol_to_copy_from = self._get_cli_volume(source_has_deduplicated_copy) + def _get_custom_dedup_cli_volume(self, support_deduplicated_copy, with_deduplicated_copy, name='source_volume', + pool_name='pool_name'): + volume = self._get_cli_volume(with_deduplicated_copy, name=name, pool_name=pool_name) if not support_deduplicated_copy: - del source_vol_to_copy_from.deduplicated_copy - target_vol_after_creation = self._get_mapless_target_cli_volume() - target_vol_after_mapping = self._get_mapped_target_cli_volume() - target_vol_for_rollback = self._get_mapped_target_cli_volume() - vols_to_return = [source_vol_to_copy_from, source_vol_to_copy_from, target_vol_after_creation, - target_vol_after_mapping, target_vol_for_rollback] - return_values = map(self._mock_cli_object, vols_to_return) - self.svc.client.svcinfo.lsvdisk.side_effect = return_values + del volume.deduplicated_copy + return volume + def _prepare_mocks_for_create_snapshot(self, support_deduplicated_copy=True, source_has_deduplicated_copy=False, + different_pool_site=False): + self.svc.client.svctask.mkvolume.return_value = Mock() + self.svc.client.svctask.mkfcmap.return_value = Mock() + source_volume_to_copy_from = self._get_custom_dedup_cli_volume(support_deduplicated_copy, + source_has_deduplicated_copy) + volumes_to_return = [source_volume_to_copy_from, source_volume_to_copy_from] + + if different_pool_site: + pools_to_return = [Munch({'site_name': 'pool_site'}), + Munch({'site_name': 'source_volume_site'}), + Munch({'site_name': 'other_volume_site'}), + Munch({'site_name': 'pool_site'})] + self.svc.client.svcinfo.lsmdiskgrp.side_effect = self._mock_cli_objects(pools_to_return) + + auxiliary_volumes = [self._get_cli_volume(name='other_volume', pool_name='other_volume_pool'), + self._get_custom_dedup_cli_volume(support_deduplicated_copy, + source_has_deduplicated_copy, + name='relevant_volume', + pool_name='relevant_volume_pool')] + volumes_to_return.extend(auxiliary_volumes) + + rcrelationships_to_return = [Munch({'aux_vdisk_name': 'other_volume'}), + Munch({'aux_vdisk_name': 'relevant_volume'})] + self.svc.client.svcinfo.lsrcrelationship.return_value = Mock(as_list=rcrelationships_to_return) + + target_volume_after_creation = self._get_mapless_target_cli_volume() + target_volume_after_mapping = self._get_mapped_target_cli_volume() + target_volume_for_rollback = self._get_mapped_target_cli_volume() + volumes_to_return.extend([target_volume_after_creation, target_volume_after_mapping, + target_volume_for_rollback]) + + self.svc.client.svcinfo.lsvdisk.side_effect = self._mock_cli_objects(volumes_to_return) self.svc.client.svctask.startfcmap.return_value = Mock() @patch("controller.array_action.array_mediator_svc.is_warning_message") @@ -436,7 +486,7 @@ def test_create_snapshot_lsvdisk_cli_failure_errors(self): array_errors.IllegalObjectID) def test_create_snapshot_source_not_found_error(self): - self.svc.client.svcinfo.lsvdisk.side_effect = [Mock(as_single_element=None)] + self.svc.client.svcinfo.lsvdisk.side_effect = [Mock(as_single_element=None), Mock(as_single_element=None)] with self.assertRaises(array_errors.ObjectNotFoundError): self.svc.create_snapshot("source_volume_id", "test_snapshot", space_efficiency=None, pool="pool1") @@ -476,6 +526,13 @@ def test_create_snapshot_with_different_pool_success(self): self.svc.client.svctask.mkvolume.assert_called_once_with(name='test_snapshot', unit='b', size=1024, pool='different_pool', thin=True) + def test_create_snapshot_with_different_site_success(self): + self._prepare_mocks_for_create_snapshot(different_pool_site=True) + + self.svc.create_snapshot("source_volume_id", "test_snapshot", space_efficiency=None, pool="different_pool") + self.svc.client.svctask.mkfcmap.assert_called_once_with(source="relevant_volume", target="test_snapshot", + copyrate=0) + def test_create_snapshot_with_specified_source_volume_space_efficiency_success(self): self._prepare_mocks_for_create_snapshot(source_has_deduplicated_copy=True) @@ -521,8 +578,7 @@ def test_delete_snapshot_call_rmfcmap(self): def test_delete_snapshot_does_not_remove_hyperswap_fcmap(self): self._prepare_mocks_for_delete_snapshot() - fcmaps_as_source, fcmaps_as_target = self._prepare_fcmaps_for_hyperswap() - self.svc.client.svcinfo.lsfcmap.side_effect = [fcmaps_as_target, fcmaps_as_source] + self._prepare_fcmaps_for_hyperswap() self.svc.delete_snapshot("test_snapshot") self.svc.client.svctask.rmfcmap.assert_not_called() @@ -587,22 +643,28 @@ def test_validate_supported_space_efficiency_success(self): self.svc.validate_supported_space_efficiency(compressed_space_efficiency) deduplicated_space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED self.svc.validate_supported_space_efficiency(deduplicated_space_efficiency) + deduplicated_thin_space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED_THIN + self.svc.validate_supported_space_efficiency(deduplicated_thin_space_efficiency) + deduplicated_compressed_space_efficiency = config.SPACE_EFFICIENCY_DEDUPLICATED_COMPRESSED + self.svc.validate_supported_space_efficiency(deduplicated_compressed_space_efficiency) + + def _test_build_kwargs_from_parameters(self, space_efficiency, pool, name, size, expected_space_efficiency_kwargs): + expected_kwargs = {'name': name, 'unit': 'b', 'size': size, 'pool': pool} + expected_kwargs.update(expected_space_efficiency_kwargs) + actual_kwargs = build_kwargs_from_parameters(space_efficiency, pool, name, size) + self.assertDictEqual(actual_kwargs, expected_kwargs) def test_build_kwargs_from_parameters(self): size = self.svc._convert_size_bytes(1000) - result_a = build_kwargs_from_parameters('Thin', 'P1', 'V1', size) - self.assertDictEqual(result_a, {'name': 'V1', 'unit': 'b', - 'size': 1024, 'pool': 'P1', - 'thin': True}) - result_b = build_kwargs_from_parameters('compressed', 'P2', 'V2', size) - self.assertDictEqual(result_b, {'name': 'V2', 'unit': 'b', - 'size': 1024, 'pool': 'P2', - 'compressed': True}) - result_c = build_kwargs_from_parameters('Deduplicated', 'P3', 'V3', self.svc._convert_size_bytes(2048)) - self.assertDictEqual(result_c, {'name': 'V3', 'unit': 'b', - 'size': 2048, 'pool': 'P3', - 'compressed': True, - 'deduplicated': True}) + + self._test_build_kwargs_from_parameters('Thin', 'P1', 'V1', size, {'thin': True}) + self._test_build_kwargs_from_parameters('compressed', 'P2', 'V2', size, {'compressed': True}) + self._test_build_kwargs_from_parameters('dedup_thin', 'P3', 'V3', self.svc._convert_size_bytes(2048), + {'thin': True, 'deduplicated': True}) + self._test_build_kwargs_from_parameters('dedup_compressed', 'P3', 'V3', self.svc._convert_size_bytes(2048), + {'compressed': True, 'deduplicated': True}) + self._test_build_kwargs_from_parameters('Deduplicated', 'P3', 'V3', self.svc._convert_size_bytes(2048), + {'compressed': True, 'deduplicated': True}) def test_properties(self): self.assertEqual(SVCArrayMediator.port, 22) @@ -612,7 +674,17 @@ def test_properties(self): self.assertEqual(SVCArrayMediator.max_connections, 2) self.assertEqual(SVCArrayMediator.max_lun_retries, 10) - def _prepare_mocks_for_get_host_by_identifiers_(self, result_reader_iter, hosts): + def _prepare_mocks_for_get_host_by_identifiers(self, result_reader_iter, custom_host=None): + host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', nqn_list=['nqn.test.1'], wwpns_list=['wwn1'], + iscsi_names_list=['iqn.test.1']) + host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', nqn_list=['nqn.test.2'], wwpns_list=['wwn2'], + iscsi_names_list=['iqn.test.2']) + if custom_host: + host_3 = custom_host + else: + host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', nqn_list=['nqn.test.3'], + wwpns_list=['wwn3'], iscsi_names_list=['iqn.test.3']) + hosts = [host_1, host_2, host_3] self.svc.client.svcinfo.lshost = Mock() self.svc.client.svcinfo.lshost.return_value = self._get_hosts_list_result(hosts) self.svc.client.send_raw_command = Mock() @@ -621,99 +693,123 @@ def _prepare_mocks_for_get_host_by_identifiers_(self, result_reader_iter, hosts) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_returns_host_not_found(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', ['iqn.test.1'], []) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.2'], []) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.3'], []) - hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) with self.assertRaises(array_errors.HostNotFoundError): - self.svc.get_host_by_host_identifiers(Initiators('Test_iqn', ['Test_wwn'])) + self.svc.get_host_by_host_identifiers(Initiators('Test_nqn', ['Test_wwn'], 'Test_iqn')) def test_get_host_by_identifier_return_host_not_found_when_no_hosts_exist(self): hosts = [] self.svc.client.svcinfo.lshost = Mock() self.svc.client.svcinfo.lshost.return_value = self._get_hosts_list_result(hosts) with self.assertRaises(array_errors.HostNotFoundError): - self.svc.get_host_by_host_identifiers(Initiators('Test_iqn', ['Test_wwn'])) + self.svc.get_host_by_host_identifiers(Initiators('Test_nqn', ['Test_wwn'], 'Test_iqn')) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_raise_multiplehostsfounderror(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', ['iqn.test.1'], []) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.3'], []) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', [], ['Test_wwn']) - hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) with self.assertRaises(array_errors.MultipleHostsFoundError): - self.svc.get_host_by_host_identifiers(Initiators('iqn.test.3', ['Test_wwn'])) + self.svc.get_host_by_host_identifiers(Initiators('Test_nqn', ['wwn2'], 'iqn.test.3')) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_return_iscsi_host(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', [], ['abc1']) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.2'], ['abc3']) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.3'], ['abc3']) - hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) - host, connectivity_type = self.svc.get_host_by_host_identifiers(Initiators( - 'iqn.test.2', ['abcd3'])) - self.assertEqual('test_host_2', host) - self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE], connectivity_type) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['Test_wwn'], 'iqn.test.2')) + self.assertEqual('test_host_2', hostname) + self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE], connectivity_types) + + @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") + def test_get_host_by_identifiers_no_other_ports_return_iscsi_host(self, result_reader_iter): + host_with_iqn = self._get_host_as_dictionary('costume_host_id', 'test_costume_host', + iscsi_names_list=['iqn.test.costume']) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter, custom_host=host_with_iqn) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['Test_wwn'], 'iqn.test.costume')) + self.assertEqual('test_costume_host', hostname) + self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE], connectivity_types) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_return_iscsi_host_with_list_iqn(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', [], ['abc1']) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.2', 'iqn.test.22'], ['abc3']) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.3'], ['abc3']) - hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) - host, connectivity_type = self.svc.get_host_by_host_identifiers(Initiators( - 'iqn.test.2', ['abcd3'])) - self.assertEqual('test_host_2', host) - self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE], connectivity_type) + host_with_iqn_list = self._get_host_as_dictionary('costume_host_id', 'test_costume_host', wwpns_list=['wwns'], + iscsi_names_list=['iqn.test.s1', 'iqn.test.s2']) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter, custom_host=host_with_iqn_list) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['Test_wwn'], 'iqn.test.s1')) + self.assertEqual('test_costume_host', hostname) + self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE], connectivity_types) + + @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") + def test_get_host_by_identifiers_return_nvme_host(self, result_reader_iter): + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('nqn.test.3', ['Test_wwn'], 'iqn.test.6')) + self.assertEqual('test_host_3', hostname) + self.assertEqual([config.NVME_OVER_FC_CONNECTIVITY_TYPE], connectivity_types) + + @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") + def test_get_host_by_identifiers_no_other_ports_return_nvme_host(self, result_reader_iter): + host_with_nqn = self._get_host_as_dictionary('costume_host_id', 'test_costume_host', + nqn_list=['nqn.test.costume']) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter, custom_host=host_with_nqn) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('nqn.test.costume', ['Test_wwn'], 'Test_iqn')) + self.assertEqual('test_costume_host', hostname) + self.assertEqual([config.NVME_OVER_FC_CONNECTIVITY_TYPE], connectivity_types) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_return_fc_host(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', [], ['abc1']) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', [''], ['abc2']) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.3'], ['abc1', 'abc3']) + host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', wwpns_list=['wwn1'], iscsi_names_list=[]) + host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', wwpns_list=['wwn2'], iscsi_names_list=['']) + host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', wwpns_list=['wwn3', 'wwn4'], + iscsi_names_list=['iqn.test.3']) hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) - host, connectivity_type = self.svc.get_host_by_host_identifiers(Initiators( - 'iqn.test.6', ['abc3', 'ABC1'])) - self.assertEqual('test_host_3', host) - self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_type) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['wwn4', 'WWN3'], 'iqn.test.6')) + self.assertEqual('test_host_3', hostname) + self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_types) result_reader_iter.return_value = self._get_detailed_hosts_list_result(hosts) - host, connectivity_type = self.svc.get_host_by_host_identifiers(Initiators( - 'iqn.test.6', ['abc3'])) - self.assertEqual('test_host_3', host) - self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_type) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['wwn3'], 'iqn.test.6')) + self.assertEqual('test_host_3', hostname) + self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_types) + + @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") + def test_get_host_by_identifiers_no_other_ports_return_fc_host(self, result_reader_iter): + host_with_wwpn = self._get_host_as_dictionary('costume_host_id', 'test_costume_host', wwpns_list=['WWNs']) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter, custom_host=host_with_wwpn) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('Test_nqn', ['Test_wwn', 'WWNs'], 'Test_iqn')) + self.assertEqual('test_costume_host', hostname) + self.assertEqual([config.FC_CONNECTIVITY_TYPE], connectivity_types) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") def test_get_host_by_identifiers_with_wrong_fc_iscsi_raise_not_found(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', [], ['abc1']) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.2'], ['abc3']) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.3'], ['abc3']) + host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', wwpns_list=['wwn1'], iscsi_names_list=[]) + host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', wwpns_list=['wwn3'], + iscsi_names_list=['iqn.test.2']) + host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', wwpns_list=['wwn3'], + iscsi_names_list=['iqn.test.3']) hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) with self.assertRaises(array_errors.HostNotFoundError): - self.svc.get_host_by_host_identifiers(Initiators('', [])) + self.svc.get_host_by_host_identifiers(Initiators('Test_nqn', [], '')) result_reader_iter.return_value = self._get_detailed_hosts_list_result(hosts) with self.assertRaises(array_errors.HostNotFoundError): - self.svc.get_host_by_host_identifiers(Initiators('123', ['a', 'b'])) + self.svc.get_host_by_host_identifiers(Initiators('Test_nqn', ['a', 'b'], '123')) @patch("controller.array_action.svc_cli_result_reader.SVCListResultsReader.__iter__") - def test_get_host_by_identifiers_return_iscsi_and_fc_all_support(self, result_reader_iter): - host_1 = self._get_host_as_dictionary('host_id_1', 'test_host_1', [], ['abc1']) - host_2 = self._get_host_as_dictionary('host_id_2', 'test_host_2', ['iqn.test.6'], ['abcd3']) - host_3 = self._get_host_as_dictionary('host_id_3', 'test_host_3', ['iqn.test.2'], ['abc3']) - hosts = [host_1, host_2, host_3] - self._prepare_mocks_for_get_host_by_identifiers_(result_reader_iter, hosts) - host, connectivity_type = self.svc.get_host_by_host_identifiers(Initiators('iqn.test.2', ['ABC3'])) - self.assertEqual('test_host_3', host) - self.assertEqual([config.ISCSI_CONNECTIVITY_TYPE, - config.FC_CONNECTIVITY_TYPE], connectivity_type) - - def _get_host_as_dictionary(self, id, name, iscsi_names_list, wwpns_list, portset_id=None): + def test_get_host_by_identifiers_return_nvme_fc_and_iscsi(self, result_reader_iter): + self._prepare_mocks_for_get_host_by_identifiers(result_reader_iter) + hostname, connectivity_types = self.svc.get_host_by_host_identifiers( + Initiators('nqn.test.2', ['WWN2'], 'iqn.test.2')) + self.assertEqual('test_host_2', hostname) + self.assertEqual( + {config.NVME_OVER_FC_CONNECTIVITY_TYPE, config.FC_CONNECTIVITY_TYPE, config.ISCSI_CONNECTIVITY_TYPE}, + set(connectivity_types)) + + def _get_host_as_dictionary(self, id, name, nqn_list=None, wwpns_list=None, iscsi_names_list=None, portset_id=None): res = {HOST_ID_PARAM: id, HOST_NAME_PARAM: name} if iscsi_names_list: res[HOST_ISCSI_NAMES_PARAM] = iscsi_names_list @@ -721,6 +817,8 @@ def _get_host_as_dictionary(self, id, name, iscsi_names_list, wwpns_list, portse res[HOST_WWPNS_PARAM] = wwpns_list if portset_id: res[HOST_PORTSET_ID] = portset_id + if nqn_list: + res[HOST_NQN_PARAM] = nqn_list return res def _get_hosts_list_result(self, hosts_dict): @@ -732,14 +830,15 @@ def _get_detailed_hosts_list_result(self, hosts_dict): current_element = SVCListResultsElement() current_element.add(HOST_ID_PARAM, host_dict.get(HOST_ID_PARAM)) current_element.add(HOST_NAME_PARAM, host_dict.get(HOST_NAME_PARAM)) - iscsi_names_list = host_dict.get(HOST_ISCSI_NAMES_PARAM) - if iscsi_names_list: - for iscsi_name in iscsi_names_list: - current_element.add(HOST_ISCSI_NAMES_PARAM, iscsi_name) - wwpns_list = host_dict.get(HOST_WWPNS_PARAM) - if wwpns_list: - for wwpn in wwpns_list: - current_element.add(HOST_WWPNS_PARAM, wwpn) + nvme_nqn_list = host_dict.get(HOST_NQN_PARAM, []) + for nqn in nvme_nqn_list: + current_element.add(HOST_NQN_PARAM, nqn) + wwpns_list = host_dict.get(HOST_WWPNS_PARAM, []) + for wwpn in wwpns_list: + current_element.add(HOST_WWPNS_PARAM, wwpn) + iscsi_names_list = host_dict.get(HOST_ISCSI_NAMES_PARAM, []) + for iscsi_name in iscsi_names_list: + current_element.add(HOST_ISCSI_NAMES_PARAM, iscsi_name) current_element.add(HOST_PORTSET_ID, host_dict.get(HOST_PORTSET_ID)) detailed_hosts_list.append(current_element) return iter(detailed_hosts_list) @@ -774,31 +873,42 @@ def test_get_volume_mappings_success(self): mappings = self.svc.get_volume_mappings("volume") self.assertEqual(mappings, {'Test_P': '0', 'Test_W': '1'}) - def test_get_first_free_lun_raises_host_not_found_error(self): + def test_get_free_lun_raises_host_not_found_error(self): self.svc.client.svcinfo.lshostvdiskmap.side_effect = [ svc_errors.CommandExecutionError('Failed')] with self.assertRaises(array_errors.HostNotFoundError): - self.svc.get_first_free_lun('host') - - def test_get_first_free_lun_with_no_host_mappings(self): - self.svc.client.svcinfo.lshostvdiskmap.return_value = [] - lun = self.svc.get_first_free_lun('host') - self.assertEqual(lun, '0') - - @patch.object(SVCArrayMediator, "MAX_LUN_NUMBER", 3) - @patch.object(SVCArrayMediator, "MIN_LUN_NUMBER", 1) - def test_get_first_free_lun_success(self): - map1 = Munch({'id': '51', 'name': 'peng', 'SCSI_id': '0', - 'host_id': '12', 'host_name': 'Test_P'}) - map2 = Munch({'id': '56', 'name': 'peng', 'SCSI_id': '1', - 'host_id': '16', 'host_name': 'Test_W'}) - self.svc.client.svcinfo.lshostvdiskmap.return_value = [map1, map2] - lun = self.svc.get_first_free_lun('Test_P') - self.assertEqual(lun, '2') + self.svc._get_free_lun('host') + + def _test_get_free_lun_host_mappings(self, lun_list, expected_lun='0'): + maps = [] + for index, lun in enumerate(lun_list): + maps.append(Munch({'id': index, 'name': 'peng{}'.format(index), 'SCSI_id': lun, + 'host_id': index, 'host_name': 'Test_{}'.format(index)})) + self.svc.client.svcinfo.lshostvdiskmap.return_value = maps + lun = self.svc._get_free_lun('host') + if lun_list: + self.assertNotIn(lun, lun_list) + self.assertEqual(lun, expected_lun) + + @patch("controller.array_action.array_mediator_svc.choice") + def test_get_free_lun_with_no_host_mappings(self, random_choice): + random_choice.return_value = '0' + self._test_get_free_lun_host_mappings([]) + + @patch.object(SVCArrayMediator, "MAX_LUN_NUMBER", 2) + @patch.object(SVCArrayMediator, "MIN_LUN_NUMBER", 0) + def test_get_free_lun_success(self): + self._test_get_free_lun_host_mappings(('1', '2')) + + @patch.object(SVCArrayMediator, "MAX_LUN_NUMBER", 4) + @patch.object(SVCArrayMediator, "MIN_LUN_NUMBER", 0) + @patch("controller.array_action.array_mediator_svc.LUN_INTERVAL", 1) + def test_get_free_lun_in_interval_success(self): + self._test_get_free_lun_host_mappings(('0', '1'), expected_lun='2') @patch.object(SVCArrayMediator, "MAX_LUN_NUMBER", 3) @patch.object(SVCArrayMediator, "MIN_LUN_NUMBER", 1) - def test_first_free_lun_no_available_lun(self): + def test_free_lun_no_available_lun(self): map1 = Munch({'id': '51', 'name': 'peng', 'SCSI_id': '1', 'host_id': '12', 'host_name': 'Test_P'}) map2 = Munch({'id': '56', 'name': 'peng', 'SCSI_id': '2', @@ -808,12 +918,12 @@ def test_first_free_lun_no_available_lun(self): self.svc.client.svcinfo.lshostvdiskmap.return_value = [map1, map2, map3] with self.assertRaises(array_errors.NoAvailableLunError): - self.svc.get_first_free_lun('Test_P') + self.svc._get_free_lun('Test_P') - @patch("controller.array_action.array_mediator_svc.SVCArrayMediator.get_first_free_lun") - def _test_map_volume_mkvdiskhostmap_error(self, client_error, expected_error, mock_get_first_free_lun): - mock_get_first_free_lun.return_value = '1' - self._test_mediator_method_client_error(self.svc.map_volume, ("volume", "host"), + @patch("controller.array_action.array_mediator_svc.SVCArrayMediator._get_free_lun") + def _test_map_volume_mkvdiskhostmap_error(self, client_error, expected_error, mock_get_free_lun): + mock_get_free_lun.return_value = '1' + self._test_mediator_method_client_error(self.svc.map_volume, ("volume", "host", "connectivity_type"), self.svc.client.svctask.mkvdiskhostmap, client_error, expected_error) @@ -828,12 +938,22 @@ def test_map_volume_mkvdiskhostmap_errors(self): array_errors.MappingError) self._test_map_volume_mkvdiskhostmap_error(Exception, Exception) - @patch("controller.array_action.array_mediator_svc.SVCArrayMediator.get_first_free_lun") - def test_map_volume_success(self, mock_get_first_free_lun): - mock_get_first_free_lun.return_value = '5' + @patch("controller.array_action.array_mediator_svc.SVCArrayMediator._get_free_lun") + def test_map_volume_success(self, mock_get_free_lun): + mock_get_free_lun.return_value = '5' self.svc.client.svctask.mkvdiskhostmap.return_value = None - lun = self.svc.map_volume("volume", "host") + self.svc.client.svcinfo.lsvdisk.return_value = Mock(as_single_element=self._get_cli_volume(name='volume')) + lun = self.svc.map_volume("volume_id", "host", "connectivity_type") self.assertEqual(lun, '5') + self.svc.client.svctask.mkvdiskhostmap.assert_called_once_with(host='host', object_id='volume', force=True, + scsi='5') + + def test_map_volume_nvme_success(self): + self.svc.client.svctask.mkvdiskhostmap.return_value = None + self.svc.client.svcinfo.lsvdisk.return_value = Mock(as_single_element=self._get_cli_volume(name='volume')) + lun = self.svc.map_volume("volume", "host", config.NVME_OVER_FC_CONNECTIVITY_TYPE) + self.assertEqual(lun, "") + self.svc.client.svctask.mkvdiskhostmap.assert_called_once_with(host='host', object_id='volume', force=True) def _test_unmap_volume_rmvdiskhostmap_error(self, client_error, expected_error): self._test_mediator_method_client_error(self.svc.unmap_volume, ("volume", "host"), @@ -856,7 +976,8 @@ def test_unmap_volume_success(self): self.svc.unmap_volume("volume", "host") def _prepare_mocks_for_get_iscsi_targets(self, portset_id=None): - host = self._get_host_as_dictionary('host_id', 'test_host', ['iqn.test.0', 'iqn.test.00'], ['abc0'], portset_id) + host = self._get_host_as_dictionary('host_id', 'test_host', wwpns_list=['wwn0'], + iscsi_names_list=['iqn.test.0', 'iqn.test.00'], portset_id=portset_id) self.svc.client.svcinfo.lshost = Mock() self.svc.client.svcinfo.lshost.return_value = Mock(as_single_element=host) @@ -1002,11 +1123,10 @@ def test_expand_volume_raise_object_in_use(self): def test_expand_volume_in_hyperswap(self): self._prepare_mocks_for_expand_volume() - fcmaps_as_source, fcmaps_as_target = self._prepare_fcmaps_for_hyperswap() - self.svc.client.svcinfo.lsfcmap.side_effect = [fcmaps_as_target, fcmaps_as_source] + self._prepare_fcmaps_for_hyperswap() self.svc.expand_volume('vol_id', 1024) - self.svc.client.svctask.expandvdisksize.assert_called_once_with(vdisk_id='test_volume', unit='b', size=512) + self.svc.client.svctask.expandvolume.assert_called_once_with(object_id='test_volume', unit='b', size=512) self.svc.client.svctask.rmfcmap.assert_not_called() def test_expand_volume_raise_object_not_found(self): diff --git a/controller/tests/array_action/xiv/array_mediator_xiv_tests.py b/controller/tests/array_action/xiv/array_mediator_xiv_tests.py index 21d6012bf..0e65f1a6a 100644 --- a/controller/tests/array_action/xiv/array_mediator_xiv_tests.py +++ b/controller/tests/array_action/xiv/array_mediator_xiv_tests.py @@ -389,65 +389,66 @@ def test_property(self): self.assertEqual(XIVArrayMediator.port, 7778) def test_get_host_by_identifiers_returns_host_not_found(self): - iqn = "iqn" + nqn = "" wwns = ['wwn1', 'wwn2'] + iqn = "iqn" host1 = utils.get_mock_xiv_host("host1", "iqn1", "") host2 = utils.get_mock_xiv_host("host2", "iqn1", "") host3 = utils.get_mock_xiv_host("host3", "iqn2", "") self.mediator.client.cmd.host_list.return_value = Mock(as_list=[host1, host2, host3]) with self.assertRaises(array_errors.HostNotFoundError): - self.mediator.get_host_by_host_identifiers(Initiators(iqn, wwns)) + self.mediator.get_host_by_host_identifiers(Initiators(nqn, wwns, iqn)) def test_get_host_by_identifiers_returns_host_not_found_when_no_hosts_exist(self): + nqn = "" iqn = "iqn" - self.mediator.client.cmd.host_list.return_value = Mock(as_list=[]) with self.assertRaises(array_errors.HostNotFoundError): - self.mediator.get_host_by_host_identifiers(Initiators(iqn, [])) + self.mediator.get_host_by_host_identifiers(Initiators(nqn, [], iqn)) def test_get_host_by_iscsi_identifiers_succeeds(self): - iqn = "iqn1" + nqn = "" wwns = [] + iqn = "iqn1" right_host = "host1" - host1 = utils.get_mock_xiv_host(right_host, "iqn1,iqn4", "") host2 = utils.get_mock_xiv_host("host2", "iqn2", "") host3 = utils.get_mock_xiv_host("host3", "iqn2", "") host4 = utils.get_mock_xiv_host("host4", "iqn3", "") self.mediator.client.cmd.host_list.return_value = Mock(as_list=[host1, host2, host3, host4]) - host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(iqn, wwns)) + host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(nqn, wwns, iqn)) self.assertEqual(host, right_host) self.assertEqual(connectivity_type, [ISCSI_CONNECTIVITY_TYPE]) def test_get_host_by_fc_identifiers_succeeds(self): - iqn = "iqn5" + nqn = "" wwns = ["wwn2", "wwn5"] + iqn = "iqn5" right_host = "host2" - host1 = utils.get_mock_xiv_host("host1", "iqn1", "wwn1") host2 = utils.get_mock_xiv_host(right_host, "iqn2", "wwn2") host3 = utils.get_mock_xiv_host("host3", "iqn2", "wwn3") host4 = utils.get_mock_xiv_host("host4", "iqn3", "wwn4") self.mediator.client.cmd.host_list.return_value = Mock(as_list=[host1, host2, host3, host4]) - host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(iqn, wwns)) + host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(nqn, wwns, iqn)) self.assertEqual(host, right_host) self.assertEqual(connectivity_type, [FC_CONNECTIVITY_TYPE]) def test_get_host_by_iscsi_and_fc_identifiers_succeeds(self): - iqn = "iqn2" + nqn = "" wwns = ["wwn2", "wwn5"] + iqn = "iqn2" right_host = "host2" - host1 = utils.get_mock_xiv_host("host1", "iqn1", "wwn1") host2 = utils.get_mock_xiv_host(right_host, "iqn2", "wwn2") host3 = utils.get_mock_xiv_host("host3", "iqn3", "wwn3") host4 = utils.get_mock_xiv_host("host4", "iqn4", "wwn4") self.mediator.client.cmd.host_list.return_value = Mock(as_list=[host1, host2, host3, host4]) - host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(iqn, wwns)) + host, connectivity_type = self.mediator.get_host_by_host_identifiers(Initiators(nqn, wwns, iqn)) self.assertEqual(host, right_host) self.assertEqual(connectivity_type, [FC_CONNECTIVITY_TYPE, ISCSI_CONNECTIVITY_TYPE]) @@ -515,12 +516,12 @@ def test_get_next_available_lun_no_available_lun(self): def test_map_volume_volume_not_found(self): self.mediator.client.cmd.vol_list.return_value = Mock(as_single_element=None) with self.assertRaises(array_errors.ObjectNotFoundError): - self.mediator.map_volume("volume-wwn", "host") + self.mediator.map_volume("volume-wwn", "host", "connectivity_type") def test_map_volume_raise_illegal_object_id(self): self.mediator.client.cmd.vol_list.side_effect = [xcli_errors.IllegalValueForArgumentError("", "volume-wwn", "")] with self.assertRaises(array_errors.IllegalObjectID): - self.mediator.map_volume("volume-wwn", "host") + self.mediator.map_volume("volume-wwn", "host", "connectivity_type") @patch.object(XIVArrayMediator, "MAX_LUN_NUMBER", 3) @patch.object(XIVArrayMediator, "MIN_LUN_NUMBER", 1) @@ -531,13 +532,13 @@ def test_map_volume_no_availabe_lun(self): self.mediator.client.cmd.mapping_list.return_value = Mock(as_list=[mapping1, mapping2, mapping3]) with self.assertRaises(array_errors.NoAvailableLunError): - self.mediator.map_volume("volume-wwn", "host") + self.mediator.map_volume("volume-wwn", "host", "connectivity_type") def map_volume_with_error(self, xcli_err, status, returned_err): self.mediator.client.cmd.map_vol.side_effect = [xcli_err("", status, "")] with patch.object(XIVArrayMediator, "_get_next_available_lun"): with self.assertRaises(returned_err): - self.mediator.map_volume("volume-wwn", "host") + self.mediator.map_volume("volume-wwn", "host", "connectivity_type") def test_map_volume_operation_forbidden(self): self.map_volume_with_error(xcli_errors.OperationForbiddenForUserCategoryError, "", @@ -563,7 +564,7 @@ def test_map_volume_other_command_runtime_error(self): def test_map_volume_success(self, next_lun): next_lun.return_value = 5 self.mediator.client.cmd.map_vol.return_value = None - lun = self.mediator.map_volume("volume-wwn", "host") + lun = self.mediator.map_volume("volume-wwn", "host", "connectivity_type") self.assertEqual(lun, '5') def test_unmap_volume_no_volume_raise_object_not_found(self): diff --git a/controller/tests/controller_server/utils_test.py b/controller/tests/controller_server/utils_test.py index 0e768e439..2f91981c8 100644 --- a/controller/tests/controller_server/utils_test.py +++ b/controller/tests/controller_server/utils_test.py @@ -6,6 +6,8 @@ import controller.array_action.errors as array_errors import controller.controller_server.utils as utils from controller.array_action import config as array_config +from controller.array_action.config import NVME_OVER_FC_CONNECTIVITY_TYPE, FC_CONNECTIVITY_TYPE, ISCSI_CONNECTIVITY_TYPE +from controller.common.node_info import NodeIdInfo from controller.controller_server import config as controller_config from controller.controller_server.csi_controller_server import CSIControllerServicer from controller.controller_server.errors import ObjectIdError, ValidationException @@ -383,51 +385,72 @@ def test_get_volume_id_info_no_id_fail(self): utils.get_volume_id_info("badvolumeformat") self.assertIn("Wrong volume id format", str(ex.exception)) + def _check_node_id_parameters(self, node_id_info, nvme_nqn, fc_wwns, iscsi_iqn): + self.assertEqual(node_id_info.node_name, "host-name") + self.assertEqual(node_id_info.initiators.nvme_nqn, nvme_nqn) + self.assertEqual(node_id_info.initiators.fc_wwns, fc_wwns.split(":")) + self.assertEqual(node_id_info.initiators.iscsi_iqn, iscsi_iqn) + def test_get_node_id_info(self): with self.assertRaises(array_errors.HostNotFoundError) as ex: - utils.get_node_id_info("badnodeformat") + utils.get_node_id_info("bad-node-format") self.assertTrue("node" in str(ex)) + host_name = "host-name" + nvme_nqn = "nqn.ibm" + fc_wwns = "wwn1:wwn2" + iscsi_iqn = "iqn.ibm" - hostname, fc_wwns, iscsi_iqn = utils.get_node_id_info("hostabc;;iqn.ibm") - self.assertEqual(hostname, "hostabc") - self.assertEqual(iscsi_iqn, "iqn.ibm") - self.assertEqual(fc_wwns, "") + node_id_info = NodeIdInfo("{};;;{}".format(host_name, iscsi_iqn)) + self._check_node_id_parameters(node_id_info, "", "", iscsi_iqn) - hostname, fc_wwns, iscsi_iqn = utils.get_node_id_info("hostabc;wwn1:wwn2;iqn.ibm") - self.assertEqual(hostname, "hostabc") - self.assertEqual(iscsi_iqn, "iqn.ibm") - self.assertEqual(fc_wwns, "wwn1:wwn2") + node_id_info = NodeIdInfo("{};;{};{}".format(host_name, fc_wwns, iscsi_iqn)) + self._check_node_id_parameters(node_id_info, "", fc_wwns, iscsi_iqn) - hostname, fc_wwns, iscsi_iqn = utils.get_node_id_info("hostabc;wwn1:wwn2") - self.assertEqual(hostname, "hostabc") - self.assertEqual(iscsi_iqn, "") - self.assertEqual(fc_wwns, "wwn1:wwn2") + node_id_info = NodeIdInfo("{};{};{}".format(host_name, nvme_nqn, fc_wwns)) + self._check_node_id_parameters(node_id_info, nvme_nqn, fc_wwns, "") - def test_choose_connectivity_types(self): - res = utils.choose_connectivity_type(["iscsi"]) - self.assertEqual(res, "iscsi") + node_id_info = NodeIdInfo("{};{}".format(host_name, nvme_nqn)) + self._check_node_id_parameters(node_id_info, nvme_nqn, "", "") - res = utils.choose_connectivity_type(["fc"]) - self.assertEqual(res, "fc") + node_id_info = NodeIdInfo("{};;{}".format(host_name, fc_wwns)) + self._check_node_id_parameters(node_id_info, "", fc_wwns, "") - res = utils.choose_connectivity_type(["iscsi", "fc"]) - self.assertEqual(res, "fc") + def test_choose_connectivity_types(self): + nvme = NVME_OVER_FC_CONNECTIVITY_TYPE + fc = FC_CONNECTIVITY_TYPE + iscsi = ISCSI_CONNECTIVITY_TYPE + expected_chosen_by_connectivities_found = { + (nvme, fc, iscsi): nvme, (fc, iscsi): fc, + (nvme,): nvme, (fc,): fc, (iscsi,): iscsi + } + for connectivities_found, expected_chosen_connectivity in expected_chosen_by_connectivities_found.items(): + actual_chosen = utils.choose_connectivity_type(list(connectivities_found)) + self.assertEqual(actual_chosen, expected_chosen_connectivity) + + def _check_publish_volume_response_parameters(self, lun, connectivity_type, array_initiators): + publish_volume_response = utils.generate_csi_publish_volume_response(lun, connectivity_type, self.config, + array_initiators) + self.assertEqual(publish_volume_response.publish_context["lun"], lun) + self.assertEqual(publish_volume_response.publish_context["connectivity_type"], connectivity_type) + if connectivity_type == NVME_OVER_FC_CONNECTIVITY_TYPE: + self.assertIsNone(publish_volume_response.publish_context.get("fc_wwns")) + self.assertIsNone(publish_volume_response.publish_context.get("array_iqn")) + elif connectivity_type == FC_CONNECTIVITY_TYPE: + self.assertEqual(publish_volume_response.publish_context["fc_wwns"], ",".join(array_initiators)) + self.assertIsNone(publish_volume_response.publish_context.get("array_iqn")) + elif connectivity_type == ISCSI_CONNECTIVITY_TYPE: + self.assertEqual(publish_volume_response.publish_context["array_iqn"], ",".join(array_initiators.keys())) + for iqn, ips in array_initiators.items(): + self.assertEqual(publish_volume_response.publish_context[iqn], ",".join(ips)) + self.assertIsNone(publish_volume_response.publish_context.get("fc_wwns")) def test_generate_publish_volume_response_success(self): - res = utils.generate_csi_publish_volume_response(0, "iscsi", self.config, - {"iqn": ["1.1.1.1", "2.2.2.2"], - "iqn2": ["3.3.3.3", "::1"]}) - self.assertEqual(res.publish_context["lun"], '0') - self.assertEqual(res.publish_context["connectivity_type"], "iscsi") - self.assertEqual(res.publish_context["array_iqn"], "iqn,iqn2") - self.assertEqual(res.publish_context["iqn"], "1.1.1.1,2.2.2.2") - self.assertEqual(res.publish_context["iqn2"], "3.3.3.3,::1") - - res = utils.generate_csi_publish_volume_response(1, "fc", self.config, - ["wwn1", "wwn2"]) - self.assertEqual(res.publish_context["lun"], '1') - self.assertEqual(res.publish_context["connectivity_type"], "fc") - self.assertEqual(res.publish_context["fc_wwns"], "wwn1,wwn2") + self._check_publish_volume_response_parameters("", NVME_OVER_FC_CONNECTIVITY_TYPE, []) + + self._check_publish_volume_response_parameters("1", FC_CONNECTIVITY_TYPE, ["wwn1", "wwn2"]) + + self._check_publish_volume_response_parameters("0", ISCSI_CONNECTIVITY_TYPE, + {"iqn": ["1.1.1.1", "2.2.2.2"], "iqn2": ["3.3.3.3", "::1"]}) def _test_validate_parameters_match_volume(self, volume_field, volume_value, parameter_field, parameter_value, default_space_efficiency=None): diff --git a/deploy/kubernetes/examples/demo-storageclass-config-secret.yaml b/deploy/kubernetes/examples/demo-storageclass-config-secret.yaml index 4aa90c9d1..b3283036d 100644 --- a/deploy/kubernetes/examples/demo-storageclass-config-secret.yaml +++ b/deploy/kubernetes/examples/demo-storageclass-config-secret.yaml @@ -7,7 +7,7 @@ volumeBindingMode: WaitForFirstConsumer parameters: # non-csi.storage.k8s.io parameters may be specified in by_management_id per system and/or outside by_management_id as the cross-system default. - by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"deduplicated","volume_name_prefix":"demo-prefix-1"}, + by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"dedup_compressed","volume_name_prefix":"demo-prefix-1"}, "demo-management-id-2":{"pool":"demo-pool-2","volume_name_prefix":"demo-prefix-2"}}' # Optional. pool: demo-pool SpaceEfficiency: thin # Optional. diff --git a/deploy/kubernetes/examples/demo-volumesnapshotclass-config-secret.yaml b/deploy/kubernetes/examples/demo-volumesnapshotclass-config-secret.yaml index 958a04a86..8ee201d0d 100644 --- a/deploy/kubernetes/examples/demo-volumesnapshotclass-config-secret.yaml +++ b/deploy/kubernetes/examples/demo-volumesnapshotclass-config-secret.yaml @@ -7,7 +7,7 @@ deletionPolicy: Delete parameters: # non-csi.storage.k8s.io parameters may be specified in by_management_id per system and/or outside by_management_id as the cross-system default. - by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"deduplicated","snapshot_name_prefix":"demo-prefix-1"}, + by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"dedup_compressed","snapshot_name_prefix":"demo-prefix-1"}, "demo-management-id-2":{"pool":"demo-pool-2","snapshot_name_prefix":"demo-prefix-2"}}' # Optional. pool: demo-pool # Optional. Use to create the snapshot on a different pool than the source. SpaceEfficiency: thin # Optional. Use to create the snapshot with a different space efficiency than the source. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index b189c9cac..08cee4759 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -3,59 +3,60 @@ * [Welcome](book_files/csi_block_storage_kc_welcome.md) * [What's new](book_files/csi_block_storage_kc_whatsnew.md) * [Release notes](book_files/csi_block_storage_kc_rn.md) - * [What's new in 1.7.0](content/release_notes/csi_rn_whatsnew.md) - * [Compatibility and requirements](content/release_notes/csi_rn_compatibility.md) - * [Supported storage systems](content/release_notes/csi_rn_supported_storage.md) - * [Supported operating systems](content/release_notes/csi_rn_supported_os.md) - * [Supported orchestration platforms](content/release_notes/csi_rn_supported_orchestration.md) - * [Change log](content/release_notes/csi_rn_changelog.md) - * [1.7.0 (September 2021)](content/release_notes/csi_rn_changelog_1.7.0.md) - * [1.6.0 (June 2021)](content/release_notes/csi_rn_changelog_1.6.0.md) - * [1.5.1 (July 2021)](content/release_notes/csi_rn_changelog_1.5.1.md) - * [1.5.0 (March 2021)](content/release_notes/csi_rn_changelog_1.5.0.md) - * [1.4.0 (December 2020)](content/release_notes/csi_rn_changelog_1.4.0.md) - * [1.3.0 (September 2020)](content/release_notes/csi_rn_changelog_1.3.0.md) - * [1.2.0 (June 2020)](content/release_notes/csi_rn_changelog_1.2.0.md) - * [1.1.0 (March 2020)](content/release_notes/csi_rn_changelog_1.1.0.md) - * [1.0.0 (November 2019)](content/release_notes/csi_rn_changelog_1.0.0.md) - * [Limitations](content/release_notes/csi_rn_limitations.md) - * [Known issues](content/release_notes/csi_rn_knownissues.md) -* [Overview](content/csi_overview.md) -* [Installation](content/installation/csi_ug_install_intro.md) - * [Compatibility and requirements](content/installation/csi_ug_requirements.md) - * [Installing the operator and driver](content/installation/csi_ug_install_operator.md) - * [Installing the driver with OpenShift web console](content/installation/csi_ug_install_operator_openshift.md) - * [Installing the driver with GitHub](content/installation/csi_ug_install_operator_github.md) - * [Installing the driver with OperatorHub.io](content/installation/csi_ug_install_operator_operatorhub.md) - * [Uninstalling the operator and driver](content/installation/csi_ug_uninstall.md) - * [Uninstalling the driver with the OpenShift web console](content/installation/csi_ug_uninstall_openshift.md) - * [Uninstalling the driver with GitHub](content/installation/csi_ug_uninstall_github.md) - * [Uninstalling the driver with OperatorHub.io](content/installation/csi_ug_uninstall_operatorhub.md) - * [Upgrading the CSI driver](content/installation/csi_ug_upgrade.md) - * [Manual upgrade with OpenShift](content/installation/csi_ug_upgrade_ocp_manual.md) -* [CSI driver configuration](content/configuration/csi_ug_config.md) - * [Creating a Secret](content/configuration/csi_ug_config_create_secret.md) - * [Creating a StorageClass](content/configuration/csi_ug_config_create_storageclasses.md) - * [Creating a PersistentVolumeClaim (PVC)](content/configuration/csi_ug_config_create_pvc.md) - * [Creating a StatefulSet](content/configuration/csi_ug_config_create_statefulset.md) - * [Creating a VolumeSnapshotClass](content/configuration/csi_ug_config_create_vol_snapshotclass.md) - * [Creating a VolumeSnapshot](content/configuration/csi_ug_config_create_snapshots.md) - * [Creating a VolumeReplicationClass](content/configuration/csi_ug_config_create_vol_replicationclass.md) - * [Finding a `system_id`](content/configuration/csi_ug_config_replication_find_systemid.md) - * [Creating a VolumeReplication](content/configuration/csi_ug_config_create_replication.md) - * [Expanding a PersistentVolumeClaim (PVC)](content/configuration/csi_ug_config_expand_pvc.md) - * [Configuring for CSI Topology](content/configuration/csi_ug_config_topology.md) - * [Creating a Secret with topology awareness](content/configuration/csi_ug_config_create_secret_topology.md) - * [Creating a StorageClass with topology awareness](content/configuration/csi_ug_config_create_storageclasses_topology.md) - * [Creating a VolumeSnapshotClass with topology awareness](content/configuration/csi_ug_config_create_vol_snapshotclass_topology.md) - * [Advanced configuration](content/configuration/csi_ug_config_advanced.md) - * [Importing an existing volume](content/configuration/csi_ug_config_advanced_importvol.md) -* [Using IBM block storage CSI driver](content/using/csi_ug_using.md) - * [Sample configurations for running a stateful container](content/using/csi_ug_using_sample.md) -* [Troubleshooting](content/troubleshooting/csi_ug_troubleshooting.md) - * [Log and status collection](content/troubleshooting/csi_ug_troubleshooting_logs.md) - * [Recovering a pod volume attachment from a crashed Kubernetes node](content/troubleshooting/csi_ug_troubleshooting_node_crash.md) - * [Miscellaneous troubleshooting](content/troubleshooting/csi_ug_troubleshooting_misc.md) + * [What's new in 1.8.0](content/release_notes/whats_new.md) + * [Compatibility and requirements](content/release_notes/compatibility_requirements.md) + * [Supported storage systems](content/release_notes/supported_storage.md) + * [Supported operating systems](content/release_notes/supported_os.md) + * [Supported orchestration platforms](content/release_notes/supported_orchestration.md) + * [Change log](content/release_notes/change_log.md) + * [1.8.0 (December 2021)](content/release_notes/changelog_1.8.0.md) + * [1.7.0 (September 2021)](content/release_notes/changelog_1.7.0.md) + * [1.6.0 (June 2021)](content/release_notes/changelog_1.6.0.md) + * [1.5.1 (July 2021)](content/release_notes/changelog_1.5.1.md) + * [1.5.0 (March 2021)](content/release_notes/changelog_1.5.0.md) + * [1.4.0 (December 2020)](content/release_notes/changelog_1.4.0.md) + * [1.3.0 (September 2020)](content/release_notes/changelog_1.3.0.md) + * [1.2.0 (June 2020)](content/release_notes/changelog_1.2.0.md) + * [1.1.0 (March 2020)](content/release_notes/changelog_1.1.0.md) + * [1.0.0 (November 2019)](content/release_notes/changelog_1.0.0.md) + * [Limitations](content/release_notes/limitations.md) + * [Known issues](content/release_notes/known_issues.md) +* [Overview](content/overview.md) +* [Installing](content/installation/installation.md) + * [Compatibility and requirements](content/installation/install_compatibility_requirements.md) + * [Installing the operator and driver](content/installation/install_operator_driver.md) + * [Installing the driver with OpenShift web console](content/installation/install_driver_openshift_web.md) + * [Installing the driver with GitHub](content/installation/install_driver_github.md) + * [Installing the driver with OperatorHub.io](content/installation/install_driver_operatorhub.md) + * [Uninstalling the operator and driver](content/installation/uninstalling.md) + * [Uninstalling the driver with the OpenShift web console](content/installation/uninstall_driver_openshift_web.md) + * [Uninstalling the driver with GitHub](content/installation/uninstall_driver_github.md) + * [Uninstalling the driver with OperatorHub.io](content/installation/uninstall_driver_operatorhub.md) + * [Upgrading the CSI driver](content/installation/upgrade.md) + * [Manual upgrade with OpenShift](content/installation/upgrade_manual_openshift.md) +* [Configuring](content/configuration/configuring.md) + * [Creating a Secret](content/configuration/creating_secret.md) + * [Creating a StorageClass](content/configuration/creating_volumestorageclass.md) + * [Creating a PersistentVolumeClaim (PVC)](content/configuration/creating_pvc.md) + * [Creating a StatefulSet](content/configuration/creating_statefulset.md) + * [Creating a VolumeSnapshotClass](content/configuration/creating_volumesnapshotclass.md) + * [Creating a VolumeSnapshot](content/configuration/creating_volumesnapshot.md) + * [Creating a VolumeReplicationClass](content/configuration/creating_volumereplicationclass.md) + * [Finding a `system_id`](content/configuration/finding_systemid.md) + * [Creating a VolumeReplication](content/configuration/creating_volumereplication.md) + * [Expanding a PersistentVolumeClaim (PVC)](content/configuration/expanding_pvc.md) + * [Configuring for CSI Topology](content/configuration/configuring_topology.md) + * [Creating a Secret with topology awareness](content/configuration/creating_secret_topology_aware.md) + * [Creating a StorageClass with topology awareness](content/configuration/creating_storageclass_topology_aware.md) + * [Creating a VolumeSnapshotClass with topology awareness](content/configuration/creating_volumesnapshotclass_topology_aware.md) + * [Advanced configuration](content/configuration/advanced_configuration.md) + * [Importing an existing volume](content/configuration/importing_existing_volume.md) +* [Using IBM block storage CSI driver](content/using/using.md) + * [Sample configurations for running a stateful container](content/using/sample_stateful_container.md) +* [Troubleshooting](content/troubleshooting/troubleshooting.md) + * [Log and status collection](content/troubleshooting/log_status_collect.md) + * [Recovering a pod volume attachment from a crashed Kubernetes node](content/troubleshooting/recovering_vol_attach_crashed_k8s.md) + * [Miscellaneous troubleshooting](content/troubleshooting/troubleshooting_misc.md) * [Notices](book_files/storage_csi_notices.md) * [Trademarks](book_files/csi_trademarks.md) * [Publications and related information](book_files/csi_block_storage_kc_pdfs.md) \ No newline at end of file diff --git a/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_RN.ditamap b/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_RN.ditamap deleted file mode 100644 index 77a5e1149..000000000 --- a/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_RN.ditamap +++ /dev/null @@ -1,47 +0,0 @@ - - - - -IBM block storage CSI -driver1.7.0 -Release Notes - - - -International Business Machines -Printed in USA - - - -IBM block storage CSI driver - -First - - - -2021 - - -IBM - - - - - - - - - - - - - - - - - - - - diff --git a/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_UG.ditamap b/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_UG.ditamap deleted file mode 100644 index 6ac483eac..000000000 --- a/docs/book_files/IBM_block_storage_CSI_driver_1.7.0_UG.ditamap +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - -IBM block storage CSI -driver1.7.0 -User Guide - - - -International Business Machines -Printed in USA - - - - - - -2021 - - -IBM - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/book_files/csi_block_storage_kc_pdfs.md b/docs/book_files/csi_block_storage_kc_pdfs.md index f6ca0deab..050175a61 100644 --- a/docs/book_files/csi_block_storage_kc_pdfs.md +++ b/docs/book_files/csi_block_storage_kc_pdfs.md @@ -1,15 +1,10 @@ # Publications and related information -The following Portable Document Format (PDF) publications and related online information sources are available for the IBM® block storage CSI driver. +Download the Portable Document Format (PDF) publications of this product from the table of contents side bar. -To view a PDF file, you need Adobe™ Reader. You can download it at no charge from the [Adobe website](http://get.adobe.com/reader/). - -## Publications +The PDF of this version collection is now available to download from the `Download PDF` button on the bottom of the table of contents side bar. -|IBM block storage CSI driver publication|Description|PDF download link| -|----------------------------------------|-----------|-----------------| -|*Release notes*|This publication describes requirements, compatibility, change log, and known issues information for version 1.7.0.
First Edition (June 2021) for version 1.7.0.|![PDF icon](PDF_icon.jpg) [Download](../pdf/IBM_block_storage_CSI_driver_1.7.0_RN.pdf)| -|*User guide*|This publication describes how to prepare for, install, configure, and use IBM block storage CSI driver.
First Edition (September 2021).|![PDF icon](PDF_icon.jpg) [Download](../pdf/IBM_block_storage_CSI_driver_1.7.0_UG.pdf)| +To view a PDF file, you need Adobe™ Reader. You can download it at no charge from the [Adobe website](http://get.adobe.com/reader/). ## Related information and publications diff --git a/docs/book_files/csi_block_storage_kc_rn.md b/docs/book_files/csi_block_storage_kc_rn.md index 4da04204f..583de3fa6 100644 --- a/docs/book_files/csi_block_storage_kc_rn.md +++ b/docs/book_files/csi_block_storage_kc_rn.md @@ -1,4 +1,4 @@ # Release notes -The following release information is available for version 1.7.0 of the IBM® block storage CSI driver. +The following release information is available for version 1.8.0 of the IBM® block storage CSI driver. diff --git a/docs/book_files/csi_block_storage_kc_welcome.md b/docs/book_files/csi_block_storage_kc_welcome.md index 6a51d9f92..876c9b6df 100644 --- a/docs/book_files/csi_block_storage_kc_welcome.md +++ b/docs/book_files/csi_block_storage_kc_welcome.md @@ -1,4 +1,4 @@ -# IBM block storage CSI driver 1.7.0 welcome page +# IBM block storage CSI driver 1.8.0 welcome page IBM block storage CSI driver is based on an open-source IBM project, included as a part of IBM Storage orchestration for containers. IBM Storage orchestration for containers enables enterprises to implement a modern container-driven hybrid multicloud environment that can diff --git a/docs/book_files/csi_block_storage_kc_whatsnew.md b/docs/book_files/csi_block_storage_kc_whatsnew.md index 4d3489921..311cb200b 100644 --- a/docs/book_files/csi_block_storage_kc_whatsnew.md +++ b/docs/book_files/csi_block_storage_kc_whatsnew.md @@ -1,8 +1,8 @@ # What's new -This topic lists the dates and nature of updates to the published information of IBM® block storage CSI driver 1.7.0. +This topic lists the dates and nature of updates to the published information of IBM® block storage CSI driver 1.8.0. |Date|Nature of updates to the published information| |----|----------------------------------------------| -|30 September 2021|The version information was added to the IBM Documentation.
For more information about this version, see the [What's new in 1.7.0](../content/release_notes/csi_rn_whatsnew.md) section in the release notes.
In addition, a new [Lifecycle support matrix](https://www.ibm.com/docs/en/stg-block-csi-driver?topic=SSRQ8T/landing/csi_lifecycle_support_matrix.html) was added to IBM Documentation for this product.| +|15 December 2021|The version information was added to the IBM Documentation.
For more information about this version, see the [What's new in 1.8.0](../content/release_notes/whats_new.md) section in the release notes.| diff --git a/docs/book_files/csi_bookconventions.dita b/docs/book_files/csi_bookconventions.dita deleted file mode 100644 index bd8d9d14a..000000000 --- a/docs/book_files/csi_bookconventions.dita +++ /dev/null @@ -1,18 +0,0 @@ - - - - - -Conventions used in this guide -These notices are used in this guide to highlight key information. - -
-These notices provide important tips, guidance, or advice. -These notices provide information or advice that might help you avoid -inconvenient or difficult situations. -These notices indicate possible damage to programs, devices, or data. An -attention notice appears before the instruction or situation in which damage can occur.
-
-
- diff --git a/docs/book_files/csi_gettinginfohelpandservice.dita b/docs/book_files/csi_gettinginfohelpandservice.dita deleted file mode 100644 index 60eb5d6d9..000000000 --- a/docs/book_files/csi_gettinginfohelpandservice.dita +++ /dev/null @@ -1,20 +0,0 @@ - - - - - -Getting information, help, and service - -

If you need help, service, technical assistance, or want more information about IBM products, you can find various sources to assist you. You can view the following websites to get information about IBM products and services and to find the latest technical information and support.

    -
  • #get-help_csi Slack channel
  • -
  • IBM website (ibm.com)
  • -
  • IBM Support Portal website (ibm.com/support/entry/portal/support?brandind=Hardware~System_Storage)
  • -
  • IBM Directory of Worldwide Contacts website (ibm.com/planetwide)

    Use -the Directory of Worldwide Contacts to find the appropriate phone number for initiating voice call -support. Select the Software option, when using voice response system.

    When asked, provide -your Internal Customer Number (ICN) and/or the serial number of the storage system that requires -support. Your call will then be routed to the relevant support team, to whom you can provide the -specifics of your problem.

  • -

- -
diff --git a/docs/book_files/csi_howtoorderpubs.dita b/docs/book_files/csi_howtoorderpubs.dita deleted file mode 100644 index e1c0411d3..000000000 --- a/docs/book_files/csi_howtoorderpubs.dita +++ /dev/null @@ -1,14 +0,0 @@ - - - -<tm trademark="IBM" tmtype="reg">IBM</tm> Publications Center -The IBM Publications Center is a worldwide central -repository for IBM product publications and marketing -material. - -
-

The IBM Publications Center website (ibm.com/shop/publications/order) offers customized search functions to help you find the publications that you need. You can view or download publications at no charge.

-
-
- -
diff --git a/docs/book_files/csi_relatedpubs.dita b/docs/book_files/csi_relatedpubs.dita deleted file mode 100644 index 79428ddfd..000000000 --- a/docs/book_files/csi_relatedpubs.dita +++ /dev/null @@ -1,94 +0,0 @@ - - - -Related information and publications - -Related information and publications -Related information and publications - - - - - diff --git a/docs/book_files/csi_rn_content.ditamap b/docs/book_files/csi_rn_content.ditamap deleted file mode 100644 index c9ed64556..000000000 --- a/docs/book_files/csi_rn_content.ditamap +++ /dev/null @@ -1,33 +0,0 @@ - - - - -<tm trademark="IBM" tmtype="reg">IBM</tm> block storage CSI driver 1.7.0 Release <tm -trademark="Notes" tmtype="reg">Notes</tm> content map - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/book_files/csi_rn_edition_notice.dita b/docs/book_files/csi_rn_edition_notice.dita deleted file mode 100644 index 48304c513..000000000 --- a/docs/book_files/csi_rn_edition_notice.dita +++ /dev/null @@ -1,11 +0,0 @@ - - - -First Edition (September 2021) -This edition applies to version 1.7.0 of the IBM -block storage CSI driver software package. Newer document editions may be issued for the same -product version in order to add missing information, update information, or amend typographical -errors. The edition is reset to 'First Edition' for every new product version. - - - diff --git a/docs/book_files/csi_ug_about_this_guide.dita b/docs/book_files/csi_ug_about_this_guide.dita deleted file mode 100644 index d6f53ea06..000000000 --- a/docs/book_files/csi_ug_about_this_guide.dita +++ /dev/null @@ -1,15 +0,0 @@ - - - - -About this guide - -About this guide -About this guide - -This guide describes how to install, configure, and use the IBM block storage CSI -driver. - - - diff --git a/docs/book_files/csi_ug_audience.dita b/docs/book_files/csi_ug_audience.dita deleted file mode 100644 index 97561a216..000000000 --- a/docs/book_files/csi_ug_audience.dita +++ /dev/null @@ -1,16 +0,0 @@ - - - - -Who should use this guide - -Who should use this guide -Who should use this guide - -This guide is intended for system administrators who are familiar with container-based -application delivery, orchestration methods, and with the specific IBM storage system that is in use. - - - diff --git a/docs/book_files/csi_ug_content.ditamap b/docs/book_files/csi_ug_content.ditamap index 6683d851f..57eabcbc5 100644 --- a/docs/book_files/csi_ug_content.ditamap +++ b/docs/book_files/csi_ug_content.ditamap @@ -4,68 +4,57 @@ CSI UG content ditamap - - - - - - - + + + + + + + - - - - + + + + - + - + - - - - - - + + + + + - - + +href="../content/configuration/finding_systemid.md"/> - - - - - + + + + - - - + + - - + + - - - - + + + + diff --git a/docs/book_files/csi_ug_edition_notice.dita b/docs/book_files/csi_ug_edition_notice.dita deleted file mode 100644 index a6873d2d5..000000000 --- a/docs/book_files/csi_ug_edition_notice.dita +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -Edition notice -Publication number: SC27-9590-10. This publication applies to version 1.6.0 of IBM block -storage CSI driver and to all subsequent releases and modifications until otherwise indicated in a -newer publication. - - - - diff --git a/docs/book_files/csi_ug_special_notice.dita b/docs/book_files/csi_ug_special_notice.dita deleted file mode 100644 index 4becb7156..000000000 --- a/docs/book_files/csi_ug_special_notice.dita +++ /dev/null @@ -1,12 +0,0 @@ - - - - -Note - -

Before using this document and the product it supports, read the information in .

- -
- diff --git a/docs/book_files/sending_comments.dita b/docs/book_files/sending_comments.dita deleted file mode 100644 index 43336ad18..000000000 --- a/docs/book_files/sending_comments.dita +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - -Sending comments - -Feedback - -Your feedback is important in helping to provide the most -accurate and highest quality information. - -comments, sendingfeedback, -sending - - - - -To submit any comments about this publication or any -other IBM storage product documentation: - -Send your comments by email to ibmdocs@us.ibm.com. Be sure to include the following information: - -
    -
  • Exact publication title and version
  • -
  • Publication form number (for example, GA32-1234-00)
  • -
  • Page, table, or illustration numbers that you are commenting on
  • -
  • A detailed description of any information that should be changed
  • -
-
-
-
-
- -
- diff --git a/docs/content/configuration/csi_ug_config_advanced.md b/docs/content/configuration/advanced_configuration.md similarity index 65% rename from docs/content/configuration/csi_ug_config_advanced.md rename to docs/content/configuration/advanced_configuration.md index b328082e5..8ef33857d 100644 --- a/docs/content/configuration/csi_ug_config_advanced.md +++ b/docs/content/configuration/advanced_configuration.md @@ -2,5 +2,5 @@ Use advanced configuration tasks to further customize the configuration of the IBM® block storage CSI driver. -- [Importing an existing volume](csi_ug_config_advanced_importvol.md) +- [Importing an existing volume](importing_existing_volume.md) diff --git a/docs/content/configuration/configuring.md b/docs/content/configuration/configuring.md new file mode 100644 index 000000000..2dda07702 --- /dev/null +++ b/docs/content/configuration/configuring.md @@ -0,0 +1,19 @@ +# Configuring + +Use this information to configure the IBM® block storage CSI driver after installation. + +Once the driver is installed and running (see [Installing the operator and driver](../installation/install_operator_driver.md)), in order to use the driver and run stateful applications using IBM block storage systems, the relevant YAML files must be created. + +Multiple YAML files per type can be created (with different configurations), according to your storage needs. + +- [Creating a Secret](creating_secret.md) +- [Creating a StorageClass](creating_volumestorageclass.md) +- [Creating a PersistentVolumeClaim (PVC)](creating_pvc.md) +- [Creating a StatefulSet](creating_statefulset.md) +- [Creating a VolumeSnapshotClass](creating_volumesnapshotclass.md) +- [Creating a VolumeSnapshot](creating_volumesnapshot.md) +- [Creating a VolumeReplicationClass](creating_volumereplicationclass.md) +- [Creating a VolumeReplication](creating_volumereplication.md) +- [Expanding a PersistentVolumeClaim (PVC)](expanding_pvc.md) +- [Configuring for CSI Topology](configuring_topology.md) +- [Advanced configuration](advanced_configuration.md) \ No newline at end of file diff --git a/docs/content/configuration/configuring_topology.md b/docs/content/configuration/configuring_topology.md new file mode 100644 index 000000000..52465e15b --- /dev/null +++ b/docs/content/configuration/configuring_topology.md @@ -0,0 +1,9 @@ +# Configuring for CSI Topology + +Use this information for specific configuring information when using CSI Topology with the IBM® block storage CSI driver. + +**Important:** Be sure that all of the topology requirements are met before starting. For more information, see [Compatibility and requirements](../installation/install_compatibility_requirements.md). + +- [Creating a Secret with topology awareness](creating_secret_topology_aware.md) +- [Creating a StorageClass with topology awareness](creating_storageclass_topology_aware.md) +- [Creating a VolumeSnapshotClass with topology awareness](creating_volumesnapshotclass_topology_aware.md) \ No newline at end of file diff --git a/docs/content/configuration/csi_ug_config_create_pvc.md b/docs/content/configuration/creating_pvc.md similarity index 86% rename from docs/content/configuration/csi_ug_config_create_pvc.md rename to docs/content/configuration/creating_pvc.md index 3ef849f9b..65eee19a0 100644 --- a/docs/content/configuration/csi_ug_config_create_pvc.md +++ b/docs/content/configuration/creating_pvc.md @@ -18,12 +18,12 @@ The `persistentvolumeclaim/ created` message is emitted. Use the following sections, according to your PVC needs: -- Creating PVC for volume with file system -- Creating PVC for raw block volume -- Creating PVC from volume snapshot -- Creating a volume clone from an existing PVC +- [Creating a PVC for volume with file system](#creating-a-pvc-for-volume-with-file-system) +- [Creating a PVC for raw block volume](#creating-a-pvc-for-raw-block-volume) +- [Creating a PVC from volume snapshot](#creating-a-pvc-from-volume-snapshot) +- [Creating a volume clone from an existing PVC](#creating-a-volume-clone-from-an-existing-pvc) -## Creating PVC for volume with Filesystem +## Creating a PVC for volume with file system Create a PVC YAML file, similar to the following `demo-pvc-file-system.yaml` file, with the size of 1 Gb, with `volumeMode` defined as `Filesystem`. @@ -42,7 +42,7 @@ Create a PVC YAML file, similar to the following `demo-pvc-file-system.yaml` fil storage: 1Gi storageClassName: demo-storageclass -## Creating PVC for raw block volume +## Creating a PVC for raw block volume Create a PVC YAML file, similar to the following `demo-pvc-raw-block.yaml` file, with the size of 1 Gb, with `volumeMode` defined as `Block`. @@ -59,7 +59,7 @@ Create a PVC YAML file, similar to the following `demo-pvc-raw-block.yaml` file, storage: 1Gi storageClassName: demo-storageclass -## Creating PVC from volume snapshot +## Creating a PVC from volume snapshot To create a PVC from an existing volume snapshot, create a PVC YAML file, similar to the following `demo-pvc-from-snapshot.yaml` file, with the size of 1 Gb. @@ -82,7 +82,7 @@ Update the `dataSource` parameters to reflect the existing volume snapshot infor kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io -## Creating a volume clone from an existing PVC +## Creating a volume clone from an existing PVC **Note:** IBM FlashCopy® function is referred to as the more generic volume snapshots and cloning within this documentation set. Not all supported products use the FlashCopy function terminology. diff --git a/docs/content/configuration/csi_ug_config_create_secret.md b/docs/content/configuration/creating_secret.md similarity index 88% rename from docs/content/configuration/csi_ug_config_create_secret.md rename to docs/content/configuration/creating_secret.md index 04dd67771..2dba042cf 100644 --- a/docs/content/configuration/csi_ug_config_create_secret.md +++ b/docs/content/configuration/creating_secret.md @@ -4,9 +4,11 @@ Create an array secret YAML file in order to define the storage credentials (use **Important:** When your storage system password is changed, be sure to also change the passwords in the corresponding secrets, particularly when LDAP is used on the storage systems.

Failing to do so causes mismatched passwords across the storage systems and the secrets, causing the user to be locked out of the storage systems. -**Note:** If using the CSI Topology feature, follow the steps in [Creating a Secret with topology awareness](csi_ug_config_create_secret_topology.md). +**Note:** If using the CSI Topology feature, follow the steps in [Creating a Secret with topology awareness](creating_secret_topology_aware.md). Use one of the following procedures to create and apply the secret: + - [Creating an array secret file](#creating-an-array-secret-file) + - [Creating an array secret via command line](#creating-an-array-secret-via-command-line) ## Creating an array secret file 1. Create the secret file, similar to the following `demo-secret.yaml`: diff --git a/docs/content/configuration/csi_ug_config_create_secret_topology.md b/docs/content/configuration/creating_secret_topology_aware.md similarity index 96% rename from docs/content/configuration/csi_ug_config_create_secret_topology.md rename to docs/content/configuration/creating_secret_topology_aware.md index 920fd247f..bbe907219 100644 --- a/docs/content/configuration/csi_ug_config_create_secret_topology.md +++ b/docs/content/configuration/creating_secret_topology_aware.md @@ -2,7 +2,7 @@ Create an array secret YAML file to define the storage credentials (username and password) and address. Use this information for creating a Secret that is topology aware. -**Note:** If you are not using the CSI Topology feature, follow the steps in [Creating a Secret](csi_ug_config_create_secret.md). +**Note:** If you are not using the CSI Topology feature, follow the steps in [Creating a Secret](creating_secret.md). Within the Secret, each user-defined management ID (here, represented by `demo-management-id-x`), is used to identify the storage system within other configuration files. diff --git a/docs/content/configuration/csi_ug_config_create_statefulset.md b/docs/content/configuration/creating_statefulset.md similarity index 89% rename from docs/content/configuration/csi_ug_config_create_statefulset.md rename to docs/content/configuration/creating_statefulset.md index 390b56ef0..256c34c80 100644 --- a/docs/content/configuration/csi_ug_config_create_statefulset.md +++ b/docs/content/configuration/creating_statefulset.md @@ -8,7 +8,14 @@ StatefulSets can include file system volumes, raw block volumes, or both. **Important:** When defining the StatefulSet configuration, be sure to define volumes according to the PVC volume mode. -Use the following sections for YAML creation of StatefulSets with file system, raw block volume, and mixed volume modes. After each YAML file creation, use the `kubectl apply` command. +Use the following sections for YAML creation of StatefulSets with file system, raw block volume, and mixed volume modes. + + - [Creating a StatefulSet with file system volumes](#creating-a-statefulset-with-file-system-volumes) + - [Creating a StatefulSet with raw block volume](#creating-a-statefulset-with-raw-block-volume) + - [Creating a StatefulSet with both raw block and file system volumes](#creating-a-statefulset-with-both-raw-block-and-file-system-volumes) + + +After each YAML file creation, use the `kubectl apply` command. ``` kubectl apply -f .yaml diff --git a/docs/content/configuration/csi_ug_config_create_storageclasses_topology.md b/docs/content/configuration/creating_storageclass_topology_aware.md similarity index 52% rename from docs/content/configuration/csi_ug_config_create_storageclasses_topology.md rename to docs/content/configuration/creating_storageclass_topology_aware.md index 14e87a773..76ab3d7d2 100644 --- a/docs/content/configuration/csi_ug_config_create_storageclasses_topology.md +++ b/docs/content/configuration/creating_storageclass_topology_aware.md @@ -2,9 +2,9 @@ When using the CSI Topology feature, different parameters must be taken into account when creating a storage class YAML file with specific `by_management_id` requirements. Use this information to help define a StorageClass that is topology aware. -**Note:** For information and parameter definitions that are not related to topology awareness, be sure to see the information provided in [Creating a StorageClass](csi_ug_config_create_storageclasses.md), in addition to the current section. +**Note:** For information and parameter definitions that are not related to topology awareness, be sure to see the information provided in [Creating a StorageClass](creating_volumestorageclass.md), in addition to the current section. -The StorageClass file must be defined to contain topology information, based off of the labels that were already defined on the nodes in the cluster (see [Compatibility and requirements](../installation/csi_ug_requirements.md)). This determines the storage pools that are then served as candidates for PersistentVolumeClaim (PVC) requests made, as well as the subset of nodes that can make use of the volumes provisioned by the CSI driver. +The StorageClass file must be defined to contain topology information, based off of the labels that were already defined on the nodes in the cluster (see [Compatibility and requirements](../installation/install_compatibility_requirements.md)). This determines the storage pools that are then served as candidates for PersistentVolumeClaim (PVC) requests made, as well as the subset of nodes that can make use of the volumes provisioned by the CSI driver. With topology awareness, the StorageClass must have the `volumeBindingMode` set to `WaitForFirstConsumer` (as defined in the `.yaml` example below). This defines that any PVCs that are requested with this specific StorageClass, will wait to be configured until the CSI driver can see the worker node topology. @@ -14,28 +14,26 @@ The various `by_management_id` parameters are chosen within the following hierar 1. From within the `by_management_id` parameter, per system (if specified). 2. Outside of the parameter, as a cross-system default (if not specified within the `by_management_id` parameter for the relevant `management-id`). - - ``` -kind: StorageClass -apiVersion: storage.k8s.io/v1 -metadata: - name: demo-storageclass-config-secret -provisioner: block.csi.ibm.com -volumeBindingMode: WaitForFirstConsumer -parameters: - # non-csi.storage.k8s.io parameters may be specified in by_management_id per system and/or outside by_management_id as the cross-system default. - - by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"deduplicated","volume_name_prefix":"demo-prefix-1"}, - "demo-management-id-2":{"pool":"demo-pool-2","volume_name_prefix":"demo-prefix-2"}}' # Optional. - pool: demo-pool - SpaceEfficiency: thin # Optional. - volume_name_prefix: demo-prefix # Optional. - - csi.storage.k8s.io/fstype: xfs # Optional. Values ext4/xfs. The default is ext4. - csi.storage.k8s.io/secret-name: demo-config-secret - csi.storage.k8s.io/secret-namespace: default -allowVolumeExpansion: true - ``` + kind: StorageClass + apiVersion: storage.k8s.io/v1 + metadata: + name: demo-storageclass-config-secret + provisioner: block.csi.ibm.com + volumeBindingMode: WaitForFirstConsumer + parameters: + # non-csi.storage.k8s.io parameters may be specified in by_management_id per system and/or outside by_management_id as the cross-system default. + + by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"dedup_compressed","volume_name_prefix":"demo-prefix-1"}, + "demo-management-id-2":{"pool":"demo-pool-2","volume_name_prefix":"demo-prefix-2"}}' # Optional. + pool: demo-pool + SpaceEfficiency: thin # Optional. + volume_name_prefix: demo-prefix # Optional. + + csi.storage.k8s.io/fstype: xfs # Optional. Values ext4/xfs. The default is ext4. + csi.storage.k8s.io/secret-name: demo-config-secret + csi.storage.k8s.io/secret-namespace: default + allowVolumeExpansion: true + Apply the storage class. ``` diff --git a/docs/content/configuration/csi_ug_config_create_replication.md b/docs/content/configuration/creating_volumereplication.md similarity index 92% rename from docs/content/configuration/csi_ug_config_create_replication.md rename to docs/content/configuration/creating_volumereplication.md index bb4638b64..8bd5df119 100644 --- a/docs/content/configuration/csi_ug_config_create_replication.md +++ b/docs/content/configuration/creating_volumereplication.md @@ -2,15 +2,15 @@ Create a VolumeReplication YAML file to replicate a specific PersistentVolumeClaim (PVC). -VolumeReplicationClass needs to be present before a VolumeReplication can be created. For more information, see [Creating a VolumeReplicationClass](csi_ug_config_create_vol_replicationclass.md). +VolumeReplicationClass needs to be present before a VolumeReplication can be created. For more information, see [Creating a VolumeReplicationClass](creating_volumereplicationclass.md). **Note:** Remote copy function is referred to as the more generic volume replication within this documentation set. Not all supported products use the remote-copy function terminology. -When replicating a volume, be sure to follow all of the replication configurations, found in [Compatibility and requirements](../installation/csi_ug_requirements.md) before volume replication. +When replicating a volume, be sure to follow all of the replication configurations, found in [Compatibility and requirements](../installation/install_compatibility_requirements.md) before volume replication. 1. Replicate a specific PersistentVolumeClaim (PVC) using the `demo-volumereplication.yaml`. - For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](csi_ug_config_create_pvc.md). + For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](creating_pvc.md). **Note:** Use the `spec.csi.volumeHandle` of the relevant target PersistentVolume (PV) for the `replicationHandle` value. diff --git a/docs/content/configuration/csi_ug_config_create_vol_replicationclass.md b/docs/content/configuration/creating_volumereplicationclass.md similarity index 88% rename from docs/content/configuration/csi_ug_config_create_vol_replicationclass.md rename to docs/content/configuration/creating_volumereplicationclass.md index a7355145a..839f6aa76 100644 --- a/docs/content/configuration/csi_ug_config_create_vol_replicationclass.md +++ b/docs/content/configuration/creating_volumereplicationclass.md @@ -6,9 +6,9 @@ Create a VolumeReplicationClass YAML file to enable volume replication. In order to enable volume replication for your storage system, create a VolumeReplicationClass YAML file, similar to the following `demo-volumereplicationclass.yaml`. -When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](csi_ug_config_create_secret.md). +When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](creating_secret.md). -For information on obtaining your storage system `system_id`, see [Finding a `system_id`](csi_ug_config_replication_find_systemid.md). +For information on obtaining your storage system `system_id`, see [Finding a `system_id`](finding_systemid.md). ``` apiVersion: replication.storage.openshift.io/v1alpha1 diff --git a/docs/content/configuration/csi_ug_config_create_snapshots.md b/docs/content/configuration/creating_volumesnapshot.md similarity index 90% rename from docs/content/configuration/csi_ug_config_create_snapshots.md rename to docs/content/configuration/creating_volumesnapshot.md index d418d879d..7801dc55e 100644 --- a/docs/content/configuration/csi_ug_config_create_snapshots.md +++ b/docs/content/configuration/creating_volumesnapshot.md @@ -2,17 +2,17 @@ Create a VolumeSnapshot YAML file for a specific PersistentVolumeClaim (PVC). -VolumeSnapshotClass needs to be present before a VolumeSnapshot can be created. For more information, see [Creating a VolumeSnapshotClass](csi_ug_config_create_vol_snapshotclass.md). +VolumeSnapshotClass needs to be present before a VolumeSnapshot can be created. For more information, see [Creating a VolumeSnapshotClass](creating_volumesnapshotclass.md). **Note:** - IBM® FlashCopy® function is referred to as the more generic volume snapshots and cloning within this documentation set. Not all supported products use the FlashCopy function terminology. -When creating volume snapshots, be sure to follow all of the snapshot configurations, found in [Compatibility and requirements](../installation/csi_ug_requirements.md) before snapshot creation. +When creating volume snapshots, be sure to follow all of the snapshot configurations, found in [Compatibility and requirements](../installation/install_compatibility_requirements.md) before snapshot creation. 1. Create a snapshot for a specific PersistentVolumeClaim (PVC) using the `demo-volumesnapshot.yaml`. - For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](csi_ug_config_create_pvc.md). + For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](creating_pvc.md). ``` apiVersion: snapshot.storage.k8s.io/v1beta1 diff --git a/docs/content/configuration/csi_ug_config_create_vol_snapshotclass.md b/docs/content/configuration/creating_volumesnapshotclass.md similarity index 92% rename from docs/content/configuration/csi_ug_config_create_vol_snapshotclass.md rename to docs/content/configuration/creating_volumesnapshotclass.md index c72aae29a..2cda4e3a6 100644 --- a/docs/content/configuration/csi_ug_config_create_vol_snapshotclass.md +++ b/docs/content/configuration/creating_volumesnapshotclass.md @@ -6,11 +6,11 @@ Create a VolumeSnapshotClass YAML file to enable creation and deletion of volume In order to enable creation and deletion of volume snapshots for your storage system, create a VolumeSnapshotClass YAML file, similar to the following `demo-volumesnapshotclass.yaml`. -When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](csi_ug_config_create_secret.md). +When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](creating_secret.md). - The `snapshot_name_prefix` parameter is optional. - **Note:** For IBM DS8000® Family, the maximum prefix length is five characters.
The maximum prefix length for other systems is 20 characters.
For storage systems that use Spectrum Virtualize, the `CSI` prefix is added as default if not specified by the user. + **Note:** For IBM DS8000® family, the maximum prefix length is five characters.
The maximum prefix length for other systems is 20 characters.
For storage systems that use Spectrum Virtualize, the `CSI` prefix is added as default if not specified by the user. - The `pool` parameter is not available on IBM FlashSystem A9000 and A9000R storage systems. For these storage systems, the snapshot must be created on the same pool as the source. diff --git a/docs/content/configuration/csi_ug_config_create_vol_snapshotclass_topology.md b/docs/content/configuration/creating_volumesnapshotclass_topology_aware.md similarity index 92% rename from docs/content/configuration/csi_ug_config_create_vol_snapshotclass_topology.md rename to docs/content/configuration/creating_volumesnapshotclass_topology_aware.md index 2946eb8af..e789ed7a5 100644 --- a/docs/content/configuration/csi_ug_config_create_vol_snapshotclass_topology.md +++ b/docs/content/configuration/creating_volumesnapshotclass_topology_aware.md @@ -3,7 +3,7 @@ When using the CSI Topology feature, different parameters must be taken into account when creating a VolumeSnapshotClass YAML file with specific `by_management_id` requirements. Use this information to help define a VolumeSnapshotClass that is topology aware and enables the creation and deletion of volume snapshots. **Note:** - - For information and parameter definitions that are not related to topology awareness, be sure to see the information that is provided in [Creating a VolumeSnapshotClass](csi_ug_config_create_vol_snapshotclass.md), in addition to the current section. + - For information and parameter definitions that are not related to topology awareness, be sure to see the information that is provided in [Creating a VolumeSnapshotClass](creating_volumesnapshotclass.md), in addition to the current section. - IBM® FlashCopy® function is referred to as the more generic volume snapshots and cloning within this documentation set. Not all supported products use the FlashCopy function terminology. @@ -25,7 +25,7 @@ deletionPolicy: Delete parameters: # non-csi.storage.k8s.io parameters may be specified in by_management_id per system and/or outside by_management_id as the cross-system default. - by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"deduplicated","snapshot_name_prefix":"demo-prefix-1"}, + by_management_id: '{"demo-management-id-1":{"pool":"demo-pool-1","SpaceEfficiency":"dedup_compressed","snapshot_name_prefix":"demo-prefix-1"}, "demo-management-id-2":{"pool":"demo-pool-2","snapshot_name_prefix":"demo-prefix-2"}}' # Optional. pool: demo-pool # Optional. Use to create the snapshot on a different pool than the source. SpaceEfficiency: thin # Optional. Use to create the snapshot with a different space efficiency than the source. diff --git a/docs/content/configuration/creating_volumestorageclass.md b/docs/content/configuration/creating_volumestorageclass.md new file mode 100644 index 000000000..6f41a2ee8 --- /dev/null +++ b/docs/content/configuration/creating_volumestorageclass.md @@ -0,0 +1,69 @@ +# Creating a StorageClass + +Create a storage class YAML file in order to define the storage parameters, such as pool name, secret reference, `SpaceEfficiency`, and `fstype`. + +**Note:** If you are using the CSI Topology feature, in addition to the information and parameter definitions provided here, be sure to follow the steps in [Creating a StorageClass with topology awareness](creating_storageclass_topology_aware.md). + +Use the following procedure to create and apply the storage classes. + +**Note:** This procedure is applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. + +Create a storage class YAML file, similar to the following `demo-storageclass.yaml` and update the storage parameters as needed. + +When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](creating_secret.md). + +Use the `SpaceEfficiency` parameters for each storage system, as defined in [the following table](#spaceefficiency). These values are not case-sensitive. + +#### `SpaceEfficiency` parameter definitions per storage system type + +|Storage system type|SpaceEfficiency parameter options| +|-------------------|---------------------------------| +|IBM FlashSystem® A9000 and A9000R|Always includes deduplication and compression. No need to specify during configuration.| +|IBM Spectrum® Virtualize family|- `thick` (default value)
- `thin`
- `compressed`
- `dedup_thin` (creates volumes that are deduplicated with thin-provisioning)
- `dedup_compressed` (creates deduplicated and compressed volumes)

**Note:**
- The `deduplicated` value is deprecated. Use `dedup_compressed`, if possible. When used, `deduplicated` provide the same results as `dedup_compressed`.
- If not specified, the default value is `thick`.| +|IBM® DS8000® family| - `none` (default value)
- `thin`

**Note:** If not specified, the default value is `none`.| + +- The IBM DS8000 family `pool` value is the pool ID and not the pool name as is used in other storage systems. +- Be sure that the `pool` value is the name of an existing pool on the storage system. +- To create a volume with HyperSwap on IBM Spectrum Virtualize storage systems, put a colon (:) between the two pools within the `pool` value. For example: + + ``` + pool: demo-pool1:demo-pool2 + ``` + **Important:** The two pools must be from different sites. + + For more information about the HyperSwap limitations and requirements, see [Limitations](../release_notes/limitations.md) within the release notes and [Compatibility and requirements](../installation/install_compatibility_requirements.md) within this guide. + +- The `allowVolumeExpansion` parameter is optional but is necessary for using volume expansion. The default value is _false_. + + **Note:** Be sure to set the value to _true_ to allow volume expansion. + +- The `csi.storage.k8s.io/fstype` parameter is optional. The values that are allowed are _ext4_ or _xfs_. The default value is _ext4_. +- The `volume_name_prefix` parameter is optional. + + **Note:** + For IBM DS8000 family, the maximum prefix length is five characters. The maximum prefix length for other systems is 20 characters.

For storage systems that use Spectrum Virtualize, the `CSI` prefix is added as default if not specified by the user. + + + kind: StorageClass + apiVersion: storage.k8s.io/v1 + metadata: + name: demo-storageclass + provisioner: block.csi.ibm.com + parameters: + pool: demo-pool + SpaceEfficiency: thin # Optional. + volume_name_prefix: demo-prefix # Optional. + + csi.storage.k8s.io/fstype: xfs # Optional. Values ext4/xfs. The default is ext4. + csi.storage.k8s.io/secret-name: demo-secret + csi.storage.k8s.io/secret-namespace: default + allowVolumeExpansion: true + + +Apply the storage class. + + ``` + kubectl apply -f .yaml + ``` + +The `storageclass.storage.k8s.io/ created` message is emitted. \ No newline at end of file diff --git a/docs/content/configuration/csi_ug_config.md b/docs/content/configuration/csi_ug_config.md deleted file mode 100644 index 5cab8e384..000000000 --- a/docs/content/configuration/csi_ug_config.md +++ /dev/null @@ -1,19 +0,0 @@ -# CSI driver configuration - -Use this information to configure the IBM® block storage CSI driver after installation. - -Once the driver is installed and running (see [Installing the operator and driver](../installation/csi_ug_install_operator.md)), in order to use the driver and run stateful applications using IBM block storage systems, the relevant YAML files must be created. - -Multiple YAML files per type can be created (with different configurations), according to your storage needs. - -- [Creating a Secret](csi_ug_config_create_secret.md) -- [Creating a StorageClass](csi_ug_config_create_storageclasses.md) -- [Creating a PersistentVolumeClaim (PVC)](csi_ug_config_create_pvc.md) -- [Creating a StatefulSet](csi_ug_config_create_statefulset.md) -- [Creating a VolumeSnapshotClass](csi_ug_config_create_vol_snapshotclass.md) -- [Creating a VolumeSnapshot](csi_ug_config_create_snapshots.md) -- [Creating a VolumeReplicationClass](csi_ug_config_create_vol_replicationclass.md) -- [Creating a VolumeReplication](csi_ug_config_create_replication.md) -- [Expanding a PersistentVolumeClaim (PVC)](csi_ug_config_expand_pvc.md) -- [Configuring for CSI Topology](csi_ug_config_topology.md) -- [Advanced configuration](csi_ug_config_advanced.md) \ No newline at end of file diff --git a/docs/content/configuration/csi_ug_config_create_storageclasses.md b/docs/content/configuration/csi_ug_config_create_storageclasses.md deleted file mode 100644 index 750dc8d3e..000000000 --- a/docs/content/configuration/csi_ug_config_create_storageclasses.md +++ /dev/null @@ -1,59 +0,0 @@ -# Creating a StorageClass - -Create a storage class YAML file in order to define the storage parameters, such as pool name, secret reference, `SpaceEfficiency`, and `fstype`. - -**Note:** If you are using the CSI Topology feature, in addition to the information and parameter definitions provided here, be sure to follow the steps in [Creating a StorageClass with topology awareness](csi_ug_config_create_storageclasses_topology.md). - -Use the following procedure to create and apply the storage classes. - -**Note:** This procedure is applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. - -Create a storage class YAML file, similar to the following `demo-storageclass.yaml` and update the storage parameters as needed. - -When configuring the file, be sure to use the same array secret and array secret namespace as defined in [Creating a Secret](csi_ug_config_create_secret.md). - -Use the `SpaceEfficiency` parameters for each storage system, as defined in [the following table](#spaceefficiency). These values are not case-sensitive. - -_**Table:** `SpaceEfficiency` parameter definitions per storage system type_ - -|Storage system type|SpaceEfficiency parameter options| -|-------------------|---------------------------------| -|IBM FlashSystem® A9000 and A9000R|Always includes deduplication and compression. No need to specify during configuration.| -|IBM Spectrum® Virtualize Family|- `thick` (default value)
- `thin`
- `compressed`
- `deduplicated`

**Note:** If not specified, the default value is thick.| -|IBM® DS8000® Family| - `none` (default value)
- `thin`

**Note:** If not specified, the default value is `none`.| - -- The IBM DS8000 Family `pool` value is the pool ID and not the pool name as is used in other storage systems. -- Be sure that the `pool` value is the name of an existing pool on the storage system. -- The `allowVolumeExpansion` parameter is optional but is necessary for using volume expansion. The default value is _false_. - -**Note:** Be sure to set the value to true to allow volume expansion. - -- The `csi.storage.k8s.io/fstype` parameter is optional. The values that are allowed are _ext4_ or _xfs_. The default value is _ext4_. -- The `volume_name_prefix` parameter is optional. - -**Note:** For IBM DS8000 Family, the maximum prefix length is 5 characters. The maximum prefix length for other systems is 20 characters.

For storage systems that use Spectrum Virtualize, the `CSI` prefix is added as default if not specified by the user. - - - kind: StorageClass - apiVersion: storage.k8s.io/v1 - metadata: - name: demo-storageclass - provisioner: block.csi.ibm.com - parameters: - pool: demo-pool - SpaceEfficiency: thin # Optional. - volume_name_prefix: demo-prefix # Optional. - - csi.storage.k8s.io/fstype: xfs # Optional. Values ext4/xfs. The default is ext4. - csi.storage.k8s.io/secret-name: demo-secret - csi.storage.k8s.io/secret-namespace: default - allowVolumeExpansion: true - - -Apply the storage class. - - ``` - kubectl apply -f .yaml - ``` - -The `storageclass.storage.k8s.io/ created` message is emitted. \ No newline at end of file diff --git a/docs/content/configuration/csi_ug_config_topology.md b/docs/content/configuration/csi_ug_config_topology.md deleted file mode 100644 index a7d09fe7d..000000000 --- a/docs/content/configuration/csi_ug_config_topology.md +++ /dev/null @@ -1,9 +0,0 @@ -# Configuring for CSI Topology - -Use this information for specific configuring information when using CSI Topology with the IBM® block storage CSI driver. - -**Important:** Be sure that all of the topology requirements are met before starting. For more information, see [Compatibility and requirements](../installation/csi_ug_requirements.md). - -- [Creating a Secret with topology awareness](csi_ug_config_create_secret_topology.md) -- [Creating a StorageClass with topology awareness](csi_ug_config_create_storageclasses_topology.md) -- [Creating a VolumeSnapshotClass with topology awareness](csi_ug_config_create_vol_snapshotclass_topology.md) \ No newline at end of file diff --git a/docs/content/configuration/csi_ug_config_expand_pvc.md b/docs/content/configuration/expanding_pvc.md similarity index 72% rename from docs/content/configuration/csi_ug_config_expand_pvc.md rename to docs/content/configuration/expanding_pvc.md index e94b2a81a..f59e8ade1 100644 --- a/docs/content/configuration/csi_ug_config_expand_pvc.md +++ b/docs/content/configuration/expanding_pvc.md @@ -2,9 +2,9 @@ Use this information to expand existing volumes. -**Important:** Before expanding an existing volume, be sure that the relevant StorageClass `.yaml` `allowVolumeExpansion` parameter is set to true. For more information, see [Creating a StorageClass](csi_ug_config_create_storageclasses.md). +**Important:** Before expanding an existing volume, be sure that the relevant StorageClass `allowVolumeExpansion` parameter is set to true. For more information, see [Creating a StorageClass](creating_volumestorageclass.md). -To expand an existing volume, open the relevant PersistentVolumeClaim (PVC) YAML file and increase the `storage` parameter value. For example, if the current `storage` value is set to _1Gi_, you can change it to _10Gi_, as needed. For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](csi_ug_config_create_pvc.md). +To expand an existing volume, open the relevant PersistentVolumeClaim (PVC) YAML file and increase the `storage` parameter value. For example, if the current `storage` value is set to _1Gi_, you can change it to _10Gi_, as needed. For more information about PVC configuration, see [Creating a PersistentVolumeClaim (PVC)](creating_pvc.md). Be sure to use the `kubectl apply` command in order to apply your changes. diff --git a/docs/content/configuration/csi_ug_config_replication_find_systemid.md b/docs/content/configuration/finding_systemid.md similarity index 100% rename from docs/content/configuration/csi_ug_config_replication_find_systemid.md rename to docs/content/configuration/finding_systemid.md diff --git a/docs/content/configuration/csi_ug_config_advanced_importvol.md b/docs/content/configuration/importing_existing_volume.md similarity index 90% rename from docs/content/configuration/csi_ug_config_advanced_importvol.md rename to docs/content/configuration/importing_existing_volume.md index 82e7cd7bb..fc7c9942c 100644 --- a/docs/content/configuration/csi_ug_config_advanced_importvol.md +++ b/docs/content/configuration/importing_existing_volume.md @@ -8,14 +8,14 @@ Before starting to import an existing volume, find the following information in Including: - - `pool_name`: _Name of Pool where volume is located_ (Listed as `pool_id` for DS8000® Family systems.) + - `pool_name`: _Name of Pool where volume is located_ (Listed as `pool_id` for DS8000® family systems.) - `storage_type`: <`SVC` | `A9000` | `DS8K`> - `volume_name`: _Volume name_ - `array_address`: _Array address_ To find the `volumeHandle`, use one of the following procedures: -- **For Spectrum Virtualize Family** +- **For Spectrum Virtualize family** The `volumeHandle` is formatted as `SVC:id;vdisk_UID`. @@ -60,7 +60,7 @@ To find the `volumeHandle`, use one of the following procedures: For more information, see [IBM Hyper-Scale Manager documentation](https://www.ibm.com/docs/en/hyper-scale-manager/). -- **For DS8000 Family:** +- **For DS8000 family:** The `volumeHandle` is formatted as `DS8K:id;GUID`. The `id` is the last four digits of the `GUID`. @@ -81,12 +81,12 @@ To find the `volumeHandle`, use one of the following procedures: The Properties window is displayed. Use the **GUID** value. - For more information about DS8000 Family products, find your product information in [IBM Documentation](https://www.ibm.com/docs/). + For more information about DS8000 family products, find your product information in [IBM Documentation](https://www.ibm.com/docs/). Use this procedure to help build a PV YAML file for your volumes. -**Note:** These steps are set up for importing volumes from a Spectrum Virtualize Family system. Change parameters, as needed. +**Note:** These steps are set up for importing volumes from a Spectrum Virtualize family system. Change parameters, as needed. 1. Create a persistent volume (PV) YAML file. @@ -94,7 +94,7 @@ Use this procedure to help build a PV YAML file for your volumes. 2. Take the `volume_name` and other optional information (collected before the procedure) and insert it into the YAML file (under `spec.csi.volumeAttributes`). - **Important:** If using the CSI Topology feature, the `spec.csi.volumeHandle` contains the management ID (see [Creating a StorageClass with topology awareness](csi_ug_config_create_storageclasses_topology.md)). In the example below, the `spec.csi.volumeHandle` would read similar to the following: `SVC:demo-system-id-1:0;600507640082000B08000000000004FF`. + **Important:** If using the CSI Topology feature, the `spec.csi.volumeHandle` contains the management ID (see [Creating a StorageClass with topology awareness](creating_storageclass_topology_aware.md)). In the example below, the `spec.csi.volumeHandle` would read similar to the following: `SVC:demo-system-id-1:0;600507640082000B08000000000004FF`. apiVersion: v1 kind: PersistentVolume @@ -127,7 +127,7 @@ Use this procedure to help build a PV YAML file for your volumes. **Note:** - Be sure to include the `storageClassName`. - - For more information about creating a PVC YAML file, see [Creating a PersistentVolumeClaim (PVC)](csi_ug_config_create_pvc.md). + - For more information about creating a PVC YAML file, see [Creating a PersistentVolumeClaim (PVC)](creating_pvc.md). ``` apiVersion: v1 diff --git a/docs/content/installation/csi_ug_install_intro.md b/docs/content/installation/csi_ug_install_intro.md deleted file mode 100644 index d0c55c850..000000000 --- a/docs/content/installation/csi_ug_install_intro.md +++ /dev/null @@ -1,11 +0,0 @@ -# Installation - -Download and install the IBM® block storage CSI driver installation package your container platform (such as Kubernetes), as described in the following sections. - -- [Compatibility and requirements](csi_ug_requirements.md) -- [Installing the operator and driver](csi_ug_install_operator.md) -- [Upgrading the CSI driver](csi_ug_upgrade.md) - -For information about uninstallation, see [Uninstalling](csi_ug_uninstall.md). - - diff --git a/docs/content/installation/csi_ug_requirements.md b/docs/content/installation/install_compatibility_requirements.md similarity index 61% rename from docs/content/installation/csi_ug_requirements.md rename to docs/content/installation/install_compatibility_requirements.md index 53e8260ea..23937a586 100644 --- a/docs/content/installation/csi_ug_requirements.md +++ b/docs/content/installation/install_compatibility_requirements.md @@ -8,24 +8,22 @@ For IBM Cloud® Satellite users, see [cloud.ibm.com/docs/satellite](https://clou **Important:** When using Satellite, complete the following checks, configurations, and the installation process before assigning the hosts to your locations.
In addition, **do not** create a Kubernetes cluster. Creating the Kubernetes cluster is done through Satellite. -- The CSI driver requires the following ports to be opened on the worker nodes OS firewall: - - **For all iSCSI users** +The CSI driver requires the following ports to be opened on the worker nodes OS firewall: + - **For all iSCSI users** Port 3260 - - **FlashSystem A9000 and A9000R** + - **FlashSystem A9000 and A9000R** Port 7778 - - **IBM Spectrum® Virtualize Family includes IBM® SAN Volume Controller and IBM FlashSystem® family members that are built with IBM Spectrum® Virtualize (including FlashSystem 5xxx, 7200, 9100, 9200, 9200R)** + - **IBM Spectrum® Virtualize family includes IBM® SAN Volume Controller and IBM FlashSystem® family members that are built with IBM Spectrum® Virtualize (including FlashSystem 5xxx, 7200, 9100, 9200, 9200R)** Port 22 - - **DS8000® Family systems** + - **DS8000® family systems** - Port 8452 - -- Be sure that multipathing is installed and running. + Port 8452 Complete these steps for each worker node in Kubernetes cluster to prepare your environment for installing the CSI (Container Storage Interface) driver. @@ -33,7 +31,7 @@ Complete these steps for each worker node in Kubernetes cluster to prepare your **Important:** Be sure to configure each worker with storage connectivity according to your storage system instructions. For more information, find your storage system documentation in [IBM Documentation](http://www.ibm.com/docs/). - **Additional configuration steps for OpenShift® Container Platform users (RHEL and RHCOS).** Other users can continue to step 3. + **Additional configuration steps for OpenShift® Container Platform users (RHEL and RHCOS).** Other users can skip these additional configuration steps. Download and save the following YAML file: @@ -43,28 +41,37 @@ Complete these steps for each worker node in Kubernetes cluster to prepare your This file can be used for both Fibre Channel and iSCSI configurations. To support iSCSI, uncomment the last two lines in the file. - **Important:** The `99-ibm-attach.yaml` configuration file overrides any files that exist on your system. Only use this file if the files mentioned are not already created.
If one or more were created, edit this YAML file, as necessary. + **Important:** + - The `99-ibm-attach.yaml` configuration file overrides any files that exist on your system. Only use this file if the files mentioned are not already created.
If one or more were created, edit this YAML file, as necessary. + - The `99-ibm-attach.yaml` configuration file with the default configuration by the CSI driver. It is best practice to update the file according to your storage system and application networking needs. Apply the YAML file. `oc apply -f 99-ibm-attach.yaml` -2. Configure storage system connectivity. - - 1. Define the host of each Kubernetes node on the relevant storage systems with the valid WWPN (for Fibre Channel) or IQN (for iSCSI) of the node. +2. Configure your storage system host attachment. - 2. For Fibre Channel, configure the relevant zoning from the storage to the host. + **Important:** The CSI driver does not define hosts on your storage system. + + Be sure to configure your storage system host attachment according to your storage system instructions. - 3. Ensure proper connectivity. + The CSI driver supports the following connectivity for each worker node: Fibre Channel (WWPN), NVMe®/FC (NQN), and iSCSI (IQN). + + **Note:** + - The CSI driver supports NVMe®/FC only on IBM Spectrum Virtualize family products. + - For Fibre Channel connectivity be sure that storage system is using one of the fully supported HBAs compatible with your host connection, as listed in the [IBM® System Storage® Interoperation Center (SSIC)](https://www-03.ibm.com/systems/support/storage/ssic/interoperability.wss). + - The CSI driver supports IBM DS8000 family storage systems only with Fibre Channel connectivity. + + For more information, find your storage system documentation in [IBM Documentation](http://www.ibm.com/docs/). 3. **For RHEL OS users:** Ensure that the following packages are installed. If using RHCOS or if the packages are already installed, this step may be skipped. - - sg3_utils - - iscsi-initiator-utils - - device-mapper-multipath - - xfsprogs (if XFS file system is required) + - sg3_utils + - iscsi-initiator-utils + - device-mapper-multipath + - xfsprogs (if XFS file system is required) 4. (Optional) If planning on using volume snapshots (FlashCopy® function), enable support on your Kubernetes cluster. @@ -79,10 +86,10 @@ Complete these steps for each worker node in Kubernetes cluster to prepare your 1. To enable support on your Kubernetes cluster, install the following replication CRDs once per cluster. ``` - curl -O https://raw.githubusercontent.com/csi-addons/volume-replication-operator/v0.1.0/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml + curl -O https://raw.githubusercontent.com/csi-addons/volume-replication-operator/v0.2.0/config/crd/bases/replication.storage.openshift.io_volumereplicationclasses.yaml kubectl apply -f ./replication.storage.openshift.io_volumereplicationclasses.yaml - curl -O https://raw.githubusercontent.com/csi-addons/volume-replication-operator/v0.1.0/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml + curl -O https://raw.githubusercontent.com/csi-addons/volume-replication-operator/v0.2.0/config/crd/bases/replication.storage.openshift.io_volumereplications.yaml kubectl apply -f ./replication.storage.openshift.io_volumereplications.yaml ```` @@ -92,4 +99,6 @@ Complete these steps for each worker node in Kubernetes cluster to prepare your **Important:** This label-prefix must be found on the nodes in the cluster **before** installing the IBM® block storage CSI driver. If the nodes do not have the proper label-prefix before installation, CSI Topology cannot be used with the CSI driver. - For more information, see [Configuring for CSI Topology](../configuration/csi_ug_config_topology.md). \ No newline at end of file + For more information, see [Configuring for CSI Topology](../configuration/configuring_topology.md). + +7. (Optional) If planning on using HyperSwap on your storage system, see the following section within your Spectrum Virtualize product documentation on [IBM Documentation](https://www.ibm.com/docs/en/): **Planning** > **Planning for high availability** > **Planning for a HyperSwap topology system**. \ No newline at end of file diff --git a/docs/content/installation/csi_ug_install_operator_github.md b/docs/content/installation/install_driver_github.md similarity index 92% rename from docs/content/installation/csi_ug_install_operator_github.md rename to docs/content/installation/install_driver_github.md index ef71d8ce8..3bd8fbdc8 100644 --- a/docs/content/installation/csi_ug_install_operator_github.md +++ b/docs/content/installation/install_driver_github.md @@ -11,7 +11,7 @@ Use the following steps to install the operator and driver, with [GitHub](https: 1. Download the manifest from GitHub. ``` - curl https://raw.githubusercontent.com/IBM/ibm-block-csi-operator/v1.7.0/deploy/installer/generated/ibm-block-csi-operator.yaml > ibm-block-csi-operator.yaml + curl https://raw.githubusercontent.com/IBM/ibm-block-csi-operator/v1.8.0/deploy/installer/generated/ibm-block-csi-operator.yaml > ibm-block-csi-operator.yaml ``` 2. (Optional) Update the image fields in the `ibm-block-csi-operator.yaml`. @@ -37,7 +37,7 @@ Use the following steps to install the operator and driver, with [GitHub](https: 1. Download the manifest from GitHub. ``` - curl https://raw.githubusercontent.com/IBM/ibm-block-csi-operator/v1.7.0/config/samples/csi.ibm.com_v1_ibmblockcsi_cr.yaml > csi.ibm.com_v1_ibmblockcsi_cr.yaml + curl https://raw.githubusercontent.com/IBM/ibm-block-csi-operator/v1.8.0/config/samples/csi.ibm.com_v1_ibmblockcsi_cr.yaml > csi.ibm.com_v1_ibmblockcsi_cr.yaml ``` 2. (Optional) Update the image repository field, tag field, or both in the `csi.ibm.com_v1_ibmblockcsi_cr.yaml`. @@ -52,7 +52,7 @@ Use the following steps to install the operator and driver, with [GitHub](https: 4. Verify that the driver is running: ``` - $> kubectl get pods -n -l csi + $> kubectl get pods -n -l product=ibm-block-csi-driver NAME READY STATUS RESTARTS AGE ibm-block-csi-controller-0 7/7 Running 0 9m36s ibm-block-csi-node-jvmvh 3/3 Running 0 9m36s diff --git a/docs/content/installation/csi_ug_install_operator_openshift.md b/docs/content/installation/install_driver_openshift_web.md similarity index 100% rename from docs/content/installation/csi_ug_install_operator_openshift.md rename to docs/content/installation/install_driver_openshift_web.md diff --git a/docs/content/installation/csi_ug_install_operator_operatorhub.md b/docs/content/installation/install_driver_operatorhub.md similarity index 100% rename from docs/content/installation/csi_ug_install_operator_operatorhub.md rename to docs/content/installation/install_driver_operatorhub.md diff --git a/docs/content/installation/csi_ug_install_operator.md b/docs/content/installation/install_operator_driver.md similarity index 71% rename from docs/content/installation/csi_ug_install_operator.md rename to docs/content/installation/install_operator_driver.md index b65e6d422..033ff8cfe 100644 --- a/docs/content/installation/csi_ug_install_operator.md +++ b/docs/content/installation/install_operator_driver.md @@ -4,9 +4,9 @@ Install the operator for IBM® block storage CSI driver in order to deploy, inst The CSI operator and driver can be downloaded in one of the following ways: -- With the OpenShift web console (see [Installing the driver with the OpenShift web console](csi_ug_install_operator_openshift.md)). -- With GitHub (see [Installing the driver with GitHub](csi_ug_install_operator_github.md)). -- With OperatorHub.io (see [Installing the driver with OperatorHub.io](csi_ug_install_operator_operatorhub.md)). +- With the OpenShift web console (see [Installing the driver with the OpenShift web console](install_driver_openshift_web.md)). +- With GitHub (see [Installing the driver with GitHub](install_driver_github.md)). +- With OperatorHub.io (see [Installing the driver with OperatorHub.io](install_driver_operatorhub.md)). - With the IBM Cloud® Satellite web console. For more information, see [cloud.ibm.com/docs/satellite](https://cloud.ibm.com/docs/satellite). diff --git a/docs/content/installation/installation.md b/docs/content/installation/installation.md new file mode 100644 index 000000000..12c7cb3a2 --- /dev/null +++ b/docs/content/installation/installation.md @@ -0,0 +1,11 @@ +# Installing + +Download and install the IBM® block storage CSI driver installation package for your container platform (such as Kubernetes), as described in the following sections. + +- [Compatibility and requirements](install_compatibility_requirements.md) +- [Installing the operator and driver](install_operator_driver.md) +- [Upgrading the CSI driver](upgrade.md) + +For information about uninstallation, see [Uninstalling](uninstalling.md). + + diff --git a/docs/content/installation/csi_ug_uninstall_github.md b/docs/content/installation/uninstall_driver_github.md similarity index 100% rename from docs/content/installation/csi_ug_uninstall_github.md rename to docs/content/installation/uninstall_driver_github.md diff --git a/docs/content/installation/csi_ug_uninstall_openshift.md b/docs/content/installation/uninstall_driver_openshift_web.md similarity index 84% rename from docs/content/installation/csi_ug_uninstall_openshift.md rename to docs/content/installation/uninstall_driver_openshift_web.md index cc62f169c..aff25eda3 100644 --- a/docs/content/installation/csi_ug_uninstall_openshift.md +++ b/docs/content/installation/uninstall_driver_openshift_web.md @@ -17,7 +17,6 @@ Perform the following steps in order to uninstall the CSI driver and operator th This deletes the CSI driver. Continue to step [5](#operator) to delete the operator for IBM block storage CSI driver. -5. From the **Installed Operators** page, click on the **more** menu for the **Operator for IBM block storage CSI driver** and select **Uninstall Operator**. - +5. From the **Installed Operators** page, click on the **more** menu for the **Operator for IBM block storage CSI driver** and select **Uninstall Operator**. diff --git a/docs/content/installation/csi_ug_uninstall_operatorhub.md b/docs/content/installation/uninstall_driver_operatorhub.md similarity index 100% rename from docs/content/installation/csi_ug_uninstall_operatorhub.md rename to docs/content/installation/uninstall_driver_operatorhub.md diff --git a/docs/content/installation/csi_ug_uninstall.md b/docs/content/installation/uninstalling.md similarity index 77% rename from docs/content/installation/csi_ug_uninstall.md rename to docs/content/installation/uninstalling.md index 1b1768f72..9f66ddf2d 100644 --- a/docs/content/installation/csi_ug_uninstall.md +++ b/docs/content/installation/uninstalling.md @@ -6,9 +6,9 @@ The CSI operator and driver can be uninstalled in one of the following ways: **Note:** Be sure to use the corresponding uninstall method to operator and driver installation originally used. -- With the OpenShift web console (see [Uninstalling the driver with the OpenShift web console](csi_ug_uninstall_openshift.md)). -- With GitHub (see [Uninstalling the driver with GitHub](csi_ug_uninstall_github.md)). -- With OperatorHub.io (see [Uninstalling the driver with OperatorHub.io](csi_ug_uninstall_operatorhub.md)). +- With the OpenShift web console (see [Uninstalling the driver with the OpenShift web console](uninstall_driver_openshift_web.md)). +- With GitHub (see [Uninstalling the driver with GitHub](uninstall_driver_github.md)). +- With OperatorHub.io (see [Uninstalling the driver with OperatorHub.io](uninstall_driver_operatorhub.md)). - With the IBM Cloud® Satellite web console. To uninstall from IBM Cloud® Satellite web console, **Remove** the CSI driver subscription. For more information, see [cloud.ibm.com/docs/satellite](https://cloud.ibm.com/docs/satellite). diff --git a/docs/content/installation/csi_ug_upgrade.md b/docs/content/installation/upgrade.md similarity index 86% rename from docs/content/installation/csi_ug_upgrade.md rename to docs/content/installation/upgrade.md index 85d7ee7fd..a02ba6d0a 100644 --- a/docs/content/installation/csi_ug_upgrade.md +++ b/docs/content/installation/upgrade.md @@ -9,9 +9,9 @@ Use this information to upgrade the IBM® block storage CSI driver. **Note:** For more information about automatic upgrades, see https://olm.operatorframework.io/docs/concepts/crds/subscription/. -- To manually upgrade the CSI driver with the OpenShift web console, see [Manual upgrade with OpenShift](csi_ug_upgrade_ocp_manual.md). +- To manually upgrade the CSI driver with the OpenShift web console, see [Manual upgrade with OpenShift](upgrade_manual_openshift.md). -- To manually upgrade the CSI (Container Storage Interface) driver from a previous version with GitHub, perform step 1 of the [installation procedure](csi_ug_install_operator_github.md) for the latest version. +- To manually upgrade the CSI (Container Storage Interface) driver from a previous version with GitHub, perform step 1 of the [installation procedure](install_driver_github.md) for the latest version. diff --git a/docs/content/installation/csi_ug_upgrade_ocp_manual.md b/docs/content/installation/upgrade_manual_openshift.md similarity index 100% rename from docs/content/installation/csi_ug_upgrade_ocp_manual.md rename to docs/content/installation/upgrade_manual_openshift.md diff --git a/docs/content/csi_overview.md b/docs/content/overview.md similarity index 100% rename from docs/content/csi_overview.md rename to docs/content/overview.md diff --git a/docs/content/release_notes/csi_rn_changelog.md b/docs/content/release_notes/change_log.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog.md rename to docs/content/release_notes/change_log.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.0.0.md b/docs/content/release_notes/changelog_1.0.0.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog_1.0.0.md rename to docs/content/release_notes/changelog_1.0.0.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.1.0.md b/docs/content/release_notes/changelog_1.1.0.md similarity index 83% rename from docs/content/release_notes/csi_rn_changelog_1.1.0.md rename to docs/content/release_notes/changelog_1.1.0.md index 84a73b56a..543fd0763 100644 --- a/docs/content/release_notes/csi_rn_changelog_1.1.0.md +++ b/docs/content/release_notes/changelog_1.1.0.md @@ -2,7 +2,7 @@ IBM® block storage CSI driver 1.1.0 provided a range of enhancements: -- Added support for DS8000® Family storage systems +- Added support for DS8000® family storage systems - RHCOS support - Now supports Kubernetes 1.16 and Red Hat® OpenShift® 4.3 - IBM Z® architecture support diff --git a/docs/content/release_notes/csi_rn_changelog_1.2.0.md b/docs/content/release_notes/changelog_1.2.0.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog_1.2.0.md rename to docs/content/release_notes/changelog_1.2.0.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.3.0.md b/docs/content/release_notes/changelog_1.3.0.md similarity index 92% rename from docs/content/release_notes/csi_rn_changelog_1.3.0.md rename to docs/content/release_notes/changelog_1.3.0.md index 0f3854ea8..317bdc74d 100644 --- a/docs/content/release_notes/csi_rn_changelog_1.3.0.md +++ b/docs/content/release_notes/changelog_1.3.0.md @@ -10,4 +10,4 @@ IBM® block storage CSI driver 1.3.0 provided a range of enhancements: |Ticket ID|Severity|Description| |---------|--------|-----------| |**CSI-1672**|Moderate|**Fixed:** In rare cases, if the volume devices have an unexpected `udev` path on the node host, the CSI driver may not be able to find the device mapper in order to mount the volume.| -|**CSI-1658**|Moderate|**Fixed:** In some cases, when mounting a volume through the CSI driver on a Spectrum Virtualize Family system, the same LUN ID may be defined on different I/O groups on the same storage system. This causes the volume mount to fail.| \ No newline at end of file +|**CSI-1658**|Moderate|**Fixed:** In some cases, when mounting a volume through the CSI driver on a Spectrum Virtualize family system, the same LUN ID may be defined on different I/O groups on the same storage system. This causes the volume mount to fail.| \ No newline at end of file diff --git a/docs/content/release_notes/csi_rn_changelog_1.4.0.md b/docs/content/release_notes/changelog_1.4.0.md similarity index 93% rename from docs/content/release_notes/csi_rn_changelog_1.4.0.md rename to docs/content/release_notes/changelog_1.4.0.md index 3a126a1b2..dd74d645e 100644 --- a/docs/content/release_notes/csi_rn_changelog_1.4.0.md +++ b/docs/content/release_notes/changelog_1.4.0.md @@ -10,7 +10,7 @@ IBM® block storage CSI driver 1.4.0 provided a range of enhancements and resolv |Ticket ID|Severity|Description| |---------|--------|-----------| |**CSI-2156**|Service|**Fixed:** IBM block storage driver node registration may encounter an error when the `node_id` exceeds 128 bytes.| -|**CSI-1842**|Service|**Fixed:** When creating a new volume on a DS8000® Family storage system, if an error occurs during PersistentVolumeClaim (PVC) attachment, the attachment retry may fail.| +|**CSI-1842**|Service|**Fixed:** When creating a new volume on a DS8000® family storage system, if an error occurs during PersistentVolumeClaim (PVC) attachment, the attachment retry may fail.| |**CSI-645**|Low|**Fixed:** In some cases, during high-scale operations, such as pod creation with many PersistentVolumeClaims (PVCs), the "ibm-block-csi-controller-0" controller pod restarts.| diff --git a/docs/content/release_notes/csi_rn_changelog_1.5.0.md b/docs/content/release_notes/changelog_1.5.0.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog_1.5.0.md rename to docs/content/release_notes/changelog_1.5.0.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.5.1.md b/docs/content/release_notes/changelog_1.5.1.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog_1.5.1.md rename to docs/content/release_notes/changelog_1.5.1.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.6.0.md b/docs/content/release_notes/changelog_1.6.0.md similarity index 100% rename from docs/content/release_notes/csi_rn_changelog_1.6.0.md rename to docs/content/release_notes/changelog_1.6.0.md diff --git a/docs/content/release_notes/csi_rn_changelog_1.7.0.md b/docs/content/release_notes/changelog_1.7.0.md similarity index 61% rename from docs/content/release_notes/csi_rn_changelog_1.7.0.md rename to docs/content/release_notes/changelog_1.7.0.md index c5df058a1..430457aa1 100644 --- a/docs/content/release_notes/csi_rn_changelog_1.7.0.md +++ b/docs/content/release_notes/changelog_1.7.0.md @@ -1,6 +1,6 @@ # 1.7.0 (September 2021) -IBM® block storage CSI driver 1.7.0 adds new support and enhancements: +IBM® block storage CSI driver 1.7.0 added new support and enhancements: - Now supports the CSI Topology feature -- New volume replication (remote copy) support for IBM Spectrum Virtualize Family storage systems +- New volume replication (remote copy) support for IBM Spectrum Virtualize family storage systems - Additional support for Kubernetes 1.22 \ No newline at end of file diff --git a/docs/content/release_notes/changelog_1.8.0.md b/docs/content/release_notes/changelog_1.8.0.md new file mode 100644 index 000000000..bdd121b86 --- /dev/null +++ b/docs/content/release_notes/changelog_1.8.0.md @@ -0,0 +1,10 @@ +# 1.8.0 (December 2021) + +IBM® block storage CSI driver 1.8.0 adds new support and enhancements: +- New support and enhancements for IBM Spectrum Virtualize family storage systems: + - New HyperSwap support + - New NVMe®/FC support + - Increased StorageClass `SpaceEfficiency` parameter capabilities +- Added custom resource configurability for the CSI driver health port +- Additional support for OpenShift 4.9 +- Reintroduces support for OpenShift 4.7 \ No newline at end of file diff --git a/docs/content/release_notes/csi_rn_compatibility.md b/docs/content/release_notes/compatibility_requirements.md similarity index 68% rename from docs/content/release_notes/csi_rn_compatibility.md rename to docs/content/release_notes/compatibility_requirements.md index 2952aebb1..537392b82 100644 --- a/docs/content/release_notes/csi_rn_compatibility.md +++ b/docs/content/release_notes/compatibility_requirements.md @@ -1,3 +1,3 @@ # Compatibility and requirements -This section specifies the compatibility and requirements of version 1.7.0 of IBM® block storage CSI driver. +This section specifies the compatibility and requirements of version 1.8.0 of IBM® block storage CSI driver. diff --git a/docs/content/release_notes/csi_rn_edition_notice.md b/docs/content/release_notes/csi_rn_edition_notice.md deleted file mode 100644 index 6d4b68466..000000000 --- a/docs/content/release_notes/csi_rn_edition_notice.md +++ /dev/null @@ -1,4 +0,0 @@ -# First Edition (September 2021) - -This edition applies to version 1.7.0 of the IBM® block storage CSI driver software package. Newer document editions may be issued for the same product version in order to add missing information, update information, or amend typographical errors. The edition is reset to 'First Edition' for every new product version. - diff --git a/docs/content/release_notes/csi_rn_whatsnew.md b/docs/content/release_notes/csi_rn_whatsnew.md deleted file mode 100644 index 65e20822c..000000000 --- a/docs/content/release_notes/csi_rn_whatsnew.md +++ /dev/null @@ -1,22 +0,0 @@ -# What's new in 1.7.0 - -IBM® block storage CSI driver 1.7.0 introduces the enhancements that are detailed in the following section. - -**General availability date:** 30 September 2021 - -## Now supports CSI Topology - -IBM® block storage CSI driver 1.7.0 is now topology aware. Using this feature, volume access can be limited to a subset of nodes, based on regions and availability zones. Nodes can be located in various regions within an availability zone, or across the different availability zones. Using CSI Topology feature can ease volume provisioning for workloads within a multi-zone architecture. - -For more information, see [CSI Topology Feature](https://kubernetes-csi.github.io/docs/topology.html). - -## New volume replication support for IBM Spectrum Virtualize Family storage systems - -When using IBM Spectrum Virtualize Family storage systems, the CSI driver now supports volume replication (remote copy). - -## Additional support for Kubernetes 1.22 orchestration platforms for deployment - -This version adds support for orchestration platform Kubernetes 1.22, suitable for deployment of the CSI (Container Storage Interface) driver. - - - diff --git a/docs/content/release_notes/csi_rn_knownissues.md b/docs/content/release_notes/known_issues.md similarity index 90% rename from docs/content/release_notes/csi_rn_knownissues.md rename to docs/content/release_notes/known_issues.md index 1874de6c1..86a42d1f4 100644 --- a/docs/content/release_notes/csi_rn_knownissues.md +++ b/docs/content/release_notes/known_issues.md @@ -1,6 +1,6 @@ # Known issues -This section details the known issues in IBM® block storage CSI driver 1.7.0, along with possible solutions or workarounds (if available). +This section details the known issues in IBM® block storage CSI driver 1.8.0, along with possible solutions or workarounds (if available). The following severity levels apply to known issues: @@ -12,8 +12,8 @@ The following severity levels apply to known issues: **Important:** -- **The issues listed below apply to IBM block storage CSI driver 1.7.0**. As long as a newer version has not yet been released, a newer release notes edition for IBM block storage CSI driver 1.7.0 might be issued to provide a more updated list of known issues and workarounds. -- When a newer version is released for general availability, the release notes of this version will no longer be updated. Accordingly, check the release notes of the newer version to learn whether any newly discovered issues affect IBM block storage CSI driver 1.7.0 or whether the newer version resolves any of the issues listed below. +- **The issues listed below apply to IBM block storage CSI driver 1.8.0**. As long as a newer version has not yet been released, a newer release notes edition for IBM block storage CSI driver 1.8.0 might be issued to provide a more updated list of known issues and workarounds. +- When a newer version is released for general availability, the release notes of this version will no longer be updated. Accordingly, check the release notes of the newer version to learn whether any newly discovered issues affect IBM block storage CSI driver 1.8.0 or whether the newer version resolves any of the issues listed below. |Ticket ID|Severity|Description| |---------|--------|-----------| diff --git a/docs/content/release_notes/csi_rn_limitations.md b/docs/content/release_notes/limitations.md similarity index 51% rename from docs/content/release_notes/csi_rn_limitations.md rename to docs/content/release_notes/limitations.md index b766a6f55..ff5c16309 100644 --- a/docs/content/release_notes/csi_rn_limitations.md +++ b/docs/content/release_notes/limitations.md @@ -4,14 +4,16 @@ As opposed to known issues, limitations are functionality restrictions that are ## IBM® DS8000® usage limitations -Connectivity limits on the storage side might be reached with DS8000 Family products due to too many open connections. This occurs due to connection closing lag times from the storage side. +Connectivity limits on the storage side might be reached with DS8000 family products due to too many open connections. This occurs due to connection closing lag times from the storage side. ## Volume snapshot limitations The following limitations apply when using volume snapshots with the IBM block storage CSI driver: - When deleting a PersistentVolumeClaim (PVC), the persistent volume (PV) remains until all snapshots of the specific PV are deleted. -- When using the CSI (Container Storage Interface) driver with IBM Spectrum® Virtualize Family products, a snapshot can only be used to provision a new volume of equal size. +- When using the CSI (Container Storage Interface) driver with IBM Spectrum® Virtualize family products, a snapshot can only be used to provision a new volume of equal size. + +**Note:** For volume snapshot limitations pertaining specifically to HyperSwap usage, see [HyperSwap usage limitations](#hyperSwap-usage-limitations). ## Volume clone limitations @@ -23,13 +25,15 @@ The following limitations apply when using volume clones with the IBM block stor - A PVC and its clone need to both have the same volume mode (**Filesystem** or **Block**). +**Note:** For volume clone limitations pertaining specifically to HyperSwap usage, see [HyperSwap usage limitations](#hyperSwap-usage-limitations). + ## Volume expansion limitations The following limitations apply when expanding volumes with the IBM block storage CSI driver: -- When using the CSI driver with IBM Spectrum Virtualize Family and IBM DS8000 Family products, during size expansion of a PersistentVolumeClaim (PVC), the size remains until all snapshots of the specific PVC are deleted. +- When using the CSI driver with IBM Spectrum Virtualize family and IBM DS8000 family products, during size expansion of a PersistentVolumeClaim (PVC), the size remains until all snapshots of the specific PVC are deleted. - When expanding a PVC while not in use by a pod, the volume size immediately increases on the storage side. However, PVC size only increases after a pod uses the PVC. -- When expanding a filesystem PVC for a volume that was previously formatted but is now no longer being used by a pod, any copy or replication operations performed on the PVC (such as snapshots or cloning) results in a copy with the newer, larger, size on the storage. However, its filesystem has the original, smaller, size. +- When expanding a file system PVC for a volume that was previously formatted but is now no longer being used by a pod, any copy or replication operations performed on the PVC (such as snapshots or cloning) results in a copy with the newer, larger, size on the storage. However, its file system has the original, smaller, size. ## Volume replication limitations @@ -41,4 +45,30 @@ When a role switch is conducted, this is not reflected within the other orchestr 2. Delete the relevant PersistentVolumes. 3. Import the volumes, by using the latest import procedure (version 1.7.0 or later) (see **CSI driver configuration** > **Advanced configuration** > **Importing an existing volume** in the user information). - For more information, see the [Change the Reclaim Policy of a PersistentVolume](https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/) information in the Kubernetes documentation. \ No newline at end of file + For more information, see the [Change the Reclaim Policy of a PersistentVolume](https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/) information in the Kubernetes documentation. + +## HyperSwap usage limitations + +**Important:** The HyperSwap feature is only supported for use with IBM Spectrum Virtualize family storage systems. + +The following IBM block storage CSI driver features are not supported on volumes where HyperSwap is used: + +- A HyperSwap volume cannot be created from a snapshot. + + **Note:** A snapshot can be created from a HyperSwap volume. + - Volume cloning. + +## NVMe®/FC usage limitations + + Red Hat® Enterprise Linux CoreOS (RHCOS) does not support NVMe®/FC. + + For other limitations with your storage system, see the following section within your Spectrum Virtualize product documentation on [IBM Documentation](https://www.ibm.com/docs/en/): **Configuring** > **Host attachment** > **NVMe over Fibre Channel host attachments** > **FC-NVMe limitations and SAN configuration guidelines**. + + ## Volume attach limitations + + In cases where a volume cleanup consistently fails, eventually the orchestrator incorrectly resorts to detaching the volume. As a result, subsequent volume attachment disruptions may occur on the worker node. + + This limitation is tracked in the following places: + +- Red Hat Bug [2022328](https://bugzilla.redhat.com/show_bug.cgi?id=2022328) +- Kubernetes Issue [106710](https://github.com/kubernetes/kubernetes/issues/106710) \ No newline at end of file diff --git a/docs/content/release_notes/csi_rn_supported_orchestration.md b/docs/content/release_notes/supported_orchestration.md similarity index 82% rename from docs/content/release_notes/csi_rn_supported_orchestration.md rename to docs/content/release_notes/supported_orchestration.md index 1c783ef58..888ce5a56 100644 --- a/docs/content/release_notes/csi_rn_supported_orchestration.md +++ b/docs/content/release_notes/supported_orchestration.md @@ -6,9 +6,11 @@ The following table details orchestration platforms suitable for deployment of t |----------------------|-------|------------| |Kubernetes|1.21|x86| |Kubernetes|1.22|x86| +|Red Hat OpenShift|4.7|x86, IBM Z, IBM Power Systems1| |Red Hat OpenShift|4.8|x86, IBM Z, IBM Power Systems1| +|Red Hat OpenShift|4.9|x86, IBM Z, IBM Power Systems1| -1IBM Power Systems architecture is only supported on Spectrum Virtualize and DS8000 Family storage systems. +1IBM Power Systems architecture is only supported on Spectrum Virtualize and DS8000 family storage systems. **Note:** - As of this document's publication date, IBM Cloud® Satellite only supports RHEL 7 on x86 architecture for Red Hat OpenShift. For the latest support information, see [cloud.ibm.com/docs/satellite](https://cloud.ibm.com/docs/satellite). diff --git a/docs/content/release_notes/csi_rn_supported_os.md b/docs/content/release_notes/supported_os.md similarity index 91% rename from docs/content/release_notes/csi_rn_supported_os.md rename to docs/content/release_notes/supported_os.md index 0acdf260c..e85dcdb2c 100644 --- a/docs/content/release_notes/csi_rn_supported_os.md +++ b/docs/content/release_notes/supported_os.md @@ -7,7 +7,7 @@ The following table lists operating systems required for deployment of the IBM® |Red Hat® Enterprise Linux® (RHEL) 7.x|x86, IBM Z®| |Red Hat Enterprise Linux CoreOS (RHCOS)|x86, IBM Z, IBM Power Systems™1| -1IBM Power Systems architecture is only supported on Spectrum Virtualize and DS8000 Family storage systems. +1IBM Power Systems architecture is only supported on Spectrum Virtualize and DS8000 family storage systems. **Note:** For the latest operating system support information, see the [Lifecycle and support matrix](https://www.ibm.com/docs/en/stg-block-csi-driver?topic=SSRQ8T/landing/csi_lifecycle_support_matrix.html). diff --git a/docs/content/release_notes/csi_rn_supported_storage.md b/docs/content/release_notes/supported_storage.md similarity index 69% rename from docs/content/release_notes/csi_rn_supported_storage.md rename to docs/content/release_notes/supported_storage.md index c65710854..18eaf327e 100644 --- a/docs/content/release_notes/csi_rn_supported_storage.md +++ b/docs/content/release_notes/supported_storage.md @@ -1,18 +1,18 @@ # Supported storage systems -IBM® block storage CSI driver 1.7.0 supports different IBM storage systems as listed in the following table. +IBM® block storage CSI driver 1.8.0 supports different IBM storage systems as listed in the following table. |Storage system|Microcode version| |--------------|-----------------| -|IBM FlashSystem™ A9000|12.3.0.a or later| -|IBM FlashSystem A9000R|12.3.0.a or later| -|IBM Spectrum Virtualize™ Family including IBM SAN Volume Controller (SVC) and IBM FlashSystem® family members built with IBM Spectrum® Virtualize (including FlashSystem 5xxx, 7200, 9100, 9200, 9200R)|7.8 and above, 8.x| +|IBM FlashSystem™ A9000|12.3.2.b or later| +|IBM FlashSystem A9000R|12.3.2.b or later| +|IBM Spectrum Virtualize™ family including IBM SAN Volume Controller (SVC) and IBM FlashSystem® family members built with IBM Spectrum® Virtualize (including FlashSystem 5xxx, 7200, 9100, 9200, 9200R)|7.8 and above, 8.x| |IBM Spectrum Virtualize as software only|7.8 and above, 8.x| -|IBM DS8000® Family|8.x and higher with same API interface| +|IBM DS8000® family|8.x and higher with same API interface| **Note:** - For the latest microcode storage support information, see the [Lifecycle and support matrix](https://www.ibm.com/docs/en/stg-block-csi-driver?topic=SSRQ8T/landing/csi_lifecycle_support_matrix.html). -- The IBM Spectrum Virtualize Family and IBM SAN Volume Controller storage systems run the IBM Spectrum Virtualize software. In addition, IBM Spectrum Virtualize package is available as a deployable solution that can be run on any compatible hardware. +- The IBM Spectrum Virtualize family and IBM SAN Volume Controller storage systems run the IBM Spectrum Virtualize software. In addition, IBM Spectrum Virtualize package is available as a deployable solution that can be run on any compatible hardware. diff --git a/docs/content/release_notes/whats_new.md b/docs/content/release_notes/whats_new.md new file mode 100644 index 000000000..6e8e2b057 --- /dev/null +++ b/docs/content/release_notes/whats_new.md @@ -0,0 +1,25 @@ +# What's new in 1.8.0 + +IBM® block storage CSI driver 1.8.0 introduces the enhancements that are detailed in the following section. + +**General availability date:** 17 December 2021 + +## New HyperSwap support for IBM Spectrum Virtualize family storage systems + +IBM® block storage CSI driver 1.8.0 now supports HyperSwap implementation, when using IBM Spectrum Virtualize family storage systems. + +## New NVMe® over Fibre Channel protocol for IBM Spectrum Virtualize family storage systems + +This version adds NVMe®/FC support for supported IBM Spectrum Virtualize family storage systems using Red Hat® Enterprise Linux® (RHEL) operating systems. + +## Increased StorageClass `SpaceEfficiency` parameter capabilities + +Version 1.8.0 increases the `SpaceEfficiency` deduplication parameter options for IBM Spectrum Virtualize family storage systems. For more information, see [Creating a StorageClass](../configuration/creating_volumestorageclass.md). + +## Added custom resource configurability for the CSI driver health port + +This version allows you to configure the health port (9808) for the CSI driver through the custom resource. Configure using the `healthPort` parameter. + +## Additional orchestration support for OpenShift 4.7 and 4.9 for deployment + +This version reintroduces Red Hat® OpenShift 4.7 and adds new support for orchestration platform Red Hat OpenShift 4.9, suitable for deployment of the CSI (Container Storage Interface) driver. \ No newline at end of file diff --git a/docs/content/troubleshooting/csi_ug_troubleshooting_logs.md b/docs/content/troubleshooting/csi_ug_troubleshooting_logs.md deleted file mode 100644 index fa19d2387..000000000 --- a/docs/content/troubleshooting/csi_ug_troubleshooting_logs.md +++ /dev/null @@ -1,41 +0,0 @@ -# Log and status collection - -Use the CSI (Container Storage Interface) driver debug information for problem identification. - -**Note:** These procedures are applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. - -To collect and display status and logs related to the different components of IBM® block storage CSI driver, use the following Kubernetes commands: - -## Status collection for CSI pods, daemonset, and statefulset - -`kubectl get all -n -l csi` - -## Log collection for IBM block storage CSI driver controller - -`kubectl log -f -n ibm-block-csi-controller-0 -c ibm-block-csi-controller` - -## Log collection for IBM block storage CSI driver node (per worker node or PODID) - -`kubectl log -f -n ibm-block-csi-node- -c ibm-block-csi-node` - -## Log collection for Operator for IBM block storage CSI driver - -`kubectl log -f -n ibm-block-csi-operator- -c ibm-block-csi-operator` - -## Detecting errors - -To help pinpoint potential causes for stateful pod failure: - -1. Verify that all CSI pods are running. - - ``` - kubectl get pods -n -l csi - ``` - -2. If a pod is not in a _Running_ state, run the following command: - - ``` - kubectl describe -n pod/ - ``` - - View the logs. \ No newline at end of file diff --git a/docs/content/troubleshooting/log_status_collect.md b/docs/content/troubleshooting/log_status_collect.md new file mode 100644 index 000000000..a50e06aa4 --- /dev/null +++ b/docs/content/troubleshooting/log_status_collect.md @@ -0,0 +1,105 @@ +# Detecting errors and log collection + +Use the CSI (Container Storage Interface) driver debug information for problem identification. + +**Note:** These procedures are applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. + +## Detecting errors + +To help pinpoint potential causes for stateful pod failure: + +1. Verify that all CSI pods are running. + ``` + kubectl get pods -n -l product=ibm-block-csi-driver + ``` + +2. If a pod is not in a _Running_ state, run the following command: + ``` + kubectl describe -n pod/ + ``` + View the logs. + + +## Status and log collection +To collect and display status and logs related to the different components of IBM® block storage CSI driver, use the Kubernetes commands that are found in this section. + +Before you begin collecting logs, create a directory for the logs on the control-plane or bastion server. + +For example: + +``` +mkdir logs +``` +Save logs and status reports directly to the created directory by adding in the following string at the end of the collection command: `> logs/.log`. + +**Important:** Be sure that the logs cover any relevant time frames for the specific issues that you are trying to debug when gathering logs from the storage system. + +**Note:** All commands here are listed with the collection command with the `logs` folder name example. Change the folder name according as needed. + +### General status and log collection for IBM Support +Be sure to run the following steps and copy the output to an external file, when engaging IBM Support and sending log collections. + +1. Check the node status. + + `kubectl get nodes` +2. Check the CSI driver component status. + + `kubectl get -all-namespaces pod -o wide | grep ibm-block-csi` +3. Check if the PersistentVolumeClaims (PVCs) are _Bound_. + + `kubectl get -n pvc -o=jsonpath='{range .items[?(@.metadata.annotations.volume\.beta\.kubernetes\.io/storage-provisioner=="block.csi.ibm.com")]}{"PVC NAME: "}{@.metadata.name}{" PVC STATUS: "}{@.status.phase}{"\n"}{end}'` + + The output should be similar to the following: + + `PVC NAME: demo-pvc-file-system PVC STATUS: Bound` + + **Note:** If the PVCs are not in the _Bound_ state collect the events of all unbound PVCs. (See [Log collection for unbound PVCs](#log-collection-for-unbound-pvcs).) + +#### Log collection for all CSI driver node pods and their containers + +To collect logs for all CSI driver node pods, use the following commands: + + nodepods=`kubectl get pods -l product=ibm-block-csi-driver -l app.kubernetes.io/component=csi-node --output=jsonpath={.items..metadata.name}` + + for pod in $nodepods;do for container in `kubectl get -n pod $pod -o jsonpath='{.spec.containers[*].name}'`;do kubectl logs -n $pod -c $container > logs/${pod}_${container}.log;done;done + + +#### Log collection for all CSI controller containers + +To collect logs for all controller containers, use the following commands: + + for container in `kubectl get -n pod ibm-block-csi-controller-0 -o jsonpath='{.spec.containers[*].name}'`;do kubectl logs -n ibm-block-csi-controller-0 -c $container > logs/ibm-block-csi-controller-0_${container}.log;done + + +#### Log collection for CSI operator logs +To collect CSI operator logs, use the following commands: + + operatorpod=`kubectl get pods --all-namespaces |grep ibm-block-csi-operator|awk '{print $2}'` + kubectl logs $operatorpod -n > logs/operator.log + + +### Collecting details of all CSI objects and components +`kubectl describe all -l product=ibm-block-csi-driver -n > logs/describe_ibm-block-csi-driver.log` + + +### Status collection for CSI pods, daemonset, and statefulset +`kubectl get all -n -l product=ibm-block-csi-driver > logs/get_all_ibm-block-csi-driver.log` + + + +### Log collection for the CSI driver controller +`kubectl logs -f -n ibm-block-csi-controller-0 -c ibm-block-csi-controller > logs/ibm-block-csi-controller.log` + + +### Log collection for the CSI driver node (per worker node or PODID) +`kubectl logs -f -n ibm-block-csi-node- -c ibm-block-csi-node > logs/csi-node-.log` + + + +### Details collection for unbound PVCs +`kubectl describe -n pvc > logs/pvc_not_bounded.log` + + + +### Details collection for pods not in the _Running_ state +`kubectl describe -n pod > logs/pod_not_running.log` \ No newline at end of file diff --git a/docs/content/troubleshooting/csi_ug_troubleshooting_node_crash.md b/docs/content/troubleshooting/recovering_vol_attach_crashed_k8s.md similarity index 100% rename from docs/content/troubleshooting/csi_ug_troubleshooting_node_crash.md rename to docs/content/troubleshooting/recovering_vol_attach_crashed_k8s.md diff --git a/docs/content/troubleshooting/csi_ug_troubleshooting.md b/docs/content/troubleshooting/troubleshooting.md similarity index 57% rename from docs/content/troubleshooting/csi_ug_troubleshooting.md rename to docs/content/troubleshooting/troubleshooting.md index 9524791f3..8ad705a03 100644 --- a/docs/content/troubleshooting/csi_ug_troubleshooting.md +++ b/docs/content/troubleshooting/troubleshooting.md @@ -1,4 +1,3 @@ # Troubleshooting -This section can help you detect and solve problems that you might encounter when using the IBM® block storage CSI driver. - +This section can help you detect and solve problems that you might encounter when using the IBM® block storage CSI driver. \ No newline at end of file diff --git a/docs/content/troubleshooting/csi_ug_troubleshooting_misc.md b/docs/content/troubleshooting/troubleshooting_misc.md similarity index 92% rename from docs/content/troubleshooting/csi_ug_troubleshooting_misc.md rename to docs/content/troubleshooting/troubleshooting_misc.md index b23bb2ec3..4c237347d 100644 --- a/docs/content/troubleshooting/csi_ug_troubleshooting_misc.md +++ b/docs/content/troubleshooting/troubleshooting_misc.md @@ -2,7 +2,7 @@ Use this information to help pinpoint potential causes for stateful pod failure. -**Note:** These procedures are applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. +**Note:** These procedures are applicable for both Kubernetes and Red Hat® OpenShift®. For Red Hat OpenShift, replace `kubectl` with `oc` in all relevant commands. ## General troubleshooting Use the following command for general troubleshooting: @@ -38,6 +38,4 @@ If the following error occurs during stateful application pod creation (the pod 2. Rescan any iSCSI devices, using the `rescan-scsi-bus.sh` command. 3. Restart the multipath daemon again, using the `systemctl restart multipathd` command. - The multipath devices should be running properly and the pod should come up immediately. - - + The multipath devices should be running properly and the pod should come up immediately. \ No newline at end of file diff --git a/docs/content/using/csi_ug_using_sample.md b/docs/content/using/sample_stateful_container.md similarity index 54% rename from docs/content/using/csi_ug_using_sample.md rename to docs/content/using/sample_stateful_container.md index 44032b42a..6533f12fe 100644 --- a/docs/content/using/csi_ug_using_sample.md +++ b/docs/content/using/sample_stateful_container.md @@ -2,24 +2,20 @@ You can use the CSI (Container Storage Interface) driver for running stateful containers with a storage volume provisioned from IBM® block storage systems. -These instructions illustrate the general flow for a basic configuration required for running a stateful container with volumes provisioned on storage system. +These instructions illustrate the general flow for a basic configuration required for running a stateful container with volumes provisioned on a storage system. **Note:** The secret names given are user specified. To implement order and help any debugging that may be required, provide system type indicators to each secret name when managing different system storage types. Use this information to run a stateful container on StatefulSet volumes using either file systems or raw block volumes. -1. Create an array secret, as described in [Creating a Secret](../configuration/csi_ug_config_create_secret.md). +1. Create an array secret, as described in [Creating a Secret](../configuration/creating_secret.md). -2. Create a storage class, as described in [Creating a StorageClass](../configuration/csi_ug_config_create_storageclasses.md). +2. Create a storage class, as described in [Creating a StorageClass](../configuration/creating_volumestorageclass.md). - **Remember:** The `SpaceEfficiency` values for Spectrum Virtualize Family are: `thick`, `thin`, `compressed`, or `deduplicated`. These values are not case specific. - - For DS8000 Family systems, the default value is `none`, but can be set to `thin`, if required. These values are not case specific. For more information, see [Creating a StorageClass](../configuration/csi_ug_config_create_storageclasses.md). - - This parameter is not applicable for IBM FlashSystem A9000 and A9000R systems. These systems always include deduplication and compression. + **Note:** Use the `SpaceEfficiency` parameters available for your storage system, as specified in the [`SpaceEfficiency` parameter definitions per storage system type](../configuration/creating_volumestorageclass.md#spaceefficiency-parameter-definitions-per-storage-system-type) table. -3. Create a PVC with the size of 1 Gb, as described in [Creating a PersistentVolumeClaim (PVC)](../configuration/csi_ug_config_create_pvc.md). +3. Create a PVC with the size of 1 Gb, as described in [Creating a PersistentVolumeClaim (PVC)](../configuration/creating_pvc.md). 4. (Optional) Display the existing PVC and the created persistent volume (PV). -5. Create a StatefulSet, as described in [Creating a StatefulSet](../configuration/csi_ug_config_create_statefulset.md). \ No newline at end of file +5. Create a StatefulSet, as described in [Creating a StatefulSet](../configuration/creating_statefulset.md). \ No newline at end of file diff --git a/docs/content/using/csi_ug_using.md b/docs/content/using/using.md similarity index 100% rename from docs/content/using/csi_ug_using.md rename to docs/content/using/using.md diff --git a/go.mod b/go.mod index 0d89c4690..4d364c348 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ibm/ibm-block-csi-driver go 1.13 require ( - github.com/container-storage-interface/spec v1.2.0 + github.com/container-storage-interface/spec v1.5.0 github.com/golang/mock v1.3.1 github.com/sirupsen/logrus v1.4.2 golang.org/x/sync v0.0.0-20190423024810-112230192c58 diff --git a/go.sum b/go.sum index 26cde72ab..c65487da0 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/container-storage-interface/spec v1.2.0 h1:bD9KIVgaVKKkQ/UbVUY9kCaH/CJbhNxe0eeB4JeJV2s= -github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= +github.com/container-storage-interface/spec v1.5.0 h1:lvKxe3uLgqQeVQcrnL2CPQKISoKjTJxojEs9cBk+HXo= +github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s= 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= @@ -188,6 +188,7 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2El google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric.go b/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric.go index b69a8106c..8ec8cafc6 100644 --- a/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric.go +++ b/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric.go @@ -59,21 +59,27 @@ type WaitForMpathResult struct { var ( TimeOutMultipathCmd = 60 * 1000 TimeOutMultipathdCmd = 10 * 1000 + TimeOutBlockDevCmd = 10 * 1000 + TimeOutSgInqCmd = 3 * 1000 ) const ( DevPath = "/dev" - ConnectionTypeISCSI = "iscsi" + ConnectionTypeNVMEoFC = "nvmeofc" ConnectionTypeFC = "fc" + ConnectionTypeISCSI = "iscsi" WaitForMpathRetries = 5 WaitForMpathWaitIntervalSec = 1 - FC_HOST_SYSFS_PATH = "/sys/class/fc_remote_ports/rport-*/port_name" + FcHostSysfsPath = "/sys/class/fc_remote_ports/rport-*/port_name" IscsiHostRexExPath = "/sys/class/iscsi_host/host*/device/session*/iscsi_session/session*/targetname" - MpathdSeparator = "," + blockDevCmd = "blockdev" + mpathdSeparator = "," multipathdCmd = "multipathd" multipathCmd = "multipath" VolumeIdDelimiter = ":" VolumeStorageIdsDelimiter = ";" + WwnOuiEnd = 7 + WwnVendorIdentifierEnd = 16 ) func NewOsDeviceConnectivityHelperScsiGeneric(executer executer.ExecuterInterface) OsDeviceConnectivityHelperScsiGenericInterface { @@ -150,13 +156,13 @@ func (r OsDeviceConnectivityHelperScsiGeneric) GetMpathDevice(volumeId string) ( volumeUuid := getVolumeUuid(volumeId) volumeUuidLower := strings.ToLower(volumeUuid) - - dmPath, _ := r.Helper.GetDmsPath(volumeUuidLower) + volumeNguid := ConvertScsiIdToNguid(volumeUuidLower) + dmPath, _ := r.Helper.GetDmsPath(volumeUuidLower, volumeNguid) if dmPath != "" { SgInqWwn, _ := r.Helper.GetWwnByScsiInq(dmPath) - - if strings.ToLower(SgInqWwn) == volumeUuidLower { + SgInqWwnLower := strings.ToLower(SgInqWwn) + if SgInqWwnLower == volumeUuidLower || SgInqWwnLower == volumeNguid { return dmPath, nil } } @@ -165,7 +171,7 @@ func (r OsDeviceConnectivityHelperScsiGeneric) GetMpathDevice(volumeId string) ( return "", err } - dmPath, err := r.Helper.GetDmsPath(volumeUuidLower) + dmPath, err := r.Helper.GetDmsPath(volumeUuidLower, volumeNguid) if err != nil { return "", err @@ -179,15 +185,41 @@ func (r OsDeviceConnectivityHelperScsiGeneric) GetMpathDevice(volumeId string) ( if err != nil { return "", err } - - if strings.ToLower(SgInqWwn) != volumeUuidLower { + SgInqWwnLower := strings.ToLower(SgInqWwn) + if SgInqWwnLower != volumeUuidLower && SgInqWwnLower != volumeNguid { // To make sure we found the right WWN, if not raise error instead of using wrong mpath return "", &ErrorWrongDeviceFound{dmPath, volumeUuidLower, SgInqWwn} } return dmPath, nil } +func (r OsDeviceConnectivityHelperScsiGeneric) flushDeviceBuffers(deviceName string) error { + devicePath := filepath.Join(DevPath, deviceName) + _, err := r.Executer.ExecuteWithTimeout(TimeOutBlockDevCmd, blockDevCmd, []string{"--flushbufs", devicePath}) + if err != nil { + logger.Errorf("blockdev --flushbufs {%v} did not succeed to flush the device buffers. err={%v}", devicePath, + err.Error()) + return err + } + return nil +} + +func (r OsDeviceConnectivityHelperScsiGeneric) flushDevicesBuffers(deviceNames []string) error { + for _, deviceName := range deviceNames { + err := r.flushDeviceBuffers(deviceName) + if err != nil { + return err + } + } + return nil +} + func (r OsDeviceConnectivityHelperScsiGeneric) FlushMultipathDevice(mpathDevice string) error { + err := r.flushDeviceBuffers(mpathDevice) + if err != nil { + return err + } + // mpathdevice is dm-4 for example logger.Debugf("Flushing mpath device : {%v}", mpathDevice) @@ -196,7 +228,7 @@ func (r OsDeviceConnectivityHelperScsiGeneric) FlushMultipathDevice(mpathDevice logger.Debugf("Try to acquire lock for running the command multipath -f {%v} (to avoid concurrent multipath commands)", mpathDevice) r.MutexMultipathF.Lock() logger.Debugf("Acquired lock for multipath -f command") - _, err := r.Executer.ExecuteWithTimeout(TimeOutMultipathCmd, "multipath", []string{"-f", fullDevice}) + _, err = r.Executer.ExecuteWithTimeout(TimeOutMultipathCmd, multipathCmd, []string{"-f", fullDevice}) r.MutexMultipathF.Unlock() if err != nil { @@ -208,12 +240,16 @@ func (r OsDeviceConnectivityHelperScsiGeneric) FlushMultipathDevice(mpathDevice } } - logger.Debugf("Finshed flushing mpath device : {%v}", mpathDevice) + logger.Debugf("Finished flushing mpath device : {%v}", mpathDevice) return nil - } func (r OsDeviceConnectivityHelperScsiGeneric) RemovePhysicalDevice(sysDevices []string) error { + flushErr := r.flushDevicesBuffers(sysDevices) + if flushErr != nil { + return flushErr + } + // sysDevices = sdb, sda,... logger.Debugf("Removing scsi device : {%v}", sysDevices) // NOTE: this func could be also relevant for SCSI (not only for iSCSI) @@ -247,7 +283,7 @@ func (r OsDeviceConnectivityHelperScsiGeneric) RemovePhysicalDevice(sysDevices [ return err // TODO: maybe we need to just swallow the error and continnue?? } } - logger.Debugf("Finshed to remove SCSI devices : {%v}", sysDevices) + logger.Debugf("Finished removing SCSI devices : {%v}", sysDevices) return nil } @@ -261,7 +297,7 @@ type OsDeviceConnectivityHelperInterface interface { Mainly for writting clean unit testing, so we can Mock this interface in order to unit test OsDeviceConnectivityHelperGeneric logic. */ GetHostsIdByArrayIdentifier(arrayIdentifier string) ([]int, error) - GetDmsPath(volumeId string) (string, error) + GetDmsPath(volumeId string, volumeNguid string) (string, error) GetWwnByScsiInq(dev string) (string, error) ReloadMultipath() error } @@ -296,7 +332,7 @@ func (o OsDeviceConnectivityHelperGeneric) GetHostsIdByArrayIdentifier(arrayIden targetFilePath = IscsiHostRexExPath regexpValue = "host([0-9]+)" } else { - targetFilePath = FC_HOST_SYSFS_PATH + targetFilePath = FcHostSysfsPath regexpValue = "rport-([0-9]+)" } @@ -310,17 +346,16 @@ func (o OsDeviceConnectivityHelperGeneric) GetHostsIdByArrayIdentifier(arrayIden logger.Debugf("targetname files matches were found : {%v}", matches) re := regexp.MustCompile(regexpValue) + logger.Debugf("Check if any match is relevant for storage target (%s).", arrayIdentifier) for _, targetPath := range matches { - logger.Debugf("Check if targetname path (%s) is relevant for storage target (%s).", targetPath, arrayIdentifier) targetName, err := o.Executer.IoutilReadFile(targetPath) if err != nil { logger.Warningf("Could not read target name from file : {%v}, error : {%v}", targetPath, err) continue } identifierFromHost := strings.TrimSpace(string(targetName)) - //For FC WWNs from the host, the value will like this: 0x500507680b26c0aa, but the arrayIdentifier doesn't has this prefix + //For FC WWNs from the host, the value will like this: 0x500507680b26c0aa, but the arrayIdentifier doesn't have this prefix if strings.HasPrefix(identifierFromHost, "0x") { - logger.Tracef("Remove the 0x prefix for: {%v}", identifierFromHost) identifierFromHost = strings.TrimLeft(identifierFromHost, "0x") } if strings.EqualFold(identifierFromHost, arrayIdentifier) { @@ -394,7 +429,7 @@ func (o OsDeviceConnectivityHelperGeneric) GetWwnByScsiInq(dev string) (string, args := []string{"-p", "0x83", dev} // add timeout in case the call never comes back. logger.Debugf("Calling [%s] with timeout", sgInqCmd) - outputBytes, err := o.Executer.ExecuteWithTimeout(3000, sgInqCmd, args) + outputBytes, err := o.Executer.ExecuteWithTimeout(TimeOutSgInqCmd, sgInqCmd, args) if err != nil { return "", err } @@ -458,10 +493,11 @@ func (o OsDeviceConnectivityHelperGeneric) ReloadMultipath() error { logger.Infof("ReloadMultipath: reload finished successfully") return nil } -func (o OsDeviceConnectivityHelperGeneric) GetDmsPath(volumeId string) (string, error) { + +func (o OsDeviceConnectivityHelperGeneric) GetDmsPath(volumeId string, volumeNguid string) (string, error) { volumeUuidLower := strings.ToLower(volumeId) - mpathdOutput, err := o.Helper.WaitForDmToExist(volumeUuidLower, WaitForMpathRetries, WaitForMpathWaitIntervalSec) + mpathdOutput, err := o.Helper.WaitForDmToExist(volumeUuidLower, volumeNguid, WaitForMpathRetries, WaitForMpathWaitIntervalSec) if err != nil { return "", err @@ -475,9 +511,9 @@ func (o OsDeviceConnectivityHelperGeneric) GetDmsPath(volumeId string) (string, scanner := bufio.NewScanner(strings.NewReader(mpathdOutput)) for scanner.Scan() { deviceLine := scanner.Text() - lineParts := strings.Split(deviceLine, MpathdSeparator) + lineParts := strings.Split(deviceLine, mpathdSeparator) dm, uuid := lineParts[0], lineParts[1] - if strings.Contains(uuid, volumeUuidLower) { + if strings.Contains(uuid, volumeUuidLower) || strings.Contains(uuid, volumeNguid) { dmPath := filepath.Join(DevPath, filepath.Base(strings.TrimSpace(dm))) dms[dmPath] = true logger.Infof("GetMpathDevice: DM found: %s for volume %s", dmPath, uuid) @@ -499,7 +535,7 @@ func (o OsDeviceConnectivityHelperGeneric) GetDmsPath(volumeId string) (string, //go:generate mockgen -destination=../../../mocks/mock_GetDmsPathHelperInterface.go -package=mocks github.com/ibm/ibm-block-csi-driver/node/pkg/driver/device_connectivity GetDmsPathHelperInterface type GetDmsPathHelperInterface interface { - WaitForDmToExist(volumeUuid string, maxRetries int, intervalSeconds int) (string, error) + WaitForDmToExist(volumeUuid string, volumeNguid string, maxRetries int, intervalSeconds int) (string, error) } type GetDmsPathHelperGeneric struct { @@ -510,9 +546,18 @@ func NewGetDmsPathHelperGeneric(executer executer.ExecuterInterface) GetDmsPathH return &GetDmsPathHelperGeneric{executer: executer} } -func (o GetDmsPathHelperGeneric) WaitForDmToExist(volumeUuid string, maxRetries int, intervalSeconds int) (string, error) { +func ConvertScsiIdToNguid(scsiId string) string { + logger.Infof("Converting scsi uuid : %s to nguid", scsiId) + oui := scsiId[1:WwnOuiEnd] + vendorIdentifier := scsiId[WwnOuiEnd:WwnVendorIdentifierEnd] + vendorIdentifierExtension := scsiId[WwnVendorIdentifierEnd:] + finalNguid := vendorIdentifierExtension + oui + "0" + vendorIdentifier + logger.Infof("Nguid is : %s", finalNguid) + return finalNguid +} - formatTemplate := strings.Join([]string{"%d", "%w"}, MpathdSeparator) +func (o GetDmsPathHelperGeneric) WaitForDmToExist(volumeUuid string, volumeNguid string, maxRetries int, intervalSeconds int) (string, error) { + formatTemplate := strings.Join([]string{"%d", "%w"}, mpathdSeparator) args := []string{"show", "maps", "raw", "format", "\"", formatTemplate, "\""} var err error for i := 0; i < maxRetries; i++ { @@ -522,7 +567,7 @@ func (o GetDmsPathHelperGeneric) WaitForDmToExist(volumeUuid string, maxRetries return "", err } dms := string(out) - if !strings.Contains(dms, volumeUuid) { + if !strings.Contains(dms, volumeUuid) && !strings.Contains(dms, volumeNguid) { err = os.ErrNotExist } else { return dms, nil diff --git a/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric_test.go b/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric_test.go index 3df148428..cb205162e 100644 --- a/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric_test.go +++ b/node/pkg/driver/device_connectivity/device_connectivity_helper_scsigeneric_test.go @@ -28,6 +28,11 @@ import ( "testing" ) +var ( + volumeUuid = "6oui000vendorsi0vendorsie0000000" + volumeNguid = "vendorsie0000000oui0000vendorsi0" +) + func NewOsDeviceConnectivityHelperScsiGenericForTest( executer executer.ExecuterInterface, helper device_connectivity.OsDeviceConnectivityHelperInterface, @@ -161,7 +166,7 @@ func TestGetMpathDevice(t *testing.T) { }, getWwnByScsiInqReturn: []GetWwnByScsiInqReturn{ GetWwnByScsiInqReturn{ - wwn: "600fakevolumeuuid000000000111", + wwn: volumeUuid, err: nil, }, }, @@ -191,7 +196,7 @@ func TestGetMpathDevice(t *testing.T) { getWwnByScsiInqReturn: []GetWwnByScsiInqReturn{ GetWwnByScsiInqReturn{ - wwn: "600fakevolumeuuid000000000111", + wwn: volumeUuid, err: nil, }, }, @@ -207,12 +212,12 @@ func TestGetMpathDevice(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) fake_helper := mocks.NewMockOsDeviceConnectivityHelperInterface(mockCtrl) fake_mutex := &sync.Mutex{} for _, r := range tc.getDmsPathReturn { - fake_helper.EXPECT().GetDmsPath("600fakevolumeuuid000000000111").Return( + fake_helper.EXPECT().GetDmsPath(volumeUuid, volumeNguid).Return( r.dmPath, r.err) } @@ -228,8 +233,8 @@ func TestGetMpathDevice(t *testing.T) { r.err) } - o := NewOsDeviceConnectivityHelperScsiGenericForTest(fake_executer, fake_helper, fake_mutex) - DMPath, err := o.GetMpathDevice("Test:600FAKEVOLUMEUUID000000000111") + o := NewOsDeviceConnectivityHelperScsiGenericForTest(fakeExecuter, fake_helper, fake_mutex) + DMPath, err := o.GetMpathDevice(fmt.Sprintf("Test:%s", volumeUuid)) if tc.expErr != nil || tc.expErrType != nil { if err == nil { t.Fatalf("Expected to fail with error, got success.") @@ -284,7 +289,7 @@ func TestGetDmsPath(t *testing.T) { name: "Should fail when WaitForDmToExist found more than 1 dm for volume", waitForDmToExistReturn: []WaitForDmToExistReturn{ WaitForDmToExistReturn{ - out: "dm-1,600fakevolumeuuid000000000111\ndm-2,otheruuid\ndm-3,600fakevolumeuuid000000000111", + out: fmt.Sprintf("dm-1,%s\ndm-2,%s\ndm-3,%s", volumeUuid, "otheruuid", volumeUuid), err: nil, }, }, @@ -297,7 +302,7 @@ func TestGetDmsPath(t *testing.T) { name: "Should succeed to GetDmPath with space in start of input", waitForDmToExistReturn: []WaitForDmToExistReturn{ WaitForDmToExistReturn{ - out: " dm-1,600fakevolumeuuid000000000111", + out: fmt.Sprintf(" dm-1,%s", volumeUuid), err: nil, }, }, @@ -310,7 +315,7 @@ func TestGetDmsPath(t *testing.T) { name: "Should succeed to GetDmPath", waitForDmToExistReturn: []WaitForDmToExistReturn{ WaitForDmToExistReturn{ - out: "dm-1,600fakevolumeuuid000000000111\ndm-2,otheruuid\ndm-3,otheruuid2", + out: fmt.Sprintf("dm-1,%s\ndm-2,%s\ndm-3,%s", volumeUuid, "otheruuid", "otheruuid2"), err: nil, }, }, @@ -326,15 +331,15 @@ func TestGetDmsPath(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) fake_helper := mocks.NewMockGetDmsPathHelperInterface(mockCtrl) for _, r := range tc.waitForDmToExistReturn { - fake_helper.EXPECT().WaitForDmToExist("600fakevolumeuuid000000000111", 5, 1).Return(r.out, r.err) + fake_helper.EXPECT().WaitForDmToExist(volumeUuid, volumeNguid, 5, 1).Return(r.out, r.err) } - helperGeneric := NewOsDeviceConnectivityHelperGenericForTest(fake_executer, fake_helper) - dmPath, err := helperGeneric.GetDmsPath("600FAKEVOLUMEUUID000000000111") + helperGeneric := NewOsDeviceConnectivityHelperGenericForTest(fakeExecuter, fake_helper) + dmPath, err := helperGeneric.GetDmsPath(volumeUuid, volumeNguid) if tc.expErr != nil || tc.expErrType != nil { if err == nil { t.Fatalf("Expected to fail with error, got success.") @@ -380,7 +385,7 @@ func TestHelperWaitForDmToExist(t *testing.T) { }, { name: "Should succeed", - devices: "dm-1,volumeUuid\ndm-2,otherUuid", + devices: fmt.Sprintf("dm-1,%s\ndm-2,%s", volumeUuid, "otherUuid"), cmdReturnErr: nil, expErr: nil, }, @@ -392,12 +397,11 @@ func TestHelperWaitForDmToExist(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) - volumeUuid := "volumeUuid" + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) args := []string{"show", "maps", "raw", "format", "\"", "%d,%w", "\""} - fake_executer.EXPECT().ExecuteWithTimeout(device_connectivity.TimeOutMultipathdCmd, "multipathd", args).Return([]byte(tc.devices), tc.cmdReturnErr) - helperGeneric := device_connectivity.NewGetDmsPathHelperGeneric(fake_executer) - devices, err := helperGeneric.WaitForDmToExist(volumeUuid, 1, 1) + fakeExecuter.EXPECT().ExecuteWithTimeout(device_connectivity.TimeOutMultipathdCmd, "multipathd", args).Return([]byte(tc.devices), tc.cmdReturnErr) + helperGeneric := device_connectivity.NewGetDmsPathHelperGeneric(fakeExecuter) + devices, err := helperGeneric.WaitForDmToExist(volumeUuid, volumeNguid, 1, 1) if err != nil { if err.Error() != tc.expErr.Error() { t.Fatalf("Expected error code %s, got %s", tc.expErr, err.Error()) @@ -439,7 +443,7 @@ func TestHelperGetWwnByScsiInq(t *testing.T) { }, { name: "Should return error when wwn line not matching the expected pattern", - cmdReturn: []byte("Vendor Specific Identifier Extension: 0xcea5f6\n\t\t\t [600fakevolumeuuid000000000111]"), + cmdReturn: []byte(fmt.Sprintf("Vendor Specific Identifier Extension: 0xcea5f6\n\t\t\t [%s]", volumeUuid)), wwn: "", cmdReturnErr: nil, expErrType: reflect.TypeOf(&device_connectivity.ErrorNoRegexWwnMatchInScsiInq{}), @@ -455,8 +459,8 @@ func TestHelperGetWwnByScsiInq(t *testing.T) { }, { name: "Should succeed", - cmdReturn: []byte("Vendor Specific Identifier Extension: 0xcea5f6\n\t\t\t [0x600fakevolumeuuid000000000111]"), - wwn: "600FAKEVOLUMEUUID000000000111", + cmdReturn: []byte(fmt.Sprintf("Vendor Specific Identifier Extension: 0xcea5f6\n\t\t\t [0x%s]", volumeUuid)), + wwn: volumeUuid, cmdReturnErr: nil, expErr: nil, sgInqExecutable: nil, @@ -470,15 +474,15 @@ func TestHelperGetWwnByScsiInq(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) args := []string{"-p", "0x83", device} - fake_executer.EXPECT().IsExecutable(sgInqCmd).Return(tc.sgInqExecutable) + fakeExecuter.EXPECT().IsExecutable(sgInqCmd).Return(tc.sgInqExecutable) if tc.sgInqExecutable == nil { - fake_executer.EXPECT().ExecuteWithTimeout(3000, sgInqCmd, args).Return(tc.cmdReturn, tc.cmdReturnErr) + fakeExecuter.EXPECT().ExecuteWithTimeout(device_connectivity.TimeOutSgInqCmd, sgInqCmd, args).Return(tc.cmdReturn, tc.cmdReturnErr) } - helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fake_executer) + helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fakeExecuter) wwn, err := helperGeneric.GetWwnByScsiInq(device) if tc.expErr != nil || tc.expErrType != nil { if err == nil { @@ -626,18 +630,18 @@ func TestGetHostsIdByArrayIdentifier(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) - fake_executer.EXPECT().FilepathGlob(device_connectivity.IscsiHostRexExPath).Return(tc.globReturnMatches, tc.globReturnErr) + fakeExecuter.EXPECT().FilepathGlob(device_connectivity.IscsiHostRexExPath).Return(tc.globReturnMatches, tc.globReturnErr) var mcalls []*gomock.Call for _, r := range tc.ioutilReadFileReturns { - call := fake_executer.EXPECT().IoutilReadFile(r.ReadFileParam).Return(r.data, r.err) + call := fakeExecuter.EXPECT().IoutilReadFile(r.ReadFileParam).Return(r.data, r.err) mcalls = append(mcalls, call) } gomock.InOrder(mcalls...) - helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fake_executer) + helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fakeExecuter) returnHostList, err := helperGeneric.GetHostsIdByArrayIdentifier(tc.arrayIdentifier) if tc.expErr != nil || tc.expErrType != nil { @@ -788,18 +792,18 @@ func TestGetHostsIdByArrayIdentifier(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) - fake_executer.EXPECT().FilepathGlob(device_connectivity.FC_HOST_SYSFS_PATH).Return(tc.globReturnMatches, tc.globReturnErr) + fakeExecuter.EXPECT().FilepathGlob(device_connectivity.FcHostSysfsPath).Return(tc.globReturnMatches, tc.globReturnErr) var mcalls []*gomock.Call for _, r := range tc.ioutilReadFileReturns { - call := fake_executer.EXPECT().IoutilReadFile(r.ReadFileParam).Return(r.data, r.err) + call := fakeExecuter.EXPECT().IoutilReadFile(r.ReadFileParam).Return(r.data, r.err) mcalls = append(mcalls, call) } gomock.InOrder(mcalls...) - helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fake_executer) + helperGeneric := device_connectivity.NewOsDeviceConnectivityHelperGeneric(fakeExecuter) returnHostList, err := helperGeneric.GetHostsIdByArrayIdentifier(tc.arrayIdentifier) if tc.expErr != nil || tc.expErrType != nil { diff --git a/node/pkg/driver/device_connectivity/device_connectivity_nvmeofc.go b/node/pkg/driver/device_connectivity/device_connectivity_nvmeofc.go new file mode 100644 index 000000000..2dea2068a --- /dev/null +++ b/node/pkg/driver/device_connectivity/device_connectivity_nvmeofc.go @@ -0,0 +1,52 @@ +/** + * Copyright 2019 IBM Corp. + * + * 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. + */ + +package device_connectivity + +import ( + "github.com/ibm/ibm-block-csi-driver/node/pkg/driver/executer" +) + +type OsDeviceConnectivityNvmeOFc struct { + Executer executer.ExecuterInterface + HelperScsiGeneric OsDeviceConnectivityHelperScsiGenericInterface +} + +func NewOsDeviceConnectivityNvmeOFc(executer executer.ExecuterInterface) OsDeviceConnectivityInterface { + return &OsDeviceConnectivityNvmeOFc{ + Executer: executer, + HelperScsiGeneric: NewOsDeviceConnectivityHelperScsiGeneric(executer), + } +} + +func (r OsDeviceConnectivityNvmeOFc) EnsureLogin(_ map[string][]string) { +} + +func (r OsDeviceConnectivityNvmeOFc) RescanDevices(_ int, _ []string) error { + return nil +} + +func (r OsDeviceConnectivityNvmeOFc) GetMpathDevice(volumeId string) (string, error) { + return r.HelperScsiGeneric.GetMpathDevice(volumeId) +} + +func (r OsDeviceConnectivityNvmeOFc) FlushMultipathDevice(mpathDevice string) error { + return r.HelperScsiGeneric.FlushMultipathDevice(mpathDevice) +} + +func (r OsDeviceConnectivityNvmeOFc) RemovePhysicalDevice(sysDevices []string) error { + return r.HelperScsiGeneric.RemovePhysicalDevice(sysDevices) +} diff --git a/node/pkg/driver/driver.go b/node/pkg/driver/driver.go index 3d35300f7..acc5ed75c 100644 --- a/node/pkg/driver/driver.go +++ b/node/pkg/driver/driver.go @@ -56,9 +56,9 @@ func NewDriver(endpoint string, configFilePath string, hostname string) (*Driver syncLock := NewSyncLock() executer := &executer.Executer{} osDeviceConnectivityMapping := map[string]device_connectivity.OsDeviceConnectivityInterface{ - device_connectivity.ConnectionTypeISCSI: device_connectivity.NewOsDeviceConnectivityIscsi(executer), - device_connectivity.ConnectionTypeFC: device_connectivity.NewOsDeviceConnectivityFc(executer), - // TODO nvme + device_connectivity.ConnectionTypeNVMEoFC: device_connectivity.NewOsDeviceConnectivityNvmeOFc(executer), + device_connectivity.ConnectionTypeFC: device_connectivity.NewOsDeviceConnectivityFc(executer), + device_connectivity.ConnectionTypeISCSI: device_connectivity.NewOsDeviceConnectivityIscsi(executer), } osDeviceConnectivityHelper := device_connectivity.NewOsDeviceConnectivityHelperScsiGeneric(executer) return &Driver{ diff --git a/node/pkg/driver/messages.go b/node/pkg/driver/messages.go index c257a7df3..3fa4b20c3 100644 --- a/node/pkg/driver/messages.go +++ b/node/pkg/driver/messages.go @@ -15,10 +15,8 @@ */ package driver -var ErrorWhileTryingToReadIQN = "Error while trying to get iqn from string: %v." +var ErrorWhileTryingToReadPort = "Error while trying to get %s port from string: %v." var ErrorUnsupportedConnectivityType = "Unsupported connectivity type : {%v}" -var ErrorWhileTryingToReadFC = "Error while tring to get FC port from string: %v." - var ErrorNoPortsCouldFitInNodeId = "could not fit any ports in node id: %v, length limit: %d" diff --git a/node/pkg/driver/node.go b/node/pkg/driver/node.go index 06e4cea53..e2992c9c1 100644 --- a/node/pkg/driver/node.go +++ b/node/pkg/driver/node.go @@ -50,11 +50,12 @@ var ( defaultFSType = "ext4" StageInfoFilename = ".stageInfo.json" supportedConnectivityTypes = map[string]bool{ - device_connectivity.ConnectionTypeISCSI: true, - device_connectivity.ConnectionTypeFC: true, - // TODO add nvme later on + device_connectivity.ConnectionTypeNVMEoFC: true, + device_connectivity.ConnectionTypeFC: true, + device_connectivity.ConnectionTypeISCSI: true, } + NvmeFullPath = "/host/etc/nvme/hostnqn" IscsiFullPath = "/host/etc/iscsi/initiatorname.iscsi" ) @@ -242,9 +243,11 @@ func (d *NodeService) nodeStageVolumeRequestValidation(req *csi.NodeStageVolumeR return &RequestValidationError{fmt.Sprintf("PublishContext with wrong lun id %d.", lun)} } - if len(ipsByArrayInitiator) == 0 { - return &RequestValidationError{fmt.Sprintf("PublishContext with wrong arrayInitiators %v.", - ipsByArrayInitiator)} + if connectivityType != device_connectivity.ConnectionTypeNVMEoFC { + if len(ipsByArrayInitiator) == 0 { + return &RequestValidationError{fmt.Sprintf("PublishContext with wrong arrayInitiators %v.", + ipsByArrayInitiator)} + } } if connectivityType == device_connectivity.ConnectionTypeISCSI { @@ -415,15 +418,28 @@ func (d *NodeService) NodePublishVolume(ctx context.Context, req *csi.NodePublis case *csi.VolumeCapability_Block: isFSVolume = false } + + if isFSVolume { + stagingPathWithHostPrefix := d.NodeUtils.GetPodPath(stagingPath) + isStagingNotMounted, err := d.NodeUtils.IsNotMountPoint(stagingPathWithHostPrefix) + if err != nil { + logger.Errorf("Existing mount check failed {%v}", err.Error()) + return nil, err + } + if isStagingNotMounted { + return nil, status.Errorf(codes.InvalidArgument, "Staging path %v is not a mount point", stagingPath) + } + } + isTargetPathExists := d.NodeUtils.IsPathExists(targetPathWithHostPrefix) if isTargetPathExists { // check if already mounted - isMounted, err := d.isTargetMounted(targetPathWithHostPrefix, isFSVolume) + isTargetMounted, err := d.isTargetMounted(targetPathWithHostPrefix, isFSVolume) if err != nil { logger.Debugf("Existing mount check failed {%v}", err.Error()) return nil, err } - if isMounted { // idempotent case + if isTargetMounted { // idempotent case return &csi.NodePublishVolumeResponse{}, nil } } else { @@ -627,12 +643,17 @@ func (d *NodeService) NodeExpandVolume(ctx context.Context, req *csi.NodeExpandV } sysDevices := strings.Split(rawSysDevices, ",") - - err = d.NodeUtils.RescanPhysicalDevices(sysDevices) + devicesAreNvme, err := d.NodeUtils.DevicesAreNvme(sysDevices) if err != nil { + logger.Errorf("Error while trying to check if sys devices are nvme devices : {%v}", err.Error()) return nil, status.Error(codes.Internal, err.Error()) } - + if !devicesAreNvme { + err = d.NodeUtils.RescanPhysicalDevices(sysDevices) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + } err = d.NodeUtils.ExpandMpathDevice(baseDevice) if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -702,8 +723,9 @@ func (d *NodeService) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoReque logger.Debugf(">>>> NodeGetInfo: called with args %+v", *req) defer logger.Debugf("<<<< NodeGetInfo") - var iscsiIQN string + var nvmeNQN string var fcWWNs []string + var iscsiIQN string var err error topologyLabels, err := d.NodeUtils.GetTopologyLabels(ctx, d.Hostname) @@ -712,6 +734,14 @@ func (d *NodeService) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoReque } logger.Debugf("discovered topology labels : %v", topologyLabels) + nvmeExists := d.NodeUtils.IsPathExists(NvmeFullPath) + if nvmeExists { + nvmeNQN, err = d.NodeUtils.ReadNvmeNqn() + if err != nil { + logger.Warning(err) + } + } + fcExists := d.NodeUtils.IsFCExists() if fcExists { fcWWNs, err = d.NodeUtils.ParseFCPorts() @@ -722,15 +752,18 @@ func (d *NodeService) NodeGetInfo(ctx context.Context, req *csi.NodeGetInfoReque iscsiExists := d.NodeUtils.IsPathExists(IscsiFullPath) if iscsiExists { - iscsiIQN, _ = d.NodeUtils.ParseIscsiInitiators() + iscsiIQN, err = d.NodeUtils.ParseIscsiInitiators() + if err != nil { + logger.Warning(err) + } } - if fcWWNs == nil && iscsiIQN == "" { - err := fmt.Errorf("Cannot find valid fc wwns or iscsi iqn") + if nvmeNQN == "" && fcWWNs == nil && iscsiIQN == "" { + err := fmt.Errorf("Cannot find valid nvme nqn, fc wwns or iscsi iqn") return nil, status.Error(codes.Internal, err.Error()) } - nodeId, err := d.NodeUtils.GenerateNodeID(d.Hostname, fcWWNs, iscsiIQN) + nodeId, err := d.NodeUtils.GenerateNodeID(d.Hostname, nvmeNQN, fcWWNs, iscsiIQN) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/node/pkg/driver/node_test.go b/node/pkg/driver/node_test.go index 70db3e0a4..141d93367 100644 --- a/node/pkg/driver/node_test.go +++ b/node/pkg/driver/node_test.go @@ -55,8 +55,9 @@ func newTestNodeService(nodeUtils driver.NodeUtilsInterface, osDevCon device_con func newTestNodeServiceStaging(nodeUtils driver.NodeUtilsInterface, osDevCon device_connectivity.OsDeviceConnectivityInterface, nodeMounter driver.NodeMounter) driver.NodeService { osDeviceConnectivityMapping := map[string]device_connectivity.OsDeviceConnectivityInterface{ - device_connectivity.ConnectionTypeISCSI: osDevCon, - device_connectivity.ConnectionTypeFC: osDevCon, + device_connectivity.ConnectionTypeNVMEoFC: osDevCon, + device_connectivity.ConnectionTypeFC: osDevCon, + device_connectivity.ConnectionTypeISCSI: osDevCon, } return driver.NodeService{ @@ -541,8 +542,9 @@ func TestNodePublishVolume(t *testing.T) { volumeId := "vol-test" fsTypeXfs := "ext4" targetPath := "/test/path" + stagingPath := "/test/staging" targetPathWithHostPrefix := GetPodPath(targetPath) - stagingTargetPath := path.Join("/test/staging", driver.StageInfoFilename) + stagingPathWithHostPrefix := GetPodPath(stagingPath) deviceName := "fakedev" mpathDevice := filepath.Join(device_connectivity.DevPath, deviceName) accessMode := &csi.VolumeCapability_AccessMode{ @@ -571,7 +573,7 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(nil, nil, nil) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: fsVolCap, } @@ -601,7 +603,7 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(nil, nil, nil) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, VolumeCapability: fsVolCap, VolumeId: volumeId, } @@ -616,7 +618,7 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(nil, nil, nil) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeId: volumeId, } @@ -631,7 +633,7 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(nil, nil, nil) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: &csi.VolumeCapability{ AccessMode: &csi.VolumeCapability_AccessMode{ @@ -655,13 +657,15 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(mockNodeUtils, nil, mockMounter) mockNodeUtils.EXPECT().GetPodPath(targetPath).Return(targetPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().GetPodPath(stagingPath).Return(stagingPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().IsNotMountPoint(stagingPathWithHostPrefix).Return(false, nil) mockNodeUtils.EXPECT().IsPathExists(targetPathWithHostPrefix).Return(true) mockNodeUtils.EXPECT().IsNotMountPoint(targetPathWithHostPrefix).Return(false, nil) mockNodeUtils.EXPECT().IsDirectory(targetPathWithHostPrefix).Return(false) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: fsVolCap, VolumeId: volumeId, @@ -682,13 +686,15 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(mockNodeUtils, nil, mockMounter) mockNodeUtils.EXPECT().GetPodPath(targetPath).Return(targetPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().GetPodPath(stagingPath).Return(stagingPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().IsNotMountPoint(stagingPathWithHostPrefix).Return(false, nil) mockNodeUtils.EXPECT().IsPathExists(targetPathWithHostPrefix).Return(false) mockNodeUtils.EXPECT().MakeDir(targetPathWithHostPrefix).Return(nil) - mockMounter.EXPECT().Mount(stagingTargetPath, targetPath, fsTypeXfs, mountOptions) + mockMounter.EXPECT().Mount(stagingPath, targetPath, fsTypeXfs, mountOptions) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: fsVolCap, VolumeId: volumeId, @@ -710,13 +716,15 @@ func TestNodePublishVolume(t *testing.T) { node := newTestNodeService(mockNodeUtils, nil, mockMounter) mockNodeUtils.EXPECT().GetPodPath(targetPath).Return(targetPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().GetPodPath(stagingPath).Return(stagingPathWithHostPrefix).AnyTimes() + mockNodeUtils.EXPECT().IsNotMountPoint(stagingPathWithHostPrefix).Return(false, nil) mockNodeUtils.EXPECT().IsPathExists(targetPathWithHostPrefix).Return(true) mockNodeUtils.EXPECT().IsNotMountPoint(targetPathWithHostPrefix).Return(false, nil) mockNodeUtils.EXPECT().IsDirectory(targetPathWithHostPrefix).Return(true) req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: fsVolCap, VolumeId: volumeId, @@ -746,7 +754,7 @@ func TestNodePublishVolume(t *testing.T) { req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: rawBlockVolumeCap, VolumeId: "vol-test", @@ -776,7 +784,7 @@ func TestNodePublishVolume(t *testing.T) { req := &csi.NodePublishVolumeRequest{ PublishContext: map[string]string{}, - StagingTargetPath: stagingTargetPath, + StagingTargetPath: stagingPath, TargetPath: targetPath, VolumeCapability: rawBlockVolumeCap, VolumeId: "vol-test", @@ -1002,6 +1010,7 @@ func TestNodeExpandVolume(t *testing.T) { mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(false, nil) mockNodeUtils.EXPECT().RescanPhysicalDevices(sysDevices).Return(dummyError) _, err := node.NodeExpandVolume(context.TODO(), expandRequest) @@ -1020,6 +1029,7 @@ func TestNodeExpandVolume(t *testing.T) { mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(false, nil) mockNodeUtils.EXPECT().RescanPhysicalDevices(sysDevices) mockNodeUtils.EXPECT().ExpandMpathDevice(mpathDeviceName).Return(dummyError) @@ -1039,6 +1049,7 @@ func TestNodeExpandVolume(t *testing.T) { mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(false, nil) mockNodeUtils.EXPECT().RescanPhysicalDevices(sysDevices) mockNodeUtils.EXPECT().ExpandMpathDevice(mpathDeviceName) mockMounter.EXPECT().GetDiskFormat(mpathDevice).Return("", dummyError) @@ -1059,6 +1070,7 @@ func TestNodeExpandVolume(t *testing.T) { mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(false, nil) mockNodeUtils.EXPECT().RescanPhysicalDevices(sysDevices) mockNodeUtils.EXPECT().ExpandMpathDevice(mpathDeviceName) mockMounter.EXPECT().GetDiskFormat(mpathDevice).Return(fsType, nil) @@ -1068,6 +1080,29 @@ func TestNodeExpandVolume(t *testing.T) { assertError(t, err, codes.Internal) }, }, + { + name: "success expand volume, nvme", + testFunc: func(t *testing.T) { + mockCtl := gomock.NewController(t) + defer mockCtl.Finish() + mockNodeUtils := mocks.NewMockNodeUtilsInterface(mockCtl) + mockOsDeviceConHelper := mocks.NewMockOsDeviceConnectivityHelperScsiGenericInterface(mockCtl) + mockMounter := mocks.NewMockNodeMounter(mockCtl) + node := newTestNodeServiceExpand(mockNodeUtils, mockOsDeviceConHelper, mockMounter) + + mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) + mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(true, nil) + mockNodeUtils.EXPECT().ExpandMpathDevice(mpathDeviceName) + mockMounter.EXPECT().GetDiskFormat(mpathDevice).Return(fsType, nil) + mockNodeUtils.EXPECT().ExpandFilesystem(mpathDevice, stagingTargetPath, fsType) + + _, err := node.NodeExpandVolume(context.TODO(), expandRequest) + if err != nil { + t.Fatalf("Expect no error but got: %v", err) + } + }, + }, { name: "success expand volume", testFunc: func(t *testing.T) { @@ -1080,6 +1115,7 @@ func TestNodeExpandVolume(t *testing.T) { mockOsDeviceConHelper.EXPECT().GetMpathDevice(volId).Return(mpathDevice, nil) mockNodeUtils.EXPECT().GetSysDevicesFromMpath(mpathDeviceName).Return(rawSysDevices, nil) + mockNodeUtils.EXPECT().DevicesAreNvme(sysDevices).Return(false, nil) mockNodeUtils.EXPECT().RescanPhysicalDevices(sysDevices) mockNodeUtils.EXPECT().ExpandMpathDevice(mpathDeviceName) mockMounter.EXPECT().GetDiskFormat(mpathDevice).Return(fsType, nil) @@ -1138,74 +1174,97 @@ func TestNodeGetInfo(t *testing.T) { topologySegments := map[string]string{"topology.block.csi.ibm.com/zone": "testZone"} testCases := []struct { - name string - return_iqn string - return_iqn_err error - return_fcs []string - return_fc_err error - return_nodeId_err error - expErr error - expNodeId string - iscsiExists bool - fcExists bool + name string + returnNqn string + returnNqnErr error + returnFcs []string + returnFcErr error + returnIqn string + returnIqnErr error + returnNodeIdErr error + expErr error + expNodeId string + nvmeExists bool + fcExists bool + iscsiExists bool }{ { - name: "good iqn, empty fc with error from node_utils", - return_fc_err: fmt.Errorf("some error"), - expErr: status.Error(codes.Internal, fmt.Errorf("some error").Error()), - iscsiExists: true, - fcExists: true, + name: "empty nqn with error from node_utils, valid fcs", + returnNqnErr: fmt.Errorf("some error"), + returnFcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + expNodeId: "test-host;;10000000c9934d9f:10000000c9934d9h", + nvmeExists: true, + fcExists: true, + iscsiExists: true, }, { - name: "empty iqn with error, one fc port", - return_fcs: []string{"10000000c9934d9f"}, - expNodeId: "test-host;10000000c9934d9f", - iscsiExists: true, + name: "empty fc with error from node_utils", + returnFcErr: fmt.Errorf("some error"), + expErr: status.Error(codes.Internal, fmt.Errorf("some error").Error()), + nvmeExists: false, fcExists: true, + iscsiExists: true, }, { - name: "empty iqn with error from node_utils, one more fc ports", - return_iqn: "", - return_fcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, - expNodeId: "test-host;10000000c9934d9f:10000000c9934d9h", - iscsiExists: true, - fcExists: true, + name: "empty iqn with error from node_utils, valid fcs", + returnIqnErr: fmt.Errorf("some error"), + returnFcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + expNodeId: "test-host;;10000000c9934d9f:10000000c9934d9h", + nvmeExists: false, + fcExists: true, + iscsiExists: true, }, { - name: "good iqn and good fcs", - return_iqn: "iqn.1994-07.com.redhat:e123456789", - return_fcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, - expNodeId: "test-host;10000000c9934d9f:10000000c9934d9h;iqn.1994-07.com.redhat:e123456789", + name: "valid iqn and fcs", + returnIqn: "iqn.1994-07.com.redhat:e123456789", + returnFcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + expNodeId: "test-host;;10000000c9934d9f:10000000c9934d9h;iqn.1994-07.com.redhat:e123456789", + nvmeExists: false, + fcExists: true, iscsiExists: true, + }, + { + name: "valid nqn, fcs and iqn", + returnNqn: "nqn.2014-08.org.nvmexpress:uuid:b57708c7-5bb6-46a0-b2af-9d824bf539e1", + returnFcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + returnIqn: "iqn.1994-07.com.redhat:e123456789", + expNodeId: "test-host;nqn.2014-08.org.nvmexpress:uuid:b57708c7-5bb6-46a0-b2af-9d824bf539e1;10000000c9934d9f:10000000c9934d9h;iqn.1994-07.com.redhat:e123456789", + nvmeExists: true, fcExists: true, + iscsiExists: true, }, { - name: "iqn and fc path are inexistent", - iscsiExists: false, + name: "nqn, fc and iqn path are inexistent", + nvmeExists: false, fcExists: false, - expErr: status.Error(codes.Internal, fmt.Errorf("Cannot find valid fc wwns or iscsi iqn").Error()), + iscsiExists: false, + expErr: status.Error(codes.Internal, fmt.Errorf("Cannot find valid nvme nqn, fc wwns or iscsi iqn").Error()), }, { - name: "iqn path is inexistsent", - iscsiExists: false, + name: "nqn and iqn path is inexistsent", + nvmeExists: false, fcExists: true, - return_fcs: []string{"10000000c9934d9f"}, - expNodeId: "test-host;10000000c9934d9f", + iscsiExists: false, + returnFcs: []string{"10000000c9934d9f"}, + expNodeId: "test-host;;10000000c9934d9f", }, { name: "fc path is inexistent", - iscsiExists: true, + nvmeExists: true, fcExists: false, - return_iqn: "iqn.1994-07.com.redhat:e123456789", - expNodeId: "test-host;;iqn.1994-07.com.redhat:e123456789", + iscsiExists: true, + returnNqn: "nqn.2014-08.org.nvmexpress:uuid:b57708c7-5bb6-46a0-b2af-9d824bf539e1", + returnIqn: "iqn.1994-07.com.redhat:e123456789", + expNodeId: "test-host;nqn.2014-08.org.nvmexpress:uuid:b57708c7-5bb6-46a0-b2af-9d824bf539e1;;iqn.1994-07.com.redhat:e123456789", }, { - name: "generate NodeID returns error", - return_iqn: "iqn.1994-07.com.redhat:e123456789", - return_fcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, - return_nodeId_err: fmt.Errorf("some error"), - expErr: status.Error(codes.Internal, fmt.Errorf("some error").Error()), - iscsiExists: true, - fcExists: true, + name: "generate NodeID returns error", + returnIqn: "iqn.1994-07.com.redhat:e123456789", + returnFcs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + returnNodeIdErr: fmt.Errorf("some error"), + expErr: status.Error(codes.Internal, fmt.Errorf("some error").Error()), + nvmeExists: false, + fcExists: true, + iscsiExists: true, }, } for _, tc := range testCases { @@ -1215,22 +1274,26 @@ func TestNodeGetInfo(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_nodeutils := mocks.NewMockNodeUtilsInterface(mockCtrl) - d := newTestNodeService(fake_nodeutils, nil, nil) - fake_nodeutils.EXPECT().GetTopologyLabels(context.TODO(), d.Hostname).Return(topologySegments, nil) - fake_nodeutils.EXPECT().IsFCExists().Return(tc.fcExists) + fakeNodeutils := mocks.NewMockNodeUtilsInterface(mockCtrl) + d := newTestNodeService(fakeNodeutils, nil, nil) + fakeNodeutils.EXPECT().GetTopologyLabels(context.TODO(), d.Hostname).Return(topologySegments, nil) + fakeNodeutils.EXPECT().IsPathExists(driver.NvmeFullPath).Return(tc.nvmeExists) + fakeNodeutils.EXPECT().IsFCExists().Return(tc.fcExists) + if tc.nvmeExists { + fakeNodeutils.EXPECT().ReadNvmeNqn().Return(tc.returnNqn, tc.returnNqnErr) + } if tc.fcExists { - fake_nodeutils.EXPECT().ParseFCPorts().Return(tc.return_fcs, tc.return_fc_err) + fakeNodeutils.EXPECT().ParseFCPorts().Return(tc.returnFcs, tc.returnFcErr) } - if tc.return_fc_err == nil { - fake_nodeutils.EXPECT().IsPathExists(driver.IscsiFullPath).Return(tc.iscsiExists) + if tc.returnFcErr == nil { + fakeNodeutils.EXPECT().IsPathExists(driver.IscsiFullPath).Return(tc.iscsiExists) if tc.iscsiExists { - fake_nodeutils.EXPECT().ParseIscsiInitiators().Return(tc.return_iqn, tc.return_iqn_err) + fakeNodeutils.EXPECT().ParseIscsiInitiators().Return(tc.returnIqn, tc.returnIqnErr) } } - if (tc.iscsiExists || tc.fcExists) && tc.return_fc_err == nil { - fake_nodeutils.EXPECT().GenerateNodeID("test-host", tc.return_fcs, tc.return_iqn).Return(tc.expNodeId, tc.return_nodeId_err) + if tc.returnNqn != "" || len(tc.returnFcs) > 0 || tc.returnIqn != "" { + fakeNodeutils.EXPECT().GenerateNodeID("test-host", tc.returnNqn, tc.returnFcs, tc.returnIqn).Return(tc.expNodeId, tc.returnNodeIdErr) } expTopology := &csi.Topology{Segments: topologySegments} diff --git a/node/pkg/driver/node_utils.go b/node/pkg/driver/node_utils.go index 47aadaf3b..50ce95f63 100644 --- a/node/pkg/driver/node_utils.go +++ b/node/pkg/driver/node_utils.go @@ -46,22 +46,28 @@ var ( const ( // In the Dockerfile of the node, specific commands (e.g: multipath, mount...) from the host mounted inside the container in /host directory. // Command lines inside the container will show /host prefix. - PrefixChrootOfHostRoot = "/host" - PublishContextSeparator = "," - NodeIdDelimiter = ";" - NodeIdFcDelimiter = ":" - mkfsTimeoutMilliseconds = 15 * 60 * 1000 - resizeFsTimeoutMilliseconds = 30 * 1000 - TimeOutMultipathdCmd = 10 * 1000 - multipathdCmd = "multipathd" - minFilesInNonEmptyDir = 1 + PrefixChrootOfHostRoot = "/host" + PublishContextSeparator = "," + NodeIdDelimiter = ";" + NodeIdFcDelimiter = ":" + mkfsTimeoutMilliseconds = 15 * 60 * 1000 + resizeFsTimeoutMilliseconds = 30 * 1000 + TimeOutGeneralCmd = 10 * 1000 + TimeOutMultipathdCmd = TimeOutGeneralCmd + TimeOutNvmeCmd = TimeOutGeneralCmd + multipathdCmd = "multipathd" + nvmeCmd = "nvme" + minFilesInNonEmptyDir = 1 + noSuchFileOrDirectoryErrorMessage = "No such file or directory" ) //go:generate mockgen -destination=../../mocks/mock_node_utils.go -package=mocks github.com/ibm/ibm-block-csi-driver/node/pkg/driver NodeUtilsInterface type NodeUtilsInterface interface { - ParseIscsiInitiators() (string, error) + ReadNvmeNqn() (string, error) + DevicesAreNvme(sysDevices []string) (bool, error) ParseFCPorts() ([]string, error) + ParseIscsiInitiators() (string, error) GetInfoFromPublishContext(publishContext map[string]string, configYaml ConfigFile) (string, int, map[string][]string, error) GetArrayInitiators(ipsByArrayInitiator map[string][]string) []string GetSysDevicesFromMpath(baseDevice string) (string, error) @@ -81,7 +87,7 @@ type NodeUtilsInterface interface { FormatDevice(devicePath string, fsType string) IsNotMountPoint(file string) (bool, error) GetPodPath(filepath string) string - GenerateNodeID(hostName string, fcWWNs []string, iscsiIQN string) (string, error) + GenerateNodeID(hostName string, nvmeNQN string, fcWWNs []string, iscsiIQN string) (string, error) GetTopologyLabels(ctx context.Context, nodeName string) (map[string]string, error) } @@ -97,40 +103,26 @@ func NewNodeUtils(executer executer.ExecuterInterface, mounter mount.Interface) } } -func (n NodeUtils) ParseIscsiInitiators() (string, error) { - file, err := os.Open(IscsiFullPath) - if err != nil { - return "", err - } - - defer file.Close() - - fileOut, err := ioutil.ReadAll(file) - if err != nil { - return "", err - } - - fileSplit := strings.Split(string(fileOut), "InitiatorName=") - if len(fileSplit) != 2 { - return "", fmt.Errorf(ErrorWhileTryingToReadIQN, string(fileOut)) - } - - iscsiIqn := strings.TrimSpace(fileSplit[1]) - - return iscsiIqn, nil -} - func (n NodeUtils) GetInfoFromPublishContext(publishContext map[string]string, configYaml ConfigFile) (string, int, map[string][]string, error) { // this will return : connectivityType, lun, ipsByArrayInitiator, error ipsByArrayInitiator := make(map[string][]string) strLun := publishContext[configYaml.Controller.Publish_context_lun_parameter] - lun, err := strconv.Atoi(strLun) - if err != nil { - return "", -1, nil, err - } - + var lun int + var err error connectivityType := publishContext[configYaml.Controller.Publish_context_connectivity_parameter] + if connectivityType != device_connectivity.ConnectionTypeNVMEoFC { + lun, err = strconv.Atoi(strLun) + if err != nil { + return "", -1, nil, err + } + } + if connectivityType == device_connectivity.ConnectionTypeFC { + wwns := strings.Split(publishContext[configYaml.Controller.Publish_context_fc_initiators], PublishContextSeparator) + for _, wwn := range wwns { + ipsByArrayInitiator[wwn] = nil + } + } if connectivityType == device_connectivity.ConnectionTypeISCSI { iqns := strings.Split(publishContext[configYaml.Controller.Publish_context_array_iqn], PublishContextSeparator) for _, iqn := range iqns { @@ -141,12 +133,6 @@ func (n NodeUtils) GetInfoFromPublishContext(publishContext map[string]string, c } } } - if connectivityType == device_connectivity.ConnectionTypeFC { - wwns := strings.Split(publishContext[configYaml.Controller.Publish_context_fc_initiators], PublishContextSeparator) - for _, wwn := range wwns { - ipsByArrayInitiator[wwn] = nil - } - } logger.Debugf("PublishContext relevant info : connectivityType=%v, lun=%v, arrayInitiators=%v", connectivityType, lun, ipsByArrayInitiator) @@ -197,6 +183,63 @@ func (n NodeUtils) StageInfoFileIsExist(filePath string) bool { return true } +func (n NodeUtils) DevicesAreNvme(sysDevices []string) (bool, error) { + args := []string{"list"} + out, err := n.Executer.ExecuteWithTimeout(TimeOutNvmeCmd, nvmeCmd, args) + if err != nil { + outMessage := strings.TrimSpace(string(out)) + if strings.HasSuffix(outMessage, noSuchFileOrDirectoryErrorMessage) { + return false, nil + } + return false, err + } + nvmeDevices := string(out) + for _, deviceName := range sysDevices { + if strings.Contains(nvmeDevices, deviceName) { + logger.Debugf("found device {%s} in nvme list", deviceName) + return true, nil + } + } + return false, nil +} + +func readFile(path string) (string, error) { + file, err := os.Open(path) + if err != nil { + return "", err + } + + defer file.Close() + + rawContent, err := ioutil.ReadAll(file) + if err != nil { + return "", err + } + + content := string(rawContent) + trimmedContent := strings.TrimSpace(content) + + return trimmedContent, nil +} + +func readAfterPrefix(path string, prefix string, portType string) (string, error) { + fileContent, err := readFile(path) + if err != nil { + return "", err + } + + if !strings.HasPrefix(fileContent, prefix) { + return "", fmt.Errorf(ErrorWhileTryingToReadPort, portType, fileContent) + } + contentPostfix := strings.TrimPrefix(fileContent, prefix) + + return contentPostfix, nil +} + +func (n NodeUtils) ReadNvmeNqn() (string, error) { + return readFile(NvmeFullPath) +} + func (n NodeUtils) ParseFCPorts() ([]string, error) { var errs []error var fcPorts []string @@ -210,31 +253,17 @@ func (n NodeUtils) ParseFCPorts() ([]string, error) { } for _, fpath := range fpaths { - file, err := os.Open(fpath) - if err != nil { - errs = append(errs, err) - break - } - defer file.Close() - - fileOut, err := ioutil.ReadAll(file) + fcPort, err := readAfterPrefix(fpath, "0x", device_connectivity.ConnectionTypeFC) if err != nil { errs = append(errs, err) - break - } - - fileSplit := strings.Split(string(fileOut), "0x") - if len(fileSplit) != 2 { - err := fmt.Errorf(ErrorWhileTryingToReadFC, string(fileOut)) - errs = append(errs, err) } else { - fcPorts = append(fcPorts, strings.TrimSpace(fileSplit[1])) + fcPorts = append(fcPorts, fcPort) } } if errs != nil { err := errors.NewAggregate(errs) - logger.Errorf("errors occured while looking for FC ports: {%v}", err) + logger.Errorf("errors occured while looking for fc ports: {%v}", err) if fcPorts == nil { return nil, err } @@ -243,6 +272,10 @@ func (n NodeUtils) ParseFCPorts() ([]string, error) { return fcPorts, nil } +func (n NodeUtils) ParseIscsiInitiators() (string, error) { + return readAfterPrefix(IscsiFullPath, "InitiatorName=", device_connectivity.ConnectionTypeISCSI) +} + func (n NodeUtils) IsFCExists() bool { return n.IsPathExists(FCPath) && !n.isEmptyDir(FCPath) } @@ -414,16 +447,24 @@ func (n NodeUtils) GetPodPath(origPath string) string { return path.Join(PrefixChrootOfHostRoot, origPath) } -func (n NodeUtils) GenerateNodeID(hostName string, fcWWNs []string, iscsiIQN string) (string, error) { +func (n NodeUtils) GenerateNodeID(hostName string, nvmeNQN string, fcWWNs []string, iscsiIQN string) (string, error) { var nodeId strings.Builder nodeId.Grow(MaxNodeIdLength) nodeId.WriteString(hostName) nodeId.WriteString(NodeIdDelimiter) + if len(nvmeNQN) > 0 { + if nodeId.Len()+len(nvmeNQN)+len(NodeIdDelimiter) <= MaxNodeIdLength { + nodeId.WriteString(nvmeNQN) + } else { + return "", fmt.Errorf(ErrorNoPortsCouldFitInNodeId, nodeId.String(), MaxNodeIdLength) + } + } + nodeId.WriteString(NodeIdDelimiter) if len(fcWWNs) > 0 { if nodeId.Len()+len(fcWWNs[0]) <= MaxNodeIdLength { nodeId.WriteString(fcWWNs[0]) - } else { + } else if nvmeNQN == "" { return "", fmt.Errorf(ErrorNoPortsCouldFitInNodeId, nodeId.String(), MaxNodeIdLength) } @@ -438,12 +479,13 @@ func (n NodeUtils) GenerateNodeID(hostName string, fcWWNs []string, iscsiIQN str if nodeId.Len()+len(NodeIdDelimiter)+len(iscsiIQN) <= MaxNodeIdLength { nodeId.WriteString(NodeIdDelimiter) nodeId.WriteString(iscsiIQN) - } else if len(fcWWNs) == 0 { + } else if len(fcWWNs) == 0 && nvmeNQN == "" { return "", fmt.Errorf(ErrorNoPortsCouldFitInNodeId, nodeId.String(), MaxNodeIdLength) } } - return nodeId.String(), nil + finalNodeId := strings.TrimSuffix(nodeId.String(), ";") + return finalNodeId, nil } func (n NodeUtils) GetTopologyLabels(ctx context.Context, nodeName string) (map[string]string, error) { diff --git a/node/pkg/driver/node_utils_test.go b/node/pkg/driver/node_utils_test.go index e5e441bfe..80438b2fd 100644 --- a/node/pkg/driver/node_utils_test.go +++ b/node/pkg/driver/node_utils_test.go @@ -22,6 +22,7 @@ import ( "io/ioutil" "os" "reflect" + "strings" "syscall" "testing" @@ -33,29 +34,30 @@ import ( ) var ( - nodeUtils = driver.NewNodeUtils(&executer.Executer{}, nil) + nodeUtils = driver.NewNodeUtils(&executer.Executer{}, nil) + maxNodeIdLength = driver.MaxNodeIdLength + hostName = "test-hostname" + longHostName = strings.Repeat(hostName, 15) + nvmeNQN = "nqn.2014-08.org.nvmexpress:uuid:b57708c7-5bb6-46a0-b2af-9d824bf539e1" + fcWWNs = []string{"10000000c9934d9f", "10000000c9934d9h", "10000000c9934d9a", "10000000c9934d9b", "10000000c9934d9z"} + iscsiIQN = "iqn.1994-07.com.redhat:e123456789" ) -func TestParseIscsiInitiators(t *testing.T) { +func TestReadNvmeNqn(t *testing.T) { testCases := []struct { name string file_content string expErr error - expIqn string + expNqn string }{ - { - name: "wrong iqn file", - file_content: "wrong-content", - expErr: fmt.Errorf(driver.ErrorWhileTryingToReadIQN, "wrong-content"), - }, { name: "non existing file", expErr: &os.PathError{Op: "open", Path: "/non/existent/path", Err: syscall.ENOENT}, }, { - name: "right_iqn", - file_content: "InitiatorName=iqn.1996-05.com.redhat:123123122", - expIqn: "iqn.1996-05.com.redhat:123123122", + name: "right_nqn", + file_content: nvmeNQN, + expNqn: nvmeNQN, }, } @@ -65,7 +67,7 @@ func TestParseIscsiInitiators(t *testing.T) { filePath := "" if tc.file_content != "" { - tmpFile, err := ioutil.TempFile(os.TempDir(), "iscis-initiators-") + tmpFile, err := ioutil.TempFile(os.TempDir(), "nvme-") fmt.Println(tmpFile) if err != nil { t.Fatalf("Cannot create temporary file : %v", err) @@ -73,7 +75,7 @@ func TestParseIscsiInitiators(t *testing.T) { defer func() { os.Remove(tmpFile.Name()) - driver.IscsiFullPath = "/host/etc/iscsi/initiatorname.iscsi" + driver.NvmeFullPath = "/host/etc/nvme/hostnqn" }() fmt.Println("Created File: " + tmpFile.Name()) @@ -91,8 +93,8 @@ func TestParseIscsiInitiators(t *testing.T) { filePath = "/non/existent/path" } - driver.IscsiFullPath = filePath - isci, err := nodeUtils.ParseIscsiInitiators() + driver.NvmeFullPath = filePath + nqn, err := nodeUtils.ReadNvmeNqn() if tc.expErr != nil { if err.Error() != tc.expErr.Error() { @@ -103,8 +105,8 @@ func TestParseIscsiInitiators(t *testing.T) { if err != nil { t.Fatalf("err is not nil. got: %v", err) } - if isci != tc.expIqn { - t.Fatalf("scheme mismatches: expected %v, got %v", tc.expIqn, isci) + if nqn != tc.expNqn { + t.Fatalf("scheme mismatches: expected %v, got %v", tc.expNqn, nqn) } } @@ -125,26 +127,26 @@ func TestParseFCPortsName(t *testing.T) { { name: "fc port file with wrong content", file_contents: []string{"wrong content"}, - expErr: fmt.Errorf(driver.ErrorWhileTryingToReadFC, "wrong content"), + expErr: fmt.Errorf(driver.ErrorWhileTryingToReadPort, device_connectivity.ConnectionTypeFC, "wrong content"), }, { name: "fc unsupported", expErr: fmt.Errorf(driver.ErrorUnsupportedConnectivityType, device_connectivity.ConnectionTypeFC), }, { - name: "one FC port", + name: "one fc port", file_contents: []string{"0x10000000c9934d9f"}, expFCPorts: []string{"10000000c9934d9f"}, }, { - name: "one FC port file with wrong content, another is good", + name: "one fc port file with wrong content, another is valid", file_contents: []string{"wrong content", "0x10000000c9934dab"}, expFCPorts: []string{"10000000c9934dab"}, }, { - name: "one fc port file with wrong content, aonther file path is inexistent", + name: "one fc port file with wrong content, another file path is inexistent", file_contents: []string{"wrong content", ""}, - expErr: errors.New("[Error while tring to get FC port from string: wrong content., open /non/existent/path: no such file or directory]"), + expErr: errors.New("[Error while trying to get fc port from string: wrong content., open /non/existent/path: no such file or directory]"), }, { name: "two FC ports", @@ -187,10 +189,10 @@ func TestParseFCPortsName(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) devicePath := "/sys/class/fc_host/host*/port_name" - fake_executer.EXPECT().FilepathGlob(devicePath).Return(fpaths, tc.err) - nodeUtils := driver.NewNodeUtils(fake_executer, nil) + fakeExecuter.EXPECT().FilepathGlob(devicePath).Return(fpaths, tc.err) + nodeUtils := driver.NewNodeUtils(fakeExecuter, nil) fcs, err := nodeUtils.ParseFCPorts() @@ -212,50 +214,149 @@ func TestParseFCPortsName(t *testing.T) { } } +func TestParseIscsiInitiators(t *testing.T) { + testCases := []struct { + name string + file_content string + expErr error + expIqn string + }{ + { + name: "wrong iqn file", + file_content: "wrong-content", + expErr: fmt.Errorf(driver.ErrorWhileTryingToReadPort, device_connectivity.ConnectionTypeISCSI, "wrong-content"), + }, + { + name: "non existing file", + expErr: &os.PathError{Op: "open", Path: "/non/existent/path", Err: syscall.ENOENT}, + }, + { + name: "right_iqn", + file_content: fmt.Sprintf("InitiatorName=%s", iscsiIQN), + expIqn: iscsiIQN, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + + filePath := "" + + if tc.file_content != "" { + tmpFile, err := ioutil.TempFile(os.TempDir(), "iscis-initiators-") + fmt.Println(tmpFile) + if err != nil { + t.Fatalf("Cannot create temporary file : %v", err) + } + + defer func() { + os.Remove(tmpFile.Name()) + driver.IscsiFullPath = "/host/etc/iscsi/initiatorname.iscsi" + }() + + fmt.Println("Created File: " + tmpFile.Name()) + + text := []byte(tc.file_content) + if _, err = tmpFile.Write(text); err != nil { + t.Fatalf("Failed to write to temporary file: %v", err) + } + + if err := tmpFile.Close(); err != nil { + t.Fatalf(err.Error()) + } + filePath = tmpFile.Name() + } else { + filePath = "/non/existent/path" + } + + driver.IscsiFullPath = filePath + isci, err := nodeUtils.ParseIscsiInitiators() + + if tc.expErr != nil { + if err.Error() != tc.expErr.Error() { + t.Fatalf("Expecting err: expected %v, got %v", tc.expErr, err) + } + + } else { + if err != nil { + t.Fatalf("err is not nil. got: %v", err) + } + if isci != tc.expIqn { + t.Fatalf("scheme mismatches: expected %v, got %v", tc.expIqn, isci) + } + + } + + }) + } + +} + func TestGenerateNodeID(t *testing.T) { testCases := []struct { name string hostName string + nvmeNQN string fcWWNs []string iscsiIQN string expErr error expNodeId string }{ - {name: "success all in", - hostName: "test-host", - fcWWNs: []string{"10000000c9934d9f", "10000000c9934d9h"}, - iscsiIQN: "iqn.1994-07.com.redhat:e123456789", - expNodeId: "test-host;10000000c9934d9f:10000000c9934d9h;iqn.1994-07.com.redhat:e123456789", + {name: "success all given, only nvme and fc in", + hostName: hostName, + nvmeNQN: nvmeNQN, + fcWWNs: fcWWNs[:2], + iscsiIQN: iscsiIQN, + expNodeId: fmt.Sprintf("%s;%s;%s", hostName, nvmeNQN, strings.Join(fcWWNs[:2], ":")), }, - {name: "success no fc ports", - hostName: "test-hostname.ibm.com", + {name: "success only iscsi port", + hostName: hostName, + nvmeNQN: "", fcWWNs: []string{}, - iscsiIQN: "iqn.1994-07.com.redhat:e123456789", - expNodeId: "test-hostname.ibm.com;;iqn.1994-07.com.redhat:e123456789", + iscsiIQN: iscsiIQN, + expNodeId: fmt.Sprintf("%s;;;%s", hostName, iscsiIQN), }, - {name: "success no iscsi port", - hostName: "test-hostname.ibm.com", - fcWWNs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + {name: "success only fc ports", + hostName: hostName, + nvmeNQN: "", + fcWWNs: fcWWNs[:2], iscsiIQN: "", - expNodeId: "test-hostname.ibm.com;10000000c9934d9f:10000000c9934d9h", + expNodeId: fmt.Sprintf("%s;;%s", hostName, strings.Join(fcWWNs[:2], ":")), }, - {name: "success many fc ports", - hostName: "test-hostname.ibm.com", - fcWWNs: []string{"10000000c9934d9f", "10000000c9934d9h", "10000000c9934d9a", "10000000c9934d9b", "10000000c9934d9z"}, - iscsiIQN: "iqn.1994-07.com.redhat:e123456789", - expNodeId: "test-hostname.ibm.com;10000000c9934d9f:10000000c9934d9h:10000000c9934d9a:10000000c9934d9b:10000000c9934d9z", + {name: "success only nvme port", + hostName: hostName, + nvmeNQN: nvmeNQN, + fcWWNs: []string{}, + iscsiIQN: "", + expNodeId: fmt.Sprintf("%s;%s", hostName, nvmeNQN), + }, + {name: "success fc ports and iscsi port", + hostName: hostName, + nvmeNQN: "", + fcWWNs: fcWWNs[:2], + iscsiIQN: iscsiIQN, + expNodeId: fmt.Sprintf("%s;;%s;%s", hostName, strings.Join(fcWWNs[:2], ":"), iscsiIQN), + }, + {name: "fail long hostName on nvme port", + hostName: longHostName, + nvmeNQN: nvmeNQN, + fcWWNs: []string{}, + iscsiIQN: "", + expErr: errors.New(fmt.Sprintf("could not fit any ports in node id: %s;, length limit: %d", longHostName, maxNodeIdLength)), }, {name: "fail long hostName on fc ports", - hostName: "test-hostname-that-is-too-long-and-take-almost-128-characters-so-no-port-get-place-additional-characters.nodeutilstest.ibm.com", - fcWWNs: []string{"10000000c9934d9f", "10000000c9934d9h"}, + hostName: longHostName, + nvmeNQN: "", + fcWWNs: fcWWNs[:2], iscsiIQN: "", - expErr: errors.New("could not fit any ports in node id: test-hostname-that-is-too-long-and-take-almost-128-characters-so-no-port-get-place-additional-characters.nodeutilstest.ibm.com;, length limit: 128"), + expErr: errors.New(fmt.Sprintf("could not fit any ports in node id: %s;;, length limit: %d", longHostName, maxNodeIdLength)), }, - {name: "fail long hostName on iscsi ports", - hostName: "test-hostname-that-is-too-long-and-take-almost-128-characters-so-no-port-get-place-additional-characters.nodeutilstest.ibm.com", + {name: "fail long hostName on iscsi port", + hostName: longHostName, + nvmeNQN: "", fcWWNs: []string{}, - iscsiIQN: "iqn.1994-07.com.redhat:e123456789", - expErr: errors.New("could not fit any ports in node id: test-hostname-that-is-too-long-and-take-almost-128-characters-so-no-port-get-place-additional-characters.nodeutilstest.ibm.com;, length limit: 128"), + iscsiIQN: iscsiIQN, + expErr: errors.New(fmt.Sprintf("could not fit any ports in node id: %s;;, length limit: %d", longHostName, maxNodeIdLength)), }, } for _, tc := range testCases { @@ -264,13 +365,13 @@ func TestGenerateNodeID(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() - fake_executer := mocks.NewMockExecuterInterface(mockCtrl) - nodeUtils := driver.NewNodeUtils(fake_executer, nil) + fakeExecuter := mocks.NewMockExecuterInterface(mockCtrl) + nodeUtils := driver.NewNodeUtils(fakeExecuter, nil) - nodeId, err := nodeUtils.GenerateNodeID(tc.hostName, tc.fcWWNs, tc.iscsiIQN) + nodeId, err := nodeUtils.GenerateNodeID(tc.hostName, tc.nvmeNQN, tc.fcWWNs, tc.iscsiIQN) if tc.expErr != nil { - if err.Error() != tc.expErr.Error() { + if err == nil || err.Error() != tc.expErr.Error() { t.Fatalf("Expecting err: expected %v, got %v", tc.expErr, err) } diff --git a/node/pkg/driver/version_test.go b/node/pkg/driver/version_test.go index ffef8696c..9efac1b1b 100644 --- a/node/pkg/driver/version_test.go +++ b/node/pkg/driver/version_test.go @@ -46,7 +46,7 @@ func TestGetVersion(t *testing.T) { version, err := GetVersion(dir) expected := VersionInfo{ - DriverVersion: "1.7.0", + DriverVersion: "1.8.0", GitCommit: "", BuildDate: "", GoVersion: runtime.Version(), @@ -76,7 +76,7 @@ func TestGetVersionJSON(t *testing.T) { } expected := fmt.Sprintf(`{ - "driverVersion": "1.7.0", + "driverVersion": "1.8.0", "gitCommit": "", "buildDate": "", "goVersion": "%s", diff --git a/scripts/ci/Jenkinsfile b/scripts/ci/Jenkinsfile index 95c72e5bb..8a27e58b9 100644 --- a/scripts/ci/Jenkinsfile +++ b/scripts/ci/Jenkinsfile @@ -1,6 +1,6 @@ pipeline { parameters { - string(name: 'IMAGE_VERSION', defaultValue: "1.7.0") + string(name: 'IMAGE_VERSION', defaultValue: "1.8.0") string(name: 'DOCKER_REGISTRY', defaultValue: DEFAULT_DOCKER_REGISTRY) string(name: 'EMAIL_TO', defaultValue: "") } @@ -39,9 +39,11 @@ pipeline { stage ('CSI-controller & node: Build and push images') { steps { script { - registryUrl = "https://${DOCKER_REGISTRY}" - docker.withRegistry(registryUrl, registryCredentialsID) { + registryUrl = "${DOCKER_REGISTRY}" + withCredentials([usernamePassword(credentialsId: registryCredentialsID, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { + sh 'docker login -u $USERNAME -p $PASSWORD ${DOCKER_REGISTRY}' sh './scripts/ci/build_push_images.sh build/reports/images_url' + sh 'docker logout ${DOCKER_REGISTRY}' } } }