├── bin └── .gitkeep ├── tests ├── e2e │ ├── reports │ │ └── .gitkeep │ └── common │ │ ├── testcontext.go │ │ ├── types.go │ │ └── helm.go ├── e2e-test-framework │ ├── logs │ │ └── .dummy │ ├── .flake8 │ ├── requirements.txt │ ├── pytest.ini │ ├── framework │ │ ├── docker_helper.py │ │ ├── test_description_plugin.py │ │ ├── propagating_thread.py │ │ ├── kubernetes_helper.py │ │ ├── ssh.py │ │ └── const.py │ ├── tox.ini │ ├── tests │ │ ├── test_sts_hdd.py │ │ └── test_sts_loopback.py │ └── README.md ├── kind │ ├── small-kind.yaml │ ├── kind-0.8.1.patch │ ├── kind-0.11.1.patch │ └── kind.yaml ├── app │ ├── nginx-inline.yaml │ ├── nginx.yaml │ ├── nginx-block.yaml │ ├── nginx-block-lvg.yaml │ ├── nginx-generic-ephemeral.yaml │ └── nginx-lvg.yaml └── ci.sh ├── docs ├── proposals │ ├── drive-replacement.md │ ├── images │ │ ├── Patcher_flow.png │ │ ├── extender_flow.png │ │ ├── ACR_limitations.png │ │ ├── drive_including.png │ │ ├── Operator_vanilla_flow.png │ │ ├── Patcher_SIGTERM_flow.png │ │ ├── disk_taint_user_case.png │ │ ├── Operator_openshift_flow.png │ │ ├── failed_volume_proposal.png │ │ ├── handle_capacity_request.png │ │ ├── disk_taint_scheduler_process.png │ │ ├── disk_taint_scenario_1_callchain.png │ │ ├── disk_taint_scenario_2_callchain.png │ │ ├── Operator_vanilla_deletion-handle.png │ │ └── Operator_Openshift_deletion-handle.png │ ├── failed-volume-proposal.md │ ├── TEMPLATE.md │ ├── immediate-volume-binding-mode.md │ └── distributed-tracing-of-volume-requests.md ├── images │ ├── drive_usage.png │ ├── volume_csi.png │ ├── delete_volume.png │ ├── drive_health.png │ ├── expand_volume.png │ ├── csi_architecture.png │ ├── release_workflow.png │ ├── unpublish_volume.png │ ├── drive_usage_status.png │ ├── volume_usage_status.png │ ├── drive_removal_workflow.png │ └── create_and_publish_volume.png ├── CODEOWNERS ├── volume-requests-flow.md ├── PULL_REQUEST_TEMPLATE.md ├── crds-generation.md ├── supported-mount-options.md ├── maintenance-mode.md ├── DOC_TEMPLATE.md ├── volume-statuses.md └── block-mode.md ├── pkg ├── controller │ ├── Dockerfile.build │ ├── Dockerfile │ ├── Dockerfile.debug │ ├── identity_test.go │ └── mountoptions │ │ └── mount_options.go ├── scheduler │ ├── plugin │ │ └── Dockerfile │ ├── patcher │ │ ├── Dockerfile │ │ └── requirements.txt │ └── extender │ │ ├── Dockerfile │ │ ├── healthserver │ │ └── common │ │ │ └── common.go │ │ └── README.md ├── node │ ├── Dockerfile │ ├── Dockerfile-kernel-5.4 │ ├── Dockerfile.build │ ├── Dockerfile-kernel-5.4.build │ ├── wbt │ │ └── common │ │ │ └── config.go │ ├── provisioners │ │ ├── utilwrappers │ │ │ └── doc.go │ │ └── volumeprovisioner.go │ ├── smart_test.go │ └── liveness_check_test.go ├── drivemgr │ ├── basemgr │ │ ├── Dockerfile │ │ └── Dockerfile.build │ ├── loopbackmgr │ │ ├── Dockerfile │ │ └── Dockerfile.build │ ├── drivemgr-update-history.md │ └── drivemgr.go ├── crcontrollers │ └── node │ │ ├── Dockerfile │ │ └── common │ │ └── const.go ├── base │ ├── error │ │ ├── k8s.go │ │ └── types.go │ ├── logger │ │ ├── objects │ │ │ ├── node.go │ │ │ ├── drive.go │ │ │ ├── volume.go │ │ │ ├── logical_volume_group.go │ │ │ ├── available_capacity.go │ │ │ └── available_capacity_reservation.go │ │ ├── logger_test.go │ │ └── runtime_formatter.go │ ├── net │ │ ├── connect_test.go │ │ └── connect.go │ ├── k8s │ │ ├── kubeclientset_test.go │ │ ├── kubeclientset.go │ │ └── kubecache_test.go │ ├── util │ │ ├── logging.go │ │ ├── healthcheck.go │ │ ├── volume_helper_test.go │ │ ├── healthcheck_test.go │ │ ├── signal_handler.go │ │ └── parser.go │ ├── linuxutils │ │ ├── datadiscover │ │ │ └── types │ │ │ │ └── types.go │ │ └── ipmi │ │ │ └── ipmitool_test.go │ ├── featureconfig │ │ └── feature_test.go │ ├── cache │ │ ├── cache_test.go │ │ └── cache.go │ ├── rpc │ │ └── grpcclient_test.go │ └── capacityplanner │ │ └── common.go ├── mocks │ ├── linuxutils │ │ ├── datadiscover.go │ │ ├── lsscsi.go │ │ ├── nvmecli.go │ │ ├── wbt.go │ │ ├── smartctl.go │ │ └── lsblk.go │ ├── drives.go │ ├── rpc │ │ └── mock_health_server.go │ ├── events.go │ └── provisioners │ │ ├── mock_parititoner.go │ │ ├── fs_operations.go │ │ └── provisioner.go ├── events │ ├── mocks │ │ ├── EventRecorder.go │ │ └── EventSink.go │ └── example_test.go ├── metrics │ ├── common │ │ ├── sysutil.go │ │ ├── reconcile.go │ │ ├── kubeclient.go │ │ ├── controller.go │ │ ├── node.go │ │ └── ac_reservation.go │ └── metrics_test.go ├── eventing │ └── event_manager.go └── testutils │ └── testutils.go ├── api ├── smart │ ├── generated │ │ ├── oas_request_decoders_gen.go │ │ ├── oas_request_encoders_gen.go │ │ ├── oas_middleware_gen.go │ │ ├── oas_interfaces_gen.go │ │ ├── oas_unimplemented_gen.go │ │ ├── oas_server_gen.go │ │ ├── oas_labeler_gen.go │ │ └── oas_parameters_gen.go │ └── api │ │ └── generate.go └── v1 │ ├── drivemgrsvc.proto │ ├── drivecrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go │ ├── volumecrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go │ ├── lvgcrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go │ ├── nodecrd │ ├── groupversion_info.go │ ├── zz_generated.deepcopy.go │ └── node_types.go │ ├── acreservationcrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go │ ├── storagegroupcrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go │ └── availablecapacitycrd │ ├── groupversion_info.go │ └── zz_generated.deepcopy.go ├── .github ├── .codecov.yaml ├── workflows │ ├── tests │ │ ├── release.json │ │ └── pre-release.json │ ├── devkit.yml │ └── release.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── .gitignore ├── devkit ├── kind │ ├── kind-build.sh │ ├── kind-0.8.1.patch │ ├── kind-0.11.1.patch │ ├── kind-0.17.0.patch │ └── kind-0.23.0.patch └── start_ide.sh └── cmd ├── scheduling └── scheduler │ └── main.go └── drivemgr ├── setup.go ├── basemgr └── main.go └── idracmgr └── main.go /bin/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/e2e/reports/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/proposals/drive-replacement.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/logs/.dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pkg/controller/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | ADD health_probe health_probe 4 | -------------------------------------------------------------------------------- /docs/images/drive_usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/drive_usage.png -------------------------------------------------------------------------------- /docs/images/volume_csi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/volume_csi.png -------------------------------------------------------------------------------- /api/smart/generated/oas_request_decoders_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | -------------------------------------------------------------------------------- /api/smart/generated/oas_request_encoders_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | -------------------------------------------------------------------------------- /docs/images/delete_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/delete_volume.png -------------------------------------------------------------------------------- /docs/images/drive_health.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/drive_health.png -------------------------------------------------------------------------------- /docs/images/expand_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/expand_volume.png -------------------------------------------------------------------------------- /docs/images/csi_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/csi_architecture.png -------------------------------------------------------------------------------- /docs/images/release_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/release_workflow.png -------------------------------------------------------------------------------- /docs/images/unpublish_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/unpublish_volume.png -------------------------------------------------------------------------------- /docs/images/drive_usage_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/drive_usage_status.png -------------------------------------------------------------------------------- /docs/images/volume_usage_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/volume_usage_status.png -------------------------------------------------------------------------------- /docs/images/drive_removal_workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/drive_removal_workflow.png -------------------------------------------------------------------------------- /docs/proposals/images/Patcher_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Patcher_flow.png -------------------------------------------------------------------------------- /docs/proposals/images/extender_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/extender_flow.png -------------------------------------------------------------------------------- /docs/images/create_and_publish_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/images/create_and_publish_volume.png -------------------------------------------------------------------------------- /docs/proposals/images/ACR_limitations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/ACR_limitations.png -------------------------------------------------------------------------------- /docs/proposals/images/drive_including.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/drive_including.png -------------------------------------------------------------------------------- /docs/proposals/images/Operator_vanilla_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Operator_vanilla_flow.png -------------------------------------------------------------------------------- /docs/proposals/images/Patcher_SIGTERM_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Patcher_SIGTERM_flow.png -------------------------------------------------------------------------------- /docs/proposals/images/disk_taint_user_case.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/disk_taint_user_case.png -------------------------------------------------------------------------------- /docs/proposals/images/Operator_openshift_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Operator_openshift_flow.png -------------------------------------------------------------------------------- /docs/proposals/images/failed_volume_proposal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/failed_volume_proposal.png -------------------------------------------------------------------------------- /docs/proposals/images/handle_capacity_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/handle_capacity_request.png -------------------------------------------------------------------------------- /api/smart/api/generate.go: -------------------------------------------------------------------------------- 1 | package smartapi 2 | 3 | //go:generate go run github.com/ogen-go/ogen/cmd/ogen@latest --target ../generated --clean smart.yaml 4 | -------------------------------------------------------------------------------- /docs/proposals/images/disk_taint_scheduler_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/disk_taint_scheduler_process.png -------------------------------------------------------------------------------- /docs/proposals/images/disk_taint_scenario_1_callchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/disk_taint_scenario_1_callchain.png -------------------------------------------------------------------------------- /docs/proposals/images/disk_taint_scenario_2_callchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/disk_taint_scenario_2_callchain.png -------------------------------------------------------------------------------- /docs/proposals/images/Operator_vanilla_deletion-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Operator_vanilla_deletion-handle.png -------------------------------------------------------------------------------- /docs/proposals/images/Operator_Openshift_deletion-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dell/csi-baremetal/HEAD/docs/proposals/images/Operator_Openshift_deletion-handle.png -------------------------------------------------------------------------------- /pkg/scheduler/plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | LABEL description="Bare-metal CSI Scheduler" 4 | 5 | ADD scheduler scheduler 6 | 7 | ENTRYPOINT ["/scheduler"] 8 | -------------------------------------------------------------------------------- /pkg/node/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:base 2 | 3 | LABEL description="Bare-metal CSI Node Service" 4 | 5 | ADD node node 6 | 7 | EXPOSE 9999 8 | 9 | ENTRYPOINT ["/node"] 10 | -------------------------------------------------------------------------------- /pkg/node/Dockerfile-kernel-5.4: -------------------------------------------------------------------------------- 1 | FROM node:base-kernel-5.4 2 | 3 | LABEL description="Bare-metal CSI Node Service" 4 | 5 | ADD node node 6 | 7 | EXPOSE 9999 8 | 9 | ENTRYPOINT ["/node"] 10 | -------------------------------------------------------------------------------- /pkg/scheduler/patcher/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.13.0rc1-alpine3.19 2 | 3 | COPY requirements.txt main.py /patcher/ 4 | WORKDIR /patcher 5 | 6 | RUN pip3 install -r requirements.txt 7 | 8 | ENTRYPOINT ["python3","main.py"] 9 | -------------------------------------------------------------------------------- /pkg/drivemgr/basemgr/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM basemgr:base 2 | 3 | LABEL description="Bare-metal CSI Base Drive Manager" 4 | 5 | ADD basemgr base-drivemgr 6 | 7 | EXPOSE 8888 8 | 9 | ENTRYPOINT ["./base-drivemgr"] 10 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | select = E,F,W,C901 3 | max-line-length = 210 4 | exclude = .git,.tox,dist,tests,docs,*egg*,build,__init__.py,setup.py,sanity-test,conftest.py 5 | max-complexity = 10 6 | ignore = W503 7 | -------------------------------------------------------------------------------- /pkg/drivemgr/loopbackmgr/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM loopbackmgr:base 2 | 3 | LABEL description="Bare-metal CSI Loopback Drive Manager" 4 | 5 | ADD loopbackmgr loopback-drivemgr 6 | 7 | EXPOSE 8888 8 | 9 | ENTRYPOINT ["./loopback-drivemgr"] 10 | -------------------------------------------------------------------------------- /docs/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # file is used to notify teams or individuals about 2 | # changes to directories or files of interest. 3 | # 4 | # See https://help.github.com/articles/about-codeowners/ 5 | # for more info about the CODEOWNERS file. 6 | 7 | * @dell/csi-baremetal 8 | -------------------------------------------------------------------------------- /api/smart/generated/oas_middleware_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | "github.com/ogen-go/ogen/middleware" 7 | ) 8 | 9 | // Middleware is middleware type. 10 | type Middleware = middleware.Middleware 11 | -------------------------------------------------------------------------------- /api/smart/generated/oas_interfaces_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | package api 3 | 4 | type GetAllDrivesSmartInfoRes interface { 5 | getAllDrivesSmartInfoRes() 6 | } 7 | 8 | type GetDriveSmartInfoRes interface { 9 | getDriveSmartInfoRes() 10 | } 11 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest==8.2.1 2 | pytest-html-reporter==0.2.9 3 | kubernetes==29.0.0 4 | tox==4.14.2 5 | flake8==7.0.0 6 | pylint==3.2.2 7 | paramiko==3.4.0 8 | wiremock==2.6.1 9 | docker==7.1.0 10 | requests==2.32.2 11 | testcontainers==4.5.1 12 | -------------------------------------------------------------------------------- /pkg/controller/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM controller:base 2 | 3 | LABEL description="Bare-metal CSI Controller Service" 4 | 5 | ADD controller /controller 6 | 7 | RUN addgroup -S bmcsi && adduser -S bmcsi -u 1000 -G bmcsi 8 | 9 | USER 1000 10 | 11 | ENTRYPOINT ["/controller"] 12 | -------------------------------------------------------------------------------- /pkg/node/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | ADD health_probe health_probe 4 | 5 | RUN apt update --no-install-recommends -y -q; apt install --no-install-recommends -y -q util-linux parted xfsprogs lvm2 fdisk gdisk strace udev net-tools; apt upgrade --no-install-recommends -y -q 6 | -------------------------------------------------------------------------------- /pkg/node/Dockerfile-kernel-5.4.build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | ADD health_probe health_probe 4 | 5 | RUN apt update --no-install-recommends -y -q; apt install --no-install-recommends -y -q util-linux parted xfsprogs lvm2 fdisk gdisk strace udev net-tools; apt upgrade --no-install-recommends -y -q 6 | -------------------------------------------------------------------------------- /.github/.codecov.yaml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 70..85 3 | round: down 4 | precision: 2 5 | status: 6 | project: 7 | default: 8 | threshold: 1% 9 | ignore: 10 | # test module 11 | - "pkg/base/k8s/fake_kubeclient.go" 12 | - "pkg/mocks/k8sclient.go" 13 | - "pkg/mocks/manager.go" -------------------------------------------------------------------------------- /pkg/crcontrollers/node/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | LABEL description="Baremetal CSI Operator" 4 | 5 | ADD controller node-controller 6 | 7 | RUN apk update; apk upgrade 8 | 9 | RUN addgroup -S bmcsi && adduser -S bmcsi -u 1000 -G bmcsi 10 | 11 | USER 1000 12 | 13 | ENTRYPOINT ["/node-controller"] 14 | -------------------------------------------------------------------------------- /pkg/base/error/k8s.go: -------------------------------------------------------------------------------- 1 | package error 2 | 3 | import k8sError "k8s.io/apimachinery/pkg/api/errors" 4 | 5 | // IsSafeReturnError returns if error is safe to retry 6 | func IsSafeReturnError(err error) bool { 7 | return k8sError.IsServerTimeout(err) || 8 | k8sError.IsTimeout(err) || 9 | k8sError.IsTooManyRequests(err) 10 | } 11 | -------------------------------------------------------------------------------- /pkg/controller/Dockerfile.debug: -------------------------------------------------------------------------------- 1 | FROM controller:base 2 | 3 | LABEL description="Bare-metal CSI Controller Service" 4 | 5 | ADD controller /controller 6 | ADD dlv /dlv 7 | 8 | EXPOSE 40000 9 | 10 | ENTRYPOINT ["/dlv", "--listen", "0.0.0.0:40000", "--headless=true", "--api-version=2", "exec", "--", "./controller"] 11 | -------------------------------------------------------------------------------- /.github/workflows/tests/release.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "release": { 4 | "tag_name": "v1.1.0-test", 5 | "target_commitish": "master", 6 | "name": "Release v1.1.0-test", 7 | "draft": false, 8 | "prerelease": false, 9 | "body": "csi_version: 1.1.0-569.d875c82, csi_operator_version: 1.1.0-99.36a85e3" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/tests/pre-release.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "release": { 4 | "tag_name": "v1.1.0-test", 5 | "target_commitish": "master", 6 | "name": "Release v1.1.0-test", 7 | "draft": false, 8 | "prerelease": true, 9 | "body": "csi_version: 1.1.0-569.d875c82, csi_operator_version: 1.1.0-99.36a85e3" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/volume-requests-flow.md: -------------------------------------------------------------------------------- 1 | # Flow diagrams of CSI volume requests across different components 2 | ## Create and publish 3 | ![Screenshot](images/create_and_publish_volume.png) 4 | ## Expand 5 | ![Screenshot](images/expand_volume.png) 6 | ## Unpublish 7 | ![Screenshot](images/unpublish_volume.png) 8 | ## Delete 9 | ![Screenshot](images/delete_volume.png) 10 | 11 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19 2 | 3 | LABEL description="Bare-metal CSI Scheduler Extender" 4 | 5 | ADD extender extender 6 | 7 | ADD health_probe health_probe 8 | 9 | RUN apk update; apk upgrade 10 | 11 | RUN addgroup -S bmcsi && adduser -S bmcsi -u 1000 -G bmcsi 12 | 13 | USER 1000 14 | 15 | ENTRYPOINT ["/extender"] 16 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = -vs -rfEps --no-header --disable-pytest-warnings --html-report=./report --title='CSI BAREMETAL EXECUTION REPORT' 3 | log_cli = true 4 | log_cli_level = INFO 5 | log_cli_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s) 6 | log_cli_date_format=%Y-%m-%d %H:%M:%S 7 | markers = 8 | example: marks example tests 9 | -------------------------------------------------------------------------------- /pkg/scheduler/patcher/requirements.txt: -------------------------------------------------------------------------------- 1 | cachetools==5.0.0 2 | certifi==2024.07.04 3 | chardet==4.0.0 4 | google-auth==2.6.6 5 | idna==3.3 6 | kubernetes==23.3.0b1 7 | oauthlib==3.2.0 8 | pyasn1==0.4.8 9 | pyasn1-modules==0.2.8 10 | python-dateutil==2.8.2 11 | PyYAML==6.0.1 12 | requests==2.27.1 13 | requests-oauthlib==1.3.1 14 | rsa==4.8 15 | six==1.16.0 16 | urllib3==1.26.18 17 | websocket-client==1.3.2 18 | -------------------------------------------------------------------------------- /pkg/drivemgr/basemgr/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | # Remove bash packet to get rid of related CVEs 4 | RUN apt update --no-install-recommends -y -q \ 5 | && apt remove --no-install-recommends -y --allow-remove-essential -q bash \ 6 | && apt install --no-install-recommends -y -q lsscsi smartmontools \ 7 | && apt-get install -y nvme-cli \ 8 | && apt upgrade --no-install-recommends -y -q 9 | -------------------------------------------------------------------------------- /docs/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | ### Resolves # 3 | 4 | _Describe your changes_ 5 | 6 | ## PR checklist 7 | - [ ] Add link to the issue 8 | - [ ] Choose Project 9 | - [ ] Choose PR label 10 | - [ ] New unit tests added 11 | - [ ] Modified code has meaningful comments 12 | - [ ] All TODOs are linked with the issues 13 | - [ ] All comments are resolved 14 | 15 | ## Testing 16 | _Provide test details_ 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # git diff files 2 | *.diff 3 | # idea files 4 | .idea 5 | *.iml 6 | # libries and build artifacts 7 | *_output 8 | vendor 9 | build/ 10 | # tests results 11 | coverage.out 12 | coverage.html 13 | ci.log 14 | tests/e2e/reports/report.xml 15 | tests/kind/kind 16 | tests/log.txt 17 | # e2e tests results 18 | tests/e2e-test-framework/logs 19 | tests/e2e-test-framework/report 20 | # vscode 21 | .vscode 22 | # python 23 | __pycache__ 24 | bin/controller-gen -------------------------------------------------------------------------------- /pkg/drivemgr/drivemgr-update-history.md: -------------------------------------------------------------------------------- 1 | ### drivemgr update history 2 | 3 | drivemgr have several implementations, file here to track changeset to create new 4 | git commit for proprietary code. 5 | 6 | 2023/05/16 remove empty image csi-baremetal-scheduler. 7 | 2023/05/23 upgrade halmgr to SP4. 8 | 2024/01/22 remove upper case from disk serial number. 9 | 2024/11/04 trigger halmgr build 10 | 2025/03/04 trigger halmgr build 11 | 2025/03/06 trigger halmgr build -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/docker_helper.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import docker 3 | 4 | 5 | class Docker: 6 | @classmethod 7 | def is_docker_running(cls): 8 | try: 9 | client = docker.from_env() 10 | client.ping() 11 | 12 | logging.info("\nDocker is running.") 13 | return True 14 | except Exception as exc: 15 | logging.error(f"Error: {exc}") 16 | return False 17 | -------------------------------------------------------------------------------- /pkg/drivemgr/loopbackmgr/Dockerfile.build: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | 3 | # RUN sed -i -re 's/archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list \ 4 | # && sed -i -re 's/deb|deb-src/& \[trusted=yes\]/' /etc/apt/sources.list 5 | # Remove bash packet to get rid of related CVEs 6 | RUN apt update --no-install-recommends -y -q && apt remove --no-install-recommends -y --allow-remove-essential -q bash && apt upgrade --no-install-recommends -y -q 7 | 8 | -------------------------------------------------------------------------------- /pkg/base/error/types.go: -------------------------------------------------------------------------------- 1 | package error 2 | 3 | import "errors" 4 | 5 | // ErrorNotFound indicates that requested object wasn't found 6 | var ( 7 | ErrorNotFound = errors.New("not found") 8 | ErrorEmptyParameter = errors.New("empty parameter") 9 | ErrorFailedParsing = errors.New("failed to parse") 10 | ErrorGetDriveFailed = errors.New("failed to get drive cr") 11 | ErrorRejectReservationRequest = errors.New("reject reservation request") 12 | ) 13 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/node.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dell/csi-baremetal/api/v1/nodecrd" 7 | ) 8 | 9 | type node struct{} 10 | 11 | func (l *node) Log(object *nodecrd.Node) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newNode() *node { 18 | return &node{} 19 | } 20 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/drive.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dell/csi-baremetal/api/v1/drivecrd" 7 | ) 8 | 9 | type drive struct{} 10 | 11 | func (l *drive) Log(object *drivecrd.Drive) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newDrive() *drive { 18 | return &drive{} 19 | } 20 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/volume.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dell/csi-baremetal/api/v1/volumecrd" 7 | ) 8 | 9 | type volume struct{} 10 | 11 | func (l *volume) Log(object *volumecrd.Volume) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Namespace: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, object.ObjectMeta.Namespace, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newVolume() *volume { 18 | return &volume{} 19 | } 20 | -------------------------------------------------------------------------------- /docs/crds-generation.md: -------------------------------------------------------------------------------- 1 | # CRDs generation routine 2 | 3 | CRDs generated in this repository and placed to the [`csi-baremetal-operator`](https://github.com/dell/csi-baremetal-operator) repository (charts folder). 4 | 5 | All charts crds generated with [`controller-tools`](https://github.com/kubernetes-sigs/controller-tools). 6 | 7 | ### **Don't edit crds manually** 8 | 9 | Use right annotation for your structs so validations would be applied on the install step. 10 | 11 | Refer to [`CRD Validation`](https://book.kubebuilder.io/reference/markers/crd-validation.html) documentation for more info. 12 | 13 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/logical_volume_group.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/dell/csi-baremetal/api/v1/lvgcrd" 7 | ) 8 | 9 | type logicalVolumeGroup struct{} 10 | 11 | func (l *logicalVolumeGroup) Log(object *lvgcrd.LogicalVolumeGroup) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newLogicalVolumeGroup() *logicalVolumeGroup { 18 | return &logicalVolumeGroup{} 19 | } 20 | -------------------------------------------------------------------------------- /pkg/crcontrollers/node/common/const.go: -------------------------------------------------------------------------------- 1 | // Package common contains variables that are used in controller code and in other places too 2 | // the reason of that package is to avoid conflict during initialization k8s client for e2e test 3 | package common 4 | 5 | const ( 6 | nodeKey = "nodes.csi-baremetal.dell.com" 7 | // DeafultNodeIDAnnotationKey hold special ID for node object if external annotaion is not used 8 | DeafultNodeIDAnnotationKey = nodeKey + "/uuid" 9 | // NodeIDTopologyLabelKey used as a label key in external component csi-provisioner 10 | NodeIDTopologyLabelKey = DeafultNodeIDAnnotationKey 11 | ) 12 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/available_capacity.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | accrd "github.com/dell/csi-baremetal/api/v1/availablecapacitycrd" 7 | ) 8 | 9 | type availableCapacity struct{} 10 | 11 | func (l *availableCapacity) Log(object *accrd.AvailableCapacity) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newAvailableCapacity() *availableCapacity { 18 | return &availableCapacity{} 19 | } 20 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/datadiscover.go: -------------------------------------------------------------------------------- 1 | package linuxutils 2 | 3 | import ( 4 | "github.com/stretchr/testify/mock" 5 | 6 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/datadiscover/types" 7 | ) 8 | 9 | // MockWrapDataDiscover is a mock implementation of WrapDataDiscover interface from datadiscover package 10 | type MockWrapDataDiscover struct { 11 | mock.Mock 12 | } 13 | 14 | // DiscoverData is a mock implementations 15 | func (m *MockWrapDataDiscover) DiscoverData(device, serialNumber string) (*types.DiscoverResult, error) { 16 | args := m.Mock.Called(device, serialNumber) 17 | 18 | return args.Get(0).(*types.DiscoverResult), args.Error(1) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/base/logger/objects/available_capacity_reservation.go: -------------------------------------------------------------------------------- 1 | package objects 2 | 3 | import ( 4 | "fmt" 5 | 6 | acrcrd "github.com/dell/csi-baremetal/api/v1/acreservationcrd" 7 | ) 8 | 9 | type availableCapacityReservation struct{} 10 | 11 | func (l *availableCapacityReservation) Log(object *acrcrd.AvailableCapacityReservation) (str string) { 12 | return fmt.Sprintf("ID: '%s', Name: '%s', Labels: %+v, Annotations: %+v, Spec: %+v", 13 | object.ObjectMeta.UID, object.ObjectMeta.Name, 14 | object.ObjectMeta.Labels, object.ObjectMeta.Annotations, object.Spec) 15 | } 16 | 17 | func newAvailableCapacityReservation() *availableCapacityReservation { 18 | return &availableCapacityReservation{} 19 | } 20 | -------------------------------------------------------------------------------- /devkit/kind/kind-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Env 4 | KIND_DIR=$1 5 | KIND=$KIND_DIR/kind 6 | KIND_VER=0.23.0 7 | 8 | # Get kind sources 9 | wget -O $KIND_DIR/kind-src https://codeload.github.com/kubernetes-sigs/kind/tar.gz/refs/tags/v$KIND_VER 10 | tar -xzvf $KIND_DIR/kind-src -C $KIND_DIR 11 | 12 | # Add "--ipc=host" docker option and build binary 13 | cd $KIND_DIR && patch -p0 < $KIND_DIR/kind-$KIND_VER.patch 14 | cd $KIND_DIR/kind-$KIND_VER && make build 15 | 16 | # Copy file 17 | cp $KIND_DIR/kind-$KIND_VER/bin/kind $KIND 18 | 19 | # Make executive 20 | chmod +x $KIND 21 | 22 | # Check 23 | $KIND version 24 | 25 | # Clean workdir 26 | rm -rf $KIND_DIR/kind-$KIND_VER 27 | rm -f $KIND_DIR/kind-src 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /docs/supported-mount-options.md: -------------------------------------------------------------------------------- 1 | # Supported Mount Options 2 | 3 | ## Usage 4 | User can set options in Storage Class in mountOptions section. 5 | They will be applied for all Volumes with the following SC. 6 | 7 | Example: 8 | ``` 9 | apiVersion: storage.k8s.io/v1 10 | kind: StorageClass 11 | metadata: 12 | name: sc 13 | provisioner: csi-baremetal 14 | reclaimPolicy: Delete 15 | volumeBindingMode: WaitForFirstConsumer 16 | parameters: 17 | storageType: ANY 18 | fsType: xfs 19 | mountOptions: 20 | - noatime 21 | ``` 22 | 23 | ## List of supported options 24 | 25 | - Name: noatime 26 | 27 | Effect: Add "noatime" option to mount command on NodePublishRequest 28 | 29 | Example: `mount -o noatime /src /dst` 30 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/test_description_plugin.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import pytest 3 | 4 | 5 | class TestDescriptionPlugin: 6 | 7 | def __init__(self, terminal_reporter: str): 8 | self.terminal_reporter = terminal_reporter 9 | self.desc = None 10 | 11 | def pytest_runtest_protocol(self, item): 12 | self.desc = inspect.getdoc(item.obj) 13 | 14 | @pytest.hookimpl(hookwrapper=True, tryfirst=True) 15 | def pytest_runtest_logstart(self) -> None: 16 | if self.terminal_reporter.verbosity == 0: 17 | yield 18 | else: 19 | self.terminal_reporter.write('\n\n') 20 | yield 21 | if self.desc: 22 | self.terminal_reporter.write(f'\n{self.desc} \n') 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Environment (please complete the following information):** 14 | - Hardware: [e.g. Dell PowerEdge] 15 | - OS: [e.g. Ubuntu, run `printf "$(uname -srm)\n$(cat /etc/os-release)\n"`] 16 | - Version: [e.g. 1.0.0] 17 | 18 | **To Reproduce** 19 | Steps to reproduce the behavior. 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /pkg/base/net/connect_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package net 18 | 19 | import "testing" 20 | 21 | func TestIsPortOpen(t *testing.T) { 22 | // todo add UTs 23 | //isPortOpen("tcp", "localhost:1111") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/healthserver/common/common.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | const ( 4 | // ExtenderConfigMapPath - the path to ExtenderConfigMap 5 | ExtenderConfigMapPath = "/status" 6 | // ExtenderConfigMapFile - ExtenderConfigMap data key 7 | ExtenderConfigMapFile = "nodes.yaml" 8 | // ExtenderConfigMapFullPath - full path to extender-readiness file 9 | ExtenderConfigMapFullPath = ExtenderConfigMapPath + "/" + ExtenderConfigMapFile 10 | ) 11 | 12 | // ReadinessStatus contains info about kube-scheduler restart for the related node 13 | type ReadinessStatus struct { 14 | NodeName string `yaml:"node_name"` 15 | KubeScheduler string `yaml:"kube_scheduler"` 16 | Restarted bool `yaml:"restarted"` 17 | } 18 | 19 | // ReadinessStatusList contains info about all kube-schedulers 20 | type ReadinessStatusList struct { 21 | Items []ReadinessStatus `yaml:"nodes"` 22 | } 23 | -------------------------------------------------------------------------------- /tests/kind/small-kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | networking: 4 | disableDefaultCNI: true 5 | # 1 control plane node and 2 workers 6 | nodes: 7 | # the control plane node config 8 | - role: control-plane 9 | # the two workers 10 | - role: worker 11 | extraMounts: 12 | - hostPath: /dev 13 | containerPath: /dev 14 | - hostPath: /run/udev 15 | containerPath: /run/udev 16 | - hostPath: /run/lvm 17 | containerPath: /run/lvm 18 | - hostPath: /run/lock 19 | containerPath: /run/lock 20 | - role: worker 21 | extraMounts: 22 | - hostPath: /dev 23 | containerPath: /dev 24 | - hostPath: /run/udev 25 | containerPath: /run/udev 26 | - hostPath: /run/lvm 27 | containerPath: /run/lvm 28 | - hostPath: /run/lock 29 | containerPath: /run/lock 30 | -------------------------------------------------------------------------------- /pkg/node/wbt/common/config.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | // WbtConfig is a part of WBT ConfigMap 4 | // contains changing value and options to select acceptable volume 5 | type WbtConfig struct { 6 | Enable bool `yaml:"enable"` 7 | Value uint32 `yaml:"wbt_lat_usec_value"` 8 | VolumeOptions VolumeOptions `yaml:"acceptable_volume_options"` 9 | } 10 | 11 | // VolumeOptions contains options to select acceptable volume 12 | type VolumeOptions struct { 13 | Modes []string `yaml:"modes"` 14 | StorageClasses []string `yaml:"storage_classes"` 15 | } 16 | 17 | // AcceptableKernelsConfig is a part of WBT ConfigMap 18 | // contains the list of kernel versions from nodes, 19 | // which should be able to set custom WBT value 20 | type AcceptableKernelsConfig struct { 21 | EnableForAll bool `yaml:"enable_for_all"` 22 | KernelVersions []string `yaml:"node_kernel_versions"` 23 | } 24 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/tox.ini: -------------------------------------------------------------------------------- 1 | ; For more information about tox, see https://tox.readthedocs.org/en/latest/ 2 | [tox] 3 | skipsdist = True 4 | envlist = py{312} 5 | indexserver = 6 | LOCAL = https://{env:CFG_ARTIFACTORY_SERVER:afeoscyc-mw.cec.lab.emc.com}/artifactory/api/pypi/cyclone-pypi/simple 7 | 8 | [testenv:py{312}-pylint] 9 | commands = flake8 tests 10 | pylint -d R -j 0 tests 11 | flake8 framework 12 | pylint -d R -j 0 framework 13 | 14 | [testenv] 15 | sitepackages=False 16 | setenv = 17 | PIP_TRUSTED_HOST = {env:CFG_ARTIFACTORY_SERVER:afeoscyc-mw.cec.lab.emc.com} 18 | PIP_EXTRA_INDEX_URL = https://{env:CFG_ARTIFACTORY_SERVER:afeoscyc-mw.cec.lab.emc.com}/artifactory/api/pypi/cyclone-pypi/simple/ 19 | PYTHONPATH = {toxinidir} 20 | deps = -rrequirements.txt 21 | whitelist_externals= 22 | /usr/bin/bash 23 | /bin/bash 24 | commands = 25 | py312: {[testenv:py312-pylint]commands} 26 | -------------------------------------------------------------------------------- /devkit/kind/kind-0.8.1.patch: -------------------------------------------------------------------------------- 1 | --- kind-0.8.1/pkg/cluster/internal/providers/docker/provision.go 2020-05-02 02:54:15.000000000 +0300 2 | +++ kind-0.8.1/pkg/cluster/internal/providers/docker/provision-patched.go 2021-07-06 12:36:23.376743088 +0300 3 | @@ -227,6 +227,8 @@ 4 | "--volume", "/var", 5 | // some k8s things want to read /lib/modules 6 | "--volume", "/lib/modules:/lib/modules:ro", 7 | + // ipc host 8 | + "--ipc", "host", 9 | }, 10 | args..., 11 | ) 12 | --- kind-0.8.1/pkg/cmd/kind/version/version.go 2020-05-02 02:54:15.000000000 +0300 13 | +++ kind-0.8.1/pkg/cmd/kind/version/version-patched.go 2021-07-06 12:38:29.521715917 +0300 14 | @@ -50,7 +50,7 @@ 15 | } 16 | 17 | // VersionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 18 | -const VersionCore = "0.8.1" 19 | +const VersionCore = "0.8.1-patched" 20 | 21 | // VersionPreRelease is the pre-release portion of the kind CLI version per 22 | // Semantic Versioning 2.0.0 23 | -------------------------------------------------------------------------------- /tests/kind/kind-0.8.1.patch: -------------------------------------------------------------------------------- 1 | --- kind-0.8.1/pkg/cluster/internal/providers/docker/provision.go 2020-05-02 02:54:15.000000000 +0300 2 | +++ kind-0.8.1/pkg/cluster/internal/providers/docker/provision-patched.go 2021-07-06 12:36:23.376743088 +0300 3 | @@ -227,6 +227,8 @@ 4 | "--volume", "/var", 5 | // some k8s things want to read /lib/modules 6 | "--volume", "/lib/modules:/lib/modules:ro", 7 | + // ipc host 8 | + "--ipc", "host", 9 | }, 10 | args..., 11 | ) 12 | --- kind-0.8.1/pkg/cmd/kind/version/version.go 2020-05-02 02:54:15.000000000 +0300 13 | +++ kind-0.8.1/pkg/cmd/kind/version/version-patched.go 2021-07-06 12:38:29.521715917 +0300 14 | @@ -50,7 +50,7 @@ 15 | } 16 | 17 | // VersionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 18 | -const VersionCore = "0.8.1" 19 | +const VersionCore = "0.8.1-patched" 20 | 21 | // VersionPreRelease is the pre-release portion of the kind CLI version per 22 | // Semantic Versioning 2.0.0 23 | -------------------------------------------------------------------------------- /tests/kind/kind-0.11.1.patch: -------------------------------------------------------------------------------- 1 | --- kind-0.11.1/pkg/cluster/internal/providers/docker/provision.go 2021-07-02 15:32:23.872508147 +0300 2 | +++ kind-0.11.1-patched/pkg/cluster/internal/providers/docker/provision.go 2021-06-30 18:57:28.806000000 +0300 3 | @@ -243,6 +243,8 @@ 4 | "--volume", "/var", 5 | // some k8s things want to read /lib/modules 6 | "--volume", "/lib/modules:/lib/modules:ro", 7 | + // ipc host 8 | + "--ipc", "host", 9 | }, 10 | args..., 11 | ) 12 | --- kind-0.11.1/pkg/cmd/kind/version/version.go 2021-05-28 02:18:13.000000000 +0300 13 | +++ kind-0.11.1-patched/pkg/cmd/kind/version/version.go 2021-07-02 15:31:45.440367546 +0300 14 | @@ -50,7 +50,7 @@ 15 | } 16 | 17 | // VersionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 18 | -const VersionCore = "0.11.1" 19 | +const VersionCore = "0.11.1-patched" 20 | 21 | // VersionPreRelease is the pre-release portion of the kind CLI version per 22 | // Semantic Versioning 2.0.0 23 | -------------------------------------------------------------------------------- /devkit/kind/kind-0.11.1.patch: -------------------------------------------------------------------------------- 1 | --- kind-0.11.1/pkg/cluster/internal/providers/docker/provision.go 2021-07-02 15:32:23.872508147 +0300 2 | +++ kind-0.11.1-patched/pkg/cluster/internal/providers/docker/provision.go 2021-06-30 18:57:28.806000000 +0300 3 | @@ -243,6 +243,8 @@ 4 | "--volume", "/var", 5 | // some k8s things want to read /lib/modules 6 | "--volume", "/lib/modules:/lib/modules:ro", 7 | + // ipc host 8 | + "--ipc", "host", 9 | }, 10 | args..., 11 | ) 12 | --- kind-0.11.1/pkg/cmd/kind/version/version.go 2021-05-28 02:18:13.000000000 +0300 13 | +++ kind-0.11.1-patched/pkg/cmd/kind/version/version.go 2021-07-02 15:31:45.440367546 +0300 14 | @@ -50,7 +50,7 @@ 15 | } 16 | 17 | // VersionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 18 | -const VersionCore = "0.11.1" 19 | +const VersionCore = "0.11.1-patched" 20 | 21 | // VersionPreRelease is the pre-release portion of the kind CLI version per 22 | // Semantic Versioning 2.0.0 23 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/propagating_thread.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | 3 | 4 | class PropagatingThread(Thread): 5 | def __init__(self, *args, **kwargs): 6 | self.target = kwargs.get('target') 7 | self.test_name = kwargs.get('test_name', None) 8 | 9 | if self.test_name is None: 10 | raise ValueError("Missing kwargs test_name") 11 | 12 | else: 13 | kwargs.pop('test_name') 14 | self.args = kwargs.get('args', ()) 15 | self.kwargs = kwargs.get('kwargs', {}) 16 | super(PropagatingThread, self).__init__(*args, **kwargs) 17 | self.exc = None 18 | 19 | def run(self): 20 | try: 21 | if self.target: 22 | self.target(*self.args, **self.kwargs) 23 | except Exception as exc: 24 | self.exc = exc 25 | 26 | def has_failed(self): 27 | return self.exc is not None 28 | 29 | def get_target_name(self): 30 | return self.target.__name__ 31 | -------------------------------------------------------------------------------- /tests/e2e/common/testcontext.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import "time" 20 | 21 | // BMDriverTestContextType stores custom testing context 22 | type BMDriverTestContextType struct { 23 | ChartsDir string 24 | CompleteUninstall bool 25 | NeedAllTests bool 26 | Timeout time.Duration 27 | } 28 | 29 | var BMDriverTestContext BMDriverTestContextType 30 | -------------------------------------------------------------------------------- /devkit/start_ide.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This script starts IDEs made by JetBrains, such as IntelliJ IDEA and GoLand. 5 | # Their IDEs usually put start scripts to /bin/.sh. 6 | # This script should not be used directly; symlink with the corresponding 7 | # IDE name should be created. 8 | # 9 | 10 | IDE="$(basename $0)" 11 | 12 | START_SCRIPT=/opt/software/$IDE/bin/$IDE.sh 13 | 14 | if [[ ! -x $START_SCRIPT ]]; then 15 | echo "ERROR: $START_SCRIPT does not exist or does not have executable permission." 1>&2 16 | exit 1 17 | fi 18 | 19 | $START_SCRIPT &>/dev/null & 20 | 21 | # sleep for a while to give a process a chance to start 22 | # if something is wrong, process will start and exit but we want it to start and work 23 | sleep 2 24 | 25 | # the following command will return error exit status if IDE not started 26 | pidof -x $IDE.sh &>/dev/null 27 | 28 | if [[ $? -ne 0 ]]; then 29 | echo "ERROR: $START_SCRIPT did not start; check that X11 support is enabled." 1>&2 30 | exit 2 31 | fi 32 | 33 | exit 0 34 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/tests/test_sts_hdd.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from framework.sts import STS 3 | from framework.utils import Utils 4 | 5 | 6 | class TestStsHdd: 7 | @classmethod 8 | @pytest.fixture(autouse=True) 9 | def setup_class( 10 | cls, 11 | namespace, 12 | utils: Utils, 13 | ): 14 | cls.namespace = namespace 15 | cls.utils = utils 16 | cls.name = "test-sts-hdd" 17 | cls.timeout = 120 18 | cls.replicas = 1 19 | 20 | cls.sts = STS(cls.namespace, cls.name, cls.replicas) 21 | cls.sts.delete() 22 | cls.sts.create(storage_classes=["csi-baremetal-sc-hdd"]) 23 | 24 | yield 25 | 26 | cls.utils.wait_for_pod_removing(cls.sts.delete()) 27 | cls.utils.clear_csi_resources(namespace=cls.namespace) 28 | 29 | @pytest.mark.hal 30 | def test_6105_create_sts_with_hdd_volume(self): 31 | assert self.sts.verify(self.timeout) is True, f"STS: {self.name} failed to reach desired number of replicas: {self.replicas}" 32 | -------------------------------------------------------------------------------- /docs/proposals/failed-volume-proposal.md: -------------------------------------------------------------------------------- 1 | # Proposal: volume statuses 2 | 3 | Last updated: 01.02.22 4 | 5 | ## Background 6 | 7 | Volume has the terminated state which is called "Failed". 8 | This state can be reached by some reason, but there is no way to go out from this state. 9 | Also, it needs to remove Failed volume in the most cases. 10 | So, this proposal should suggest a work flow to remove Failed volume and its additional statuses, 11 | if it's required. 12 | *Note*: "Remove" action is related to custom resource (CR). 13 | As far volume can contain a data which can be still needed, it's proposed to leave that without changes. 14 | So, operator can manually handle this case in the future. 15 | 16 | ## Proposal 17 | 18 | The current implementation of volumes' work flow can be found [here](../volume-statuses.md). 19 | It's proposed to add new transition "17" from "Failed" to "Removed" state as the result of handling "DeleteVolume" RPC. 20 | So, FSM of volume statuses will be like below: 21 | 22 | ![Screenshot](images/failed_volume_proposal.png) 23 | 24 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/tests/test_sts_loopback.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from framework.sts import STS 3 | from framework.utils import Utils 4 | 5 | 6 | class TestStsLoopback: 7 | @classmethod 8 | @pytest.fixture(autouse=True) 9 | def setup_class( 10 | cls, 11 | namespace, 12 | utils: Utils 13 | ): 14 | cls.namespace = namespace 15 | cls.utils = utils 16 | cls.name = "test-sts-loopback" 17 | cls.timeout = 120 18 | cls.replicas = 1 19 | 20 | cls.sts = STS(cls.namespace, cls.name, cls.replicas) 21 | cls.sts.delete() 22 | cls.sts.create(storage_classes=["csi-baremetal-sc"]) 23 | 24 | yield 25 | 26 | cls.utils.wait_for_pod_removing(cls.sts.delete()) 27 | cls.utils.clear_csi_resources(namespace=cls.namespace) 28 | 29 | @pytest.mark.loopback 30 | def test_6106_create_sts_with_loopback_volume(self): 31 | assert self.sts.verify(self.timeout) is True, f"STS: {self.name} failed to reach desired number of replicas: {self.replicas}" 32 | -------------------------------------------------------------------------------- /pkg/node/provisioners/utilwrappers/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | Package utilwrappers consists of code that manipulates by os utils and use code from linuxutils for that 19 | 20 | Interfaces descriptions: 21 | 1. FSOperations works with file system and holds compound methods for interacting with it 22 | 2. PartitionOperations works with partition on the system and holds compound methods for interacting with it 23 | */ 24 | package utilwrappers 25 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/kubernetes_helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | from kubernetes import client, config 3 | 4 | 5 | class KubernetesHelper: 6 | @classmethod 7 | def load_kube_api(cls): 8 | if 'KUBERNETES_SERVICE_HOST' in os.environ and 'KUBERNETES_SERVICE_PORT' in os.environ: 9 | config.load_incluster_config() 10 | else: 11 | config.load_kube_config() 12 | 13 | configuration = client.Configuration().get_default_copy() 14 | configuration.verify_ssl = False 15 | configuration.assert_hostname = False 16 | client.Configuration.set_default(configuration) 17 | 18 | api_client = client.ApiClient() 19 | core_v1_api = client.CoreV1Api(api_client) 20 | custom_objects_api = client.CustomObjectsApi(api_client) 21 | apps_v1_api = client.AppsV1Api(api_client) 22 | network_v1_api = client.NetworkingV1Api(api_client) 23 | coordination_v1_api = client.CoordinationV1Api(api_client) 24 | return core_v1_api, custom_objects_api, apps_v1_api, network_v1_api, coordination_v1_api 25 | -------------------------------------------------------------------------------- /api/smart/generated/oas_unimplemented_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | "context" 7 | 8 | ht "github.com/ogen-go/ogen/http" 9 | ) 10 | 11 | // UnimplementedHandler is no-op Handler which returns http.ErrNotImplemented. 12 | type UnimplementedHandler struct{} 13 | 14 | var _ Handler = UnimplementedHandler{} 15 | 16 | // GetAllDrivesSmartInfo implements get-all-drives-smart-info operation. 17 | // 18 | // Retrieve all discovered disks information/metrics. 19 | // 20 | // GET /smart/api/v1/drives 21 | func (UnimplementedHandler) GetAllDrivesSmartInfo(ctx context.Context) (r GetAllDrivesSmartInfoRes, _ error) { 22 | return r, ht.ErrNotImplemented 23 | } 24 | 25 | // GetDriveSmartInfo implements get-drive-smart-info operation. 26 | // 27 | // Retrieve the disk information/metrics with the matching serial number. 28 | // 29 | // GET /smart/api/v1/drive/{serialNumber} 30 | func (UnimplementedHandler) GetDriveSmartInfo(ctx context.Context, params GetDriveSmartInfoParams) (r GetDriveSmartInfoRes, _ error) { 31 | return r, ht.ErrNotImplemented 32 | } 33 | -------------------------------------------------------------------------------- /api/v1/drivemgrsvc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package v1api; 4 | option go_package="v1api"; 5 | 6 | import "types.proto"; 7 | 8 | message DrivesRequest { 9 | string nodeId = 1; 10 | } 11 | 12 | message DrivesResponse { 13 | repeated Drive disks = 1; 14 | } 15 | 16 | message DriveLocateRequest { 17 | string driveSerialNumber = 1; 18 | int32 action = 2; 19 | } 20 | 21 | message DriveLocateResponse { 22 | int32 status = 1; 23 | } 24 | 25 | message NodeLocateRequest { 26 | int32 action = 1; 27 | } 28 | 29 | message Empty {} 30 | 31 | message SmartInfoRequest { 32 | string serialNumber = 1; 33 | } 34 | 35 | message SmartInfoResponse { 36 | string smartInfo = 1; 37 | } 38 | 39 | service DriveService { 40 | rpc GetDrivesList(DrivesRequest) returns (DrivesResponse){}; 41 | rpc Locate(DriveLocateRequest) returns (DriveLocateResponse){}; 42 | rpc LocateNode(NodeLocateRequest) returns (Empty){}; 43 | rpc GetDriveSmartInfo(SmartInfoRequest) returns (SmartInfoResponse){}; 44 | rpc GetAllDrivesSmartInfo(Empty) returns (SmartInfoResponse){}; 45 | } 46 | -------------------------------------------------------------------------------- /pkg/base/k8s/kubeclientset_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package k8s 18 | 19 | import ( 20 | "k8s.io/client-go/rest" 21 | "testing" 22 | ) 23 | 24 | // Since we run test not in k8s, it will always fail 25 | // It ain't much but it's honest work. 26 | func TestGetK8SClientset(t *testing.T) { 27 | _, err := GetK8SClientset() 28 | if err != rest.ErrNotInCluster { 29 | t.Errorf("GetK8SClientset() error got = %v, want %v", err, rest.ErrNotInCluster) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pkg/base/util/logging.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/sirupsen/logrus" 23 | 24 | "github.com/dell/csi-baremetal/pkg/base" 25 | ) 26 | 27 | // AddCommonFields read common fields from ctx and add them to logger 28 | func AddCommonFields(ctx context.Context, logger *logrus.Entry, method string) *logrus.Entry { 29 | return logger.WithFields(logrus.Fields{ 30 | "volumeID": ctx.Value(base.RequestUUID), 31 | "method": method}) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/base/linuxutils/datadiscover/types/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package types contains interface and structure for discovering of logic entries on drive 18 | package types 19 | 20 | // WrapDataDiscover is the interface which encapsulates method to discover data on drives 21 | type WrapDataDiscover interface { 22 | DiscoverData(device, serialNumber string) (*DiscoverResult, error) 23 | } 24 | 25 | // DiscoverResult encapsulates result of DiscoverData function 26 | type DiscoverResult struct { 27 | Message string 28 | HasData bool 29 | } 30 | -------------------------------------------------------------------------------- /pkg/events/mocks/EventRecorder.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.0.0-alpha.2. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | mock "github.com/stretchr/testify/mock" 7 | runtime "k8s.io/apimachinery/pkg/runtime" 8 | ) 9 | 10 | // EventRecorder is an autogenerated mock type for the EventRecorder type 11 | type EventRecorder struct { 12 | mock.Mock 13 | } 14 | 15 | // LabeledEventf provides a mock function with given fields: object, labels, eventtype, reason, messageFmt, args 16 | func (_m *EventRecorder) LabeledEventf(object runtime.Object, labels map[string]string, eventtype string, reason string, messageFmt string, args ...interface{}) { 17 | var _ca []interface{} 18 | _ca = append(_ca, object, labels, eventtype, reason, messageFmt) 19 | _ca = append(_ca, args...) 20 | _m.Called(_ca...) 21 | } 22 | 23 | // Eventf provides a mock function with given fields: object, eventtype, reason, messageFmt, args 24 | func (_m *EventRecorder) Eventf(object runtime.Object, eventtype string, reason string, messageFmt string, args ...interface{}) { 25 | var _ca []interface{} 26 | _ca = append(_ca, object, eventtype, reason, messageFmt) 27 | _ca = append(_ca, args...) 28 | _m.Called(_ca...) 29 | } 30 | -------------------------------------------------------------------------------- /tests/kind/kind.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | # 1 control plane node and 2 workers 4 | nodes: 5 | # the control plane node config 6 | - role: control-plane 7 | labels: 8 | node-role.kubernetes.io/master: true 9 | # the two workers 10 | - role: worker 11 | extraMounts: 12 | - hostPath: /dev 13 | containerPath: /dev 14 | - hostPath: /run/udev 15 | containerPath: /run/udev 16 | - hostPath: /run/lvm 17 | containerPath: /run/lvm 18 | - hostPath: /run/lock 19 | containerPath: /run/lock 20 | - role: worker 21 | extraMounts: 22 | - hostPath: /dev 23 | containerPath: /dev 24 | - hostPath: /run/udev 25 | containerPath: /run/udev 26 | - hostPath: /run/lvm 27 | containerPath: /run/lvm 28 | - hostPath: /run/lock 29 | containerPath: /run/lock 30 | - role: worker 31 | extraMounts: 32 | - hostPath: /dev 33 | containerPath: /dev 34 | - hostPath: /run/udev 35 | containerPath: /run/udev 36 | - hostPath: /run/lvm 37 | containerPath: /run/lvm 38 | - hostPath: /run/lock 39 | containerPath: /run/lock 40 | -------------------------------------------------------------------------------- /pkg/base/k8s/kubeclientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package k8s 18 | 19 | import ( 20 | "k8s.io/client-go/kubernetes" 21 | "k8s.io/client-go/rest" 22 | ) 23 | 24 | // GetK8SClientset gets in-cluster k8s clientset 25 | func GetK8SClientset() (*kubernetes.Clientset, error) { 26 | // creates the in-cluster config 27 | config, err := rest.InClusterConfig() 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | // creates the clientset 33 | clientset, err := kubernetes.NewForConfig(config) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | return clientset, err 39 | } 40 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/lsscsi.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package linuxutils 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/lsscsi" 23 | ) 24 | 25 | // MockWrapLsscsi is a mock implementation of WrapLsscsi interface from lsscsi package 26 | type MockWrapLsscsi struct { 27 | mock.Mock 28 | } 29 | 30 | // GetSCSIDevices is a mock implementations 31 | func (m *MockWrapLsscsi) GetSCSIDevices() ([]*lsscsi.SCSIDevice, error) { 32 | args := m.Mock.Called() 33 | 34 | return args.Get(0).([]*lsscsi.SCSIDevice), args.Error(1) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/nvmecli.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package linuxutils 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/nvmecli" 23 | ) 24 | 25 | // MockWrapNvmecli is a mock implementation of WrapNvmecli interface from nvmee package 26 | type MockWrapNvmecli struct { 27 | mock.Mock 28 | } 29 | 30 | // GetNVMDevices is a mock implementations 31 | func (m *MockWrapNvmecli) GetNVMDevices() ([]nvmecli.NVMDevice, error) { 32 | args := m.Mock.Called() 33 | 34 | return args.Get(0).([]nvmecli.NVMDevice), args.Error(1) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/base/k8s/kubecache_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package k8s 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | "k8s.io/client-go/rest" 24 | ctrl "sigs.k8s.io/controller-runtime" 25 | ) 26 | 27 | func TestKubeCache_GetK8SCache(t *testing.T) { 28 | config := &rest.Config{} 29 | origFun := ctrl.GetConfigOrDie 30 | 31 | defer func() { 32 | ctrl.GetConfigOrDie = origFun 33 | }() 34 | 35 | ctrl.GetConfigOrDie = func() *rest.Config { 36 | return config 37 | } 38 | 39 | cache, err := GetK8SCache() 40 | assert.Nil(t, err) 41 | assert.NotNil(t, cache) 42 | } 43 | -------------------------------------------------------------------------------- /cmd/scheduling/scheduler/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | func main() { 20 | panic("NOT IMPLEMENTED") 21 | } 22 | 23 | /* 24 | import ( 25 | "math/rand" 26 | "os" 27 | "time" 28 | 29 | "k8s.io/kubernetes/cmd/kube-scheduler/app" 30 | 31 | "github.com/dell/csi-baremetal/pkg/scheduler/plugin" 32 | ) 33 | 34 | func main() { 35 | rand.Seed(time.Now().UnixNano()) 36 | // Register plugin to the scheduler framework. 37 | command := app.NewSchedulerCommand( 38 | app.WithPlugin(plugin.Name, plugin.New), 39 | ) 40 | if err := command.Execute(); err != nil { 41 | os.Exit(1) 42 | } 43 | } 44 | */ 45 | -------------------------------------------------------------------------------- /pkg/metrics/common/sysutil.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // SystemCMDDuration used to collect durations of system utils 26 | var SystemCMDDuration = metrics.NewMetrics(prometheus.HistogramOpts{ 27 | Name: "system_utils_duration_seconds", 28 | Help: "Duration of the each system util", 29 | Buckets: metrics.ExtendedDefBuckets, 30 | }, "name") 31 | 32 | // nolint: gochecknoinits 33 | func init() { 34 | prometheus.MustRegister(SystemCMDDuration.Collect()) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/metrics/common/reconcile.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // ReconcileDuration used to collect durations of reconcile loops 26 | var ReconcileDuration = metrics.NewMetrics(prometheus.HistogramOpts{ 27 | Name: "reconcile_duration_seconds", 28 | Help: "duration of the each reconcile loop", 29 | Buckets: metrics.ExtendedDefBuckets, 30 | }, "type") 31 | 32 | // nolint: gochecknoinits 33 | func init() { 34 | prometheus.MustRegister(ReconcileDuration.Collect()) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/metrics/common/kubeclient.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // KubeclientDuration used to collect durations of k8s api calls 26 | var KubeclientDuration = metrics.NewMetrics(prometheus.HistogramOpts{ 27 | Name: "kubeclient_execution_duration_seconds", 28 | Help: "duration of kubeclient method", 29 | Buckets: prometheus.DefBuckets, 30 | }, "method") 31 | 32 | // nolint: gochecknoinits 33 | func init() { 34 | prometheus.MustRegister(KubeclientDuration.Collect()) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/wbt.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package linuxutils 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | ) 22 | 23 | // MockWrapWbt is a mock implementation of WrapWbt 24 | type MockWrapWbt struct { 25 | mock.Mock 26 | } 27 | 28 | // SetValue is a mock implementations 29 | func (m *MockWrapWbt) SetValue(device string, value uint32) error { 30 | args := m.Mock.Called(device, value) 31 | return args.Error(0) 32 | } 33 | 34 | // RestoreDefault is a mock implementations 35 | func (m *MockWrapWbt) RestoreDefault(device string) error { 36 | args := m.Mock.Called(device) 37 | return args.Error(0) 38 | } 39 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/smartctl.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package linuxutils 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/smartctl" 23 | ) 24 | 25 | // MockWrapSmartctl is a mock implementation of WrapSmartctl interface from smartctl package 26 | type MockWrapSmartctl struct { 27 | mock.Mock 28 | } 29 | 30 | // GetDriveInfoByPath is a mock implementations 31 | func (m *MockWrapSmartctl) GetDriveInfoByPath(path string) (*smartctl.DeviceSMARTInfo, error) { 32 | args := m.Mock.Called(path) 33 | 34 | return args.Get(0).(*smartctl.DeviceSMARTInfo), args.Error(1) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/metrics/common/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // DbgCreateVolumeDuration used to collect ducation of Controller.CreateVolume 26 | var DbgCreateVolumeDuration = metrics.NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 27 | Name: "controller_create_volume_duration_seconds", 28 | Help: "duration of the controller createVolume", 29 | }, "source", "method", "volume_name") 30 | 31 | // nolint: gochecknoinits 32 | func init() { 33 | prometheus.MustRegister(DbgCreateVolumeDuration.Collect()) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/mocks/drives.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mocks 18 | 19 | import ( 20 | api "github.com/dell/csi-baremetal/api/generated/v1" 21 | apiV1 "github.com/dell/csi-baremetal/api/v1" 22 | ) 23 | 24 | // DriveMgrRespDrives are the drives for mock GetAllDrives call of DriveManager 25 | var DriveMgrRespDrives = []*api.Drive{ 26 | { 27 | SerialNumber: "hdd1", 28 | Health: apiV1.HealthGood, 29 | Type: apiV1.DriveTypeHDD, 30 | Size: 1024 * 1024 * 1024 * 50, 31 | }, 32 | { 33 | SerialNumber: "hdd2", 34 | Health: apiV1.HealthGood, 35 | Type: apiV1.DriveTypeHDD, 36 | Size: 1024 * 1024 * 1024 * 150, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /api/smart/generated/oas_server_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | // Handler handles operations described by OpenAPI v3 specification. 10 | type Handler interface { 11 | // GetAllDrivesSmartInfo implements get-all-drives-smart-info operation. 12 | // 13 | // Retrieve all discovered disks information/metrics. 14 | // 15 | // GET /smart/api/v1/drives 16 | GetAllDrivesSmartInfo(ctx context.Context) (GetAllDrivesSmartInfoRes, error) 17 | // GetDriveSmartInfo implements get-drive-smart-info operation. 18 | // 19 | // Retrieve the disk information/metrics with the matching serial number. 20 | // 21 | // GET /smart/api/v1/drive/{serialNumber} 22 | GetDriveSmartInfo(ctx context.Context, params GetDriveSmartInfoParams) (GetDriveSmartInfoRes, error) 23 | } 24 | 25 | // Server implements http server based on OpenAPI v3 specification and 26 | // calls Handler to handle requests. 27 | type Server struct { 28 | h Handler 29 | baseServer 30 | } 31 | 32 | // NewServer creates new Server. 33 | func NewServer(h Handler, opts ...ServerOption) (*Server, error) { 34 | s, err := newServerConfig(opts...).baseServer() 35 | if err != nil { 36 | return nil, err 37 | } 38 | return &Server{ 39 | h: h, 40 | baseServer: s, 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /pkg/base/util/healthcheck.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "github.com/sirupsen/logrus" 21 | health "google.golang.org/grpc/health/grpc_health_v1" 22 | 23 | "github.com/dell/csi-baremetal/pkg/base/rpc" 24 | ) 25 | 26 | // SetupAndStartHealthCheckServer starts gRPC server to handle Health checking requests 27 | func SetupAndStartHealthCheckServer(c health.HealthServer, logger *logrus.Logger, endpoint string) error { 28 | healthServer := rpc.NewServerRunner(nil, endpoint, false, logger) 29 | // register Health checks 30 | logger.Info("Registering health check service") 31 | health.RegisterHealthServer(healthServer.GRPCServer, c) 32 | return healthServer.RunServer() 33 | } 34 | -------------------------------------------------------------------------------- /docs/proposals/TEMPLATE.md: -------------------------------------------------------------------------------- 1 | [This is a template for CSI-Baremetal's changes proposal. ] 2 | 3 | # Proposal: [Title] 4 | 5 | Last updated: [Date] 6 | 7 | 8 | ## Abstract 9 | 10 | [A short summary of the proposal.] 11 | 12 | ## Background 13 | 14 | [An introduction of the necessary background and the problem being solved by the proposed change.] 15 | 16 | ## Proposal 17 | 18 | [A precise statement of the proposed change.] 19 | 20 | ## Rationale 21 | 22 | [A discussion of alternate approaches and the trade offs, advantages, and disadvantages of the specified approach.] 23 | 24 | ## Compatibility 25 | 26 | [A discussion of the change with regard to the compatibility with previous product and Kubernetes versions.] 27 | 28 | ## Implementation 29 | 30 | [A description of the steps in the implementation, who will do them, and when.] 31 | 32 | ## Assumptions (if applicable) 33 | 34 | | ID | Name | Descriptions | Comments | 35 | |---------|------|--------------|----------| 36 | | ASSUM-1 | | | | 37 | 38 | ## Open issues (if applicable) 39 | 40 | | ID | Name | Descriptions | Status | Comments | 41 | |---------|------|--------------|--------|----------| 42 | | ISSUE-1 | | | | | 43 | -------------------------------------------------------------------------------- /devkit/kind/kind-0.17.0.patch: -------------------------------------------------------------------------------- 1 | diff -Naur kind-0.17.0/pkg/cluster/internal/providers/docker/provision.go kind-0.17.0-patched/pkg/cluster/internal/providers/docker/provision.go 2 | --- kind-0.17.0/pkg/cluster/internal/providers/docker/provision.go 2022-10-26 23:41:56.000000000 +0800 3 | +++ kind-0.17.0-patched/pkg/cluster/internal/providers/docker/provision.go 2023-05-11 14:21:36.132692234 +0800 4 | @@ -226,6 +226,8 @@ 5 | "--volume", "/var", 6 | // some k8s things want to read /lib/modules 7 | "--volume", "/lib/modules:/lib/modules:ro", 8 | + // ipc host 9 | + "--ipc", "host", 10 | // propagate KIND_EXPERIMENTAL_CONTAINERD_SNAPSHOTTER to the entrypoint script 11 | "-e", "KIND_EXPERIMENTAL_CONTAINERD_SNAPSHOTTER", 12 | }, 13 | diff -Naur kind-0.17.0/pkg/cmd/kind/version/version.go kind-0.17.0-patched/pkg/cmd/kind/version/version.go 14 | --- kind-0.17.0/pkg/cmd/kind/version/version.go 2023-05-11 13:55:02.026388670 +0800 15 | +++ kind-0.17.0-patched/pkg/cmd/kind/version/version.go 2023-05-11 14:22:09.436823934 +0800 16 | @@ -54,7 +54,7 @@ 17 | } 18 | 19 | // versionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 20 | -const versionCore = "0.17.0" 21 | +const versionCore = "0.17.0-patched" 22 | 23 | // versionPreRelease is the base pre-release portion of the kind CLI version per 24 | // Semantic Versioning 2.0.0 25 | -------------------------------------------------------------------------------- /devkit/kind/kind-0.23.0.patch: -------------------------------------------------------------------------------- 1 | diff -Naur kind-0.23.0/pkg/cluster/internal/providers/docker/provision.go kind-0.23.0-patched/pkg/cluster/internal/providers/docker/provision.go 2 | --- kind-0.23.0/pkg/cluster/internal/providers/docker/provision.go 2024-05-14 03:51:45.000000000 +0200 3 | +++ kind-0.23.0-patched/pkg/cluster/internal/providers/docker/provision.go 2024-07-18 11:28:51.094894819 +0200 4 | @@ -236,6 +236,8 @@ 5 | "--volume", "/var", 6 | // some k8s things want to read /lib/modules 7 | "--volume", "/lib/modules:/lib/modules:ro", 8 | + // ipc host 9 | + "--ipc", "host", 10 | // propagate KIND_EXPERIMENTAL_CONTAINERD_SNAPSHOTTER to the entrypoint script 11 | "-e", "KIND_EXPERIMENTAL_CONTAINERD_SNAPSHOTTER", 12 | }, 13 | diff -Naur kind-0.23.0/pkg/cmd/kind/version/version.go kind-0.23.0-patched/pkg/cmd/kind/version/version.go 14 | --- kind-0.23.0/pkg/cmd/kind/version/version.go 2024-05-14 03:51:45.000000000 +0200 15 | +++ kind-0.23.0-patched/pkg/cmd/kind/version/version.go 2024-07-18 11:29:23.614811195 +0200 16 | @@ -54,7 +54,7 @@ 17 | } 18 | 19 | // versionCore is the core portion of the kind CLI version per Semantic Versioning 2.0.0 20 | -const versionCore = "0.23.0" 21 | +const versionCore = "0.23.0-patched" 22 | 23 | // versionPreRelease is the base pre-release portion of the kind CLI version per 24 | // Semantic Versioning 2.0.0 25 | -------------------------------------------------------------------------------- /pkg/base/util/volume_helper_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "gotest.tools/assert" 21 | "testing" 22 | ) 23 | 24 | func Test_GetVolumeUUID(t *testing.T) { 25 | uuid := "84804065-9723-4954-a6ae-5e38769c9b2f" 26 | volumeID := "pvc-" + uuid 27 | 28 | test, err := GetVolumeUUID(volumeID) 29 | assert.Equal(t, uuid, test) 30 | assert.NilError(t, err) 31 | } 32 | 33 | func Test_GetEmptyVolumeID(t *testing.T) { 34 | volumeID := "" 35 | _, err := GetVolumeUUID(volumeID) 36 | assert.Error(t, err, "volume ID is empty") 37 | } 38 | 39 | func Test_GetEmptyVolumeUUID(t *testing.T) { 40 | volumeID := "pvc-" 41 | _, err := GetVolumeUUID(volumeID) 42 | assert.Error(t, err, "volume UUID is empty") 43 | } 44 | -------------------------------------------------------------------------------- /api/smart/generated/oas_labeler_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | "context" 7 | 8 | "go.opentelemetry.io/otel/attribute" 9 | ) 10 | 11 | // Labeler is used to allow adding custom attributes to the server request metrics. 12 | type Labeler struct { 13 | attrs []attribute.KeyValue 14 | } 15 | 16 | // Add attributes to the Labeler. 17 | func (l *Labeler) Add(attrs ...attribute.KeyValue) { 18 | l.attrs = append(l.attrs, attrs...) 19 | } 20 | 21 | // AttributeSet returns the attributes added to the Labeler as an attribute.Set. 22 | func (l *Labeler) AttributeSet() attribute.Set { 23 | return attribute.NewSet(l.attrs...) 24 | } 25 | 26 | type labelerContextKey struct{} 27 | 28 | // LabelerFromContext retrieves the Labeler from the provided context, if present. 29 | // 30 | // If no Labeler was found in the provided context a new, empty Labeler is returned and the second 31 | // return value is false. In this case it is safe to use the Labeler but any attributes added to 32 | // it will not be used. 33 | func LabelerFromContext(ctx context.Context) (*Labeler, bool) { 34 | if l, ok := ctx.Value(labelerContextKey{}).(*Labeler); ok { 35 | return l, true 36 | } 37 | return &Labeler{}, false 38 | } 39 | 40 | func contextWithLabeler(ctx context.Context, l *Labeler) context.Context { 41 | return context.WithValue(ctx, labelerContextKey{}, l) 42 | } 43 | -------------------------------------------------------------------------------- /docs/maintenance-mode.md: -------------------------------------------------------------------------------- 1 | # Proposal: Node Maintenance Mode (MM) 2 | 3 | Last updated: 8.10.2021 4 | 5 | 6 | ## Abstract 7 | 8 | The node is placed in Maintenance Mode - CSI pods are temporarily deliting on the node. 9 | 10 | ## Proposal 11 | 12 | To move the node to the maintenance mode, need to set the taint ```node.dell.com/drain=planned-downtine:NoSchedule```. 13 | All CSI components will be delete by the CSI Operator, except DaemonSets (```csi-baremetal-node, csi-baremetal-se```). 14 | 15 | ```csi-baremetal-node``` and ```csi-baremetal-se``` remain on the node for the execution of service procedures. 16 | 17 | ### Entering MM: 18 | 19 | When a host is put in MM in this mode, the corresponding k8s node in supervisor cluster will get the following taint: 20 | ``` 21 | kubectl taint node `node.dell.com/drain=planned-downtime:NoSchedule 22 | ``` 23 | 24 | ### Exiting MM: 25 | When the node “exits” MM the taint will disappear from the node. At this point the node will become schedulable for all POD again. 26 | 27 | To exit TMM user must remove taint from the node: 28 | ``` 29 | kubectl taint node node.dell.com/drain=planned-downtine:NoSchedule- 30 | ``` 31 | 32 | ## Compatibility 33 | 34 | There is no problem with compatibility 35 | 36 | 37 | ## Open issues (if applicable) 38 | 39 | ID | Name | Descriptions | Status | Comments 40 | ---| -----| -------------| ------ | -------- 41 | ISSUE-1 | | | | 42 | -------------------------------------------------------------------------------- /api/v1/drivecrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package drivecrd contains API Schema definitions for the drive v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package drivecrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionDrive is group version used to register these objects 31 | GroupVersionDrive = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilderDrive is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderDrive = &crScheme.Builder{GroupVersion: GroupVersionDrive} 35 | 36 | // AddToSchemeDrive adds the types in this group-version to the given scheme. 37 | AddToSchemeDrive = SchemeBuilderDrive.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /api/v1/volumecrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package volumecrd contains API Schema definitions for the volume v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package volumecrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersion is group version used to register these objects 31 | GroupVersion = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilder = &crScheme.Builder{GroupVersion: GroupVersion} 35 | 36 | // AddToScheme adds the types in this group-version to the given scheme. 37 | AddToScheme = SchemeBuilder.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /pkg/base/featureconfig/feature_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package featureconfig 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestFeatureConfig(t *testing.T) { 26 | t.Run("Feature not found", func(t *testing.T) { 27 | conf := NewFeatureConfig() 28 | assert.False(t, conf.IsEnabled(FeatureACReservation)) 29 | }) 30 | t.Run("Feature update", func(t *testing.T) { 31 | conf := NewFeatureConfig() 32 | conf.Update(FeatureACReservation, true) 33 | assert.True(t, conf.IsEnabled(FeatureACReservation)) 34 | conf.Update(FeatureACReservation, false) 35 | assert.False(t, conf.IsEnabled(FeatureACReservation)) 36 | }) 37 | t.Run("Feature list", func(t *testing.T) { 38 | conf := NewFeatureConfig() 39 | conf.Update(FeatureACReservation, false) 40 | assert.Equal(t, []string{FeatureACReservation}, conf.List()) 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /api/v1/lvgcrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package lvgcrd contains API Schema definitions for the LogicalVolumeGroup v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package lvgcrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionLVG is group version used to register these objects 31 | GroupVersionLVG = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilderLVG is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderLVG = &crScheme.Builder{GroupVersion: GroupVersionLVG} 35 | 36 | // AddToSchemeLVG adds the types in this group-version to the given scheme. 37 | AddToSchemeLVG = SchemeBuilderLVG.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /tests/app/nginx-inline.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 3 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | affinity: 18 | podAntiAffinity: 19 | requiredDuringSchedulingIgnoredDuringExecution: 20 | - labelSelector: 21 | matchExpressions: 22 | - key: app 23 | operator: In 24 | values: 25 | - nginx 26 | topologyKey: "kubernetes.io/hostname" 27 | containers: 28 | - name: nginx 29 | image: k8s.gcr.io/nginx-slim:0.8 30 | ports: 31 | - containerPort: 80 32 | name: web 33 | volumeMounts: 34 | - name: www 35 | mountPath: /usr/share/nginx/html 36 | - name: data 37 | mountPath: /usr/share/nginx/data 38 | - name: logs 39 | mountPath: /usr/share/nginx/logs 40 | volumes: 41 | - name: www 42 | csi: 43 | driver: csi-baremetal 44 | volumeAttributes: 45 | size: 60Mi 46 | - name: data 47 | csi: 48 | driver: csi-baremetal 49 | volumeAttributes: 50 | size: 60Mi 51 | - name: logs 52 | csi: 53 | driver: csi-baremetal 54 | volumeAttributes: 55 | size: 60Mi 56 | 57 | -------------------------------------------------------------------------------- /api/v1/nodecrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package nodecrd contains API Schema definitions for the csi node v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package nodecrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionCSIBMNode is group version used to register these objects 31 | GroupVersionCSIBMNode = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilderACR is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderACR = &crScheme.Builder{GroupVersion: GroupVersionCSIBMNode} 35 | 36 | // AddToSchemeCSIBMNode adds the types in this group-version to the given scheme. 37 | AddToSchemeCSIBMNode = SchemeBuilderACR.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /api/v1/acreservationcrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package acrcrd contains API Schema definitions for the available capacity reservation v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package acrcrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionAvailableCapacity is group version used to register these objects 31 | GroupVersionACR = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderACR = &crScheme.Builder{GroupVersion: GroupVersionACR} 35 | 36 | // AddToSchemeAvailableCapacity adds the types in this group-version to the given scheme. 37 | AddToSchemeACR = SchemeBuilderACR.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /api/v1/storagegroupcrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package sgcrd contains API Schema definitions for the StorageGroup v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package sgcrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionStorageGroup is group version used to register these objects 31 | GroupVersionStorageGroup = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilderStorageGroup is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderStorageGroup = &crScheme.Builder{GroupVersion: GroupVersionStorageGroup} 35 | 36 | // AddToSchemeStorageGroup adds the types in this group-version to the given scheme. 37 | AddToSchemeStorageGroup = SchemeBuilderStorageGroup.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /pkg/mocks/rpc/mock_health_server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package rpc 18 | 19 | import ( 20 | "context" 21 | 22 | "google.golang.org/grpc/health/grpc_health_v1" 23 | ) 24 | 25 | // MockHealthServer is a mock implementation for health check server 26 | type MockHealthServer struct{} 27 | 28 | // NewMockHealthServer is a constructor for MockHealthServer type 29 | func NewMockHealthServer() *MockHealthServer { 30 | return &MockHealthServer{} 31 | } 32 | 33 | // Check is mock implementation for health check function 34 | func (c *MockHealthServer) Check(context.Context, *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) { 35 | return &grpc_health_v1.HealthCheckResponse{Status: grpc_health_v1.HealthCheckResponse_SERVING}, nil 36 | } 37 | 38 | // Watch is mock implementation for health check function 39 | func (c *MockHealthServer) Watch(*grpc_health_v1.HealthCheckRequest, grpc_health_v1.Health_WatchServer) error { 40 | return nil 41 | } 42 | -------------------------------------------------------------------------------- /pkg/mocks/events.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mocks 18 | 19 | import ( 20 | "sync" 21 | 22 | "k8s.io/apimachinery/pkg/runtime" 23 | 24 | "github.com/dell/csi-baremetal/pkg/eventing" 25 | ) 26 | 27 | type eventRecorderCalls struct { 28 | Object runtime.Object 29 | Event *eventing.EventDescription 30 | MessageFmt string 31 | Args []interface{} 32 | } 33 | 34 | // NoOpRecorder is blank implementation of event recorder interface which stores calls to the interface methods 35 | type NoOpRecorder struct { 36 | Calls []eventRecorderCalls 37 | m sync.Mutex 38 | } 39 | 40 | // Eventf do nothing 41 | func (n *NoOpRecorder) Eventf(object runtime.Object, event *eventing.EventDescription, messageFmt string, args ...interface{}) { 42 | c := eventRecorderCalls{ 43 | Object: object, 44 | Event: event, 45 | MessageFmt: messageFmt, 46 | Args: args, 47 | } 48 | n.m.Lock() 49 | n.Calls = append(n.Calls, c) 50 | n.m.Unlock() 51 | } 52 | -------------------------------------------------------------------------------- /docs/proposals/immediate-volume-binding-mode.md: -------------------------------------------------------------------------------- 1 | [This is a template for CSI-Baremetal's changes proposal. ] 2 | # Proposal: Immediate Volume Binding Mode 3 | 4 | Last updated: 14-Dec-2021 5 | 6 | 7 | ## Abstract 8 | 9 | CSI doesn't support `Immediate` volumeBindingMode. It relies on capacity reservation request issued from scheduler extender. 10 | 11 | ## Background 12 | 13 | Some applications might want to use `Immediate` volumeBindingMode mode. However this is not recommended for topology-constrained 14 | volumes since PersitentVolumes will be created without knowledge of the Pod's scheduling requirements. 15 | 16 | ## Proposal 17 | 18 | CSI Controller must check `volumeBindingMode` on CreateVolume request. When mode is set to `Immediate` it should pick target 19 | Node and AvailableCapacity. 20 | 21 | ## Rationale 22 | 23 | It's not clear what is the use case for the `Immediate` volumeBindingMode. We shouldn't proceed with the implementation at the curremt moment. 24 | 25 | ## Compatibility 26 | 27 | No issues with the compatibility - no new APIs and Kubernetes features are required to support this feature. 28 | 29 | ## Implementation 30 | 31 | CSI Controller shouldn't check for AvailableCapacityReservation on CreateVolume request when volumeBindingMode is set to `Immediate`. 32 | 33 | ## Assumptions (if applicable) 34 | 35 | ID | Name | Descriptions | Comments 36 | ---| -----| -------------| -------- 37 | ASSUM-1 | | | 38 | 39 | 40 | ## Open issues (if applicable) 41 | 42 | ID | Name | Descriptions | Status | Comments 43 | ---| -----| -------------| ------ | -------- 44 | ISSUE-1 | | | | 45 | -------------------------------------------------------------------------------- /api/v1/availablecapacitycrd/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package accrd contains API Schema definitions for the available capacity v1 API group 18 | // +groupName=csi-baremetal.dell.com 19 | // +versionName=v1 20 | package accrd 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | crScheme "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | 26 | v1 "github.com/dell/csi-baremetal/api/v1" 27 | ) 28 | 29 | var ( 30 | // GroupVersionAvailableCapacity is group version used to register these objects 31 | GroupVersionAvailableCapacity = schema.GroupVersion{Group: v1.CSICRsGroupVersion, Version: v1.Version} 32 | 33 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 34 | SchemeBuilderAvailableCapacity = &crScheme.Builder{GroupVersion: GroupVersionAvailableCapacity} 35 | 36 | // AddToSchemeAvailableCapacity adds the types in this group-version to the given scheme. 37 | AddToSchemeAvailableCapacity = SchemeBuilderAvailableCapacity.AddToScheme 38 | ) 39 | -------------------------------------------------------------------------------- /pkg/metrics/common/node.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // DbgNodeStageDuration used to collect duration of Node.NodeStageVolume 26 | var DbgNodeStageDuration = metrics.NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 27 | Name: "node_stage_volume_duration_seconds", 28 | Help: "duration of the NodeStageVolume", 29 | }, "source", "method", "volume_name") 30 | 31 | // DbgNodePublishDuration used to collect duration of Node.NodePublishVolume 32 | var DbgNodePublishDuration = metrics.NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 33 | Name: "node_publish_volume_duration_seconds", 34 | Help: "duration of the NodePublishVolume", 35 | }, "source", "method", "volume_name") 36 | 37 | // nolint: gochecknoinits 38 | func init() { 39 | prometheus.MustRegister(DbgNodeStageDuration.Collect()) 40 | prometheus.MustRegister(DbgNodePublishDuration.Collect()) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/eventing/event_manager.go: -------------------------------------------------------------------------------- 1 | package eventing 2 | 3 | // EventManager is wrapper to manipulate EventDescription 4 | type EventManager struct{} 5 | 6 | // GetReason returns event reason 7 | func (e *EventManager) GetReason(event *EventDescription) string { 8 | return string(event.reason) 9 | } 10 | 11 | // GetSeverity returns event severity 12 | func (e *EventManager) GetSeverity(event *EventDescription) string { 13 | return string(event.severity) 14 | } 15 | 16 | // GetLabels return labels for event or nil it has no ones 17 | func (e *EventManager) GetLabels(event *EventDescription) map[string]string { 18 | if event.symptomCode == NoneSymptomCode { 19 | return nil 20 | } 21 | 22 | return constructEventLabels(event) 23 | } 24 | 25 | // constructEventLabels return map in the following format 26 | // {SymptomID: CSI-XX} 27 | func constructEventLabels(event *EventDescription) map[string]string { 28 | symptomID := SymptomCodePrefix + "-" + event.symptomCode 29 | return map[string]string{SymptomCodeLabelKey: string(symptomID)} 30 | } 31 | 32 | // GenerateFake returns filled EventDescription 33 | // Test function 34 | func (e *EventManager) GenerateFake() *EventDescription { 35 | return &EventDescription{ 36 | reason: "Fake-reason", 37 | severity: NormalType, 38 | symptomCode: NoneSymptomCode, 39 | } 40 | } 41 | 42 | // GenerateFakeWithLabel returns filled EventDescription contains symptom code label 43 | // Test function 44 | func (e *EventManager) GenerateFakeWithLabel() *EventDescription { 45 | return &EventDescription{ 46 | reason: "Fake-reason", 47 | severity: NormalType, 48 | symptomCode: "Fake-symptom-code", 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /pkg/base/cache/cache_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cache 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestNewMemCache(t *testing.T) { 26 | memCache := NewMemCache() 27 | assert.Equal(t, 0, len(memCache.items)) 28 | } 29 | 30 | func TestMemCache_Set(t *testing.T) { 31 | memCache := NewMemCache() 32 | memCache.Set("test", "test") 33 | 34 | assert.Equal(t, "test", memCache.items["test"]) 35 | } 36 | 37 | func TestMemCache_Get(t *testing.T) { 38 | memCache := NewMemCache() 39 | memCache.Set("test", "test") 40 | 41 | value, err := memCache.Get("test") 42 | assert.Nil(t, err) 43 | assert.Equal(t, value, memCache.items["test"]) 44 | 45 | _, err = memCache.Get("unknown_key") 46 | assert.NotNil(t, err) 47 | } 48 | 49 | func TestMemCache_Delete(t *testing.T) { 50 | memCache := NewMemCache() 51 | memCache.Set("test", "test") 52 | 53 | assert.Equal(t, "test", memCache.items["test"]) 54 | 55 | memCache.Delete("test") 56 | assert.Equal(t, "", memCache.items["test"]) 57 | } 58 | -------------------------------------------------------------------------------- /pkg/base/linuxutils/ipmi/ipmitool_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package ipmi contains code for running and interpreting output of system ipmitool util 18 | package ipmi 19 | 20 | import ( 21 | "errors" 22 | "testing" 23 | 24 | "github.com/stretchr/testify/assert" 25 | 26 | "github.com/dell/csi-baremetal/pkg/mocks" 27 | ) 28 | 29 | func TestIPMI_GetBmcIP(t *testing.T) { 30 | e := &mocks.GoMockExecutor{} 31 | l := NewIPMI(e) 32 | 33 | strOut := "IP Address Source : DHCP Address \n IP Address : 10.245.137.136" 34 | e.On(mocks.RunCmd, LanPrintCmd).Return(strOut, "", nil).Times(1) 35 | ip := l.GetBmcIP() 36 | assert.Equal(t, "10.245.137.136", ip) 37 | 38 | strOut = "IP Address Source : DHCP Address \n" 39 | e.On(mocks.RunCmd, LanPrintCmd).Return(strOut, "", nil).Times(1) 40 | ip = l.GetBmcIP() 41 | assert.Equal(t, "", ip) 42 | 43 | expectedError := errors.New("ipmitool failed") 44 | e.On(mocks.RunCmd, LanPrintCmd).Return("", "", expectedError).Times(1) 45 | ip = l.GetBmcIP() 46 | assert.Equal(t, "", ip) 47 | } 48 | -------------------------------------------------------------------------------- /pkg/base/net/connect.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package net 18 | 19 | import ( 20 | "net" 21 | "time" 22 | ) 23 | 24 | const ( 25 | numberOfRetries = 4 26 | timeoutBetweenRetries = 500 * time.Millisecond 27 | tcp = "tcp" 28 | ) 29 | 30 | // IsTCPPortOpen checks if TCP port is open 31 | func IsTCPPortOpen(endpoint string) (bool, error) { 32 | return isPortOpen(tcp, endpoint) 33 | } 34 | 35 | // try to connect to provided endpoint with 4 attempts with 0.5 sec timeout 36 | func isPortOpen(network, endpoint string) (bool, error) { 37 | // todo check network type and endpoint 38 | var err error = nil 39 | var conn net.Conn 40 | 41 | for i := 0; i < numberOfRetries; i++ { 42 | // check that port is open 43 | conn, err = net.DialTimeout(network, endpoint, time.Second) 44 | if err == nil && conn != nil { 45 | err = conn.Close() 46 | // don't handle error - just return it 47 | return true, err 48 | } 49 | // sleep before next try 50 | time.Sleep(timeoutBetweenRetries) 51 | } 52 | return false, err 53 | } 54 | -------------------------------------------------------------------------------- /pkg/drivemgr/drivemgr.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package drivemgr contains a code for managers of storage hardware such as drives 18 | package drivemgr 19 | 20 | import api "github.com/dell/csi-baremetal/api/generated/v1" 21 | 22 | // DriveManager is the interface for managers that provide information about drives on a node 23 | type DriveManager interface { 24 | // GetDrivesList gets list of drives 25 | GetDrivesList() ([]*api.Drive, error) 26 | // Locate manipulates of drive's led state, receive drive serial number and type of action 27 | // returns current led status or error 28 | Locate(serialNumber string, action int32) (currentStatus int32, err error) 29 | // LocateNode manipulates of node's led state, which should be synced with drive's led 30 | LocateNode(action int32) error 31 | // GetDriveSmartInfo gets smart info for specific drive with given serialNumber 32 | GetDriveSmartInfo(serialNumber string) (string, error) 33 | // GetAllDrivesSmartInfo gets smart info for all drives on given node 34 | GetAllDrivesSmartInfo() (string, error) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/drivemgr/setup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package dmsetup has method for drivemgr initialization and startup 18 | package dmsetup 19 | 20 | import ( 21 | "github.com/sirupsen/logrus" 22 | "google.golang.org/grpc" 23 | 24 | api "github.com/dell/csi-baremetal/api/generated/v1" 25 | "github.com/dell/csi-baremetal/pkg/base/rpc" 26 | "github.com/dell/csi-baremetal/pkg/base/util" 27 | "github.com/dell/csi-baremetal/pkg/drivemgr" 28 | ) 29 | 30 | // SetupAndRunDriveMgr setups and start/stop particular drive manager 31 | func SetupAndRunDriveMgr(d drivemgr.DriveManager, sr *rpc.ServerRunner, cleanupFn func(), logger *logrus.Logger) { 32 | logger.Info("Start DriveManager") 33 | 34 | driveServiceServer := drivemgr.NewDriveServer(logger, d) 35 | 36 | api.RegisterDriveServiceServer(sr.GRPCServer, &driveServiceServer) 37 | 38 | handler := util.NewSignalHandler(logger) 39 | 40 | go handler.SetupSIGTERMHandler(sr) 41 | 42 | go handler.SetupSIGHUPHandler(cleanupFn) 43 | 44 | if err := sr.RunServer(); err != nil && err != grpc.ErrServerStopped { 45 | logger.Fatalf("Failed to serve on %s. Error: %v", sr.Endpoint, err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /api/v1/nodecrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package nodecrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Node. 13 | func (in *Node) DeepCopy() *Node { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(Node) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *Node) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *NodeList) DeepCopyInto(out *NodeList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]Node, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeList. 45 | func (in *NodeList) DeepCopy() *NodeList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(NodeList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *NodeList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /tests/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ $# -gt 1 ]; then 3 | echo "deploy.sh " 4 | fi 5 | 6 | # TODO check for REGISTRY env var 7 | export REGISTRY=asdrepo.isus.emc.com:9042 8 | 9 | NUMBER_OF_DEVICES=3 10 | if [ $# -eq 1 ]; then 11 | NUMBER_OF_DEVICES=$1 12 | fi 13 | echo "Number of loopback devices per node:" $NUMBER_OF_DEVICES 14 | 15 | 16 | # build binaries 17 | make DRIVE_MANAGER_TYPE=loopbackmgr build 18 | if [ $? -ne 0 ]; then 19 | echo "Failed to build binaries" 20 | exit 1 21 | fi 22 | 23 | # build final images 24 | make DRIVE_MANAGER_TYPE=loopbackmgr images 25 | if [ $? -ne 0 ]; then 26 | echo "Failed to build final images" 27 | exit 1 28 | fi 29 | 30 | # pull sidecar images 31 | make kind-pull-sidecar-images 32 | if [ $? -ne 0 ]; then 33 | echo "Failed to build final images" 34 | exit 1 35 | fi 36 | 37 | # load to kind cluster 38 | make kind-tag-images 39 | if [ $? -ne 0 ]; then 40 | echo "Failed to tag images" 41 | exit 1 42 | fi 43 | 44 | make kind-load-images KIND=`which kind` 45 | if [ $? -ne 0 ]; then 46 | echo "Failed to load images" 47 | exit 1 48 | fi 49 | 50 | export OPERATOR_VERSION=`cd ../csi-baremetal-operator && make version` 51 | make load-operator-image KIND=`which kind` 52 | if [ $? -ne 0 ]; then 53 | echo "Failed to load operator image" 54 | exit 1 55 | fi 56 | 57 | echo export CSI_VERSION=`make version` 58 | echo export CSI_OPERATOR_VERSION=$OPERATOR_VERSION 59 | #export SHORT_CI_TIMEOUT=20m 60 | echo export CSI_CHARTS_PATH=../csi-baremetal-operator/charts 61 | 62 | #CI=true CSI_VERSION=${CSI_VERSION} OPERATOR_VERSION=${OPERATOR_VERSION} go test -v test/e2e/baremetal_e2e_test.go -ginkgo.v -ginkgo.progress -ginkgo.failFast -all-tests -kubeconfig=${HOME}/.kube/config -chartsDir ${CHARTS_DIR} 63 | -------------------------------------------------------------------------------- /api/v1/drivecrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package drivecrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Drive. 13 | func (in *Drive) DeepCopy() *Drive { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(Drive) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *Drive) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *DriveList) DeepCopyInto(out *DriveList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]Drive, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriveList. 45 | func (in *DriveList) DeepCopy() *DriveList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(DriveList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *DriveList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/README.md: -------------------------------------------------------------------------------- 1 | # CSI baremetal E2E test framework 2 | Test automation framwework for csi-baremetal project 3 | 4 | ## Prerequisites 5 | ``` 6 | # Install Python 3.12.2 and requirements on SUSE SP4/SP5 7 | 8 | zypper install gcc zlib-devel libopenssl-devel libffi-devel 9 | 10 | mkdir ~/src 11 | mkdir ~/venv 12 | mkdir ~/.python3.12.2 13 | 14 | cd ~/src 15 | wget https://www.python.org/ftp/python/3.12.2/Python-3.12.2.tgz 16 | tar xzvf Python-3.12.2.tgz 17 | cd Python-3.12.2/ 18 | ./configure --prefix=$HOME/.python3.12.2/ --enable-optimizations 19 | make install 20 | export PATH=~/.python3.12.2/bin:$PATH 21 | 22 | pip3 install virtualenv 23 | virtualenv ~/venv/python3.12.2 24 | . ~/venv/python3.12.2/bin/activate 25 | python3 --version 26 | 27 | cd /tests/e2e-test-framework 28 | pip3 install -r requirements.txt 29 | pytest --version 30 | ``` 31 | 32 | # Update conftest.py 33 | For local usage you can update the follwing default values: 34 | * namespace of atlantic installer 35 | * qtest access token in case you want to link test case to requirements 36 | * qtest test suite in caes you want to update test results in qtest 37 | 38 | ...or provide during cli execution: 39 | 40 | ``` 41 | pytest --namespace= --qtest_token= --qtest_test_suite= 42 | ``` 43 | 44 | ## Test execution 45 | Single test case: 46 | 47 | ``` 48 | pytest -k 6105 49 | pytest -m hal 50 | ``` 51 | 52 | All test cases: 53 | 54 | ``` 55 | pytest 56 | ``` 57 | 58 | ## Test execution reporting 59 | 60 | Test ecxecution report is available ```report/pytest_html_report.html``` 61 | 62 | ## Before code merge 63 | Static code analysis should by done by execution ```tox``` command 64 | 65 | **Note:** ```rm -rf .tox``` command will clear existing tox. 66 | -------------------------------------------------------------------------------- /pkg/controller/identity_test.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/container-storage-interface/spec/lib/go/csi" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func Test_GetPluginInfo(t *testing.T) { 12 | t.Run("Test GetPluginInfo", func(t *testing.T) { 13 | ctx := context.Background() 14 | 15 | defaultIdentityServer := NewIdentityServer("Test", "1.0.0") 16 | response, err := defaultIdentityServer.GetPluginInfo(ctx, nil) 17 | assert.Nil(t, err) 18 | 19 | assert.Equal(t, response.Name, "Test") 20 | assert.Equal(t, response.VendorVersion, "1.0.0") 21 | }) 22 | } 23 | 24 | func Test_GetPluginCapabilities(t *testing.T) { 25 | t.Run("Test GetPluginCapabilities", func(t *testing.T) { 26 | ctx := context.Background() 27 | 28 | defaultIdentityServer := NewIdentityServer("Test", "1.0.0") 29 | response, err := defaultIdentityServer.GetPluginCapabilities(ctx, nil) 30 | assert.Nil(t, err) 31 | 32 | assert.Equal(t, response.Capabilities[0].GetService().Type, csi.PluginCapability_Service_CONTROLLER_SERVICE) 33 | assert.Equal(t, response.Capabilities[1].GetService().Type, csi.PluginCapability_Service_VOLUME_ACCESSIBILITY_CONSTRAINTS) 34 | assert.Equal(t, response.Capabilities[2].GetVolumeExpansion().Type, csi.PluginCapability_VolumeExpansion_ONLINE) 35 | assert.Equal(t, response.Capabilities[3].GetVolumeExpansion().Type, csi.PluginCapability_VolumeExpansion_OFFLINE) 36 | }) 37 | } 38 | 39 | func Test_Probe(t *testing.T) { 40 | t.Run("Test Probe", func(t *testing.T) { 41 | ctx := context.Background() 42 | 43 | defaultIdentityServer := NewIdentityServer("Test", "1.0.0") 44 | response, err := defaultIdentityServer.Probe(ctx, nil) 45 | assert.Nil(t, err) 46 | 47 | assert.True(t, response.Ready.Value) 48 | }) 49 | } 50 | -------------------------------------------------------------------------------- /api/v1/volumecrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package volumecrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Volume. 13 | func (in *Volume) DeepCopy() *Volume { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(Volume) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *Volume) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *VolumeList) DeepCopyInto(out *VolumeList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]Volume, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeList. 45 | func (in *VolumeList) DeepCopy() *VolumeList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(VolumeList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *VolumeList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /pkg/mocks/provisioners/mock_parititoner.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package provisioners 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | mocklu "github.com/dell/csi-baremetal/pkg/mocks/linuxutils" 23 | "github.com/dell/csi-baremetal/pkg/node/provisioners/utilwrappers" 24 | ) 25 | 26 | // MockPartitionOps is a mock implementation of WrapPartition interface 27 | type MockPartitionOps struct { 28 | mocklu.MockWrapPartition 29 | mock.Mock 30 | } 31 | 32 | // PreparePartition is a mock implementation 33 | func (m *MockPartitionOps) PreparePartition(p utilwrappers.Partition) (*utilwrappers.Partition, error) { 34 | args := m.Mock.Called(p) 35 | 36 | return args.Get(0).(*utilwrappers.Partition), args.Error(1) 37 | } 38 | 39 | // ReleasePartition is a mock implementation 40 | func (m *MockPartitionOps) ReleasePartition(p utilwrappers.Partition) error { 41 | args := m.Mock.Called(p) 42 | 43 | return args.Error(0) 44 | } 45 | 46 | // SearchPartName is a mock implementation 47 | func (m *MockPartitionOps) SearchPartName(device, partUUID string) (string, error) { 48 | args := m.Mock.Called(device, partUUID) 49 | 50 | return args.String(0), args.Error(1) 51 | } 52 | -------------------------------------------------------------------------------- /docs/DOC_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About [subject] 3 | shortTitle: [subject] # Max 31 characters 4 | intro: 'Article intro. See tips for a great intro below.' 5 | product: '{{ optional product callout }}' 6 | type: overview 7 | topics: 'List of topics' 8 | - [topic] 9 | versions: 10 | --- 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | ## A section here 20 | 21 | 22 | 23 | 24 | ## Another section here 25 | 26 | 27 | 28 | 29 | ## Further reading 30 | 31 | 32 | 33 | - "[Article title](article-URL)" 34 | -------------------------------------------------------------------------------- /tests/e2e/common/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "k8s.io/apimachinery/pkg/runtime/schema" 21 | 22 | apiV1 "github.com/dell/csi-baremetal/api/v1" 23 | ) 24 | 25 | var ( 26 | DriveGVR = schema.GroupVersionResource{ 27 | Group: apiV1.CSICRsGroupVersion, 28 | Version: apiV1.Version, 29 | Resource: "drives", 30 | } 31 | 32 | ACGVR = schema.GroupVersionResource{ 33 | Group: apiV1.CSICRsGroupVersion, 34 | Version: apiV1.Version, 35 | Resource: "availablecapacities", 36 | } 37 | 38 | ACRGVR = schema.GroupVersionResource{ 39 | Group: apiV1.CSICRsGroupVersion, 40 | Version: apiV1.Version, 41 | Resource: "availablecapacityreservations", 42 | } 43 | 44 | VolumeGVR = schema.GroupVersionResource{ 45 | Group: apiV1.CSICRsGroupVersion, 46 | Version: apiV1.Version, 47 | Resource: "volumes", 48 | } 49 | 50 | LVGGVR = schema.GroupVersionResource{ 51 | Group: apiV1.CSICRsGroupVersion, 52 | Version: apiV1.Version, 53 | Resource: "logicalvolumegroups", 54 | } 55 | 56 | CsibmnodeGVR = schema.GroupVersionResource{ 57 | Group: apiV1.CSICRsGroupVersion, 58 | Version: apiV1.Version, 59 | Resource: "nodes", 60 | } 61 | ) 62 | -------------------------------------------------------------------------------- /.github/workflows/devkit.yml: -------------------------------------------------------------------------------- 1 | name: devkit 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | LATEST_TAG: latest 11 | REGISTRY: ghcr.io/${{ github.repository }} 12 | equeal_with_latest: true 13 | docker_version: "1.16.8" 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-20.04 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v2 21 | 22 | - name: Set env variables 23 | working-directory: devkit 24 | run: | 25 | image_name=`make repo` 26 | image_tag=`make version` 27 | echo "LOCAL_IMAGE=$image_name:$image_tag" >> $GITHUB_ENV 28 | echo "DEST_IMAGE=${{ env.REGISTRY }}/$image_name:$image_tag" >> $GITHUB_ENV 29 | echo "LATEST_IMAGE=${{ env.REGISTRY }}/$image_name:${{ env.LATEST_TAG }}" >> $GITHUB_ENV 30 | 31 | - name: Log in to GitHub Docker Registry 32 | uses: docker/login-action@v1.14.1 33 | with: 34 | registry: ${{ env.REGISTRY }} 35 | username: ${{ github.actor }} 36 | password: ${{ secrets.GITHUB_TOKEN }} 37 | 38 | - name: Pull latest csi-baremetal-devkit 39 | run: docker pull ${{ env.LATEST_IMAGE }} || true 40 | 41 | - name: Build devkit image 42 | working-directory: devkit 43 | run: make build CACHE_IMAGE=${{ env.LATEST_IMAGE }} 44 | 45 | - name: Check equeal with latest 46 | continue-on-error: true 47 | working-directory: devkit 48 | run: | 49 | id1=`docker inspect --format="{{.Id}}" ${{ env.LOCAL_IMAGE }}` 50 | id2=`docker inspect --format="{{.Id}}" ${{ env.LATEST_IMAGE }}` 51 | equeal_with_latest="false" 52 | [ ${id1} == ${id2} ] && equeal_with_latest="true" 53 | echo "equeal_with_latest=${equeal_with_latest}" >> $GITHUB_ENV 54 | -------------------------------------------------------------------------------- /tests/app/nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 3 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | app.kubernetes.io/name: nginx 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx 17 | app.kubernetes.io/name: nginx 18 | spec: 19 | affinity: 20 | podAntiAffinity: 21 | requiredDuringSchedulingIgnoredDuringExecution: 22 | - labelSelector: 23 | matchExpressions: 24 | - key: app 25 | operator: In 26 | values: 27 | - nginx 28 | topologyKey: "kubernetes.io/hostname" 29 | containers: 30 | - name: nginx 31 | image: k8s.gcr.io/nginx-slim:0.8 32 | ports: 33 | - containerPort: 80 34 | name: web 35 | volumeMounts: 36 | - name: www 37 | mountPath: /usr/share/nginx/html 38 | - name: data 39 | mountPath: /usr/share/nginx/data 40 | - name: logs 41 | mountPath: /usr/share/nginx/logs 42 | volumeClaimTemplates: 43 | - metadata: 44 | name: www 45 | spec: 46 | storageClassName: csi-baremetal-sc 47 | accessModes: [ "ReadWriteOnce" ] 48 | resources: 49 | requests: 50 | storage: 60Mi 51 | - metadata: 52 | name: data 53 | spec: 54 | storageClassName: csi-baremetal-sc 55 | accessModes: [ "ReadWriteOnce" ] 56 | resources: 57 | requests: 58 | storage: 60Mi 59 | - metadata: 60 | name: logs 61 | spec: 62 | storageClassName: csi-baremetal-sc 63 | accessModes: [ "ReadWriteOnce" ] 64 | resources: 65 | requests: 66 | storage: 60Mi 67 | -------------------------------------------------------------------------------- /pkg/node/smart_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package node 18 | 19 | import ( 20 | "context" 21 | "testing" 22 | 23 | api "github.com/dell/csi-baremetal/api/smart/generated" 24 | "github.com/dell/csi-baremetal/pkg/mocks" 25 | "github.com/stretchr/testify/assert" 26 | ) 27 | 28 | var ( 29 | invalidJSONClient = &mocks.MockDriveMgrClientFailJSON{MockJSON: "let's fail"} 30 | validJSONClient = &mocks.MockDriveMgrClientFailJSON{MockJSON: `{"test": "ok"}`} 31 | 32 | validJSONSrv = NewSmartService(validJSONClient, testLogger) 33 | invalidJSONSrv = NewSmartService(invalidJSONClient, testLogger) 34 | ) 35 | 36 | func TestGetDriveSmartInfo(t *testing.T) { 37 | t.Run("Parse_JSON_return_internal_server_error", func(t *testing.T) { 38 | res, err := invalidJSONSrv.GetDriveSmartInfo(context.Background(), api.GetDriveSmartInfoParams{}) 39 | 40 | assert.NoError(t, err) 41 | assert.IsType(t, res, &api.GetDriveSmartInfoInternalServerError{}) 42 | }) 43 | 44 | t.Run("Parse_JSON_return_metrics", func(t *testing.T) { 45 | res, err := validJSONSrv.GetDriveSmartInfo(context.Background(), api.GetDriveSmartInfoParams{}) 46 | 47 | assert.NoError(t, err) 48 | assert.IsType(t, res, &api.SmartMetrics{}) 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/ssh.py: -------------------------------------------------------------------------------- 1 | from typing import Any, List, Tuple 2 | 3 | import logging 4 | import paramiko 5 | 6 | 7 | class SSHCommandExecutor: 8 | """ 9 | A class for executing SSH commands on a remote server. 10 | 11 | Args: 12 | ip_address (str): The IP address of the SSH server. 13 | username (str): The username for authentication. 14 | password (str): The password for authentication. 15 | """ 16 | 17 | def __init__(self, ip_address: str, username: str, password: str) -> None: 18 | """ 19 | Initializes the SSHCommandExecutor with the given IP address, username, and password. 20 | """ 21 | self.ip_address = ip_address 22 | self.username = username 23 | self.password = password 24 | 25 | def exec(self, command: str) -> Tuple[str, List[Any]]: 26 | """ 27 | Executes an SSH command on the remote server. 28 | 29 | Args 30 | command (str): The command to execute. 31 | 32 | Returns: 33 | str: The output of the executed command. 34 | list: A list of error messages, if any, from the executed command. 35 | """ 36 | ssh_client = paramiko.SSHClient() 37 | ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 38 | ssh_client.connect( 39 | self.ip_address, username=self.username, password=self.password) 40 | 41 | logging.info(f"SSH connected to {self.ip_address}, executing command: {command}") 42 | _, stdout, stderr = ssh_client.exec_command(command) 43 | output = stdout.read().decode().strip() 44 | error = stderr.readlines() 45 | 46 | ssh_client.close() 47 | 48 | if len(error) > 0: 49 | logging.warning(f"SSH command {command} failed: {error}") 50 | 51 | return output, error 52 | -------------------------------------------------------------------------------- /pkg/base/logger/logger_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package logger 18 | 19 | import ( 20 | "os" 21 | "testing" 22 | 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestInitLoggerStdOut(t *testing.T) { 27 | logger, err := InitLogger("", InfoLevel) 28 | if err != nil { 29 | t.Errorf("Logger initialized with error: %s", err.Error()) 30 | } 31 | 32 | assert.Equal(t, logger.Out, os.Stdout, "Logger output was't set correctly") 33 | } 34 | 35 | func TestInitLoggerCorrectPath(t *testing.T) { 36 | logPath := "/tmp/logs.log" 37 | logger, err := InitLogger(logPath, InfoLevel) 38 | if err != nil { 39 | t.Errorf("Logger initialized with error: %s", err.Error()) 40 | } 41 | 42 | outputFile, ok := logger.Out.(*os.File) 43 | 44 | assert.True(t, ok, "Can't convert logger output to the file") 45 | 46 | assert.Equal(t, outputFile.Name(), logPath, "Logger output was't set correctly") 47 | } 48 | 49 | func TestInitLoggerWrongPath(t *testing.T) { 50 | logPath := "////" 51 | logger, err := InitLogger(logPath, InfoLevel) 52 | if err == nil { 53 | t.Errorf("Logger should be initialized with an error") 54 | } 55 | 56 | assert.Equal(t, logger.Out, os.Stdout, "Logger's defalut output should be set to the stdout") 57 | } 58 | -------------------------------------------------------------------------------- /pkg/base/util/healthcheck_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "testing" 23 | "time" 24 | 25 | "github.com/sirupsen/logrus" 26 | "github.com/stretchr/testify/assert" 27 | "google.golang.org/grpc/health/grpc_health_v1" 28 | 29 | "github.com/dell/csi-baremetal/pkg/base" 30 | grpc "github.com/dell/csi-baremetal/pkg/base/rpc" 31 | "github.com/dell/csi-baremetal/pkg/mocks/rpc" 32 | ) 33 | 34 | var testLogger = logrus.New() 35 | 36 | func Test_SetupAndStartHealthCheckServer(t *testing.T) { 37 | healthServer := rpc.NewMockHealthServer() 38 | endpoint := fmt.Sprintf("tcp://%s:%d", base.DefaultHealthIP, base.DefaultHealthPort) 39 | go func() { 40 | err := SetupAndStartHealthCheckServer(healthServer, testLogger, endpoint) 41 | assert.Nil(t, err) 42 | }() 43 | time.Sleep(3 * time.Second) 44 | 45 | client, err := grpc.NewClient(nil, endpoint, false, testLogger) 46 | assert.Nil(t, err) 47 | 48 | healthClient := grpc_health_v1.NewHealthClient(client.GRPCClient) 49 | 50 | check, err := healthClient.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{}) 51 | assert.Nil(t, err) 52 | assert.Equal(t, grpc_health_v1.HealthCheckResponse_SERVING, check.Status) 53 | } 54 | -------------------------------------------------------------------------------- /api/v1/storagegroupcrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package sgcrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageGroup. 13 | func (in *StorageGroup) DeepCopy() *StorageGroup { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(StorageGroup) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *StorageGroup) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *StorageGroupList) DeepCopyInto(out *StorageGroupList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]StorageGroup, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageGroupList. 45 | func (in *StorageGroupList) DeepCopy() *StorageGroupList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(StorageGroupList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *StorageGroupList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /tests/app/nginx-block.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 3 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | app.kubernetes.io/name: nginx 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx 17 | app.kubernetes.io/name: nginx 18 | spec: 19 | affinity: 20 | podAntiAffinity: 21 | requiredDuringSchedulingIgnoredDuringExecution: 22 | - labelSelector: 23 | matchExpressions: 24 | - key: app 25 | operator: In 26 | values: 27 | - nginx 28 | topologyKey: "kubernetes.io/hostname" 29 | containers: 30 | - name: nginx 31 | image: k8s.gcr.io/nginx-slim:0.8 32 | ports: 33 | - containerPort: 80 34 | name: web 35 | volumeDevices: 36 | - name: www 37 | devicePath: /usr/share/nginx/html 38 | - name: data 39 | devicePath: /usr/share/nginx/data 40 | - name: logs 41 | devicePath: /usr/share/nginx/logs 42 | volumeClaimTemplates: 43 | - metadata: 44 | name: www 45 | spec: 46 | storageClassName: csi-baremetal-sc 47 | accessModes: [ "ReadWriteOnce" ] 48 | volumeMode: Block 49 | resources: 50 | requests: 51 | storage: 60Mi 52 | - metadata: 53 | name: data 54 | spec: 55 | storageClassName: csi-baremetal-sc 56 | accessModes: [ "ReadWriteOnce" ] 57 | volumeMode: Block 58 | resources: 59 | requests: 60 | storage: 60Mi 61 | - metadata: 62 | name: logs 63 | spec: 64 | storageClassName: csi-baremetal-sc 65 | accessModes: [ "ReadWriteOnce" ] 66 | volumeMode: Block 67 | resources: 68 | requests: 69 | storage: 60Mi 70 | -------------------------------------------------------------------------------- /api/v1/availablecapacitycrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package accrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableCapacity. 13 | func (in *AvailableCapacity) DeepCopy() *AvailableCapacity { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(AvailableCapacity) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *AvailableCapacity) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *AvailableCapacityList) DeepCopyInto(out *AvailableCapacityList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]AvailableCapacity, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableCapacityList. 45 | func (in *AvailableCapacityList) DeepCopy() *AvailableCapacityList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(AvailableCapacityList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *AvailableCapacityList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /api/v1/lvgcrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package lvgcrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicalVolumeGroup. 13 | func (in *LogicalVolumeGroup) DeepCopy() *LogicalVolumeGroup { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(LogicalVolumeGroup) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *LogicalVolumeGroup) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *LogicalVolumeGroupList) DeepCopyInto(out *LogicalVolumeGroupList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]LogicalVolumeGroup, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LogicalVolumeGroupList. 45 | func (in *LogicalVolumeGroupList) DeepCopy() *LogicalVolumeGroupList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(LogicalVolumeGroupList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *LogicalVolumeGroupList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /tests/app/nginx-block-lvg.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 3 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | app.kubernetes.io/name: nginx 13 | template: 14 | metadata: 15 | labels: 16 | app: nginx 17 | app.kubernetes.io/name: nginx 18 | spec: 19 | affinity: 20 | podAntiAffinity: 21 | requiredDuringSchedulingIgnoredDuringExecution: 22 | - labelSelector: 23 | matchExpressions: 24 | - key: app 25 | operator: In 26 | values: 27 | - nginx 28 | topologyKey: "kubernetes.io/hostname" 29 | containers: 30 | - name: nginx 31 | image: k8s.gcr.io/nginx-slim:0.8 32 | ports: 33 | - containerPort: 80 34 | name: web 35 | volumeDevices: 36 | - name: www 37 | devicePath: /usr/share/nginx/html 38 | - name: data 39 | devicePath: /usr/share/nginx/data 40 | - name: logs 41 | devicePath: /usr/share/nginx/logs 42 | volumeClaimTemplates: 43 | - metadata: 44 | name: www 45 | spec: 46 | storageClassName: csi-baremetal-sc-hddlvg 47 | accessModes: [ "ReadWriteOnce" ] 48 | volumeMode: Block 49 | resources: 50 | requests: 51 | storage: 20Mi 52 | - metadata: 53 | name: data 54 | spec: 55 | storageClassName: csi-baremetal-sc-hddlvg 56 | accessModes: [ "ReadWriteOnce" ] 57 | volumeMode: Block 58 | resources: 59 | requests: 60 | storage: 20Mi 61 | - metadata: 62 | name: logs 63 | spec: 64 | storageClassName: csi-baremetal-sc-hddlvg 65 | accessModes: [ "ReadWriteOnce" ] 66 | volumeMode: Block 67 | resources: 68 | requests: 69 | storage: 20Mi 70 | -------------------------------------------------------------------------------- /cmd/drivemgr/basemgr/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "fmt" 22 | 23 | dmsetup "github.com/dell/csi-baremetal/cmd/drivemgr" 24 | "github.com/dell/csi-baremetal/pkg/base" 25 | "github.com/dell/csi-baremetal/pkg/base/command" 26 | "github.com/dell/csi-baremetal/pkg/base/logger" 27 | "github.com/dell/csi-baremetal/pkg/base/rpc" 28 | "github.com/dell/csi-baremetal/pkg/drivemgr/basemgr" 29 | ) 30 | 31 | var ( 32 | endpoint = flag.String("drivemgrendpoint", base.DefaultDriveMgrEndpoint, "DriveManager Endpoint") 33 | logPath = flag.String("logpath", "", "log path for DriveManager") 34 | logLevel = flag.String("loglevel", logger.InfoLevel, 35 | fmt.Sprintf("Log level, support values are %s, %s, %s", logger.InfoLevel, logger.DebugLevel, logger.TraceLevel)) 36 | ) 37 | 38 | func main() { 39 | flag.Parse() 40 | 41 | logger, err := logger.InitLogger(*logPath, *logLevel) 42 | if err != nil { 43 | logger.Warnf("Can't set logger's output to %s. Using stdout instead.\n", *logPath) 44 | } 45 | 46 | // Server is insecure for now because credentials are nil 47 | serverRunner := rpc.NewServerRunner(nil, *endpoint, false, logger) 48 | 49 | e := command.NewExecutor(logger) 50 | 51 | driveMgr := basemgr.New(e, logger) 52 | 53 | dmsetup.SetupAndRunDriveMgr(driveMgr, serverRunner, nil, logger) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/controller/mountoptions/mount_options.go: -------------------------------------------------------------------------------- 1 | package mountoptions 2 | 3 | /* 4 | In this package placed supported mount options pass from SCs 5 | Example: 6 | apiVersion: storage.k8s.io/v1 7 | kind: StorageClass 8 | metadata: 9 | name: sc1 10 | mountOptions: 11 | - noatime 12 | */ 13 | 14 | // MountOptionType type to clarify option purpose 15 | type MountOptionType string 16 | 17 | const ( 18 | // PublishCmdOpt are options for mount func on NodePublishRequest 19 | // Example: mount -o /src /dst 20 | PublishCmdOpt = MountOptionType("cmdOpt") 21 | ) 22 | 23 | // MountOption describes mount option 24 | type MountOption struct { 25 | arg string 26 | mountType MountOptionType 27 | } 28 | 29 | const ( 30 | noatimeOpt = "noatime" 31 | ) 32 | 33 | var ( 34 | // supportedMountOption contains all supported options 35 | // map[optName]{optArg, optType} 36 | // optName - passed from SC 37 | // optArg - cmd string 38 | supportedMountOption = map[string]MountOption{ 39 | noatimeOpt: { 40 | arg: noatimeOpt, 41 | mountType: PublishCmdOpt, 42 | }, 43 | } 44 | ) 45 | 46 | // IsOptionSupported returns true if option in supportedMountOption 47 | func IsOptionSupported(option string) bool { 48 | _, ok := supportedMountOption[option] 49 | return ok 50 | } 51 | 52 | // IsOptionsSupported returns true if all options in supportedMountOption 53 | func IsOptionsSupported(options []string) bool { 54 | for _, option := range options { 55 | if !IsOptionSupported(option) { 56 | return false 57 | } 58 | } 59 | 60 | return true 61 | } 62 | 63 | // FilterWithType returns all option from list with passed type 64 | func FilterWithType(mountType MountOptionType, options []string) (filteredOptions []string) { 65 | for _, option := range options { 66 | if val, ok := supportedMountOption[option]; ok { 67 | if mountType == val.mountType { 68 | filteredOptions = append(filteredOptions, val.arg) 69 | } 70 | } 71 | } 72 | 73 | return 74 | } 75 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | release: 5 | types: 6 | - created 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Parse release description 14 | id: split_description 15 | uses: winterjung/split@v2 16 | with: 17 | msg: ${{ github.event.release.body }} 18 | 19 | - name: Set vars 20 | id: vars 21 | run: | 22 | component_name_1=`echo "${{ steps.split_description.outputs._0 }}" | tr -d ':'` 23 | component_name_2=`echo "${{ steps.split_description.outputs._2 }}" | tr -d ':'` 24 | version_1=`echo "${{ steps.split_description.outputs._1 }}" | tr -d ','` 25 | version_2=`echo "${{ steps.split_description.outputs._3 }}" | tr -d ','` 26 | echo "::set-output name=${component_name_1}::$version_1" 27 | echo "::set-output name=${component_name_2}::$version_2" 28 | 29 | - name: Checkout code 30 | uses: actions/checkout@v2 31 | with: 32 | ref: ${{ github.event.release.target_commitish }} 33 | 34 | - name: Trigger release workflow in csi-baremetal-operator repo 35 | uses: benc-uk/workflow-dispatch@v1 36 | with: 37 | workflow: Release Charts 38 | repo: dell/csi-baremetal-operator 39 | token: ${{ secrets.CSI_WF_TOKEN }} 40 | ref: refs/heads/master # need to hardcode here because of this issue: https://github.com/benc-uk/workflow-dispatch/issues/11 41 | inputs: | 42 | { "csi_version": "${{ steps.vars.outputs.csi_version }}", 43 | "csi_operator_version": "${{ steps.vars.outputs.csi_operator_version }}", 44 | "release_tag": "${{ github.event.release.tag_name }}", 45 | "branch": "${{ github.event.release.target_commitish }}", 46 | "prerelease": ${{ github.event.release.prerelease }} } 47 | if: startsWith(github.ref, 'refs/tags/') 48 | -------------------------------------------------------------------------------- /tests/e2e/common/helm.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/dell/csi-baremetal/pkg/base/command" 23 | ) 24 | 25 | type HelmExecutor interface { 26 | InstallRelease(path, ns string) error 27 | DeleteRelease(path, ns string) error 28 | } 29 | 30 | // CmdHelmExecutor is HelmExecutor implementation using os/exec.Cmd 31 | type CmdHelmExecutor struct { 32 | kubeconfig string 33 | executor command.CmdExecutor 34 | } 35 | 36 | // HelmChart stores info about chart in filesystem 37 | type HelmChart struct { 38 | name string 39 | path string 40 | namespace string 41 | } 42 | 43 | // InstallRelease calls "helm install" for chart with set args 44 | // and creates namespace if not created 45 | func (c *CmdHelmExecutor) InstallRelease(ch *HelmChart, args string) error { 46 | cmdStr := fmt.Sprintf("helm install %s %s --kubeconfig %s -n %s "+args, 47 | ch.name, ch.path, c.kubeconfig, ch.namespace) 48 | 49 | _, _, err := c.executor.RunCmd(cmdStr) 50 | 51 | return err 52 | } 53 | 54 | // DeleteRelease call "helm delete" for chart 55 | func (c *CmdHelmExecutor) DeleteRelease(ch *HelmChart) error { 56 | cmdStr := fmt.Sprintf("helm delete "+ 57 | "--kubeconfig %s "+ 58 | "-n %s "+"%s", 59 | c.kubeconfig, ch.namespace, ch.name) 60 | 61 | _, _, err := c.executor.RunCmd(cmdStr) 62 | 63 | return err 64 | } 65 | -------------------------------------------------------------------------------- /pkg/mocks/linuxutils/lsblk.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package linuxutils 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | api "github.com/dell/csi-baremetal/api/generated/v1" 23 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/lsblk" 24 | ) 25 | 26 | // MockWrapLsblk is a mock implementation of WrapLsblk interface from lsblk package 27 | type MockWrapLsblk struct { 28 | mock.Mock 29 | } 30 | 31 | // GetMockWrapLsblk retruns MockWrapLsblk that perform each method without any error 32 | // everytimePath is a path that will be returning for each "SearchDrivePath" call 33 | func GetMockWrapLsblk(everytimePath string) *MockWrapLsblk { 34 | mvl := MockWrapLsblk{} 35 | mvl.On("GetBlockDevices", mock.Anything).Return(nil, nil) 36 | mvl.On("SearchDrivePath", mock.Anything).Return(everytimePath, nil) 37 | 38 | return &mvl 39 | } 40 | 41 | // GetBlockDevices is a mock implementations 42 | func (m *MockWrapLsblk) GetBlockDevices(device string) ([]lsblk.BlockDevice, error) { 43 | args := m.Mock.Called(device) 44 | 45 | if args.Get(0) == nil { 46 | return nil, args.Error(1) 47 | } 48 | return args.Get(0).([]lsblk.BlockDevice), args.Error(1) 49 | } 50 | 51 | // SearchDrivePath is a mock implementations 52 | func (m *MockWrapLsblk) SearchDrivePath(drive *api.Drive) (string, error) { 53 | args := m.Mock.Called(drive) 54 | 55 | return args.String(0), args.Error(1) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/base/cache/cache.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package cache contains common interface for caches with Get, Delete and Set methods and in memory cache implementation 18 | package cache 19 | 20 | import ( 21 | "errors" 22 | "sync" 23 | ) 24 | 25 | // Interface contains methods for caches 26 | type Interface interface { 27 | Get(key string) (string, error) 28 | Set(key, object string) 29 | Delete(key string) 30 | } 31 | 32 | // MemCache is an implementation of Interface 33 | type MemCache struct { 34 | items map[string]string 35 | sync.RWMutex 36 | } 37 | 38 | // NewMemCache is a constructor for MemCache 39 | func NewMemCache() *MemCache { 40 | return &MemCache{ 41 | items: make(map[string]string), 42 | } 43 | } 44 | 45 | // Get return item from MemCache using given key or error in case of missing key 46 | func (c *MemCache) Get(key string) (string, error) { 47 | c.Lock() 48 | defer c.Unlock() 49 | 50 | item, ok := c.items[key] 51 | if !ok { 52 | return "", errors.New("item wasn't found") 53 | } 54 | return item, nil 55 | } 56 | 57 | // Set adds object to MemCache with given key 58 | func (c *MemCache) Set(key, object string) { 59 | c.Lock() 60 | defer c.Unlock() 61 | 62 | c.items[key] = object 63 | } 64 | 65 | // Delete deletes object from MemCache with given key 66 | func (c *MemCache) Delete(key string) { 67 | c.Lock() 68 | defer c.Unlock() 69 | 70 | delete(c.items, key) 71 | } 72 | -------------------------------------------------------------------------------- /tests/app/nginx-generic-ephemeral.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 2 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | affinity: 18 | podAntiAffinity: 19 | requiredDuringSchedulingIgnoredDuringExecution: 20 | - labelSelector: 21 | matchExpressions: 22 | - key: app 23 | operator: In 24 | values: 25 | - nginx 26 | topologyKey: "kubernetes.io/hostname" 27 | containers: 28 | - name: nginx 29 | image: k8s.gcr.io/nginx-slim:0.8 30 | ports: 31 | - containerPort: 80 32 | name: web 33 | volumeMounts: 34 | - name: www 35 | mountPath: /usr/share/nginx/html 36 | - name: data 37 | mountPath: /usr/share/nginx/data 38 | - name: logs 39 | mountPath: /usr/share/nginx/logs 40 | volumes: 41 | - name: www 42 | ephemeral: 43 | volumeClaimTemplate: 44 | spec: 45 | accessModes: [ "ReadWriteOnce" ] 46 | storageClassName: csi-baremetal-sc 47 | resources: 48 | requests: 49 | storage: 60Mi 50 | - name: data 51 | ephemeral: 52 | volumeClaimTemplate: 53 | spec: 54 | accessModes: [ "ReadWriteOnce" ] 55 | storageClassName: csi-baremetal-sc 56 | resources: 57 | requests: 58 | storage: 60Mi 59 | - name: logs 60 | ephemeral: 61 | volumeClaimTemplate: 62 | spec: 63 | accessModes: [ "ReadWriteOnce" ] 64 | storageClassName: csi-baremetal-sc 65 | resources: 66 | requests: 67 | storage: 60Mi 68 | 69 | -------------------------------------------------------------------------------- /pkg/node/provisioners/volumeprovisioner.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package provisioners contains code for Volume CR reconcile handling 18 | // during which volumes on node are created or removed 19 | // It operates by underlying structures such as a drives/partitions/file system 20 | // and encapsulates all low-level work with these objects. 21 | package provisioners 22 | 23 | import api "github.com/dell/csi-baremetal/api/generated/v1" 24 | 25 | // VolumeType is used for describing class of volume depending on underlying structures 26 | // volume could be based on partitions, logical volume and so on 27 | type VolumeType string 28 | 29 | const ( 30 | // DriveBasedVolumeType represents volume that consumes whole drive 31 | DriveBasedVolumeType VolumeType = "DriveBased" 32 | // LVMBasedVolumeType represents volume that based on Volume Group 33 | LVMBasedVolumeType VolumeType = "LVMBased" 34 | ) 35 | 36 | // Provisioner is a high-level interface that encapsulates all low-level work with volumes on node 37 | type Provisioner interface { 38 | // PrepareVolume prepares volume for mount 39 | PrepareVolume(volume *api.Volume) error 40 | // ReleaseVolume completely releases underlying resources that had consumed by volume 41 | ReleaseVolume(volume *api.Volume, drive *api.Drive) error 42 | // GetVolumePath returns full path of device file that represent volume on node 43 | GetVolumePath(volume *api.Volume) (string, error) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/events/mocks/EventSink.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v2.0.0-alpha.2. DO NOT EDIT. 2 | 3 | package mocks 4 | 5 | import ( 6 | mock "github.com/stretchr/testify/mock" 7 | 8 | v1 "k8s.io/api/core/v1" 9 | ) 10 | 11 | // EventSink is an autogenerated mock type for the EventSink type 12 | type EventSink struct { 13 | mock.Mock 14 | } 15 | 16 | // Create provides a mock function with given fields: event 17 | func (_m *EventSink) Create(event *v1.Event) (*v1.Event, error) { 18 | ret := _m.Called(event) 19 | 20 | var r0 *v1.Event 21 | if rf, ok := ret.Get(0).(func(*v1.Event) *v1.Event); ok { 22 | r0 = rf(event) 23 | } else { 24 | if ret.Get(0) != nil { 25 | r0 = ret.Get(0).(*v1.Event) 26 | } 27 | } 28 | 29 | var r1 error 30 | if rf, ok := ret.Get(1).(func(*v1.Event) error); ok { 31 | r1 = rf(event) 32 | } else { 33 | r1 = ret.Error(1) 34 | } 35 | 36 | return r0, r1 37 | } 38 | 39 | // Patch provides a mock function with given fields: oldEvent, data 40 | func (_m *EventSink) Patch(oldEvent *v1.Event, data []byte) (*v1.Event, error) { 41 | ret := _m.Called(oldEvent, data) 42 | 43 | var r0 *v1.Event 44 | if rf, ok := ret.Get(0).(func(*v1.Event, []byte) *v1.Event); ok { 45 | r0 = rf(oldEvent, data) 46 | } else { 47 | if ret.Get(0) != nil { 48 | r0 = ret.Get(0).(*v1.Event) 49 | } 50 | } 51 | 52 | var r1 error 53 | if rf, ok := ret.Get(1).(func(*v1.Event, []byte) error); ok { 54 | r1 = rf(oldEvent, data) 55 | } else { 56 | r1 = ret.Error(1) 57 | } 58 | 59 | return r0, r1 60 | } 61 | 62 | // Update provides a mock function with given fields: event 63 | func (_m *EventSink) Update(event *v1.Event) (*v1.Event, error) { 64 | ret := _m.Called(event) 65 | 66 | var r0 *v1.Event 67 | if rf, ok := ret.Get(0).(func(*v1.Event) *v1.Event); ok { 68 | r0 = rf(event) 69 | } else { 70 | if ret.Get(0) != nil { 71 | r0 = ret.Get(0).(*v1.Event) 72 | } 73 | } 74 | 75 | var r1 error 76 | if rf, ok := ret.Get(1).(func(*v1.Event) error); ok { 77 | r1 = rf(event) 78 | } else { 79 | r1 = ret.Error(1) 80 | } 81 | 82 | return r0, r1 83 | } 84 | -------------------------------------------------------------------------------- /api/v1/acreservationcrd/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | // +build !ignore_autogenerated 3 | 4 | // Code generated by controller-gen. DO NOT EDIT. 5 | 6 | package acrcrd 7 | 8 | import ( 9 | runtime "k8s.io/apimachinery/pkg/runtime" 10 | ) 11 | 12 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableCapacityReservation. 13 | func (in *AvailableCapacityReservation) DeepCopy() *AvailableCapacityReservation { 14 | if in == nil { 15 | return nil 16 | } 17 | out := new(AvailableCapacityReservation) 18 | in.DeepCopyInto(out) 19 | return out 20 | } 21 | 22 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 23 | func (in *AvailableCapacityReservation) DeepCopyObject() runtime.Object { 24 | if c := in.DeepCopy(); c != nil { 25 | return c 26 | } 27 | return nil 28 | } 29 | 30 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 31 | func (in *AvailableCapacityReservationList) DeepCopyInto(out *AvailableCapacityReservationList) { 32 | *out = *in 33 | out.TypeMeta = in.TypeMeta 34 | in.ListMeta.DeepCopyInto(&out.ListMeta) 35 | if in.Items != nil { 36 | in, out := &in.Items, &out.Items 37 | *out = make([]AvailableCapacityReservation, len(*in)) 38 | for i := range *in { 39 | (*in)[i].DeepCopyInto(&(*out)[i]) 40 | } 41 | } 42 | } 43 | 44 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AvailableCapacityReservationList. 45 | func (in *AvailableCapacityReservationList) DeepCopy() *AvailableCapacityReservationList { 46 | if in == nil { 47 | return nil 48 | } 49 | out := new(AvailableCapacityReservationList) 50 | in.DeepCopyInto(out) 51 | return out 52 | } 53 | 54 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 55 | func (in *AvailableCapacityReservationList) DeepCopyObject() runtime.Object { 56 | if c := in.DeepCopy(); c != nil { 57 | return c 58 | } 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /api/v1/nodecrd/node_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package nodecrd 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | 22 | api "github.com/dell/csi-baremetal/api/generated/v1" 23 | ) 24 | 25 | // +kubebuilder:object:root=true 26 | 27 | // Node is the Schema for the Node API 28 | // +kubebuilder:resource:scope=Cluster,shortName={csibmnode,csibmnodes} 29 | // +kubebuilder:printcolumn:name="UUID",type="string",JSONPath=".spec.UUID",description="Node Id" 30 | // +kubebuilder:printcolumn:name="HOSTNAME",type="string",JSONPath=".spec.Addresses.Hostname",description="Node hostname" 31 | // +kubebuilder:printcolumn:name="NODE_IP",type="string",JSONPath=".spec.Addresses.InternalIP",description="Node ip" 32 | type Node struct { 33 | metav1.TypeMeta `json:",inline"` 34 | metav1.ObjectMeta `json:"metadata,omitempty"` 35 | Spec api.Node `json:"spec,omitempty"` 36 | } 37 | 38 | // +kubebuilder:object:root=true 39 | 40 | // NodeList contains a list of Node 41 | //+kubebuilder:object:generate=true 42 | type NodeList struct { 43 | metav1.TypeMeta `json:",inline"` 44 | metav1.ListMeta `json:"metadata,omitempty"` 45 | Items []Node `json:"items"` 46 | } 47 | 48 | func init() { 49 | SchemeBuilderACR.Register(&Node{}, &NodeList{}) 50 | } 51 | 52 | func (in *Node) DeepCopyInto(out *Node) { 53 | *out = *in 54 | out.TypeMeta = in.TypeMeta 55 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 56 | out.Spec = in.Spec 57 | } 58 | -------------------------------------------------------------------------------- /api/smart/generated/oas_parameters_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by ogen, DO NOT EDIT. 2 | 3 | package api 4 | 5 | import ( 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/go-faster/errors" 10 | 11 | "github.com/ogen-go/ogen/conv" 12 | "github.com/ogen-go/ogen/middleware" 13 | "github.com/ogen-go/ogen/ogenerrors" 14 | "github.com/ogen-go/ogen/uri" 15 | "github.com/ogen-go/ogen/validate" 16 | ) 17 | 18 | // GetDriveSmartInfoParams is parameters of get-drive-smart-info operation. 19 | type GetDriveSmartInfoParams struct { 20 | SerialNumber string 21 | } 22 | 23 | func unpackGetDriveSmartInfoParams(packed middleware.Parameters) (params GetDriveSmartInfoParams) { 24 | { 25 | key := middleware.ParameterKey{ 26 | Name: "serialNumber", 27 | In: "path", 28 | } 29 | params.SerialNumber = packed[key].(string) 30 | } 31 | return params 32 | } 33 | 34 | func decodeGetDriveSmartInfoParams(args [1]string, argsEscaped bool, r *http.Request) (params GetDriveSmartInfoParams, _ error) { 35 | // Decode path: serialNumber. 36 | if err := func() error { 37 | param := args[0] 38 | if argsEscaped { 39 | unescaped, err := url.PathUnescape(args[0]) 40 | if err != nil { 41 | return errors.Wrap(err, "unescape path") 42 | } 43 | param = unescaped 44 | } 45 | if len(param) > 0 { 46 | d := uri.NewPathDecoder(uri.PathDecoderConfig{ 47 | Param: "serialNumber", 48 | Value: param, 49 | Style: uri.PathStyleSimple, 50 | Explode: false, 51 | }) 52 | 53 | if err := func() error { 54 | val, err := d.DecodeValue() 55 | if err != nil { 56 | return err 57 | } 58 | 59 | c, err := conv.ToString(val) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | params.SerialNumber = c 65 | return nil 66 | }(); err != nil { 67 | return err 68 | } 69 | } else { 70 | return validate.ErrFieldRequired 71 | } 72 | return nil 73 | }(); err != nil { 74 | return params, &ogenerrors.DecodeParamError{ 75 | Name: "serialNumber", 76 | In: "path", 77 | Err: err, 78 | } 79 | } 80 | return params, nil 81 | } 82 | -------------------------------------------------------------------------------- /docs/proposals/distributed-tracing-of-volume-requests.md: -------------------------------------------------------------------------------- 1 | # Proposal: Distributed tracing of CSI volume requests 2 | 3 | Last updated: 7-Feb-2022 4 | 5 | 6 | ## Abstract 7 | 8 | Distributed tracing is a must for every microservices architecture: it allows to detect issues quickly and offers valuable insights that can decrease response time from hours to minutes. 9 | 10 | ## Background 11 | 12 | To create, expand, delete persistent volumes different requests are handled by CSI across multiple components. For details please see [flow diagrams of CSI volume requests](https://github.com/dell/csi-baremetal/blob/master/docs/volume-requests-flow.md). 13 | When system doesn't respond in expected time frame it's really hard to find the issue using just metrics or log analysis. 14 | 15 | ## Proposal 16 | 17 | Proposal is to use OpenTelemetry API and SDK https://opentelemetry.io/docs/instrumentation/go/ and distributed tracing system Jaeger https://www.jaegertracing.io/ to: 18 | - Distributed transaction monitoring 19 | - Root cause analysis 20 | - Performance / latency optimization 21 | 22 | ## Rationale 23 | 24 | Distributed tracing must be supported in CSI. The open question whether to make it configurable or not. 25 | 26 | ## Compatibility 27 | 28 | No compatibility issues 29 | 30 | ## Implementation 31 | 32 | The following methods must be instrumented: 33 | - Scheduler extender 34 | - FilterHandler 35 | - PrioritizeHandler 36 | - Controller 37 | - Reconcile of ACR CR 38 | - CreateVolume 39 | - ControllerExpandVolume 40 | - DeleteVolume 41 | - Node 42 | - Reconcile of Volume CR 43 | - Reconcile of LVG CR 44 | - NodeStageVolume 45 | - NodePublishVolume 46 | - NodeUnpublishVolume 47 | - NodeUnstageVolume 48 | 49 | ## Assumptions (if applicable) 50 | 51 | ID | Name | Descriptions | Comments 52 | ---| -----| -------------| -------- 53 | ASSUM-1 | | | 54 | 55 | 56 | ## Open issues (if applicable) 57 | 58 | ID | Name | Descriptions | Status | Comments 59 | ---| -----| -------------| ------ | -------- 60 | ISSUE-1 | Optional | Should tracing be optional or mandatory? | Open | Do we need it in production? 61 | -------------------------------------------------------------------------------- /pkg/mocks/provisioners/fs_operations.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package provisioners 18 | 19 | import ( 20 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/fs" 21 | mocklu "github.com/dell/csi-baremetal/pkg/mocks/linuxutils" 22 | ) 23 | 24 | // MockFsOpts is a mock implementation of FSOperation interface from volumeprovisioner package 25 | type MockFsOpts struct { 26 | mocklu.MockWrapFS 27 | } 28 | 29 | // PrepareAndPerformMount is a mock implementation 30 | func (m *MockFsOpts) PrepareAndPerformMount(src, dst string, bindMount, dstIsDir bool, _ ...string) error { 31 | args := m.Mock.Called(src, dst, bindMount, dstIsDir) 32 | 33 | return args.Error(0) 34 | } 35 | 36 | // MountFakeTmpfs is a mock implementation 37 | func (m *MockFsOpts) MountFakeTmpfs(volumeID, path string) error { 38 | args := m.Mock.Called(volumeID, path) 39 | 40 | return args.Error(0) 41 | } 42 | 43 | // UnmountWithCheck is a mock implementation 44 | func (m *MockFsOpts) UnmountWithCheck(path string) error { 45 | args := m.Mock.Called(path) 46 | 47 | return args.Error(0) 48 | } 49 | 50 | // CreateFSIfNotExist is a mock implementation 51 | func (m *MockFsOpts) CreateFSIfNotExist(fsType fs.FileSystem, device, uuid string) error { 52 | args := m.Mock.Called(fsType, device, uuid) 53 | 54 | return args.Error(0) 55 | } 56 | 57 | // CreateFakeDevice is a mock implementation 58 | func (m *MockFsOpts) CreateFakeDevice(src string) (string, error) { 59 | args := m.Mock.Called(src) 60 | 61 | return args.String(0), args.Error(1) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/base/util/signal_handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "os" 21 | "os/signal" 22 | "syscall" 23 | 24 | "github.com/sirupsen/logrus" 25 | 26 | "github.com/dell/csi-baremetal/pkg/base/rpc" 27 | ) 28 | 29 | // SignalHandler is a structure which contains methods for signal handling 30 | type SignalHandler struct { 31 | log *logrus.Entry 32 | } 33 | 34 | // NewSignalHandler is a constructor for SignalHandler 35 | func NewSignalHandler(logger *logrus.Logger) *SignalHandler { 36 | return &SignalHandler{log: logger.WithField("component", "SignalHandler")} 37 | } 38 | 39 | // SetupSIGTERMHandler tries to shutdown service, when SIGTERM is caught 40 | func (sh *SignalHandler) SetupSIGTERMHandler(server *rpc.ServerRunner) { 41 | sh.setupSignalHandler(syscall.SIGTERM) 42 | // We received an interrupt signal, shut down. 43 | server.StopServer() 44 | } 45 | 46 | // SetupSIGHUPHandler tries to make cleanup, when SIGHUP is caught 47 | func (sh *SignalHandler) SetupSIGHUPHandler(cleanupFn func()) { 48 | sh.setupSignalHandler(syscall.SIGHUP) 49 | // We received an SIGHUP signal, clean up. 50 | if cleanupFn != nil { 51 | cleanupFn() 52 | } 53 | } 54 | 55 | // setupSignalHandler sets up channel for signal 56 | func (sh *SignalHandler) setupSignalHandler(sig syscall.Signal) { 57 | signalChan := make(chan os.Signal, 1) 58 | 59 | signal.Notify(signalChan, sig) 60 | 61 | // Wait signal 62 | <-signalChan 63 | 64 | sh.log.WithField("method", "setupSignalHandler").Debugf("Got %v signal", sig) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/base/rpc/grpcclient_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package rpc 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/sirupsen/logrus" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | var ( 27 | testTcpEndpoint string = "tcp://localhost:50051" 28 | testUdsEndpoint string = "unix:///tmp/csi.sock" 29 | testFailEndpoint string = "dsf:// df df :sdf" 30 | clientLogger *logrus.Logger = logrus.New() 31 | ) 32 | 33 | func TestNewClient_Success(t *testing.T) { 34 | client, err := NewClient(nil, testTcpEndpoint, false, clientLogger) 35 | assert.Nil(t, err) 36 | assert.Nil(t, client.Creds) 37 | assert.NotNil(t, client.GRPCClient) 38 | assert.Equal(t, testTcpEndpoint, client.Endpoint) 39 | } 40 | 41 | func TestNewClient_Fail(t *testing.T) { 42 | client, err := NewClient(nil, testFailEndpoint, false, clientLogger) 43 | assert.NotNil(t, err) 44 | assert.Nil(t, client) 45 | assert.Contains(t, err.Error(), "unable to create client") 46 | } 47 | 48 | func TestClientClose(t *testing.T) { 49 | client, _ := NewClient(nil, testTcpEndpoint, false, clientLogger) 50 | err := client.Close() 51 | assert.Nil(t, err) 52 | } 53 | 54 | func TestClient_GetEndpoint(t *testing.T) { 55 | c, _ := NewClient(nil, testTcpEndpoint, false, clientLogger) 56 | actual, err := c.GetEndpoint() 57 | assert.Nil(t, err) 58 | assert.Equal(t, "localhost:50051", actual) 59 | 60 | c, _ = NewClient(nil, testUdsEndpoint, false, clientLogger) 61 | actual, err = c.GetEndpoint() 62 | assert.Nil(t, err) 63 | assert.Equal(t, "/tmp/csi.sock", actual) 64 | } 65 | -------------------------------------------------------------------------------- /pkg/events/example_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package events_test 18 | 19 | import ( 20 | "github.com/dell/csi-baremetal/pkg/eventing" 21 | "log" 22 | 23 | "github.com/sirupsen/logrus" 24 | 25 | "github.com/dell/csi-baremetal/api/v1/drivecrd" 26 | "github.com/dell/csi-baremetal/pkg/base/k8s" 27 | "github.com/dell/csi-baremetal/pkg/events" 28 | ) 29 | 30 | func Example() { 31 | // We need event interface 32 | // this would work only inside of a k8s cluster 33 | k8SClientset, err := k8s.GetK8SClientset() 34 | if err != nil { 35 | log.Fatalf("fail to create kubernetes client, error: %s", err) 36 | return 37 | } 38 | eventInter := k8SClientset.CoreV1().Events("current_ns") 39 | 40 | // get the Scheme 41 | // in our case we should use Scheme that aware of CR 42 | // if your events are based on default objects you can use runtime.NewScheme() 43 | scheme, err := k8s.PrepareScheme() 44 | if err != nil { 45 | log.Fatalf("fail to prepare kubernetes scheme, error: %s", err) 46 | return 47 | } 48 | 49 | logr := logrus.New() 50 | eventManager := &eventing.EventManager{} 51 | 52 | eventRecorder, err := events.New("baremetal-csi-node", "434aa7b1-8b8a-4ae8-92f9-1cc7e09a9030", eventInter, scheme, logr) 53 | if err != nil { 54 | log.Fatalf("fail to create events recorder, error: %s", err) 55 | return 56 | } 57 | // Wait till all events are sent/handled 58 | defer eventRecorder.Wait() 59 | 60 | // Send event 61 | drive := new(drivecrd.Drive) 62 | eventRecorder.Eventf(drive, eventManager.GenerateFake(), "DriveIsDead", "drive &s is dead", drive.GetName()) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/base/logger/runtime_formatter.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "strings" 7 | 8 | "github.com/dell/csi-baremetal/pkg/base" 9 | "github.com/sirupsen/logrus" 10 | ) 11 | 12 | // FunctionKey holds the function field 13 | const FunctionKey = "function" 14 | 15 | // FileKey holds the file field 16 | const FileKey = "file" 17 | 18 | const ( 19 | logrusStackJump = 4 20 | logrusFieldlessStackJump = 6 21 | ) 22 | 23 | // RuntimeFormatter decorates log entries with function name and package name (optional) and line number (optional) 24 | type RuntimeFormatter struct { 25 | ChildFormatter logrus.Formatter 26 | MaxLevel logrus.Level 27 | } 28 | 29 | // Format the current log entry by adding the function name and line number of the caller. 30 | func (f *RuntimeFormatter) Format(entry *logrus.Entry) ([]byte, error) { 31 | data := logrus.Fields{} 32 | if f.MaxLevel >= entry.Level { 33 | function, file, line := f.getCurrentPosition(entry) 34 | packageEnd := strings.LastIndex(function, ".") 35 | functionName := function[packageEnd+1:] 36 | 37 | // setting function name 38 | data[FunctionKey] = functionName 39 | // setting modified filepath: removing base project path and redundant delimiter 40 | adaptedFilepath := strings.TrimPrefix(file, base.ProjectPath) 41 | if adaptedFilepath != file { // if current file's path is a subdirectory of passed project path - then trim prefix delimiter 42 | adaptedFilepath = strings.TrimPrefix(adaptedFilepath, "/") 43 | } 44 | data[FileKey] = adaptedFilepath + ":" + line 45 | } 46 | for k, v := range entry.Data { 47 | data[k] = v 48 | } 49 | 50 | entry.Data = data 51 | 52 | return f.ChildFormatter.Format(entry) 53 | } 54 | 55 | func (f *RuntimeFormatter) getCurrentPosition(entry *logrus.Entry) (string, string, string) { 56 | skip := logrusStackJump 57 | if len(entry.Data) == 0 { 58 | skip = logrusFieldlessStackJump 59 | } 60 | start: 61 | pc, file, line, _ := runtime.Caller(skip) 62 | lineNumber := fmt.Sprintf("%d", line) 63 | function := runtime.FuncForPC(pc).Name() 64 | if strings.LastIndex(function, "sirupsen/logrus.") != -1 { 65 | skip++ 66 | goto start 67 | } 68 | return function, file, lineNumber 69 | } 70 | -------------------------------------------------------------------------------- /pkg/base/capacityplanner/common.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package capacityplanner 18 | 19 | import "github.com/dell/csi-baremetal/pkg/base/util" 20 | 21 | // AcSizeMinThresholdBytes means that if AC size becomes lower then AcSizeMinThresholdBytes that AC should be deleted 22 | const AcSizeMinThresholdBytes = int64(util.MBYTE) // 1MB 23 | 24 | // LvgDefaultMetadataSize is additional cost for new VG we should consider. 25 | const LvgDefaultMetadataSize = int64(util.MBYTE) // 1MB 26 | 27 | // DefaultPESize is the default extent size we should align with 28 | // TODO: use non default PE size - https://github.com/dell/csi-baremetal/issues/85 29 | const DefaultPESize = 4 * int64(util.MBYTE) 30 | 31 | // AlignSizeByPE make size aligned with default PE 32 | // TODO: use non default PE size - https://github.com/dell/csi-baremetal/issues/85 33 | func AlignSizeByPE(size int64) int64 { 34 | var alignement int64 35 | reminder := size % DefaultPESize 36 | if reminder != 0 { 37 | alignement = DefaultPESize - reminder 38 | } 39 | return size + alignement 40 | } 41 | 42 | // AlignSizeByMB make size aligned with MB 43 | func AlignSizeByMB(size int64) int64 { 44 | reminder := size % (int64(util.MBYTE)) 45 | if reminder != 0 { 46 | return size - reminder 47 | } 48 | return size 49 | } 50 | 51 | // SubtractLVMMetadataSize subtracts LVM metadata size from raw drive size 52 | func SubtractLVMMetadataSize(size int64) int64 { 53 | reminder := size % DefaultPESize 54 | result := size - reminder 55 | if reminder < LvgDefaultMetadataSize { 56 | return result - DefaultPESize 57 | } 58 | return result 59 | } 60 | -------------------------------------------------------------------------------- /pkg/scheduler/extender/README.md: -------------------------------------------------------------------------------- 1 | ### How to build and deploy scheduler extender 2 | 3 | 1. Build binary and push image (if you don't change extender' code you don't have to rebuild 4 | binary and image): 5 | ``` 6 | make build-extener 7 | make image-extender 8 | make push-extender 9 | ``` 10 | 11 | 2. On node where kubernetes scheduler pod is run create folder `/etc/kubernetes/scheduler` 12 | e.g. 13 | ``` 14 | ssh root@provo-goop mkdir -p /etc/kubernetes/scheduler 15 | ``` 16 | 3. Copy files `config.yaml` and `policy.yaml` from `pkg/scheduler` folder to the `/etc/kubernetes/scheduler` 17 | on the node. 18 | e.g. 19 | ``` 20 | scp policy.yaml config.yaml root@provo-goop:/etc/kubernetes/scheduler 21 | ``` 22 | 4. Install extender chart: 23 | ``` 24 | helm install se charts/scheduler-extender --set log.level=debug --set image.tag=`make version` 25 | ``` 26 | 5. Modify kube-scheduler manifest on the node. Config file is located in `/etc/kubernetes/manifests/kube-scheduler.yaml` 27 | 28 | - add next volumes in `.spec`: 29 | ``` 30 | - name: scheduler-config 31 | hostPath: 32 | path: /etc/kubernetes/scheduler/config.yaml 33 | type: File 34 | - name: scheduler-policy 35 | hostPath: 36 | path: /etc/kubernetes/scheduler/policy.yaml 37 | type: File 38 | ``` 39 | - add volume mounts in `.spec.containers[0].volumeMounts`: 40 | ``` 41 | - mountPath: /etc/kubernetes/scheduler/config.yaml 42 | name: scheduler-config 43 | readOnly: true 44 | - mountPath: /etc/kubernetes/scheduler/policy.yaml 45 | name: scheduler-policy 46 | readOnly: true 47 | ``` 48 | - add next params for kube-scheduler entrypoint in `.spec.containers[0].command`: 49 | ``` 50 | - --config=/etc/kubernetes/scheduler/config.yaml 51 | ``` 52 | After you save changes in `kube-scheduler.yaml` kubernetes will restart scheduler. 53 | 54 | 6. Apply some pod manifest 55 | 7. Run 56 | ``` 57 | kubectl logs -f -n %NAMESPACE_NAME% `kubectl get pods -n %NAMESPACE_NAME% --selector=app=csi-baremetal-se --no-headers | awk '{print $1}'` 58 | ``` 59 | and observe as scheduler extender works 60 | -------------------------------------------------------------------------------- /cmd/drivemgr/idracmgr/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "fmt" 22 | "time" 23 | 24 | dmsetup "github.com/dell/csi-baremetal/cmd/drivemgr" 25 | "github.com/dell/csi-baremetal/pkg/base" 26 | "github.com/dell/csi-baremetal/pkg/base/command" 27 | "github.com/dell/csi-baremetal/pkg/base/linuxutils/ipmi" 28 | "github.com/dell/csi-baremetal/pkg/base/logger" 29 | "github.com/dell/csi-baremetal/pkg/base/rpc" 30 | "github.com/dell/csi-baremetal/pkg/drivemgr/idracmgr" 31 | ) 32 | 33 | var ( 34 | endpoint = flag.String("drivemgrendpoint", base.DefaultDriveMgrEndpoint, "DriveManager Endpoint") 35 | logPath = flag.String("logpath", "", "log path for DriveManager") 36 | logLevel = flag.String("loglevel", logger.InfoLevel, 37 | fmt.Sprintf("Log level, support values are %s, %s, %s", logger.InfoLevel, logger.DebugLevel, logger.TraceLevel)) 38 | ) 39 | 40 | func main() { 41 | flag.Parse() 42 | 43 | logger, err := logger.InitLogger(*logPath, *logLevel) 44 | if err != nil { 45 | logger.Warnf("Can't set logger's output to %s. Using stdout instead.\n", *logPath) 46 | } 47 | 48 | // Server is insecure for now because credentials are nil 49 | serverRunner := rpc.NewServerRunner(nil, *endpoint, false, logger) 50 | 51 | e := command.NewExecutor(logger) 52 | 53 | ipmiTool := ipmi.NewIPMI(e) 54 | ip := ipmiTool.GetBmcIP() 55 | if ip == "" { 56 | logger.Fatal("IDRAC IP is not found") 57 | } 58 | 59 | driveMgr := idracmgr.NewIDRACManager(logger, 10*time.Second, "root", "passwd", ip) 60 | 61 | dmsetup.SetupAndRunDriveMgr(driveMgr, serverRunner, nil, logger) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/metrics/metrics_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/prometheus/client_golang/prometheus" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | func TestMetrics(t *testing.T) { 27 | vm := NewMetrics(prometheus.HistogramOpts{ 28 | Name: "partition_operations_duration", 29 | Help: "partition operations methods duration", 30 | }) 31 | rVM := vm.Collect() 32 | assert.Equal(t, vm.OperationsDuration, rVM) 33 | 34 | vm2 := NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 35 | Name: "test", 36 | Help: "test", 37 | }, "source", "pod_name") 38 | rVM2 := vm2.Collect() 39 | assert.Equal(t, vm2.GaugeVec, rVM2) 40 | 41 | assert.NotNil(t, vm2.EvaluateDurationWithLabel(prometheus.Labels{"pod_name": "test_pod"})) 42 | assert.NotNil(t, vm2.EvaluateDurationForMethod("testMethod", prometheus.Labels{"pod_name": "test_pod"})) 43 | assert.NotNil(t, vm2.EvaluateDurationForType("testType", prometheus.Labels{"pod_name": "test_pod"})) 44 | assert.NotPanics(t, func() { vm2.UpdateValue(10.0, prometheus.Labels{"pod_name": "test_pod"}, false, prometheus.Labels{}) }) 45 | assert.NotPanics(t, func() { vm2.Clear(prometheus.Labels{"pod_name": "test_pod"}) }) 46 | 47 | vm3 := NewCounterWithCustomLabels(prometheus.CounterOpts{ 48 | Name: "test counter", 49 | Help: "test counter", 50 | }, "source", "pod_name") 51 | rVM3 := vm3.Collect() 52 | assert.Equal(t, vm3.CounterVec, rVM3) 53 | assert.NotPanics(t, func() { vm3.Add(prometheus.Labels{"pod_name": "test_pod"}) }) 54 | assert.NotPanics(t, func() { vm3.Clear(prometheus.Labels{"pod_name": "test_pod"}) }) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/testutils/testutils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package testutils 18 | 19 | import ( 20 | "context" 21 | "time" 22 | 23 | accrd "github.com/dell/csi-baremetal/api/v1/availablecapacitycrd" 24 | "github.com/dell/csi-baremetal/api/v1/volumecrd" 25 | "github.com/dell/csi-baremetal/pkg/base" 26 | "github.com/dell/csi-baremetal/pkg/base/k8s" 27 | ) 28 | 29 | // VolumeReconcileImitation looking for volume CR with name volId and sets it's status to newStatus 30 | func VolumeReconcileImitation(k8sClient *k8s.KubeClient, volID string, namespace string, newStatus string) { 31 | for { 32 | <-time.After(200 * time.Millisecond) 33 | err := ReadVolumeAndChangeStatus(k8sClient, volID, namespace, newStatus) 34 | if err != nil { 35 | return 36 | } 37 | } 38 | } 39 | 40 | // AddAC create test AvailableCapacities 41 | func AddAC(k8sClient *k8s.KubeClient, acs ...*accrd.AvailableCapacity) error { 42 | for _, ac := range acs { 43 | if err := k8sClient.CreateCR(context.Background(), ac.Name, ac); err != nil { 44 | return err 45 | } 46 | } 47 | return nil 48 | } 49 | 50 | // ReadVolumeAndChangeStatus returns error if something went wrong 51 | func ReadVolumeAndChangeStatus(k8sClient *k8s.KubeClient, volumeID string, namespace string, newStatus string) error { 52 | v := &volumecrd.Volume{} 53 | ctx := context.WithValue(context.Background(), base.RequestUUID, volumeID) 54 | 55 | if err := k8sClient.ReadCR(ctx, volumeID, namespace, v); err != nil { 56 | return err 57 | } 58 | 59 | // change status 60 | v.Spec.CSIStatus = newStatus 61 | if err := k8sClient.UpdateCR(ctx, v); err != nil { 62 | return err 63 | } 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /pkg/metrics/common/ac_reservation.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | 22 | "github.com/dell/csi-baremetal/pkg/metrics" 23 | ) 24 | 25 | // ReservationDuration used to collect ReservationHelper methods durations 26 | var ReservationDuration = metrics.NewMetrics(prometheus.HistogramOpts{ 27 | Name: "ac_reservation_duration", 28 | Help: "AvailableCapacity reservation duration", 29 | Buckets: prometheus.ExponentialBuckets(0.005, 1.5, 10), 30 | }, "method") 31 | 32 | // DbgScheduleTotalTime used to collect schedule total time 33 | var DbgScheduleTotalTime = metrics.NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 34 | Name: "schedule_total_time", 35 | Help: "total schedule time cose for pod", 36 | }, "source", "pod_name") 37 | 38 | // DbgScheduleSinceLastTime used to collect schedule interval time 39 | var DbgScheduleSinceLastTime = metrics.NewMetricsWithCustomLabels(prometheus.GaugeOpts{ 40 | Name: "schedule_since_last_time", 41 | Help: "schedule interval since last time", 42 | }, "source", "pod_name") 43 | 44 | // DbgScheduleCounter used to collect schedule totol counts 45 | var DbgScheduleCounter = metrics.NewCounterWithCustomLabels(prometheus.CounterOpts{ 46 | Name: "schedule_counter", 47 | Help: "schedule counter for pod", 48 | }, "source", "pod_name") 49 | 50 | // nolint: gochecknoinits 51 | func init() { 52 | prometheus.MustRegister(ReservationDuration.Collect()) 53 | prometheus.MustRegister(DbgScheduleTotalTime.Collect()) 54 | prometheus.MustRegister(DbgScheduleSinceLastTime.Collect()) 55 | prometheus.MustRegister(DbgScheduleCounter.Collect()) 56 | } 57 | -------------------------------------------------------------------------------- /tests/e2e-test-framework/framework/const.py: -------------------------------------------------------------------------------- 1 | # common 2 | CR_GROUP = "csi-baremetal.dell.com" 3 | CR_VERSION = "v1" 4 | 5 | # storage classes 6 | HDD_SC = "csi-baremetal-sc-hdd" 7 | SSD_SC = "csi-baremetal-sc-ssd" 8 | HDDLVG_SC = "csi-baremetal-sc-hddlvg" 9 | SSDLVG_SC = "csi-baremetal-sc-ssdlvg" 10 | SYSLVG_SC = "csi-baremetal-sc-syslvg" 11 | NVME_SC = "csi-baremetal-sc-nvme-raw-part" 12 | NVMELVG_SC = "csi-baremetal-sc-nvmelvg" 13 | 14 | # storage types 15 | STORAGE_TYPE_SSD = "SSD" 16 | STORAGE_TYPE_HDD = "HDD" 17 | STORAGE_TYPE_NVME = "NVME" 18 | STORAGE_TYPE_HDDLVG = "HDDLVG" 19 | STORAGE_TYPE_SSDLVG = "SSDLVG" 20 | STORAGE_TYPE_SYSLVG = "SYSLVG" 21 | STORAGE_TYPE_NVMELVG = "NVMELVG" 22 | 23 | # usages 24 | USAGE_IN_USE = "IN_USE" 25 | USAGE_RELEASING = "RELEASING" 26 | USAGE_RELEASED = "RELEASED" 27 | USAGE_REMOVING = "REMOVING" 28 | USAGE_REMOVED = "REMOVED" 29 | USAGE_RAILED = "FAILED" 30 | 31 | # statuses 32 | STATUS_ONLINE = "ONLINE" 33 | STATUS_OFFLINE = "OFFLINE" 34 | STATUS_OPERATIVE = "OPERATIVE" 35 | 36 | # annotation keys 37 | DRIVE_HEALTH_ANNOTATION = "health" 38 | VOLUME_RELEASE_ANNOTATION = "release" 39 | FAKE_ATTACH_PVC_ANNOTATION_KEY = "pv.attach.kubernetes.io/ignore-if-inaccessible" 40 | 41 | # annotation values 42 | DRIVE_HEALTH_BAD_ANNOTATION = "BAD" 43 | VOLUME_RELEASE_DONE_VALUE = "done" 44 | FAKE_ATTACH_PVC_ANNOTATION_VALUE = "yes" 45 | 46 | # health 47 | HEALTH_GOOD = "GOOD" 48 | HEALTH_BAD = "BAD" 49 | 50 | # fake attach events 51 | FAKE_ATTACH_INVOLVED = "FakeAttachInvolved" 52 | FAKE_ATTACH_CLEARED = "FakeAttachCleared" 53 | DRIVE_HEALTH_FAILURE = "DriveHealthFailure" 54 | DRIVE_READY_FOR_REMOVAL = "DriveReadyForRemoval" 55 | VOLUME_BAD_HEALTH = "VolumeBadHealth" 56 | DRIVE_READY_FOR_PHYSICAL_REMOVAL = "DriveReadyForPhysicalRemoval" 57 | DRIVE_SUCCESSFULLY_REMOVED = "DriveSuccessfullyRemoved" 58 | 59 | # drive events 60 | DRIVE_HEALTH_FAILURE_EVENT = "DriveHealthFailure" 61 | DRIVE_READY_FOR_PHYSICAL_REMOVAL_EVENT = "DriveReadyForPhysicalRemoval" 62 | DRIVE_SUCCESSFULLY_REMOVED_EVENT = "DriveSuccessfullyRemoved" 63 | 64 | # plurals 65 | DRIVES_PLURAL = "drives" 66 | AC_PLURAL = "availablecapacities" 67 | ACR_PLURAL = "availablecapacityreservations" 68 | LVG_PLURAL = "logicalvolumegroups" 69 | VOLUMES_PLURAL = "volumes" 70 | 71 | # led 72 | LED_STATE = "1,2" 73 | -------------------------------------------------------------------------------- /docs/volume-statuses.md: -------------------------------------------------------------------------------- 1 | # Volume statuses 2 | 3 | Last updated: 01.02.22 4 | 5 | ## Abstract 6 | 7 | Every object can be created and have many states during its life. 8 | Transfer from one state to another should be described by final state machine (FSM). 9 | This document describes implemented volume statuses which should provide CSI workflow. 10 | 11 | ## Background 12 | 13 | CSI specification doesn't make restrictions for volume statuses. 14 | It only suggests the lifecycle of a volume, but implementation of the all RPC-es has to be mandatory. 15 | 16 | ## Implementation details 17 | 18 | It's been proposed to use special field of volume structure where volume status can be stored. 19 | That field is called "CSIStatus": 20 | ```go 21 | type Volume struct { 22 | Id string 23 | Owners []string 24 | ... 25 | CSIStatus string 26 | ... 27 | ``` 28 | Now it has the next volume statuses: 29 | * Creating; 30 | * Created; 31 | * VolumeReady; 32 | * Published; 33 | * Removing; 34 | * Removed; 35 | * Failed; 36 | * Resizing; 37 | * Resized. 38 | 39 | FSM of volume statuses is shown below: 40 | 41 | ![Screenshot](images/volume_csi.png) 42 | 43 | Statuses transition list: 44 | 1. Volume CR has been created as the result of "CreateVolume" RPC call. 45 | 2. Volume has been created as the result of routine call from Reconcile of Volume Manager. 46 | 3. Something went wrong during volume creation. 47 | 4. "NodeStageVolume" RPC call has been handled successfully. 48 | 5. "NodeUnstageVolume" RPC call has been handled successfully. 49 | 6. "NodePublishVolume" RPC call has been handled successfully. 50 | 7. "NodePublishVolume" RPC call has been failed. 51 | 8. "NodeUnpublishVolume" RPC call has been handled successfully. 52 | 9. "DeleteVolume" RPC call has been handled successfully. 53 | 10. Volume has been deleted as the result of routine call from Reconcile of Volume Manager. 54 | 11. Something went wrong during deletion of a volume. 55 | 12. Volume CR has been removed as the end of routine of "DeleteVolume" RPC call. 56 | 13. "ControllerExpandVolume" has been called. 57 | 14. Logical volume has been expanded successfully. 58 | 15. Something went wrong during logical volume expansion. 59 | 16. Unmount volume has failed in handler of "NodeUnpublishVolume" RPC call. -------------------------------------------------------------------------------- /pkg/mocks/provisioners/provisioner.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package provisioners 18 | 19 | import ( 20 | "github.com/stretchr/testify/mock" 21 | 22 | api "github.com/dell/csi-baremetal/api/generated/v1" 23 | ) 24 | 25 | // MockProvisioner is a mock implementation of Provisioner interface 26 | type MockProvisioner struct { 27 | mock.Mock 28 | } 29 | 30 | // GetMockProvisionerSuccess retruns MockProvisioner that perform each method without any error 31 | // everytimePath is a path that will be returning for each "GetVolumePath" call 32 | func GetMockProvisionerSuccess(everytimePath string) *MockProvisioner { 33 | mp := MockProvisioner{} 34 | mp.On("PrepareVolume", mock.Anything).Return(nil) 35 | mp.On("ReleaseVolume", mock.Anything, mock.Anything).Return(nil) 36 | mp.On("GetVolumePath", mock.Anything).Return(everytimePath, nil) 37 | 38 | return &mp 39 | } 40 | 41 | // PrepareVolume is the mock implementation of PrepareVolume method from Provisioner interface 42 | func (m *MockProvisioner) PrepareVolume(volume *api.Volume) error { 43 | args := m.Mock.Called(volume) 44 | 45 | return args.Error(0) 46 | } 47 | 48 | // ReleaseVolume is the mock implementation of ReleaseVolume method from Provisioner interface 49 | func (m *MockProvisioner) ReleaseVolume(volume *api.Volume, drive *api.Drive) error { 50 | args := m.Mock.Called(volume, drive) 51 | 52 | return args.Error(0) 53 | } 54 | 55 | // GetVolumePath is the mock implementation of GetVolumePath method from Provisioner interface 56 | func (m *MockProvisioner) GetVolumePath(volume *api.Volume) (string, error) { 57 | args := m.Mock.Called(volume) 58 | 59 | return args.String(0), args.Error(1) 60 | } 61 | -------------------------------------------------------------------------------- /tests/app/nginx-lvg.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: web 5 | spec: 6 | serviceName: "nginx" 7 | replicas: 4 8 | podManagementPolicy: Parallel 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | affinity: 18 | podAntiAffinity: 19 | requiredDuringSchedulingIgnoredDuringExecution: 20 | - labelSelector: 21 | matchExpressions: 22 | - key: app 23 | operator: In 24 | values: 25 | - nginx 26 | topologyKey: "kubernetes.io/hostname" 27 | containers: 28 | - name: nginx 29 | image: k8s.gcr.io/nginx-slim:0.8 30 | ports: 31 | - containerPort: 80 32 | name: web 33 | volumeMounts: 34 | - name: www 35 | mountPath: /usr/share/nginx/html 36 | - name: data 37 | mountPath: /usr/share/nginx/data 38 | - name: logs 39 | mountPath: /usr/share/nginx/logs 40 | - name: logs-2 41 | mountPath: /usr/share/nginx/logs-2 42 | - name: logs-3 43 | mountPath: /usr/share/nginx/logs-3 44 | volumeClaimTemplates: 45 | - metadata: 46 | name: www 47 | spec: 48 | storageClassName: csi-baremetal-sc-hddlvg 49 | accessModes: [ "ReadWriteOnce" ] 50 | resources: 51 | requests: 52 | storage: 1G 53 | - metadata: 54 | name: data 55 | spec: 56 | storageClassName: csi-baremetal-sc-hddlvg 57 | accessModes: [ "ReadWriteOnce" ] 58 | resources: 59 | requests: 60 | storage: 1G 61 | - metadata: 62 | name: logs 63 | spec: 64 | storageClassName: csi-baremetal-sc-hddlvg 65 | accessModes: [ "ReadWriteOnce" ] 66 | resources: 67 | requests: 68 | storage: 1G 69 | - metadata: 70 | name: logs-2 71 | spec: 72 | storageClassName: csi-baremetal-sc-hddlvg 73 | accessModes: [ "ReadWriteOnce" ] 74 | resources: 75 | requests: 76 | storage: 1G 77 | - metadata: 78 | name: logs-3 79 | spec: 80 | storageClassName: csi-baremetal-sc-hddlvg 81 | accessModes: [ "ReadWriteOnce" ] 82 | resources: 83 | requests: 84 | storage: 1G 85 | -------------------------------------------------------------------------------- /pkg/node/liveness_check_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2020 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package node 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | "github.com/sirupsen/logrus" 24 | "github.com/stretchr/testify/assert" 25 | ) 26 | 27 | func TestNodeLivenessCheck(t *testing.T) { 28 | 29 | logger := logrus.New() 30 | logger.SetLevel(logrus.DebugLevel) 31 | 32 | t.Run("OK by default", func(t *testing.T) { 33 | check := NewLivenessCheckHelper(logger, nil, nil) 34 | assert.True(t, check.Check()) 35 | }) 36 | 37 | t.Run("Marked as failed, ttl not expired", func(t *testing.T) { 38 | check := NewLivenessCheckHelper(logger, nil, nil) 39 | check.Fail() 40 | assert.True(t, check.Check()) 41 | }) 42 | 43 | t.Run("Marked as failed, ttl expired", func(t *testing.T) { 44 | ttl := time.Millisecond * 10 45 | check := NewLivenessCheckHelper(logger, &ttl, nil) 46 | check.Fail() 47 | time.Sleep(ttl) 48 | assert.False(t, check.Check()) 49 | }) 50 | 51 | t.Run("Marked OK, no updates for a long time", func(t *testing.T) { 52 | ttl := time.Millisecond * 10 53 | check := NewLivenessCheckHelper(logger, &ttl, nil) 54 | time.Sleep(ttl) 55 | assert.True(t, check.Check()) 56 | }) 57 | t.Run("Marked OK, no updates for a long time, timeout expired", func(t *testing.T) { 58 | ttl := time.Millisecond * 10 59 | timeout := time.Millisecond * 20 60 | check := NewLivenessCheckHelper(logger, &ttl, &timeout) 61 | time.Sleep(timeout) 62 | assert.False(t, check.Check()) 63 | }) 64 | 65 | t.Run("Recover", func(t *testing.T) { 66 | ttl := time.Millisecond * 10 67 | check := NewLivenessCheckHelper(logger, &ttl, nil) 68 | check.Fail() 69 | time.Sleep(ttl) 70 | assert.False(t, check.Check()) 71 | check.OK() 72 | assert.True(t, check.Check()) 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /docs/block-mode.md: -------------------------------------------------------------------------------- 1 | # Block mode usage 2 | 3 | ### Default block mode 4 | 5 | 1. Set VolumeMode on PVC 6 | 7 | ``` 8 | volumeClaimTemplates: 9 | - metadata: 10 | name: data 11 | spec: 12 | storageClassName: csi-baremetal-sc 13 | accessModes: [ "ReadWriteOnce" ] 14 | volumeMode: Block 15 | ``` 16 | 17 | 2. Use volumeDevices instead of volumeMounts 18 | 19 | ``` 20 | volumeDevices: 21 | - name: data 22 | devicePath: /data 23 | ``` 24 | 25 | Example: 26 | 27 | ``` 28 | root@vm-037:~# lsblk /dev/sdb 29 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT 30 | sdb 8:16 0 10G 0 disk 31 | ``` 32 | 33 | ### LVG block mode 34 | 35 | All LVG storage classes allows creating Block Volumes too. In this case device will be LVG partition. 36 | 37 | Example: 38 | 39 | ``` 40 | root@vm-037:~# lsblk /dev/sdd 41 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT 42 | sdd 8:48 0 10G 0 disk 43 | ├─fe44c368--a4a4--4424--b113--db3526d055e4-pvc--3a87a913--2d8e--4321--b954--fd24cd8b94a0 253:3 0 20M 0 lvm 44 | ├─fe44c368--a4a4--4424--b113--db3526d055e4-pvc--f0e44041--877f--4427--bbb7--7bcae3bf4b13 253:4 0 20M 0 lvm 45 | └─fe44c368--a4a4--4424--b113--db3526d055e4-pvc--03f5ad88--5332--4cba--8bc0--3534e360ae77 253:5 0 20M 0 lvm 46 | ``` 47 | 48 | ### Raw Part Mode 49 | 50 | If it is necessary, CSI Baremetal can create partition for drive and set partition as volume device. 51 | 52 | 1. Create new storage class and add `isPartitioned=true` parameter 53 | 54 | ``` 55 | apiVersion: storage.k8s.io/v1 56 | kind: StorageClass 57 | metadata: 58 | name: csi-baremetal-sc-raw-part 59 | parameters: 60 | fsType: xfs 61 | storageType: ANY 62 | isPartitioned: true 63 | provisioner: csi-baremetal 64 | reclaimPolicy: Delete 65 | volumeBindingMode: WaitForFirstConsumer 66 | ``` 67 | 68 | Note! KubeAPI forbids to edit existing storage classes 69 | ``` 70 | The StorageClass "csi-baremetal-sc" is invalid: parameters: Forbidden: updates to parameters are forbidden. 71 | ``` 72 | 73 | 2. Follow `Default block mode` 74 | 75 | Example: 76 | 77 | ``` 78 | root@vm-037:~# lsblk /dev/sdb 79 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT 80 | sdb 8:16 0 10G 0 disk 81 | └─sdb1 8:17 0 10G 0 part 82 | ``` 83 | -------------------------------------------------------------------------------- /pkg/base/util/parser.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 Dell Inc. or its subsidiaries. All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "regexp" 21 | "strings" 22 | 23 | errTypes "github.com/dell/csi-baremetal/pkg/base/error" 24 | ) 25 | 26 | // GetOSNameAndVersion receives string with the OS information in th following format: 27 | // " ". For example, "Ubuntu 18.04.4 LTS" 28 | // returns os name with the lower case and major and minor version. For example, "ubuntu", "18.04" 29 | func GetOSNameAndVersion(osInfo string) (name, version string, err error) { 30 | // check input parameter 31 | if len(osInfo) == 0 { 32 | return "", "", errTypes.ErrorEmptyParameter 33 | } 34 | 35 | // extract OS name 36 | name = regexp.MustCompile(`^[A-Za-z]+`).FindString(osInfo) 37 | if len(name) == 0 { 38 | return "", "", errTypes.ErrorFailedParsing 39 | } 40 | 41 | // extract OS version 42 | version = regexp.MustCompile(`[0-9]+\.[0-9]+`).FindString(osInfo) 43 | if len(version) == 0 { 44 | return "", "", errTypes.ErrorFailedParsing 45 | } 46 | 47 | return strings.ToLower(name), version, nil 48 | } 49 | 50 | // GetKernelVersion receives string with the kernel version information in the following format: 51 | // "X.Y.Z--". For example, "5.4.0-66-generic" 52 | // returns kernel version - major and minor. For example, "5.4" 53 | func GetKernelVersion(kernelVersion string) (version string, err error) { 54 | // check input parameter 55 | if len(kernelVersion) == 0 { 56 | return "", errTypes.ErrorEmptyParameter 57 | } 58 | 59 | // extract kernel version - x.y.z 60 | version = regexp.MustCompile(`^[0-9]+\.[0-9]+`).FindString(kernelVersion) 61 | if len(version) == 0 { 62 | return "", errTypes.ErrorFailedParsing 63 | } 64 | 65 | return version, nil 66 | } 67 | --------------------------------------------------------------------------------