{"id":19675078,"url":"https://github.com/d2iq-archive/csilvm","last_synced_at":"2025-04-29T02:30:33.134Z","repository":{"id":57492787,"uuid":"92304883","full_name":"d2iq-archive/csilvm","owner":"d2iq-archive","description":"A LVM2 CSI plugin","archived":true,"fork":false,"pushed_at":"2020-03-21T16:59:42.000Z","size":20454,"stargazers_count":54,"open_issues_count":1,"forks_count":14,"subscribers_count":90,"default_branch":"master","last_synced_at":"2025-02-20T18:23:45.778Z","etag":null,"topics":["container","csi","dcos","dcos-compute-guild","lvm","lvm2","storage"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d2iq-archive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-24T14:59:42.000Z","updated_at":"2024-12-04T11:43:01.000Z","dependencies_parsed_at":"2022-08-28T13:41:43.490Z","dependency_job_id":null,"html_url":"https://github.com/d2iq-archive/csilvm","commit_stats":null,"previous_names":["d2iq-archive/csilvm","mesosphere/csilvm"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d2iq-archive%2Fcsilvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d2iq-archive%2Fcsilvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d2iq-archive%2Fcsilvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d2iq-archive%2Fcsilvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d2iq-archive","download_url":"https://codeload.github.com/d2iq-archive/csilvm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251420867,"owners_count":21586694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["container","csi","dcos","dcos-compute-guild","lvm","lvm2","storage"],"created_at":"2024-11-11T17:21:12.303Z","updated_at":"2025-04-29T02:30:28.126Z","avatar_url":"https://github.com/d2iq-archive.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CSI plugin for LVM2 [![Issues](https://img.shields.io/badge/Issues-JIRA-ff69b4.svg?style=flat)](https://jira.mesosphere.com/issues/?jql=project%20%3D%20DCOS_OSS%20and%20component%20%3D%20csilvm%20and%20status%20not%20in%20(Resolved%2C%20Closed)) [![Build Status](https://jenkins.mesosphere.com/service/jenkins/buildStatus/icon?job=public-csilvm-pipeline/csilvm-pipelines/master)](https://jenkins.mesosphere.com/service/jenkins/job/public-csilvm-pipeline/job/csilvm-pipelines/job/master/)\n\nThis is a [container storage interface (CSI)](https://github.com/container-storage-interface/spec) plugin for LVM2.\nIt exposes a CSI-compliant API to a LVM2 volume group (VG).\nThe names of the volume group (VG) and the physical volumes (PVs) it consists of are passed to the plugin at launch time as command-line parameters.\nCSI volumes map to LVM2 logical volumes (LVs).\n\n## Getting Started\n\n\n### Setting up your local environment\n\nYou need a properly configured Go installation.\nSee the `Dockerfile` for the version of Go used in CI.\nNewer versions of Go should work.\n\nYou can `go get` the source code from GitHub.\n\n```bash\ngo get -v github.com/mesosphere/csilvm\n```\n\nIf you want to work on the code I suggest the following workflow.\n\n1. Fork the repository on GitHub.\n1. `mkdir -p $GOPATH/src/github.com/mesosphere`\n1. `cd $GOPATH/src/github.com/mesosphere`\n1. `git clone \u003cyour-fork\u003e csilvm`\n1. `cd csilvm`\n1. `git remote add upstream https://github.com/mesosphere/csilvm.git`\n1. `git checkout master`\n1. `git branch --set-upstream-to=upstream/master`\n\nYou now have the source code cloned locally and the git `origin` set to your fork.\n\nTo develop your new feature you can create a new branch and push it to your fork.\n\n1. `git checkout master`\n1. `git pull upstream master` (to make sure you're up-to-date)\n1. `git checkout -b my-feature-branch`\n1. Make changes to `./pkg/lvm`.\n1. `git commit -a -m 'lvm: refactored CreateLogicalVolume tests'`\n1. `git push origin my-feature-branch`\n1. Create a GitHub PR from your branch against `mesosphere/csilvm:master`.\n\n\n### Building the binary\n\nYou need a properly configured Go installation.\n\nThe simplest option is to `go get` the project source from GitHub.\n\n```bash\ngo get -v github.com/mesosphere/csilvm/cmd/csilvm\n```\n\n\n### Running the tests\n\n\nIn order to run the tests you need\n* a modern Linux distribution. (Fedora 27)\n* sudo rights. This is necessary to create loop devices and (un)mount volumes.\n* docker installed. (docker-ce-18.03.1.ce-1.fc27.x86_64.rpm package)\n* the `raid1` and `dm_raid` kernel modules must be loaded. If it isn't, run `modprobe raid1 dm_raid` as root.\n\nThen run\n\n```bash\nmake sudo-test\n```\n\nWhile developing in only one package it is simpler and faster to run only certain tests.\n\nFor example, if you're adding new functionality to the `./pkg/lvm` package you can do\n:\n```bash\ncd ./pkg/lvm\ngo test -c -i . \u0026\u0026 sudo ./lvm.test -test.v -test.run=TestMyNewFeature\n```\n\n\n## How does this plugin map to the CSI specification?\n\nThis plugin is a CSI-compliant wrapper around the normal `lvm2` command-line utilities.\nThese include `pvcreate`, `vgcreate`, `lvcreate`, etc.\n\nThis plugin implements the \"headless, unified plugin\" design given in the CSI specification.\n\nIn particular, the CSI specification lists the architecture as follows:\n\n```\n                            CO \"Node\" Host(s)\n+-------------------------------------------+\n|                                           |\n|  +------------+           +------------+  |\n|  |     CO     |   gRPC    | Controller |  |\n|  |            +-----------\u003e    Node    |  |\n|  +------------+           |   Plugin   |  |\n|                           +------------+  |\n|                                           |\n+-------------------------------------------+\n\nFigure 3: Headless Plugin deployment, only the CO Node hosts run\nPlugins. A unified Plugin component supplies both the Controller\nService and Node Service.\n```\n\nEvery instance of this plugin controls a single LVM2 volume group (VG).\nEvery CSI volume corresponds to a LVM2 logical volume (LV).\nThe CSI RPCs map to command-line utility invocations on LVM2 physical volumes (PV), a LVM2 volume group (VG) or LVM2 logical volumes (LV).\nFor the the exact command-line invocations read the source code, starting at https://github.com/mesosphere/csilvm/blob/master/pkg/csilvm/server.go.\n\n\n## Project structure\n\nThis project is split into `./pkg` and `./cmd` directories.\n\nThe `./pkg` directory contains logic that may be used from unit tests.\n\nThe `./cmd` directory contains commands that interface between the environment (e.g., parsing command-line options, reading environment variables, etc.) and the logic contained in the `./pkg` directory.\n\nThe `./pkg` directory is split into the `./pkg/lvm` and `./pkg/csilvm` packages.\n\nThe `./pkg/lvm` package provides a Go wrapper around LVM2 command-line utilities and actions.\n\nThe `./pkg/csilvm` package includes all the CSI-related logic and translates CSI RPCs to `./pkg/lvm` function calls.\n\nThe `./pkg/csilvm/server.go` file should serve as your entrypoint when reading the code as it includes all the CSI RPC endpoints.\n\n\n## Deployment\n\nThe plugin builds to a single executable binary called `csilvm`.\nThis binary should be copied to the node.\nIt is expected that the Plugin Supervisor will launch the binary using the appropriate command-line flags.\n\n\n### Usage\n\n```\n$ ./csilvm --help\nUsage of ./csilvm:\n  -default-fs string\n    \tThe default filesystem to format new volumes with (default \"xfs\")\n  -default-volume-size uint\n    \tThe default volume size in bytes (default 10737418240)\n  -devices string\n    \tA comma-seperated list of devices in the volume group\n  -lockfile string\n    \tThe path to the lock file used to prevent concurrent lvm invocation by multiple csilvm instances\n  -node-id string\n    \tThe node ID reported via the CSI Node gRPC service\n  -probe-module value\n    \tProbe checks that the kernel module is loaded\n  -remove-volume-group\n    \tIf set, the volume group will be removed when ProbeNode is called.\n  -request-limit int\n    \tLimits backlog of pending requests. (default 10)\n  -statsd-format string\n    \tThe statsd format to use (one of: classic, datadog) (default \"datadog\")\n  -statsd-max-udp-size int\n    \tThe size to buffer before transmitting a statsd UDP packet (default 1432)\n  -statsd-udp-host-env-var string\n    \tThe name of the environment variable containing the host where a statsd service is listening for stats over UDP\n  -statsd-udp-port-env-var string\n    \tThe name of the environment variable containing the port where a statsd service is listening for stats over UDP\n  -tag value\n    \tValue to tag the volume group with (can be given multiple times)\n  -unix-addr string\n    \tThe path to the listening unix socket file\n  -unix-addr-env string\n    \tAn optional environment variable from which to read the unix-addr\n  -volume-group string\n    \tThe name of the volume group to manage\n```\n\n\n### Listening socket\n\nThe plugin listens on a unix socket.\nThe unix socket path can be specified using the `-unix-addr=\u003cpath\u003e` command-line option.\nThe unix socket path can also be specified using the `-unix-addr-env=\u003cenv-var-name\u003e` option in which case the path will be read from the environment variable of the given name.\nIt is expected that the CO will connect to the plugin through the unix socket and will subsequently communicate with it in accordance with the CSI specification.\n\n\n### Locking\n\nAny command-line invocations executed by the `csilvm` process first acquires a\nlock on a lockfile. The path to the lockfile can be overridden using the\n`-lockfile=` option or the `CSILVM_LOCKFILE_PATH` environment variable. The\nlocking behaviour can be disabled by setting the `-lockfile=` option to the\nempty string. The purpose of locking around command-line invocations is to\nprevent multiple `csilvm` processes from executing concurrent `lvm2` commands.\nThis works around deadlocks in lvm2. For example,\nhttps://jira.mesosphere.com/browse/DCOS_OSS-5434 and\nhttps://github.com/lvmteam/lvm2/issues/23.\n\nBy default the lock file is created at `/run/csilvm.lock` so it is assumed that\nthe `/run` directory exists and is writable by the `csilvm` process.\n\n\n### Logging\n\nThe plugin emits fairly verbose logs to `STDERR`.\nThis is not currently configurable.\n\n\n### Metrics\n\nThe plugin emits metrics in StatsD format. By default, it uses the\n[DogStatsD](http://docs.datadoghq.com/guides/dogstatsd/) format which augments\nthe standard StatsD format with tags.\n\nThe format of the StatsD metrics can be set using the `-statsd-format` flag. It\ndefaults to `datadog` but can be set to `classic` in order to emit metrics in\nstandard StatsD format.\n\nMetrics are emitted over UDP. The StatsD server's host and port are read from\nenvironment variables. The names of the environment variables that specify the\nStatsD server's host and port can be set using `-statsd-udp-host-env-var` and\n`-statsd-udp-port-env-var` flags, respectively.\n\nMetrics are emitted with the prefix `csilvm`.\n\nThe following metrics are reported:\n\n- csilvm_uptime: the uptime (in seconds) of the process\n- csilvm_requests: number of requests served\n\ttags:\n\t  `result_type`: one of `success`, `error`\n\t  `method`: the RPC name, e.g., `/csi.v0.Controller/CreateVolume`\n- csilvm_requests_latency_(stddev,mean,lower,count,sum,upper): the request duration (in milliseconds)\n\ttags:\n\t  `method`: the RPC name, e.g., `/csi.v0.Controller/CreateVolume`\n- csilvm_volumes: the number of active logical volumes\n- csilvm_bytes_total: the total number of bytes in the volume group\n- csilvm_bytes_free: the number of bytes available for creating a linear logical volume\n- csilvm_bytes_used: the number of bytes allocated to active logical volumes\n- csilvm_pvs: the number of physical volumes in the volume group\n- csilvm_missing_pvs: the number of pvs given on the command-line but are not found in the volume group\n- csilvm_unexpected_pvs: the number of pvs not given on the command-line but are found in the volume group\n- csilvm_lookup_pv_errs: the number of errors encountered while looking for pvs specified on the command-line\n\nFurthermore, all metrics are tagged with `volume-group` set to the\n`-volume-group` command-line option.\n\n### Runtime dependencies\n\nThe following command-line utilties must be present in the `PATH`:\n\n* the various lvm2 cli utilities (`pvscan`, `vgcreate`, etc.)\n* `udevadm`\n* `blkid`\n* `mkfs`\n* `file`\n* the filesystem listed as `-default-fs` (defaults to: `xfs`)\n\nFor RAID1 support the `raid1` and `dm_raid` kernel modules must be available.\n\nThis plugin's tests are run in a centos 7.3.1611 container with lvm2-2.02.183 installed from source.\nIt should work with newer versions of lvm2 that are backwards-compatible in their command-line interface.\nIt may work with older versions.\n\n\n### Startup\n\nWhen the plugin starts it performs checks and initialization.\n\nNote that, as with all software, the source of truth is the code.\nThe initialization logic lives in the `(*Server).Setup()` function in `./pkg/csilvm/server.go`.\n\nIf the `-remove-volume-group` flag is provided the volume group will be removed during `Setup`.\nIf at that point the volume group is not found, it is assumed that it was successfully removed and `Setup` succeeds.\nThe PVs are not removed or cleared.\n\nIf the `-remove-volume-group` flag is NOT provided the volume group is looked up.\nIf the volume group already exists, the plugin checks whether the PVs that constitute that VG matches the list of devices provided on the command-line in the `-devices=\u003cdev1,dev2,...\u003e` flag.\nNext it checks whether the volume group tags match the `-tag` list provided on the command-line.\n\nIf the volume group does not already exist, the plugin looks up the provided list of PVs corresponding to the `-devices=\u003cdev1,dev2,...\u003e` provided on the command-line.\nFor each, if it isn't already a LVM2 PV, it zeroes the partition table and runs `pvcreate` to initialize it.\nOnce all the PVs exist, the new volume group is created consisting of those PVs and tagged with the provided `-tag` list.\n\n\n### Notes\n\n\n#### Locking\n\nThe plugin is completely stateless and performs no locking around operations.\nInstead, it relies on LVM2 to lock around operations that are not reentrant.\n\n#### Logical volume naming\n\nThe volume group name is specified at startup through the `-volume-group` argument.\n\nLogical volume names are derived from randomly generated, base36-encoded numbers and are prefixed with `csilv`, for example: `csilv9T8s7d3`.\n\nThe CO-specified volume name is captured in a LV tag conforming to one of the following formats:\n\n* `VN.\u003cCO-specified-name\u003e`, if the CO-specified name contains *only* characters safe for LVM tags (`A-Z a-z 0-9 + _ . -`).\n* `VN+\u003cbase64-rawurlencode(CO-specified-name)\u003e`, otherwise. Encoding is performed without padding.\n\nExamples:\n\n* If the CO-specified volume name is `test-volume`, then the generated LV tag is `VN.test-volume`.\n* If the CO-specified volume name is `hello volume`, then the generated LV tag is `VN+aGVsbG8gdm9sdW1l`.\n\n#### Logical volume sizes\n\nThe `CreateVolume` RPC will attempt to allocate a volume size that both:\n\n* satisfies the requested capacity with the range limits given, and;\n* aligns with an LVM extent boundary (LVM default is 4MiB)\n\nThe plugin will choose the smallest size within the requested capacity range that aligns to an extent boundary.\nIf the plugin cannot align on an extent boundary within the requested capacity range, then the `CreateVolume` RPC will return an error.\nFor example, if the requested capacity is *exactly* 25MiB (RequiredBytes = LimitBytes = 25MiB) then the RPC will fail because 25MiB does not align to the default 4MiB extent boundary.\n\n#### SINGLE_NODE_READER_ONLY\n\nIt is not possible to bind mount a device as 'ro' and thereby prevent write access to it.\n\nAs such, this plugin does not support the `SINGLE_NODE_READER_ONLY` access mode for a\nvolume of access type `BLOCK_DEVICE`.\n\n# Issues\n\nThis project uses JIRA instead of GitHub issues to track bugs and feature requests.\nYou may review the [currently open issues](https://jira.mesosphere.com/issues/?jql=project%20%3D%20DCOS_OSS%20and%20component%20%3D%20csilvm%20and%20status%20not%20in%20(Resolved%2C%20Closed)).\nYou may also create a new [bug](https://jira.mesosphere.com/secure/CreateIssueDetails!init.jspa?pid=14105\u0026issuetype=1\u0026components=20732\u0026customfield_12300=3\u0026summary=CSILVM%3a+bug+summary+goes+here\u0026description=Environment%3a%0d%0dWhat+you+attempted+to+do%3a%0d%0dThe+result+you+expected%3a%0d%0dThe+result+you+saw+instead%3a%0d\u0026priority=3) or a new [task](https://jira.mesosphere.com/secure/CreateIssueDetails!init.jspa?pid=14105\u0026issuetype=3\u0026components=20732\u0026customfield_12300=3\u0026summary=CSILVM%3a+task+summary+goes+here\u0026priority=3).\n\n\n# Authors\n\n* @gpaul\n* @jdef\n* @jieyu\n\n\n# License\n\nThis project is licensed under the Apache 2.0 License - see the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd2iq-archive%2Fcsilvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd2iq-archive%2Fcsilvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd2iq-archive%2Fcsilvm/lists"}