├── .editorconfig ├── .envrc ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── ci.yml │ └── stale.yml ├── .gitignore ├── .markdownlint-cli2.yaml ├── .mdlrc ├── .overcommit.yml ├── .rubocop.yml ├── .rubocop_todo.yml ├── .vscode └── extensions.json ├── .yamllint ├── Berksfile ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dangerfile ├── LICENSE ├── README.md ├── TESTING.md ├── attributes └── default.rb ├── chefignore ├── documentation ├── .gitkeep ├── lvm_logical_volume.md ├── lvm_physical_volume.md ├── lvm_thin_pool.md ├── lvm_thin_pool_meta_data.md ├── lvm_thin_volume.md └── lvm_volume_group.md ├── kitchen.dokken.yml ├── kitchen.exec.yml ├── kitchen.global.yml ├── kitchen.yml ├── libraries ├── base_resource_logical_volume.rb ├── lvm.rb ├── provider_lvm_logical_volume.rb ├── provider_lvm_thin_pool.rb ├── provider_lvm_thin_pool_meta_data.rb ├── provider_lvm_thin_volume.rb ├── provider_lvm_volume_group.rb ├── resource_lvm_logical_volume.rb ├── resource_lvm_thin_pool.rb ├── resource_lvm_thin_pool_meta_data.rb ├── resource_lvm_thin_volume.rb └── resource_lvm_volume_group.rb ├── metadata.rb ├── recipes └── default.rb ├── renovate.json ├── resources └── physical_volume.rb ├── spec ├── default_spec.rb ├── lvm_test │ ├── create_spec.rb │ ├── create_thin_spec.rb │ ├── remove_spec.rb │ ├── resize_spec.rb │ ├── resize_thin_pool_meta_data_spec.rb │ └── resize_thin_spec.rb ├── notify_spec.rb └── spec_helper.rb └── test ├── fixtures └── cookbooks │ └── test │ ├── metadata.rb │ ├── recipes │ ├── create.rb │ ├── create_thin.rb │ ├── remove.rb │ ├── resize.rb │ ├── resize_thin.rb │ ├── resize_thin_pool_meta_data.rb │ └── test_notify.rb │ └── resources │ └── loop_devices.rb └── integration ├── create └── create_spec.rb ├── create_thin └── create_thin_spec.rb ├── remove └── remove_spec.rb ├── resize └── resize_spec.rb ├── resize_thin └── resize_thin_spec.rb └── resize_thin_pool_meta_data └── resize_thin_pool_meta_data_spec.rb /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root=true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | 11 | # 2 space indentation 12 | indent_style = space 13 | indent_size = 2 14 | 15 | # Avoid issues parsing cookbook files later 16 | charset = utf-8 17 | 18 | # Avoid cookstyle warnings 19 | trim_trailing_whitespace = true 20 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | use chefworkstation 2 | export KITCHEN_GLOBAL_YAML=kitchen.global.yml 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @sous-chefs/maintainers 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Lint & Unit Test" 3 | 4 | "on": 5 | pull_request: 6 | push: 7 | branches: [main] 8 | 9 | jobs: 10 | lint-unit: 11 | uses: sous-chefs/.github/.github/workflows/lint-unit.yml@3.1.1 12 | permissions: 13 | actions: write 14 | checks: write 15 | pull-requests: write 16 | statuses: write 17 | issues: write 18 | 19 | integration: 20 | needs: lint-unit 21 | runs-on: ubuntu-latest 22 | strategy: 23 | matrix: 24 | os: 25 | - almalinux-8 26 | - almalinux-9 27 | - amazonlinux-2023 28 | - debian-11 29 | - debian-12 30 | - centos-stream-9 31 | - fedora-latest 32 | - ubuntu-2004 33 | - ubuntu-2204 34 | - ubuntu-2404 35 | - rockylinux-8 36 | - rockylinux-9 37 | suite: 38 | - create 39 | - remove 40 | - create-thin 41 | - resize 42 | - resize-thin 43 | - resize-thin-pool-meta-data 44 | fail-fast: false 45 | 46 | steps: 47 | - name: Check out code 48 | uses: actions/checkout@v4 49 | - name: Setup HashiCorp Vagrant 50 | run: | 51 | wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg 52 | echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list 53 | sudo apt update 54 | sudo apt install -y vagrant 55 | - name: Setup Virtualbox 56 | run: | 57 | echo "deb [arch=amd64 signed-by=/usr/share/keyrings/oracle-virtualbox-2016.gpg] https://download.virtualbox.org/virtualbox/debian $(lsb_release -cs) contrib" | sudo tee /etc/apt/sources.list.d/virtualbox.list 58 | wget -O- https://www.virtualbox.org/download/oracle_vbox_2016.asc | sudo gpg --yes --output /usr/share/keyrings/oracle-virtualbox-2016.gpg --dearmor 59 | sudo apt-get update 60 | sudo apt-get install -y build-essential software-properties-common virtualbox 61 | - name: Check versions 62 | run: | 63 | vagrant --version 64 | vboxmanage --version 65 | - name: Install Chef 66 | uses: actionshub/chef-install@3.0.1 67 | - name: test-kitchen 68 | uses: actionshub/test-kitchen@3.0.0 69 | env: 70 | CHEF_LICENSE: accept-no-persist 71 | with: 72 | suite: ${{ matrix.suite }} 73 | os: ${{ matrix.os }} 74 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Mark stale issues and pull requests 3 | 4 | "on": 5 | schedule: [cron: "0 0 * * *"] 6 | 7 | jobs: 8 | stale: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/stale@v9 12 | with: 13 | repo-token: ${{ secrets.GITHUB_TOKEN }} 14 | close-issue-message: > 15 | Closing due to inactivity. 16 | If this is still an issue please reopen or open another issue. 17 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 18 | Thanks, Sous-Chefs. 19 | days-before-close: 7 20 | days-before-stale: 365 21 | stale-issue-message: > 22 | Marking stale due to inactivity. 23 | Remove stale label or comment or this will be closed in 7 days. 24 | Alternatively drop by the #sous-chefs channel on the [Chef Community Slack](http://community-slack.chef.io/) and we'll be happy to help! 25 | Thanks, Sous-Chefs. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.rbc 2 | .config 3 | InstalledFiles 4 | pkg 5 | test/tmp 6 | test/version_tmp 7 | tmp 8 | _Store 9 | *~ 10 | *# 11 | .#* 12 | \#*# 13 | *.un~ 14 | *.tmp 15 | *.bk 16 | *.bkup 17 | 18 | # editor files 19 | .idea 20 | .*.sw[a-z] 21 | 22 | # ruby/bundler/rspec files 23 | .ruby-version 24 | .ruby-gemset 25 | .rvmrc 26 | Gemfile.lock 27 | .bundle 28 | *.gem 29 | coverage 30 | spec/reports 31 | 32 | # YARD / rdoc artifacts 33 | .yardoc 34 | _yardoc 35 | doc/ 36 | rdoc 37 | 38 | # chef infra stuff 39 | Berksfile.lock 40 | .kitchen 41 | kitchen.local.yml 42 | vendor/ 43 | .coverage/ 44 | .zero-knife.rb 45 | Policyfile.lock.json 46 | 47 | # vagrant stuff 48 | .vagrant/ 49 | .vagrant.d/ 50 | -------------------------------------------------------------------------------- /.markdownlint-cli2.yaml: -------------------------------------------------------------------------------- 1 | config: 2 | ul-indent: false # MD007 3 | line-length: false # MD013 4 | no-duplicate-heading: false # MD024 5 | reference-links-images: false # MD052 6 | ignores: 7 | - .github/copilot-instructions.md 8 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | rules "~MD013", "~MD024", "~MD025", "~MD033" 2 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | --- 2 | PreCommit: 3 | TrailingWhitespace: 4 | enabled: true 5 | YamlLint: 6 | enabled: true 7 | required_executable: "yamllint" 8 | ChefSpec: 9 | enabled: true 10 | required_executable: "chef" 11 | command: ["chef", "exec", "rspec"] 12 | Cookstyle: 13 | enabled: true 14 | required_executable: "cookstyle" 15 | command: ["cookstyle"] 16 | MarkdownLint: 17 | enabled: false 18 | required_executable: "npx" 19 | command: ["npx", "markdownlint-cli2", "'**/*.md'"] 20 | include: ["**/*.md"] 21 | 22 | CommitMsg: 23 | HardTabs: 24 | enabled: true 25 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # TODO: These need to be addressed when we convert these to using custom 2 | # resources 3 | 4 | # Offense count: 10 5 | Chef/Correctness/ResourceSetsNameProperty: 6 | Exclude: 7 | - '**/attributes/*.rb' 8 | - '**/metadata.rb' 9 | - '**/Berksfile' 10 | - 'test/fixtures/cookbooks/test/recipes/create.rb' 11 | - 'test/fixtures/cookbooks/test/recipes/resize.rb' 12 | - 'test/fixtures/cookbooks/test/recipes/resize_thin.rb' 13 | - 'test/fixtures/cookbooks/test/recipes/resize_thin_pool_meta_data.rb' 14 | 15 | # Offense count: 27 16 | # Configuration parameters: Include. 17 | # Include: **/resources/*.rb, **/libraries/*.rb 18 | Chef/Modernize/SetOrReturnInResources: 19 | Exclude: 20 | - 'libraries/base_resource_logical_volume.rb' 21 | - 'libraries/resource_lvm_logical_volume.rb' 22 | - 'libraries/resource_lvm_thin_pool_meta_data.rb' 23 | - 'libraries/resource_lvm_thin_volume.rb' 24 | - 'libraries/resource_lvm_volume_group.rb' 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "chef-software.chef", 4 | "rebornix.ruby", 5 | "editorconfig.editorconfig", 6 | "DavidAnson.vscode-markdownlint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | line-length: 5 | max: 256 6 | level: warning 7 | document-start: disable 8 | braces: 9 | forbid: false 10 | min-spaces-inside: 0 11 | max-spaces-inside: 1 12 | min-spaces-inside-empty: -1 13 | max-spaces-inside-empty: -1 14 | comments: 15 | min-spaces-from-content: 1 16 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source 'https://supermarket.chef.io' 2 | 3 | metadata 4 | 5 | group :integration do 6 | cookbook 'test', path: 'test/fixtures/cookbooks/test' 7 | end 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # lvm Cookbook CHANGELOG 2 | 3 | This file is used to list changes made in each version of the lvm cookbook. 4 | 5 | ## Unreleased 6 | 7 | ## 6.2.2 - *2025-02-21* 8 | 9 | - Bump gem to 0.4.2 10 | - CI: Update tested platforms 11 | - CI: Switch to using ubuntu-latest and manually install VirtualBox 12 | 13 | ## 6.2.1 - *2024-11-18* 14 | 15 | - Standardise files with files in sous-chefs/repo-management 16 | 17 | ## 6.2.0 - *2024-09-05* 18 | 19 | - Update chef-ruby-lvm-attrib gem to 0.4.0 20 | 21 | ## 6.1.23 - *2024-07-15* 22 | 23 | - Standardise files with files in sous-chefs/repo-management 24 | 25 | ## 6.1.22 - *2024-05-03* 26 | 27 | ## 6.1.21 - *2024-05-02* 28 | 29 | ## 6.1.20 - *2024-04-30* 30 | 31 | ## 6.1.19 - *2024-04-30* 32 | 33 | ## 6.1.18 - *2024-04-30* 34 | 35 | - Update chef-ruby-lvm-attrib gem to 0.3.15 36 | 37 | ## 6.1.17 - *2023-11-01* 38 | 39 | - Update chef-ruby-lvm-attrib gem to 0.3.14 40 | 41 | ## 6.1.16 - *2023-10-03* 42 | 43 | ## 6.1.15 - *2023-09-29* 44 | 45 | ## 6.1.14 - *2023-05-17* 46 | 47 | ## 6.1.13 - *2023-04-04* 48 | 49 | - Standardise files with files in sous-chefs/repo-management 50 | 51 | ## 6.1.12 - *2023-04-01* 52 | 53 | - Standardise files with files in sous-chefs/repo-management 54 | 55 | ## 6.1.11 - *2023-04-01* 56 | 57 | - Standardise files with files in sous-chefs/repo-management 58 | 59 | ## 6.1.10 - *2023-04-01* 60 | 61 | - Standardise files with files in sous-chefs/repo-management 62 | 63 | ## 6.1.9 - *2023-03-20* 64 | 65 | - Standardise files with files in sous-chefs/repo-management 66 | 67 | ## 6.1.8 - *2023-03-15* 68 | 69 | - Standardise files with files in sous-chefs/repo-management 70 | 71 | ## 6.1.7 - *2023-03-02* 72 | 73 | ## 6.1.6 - *2023-02-27* 74 | 75 | ## 6.1.5 - *2023-02-27* 76 | 77 | - Standardise files with files in sous-chefs/repo-management 78 | 79 | ## 6.1.4 - *2023-02-15* 80 | 81 | - Standardise files with files in sous-chefs/repo-management 82 | 83 | ## 6.1.3 - *2022-12-13* 84 | 85 | - Standardise files with files in sous-chefs/repo-management 86 | 87 | ## 6.1.2 - *2022-09-30* 88 | 89 | - Update chef-ruby-lvm-attrib gem to 0.3.11 90 | 91 | ## 6.1.1 - *2022-09-29* 92 | 93 | - Fix parsing of output from `blkid` in `libraries/provider_lvm_logical_volume.rb` due to different behavior under busybox (e.g., running in hab effortless) 94 | 95 | ## 6.1.0 - *2022-08-07* 96 | 97 | - Fix `pvcreate` and `lvcreate` to return an error if a valid signature was found on the device instead of waiting interactivly for confirmation. 98 | 99 | ## 6.0.2 - *2022-08-07* 100 | 101 | - CI: Remove use of Vagrant boxes from OSUOSL 102 | - CI: Fix loop file creation on Ubuntu 20.04 103 | 104 | ## 6.0.1 - *2022-07-29* 105 | 106 | - Update chef-ruby-lvm-attrib gem to 0.3.10 107 | 108 | ## 6.0.0 - *2022-04-25* 109 | 110 | Standardise files with files in sous-chefs/repo-management 111 | 112 | - Standardise files with files in sous-chefs/repo-management 113 | - Remove Gemfile and the community cookbook releaser 114 | - Always turn on unfied_mode so we get consistent behaviour 115 | - Require Chef 15.3 for unified_mode 116 | - Turn on unified_mode 117 | 118 | ## 5.2.2 - *2022-02-08* 119 | 120 | - Remove delivery folder 121 | 122 | ## 5.2.1 - *2021-11-23* 123 | 124 | - Add CentOS Stream 8 to CI pipeline 125 | - Update chef-ruby-lvm-attrib gem to 0.3.9 126 | 127 | ## 5.2.0 - *2021-10-22* 128 | 129 | - Use default Chef source for gems 130 | 131 | ## 5.1.0 - *2021-10-14* 132 | 133 | - Sous Chefs adoption 134 | - Standardise files with files in sous-chefs/repo-management 135 | - Enable `unified_mode` if supported 136 | - resolved cookstyle error: test/fixtures/cookbooks/test/resources/loop_devices.rb:1:1 refactor: `Chef/Deprecations/ResourceWithoutUnifiedTrue` 137 | - Move resource documentation into individual files out of README 138 | - Migrate to InSpec tests 139 | - Install thin-provisioning-tools on Debian-based systems 140 | - Add GitHub CI 141 | 142 | ## 5.0.7 (2021-07-22) 143 | 144 | - Update the attributes gem version from 0.3.6 to 0.3.7 [@wheatevo](https://github.com/wheatevo) 145 | 146 | ## 5.0.6 (2021-02-09) 147 | 148 | - Need to add explicit parameters for super called from action methods - [@b-dean](https://github.com/b-dean) 149 | 150 | ## 5.0.5 (2020-11-13) 151 | 152 | - Update the attributes gem version from 0.3.5 to 0.3.6 [@gaelik](https://github.com/gaelik) 153 | 154 | ## 5.0.4 (2020-10-02) 155 | 156 | - Standardise files with files in chef-cookbooks/repo-management - [@xorimabot](https://github.com/xorimabot) 157 | - Chase upstream chef-ruby-lvm-attrib version - [@jflemer-ndp](https://github.com/jflemer-ndp) 158 | 159 | ## 5.0.3 (2020-08-25) 160 | 161 | - Support Chef Infra Client 16 and ubuntu 20.04 - [@duncaan](https://github.com/duncaan) 162 | - resolved cookstyle error: libraries/provider_lvm_logical_volume.rb:45:7 refactor: `ChefModernize/ActionMethodInResource` 163 | - resolved cookstyle error: libraries/provider_lvm_logical_volume.rb:129:7 refactor: `ChefModernize/ActionMethodInResource` 164 | - resolved cookstyle error: libraries/provider_lvm_logical_volume.rb:221:7 refactor: `ChefModernize/ActionMethodInResource` 165 | - resolved cookstyle error: libraries/provider_lvm_thin_pool.rb:36:7 refactor: `ChefModernize/ActionMethodInResource` 166 | - resolved cookstyle error: libraries/provider_lvm_thin_pool.rb:41:7 refactor: `ChefModernize/ActionMethodInResource` 167 | - resolved cookstyle error: libraries/provider_lvm_thin_pool_meta_data.rb:41:7 refactor: `ChefModernize/ActionMethodInResource` 168 | - resolved cookstyle error: libraries/provider_lvm_volume_group.rb:43:7 refactor: `ChefModernize/ActionMethodInResource` 169 | - resolved cookstyle error: libraries/provider_lvm_volume_group.rb:66:7 refactor: `ChefModernize/ActionMethodInResource` 170 | 171 | ## 5.0.2 (2020-06-02) 172 | 173 | - Cookstyle fixes including Chef Infra Client 16 fixes - [@xorimabot](https://github.com/xorimabot) 174 | - resolved cookstyle error: libraries/provider_lvm_logical_volume.rb:21:1 refactor: `ChefModernize/IncludingMixinShelloutInResources` 175 | - resolved cookstyle error: libraries/provider_lvm_logical_volume.rb:32:7 refactor: `ChefModernize/IncludingMixinShelloutInResources` 176 | - resolved cookstyle error: libraries/provider_lvm_thin_pool_meta_data.rb:21:1 refactor: `ChefModernize/IncludingMixinShelloutInResources` 177 | - resolved cookstyle error: libraries/provider_lvm_thin_pool_meta_data.rb:31:7 refactor: `ChefModernize/IncludingMixinShelloutInResources` 178 | - resolved cookstyle error: libraries/provider_lvm_volume_group.rb:21:1 refactor: `ChefModernize/IncludingMixinShelloutInResources` 179 | - resolved cookstyle error: libraries/provider_lvm_volume_group.rb:31:7 refactor: `ChefModernize/IncludingMixinShelloutInResources` 180 | - resolved cookstyle error: libraries/resource_lvm_logical_volume.rb:28:7 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 181 | - resolved cookstyle error: libraries/resource_lvm_thin_pool.rb:29:7 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 182 | - resolved cookstyle error: libraries/resource_lvm_thin_pool_meta_data.rb:29:7 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 183 | - resolved cookstyle error: libraries/resource_lvm_thin_volume.rb:29:7 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 184 | - resolved cookstyle error: libraries/resource_lvm_volume_group.rb:29:7 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 185 | - resolved cookstyle error: test/fixtures/cookbooks/test/resources/loop_devices.rb:1:1 warning: `ChefDeprecations/ResourceUsesOnlyResourceName` 186 | 187 | ## 5.0.1 (2020-05-27) 188 | 189 | - Update the attributes gem version from 0.3.1 to 0.3.2 190 | 191 | ## 5.0.0 (2020-05-01) 192 | 193 | The 5.0 release of this cookbook no longer cleans up the legacy di-ruby-lvm-attrib and di-ruby-lvm gems. These gems were replaced and the cleanup was added ~3 years ago. Any upgrade to this cookbook or to the Chef Infra Client would remove the legacy gems. If you are trying to upgrade from a VERY old version of this cookbook to current you'll either need to perform that cleanup by hand in a wrapper cookbook or you'll want to use the 4.x release first to perform the cleanup. 194 | 195 | ## 4.6.1 (2020-04-15) 196 | 197 | - Require the chef-ruby-lvm-attrib 0.3.1 gem - [@tas50](https://github.com/tas50) 198 | 199 | ## 4.6.0 (2020-01-04) 200 | 201 | - Remove extra metadata from the metadata.rb - [@tas50](https://github.com/tas50) 202 | - Remove the foodcritic config - [@tas50](https://github.com/tas50) 203 | - Update copyrights - [@tas50](https://github.com/tas50) 204 | - Use ::File not File in the conditionals - [@tas50](https://github.com/tas50) 205 | - Simplify types in the resources - [@tas50](https://github.com/tas50) 206 | - Switch testing to Github actions - [@tas50](https://github.com/tas50) 207 | - Require Chef 12.15+ - [@tas50](https://github.com/tas50) 208 | - Fix the failing specs - [@tas50](https://github.com/tas50) 209 | 210 | ## 4.5.4 (2019-08-20) 211 | 212 | - Update the attributes gem version from 0.2.6 to 0.2.8 213 | 214 | ## 4.5.3 (2018-12-26) 215 | 216 | - Add support for the ignore_skipped_cluster property, fixes #170 - [msgarbossa](https://github.com/msgarbossa) 217 | 218 | ## 4.5.2 (2018-11-01) 219 | 220 | - Update the attributes gem version from 0.2.5 to 0.2.6 221 | 222 | ## 4.5.1 (2018-11-01) 223 | 224 | - Update the attributes gem version from 0.2.3 to 0.2.5 225 | 226 | ## 4.5.0 (2018-09-11) 227 | 228 | - Added the ability to remove a logical volume, fixes #124 229 | - Added documentation on :remove action for lvm_logical_volume resource within the readme 230 | - Documented integration tests unable to function unless minimal Chef 13.x due to ruby 2.4.x dependency (development impact only, not operational impact) 231 | 232 | ## 4.4.0 (2018-08-10) 233 | 234 | - Added 'lv_params' to be handled as part of lvm_logical_volume :resize, as it was available only for :create - to resolve GH-159 235 | - Added logic to not pass '--resizefs' if the filesystem is 'RAW' 236 | - Added missing documentation on the hidden option of sending 'lv_params' to the resource for both :create and :resize 237 | 238 | ## 4.3.0 (2018-07-31) 239 | 240 | - Added new lvm_thin_pool_meta_data resource 241 | 242 | ## 4.2.0 (2018-07-24) 243 | 244 | - Convert physical_volume to a custom resource 245 | - Add support for the ignore_skipped_cluster property, fixes #156 246 | 247 | ## 4.1.15 (2018-06-29) 248 | 249 | - Fix resources so ChefSpec matchers are auto-generated 250 | - Fix wording in the readme 251 | - Add specs 252 | 253 | ## 4.1.14 (2018-06-11) 254 | 255 | - Remove the ChefSpec matchers which are autogenerated by ChefSpec now 256 | - Resolve Chef 12 resource cloning deprecation warning 257 | 258 | ## 4.1.13 (2018-05-01) 259 | 260 | - Update chef-ruby-lvm-attrib to 0.2.3 261 | 262 | ## 4.1.12 (2018-03-19) 263 | 264 | - Fix passing nils to Chef 14 265 | 266 | ## 4.1.11 (2018-03-09) 267 | 268 | - Correct raise syntax to remove the invalid second argument, fixes #141 269 | 270 | ## 4.1.10 (2017-11-26) 271 | 272 | - updating to version 0.2.2 of chef-ruby-lvm-attrib 273 | 274 | ## 4.1.9 (2017-10-04) 275 | 276 | - Remove end.run_action resource declaration from e2fsprogs package installation on SUSE platform. 277 | 278 | ## 4.1.8 (2017-09-28) 279 | 280 | - Raise on errors instead of calling Application fatal so we can ignore failures on the LVM resources 281 | 282 | ## 4.1.7 (2017-09-15) 283 | 284 | - Require latest lvm-attrib gem 285 | 286 | ## 4.1.6 (2017-08-15) 287 | 288 | - Fix for size in extents --extents should be used 289 | 290 | ## 4.1.5 (2017-08-15) 291 | 292 | - Add missing matchers for lvm thin pools and volumes 293 | 294 | ## 4.1.4 (2017-06-21) 295 | 296 | - Require the latest lvm gem which allows for the latest attrib gem 297 | 298 | ## 4.1.3 (2017-06-21) 299 | 300 | - Require the latest chef-ruby-lvm-attrib gem to support recent distros like RHEL 7.2/7.3 301 | 302 | ## 4.1.2 (2017-06-20) 303 | 304 | - Ensure metadata parsing doesn't fail on older chef 12 releases 305 | 306 | ## 4.1.1 (2017-06-20) 307 | 308 | - Adding source for the air gaped environment use case. 309 | - Don't start lvm2-lvmetad on amazon linux when on Chef < 13 310 | 311 | ## 4.1.0 (2017-04-26) 312 | 313 | - Fix invalid platform sles in metadata 314 | - Allowing a different source for gem install 315 | 316 | ## 4.0.6 (2017-03-29) 317 | 318 | - Only cleanup gems once in a chef run 319 | 320 | ## 4.0.5 (2017-01-09) 321 | 322 | - fix false coerce float error 323 | 324 | ## 4.0.4 (2016-12-20) 325 | 326 | - Remove deprecation notices introduced in 4.0.1 327 | 328 | ## 4.0.3 (2016-12-19) 329 | 330 | - Include platformintrospection dsl to fix suse check failures 331 | 332 | ## 4.0.2 (2016-12-15) 333 | 334 | - Warn if the attributes are set vs. a hard failure 335 | - Document the new gem changes in the readme 336 | 337 | ## 4.0.1 (2016-12-14) 338 | 339 | - Uninstall the previous lvm gems to prevent failures installing the new chef forks 340 | 341 | ## 4.0.0 (2016-12-12) 342 | 343 | ### Breaking changes 344 | 345 | - This cookbook has switched from the di-ruby-lvm/di-ruby-lvm-attrib gems to chef-ruby-lvm/chef-ruby-lvm-attrib forks. This was done to ensure that the latest lvm releases are always supported by the cookbooks and brings with it support for RHEL 7.3. If you have previously pinned gem versions you will need to update to the new attributes. 346 | 347 | ## Other changes 348 | 349 | - Added "yes_flag" also to PV and LV create" 350 | - Format and reword the readme 351 | - Remove need for apt for testing 352 | - Fix Suse support if using ext filesystems by installing the e2fsprogs package if necessary 353 | 354 | ## 3.1.0 (2016-10-26) 355 | 356 | - Remove chef 11 compatibility from chef_gem install 357 | - Update to di-ruby-lvm-attrib 0.0.27 358 | 359 | ## 3.0.0 (2016-09-16) 360 | 361 | - Testing updates 362 | - update to add chefspec runner methods 363 | - Require Chef 12.1+ 364 | 365 | ## v2.1.2 (2016-06-14) 366 | 367 | - Prevent failures in other cookbooks utilizing the lvm resources 368 | 369 | ## v2.1.1 (2016-06-10) 370 | 371 | - Update di-ruby-lvm-attrib to 0.0.26 372 | 373 | ## v2.1.0 (2016-05-11) 374 | 375 | - Added lvm_thin_pool and lvm_thin_volume resources 376 | 377 | ## v2.0.0 (2016-04-11) 378 | 379 | - The gems are now installed when the provider is first used instead of in the default recipe. For users that already have the LVM package installed there is no need to include the default recipe on their run_list now 380 | - Due to how the gem is installed now this recipe now requires Chef 12.0+ 381 | - Added RHEL 7.0 specs for the default recipe 382 | 383 | ## v1.6.1 (2016-03-23) 384 | 385 | - Fixed compile time installs of di-ruby-lvm 386 | 387 | ## v1.6.0 (2016-03-23) 388 | 389 | - Add a wipe_signatures option to LVM volume group 390 | 391 | ## v1.5.2 (2016-03-23) 392 | 393 | - Update di-ruby-lvm-attrib to 0.0.25 394 | 395 | ## v1.5.1 (2016-01-26) 396 | 397 | - Added attributes to allow installing the lvm gems at compile time 398 | - Removed yum cookbook from the Berksfile as it wasn't being used 399 | - Improved testing with chefspec and test kitchen 400 | 401 | ## v1.5.0 (2015-12-09) 402 | 403 | - Update the di-ruby-lvm and di-ruby-lvm-attrib gems to the latest release to improve speed and the supported versions of LVM 404 | - Add testing of the resizing to Travis CI and the Kitchen config 405 | - Resolve issues when running under Chefspec 406 | 407 | ## v1.4.1 (2015-11-17) 408 | 409 | - Change chef_gem installs to not install at compile_time on Chef 12 to avoid warnings 410 | 411 | ## v1.4.0 (2015-10-22) 412 | 413 | - Updated the minimum supported Chef release from 10 -> 11 in the readme 414 | - Updated di-ruby-lvm-attrib gem from 0.0.16 -> 0.0.21 415 | - Added Chef 11 compatibility to the source_url and issues_url in the metadata 416 | - Added support for additional RHEL deritivites to the metadata 417 | - Added additional Chefspec matchers 418 | - Added chefignore file to limit what files are uploaded to the Chef server 419 | - Added Test Kitchen config 420 | - Updated .gitignore 421 | - Updated to use Chef standard rubocop config 422 | - Updated Travis config to test using ChefDK vs. Gems 423 | - Updated contributing and testing docs 424 | - Added maintainers.md and maintainers.toml files 425 | - Updated development dependencies in the Gemfile 426 | - Added cookbook version badge to the readme 427 | 428 | ## v1.3.7 (2015-06-20) 429 | 430 | - Allow users to specify the exact versions of the lvm gems (#49) 431 | - Start/enable the lvmetad service on RHEL7\. (#52) 432 | - Allow arbitrary parameters to be passed to lvcreate. 433 | 434 | ## v1.3.6 (2015-02-18) 435 | 436 | - Reverting chef_gem compile_time work 437 | 438 | ## v1.3.5 (2015-02-18) 439 | 440 | - Fixing chef_gem with Chef::Resource::ChefGem.method_defined?(:compile_time) 441 | 442 | ## v1.3.4 (2015-02-18) 443 | 444 | - Fixing chef_gem for Chef below 12.1.0 445 | 446 | ## v1.3.3 (2015-02-17) 447 | 448 | - Being explicit about usage of the chef_gem's compile_time property. 449 | - Eliminating future deprecation warning in Chef 12.1.0 450 | 451 | ## v1.3.1 (2015-02-09) 452 | 453 | - 46 - Unbreak cookbook on Chef Client 12 454 | - 34 - Add ability to specify optional filesystem parameters when formatting 455 | 456 | ## v1.3.0 (2014-07-09) 457 | 458 | - 32 - add support for resizing logical and physical volumes 459 | - 33 - [COOK-4701]: add ability to extend volume groups 460 | 461 | ## v1.2.2 (2014-07-02) 462 | 463 | No changes. Bumping for toolchain 464 | 465 | ## v1.2.0 (2014-07-02) 466 | 467 | - [COOK-2992] add support for resizing logical and physical volumes 468 | 469 | ## v1.1.2 (2014-05-15) 470 | 471 | - [COOK-4609] Enable the logical volume if it is disabled 472 | 473 | ## v1.1.0 (2014-04-10) 474 | 475 | - [COOK-4539] - Change default mount mode to 0755 476 | 477 | ## v1.0.8 (2014-03-27) 478 | 479 | No change. Bumping version for toolchain 480 | 481 | ## v1.0.6 (2014-03-27) 482 | 483 | - [COOK-4486] - Add ChefSpec matchers for LVM resources 484 | - [COOK-4481] - The lvm_volume_group resource is not convergent 485 | 486 | ## v1.0.4 (2013-12-28) 487 | 488 | - **COOK-3987** - Volumes are created with the wrong # of extents. Size = '2%VG' is treated as a size of 2 extents. 489 | 490 | ## v1.0.2 491 | 492 | - **COOK-3935** - fix minor typo 493 | - Fixing up style 494 | - Updating test harness 495 | 496 | ## v1.0.0 497 | 498 | - **COOK-3357** - Complete refactor into a heavy-weight provider with tests 499 | 500 | ## v0.8.12 501 | 502 | - **COOK-2991** - Add SLES support 503 | - **COOK-2348** - Fix `lvm_logical_volume` when `mount_point` parameter is a String 504 | 505 | ## v0.8.10 506 | 507 | - [COOK-3031]: `ruby_block` to create logical volume is improperly named, causing collisions 508 | 509 | ## v0.8.8 510 | 511 | - [COOK-2283] - lvm version mismatch on fresh amazon linux install 512 | - [COOK-2733] - Fix invalid only_if command in lvm cookbook 513 | - [COOK-2822] - install, don't upgrade, lvm2 package 514 | 515 | ## v0.8.6 516 | 517 | - [COOK-2348] - lvm `logical_volume` doesn't work with `mount_point` parameter as String 518 | 519 | ## v0.8.4 520 | 521 | - [COOK-1977] - Typo "stripesize" in LVM cookbook 522 | - [COOK-1994] - Cannot create a logical volume if fstype is not given 523 | 524 | ## v0.8.2 525 | 526 | - [COOK-1857] - `lvm_logical_volume` resource callback conflicts with code in provider. 527 | 528 | ## v0.8.0 529 | 530 | - Added providers for managing the creation of LVM physical volumes, volume groups, and logical volumes. 531 | 532 | ## v0.7.1 533 | 534 | - Current public release 535 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Community Guidelines 2 | 3 | This project follows the Chef Community Guidelines 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please refer to 4 | [https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/CONTRIBUTING.MD](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/CONTRIBUTING.MD) 5 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Reference: http://danger.systems/reference.html 2 | 3 | # A pull request summary is required. Add a description of the pull request purpose. 4 | # Changelog must be updated for each pull request that changes code. 5 | # Warnings will be issued for: 6 | # Pull request with more than 400 lines of code changed 7 | # Pull reqest that change more than 5 lines without test changes 8 | # Failures will be issued for: 9 | # Pull request without summary 10 | # Pull requests with code changes without changelog entry 11 | 12 | def code_changes? 13 | code = %w(libraries attributes recipes resources files templates) 14 | code.each do |location| 15 | return true unless git.modified_files.grep(/#{location}/).empty? 16 | end 17 | false 18 | end 19 | 20 | def test_changes? 21 | tests = %w(spec test kitchen.yml kitchen.dokken.yml) 22 | tests.each do |location| 23 | return true unless git.modified_files.grep(/#{location}/).empty? 24 | end 25 | false 26 | end 27 | 28 | failure 'Please provide a summary of your Pull Request.' if github.pr_body.length < 10 29 | 30 | warn 'This is a big Pull Request.' if git.lines_of_code > 400 31 | 32 | warn 'This is a Table Flip.' if git.lines_of_code > 2000 33 | 34 | # Require a CHANGELOG entry for non-test changes. 35 | if !git.modified_files.include?('CHANGELOG.md') && code_changes? 36 | failure 'Please include a CHANGELOG entry.' 37 | end 38 | 39 | # Require Major Minor Patch version labels 40 | unless github.pr_labels.grep /minor|major|patch/i 41 | warn 'Please add a release label to this pull request' 42 | end 43 | 44 | # A sanity check for tests. 45 | if git.lines_of_code > 5 && code_changes? && !test_changes? 46 | warn 'This Pull Request is probably missing tests.' 47 | end 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lvm Cookbook 2 | 3 | [![Cookbook Version](https://img.shields.io/cookbook/v/lvm.svg)](https://supermarket.chef.io/cookbooks/lvm) 4 | [![CI State](https://github.com/sous-chefs/lvm/workflows/ci/badge.svg)](https://github.com/sous-chefs/lvm/actions?query=workflow%3Aci) 5 | [![OpenCollective](https://opencollective.com/sous-chefs/backers/badge.svg)](#backers) 6 | [![OpenCollective](https://opencollective.com/sous-chefs/sponsors/badge.svg)](#sponsors) 7 | [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) 8 | 9 | Installs lvm2 package and includes resources for managing LVM. 10 | 11 | ## Note on LVM gems 12 | 13 | This cookbook has used multiple variants of the ruby-lvm and ruby-lvm-attrib gems for interacting with LVM. Most recently we used di-ruby-lvm and di-ruby-lvm-attrib gems, which are no longer being maintained. As of the 4.0 release this cookbook uses new Chef maintained gems: chef-ruby-lvm and chef-ruby-lvm-attrib. Previous versions of this cookbook supported cleaning those gems up for approximetly 3 years. At this point you'll need to remove those gems yourself if they're still present as the namespaces will conflict. If you previously used attributes to control the version of the gems to install, you will need to update to the latest attribute names to maintain that functionality. 14 | 15 | ## Maintainers 16 | 17 | This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of Chef cookbook maintainers working together to maintain important cookbooks. If you’d like to know more please visit [sous-chefs.org](https://sous-chefs.org/) or come chat with us on the Chef Community Slack in [#sous-chefs](https://chefcommunity.slack.com/messages/C2V7B88SF). 18 | 19 | ## Requirements 20 | 21 | ### Platforms 22 | 23 | - Debian/Ubuntu 24 | - RHEL/CentOS/Scientific/Amazon/Oracle 25 | - SLES 26 | 27 | ### Chef 28 | 29 | - Chef 12.15+ 30 | 31 | ### Cookbooks 32 | 33 | - none 34 | 35 | ## Resources 36 | 37 | The following resources are provided: 38 | 39 | - [lvm_logical_volume](documentation/lvm_logical_volume.md) 40 | - [lvm_physical_volume](documentation/lvm_physical_volume.md) 41 | - [lvm_thin_pool](documentation/lvm_thin_pool.md) 42 | - [lvm_thin_pool_meta_data](documentation/lvm_thin_pool_meta_data.md) 43 | - [lvm_thin_volume](documentation/lvm_thin_volume.md) 44 | - [lvm_volume_group](documentation/lvm_volume_group.md) 45 | 46 | ## Usage 47 | 48 | Include the default recipe in your run list on a node, in a role, or in another recipe: 49 | 50 | ```ruby 51 | run_list( 52 | 'recipe[lvm::default]' 53 | ) 54 | ``` 55 | 56 | Depend on `lvm` in any cookbook that uses its Resources/Providers: 57 | 58 | ```ruby 59 | # other_cookbook/metadata.rb 60 | depends 'lvm' 61 | ``` 62 | 63 | ## Caveats 64 | 65 | This cookbook depends on the [chef-ruby-lvm](https://github.com/chef/chef-ruby-lvm) and [chef-ruby-lvm-attrib](https://github.com/chef/chef-ruby-lvm-attrib) gems. The chef-ruby-lvm-attrib gem in particular is a common cause of failures when using the providers. If you get a failure with an error message similar to 66 | 67 | ```text 68 | No such file or directory - /opt/chef/.../chef-ruby-lvm-attrib-0.0.3/lib/lvm/attributes/2.02.300(2)/lvs.yaml 69 | ``` 70 | 71 | then you are running a version of lvm that the gems do not support. However, getting support added is usually pretty easy. Just follow the instructions on "Adding Attributes" in the [chef-ruby-lvm-attrib README](https://github.com/chef/chef-ruby-lvm-attrib). 72 | 73 | ## Contributors 74 | 75 | This project exists thanks to all the people who [contribute.](https://opencollective.com/sous-chefs/contributors.svg?width=890&button=false) 76 | 77 | ### Backers 78 | 79 | Thank you to all our backers! 80 | 81 | ![https://opencollective.com/sous-chefs#backers](https://opencollective.com/sous-chefs/backers.svg?width=600&avatarHeight=40) 82 | 83 | ### Sponsors 84 | 85 | Support this project by becoming a sponsor. Your logo will show up here with a link to your website. 86 | 87 | ![https://opencollective.com/sous-chefs/sponsor/0/website](https://opencollective.com/sous-chefs/sponsor/0/avatar.svg?avatarHeight=100) 88 | ![https://opencollective.com/sous-chefs/sponsor/1/website](https://opencollective.com/sous-chefs/sponsor/1/avatar.svg?avatarHeight=100) 89 | ![https://opencollective.com/sous-chefs/sponsor/2/website](https://opencollective.com/sous-chefs/sponsor/2/avatar.svg?avatarHeight=100) 90 | ![https://opencollective.com/sous-chefs/sponsor/3/website](https://opencollective.com/sous-chefs/sponsor/3/avatar.svg?avatarHeight=100) 91 | ![https://opencollective.com/sous-chefs/sponsor/4/website](https://opencollective.com/sous-chefs/sponsor/4/avatar.svg?avatarHeight=100) 92 | ![https://opencollective.com/sous-chefs/sponsor/5/website](https://opencollective.com/sous-chefs/sponsor/5/avatar.svg?avatarHeight=100) 93 | ![https://opencollective.com/sous-chefs/sponsor/6/website](https://opencollective.com/sous-chefs/sponsor/6/avatar.svg?avatarHeight=100) 94 | ![https://opencollective.com/sous-chefs/sponsor/7/website](https://opencollective.com/sous-chefs/sponsor/7/avatar.svg?avatarHeight=100) 95 | ![https://opencollective.com/sous-chefs/sponsor/8/website](https://opencollective.com/sous-chefs/sponsor/8/avatar.svg?avatarHeight=100) 96 | ![https://opencollective.com/sous-chefs/sponsor/9/website](https://opencollective.com/sous-chefs/sponsor/9/avatar.svg?avatarHeight=100) 97 | -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Please refer to [the community cookbook documentation on testing](https://github.com/chef-cookbooks/community_cookbook_documentation/blob/main/TESTING.MD). 4 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Attributes:: default 4 | # 5 | # Copyright:: Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | default['lvm']['chef-ruby-lvm']['version'] = '0.4.0' 21 | default['lvm']['chef-ruby-lvm-attrib']['version'] = '0.4.2' 22 | default['lvm']['rubysource'] = Chef::Config['rubygems_url'] 23 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # to a Chef Infra Server or Supermarket. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | ehthumbs.db 9 | Icon? 10 | nohup.out 11 | Thumbs.db 12 | .envrc 13 | 14 | # EDITORS # 15 | ########### 16 | .#* 17 | .project 18 | .settings 19 | *_flymake 20 | *_flymake.* 21 | *.bak 22 | *.sw[a-z] 23 | *.tmproj 24 | *~ 25 | \#* 26 | REVISION 27 | TAGS* 28 | tmtags 29 | .vscode 30 | .editorconfig 31 | 32 | ## COMPILED ## 33 | ############## 34 | *.class 35 | *.com 36 | *.dll 37 | *.exe 38 | *.o 39 | *.pyc 40 | *.so 41 | */rdoc/ 42 | a.out 43 | mkmf.log 44 | 45 | # Testing # 46 | ########### 47 | .circleci/* 48 | .codeclimate.yml 49 | .delivery/* 50 | .foodcritic 51 | .kitchen* 52 | .mdlrc 53 | .overcommit.yml 54 | .rspec 55 | .rubocop.yml 56 | .travis.yml 57 | .watchr 58 | .yamllint 59 | azure-pipelines.yml 60 | Dangerfile 61 | examples/* 62 | features/* 63 | Guardfile 64 | kitchen*.yml 65 | mlc_config.json 66 | Procfile 67 | Rakefile 68 | spec/* 69 | test/* 70 | 71 | # SCM # 72 | ####### 73 | .git 74 | .gitattributes 75 | .gitconfig 76 | .github/* 77 | .gitignore 78 | .gitkeep 79 | .gitmodules 80 | .svn 81 | */.bzr/* 82 | */.git 83 | */.hg/* 84 | */.svn/* 85 | 86 | # Berkshelf # 87 | ############# 88 | Berksfile 89 | Berksfile.lock 90 | cookbooks/* 91 | tmp 92 | 93 | # Bundler # 94 | ########### 95 | vendor/* 96 | Gemfile 97 | Gemfile.lock 98 | 99 | # Policyfile # 100 | ############## 101 | Policyfile.rb 102 | Policyfile.lock.json 103 | 104 | # Documentation # 105 | ############# 106 | CODE_OF_CONDUCT* 107 | CONTRIBUTING* 108 | documentation/* 109 | TESTING* 110 | UPGRADING* 111 | 112 | # Vagrant # 113 | ########### 114 | .vagrant 115 | Vagrantfile 116 | -------------------------------------------------------------------------------- /documentation/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sous-chefs/lvm/dc750655320670d170ca154200300785dc4a969d/documentation/.gitkeep -------------------------------------------------------------------------------- /documentation/lvm_logical_volume.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_logical_volume 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM logical volumes. 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | 12 | | `:create` | (default) Creates a new logical volume | 13 | | `:resize` | Resize an existing logical volume (resizing only handles extending existing, this action will not shrink volumes due to the 'lvextend' command being passed) | 14 | | `:remove` | Remove an existing logical volume (optionally clean up the mount location/directory) | 15 | 16 | ## Properties 17 | 18 | | Name | Type | Default | Description | 19 | | ------------------------ | --------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | 20 | | `name` | String | name property | Name of the logical volume | 21 | | `group` | String | | (required) Volume group in which to create the new volume (not required if the volume is declared inside of an `lvm_volume_group` block) | 22 | | `size` | String | | (required) Size of the volume, including units (k, K, m, M, g, G, t, T) or as the percentage of the size of the volume group | 23 | | `filesystem` | String | `nil` | The format for the file system | 24 | | `filesystem_params` | String | `nil` | Optional parameters to use when formatting the file system | 25 | | `mount_point` | String, Hash | `nil` | Either a String containing the path to the mount point, or a Hash | 26 | | `physical_volumes` | String, Array | `[]` | Array of physical volumes that the volume will be restricted to | 27 | | `stripes` | Integer | `nil` | Number of stripes for the volume | 28 | | `stripe_size` | Integer | `nil` | Number of kilobytes per stripe segment (must be a power of 2 less than or equal to the physical extent size for the volume group) | 29 | | `mirrors` | Integer | `nil` | Number of mirrors for the volume | 30 | | `contiguous` | `true`, `false` | `false` | Whether or not volume should use the contiguous allocation policy | 31 | | `readahead` | Integer, String | `nil` | The readahead sector count for the volume (can be a value between 2 and 120, 'auto', or 'none') | 32 | | `take_up_free_space` | `true`, `false` | `false` | whether to have the LV take up the remainder of free space on the VG. Only valid for resize action | 33 | | `wipe_signatures` | `true`, `false` | `false` | Force the creation of the Logical Volume, even if `lvm` detects existing LV signatures | 34 | | `ignore_skipped_cluster` | `true`, `false` | `false` | Continue execution even if `lvm` detects skipped clustered volume groups | 35 | | `lv_params` | String | `nil` | Optional parameters to be passed to LVM | 36 | | `remove_mount_point` | `true`, `false` | `false` | Optional parameter to be passed to LVM during a :remove event to clean up the directory | 37 | 38 | ### mount_point 39 | 40 | If using a Hash, it _must_ contain the following keys: 41 | 42 | - `location` - (required) the directory to mount the volume on 43 | - `options` - the mount options for the volume 44 | - `dump` - the dump field for the fstab entry 45 | - `pass` - the pass field for the fstab entry 46 | 47 | ## Examples 48 | 49 | ```ruby 50 | lvm_logical_volume 'home' do 51 | group 'vg00' 52 | size '25%VG' 53 | filesystem 'ext4' 54 | mount_point '/home' 55 | stripes 3 56 | mirrors 2 57 | end 58 | 59 | lvm_logical_volume 'test' do 60 | group 'vg01' 61 | mount_point '/mnt/test' 62 | remove_mount_point true 63 | action :remove 64 | end 65 | ``` 66 | -------------------------------------------------------------------------------- /documentation/lvm_physical_volume.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_physical_volume 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM physical volumes. 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | --------------------------------------- | 12 | | `:create` | (default) Creates a new physical volume | 13 | | `:resize` | Resize an existing physical volume | 14 | 15 | ## Properties 16 | 17 | | Name | Type | Default | Description | 18 | | ------------------------ | -------------- | ------------- | -------------------------------------------------------------------------------------- | 19 | | `volume_name` | String | name property | The device to create the new physical volume on | 20 | | `wipe_signatures` | `true`,`false` | `false` | Force the creation of the Logical Volume, even if `lvm` detects existing PV signatures | 21 | | `ignore_skipped_cluster` | `true`,`false` | `false` | Continue execution even if `lvm` detects skipped clustered volume groups | 22 | 23 | ## Examples 24 | 25 | ```ruby 26 | lvm_physical_volume '/dev/sda' 27 | 28 | lvm_physical_volume '/dev/sdb' do 29 | action :resize 30 | end 31 | ``` 32 | -------------------------------------------------------------------------------- /documentation/lvm_thin_pool.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_thin_pool 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM thin pools (which are simply logical volumes created with the `--thinpool` argument to `lvcreate`). 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12 | | `:create` | (default) Create a new thin pool logical volume | 13 | | `:resize` | Resize an existing thin pool logical volume (resizing only handles extending existing, this action will not shrink volumes due to the `lvextend` command being passed) | 14 | 15 | ## Properties 16 | 17 | | Name | Type | Default | Description | 18 | | -------------------- | --------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | 19 | | `name` | String | name property | Name of the logical volume | 20 | | `group` | String | | (required) Volume group in which to create the new volume (not required if the volume is declared inside of an `lvm_volume_group` block) | 21 | | `size` | String | | (required) Size of the thin pool volume, including units (k, K, m, M, g, G, t, T) or as the percentage of the size of the volume group | 22 | | `filesystem` | String | `nil` | The format for the file system | 23 | | `filesystem_params` | String | `nil` | Optional parameters to use when formatting the file system | 24 | | `mount_point` | String, Hash | `nil` | Either a String containing the path to the mount point, or a Hash | 25 | | `physical_volumes` | String, Array | `[]` | Array of physical volumes that the volume will be restricted to | 26 | | `stripes` | Integer | `nil` | Number of stripes for the volume | 27 | | `stripe_size` | Integer | `nil` | Number of kilobytes per stripe segment (must be a power of 2 less than or equal to the physical extent size for the volume group) | 28 | | `mirrors` | Integer | `nil` | Number of mirrors for the volume | 29 | | `contiguous` | `true`, `false` | `false` | Whether or not volume should use the contiguous allocation policy | 30 | | `readahead` | Integer, String | `nil` | The readahead sector count for the volume (can be a value between 2 and 120, 'auto', or 'none') | 31 | | `take_up_free_space` | `true`, `false` | `false` | whether to have the LV take up the remainder of free space on the VG. Only valid for resize action | 32 | | `thin_volume` | Proc | `nil` | Shortcut for creating a new `lvm_thin_volume` definition (the volumes will be created in the order they are declared) | 33 | 34 | ### mount_point 35 | 36 | If using a Hash, it _must_ contain the following keys: 37 | 38 | - `location` - (required) the directory to mount the volume on 39 | - `options` - the mount options for the volume 40 | - `dump` - the dump field for the fstab entry 41 | - `pass` - the pass field for the fstab entry 42 | 43 | ## Examples 44 | 45 | ```ruby 46 | lvm_thin_pool 'home' do 47 | group 'vg00' 48 | size '25%VG' 49 | filesystem 'ext4' 50 | mount_point '/home' 51 | stripes 3 52 | mirrors 2 53 | end 54 | ``` 55 | -------------------------------------------------------------------------------- /documentation/lvm_thin_pool_meta_data.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_thin_pool_meta_data 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM thin pool metadata size. 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12 | | `:resize` | Resize an existing thin pool metadata volume (resizing only handles extending existing, this action will not shrink volumes due to the `lvextend` command being passed | 13 | 14 | ## Properties 15 | 16 | | Name | Type | Default | Description | 17 | | ------- | ------ | ------------- | ------------------------------------------------------------------------------------------ | 18 | | `name` | String | name property | Name of the thin pool metadata volume | 19 | | `group` | String | | (required) Name of volume group in which thin pool metadata volume exist | 20 | | `pool` | String | | (required) Name of thin pool volume in which thin pool metadata volume exist | 21 | | `size` | String | | (required) Size of the thin pool metadata volume, including units (k, K, m, M, g, G, t, T) | 22 | 23 | ## Examples 24 | 25 | ```ruby 26 | lvm_thin_pool_meta_data 'lv-thin-pool_tmeta' do 27 | group 'vg00' 28 | pool 'lv-thin-pool' 29 | size '2M' 30 | action :resize 31 | end 32 | ``` 33 | -------------------------------------------------------------------------------- /documentation/lvm_thin_volume.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_thin_volume 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM thin volumes (which are simply logical volumes created with the `--thin` argument to `lvcreate` and are contained inside of other logical volumes that were created with the `--thinpool` option to `lvcreate`). 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | 12 | | `:create` | (default) Create a new thin logical volume | 13 | | `:resize` | Resize an existing thin logical volume (resizing only handles extending existing, this action will not shrink volumes due to the `lvextend` command being passed) | 14 | 15 | ## Properties 16 | 17 | | Name | Type | Default | Description | 18 | | ------------------- | ------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | 19 | | `name` | String | name property | Name of the logical volume | 20 | | `group` | String | | (required) Volume group in which to create the new volume (not required if the volume is declared inside of an `lvm_volume_group` block) | 21 | | `pool` | String | | (required) Thin pool volume in which to create the new volume (not required if the volume is declared inside of an `lvm_thin_pool` block) | 22 | | `size` | String | | (required) Size of the thin volume, including units (k, K, m, M, g, G, t, T) | 23 | | `filesystem` | String | `nil` | The format for the file system | 24 | | `filesystem_params` | String | `nil` | Optional parameters to use when formatting the file system | 25 | | `mount_point` | String, Hash | `nil` | Either a String containing the path to the mount point, or a Hash | 26 | 27 | ### mount_point 28 | 29 | If using a Hash, it _must_ contain the following keys: 30 | 31 | - `location` - (required) the directory to mount the volume on 32 | - `options` - the mount options for the volume 33 | - `dump` - the dump field for the fstab entry 34 | - `pass` - the pass field for the fstab entry 35 | 36 | ## Examples 37 | 38 | ```ruby 39 | lvm_thin_volume 'thin01' do 40 | group 'vg00' 41 | pool 'lv-thin-pool' 42 | size '5G' 43 | filesystem 'ext4' 44 | mount_point location: '/var/thin01', options: 'noatime,nodiratime' 45 | end 46 | ``` 47 | -------------------------------------------------------------------------------- /documentation/lvm_volume_group.md: -------------------------------------------------------------------------------- 1 | 2 | # lvm_volume_group 3 | 4 | [Back to resource list](../README.md#resources) 5 | 6 | Manages LVM volume groups. 7 | 8 | ## Actions 9 | 10 | | Action | Description | 11 | | --------- | --------------------------------------------------------------- | 12 | | `:create` | (default) Creates a new volume group | 13 | | `:extend` | Extend an existing volume group to include new physical volumes | 14 | 15 | ## Properties 16 | 17 | | Name | Type | Default | Description | 18 | | ---------------------- | --------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 19 | | `name` | String | name property | (required) Name of the volume group | 20 | | `physical_volumes` | Array, String | | (required) The device or list of devices to use as physical volumes (if they haven't already been initialized as physical volumes, they will be initialized automatically) | 21 | | `physical_extent_size` | String | `nil` | The physical extent size for the volume group | 22 | | `logical_volume` | Proc | `nil` | Shortcut for creating a new `lvm_logical_volume` definition (the logical volumes will be created in the order they are declared) | 23 | | `wipe_signatures` | `true`, `false` | `false` | Force the creation of the Volume Group, even if `lvm` detects existing non-LVM data on disk | 24 | | `thin_pool` | Proc | `nil` | Shortcut for creating a new `lvm_thin_pool` definition (the logical volumes will be created in the order they are declared) | 25 | 26 | ## Examples 27 | 28 | ```ruby 29 | lvm_volume_group 'vg00' do 30 | physical_volumes ['/dev/sda', '/dev/sdb', '/dev/sdc'] 31 | wipe_signatures true 32 | 33 | logical_volume 'logs' do 34 | size '1G' 35 | filesystem 'xfs' 36 | mount_point location: '/var/log', options: 'noatime,nodiratime' 37 | stripes 3 38 | end 39 | 40 | logical_volume 'home' do 41 | size '25%VG' 42 | filesystem 'ext4' 43 | mount_point '/home' 44 | stripes 3 45 | mirrors 2 46 | end 47 | 48 | thin_pool "lv-thin-pool" do 49 | size '5G' 50 | stripes 2 51 | 52 | thin_volume "thin01" do 53 | size '10G' 54 | filesystem 'ext4' 55 | mount_point location: '/var/thin01', options: 'noatime,nodiratime' 56 | end 57 | end 58 | end 59 | ``` 60 | -------------------------------------------------------------------------------- /kitchen.dokken.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: dokken 3 | privileged: true 4 | chef_version: <%= ENV['CHEF_VERSION'] || 'current' %> 5 | 6 | transport: { name: dokken } 7 | provisioner: { name: dokken } 8 | 9 | platforms: 10 | - name: almalinux-8 11 | driver: 12 | image: dokken/almalinux-8 13 | pid_one_command: /usr/lib/systemd/systemd 14 | 15 | - name: almalinux-9 16 | driver: 17 | image: dokken/almalinux-9 18 | pid_one_command: /usr/lib/systemd/systemd 19 | 20 | - name: almalinux-10 21 | driver: 22 | image: dokken/almalinux-10 23 | pid_one_command: /usr/lib/systemd/systemd 24 | 25 | - name: amazonlinux-2023 26 | driver: 27 | image: dokken/amazonlinux-2023 28 | pid_one_command: /usr/lib/systemd/systemd 29 | 30 | - name: centos-stream-9 31 | driver: 32 | image: dokken/centos-stream-9 33 | pid_one_command: /usr/lib/systemd/systemd 34 | 35 | - name: centos-stream-10 36 | driver: 37 | image: dokken/centos-stream-10 38 | pid_one_command: /usr/lib/systemd/systemd 39 | 40 | - name: debian-11 41 | driver: 42 | image: dokken/debian-11 43 | pid_one_command: /bin/systemd 44 | 45 | - name: debian-12 46 | driver: 47 | image: dokken/debian-12 48 | pid_one_command: /bin/systemd 49 | 50 | - name: fedora-latest 51 | driver: 52 | image: dokken/fedora-latest 53 | pid_one_command: /usr/lib/systemd/systemd 54 | 55 | - name: opensuse-leap-15 56 | driver: 57 | image: dokken/opensuse-leap-15 58 | pid_one_command: /usr/lib/systemd/systemd 59 | 60 | - name: oraclelinux-8 61 | driver: 62 | image: dokken/oraclelinux-8 63 | pid_one_command: /usr/lib/systemd/systemd 64 | 65 | - name: oraclelinux-9 66 | driver: 67 | image: dokken/oraclelinux-9 68 | pid_one_command: /usr/lib/systemd/systemd 69 | 70 | - name: rockylinux-8 71 | driver: 72 | image: dokken/rockylinux-8 73 | pid_one_command: /usr/lib/systemd/systemd 74 | 75 | - name: rockylinux-9 76 | driver: 77 | image: dokken/rockylinux-9 78 | pid_one_command: /usr/lib/systemd/systemd 79 | 80 | - name: ubuntu-20.04 81 | driver: 82 | image: dokken/ubuntu-20.04 83 | pid_one_command: /bin/systemd 84 | 85 | - name: ubuntu-22.04 86 | driver: 87 | image: dokken/ubuntu-22.04 88 | pid_one_command: /bin/systemd 89 | 90 | - name: ubuntu-24.04 91 | driver: 92 | image: dokken/ubuntu-24.04 93 | pid_one_command: /bin/systemd 94 | -------------------------------------------------------------------------------- /kitchen.exec.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: { name: exec } 3 | transport: { name: exec } 4 | 5 | platforms: 6 | - name: macos-latest 7 | - name: windows-latest 8 | -------------------------------------------------------------------------------- /kitchen.global.yml: -------------------------------------------------------------------------------- 1 | --- 2 | provisioner: 3 | name: chef_infra 4 | product_name: chef 5 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 6 | channel: stable 7 | install_strategy: once 8 | chef_license: accept 9 | enforce_idempotency: <%= ENV['ENFORCE_IDEMPOTENCY'] || true %> 10 | multiple_converge: <%= ENV['MULTIPLE_CONVERGE'] || 2 %> 11 | deprecations_as_errors: true 12 | log_level: <%= ENV['CHEF_LOG_LEVEL'] || 'auto' %> 13 | 14 | verifier: 15 | name: inspec 16 | 17 | platforms: 18 | - name: almalinux-8 19 | - name: almalinux-9 20 | - name: amazonlinux-2023 21 | - name: centos-stream-9 22 | - name: debian-11 23 | - name: debian-12 24 | - name: fedora-latest 25 | - name: opensuse-leap-15 26 | - name: oraclelinux-8 27 | - name: oraclelinux-9 28 | - name: rockylinux-8 29 | - name: rockylinux-9 30 | - name: ubuntu-20.04 31 | - name: ubuntu-22.04 32 | - name: ubuntu-24.04 33 | -------------------------------------------------------------------------------- /kitchen.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: vagrant 3 | 4 | provisioner: 5 | name: chef_infra 6 | deprecations_as_errors: true 7 | product_name: <%= ENV['CHEF_PRODUCT_NAME'] || 'chef' %> 8 | chef_license: accept-no-persist 9 | product_version: <%= ENV['CHEF_VERSION'] || 'latest' %> 10 | log_level: <%= ENV['CHEF_LOG_LEVEL'] || 'auto' %> 11 | 12 | verifier: 13 | name: inspec 14 | 15 | platforms: 16 | - name: almalinux-8 17 | - name: almalinux-9 18 | - name: amazonlinux-2023 19 | - name: centos-stream-9 20 | - name: debian-11 21 | - name: debian-12 22 | - name: fedora-latest 23 | - name: opensuse-leap-15 24 | - name: rockylinux-8 25 | - name: rockylinux-9 26 | - name: ubuntu-20.04 27 | - name: ubuntu-22.04 28 | - name: ubuntu-24.04 29 | 30 | suites: 31 | - name: create 32 | run_list: 33 | - recipe[test::create] 34 | - name: remove 35 | run_list: 36 | - recipe[test::remove] 37 | - name: create_thin 38 | run_list: 39 | - recipe[test::create_thin] 40 | - name: resize 41 | run_list: 42 | - recipe[test::create] 43 | - recipe[test::resize] 44 | - name: resize_thin 45 | run_list: 46 | - recipe[test::create_thin] 47 | - recipe[test::resize_thin] 48 | - name: resize_thin_pool_meta_data 49 | run_list: 50 | - recipe[test::create_thin] 51 | - recipe[test::resize_thin_pool_meta_data] 52 | excludes: 53 | - debian-9 54 | -------------------------------------------------------------------------------- /libraries/base_resource_logical_volume.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: base_resource_logical_volume 4 | # 5 | # Copyright:: 2009-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | 22 | class Chef 23 | class Resource 24 | # Base class that contains common attributes for all logical volume resources 25 | # 26 | class BaseLogicalVolume < Chef::Resource 27 | include Chef::DSL::Recipe 28 | 29 | unified_mode true if respond_to?(:unified_mode) 30 | 31 | resource_name :lvm_volume_group 32 | provides :lvm_volume_group 33 | 34 | # Initializes a BaseLogicalVolume object. This class is only meant to 35 | # be used as a base class for other resources. 36 | # 37 | # @param name [String] name of the resource 38 | # @param run_context [Chef::RunContext] the run context of chef run 39 | # 40 | # @return [Chef::Resource::LvmLogicalVolume] the lvm_logical_volume resource 41 | # 42 | def initialize(name, run_context = nil) 43 | super 44 | end 45 | 46 | # Attribute: name - name of the logical volume 47 | # 48 | # @param arg [String] the name of the logical volume 49 | # 50 | # @return [String] the name of the logical volume 51 | # 52 | def name(arg = nil) 53 | set_or_return( 54 | :name, 55 | arg, 56 | kind_of: String, 57 | regex: /[\w+.-]+/, 58 | name_attribute: true, 59 | required: true, 60 | callbacks: { 61 | "cannot be '.', '..', 'snapshot', or 'pvmove'" => proc do |value| 62 | !(value == '.' || value == '..' || value == 'snapshot' || value == 'pvmove') 63 | end, 64 | "cannot contain the strings '_mlog' or '_mimage'" => proc do |value| 65 | !value.match(/.*(_mlog|_mimage).*/) 66 | end, 67 | } 68 | ) 69 | end 70 | 71 | # Attribute: group - the volume group the logical volume belongs to 72 | # 73 | # @param arg [String] the volume group name 74 | # 75 | # @return [String] the volume group name 76 | # 77 | def group(arg = nil) 78 | set_or_return( 79 | :group, 80 | arg, 81 | kind_of: String 82 | ) 83 | end 84 | 85 | # Attribute: lv_params - additional parameters for lvcreate 86 | # 87 | # @param arg [String] the parameters 88 | # 89 | # @return [String] the parameters 90 | # 91 | def lv_params(arg = nil) 92 | set_or_return( 93 | :lv_params, 94 | arg, 95 | kind_of: String 96 | ) 97 | end 98 | 99 | # Attribute: size - size of the logical volume 100 | # 101 | # @param arg [String] the size of the logical volume 102 | # 103 | # @return [String] the size of the logical volume 104 | # 105 | def size(arg = nil) 106 | set_or_return( 107 | :size, 108 | arg, 109 | kind_of: String, 110 | regex: /^(\d+[kKmMgGtTpPeE]|(\d{1,2}|100)%(FREE|VG|PVS)|\d+)$/, 111 | required: true 112 | ) 113 | end 114 | 115 | # Attribute: filesystem - the file system type 116 | # 117 | # @param arg [String] the file system type 118 | # 119 | # @return [String] the file system type 120 | # 121 | def filesystem(arg = nil) 122 | set_or_return( 123 | :filesystem, 124 | arg, 125 | kind_of: String 126 | ) 127 | end 128 | 129 | # Attribute: filesystem_params - the file system parameters 130 | # 131 | # @param arg [String] the file system parameters 132 | # 133 | # @return [String] the file system parameters 134 | # 135 | def filesystem_params(arg = nil) 136 | set_or_return( 137 | :filesystem_params, 138 | arg, 139 | kind_of: String 140 | ) 141 | end 142 | 143 | # Attribute: mount_point - mount point for the logical volume 144 | # 145 | # @param arg [String] the mount point 146 | # 147 | # @return [String] the mount point 148 | # 149 | def mount_point(arg = nil) 150 | set_or_return( 151 | :mount_point, 152 | arg, 153 | kind_of: [String, Hash], 154 | callbacks: { 155 | ': location is required!' => proc do |value| 156 | value.class == String || (value[:location] && !value[:location].empty?) 157 | end, 158 | ': location must be an absolute path!' => proc do |value| 159 | # this can be a string or a hash, so attempt to match either for 160 | # the regex 161 | matches = case value 162 | when String 163 | value =~ %r{^/[^\0]*} 164 | when Hash 165 | value[:location] =~ %r{^/[^\0]*} 166 | end 167 | !matches.nil? 168 | end, 169 | } 170 | ) 171 | end 172 | end 173 | end 174 | end 175 | -------------------------------------------------------------------------------- /libraries/lvm.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright:: Chef Software, Inc. 3 | # License:: Apache License, Version 2.0 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | module LVMCookbook 19 | def require_lvm_gems 20 | return if defined?(LVM) 21 | 22 | # require attribute specified gems 23 | gem 'chef-ruby-lvm-attrib', node['lvm']['chef-ruby-lvm-attrib']['version'] 24 | gem 'chef-ruby-lvm', node['lvm']['chef-ruby-lvm']['version'] 25 | require 'lvm' 26 | Chef::Log.debug("Node had chef-ruby-lvm-attrib #{node['lvm']['chef-ruby-lvm-attrib']['version']} and chef-ruby-lvm #{node['lvm']['chef-ruby-lvm']['version']} installed. No need to install gems.") 27 | rescue LoadError 28 | Chef::Log.debug('Did not find lvm gems of the specified versions installed. Installing now') 29 | 30 | chef_gem 'chef-ruby-lvm-attrib' do 31 | action :install 32 | version node['lvm']['chef-ruby-lvm-attrib']['version'] 33 | source node['lvm']['rubysource'] 34 | clear_sources true 35 | compile_time true 36 | end 37 | 38 | chef_gem 'chef-ruby-lvm' do 39 | action :install 40 | version node['lvm']['chef-ruby-lvm']['version'] 41 | source node['lvm']['rubysource'] 42 | clear_sources true 43 | compile_time true 44 | end 45 | 46 | require 'lvm' 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /libraries/provider_lvm_logical_volume.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: provider_lvm_logical_volume 4 | # 5 | # Copyright:: 2009-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/provider' 21 | require 'chef/dsl/recipe' 22 | require 'chef/dsl/platform_introspection' 23 | require File.join(File.dirname(__FILE__), 'lvm') 24 | 25 | class Chef 26 | class Provider 27 | # The provider for lvm_logical_volume resource 28 | # 29 | class LvmLogicalVolume < Chef::Provider 30 | include Chef::DSL::Recipe 31 | include Chef::DSL::PlatformIntrospection 32 | include LVMCookbook 33 | 34 | # Loads the current resource attributes 35 | # 36 | # @return [Chef::Resource::LvmLogicalVolume] the lvm_logical_volume resource 37 | # 38 | def load_current_resource 39 | @current_resource ||= Chef::Resource::LvmLogicalVolume.new(@new_resource.name) 40 | @current_resource 41 | end 42 | 43 | # The create action 44 | # 45 | action :create do 46 | require_lvm_gems 47 | install_filesystem_deps 48 | 49 | lvm = LVM::LVM.new(lvm_options) 50 | name = new_resource.name 51 | group = new_resource.group 52 | fs_type = new_resource.filesystem 53 | fs_params = new_resource.filesystem_params 54 | device_name = "/dev/mapper/#{to_dm_name(group)}-#{to_dm_name(name)}" 55 | updates = [] 56 | 57 | vg = lvm.volume_groups[group] 58 | # Create the logical volume 59 | if vg.nil? || vg.logical_volumes.select { |lv| lv.name == name }.empty? 60 | command = create_command 61 | Chef::Log.debug "Executing lvm command: '#{command}'" 62 | output = lvm.raw(command) 63 | Chef::Log.debug "Command output: '#{output}'" 64 | updates << true 65 | else 66 | lv = vg.logical_volumes.find { |v| v.name == name } 67 | if !lv.state.nil? && lv.state.to_sym == :active 68 | Chef::Log.info "Logical volume '#{name}' already exists and active. Not creating..." 69 | else 70 | Chef::Log.info "Logical volume '#{name}' already created and inactive. Activating now..." 71 | command = "lvchange -a y #{device_name}" 72 | Chef::Log.debug "Executing lvm command: '#{command}'" 73 | output = lvm.raw(command) 74 | Chef::Log.debug "Command output: '#{output}'" 75 | updates << true 76 | end 77 | end 78 | 79 | # If file system is specified, format the logical volume 80 | if fs_type.nil? 81 | Chef::Log.info 'File system type is not set. Not formatting...' 82 | elsif device_formatted?(device_name, fs_type) 83 | Chef::Log.info "Volume '#{device_name}' is already formatted. Not formatting..." 84 | else 85 | shell_out!("yes | mkfs -t #{fs_type} #{fs_params} #{device_name}") 86 | updates << true 87 | end 88 | 89 | # If the mount point is specified, mount the logical volume 90 | if new_resource.mount_point 91 | 92 | mount_spec = if new_resource.mount_point.is_a?(String) 93 | { location: new_resource.mount_point } 94 | else 95 | new_resource.mount_point 96 | end 97 | 98 | # Create the mount point 99 | dir_resource = directory mount_spec[:location] do 100 | mode '755' 101 | owner 'root' 102 | group 'root' 103 | recursive true 104 | action :nothing 105 | not_if { Pathname.new(mount_spec[:location]).mountpoint? } 106 | end 107 | dir_resource.run_action(:create) 108 | # Mark the resource as updated if the directory resource is updated 109 | updates << dir_resource.updated? 110 | 111 | # Mount the logical volume 112 | mount_resource = mount mount_spec[:location] do 113 | options mount_spec[:options] 114 | dump mount_spec[:dump] if mount_spec[:dump] 115 | pass mount_spec[:pass] if mount_spec[:pass] 116 | device device_name 117 | fstype fs_type 118 | action :nothing 119 | end 120 | mount_resource.run_action(:mount) 121 | mount_resource.run_action(:enable) 122 | # Mark the resource as updated if the mount resource is updated 123 | updates << mount_resource.updated? 124 | end 125 | new_resource.updated_by_last_action(updates.any?) 126 | end 127 | 128 | # Action to resize LV to specified size 129 | action :resize do 130 | require_lvm_gems 131 | lvm = LVM::LVM.new(lvm_options) 132 | name = new_resource.name 133 | group = new_resource.group 134 | 135 | vg = lvm.volume_groups[group] 136 | # if doing a resize make sure that the volume exists before doing anything 137 | 138 | raise("Error volume group #{group} does not exist") if vg.nil? 139 | 140 | lv = vg.logical_volumes.select do |lvs| 141 | lvs.name == name 142 | end 143 | # make sure that the LV specified exists in the VG specified 144 | raise("Error logical volume #{name} does not exist") if lv.empty? 145 | 146 | lv = lv.first 147 | pe_size = lvm.volume_groups[group].extent_size.to_i 148 | pe_free = lvm.volume_groups[group].free_count.to_i 149 | pe_count = lvm.volume_groups[group].extent_count.to_i 150 | lv_size_cur = lv.size.to_i / pe_size 151 | 152 | lv_size = new_resource.size 153 | lv_size = '100%FREE' if new_resource.respond_to?(:take_up_free_space) && new_resource.take_up_free_space 154 | 155 | # figure out how we should calculate extents 156 | resize_type = case lv_size 157 | when /^\d+[kKmMgGtT]$/ 158 | 'byte' 159 | when /^(\d{1,2}|100)%(FREE|VG|PVS)$/ 160 | 'percent' 161 | when /^(\d+)$/ 162 | 'extent' 163 | end 164 | 165 | # calculate extents based off of an explicit size 166 | # if not suffix is supplied assume extents is what is being specified 167 | if resize_type == 'byte' || resize_type == 'extent' 168 | lv_size_req = case lv_size 169 | when /^(\d+)(k|K)$/ 170 | (Regexp.last_match[1].to_i * 1024) / pe_size 171 | when /^(\d+)(m|M)$/ 172 | (Regexp.last_match[1].to_i * 1_048_576) / pe_size 173 | when /^(\d+)(g|G)$/ 174 | (Regexp.last_match[1].to_i * 1_073_741_824) / pe_size 175 | when /^(\d+)(t|T)$/ 176 | (Regexp.last_match[1].to_i * 1_099_511_627_776) / pe_size 177 | when /^(\d+)$/ 178 | Regexp.last_match[1].to_i 179 | else 180 | raise("Invalid size #{Regexp.last_match[1]} for lvm resize") 181 | end 182 | # calculate the number of extents needed differently if specifying a percentage 183 | elsif resize_type == 'percent' 184 | percent, type = lv_size.scan(/(\d{1,2}|100)%(FREE|VG|PVS)/).first 185 | 186 | lv_size_req = case type 187 | when 'VG' 188 | ((percent.to_f / 100) * pe_count).to_i 189 | when 'FREE' 190 | raise('Cannot percentage based off free space') unless new_resource.take_up_free_space 191 | (((percent.to_f / 100) * pe_free) + lv_size_cur).to_i 192 | else 193 | raise("Invalid type #{type} for resize. You can only resize using an explicit size, percentage of VG or by setting take_up_free_space to true") 194 | end 195 | else 196 | raise("Invalid size specification #{lv_size}") 197 | end 198 | 199 | raise("Error trying to extend logical volume #{lv.name} beyond the capacity of volume group #{group}") if !thin_volume? && (lv_size_req - lv_size_cur) > pe_free 200 | 201 | # don't resize if the current size is greater than or equal to the target size 202 | if lv_size_cur >= lv_size_req 203 | Chef::Log.debug "Logical volume #{lv.name} in volume group #{group} already at requested size" 204 | else 205 | Chef::Log.debug "Resizing logical volume #{lv.name} from #{lv_size_cur} pe to #{lv_size_req} pe with #{pe_free} pe left in volume group #{group}" 206 | 207 | command = resize_command(lv_size_req) 208 | Chef::Log.debug "Running command: #{command}" 209 | output = lvm.raw command 210 | Chef::Log.debug "Command output: #{output}" 211 | 212 | # broadcast that we did a resize 213 | new_resource.updated_by_last_action true 214 | end 215 | end 216 | 217 | # The remove action 218 | # must specify the volume group name - as the umount passes a full path 219 | # if mount_point specified, then unmount first 220 | # if remove_mount_point specificed, then the directory will be removed 221 | action :remove do 222 | require_lvm_gems 223 | install_filesystem_deps 224 | 225 | lvm = LVM::LVM.new(lvm_options) 226 | name = new_resource.name 227 | group = new_resource.group 228 | # fs_type = new_resource.filesystem 229 | # fs_params = new_resource.filesystem_params 230 | mount_point = new_resource.mount_point 231 | remove_mount_point = new_resource.remove_mount_point 232 | device_name = "/dev/mapper/#{to_dm_name(group)}-#{to_dm_name(name)}" 233 | updates = [] 234 | 235 | # If the mount point is specified, umount the logical volume 236 | if mount_point 237 | mount_spec = if mount_point.is_a?(String) 238 | { location: mount_point } 239 | else 240 | mount_point 241 | end 242 | 243 | # Umount the logical volume 244 | mount_resource = mount mount_spec[:location] do 245 | options mount_spec[:options] 246 | dump mount_spec[:dump] if mount_spec[:dump] 247 | pass mount_spec[:pass] if mount_spec[:pass] 248 | device device_name 249 | action :nothing 250 | end 251 | mount_resource.run_action(:umount) 252 | mount_resource.run_action(:disable) 253 | # Mark the resource as updated if the mount resource is updated 254 | updates << mount_resource.updated? 255 | 256 | # If specified, remove the mount point 257 | if remove_mount_point 258 | dir_resource = directory mount_spec[:location] do 259 | recursive true 260 | action :nothing 261 | not_if { Pathname.new(mount_spec[:location]).mountpoint? } 262 | end 263 | dir_resource.run_action(:delete) 264 | # Mark the resource as updated if the directory resource is updated 265 | updates << dir_resource.updated? 266 | end 267 | end 268 | 269 | vg = lvm.volume_groups[group] 270 | # Remove the logical volume 271 | if vg.logical_volumes.select { |lv| lv.name == name } 272 | command = remove_command 273 | Chef::Log.debug "Executing lvm command: '#{command}'" 274 | output = lvm.raw(command) 275 | Chef::Log.debug "Command output: '#{output}'" 276 | else 277 | Chef::Log.info "Logical volume '#{name}' unable to be removed. Not removing..." 278 | end 279 | updates << true 280 | new_resource.updated_by_last_action(updates.any?) 281 | end 282 | 283 | protected 284 | 285 | def lvm_options 286 | new_resource.ignore_skipped_cluster ? { additional_arguments: '--ignoreskippedcluster' } : {} 287 | end 288 | 289 | def install_filesystem_deps 290 | if platform_family?('suse') && /^ext/.match(new_resource.filesystem) 291 | Chef::Log.debug('Installing e2fsprogs to create the filesystem') 292 | package "e2fsprogs package for #{new_resource.name}" do # make unique for Chef 12 cloning warnings 293 | package_name 'e2fsprogs' 294 | end 295 | else 296 | Chef::Log.debug('Not installing any packages to configure the filesystem') 297 | end 298 | end 299 | 300 | def thin_volume? 301 | false 302 | end 303 | 304 | def create_command 305 | size = 306 | case new_resource.size 307 | when /\d+[kKmMgGtT]/ 308 | "--size #{new_resource.size}" 309 | when /(\d{1,2}|100)%(FREE|VG|PVS)/ 310 | "--extents #{new_resource.size}" 311 | when /(\d+)/ 312 | "--extents #{$1}" # rubocop:disable Style/PerlBackrefs 313 | end 314 | 315 | stripes = new_resource.stripes ? "--stripes #{new_resource.stripes}" : '' 316 | stripe_size = new_resource.stripe_size ? "--stripesize #{new_resource.stripe_size}" : '' 317 | mirrors = new_resource.mirrors ? "--mirrors #{new_resource.mirrors}" : '' 318 | contiguous = new_resource.contiguous ? '--contiguous y' : '' 319 | readahead = new_resource.readahead ? "--readahead #{new_resource.readahead}" : '' 320 | yes_flag = new_resource.wipe_signatures == true ? '--yes' : '-qq' 321 | lv_params = new_resource.lv_params 322 | name = new_resource.name 323 | group = new_resource.group 324 | physical_volumes = [new_resource.physical_volumes].flatten.join ' ' if new_resource.physical_volumes 325 | 326 | "lvcreate #{size} #{stripes} #{stripe_size} #{mirrors} #{contiguous} #{readahead} #{lv_params} --name #{name} #{group} #{physical_volumes} #{yes_flag}" 327 | end 328 | 329 | def resize_command(lv_size_req) 330 | name = new_resource.name 331 | group = new_resource.group 332 | device_name = "/dev/mapper/#{to_dm_name(group)}-#{to_dm_name(name)}" 333 | resize_fs = 334 | case new_resource.filesystem 335 | when /raw/i 336 | '' 337 | else 338 | '--resizefs' 339 | end 340 | stripes = new_resource.stripes ? "--stripes #{new_resource.stripes}" : '' 341 | stripe_size = new_resource.stripe_size ? "--stripesize #{new_resource.stripe_size}" : '' 342 | mirrors = new_resource.mirrors ? "--mirrors #{new_resource.mirrors}" : '' 343 | lv_params = new_resource.lv_params 344 | 345 | "lvextend -l #{lv_size_req} #{resize_fs} #{stripes} #{stripe_size} #{mirrors} #{device_name} #{lv_params}" 346 | end 347 | 348 | def remove_command 349 | lv_params = new_resource.lv_params 350 | name = new_resource.name 351 | group = new_resource.group 352 | 353 | # this version will only support handling logical volumes that were created by this cookbook - conforming to the naming convention of this cookbook 354 | # a future enhancement should allow to optionally delete based on a user-specified device_name 355 | device_name = "/dev/mapper/#{to_dm_name(group)}-#{to_dm_name(name)}" 356 | 357 | "lvremove #{device_name} #{lv_params} --force" 358 | end 359 | 360 | private 361 | 362 | # Converts the device name to the dm name format 363 | # 364 | # The device mapper will double any hyphens found in a volume group or 365 | # logical volume name so that it can properly locate the separator between 366 | # the volume group and the logical volume in the device name. 367 | # 368 | # @param name [String] the name to map 369 | # 370 | # @return [String] the mapped dm name 371 | # 372 | def to_dm_name(name) 373 | name.gsub(/-/, '--') 374 | end 375 | 376 | # Checks if the device is formatted with the given file system type 377 | # 378 | # @param device_name [String] the device name 379 | # @param fs_type [String] the file system type 380 | # 381 | # @return [Boolean] whether the device is formatted with the given file 382 | # system type or not 383 | # 384 | def device_formatted?(device_name, fs_type) 385 | Chef::Log.debug "Checking to see if #{device_name} is formatted..." 386 | # Do not raise when there is an error in running the blkid command. If the exitstatus is not 0, 387 | # the device is perhaps not formatted. 388 | blkid = shell_out("blkid #{device_name}") 389 | blkid.exitstatus == 0 && blkid.stdout.strip.include?(fs_type.strip) 390 | end 391 | end 392 | end 393 | end 394 | -------------------------------------------------------------------------------- /libraries/provider_lvm_thin_pool.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: provider_lvm_thin_pool 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require_relative 'provider_lvm_logical_volume' 21 | 22 | class Chef 23 | class Provider 24 | # The provider for lvm_thin_pool resource 25 | # 26 | class LvmThinPool < Chef::Provider::LvmLogicalVolume 27 | # Loads the current resource attributes 28 | # 29 | # @return [Chef::Resource::LvmThinPool] the lvm_logical_volume resource 30 | # 31 | def load_current_resource 32 | @current_resource ||= Chef::Resource::LvmThinPool.new(@new_resource.name) 33 | @current_resource 34 | end 35 | 36 | action :create do 37 | super() 38 | process_thin_volumes(:create) 39 | end 40 | 41 | action :resize do 42 | super() 43 | process_thin_volumes(:resize) 44 | end 45 | 46 | protected 47 | 48 | def create_command 49 | super.sub('--name', '--thinpool') 50 | end 51 | 52 | private 53 | 54 | def process_thin_volumes(action) 55 | updates = [] 56 | new_resource.thin_volumes.each do |tv| 57 | tv.group new_resource.group 58 | tv.pool new_resource.name 59 | tv.run_action action 60 | updates << tv.updated? 61 | end 62 | new_resource.updated_by_last_action(updates.any?) 63 | end 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /libraries/provider_lvm_thin_pool_meta_data.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: provider_lvm_thin_pool_meta_data 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/provider' 21 | require 'chef/dsl/recipe' 22 | require File.join(File.dirname(__FILE__), 'lvm') 23 | 24 | class Chef 25 | class Provider 26 | # The provider for lvm_thin_volume resource 27 | # 28 | class LvmThinPoolMetaData < Chef::Provider 29 | include Chef::DSL::Recipe 30 | include LVMCookbook 31 | 32 | # Loads the current resource attributes 33 | # 34 | # @return [Chef::Resource::LvmThinPoolMetaData] the lvm_thin_pool_meta_data resource 35 | # 36 | def load_current_resource 37 | @current_resource ||= Chef::Resource::LvmThinPoolMetaData.new(@new_resource.name) 38 | @current_resource 39 | end 40 | 41 | action :resize do 42 | require_lvm_gems 43 | lvm = LVM::LVM.new 44 | name = new_resource.name 45 | group = new_resource.group 46 | pool = new_resource.pool 47 | vg = lvm.volume_groups[group] 48 | 49 | # if doing a resize make sure that the volume exists before doing anything 50 | raise("Error volume group #{group} does not exist") if vg.nil? 51 | 52 | lv = vg.logical_volumes.select do |lvs| 53 | lvs.name == pool 54 | end 55 | 56 | # make sure that the thin pool / volume specified exists in the VG specified. 57 | raise("Error logical volume (thin pool) #{pool} does not exist") if lv.empty? 58 | 59 | lv_metadata = vg.logical_volumes.select do |lvs| 60 | lvs.metadata_lv == "[#{name}]" 61 | end 62 | 63 | # make sure that the thin pool metadata specified exists in the VG specified 64 | raise("Error logical volume thin pool metadata volume #{name} does not exist") if lv_metadata.empty? 65 | 66 | lv_metadata = lv_metadata.first 67 | pe_size = vg.extent_size.to_i 68 | lv_metadata_size_cur = lv_metadata.metadata_size.to_i / pe_size 69 | 70 | lv_metadata_size = new_resource.size 71 | lv_metadata_size_req = case lv_metadata_size 72 | when /^(\d+)(k|K)$/ 73 | (Regexp.last_match[1].to_i * 1024) / pe_size 74 | when /^(\d+)(m|M)$/ 75 | (Regexp.last_match[1].to_i * 1_048_576) / pe_size 76 | when /^(\d+)(g|G)$/ 77 | (Regexp.last_match[1].to_i * 1_073_741_824) / pe_size 78 | when /^(\d+)(t|T)$/ 79 | (Regexp.last_match[1].to_i * 1_099_511_627_776) / pe_size 80 | when /^(\d+)$/ 81 | Regexp.last_match[1].to_i 82 | else 83 | raise("Invalid size #{Regexp.last_match[1]} for lvm resize") 84 | end 85 | 86 | if lv_metadata_size_cur >= lv_metadata_size_req 87 | Chef::Log.debug "Logical volume thin pool metadata #{lv_metadata.name} in volume group #{group} already at requested size" 88 | else 89 | command = resize_command(new_resource.size) 90 | Chef::Log.debug "Running command: #{command}" 91 | output = lvm.raw command 92 | Chef::Log.debug "Command output: #{output}" 93 | # broadcast that we did a resize 94 | new_resource.updated_by_last_action true 95 | end 96 | end 97 | 98 | protected 99 | 100 | def resize_command(lv_size_req) 101 | group = new_resource.group 102 | pool = new_resource.pool 103 | "lvextend --poolmetadatasize #{lv_size_req} #{group}/#{pool}" 104 | end 105 | end 106 | end 107 | end 108 | -------------------------------------------------------------------------------- /libraries/provider_lvm_thin_volume.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: provider_lvm_thin_volume 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require_relative 'provider_lvm_logical_volume' 21 | 22 | class Chef 23 | class Provider 24 | # The provider for lvm_thin_volume resource 25 | # 26 | class LvmThinVolume < Chef::Provider::LvmLogicalVolume 27 | # Loads the current resource attributes 28 | # 29 | # @return [Chef::Resource::LvmThinVolume] the lvm_logical_volume resource 30 | # 31 | def load_current_resource 32 | @current_resource ||= Chef::Resource::LvmThinVolume.new(@new_resource.name) 33 | @current_resource 34 | end 35 | 36 | protected 37 | 38 | def thin_volume? 39 | true 40 | end 41 | 42 | def create_command 43 | size = "--virtualsize #{new_resource.size}" 44 | lv_params = new_resource.lv_params 45 | name = new_resource.name 46 | group = new_resource.group 47 | pool = new_resource.pool 48 | 49 | "lvcreate #{size} #{lv_params} --thin --name #{name} #{group}/#{pool}" 50 | end 51 | 52 | def resize_command(lv_size_req) 53 | name = new_resource.name 54 | group = new_resource.group 55 | device_name = "/dev/mapper/#{to_dm_name(group)}-#{to_dm_name(name)}" 56 | resize_fs = '--resizefs' 57 | 58 | "lvextend -l #{lv_size_req} #{resize_fs} #{device_name}" 59 | end 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /libraries/provider_lvm_volume_group.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: provider_lvm_volume_group 4 | # 5 | # Copyright:: 2009-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/provider' 21 | require 'chef/dsl/recipe' 22 | require File.join(File.dirname(__FILE__), 'lvm') 23 | 24 | class Chef 25 | class Provider 26 | # The provider for lvm_volume_group resource 27 | # 28 | class LvmVolumeGroup < Chef::Provider 29 | include Chef::DSL::Recipe 30 | include LVMCookbook 31 | 32 | # Loads the current resource attributes 33 | # 34 | # @return [Chef::Resource::LvmVolumeGroup] the lvm_volume_group resource 35 | # 36 | def load_current_resource 37 | @current_resource ||= Chef::Resource::LvmVolumeGroup.new(@new_resource.name) 38 | @current_resource 39 | end 40 | 41 | # The create action 42 | # 43 | action :create do 44 | require_lvm_gems 45 | name = new_resource.name 46 | physical_volume_list = [new_resource.physical_volumes].flatten 47 | 48 | # Make sure any pvs are not being used as filesystems (e.g. ephemeral0 on 49 | # AWS is always mounted at /mnt as an ext3 fs). 50 | # 51 | create_mount_resource(physical_volume_list) 52 | 53 | # The notifications should be set if the lvm_volume_group or any of its sub lvm_logical_volume resources are 54 | # updated. 55 | 56 | lvm = LVM::LVM.new(lvm_options) 57 | # Create the volume group 58 | create_volume_group(lvm, physical_volume_list, name) 59 | 60 | # Create the logical volumes specified as sub-resources 61 | create_logical_volumes 62 | end 63 | 64 | # The extend action 65 | # 66 | action :extend do 67 | require_lvm_gems 68 | name = new_resource.name 69 | physical_volume_list = [new_resource.physical_volumes].flatten 70 | lvm = LVM::LVM.new(lvm_options) 71 | 72 | # verify that the volume group is valid 73 | raise("VG #{name} is not a valid volume group") if lvm.volume_groups[name].nil? 74 | 75 | # get uuid of the volume group so we can compare it to the VG the PV belongs to 76 | vg_uuid = lvm.volume_groups[name].uuid 77 | 78 | pvs_to_add = [] 79 | physical_volume_list.each do |pv_name| 80 | pv = lvm.physical_volumes[pv_name] 81 | 82 | # get the uuid of the VG the PV belongs to if it exists 83 | # if we get "nil" then the PV does not belong to a VG 84 | # per the vgextend man page the pv will be initalized if it isn't already pv 85 | pv_vg_uuid = pv.nil? ? nil : pv.vg_uuid 86 | if pv_vg_uuid.nil? 87 | pvs_to_add.push pv_name 88 | else 89 | # raise an error if we attempt to add a PV that is already a member of a VG 90 | raise("PV #{pv} is already a member of another volume group. Cannot add to #{name}") unless pv_vg_uuid == vg_uuid 91 | end 92 | end 93 | 94 | return if pvs_to_add.empty? 95 | command = "vgextend #{name} #{pvs_to_add.join(' ')}" 96 | Chef::Log.debug "Executing lvm command: '#{command}'" 97 | output = lvm.raw command 98 | Chef::Log.debug "Command output: '#{output}'" 99 | new_resource.updated_by_last_action(true) 100 | resize_logical_volumes 101 | end 102 | 103 | private 104 | 105 | def lvm_options 106 | new_resource.ignore_skipped_cluster ? { additional_arguments: '--ignoreskippedcluster' } : {} 107 | end 108 | 109 | def create_mount_resource(physical_volume_list) 110 | physical_volume_list.select { |pv| ::File.exist?(pv) }.each do |pv| 111 | # If the device is mounted, the mount point will be returned else nil will be returned. 112 | # mount_point is required by the mount resource for umount and disable actions. 113 | # 114 | mount_point = get_mount_point(pv) 115 | next if mount_point.nil? 116 | 117 | mount_resource = mount mount_point do 118 | device pv 119 | action :nothing 120 | end 121 | mount_resource.run_action(:umount) 122 | mount_resource.run_action(:disable) 123 | end 124 | end 125 | 126 | def create_volume_group(lvm, physical_volume_list, name) 127 | if lvm.volume_groups[name] 128 | Chef::Log.info "Volume group '#{name}' already exists. Not creating..." 129 | else 130 | physical_volumes = physical_volume_list.join(' ') 131 | physical_extent_size = new_resource.physical_extent_size ? "-s #{new_resource.physical_extent_size}" : '' 132 | yes_flag = new_resource.wipe_signatures == true ? '--yes' : '-qq' 133 | command = "vgcreate #{name} #{physical_extent_size} #{physical_volumes} #{yes_flag}" 134 | Chef::Log.debug "Executing lvm command: '#{command}'" 135 | output = lvm.raw command 136 | Chef::Log.debug "Command output: '#{output}'" 137 | new_resource.updated_by_last_action(true) 138 | end 139 | end 140 | 141 | def create_logical_volumes 142 | updates = [] 143 | new_resource.logical_volumes.each do |lv| 144 | lv.group new_resource.name 145 | lv.run_action :create 146 | updates << lv.updated? 147 | end 148 | new_resource.updated_by_last_action(updates.any?) 149 | end 150 | 151 | def resize_logical_volumes 152 | updates = [] 153 | new_resource.logical_volumes.each do |lv| 154 | lv.group new_resource.name 155 | lv.run_action :resize 156 | updates << lv.updated? 157 | end 158 | new_resource.updated_by_last_action(updates.any?) 159 | end 160 | 161 | # Obtains the mount point of a device and returns nil if the device is not mounted 162 | # 163 | # @param device [String] the physical device 164 | # 165 | # @return [String] the mount point of the device if mounted and nil otherwise 166 | # 167 | def get_mount_point(device) 168 | mount_point = nil 169 | shell_out!('mount').stdout.each_line do |line| 170 | matched = line.match(/#{Regexp.escape(device)}\s+on\s+(.*)\s+type.*/) 171 | # If a match is found in the mount, obtain the mount point and return it 172 | unless matched.nil? 173 | mount_point = matched[1] 174 | break 175 | end 176 | end 177 | mount_point 178 | end 179 | end 180 | end 181 | end 182 | -------------------------------------------------------------------------------- /libraries/resource_lvm_logical_volume.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: resource_lvm_logical_volume 4 | # 5 | # Copyright:: 2009-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | require_relative 'base_resource_logical_volume' 22 | 23 | class Chef 24 | class Resource 25 | # The lvm_logical_volume resource 26 | # 27 | class LvmLogicalVolume < Chef::Resource::BaseLogicalVolume 28 | provides :lvm_logical_volume 29 | 30 | default_action :create 31 | allowed_actions :create, :resize, :remove 32 | 33 | # Initializes the lvm_logical_volume resource 34 | # 35 | # @param name [String] name of the resource 36 | # @param run_context [Chef::RunContext] the run context of chef run 37 | # 38 | # @return [Chef::Resource::LvmLogicalVolume] the lvm_logical_volume resource 39 | # 40 | def initialize(name, run_context = nil) 41 | super 42 | @provider = Chef::Provider::LvmLogicalVolume 43 | end 44 | 45 | # Attribute: physical_volumes - list of physical volumes to be used for creation 46 | # 47 | # @param arg [String, Array] - list of physical devices 48 | # 49 | # @return [String, Array] - list of physical devices 50 | # 51 | def physical_volumes(arg = nil) 52 | set_or_return( 53 | :physical_volumes, 54 | arg, 55 | kind_of: [String, Array] 56 | ) 57 | end 58 | 59 | # Attribute: stripes - number of stripes for the volume 60 | # 61 | # @param arg [String] number of stripes 62 | # 63 | # @return [String] number of stripes 64 | # 65 | def stripes(arg = nil) 66 | set_or_return( 67 | :stripes, 68 | arg, 69 | kind_of: Integer, 70 | callbacks: { 71 | 'must be greater than 0' => proc { |value| value > 0 }, 72 | } 73 | ) 74 | end 75 | 76 | # Attribute: stripe_size - the stripe size 77 | # 78 | # @param arg [String] the stripe size 79 | # 80 | # @return [String] the stripe size 81 | # 82 | def stripe_size(arg = nil) 83 | set_or_return( 84 | :stripe_size, 85 | arg, 86 | kind_of: Integer, 87 | callbacks: { 88 | 'must be a power of 2' => proc { |value| (Math.log2(value) % 1) == 0 }, 89 | } 90 | ) 91 | end 92 | 93 | # Attribute: mirrors - number of mirrors for the volume 94 | # 95 | # @param arg [Integer] number of mirrors 96 | # 97 | # @return [Integer] number of mirrors 98 | # 99 | def mirrors(arg = nil) 100 | set_or_return( 101 | :mirrors, 102 | arg, 103 | kind_of: Integer, 104 | callbacks: { 105 | 'must be greater than 0' => proc { |value| value > 0 }, 106 | } 107 | ) 108 | end 109 | 110 | # Attribute: contiguous - whether to use contiguous allocation policy 111 | # 112 | # @param arg [Boolean] whether to use contiguous allocation policy 113 | # 114 | # @return [Boolean] the contiguous allocation policy setting 115 | # 116 | def contiguous(arg = nil) 117 | set_or_return( 118 | :contiguous, 119 | arg, 120 | kind_of: [TrueClass, FalseClass] 121 | ) 122 | end 123 | 124 | # Attribute: readahead - the read ahead sector count of the logical volume 125 | # 126 | # @param arg [Integer, String] the read ahead sector count 127 | # 128 | # @return [Integer, String] the read ahead sector count 129 | # 130 | def readahead(arg = nil) 131 | set_or_return( 132 | :readahead, 133 | arg, 134 | kind_of: [Integer, String], 135 | equal_to: [2..120, 'auto', 'none'].flatten! 136 | ) 137 | end 138 | 139 | # Attribute: take_up_free_space - whether to have the LV take up the remainder of free space on the VG 140 | # 141 | # @param arg [Boolean] whether to have the LV take up the remainder of free space 142 | # 143 | # @return [Boolean] if the LV should take the remainder of free space 144 | # 145 | def take_up_free_space(arg = nil) 146 | set_or_return( 147 | :take_up_free_space, 148 | arg, 149 | kind_of: [TrueClass, FalseClass] 150 | ) 151 | end 152 | 153 | # Attribute: wipe_signature - 154 | # 155 | # @param arg [Boolean] whether to automatically wipe any preexisting signatures 156 | # 157 | # @return [Boolean] the wipe_signature setting 158 | # 159 | def wipe_signatures(arg = nil) 160 | set_or_return( 161 | :wipe_signatures, 162 | arg, 163 | kind_of: [TrueClass, FalseClass], 164 | default: false 165 | ) 166 | end 167 | 168 | # Attribute: ignore_skipped_cluster - 169 | # 170 | # @param arg [Boolean] whether to ignore skipped cluster VGs during LVM commands 171 | # 172 | # @return [Boolean] the ignore_skipped_cluster setting 173 | # 174 | def ignore_skipped_cluster(arg = nil) 175 | set_or_return( 176 | :ignore_skipped_cluster, 177 | arg, 178 | kind_of: [TrueClass, FalseClass], 179 | default: false 180 | ) 181 | end 182 | 183 | # Attribute: remove_mount_point - whether to remove the mount location/directory 184 | # 185 | # @param arg [Boolean] whether to have the resource clean up/delete the mount location/directory 186 | # 187 | # @return [Boolean] if the mount location should be cleaned up/deleted 188 | # 189 | def remove_mount_point(arg = nil) 190 | set_or_return( 191 | :remove_mount_point, 192 | arg, 193 | kind_of: [TrueClass, FalseClass] 194 | ) 195 | end 196 | end 197 | end 198 | end 199 | -------------------------------------------------------------------------------- /libraries/resource_lvm_thin_pool.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: resource_lvm_thin_pool 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | require_relative 'resource_lvm_logical_volume' 22 | 23 | class Chef 24 | class Resource 25 | # The lvm_thin_pool resource 26 | # 27 | # A thin pool is a logical volume that can contain thin volumes (which are also logical volumes but are "thin") 28 | class LvmThinPool < Chef::Resource::LvmLogicalVolume 29 | provides :lvm_thin_pool 30 | 31 | # Thin Logical volumes to be created in the thin pool 32 | attr_reader :thin_volumes 33 | 34 | def initialize(name, run_context = nil) 35 | super 36 | @provider = Chef::Provider::LvmThinPool 37 | @thin_volumes = [] 38 | end 39 | 40 | # A shortcut for creating a thin volume (which is just a special type of logical volume) when creating the thin pool 41 | # 42 | # @param name [String] the name of the thin volume 43 | # @param block [Proc] the block defining the lvm_thin_volume resource 44 | # 45 | # @return [Chef::Resource::LvmThinVolume] the lvm_thin_volume resource 46 | # 47 | def thin_volume(name, &block) 48 | volume = lvm_thin_volume(name, &block) 49 | volume.action :nothing 50 | @thin_volumes << volume 51 | volume 52 | end 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /libraries/resource_lvm_thin_pool_meta_data.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: resource_lvm_thin_pool_meta_data 4 | # 5 | # Copyright:: 2016-2019, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | require_relative 'base_resource_logical_volume' 22 | 23 | class Chef 24 | class Resource 25 | # The lvm_thin_pool_meta_data resource 26 | # 27 | # A thin pool metadata is a thin pool's metadata logical volume 28 | class LvmThinPoolMetaData < Chef::Resource::BaseLogicalVolume 29 | provides :lvm_thin_pool_meta_data 30 | 31 | default_action :resize 32 | allowed_actions :resize 33 | 34 | # Initializes the lvm_thin_pool_meta_data resource 35 | # 36 | # @param name [String] name of the resource 37 | # @param run_context [Chef::RunContext] the run context of chef run 38 | # 39 | # @return [Chef::Resource::LvmThinPoolMetaData] the lvm_thin_pool_meta_data resource 40 | # 41 | def initialize(name, run_context = nil) 42 | super 43 | @provider = Chef::Provider::LvmThinPoolMetaData 44 | end 45 | 46 | # Attribute: pool - The name of the thin pool logical volume in which this metadata volume exist 47 | # 48 | # @param arg [String] The name of the thin pool logical volume in which this metadata volume exist 49 | # 50 | # @return [String] The name of the thin pool logical volume in which this metadata volume exist 51 | # 52 | def pool(arg = nil) 53 | set_or_return( 54 | :pool, 55 | arg, 56 | kind_of: String, 57 | required: true 58 | ) 59 | end 60 | 61 | # Attribute: size - the size of thin pool metadata logical volume 62 | # 63 | # @param arg [String] the size of thin pool metadata logical volume 64 | # 65 | # @return [String] the size of thin pool metadata logical volume 66 | # 67 | def size(arg = nil) 68 | set_or_return( 69 | :size, 70 | arg, 71 | kind_of: String, 72 | regex: /^(\d+[kKmMgGtT]|\d+)$/, 73 | required: true 74 | ) 75 | end 76 | end 77 | end 78 | end 79 | -------------------------------------------------------------------------------- /libraries/resource_lvm_thin_volume.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: resource_lvm_thin_volume 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | require_relative 'base_resource_logical_volume' 22 | 23 | class Chef 24 | class Resource 25 | # The lvm_thin_volume resource 26 | # 27 | # A thin pool is a logical volume that can contain thin volumes (which are also logical volumes but are "thin") 28 | class LvmThinVolume < Chef::Resource::BaseLogicalVolume 29 | provides :lvm_thin_volume 30 | 31 | default_action :create 32 | allowed_actions :create, :resize 33 | 34 | # Initializes the lvm_logical_volume resource 35 | # 36 | # @param name [String] name of the resource 37 | # @param run_context [Chef::RunContext] the run context of chef run 38 | # 39 | # @return [Chef::Resource::LvmLogicalVolume] the lvm_logical_volume resource 40 | # 41 | def initialize(name, run_context = nil) 42 | super 43 | @provider = Chef::Provider::LvmThinVolume 44 | end 45 | 46 | # Attribute: size - size of the logical volume 47 | # 48 | # @param arg [String] the size of the logical volume 49 | # 50 | # @return [String] the size of the logical volume 51 | # 52 | def size(arg = nil) 53 | set_or_return( 54 | :size, 55 | arg, 56 | kind_of: String, 57 | regex: /^(\d+[kKmMgGtT]|\d+)$/, 58 | required: true 59 | ) 60 | end 61 | 62 | # Attribute: pool - The name of the thin pool logical volume in which this thin volume will be created 63 | # 64 | # @param arg [String] The name of the thin pool logical volume in which this thin volume will be created 65 | # 66 | # @return [String] The name of the thin pool logical volume in which this thin volume will be created 67 | # 68 | def pool(arg = nil) 69 | set_or_return( 70 | :pool, 71 | arg, 72 | kind_of: String, 73 | required: true 74 | ) 75 | end 76 | 77 | # Attribute: ignore_skipped_cluster - 78 | # 79 | # @param arg [Boolean] whether to ignore skipped cluster VGs during LVM commands 80 | # 81 | # @return [Boolean] the ignore_skipped_cluster setting 82 | # 83 | def ignore_skipped_cluster(arg = nil) 84 | set_or_return( 85 | :ignore_skipped_cluster, 86 | arg, 87 | kind_of: [TrueClass, FalseClass], 88 | default: false 89 | ) 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /libraries/resource_lvm_volume_group.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Library:: resource_lvm_volume_group 4 | # 5 | # Copyright:: 2009-2017, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | require 'chef/resource' 21 | 22 | class Chef 23 | class Resource 24 | # The lvm_volume_group resource 25 | # 26 | class LvmVolumeGroup < Chef::Resource 27 | include Chef::DSL::Recipe 28 | 29 | provides :lvm_volume_group 30 | 31 | unified_mode true if respond_to?(:unified_mode) 32 | 33 | default_action :create 34 | allowed_actions :create, :extend 35 | 36 | # Logical volumes to be created in the volume group 37 | attr_reader :logical_volumes 38 | 39 | # Initializes the lvm_volume_group resource 40 | # 41 | # @param name [String] name of the resource 42 | # @param run_context [Chef::RunContext] the run context of chef run 43 | # 44 | # @return [Chef::Resource::LvmVolumeGroup] the lvm_volume_group resource 45 | # 46 | def initialize(name, run_context = nil) 47 | super 48 | @logical_volumes = [] 49 | @provider = Chef::Provider::LvmVolumeGroup 50 | end 51 | 52 | # Attribute: name - name of the volume group 53 | # 54 | # @param arg [String] the name of the volume group 55 | # 56 | # @return [String] the name of the volume group 57 | # 58 | def name(arg = nil) 59 | set_or_return( 60 | :name, 61 | arg, 62 | kind_of: String, 63 | name_attribute: true, 64 | regex: /[\w+.-]+/, 65 | required: true, 66 | callbacks: { 67 | "cannot be '.' or '..'" => proc do |value| 68 | !(value == '.' || value == '..') 69 | end, 70 | } 71 | ) 72 | end 73 | 74 | # Attribute: physical_volumes - list of physical devices this volume group should be restricted to 75 | # 76 | # @param arg [Array, String] list of physical devices 77 | # 78 | # @return [String] list of physical devices 79 | # 80 | def physical_volumes(arg = nil) 81 | set_or_return( 82 | :physical_volumes, 83 | arg, 84 | kind_of: [Array, String], 85 | required: true 86 | ) 87 | end 88 | 89 | # Attribute: physical_extent_size - the physical_extent_size 90 | # 91 | # @param arg [String] the physical extent size 92 | # 93 | # @return [String] the physical extent size 94 | # 95 | def physical_extent_size(arg = nil) 96 | set_or_return( 97 | :physical_extent_size, 98 | arg, 99 | kind_of: String, 100 | regex: /\d+[bBsSkKmMgGtTpPeE]?/ 101 | ) 102 | end 103 | 104 | # A shortcut for creating a logical volume when creating the volume group 105 | # 106 | # @param name [String] the name of the logical volume 107 | # @param block [Proc] the block defining the lvm_logical_volume resource 108 | # 109 | # @return [Chef::Resource::LvmLogicalVolume] the lvm_logical_volume resource 110 | # 111 | def logical_volume(name, &block) 112 | Chef::Log.debug "Creating logical volume #{name}" 113 | volume = lvm_logical_volume(name, &block) 114 | volume.action :nothing 115 | @logical_volumes << volume 116 | volume 117 | end 118 | 119 | # Attribute: wipe_signature - 120 | # 121 | # @param arg [Boolean] whether to automatically wipe any preexisting signatures 122 | # 123 | # @return [Boolean] the wipe_signature setting 124 | # 125 | def wipe_signatures(arg = nil) 126 | set_or_return( 127 | :wipe_signatures, 128 | arg, 129 | kind_of: [TrueClass, FalseClass], 130 | default: false 131 | ) 132 | end 133 | 134 | # A shortcut for creating a thin pool (which is just a special type of logical volume) when creating the volume group 135 | # 136 | # @param name [String] the name of the thin pool 137 | # @param block [Proc] the block defining the lvm_thin_pool resource 138 | # 139 | # @return [Chef::Resource::LvmThinPool] the lvm_thin_pool resource 140 | # 141 | def thin_pool(name, &block) 142 | volume = lvm_thin_pool(name, &block) 143 | volume.action :nothing 144 | @logical_volumes << volume 145 | volume 146 | end 147 | 148 | # Attribute: ignore_skipped_cluster - 149 | # 150 | # @param arg [Boolean] whether to ignore skipped cluster VGs during LVM commands 151 | # 152 | # @return [Boolean] the ignore_skipped_cluster setting 153 | # 154 | def ignore_skipped_cluster(arg = nil) 155 | set_or_return( 156 | :ignore_skipped_cluster, 157 | arg, 158 | kind_of: [TrueClass, FalseClass], 159 | default: false 160 | ) 161 | end 162 | end 163 | end 164 | end 165 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'lvm' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | license 'Apache-2.0' 5 | description 'Installs and manages Logical Volume Manager' 6 | version '6.2.2' 7 | source_url 'https://github.com/sous-chefs/lvm' 8 | issues_url 'https://github.com/sous-chefs/lvm/issues' 9 | chef_version '>= 15.3' 10 | 11 | supports 'amazon' 12 | supports 'centos' 13 | supports 'fedora' 14 | supports 'freebsd' 15 | supports 'opensuseleap' 16 | supports 'oracle' 17 | supports 'redhat' 18 | supports 'scientific' 19 | supports 'suse' 20 | supports 'ubuntu' 21 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: lvm 3 | # Recipe:: default 4 | # 5 | # Copyright:: 2009-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | package 'lvm2' 21 | 22 | package 'thin-provisioning-tools' if platform_family?('debian') 23 | 24 | # Start+Enable the lvmetad service on RHEL7, it is required by default 25 | # but not automatically started 26 | if platform_family?('rhel') && node['platform_version'].to_i >= 7 && !platform?('amazon') 27 | service 'lvm2-lvmetad' do 28 | action [:enable, :start] 29 | provider Chef::Provider::Service::Systemd 30 | only_if '/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1' 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "groupName": "Actions", 7 | "matchUpdateTypes": ["minor", "patch", "pin"], 8 | "automerge": true, 9 | "addLabels": ["Release: Patch", "Skip: Announcements"] 10 | }, 11 | { 12 | "groupName": "Actions", 13 | "matchUpdateTypes": ["major"], 14 | "automerge": false, 15 | "addLabels": ["Release: Patch", "Skip: Announcements"] 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /resources/physical_volume.rb: -------------------------------------------------------------------------------- 1 | unified_mode true 2 | 3 | property :volume_name, 4 | String, 5 | name_property: true 6 | 7 | property :wipe_signatures, 8 | [true, false], 9 | default: false, 10 | description: 'Whether to automatically wipe any preexisting signatures' 11 | 12 | property :ignore_skipped_cluster, 13 | [true, false], 14 | default: false, 15 | description: 'Whether to ignore skipped cluster VGs during LVM commands' 16 | 17 | action :create do 18 | require_lvm_gems 19 | lvm = LVM::LVM.new(lvm_options) 20 | if lvm.physical_volumes[new_resource.name].nil? 21 | yes_flag = new_resource.wipe_signatures == true ? '--yes' : '-qq' 22 | 23 | converge_by("creating physical volume '#{new_resource.name}'") do 24 | lvm.raw "pvcreate #{new_resource.name} #{yes_flag}" 25 | end 26 | end 27 | end 28 | 29 | action :resize do 30 | require_lvm_gems 31 | lvm = LVM::LVM.new(lvm_options) 32 | pv = lvm.physical_volumes.select do |pvs| 33 | pvs.name == new_resource.name 34 | end 35 | if !pv.empty? 36 | # get the size the OS says the block device is 37 | block_device_raw_size = pv[0].dev_size.to_i 38 | # get the size LVM thinks the PV is 39 | pv_size = pv[0].size.to_i 40 | pe_size = pv_size / pv[0].pe_count 41 | 42 | # get the amount of space that cannot be allocated 43 | non_allocatable_space = block_device_raw_size % pe_size 44 | # if it's an exact amount LVM appears to just take 1 full extent 45 | non_allocatable_space = pe_size if non_allocatable_space == 0 46 | 47 | block_device_allocatable_size = block_device_raw_size - non_allocatable_space 48 | 49 | # only resize if they are not same 50 | if pv_size != block_device_allocatable_size 51 | converge_by("Resizing physical volume '#{new_resource.name}'") do 52 | lvm.raw "pvresize #{new_resource.name}" 53 | end 54 | end 55 | else 56 | Chef::Log.debug "Physical volume '#{new_resource.name}' found. Not resizing..." 57 | end 58 | end 59 | 60 | action_class do 61 | include LVMCookbook 62 | 63 | def lvm_options 64 | new_resource.ignore_skipped_cluster ? { additional_arguments: '--ignoreskippedcluster' } : {} 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /spec/default_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'lvm::default on Ubuntu 20.04' do 4 | cached(:chef_run_ubuntu) do 5 | ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '20.04').converge('lvm::default') 6 | end 7 | 8 | it 'installs lvm2' do 9 | expect(chef_run_ubuntu).to install_package('lvm2') 10 | end 11 | 12 | it 'does not start or enable lvm2-lvmetad' do 13 | expect(chef_run_ubuntu).to_not start_service('lvm2-lvmetad') 14 | expect(chef_run_ubuntu).to_not enable_service('lvm2-lvmetad') 15 | end 16 | end 17 | 18 | describe 'lvm::default on RHEL 7' do 19 | cached(:chef_run_rhel) do 20 | ChefSpec::SoloRunner.new(platform: 'centos', version: '7').converge('lvm::default') 21 | end 22 | 23 | before(:each) do 24 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 25 | end 26 | 27 | it 'installs lvm2' do 28 | expect(chef_run_rhel).to install_package('lvm2') 29 | end 30 | 31 | it 'starts / enables lvm2-lvmetad' do 32 | expect(chef_run_rhel).to start_service('lvm2-lvmetad') 33 | expect(chef_run_rhel).to enable_service('lvm2-lvmetad') 34 | end 35 | end 36 | 37 | describe 'lvm::default on Amazon Linux' do 38 | cached(:chef_run_amazon) do 39 | ChefSpec::SoloRunner.new(platform: 'amazon', version: '2').converge('lvm::default') 40 | end 41 | 42 | before(:each) do 43 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 44 | end 45 | 46 | it 'installs lvm2' do 47 | expect(chef_run_amazon).to install_package('lvm2') 48 | end 49 | 50 | it 'does not start or enable lvm2-lvmetad' do 51 | expect(chef_run_amazon).to_not start_service('lvm2-lvmetad') 52 | expect(chef_run_amazon).to_not enable_service('lvm2-lvmetad') 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/lvm_test/create_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::create' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::create') 6 | end 7 | 8 | before do 9 | allow_any_instance_of(Chef::Recipe).to receive(:shell_out).and_call_original 10 | pvs = double('pvs', stdout: '1') 11 | allow_any_instance_of(Chef::Recipe).to receive(:shell_out).with('pvs | grep -c /dev/loop11').and_return(pvs) 12 | allow(File).to receive(:stat).and_call_original 13 | allow(File).to receive(:stat).with('/mnt/small').and_return(0100555) 14 | end 15 | 16 | context 'on Ubuntu 20.04' do 17 | let(:platform) { 'ubuntu' } 18 | let(:version) { '20.04' } 19 | 20 | it 'Create volume group' do 21 | expect(chef_run).to create_lvm_volume_group('vg-test') 22 | end 23 | 24 | it 'Extend volume group' do 25 | expect(chef_run).to extend_lvm_volume_group('vg-test') 26 | end 27 | 28 | it 'Create physical volume' do 29 | expect(chef_run).to create_lvm_physical_volume('/dev/loop10') 30 | end 31 | end 32 | 33 | context 'on RHEL 7' do 34 | let(:platform) { 'centos' } 35 | let(:version) { '7' } 36 | 37 | before(:each) do 38 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 39 | end 40 | 41 | it 'Create volume group' do 42 | expect(chef_run).to create_lvm_volume_group('vg-test') 43 | end 44 | 45 | it 'Extend volume group' do 46 | expect(chef_run).to extend_lvm_volume_group('vg-test') 47 | end 48 | 49 | it 'Create physical volume' do 50 | expect(chef_run).to create_lvm_physical_volume('/dev/loop10') 51 | end 52 | end 53 | 54 | context 'on Amazon Linux' do 55 | let(:platform) { 'amazon' } 56 | let(:version) { '2' } 57 | 58 | before(:each) do 59 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 60 | end 61 | 62 | it 'Create volume group' do 63 | expect(chef_run).to create_lvm_volume_group('vg-test') 64 | end 65 | 66 | it 'Extend volume group' do 67 | expect(chef_run).to extend_lvm_volume_group('vg-test') 68 | end 69 | 70 | it 'Create physical volume' do 71 | expect(chef_run).to create_lvm_physical_volume('/dev/loop10') 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /spec/lvm_test/create_thin_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::create_thin' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::create_thin') 6 | end 7 | 8 | before do 9 | pvs = double('pvs', stdout: '1') 10 | allow_any_instance_of(Chef::Recipe).to receive(:shell_out).with('pvs | grep -c /dev/loop1').and_return(pvs) 11 | allow(File).to receive(:stat).and_call_original 12 | allow(File).to receive(:stat).with('/mnt/small').and_return(0o100555) 13 | end 14 | 15 | context 'on Ubuntu 20.04' do 16 | let(:platform) { 'ubuntu' } 17 | let(:version) { '20.04' } 18 | 19 | it 'Create volume group' do 20 | expect(chef_run).to create_lvm_volume_group('vg-data') 21 | end 22 | 23 | it 'Create thin pool' do 24 | expect(chef_run).to create_lvm_thin_pool('lv-thin') 25 | end 26 | 27 | it 'Create thin volume' do 28 | expect(chef_run).to create_lvm_thin_volume('thin_vol_1') 29 | end 30 | end 31 | 32 | context 'on RHEL 7' do 33 | let(:platform) { 'centos' } 34 | let(:version) { '7' } 35 | 36 | before(:each) do 37 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 38 | end 39 | 40 | it 'Create volume group' do 41 | expect(chef_run).to create_lvm_volume_group('vg-data') 42 | end 43 | 44 | it 'Create thin pool' do 45 | expect(chef_run).to create_lvm_thin_pool('lv-thin') 46 | end 47 | 48 | it 'Create thin volume' do 49 | expect(chef_run).to create_lvm_thin_volume('thin_vol_1') 50 | end 51 | end 52 | 53 | context 'on Amazon Linux' do 54 | let(:platform) { 'amazon' } 55 | let(:version) { '2' } 56 | 57 | before(:each) do 58 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 59 | end 60 | 61 | it 'Create volume group' do 62 | expect(chef_run).to create_lvm_volume_group('vg-data') 63 | end 64 | 65 | it 'Create thin pool' do 66 | expect(chef_run).to create_lvm_thin_pool('lv-thin') 67 | end 68 | 69 | it 'Create thin volume' do 70 | expect(chef_run).to create_lvm_thin_volume('thin_vol_1') 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /spec/lvm_test/remove_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::remove' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::remove') 6 | end 7 | 8 | before do 9 | stub_command('/opt/chef/embedded/bin/gem list | grep "chef-ruby-lvm ""').and_return(true) 10 | stub_command('/opt/chef/embedded/bin/gem list | grep chef-ruby-lvm-attrib').and_return(true) 11 | allow_any_instance_of(Chef::Recipe).to receive(:shell_out).and_call_original 12 | pvs = double('pvs', stdout: '1') 13 | allow_any_instance_of(Chef::Recipe).to receive(:shell_out).with('pvs | grep -c /dev/loop1').and_return(pvs) 14 | allow(File).to receive(:stat).and_call_original 15 | allow(File).to receive(:stat).with('/mnt/small').and_return(0100555) 16 | end 17 | 18 | context 'on Ubuntu 20.04' do 19 | let(:platform) { 'ubuntu' } 20 | let(:version) { '20.04' } 21 | 22 | %w(loop10 loop11 loop12 loop13).each do |device| 23 | it "Create physical volume: #{device}" do 24 | expect(chef_run).to create_lvm_physical_volume("/dev/#{device}") 25 | end 26 | end 27 | 28 | it 'Create volume group' do 29 | expect(chef_run).to create_lvm_volume_group('vg-rmdata') 30 | end 31 | 32 | it 'Remove logical volume: rmlogs' do 33 | expect(chef_run).to remove_lvm_logical_volume('rmlogs') 34 | end 35 | 36 | it 'Remove logical volume: rmtest' do 37 | expect(chef_run).to remove_lvm_logical_volume('rmtest') 38 | end 39 | end 40 | 41 | context 'on RHEL 7' do 42 | let(:platform) { 'centos' } 43 | let(:version) { '7' } 44 | 45 | before(:each) do 46 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 47 | end 48 | 49 | %w(loop10 loop11 loop12 loop13).each do |device| 50 | it "Create physical volume: #{device}" do 51 | expect(chef_run).to create_lvm_physical_volume("/dev/#{device}") 52 | end 53 | end 54 | 55 | it 'Create volume group' do 56 | expect(chef_run).to create_lvm_volume_group('vg-rmdata') 57 | end 58 | 59 | it 'Remove logical volume: rmlogs' do 60 | expect(chef_run).to remove_lvm_logical_volume('rmlogs') 61 | end 62 | 63 | it 'Remove logical volume: rmtest' do 64 | expect(chef_run).to remove_lvm_logical_volume('rmtest') 65 | end 66 | end 67 | 68 | context 'on Amazon Linux' do 69 | let(:platform) { 'amazon' } 70 | let(:version) { '2' } 71 | 72 | before(:each) do 73 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 74 | end 75 | 76 | %w(loop10 loop11 loop12 loop13).each do |device| 77 | it "Create physical volume: #{device}" do 78 | expect(chef_run).to create_lvm_physical_volume("/dev/#{device}") 79 | end 80 | end 81 | 82 | it 'Create volume group' do 83 | expect(chef_run).to create_lvm_volume_group('vg-rmdata') 84 | end 85 | 86 | it 'Remove logical volume: rmlogs' do 87 | expect(chef_run).to remove_lvm_logical_volume('rmlogs') 88 | end 89 | 90 | it 'Remove logical volume: rmtest' do 91 | expect(chef_run).to remove_lvm_logical_volume('rmtest') 92 | end 93 | end 94 | end 95 | -------------------------------------------------------------------------------- /spec/lvm_test/resize_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::resize' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::resize') 6 | end 7 | 8 | context 'on Ubuntu 20.04' do 9 | let(:platform) { 'ubuntu' } 10 | let(:version) { '20.04' } 11 | 12 | it 'Resize physical volume' do 13 | expect(chef_run).to resize_lvm_physical_volume('/dev/loop10') 14 | end 15 | 16 | it 'Create logical volume' do 17 | expect(chef_run).to create_lvm_logical_volume('small_resize') 18 | end 19 | 20 | it 'Resize logical volume' do 21 | expect(chef_run).to resize_lvm_logical_volume('small_resize') 22 | end 23 | 24 | it 'Create RAW logical volume' do 25 | expect(chef_run).to create_lvm_logical_volume('small_resize_raw') 26 | end 27 | 28 | it 'Resize RAW logical volume' do 29 | expect(chef_run).to resize_lvm_logical_volume('small_resize_raw') 30 | end 31 | end 32 | 33 | context 'on RHEL 7' do 34 | let(:platform) { 'centos' } 35 | let(:version) { '7' } 36 | 37 | before(:each) do 38 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 39 | end 40 | 41 | it 'Resize physical volume' do 42 | expect(chef_run).to resize_lvm_physical_volume('/dev/loop10') 43 | end 44 | 45 | it 'Create small logical volume' do 46 | expect(chef_run).to create_lvm_logical_volume('small_resize') 47 | end 48 | 49 | it 'Resize logical volume' do 50 | expect(chef_run).to resize_lvm_logical_volume('small_resize') 51 | end 52 | 53 | it 'Create RAW logical volume' do 54 | expect(chef_run).to create_lvm_logical_volume('small_resize_raw') 55 | end 56 | 57 | it 'Resize RAW logical volume' do 58 | expect(chef_run).to resize_lvm_logical_volume('small_resize_raw') 59 | end 60 | end 61 | 62 | context 'on Amazon Linux' do 63 | let(:platform) { 'amazon' } 64 | let(:version) { '2' } 65 | 66 | before(:each) do 67 | stub_command('/sbin/lvm dumpconfig global/use_lvmetad | grep use_lvmetad=1').and_return(true) 68 | end 69 | 70 | it 'Resize physical volume' do 71 | expect(chef_run).to resize_lvm_physical_volume('/dev/loop10') 72 | end 73 | 74 | it 'Create small logical volume' do 75 | expect(chef_run).to create_lvm_logical_volume('small_resize') 76 | end 77 | 78 | it 'Resize logical volume' do 79 | expect(chef_run).to resize_lvm_logical_volume('small_resize') 80 | end 81 | 82 | it 'Create RAW logical volume' do 83 | expect(chef_run).to create_lvm_logical_volume('small_resize_raw') 84 | end 85 | 86 | it 'Resize RAW logical volume' do 87 | expect(chef_run).to resize_lvm_logical_volume('small_resize_raw') 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/lvm_test/resize_thin_pool_meta_data_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::resize_thin' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::resize_thin_pool_meta_data') 6 | end 7 | 8 | describe 'on Ubuntu 20.04' do 9 | let(:platform) { 'ubuntu' } 10 | let(:version) { '20.04' } 11 | 12 | it 'resizes logical volume' do 13 | expect(chef_run).to resize_lvm_thin_pool_meta_data('lv-thin_tmeta') 14 | end 15 | end 16 | 17 | describe 'on RHEL 7' do 18 | let(:platform) { 'centos' } 19 | let(:version) { '7' } 20 | 21 | it 'resizes logical volume' do 22 | expect(chef_run).to resize_lvm_thin_pool_meta_data('lv-thin_tmeta') 23 | end 24 | end 25 | 26 | describe 'on Amazon Linux' do 27 | let(:platform) { 'amazon' } 28 | let(:version) { '2' } 29 | 30 | it 'resizes logical volume' do 31 | expect(chef_run).to resize_lvm_thin_pool_meta_data('lv-thin_tmeta') 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/lvm_test/resize_thin_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::resize_thin' do 4 | let(:chef_run) do 5 | ChefSpec::SoloRunner.new(platform: platform, version: version).converge('test::resize_thin') 6 | end 7 | 8 | describe 'on Ubuntu 20.04' do 9 | let(:platform) { 'ubuntu' } 10 | let(:version) { '20.04' } 11 | 12 | it 'resizes logical volume' do 13 | expect(chef_run).to resize_lvm_thin_volume('thin_vol_1') 14 | end 15 | end 16 | 17 | describe 'on RHEL 7' do 18 | let(:platform) { 'centos' } 19 | let(:version) { '7' } 20 | 21 | it 'resizes logical volume' do 22 | expect(chef_run).to resize_lvm_thin_volume('thin_vol_1') 23 | end 24 | end 25 | 26 | describe 'on Amazon Linux' do 27 | let(:platform) { 'amazon' } 28 | let(:version) { '2' } 29 | 30 | it 'resizes logical volume' do 31 | expect(chef_run).to resize_lvm_thin_volume('thin_vol_1') 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/notify_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'test::test_notify' do 4 | let(:chef_run) do 5 | ChefSpec::ServerRunner.new(platform: 'centos', version: '7').converge(described_recipe) 6 | end 7 | 8 | it 'should allow resource notifications in chefspec' do 9 | vg_resource = chef_run.lvm_volume_group('notify_vg') 10 | lv_resource = chef_run.lvm_logical_volume('test_notify_lv') 11 | pv_resource = chef_run.lvm_physical_volume('/dev/test_notify_pv') 12 | [vg_resource, lv_resource, pv_resource].each do |resource| 13 | expect(resource).to notify('file[/tmp/test_notify]').to(:create).immediately 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | 4 | RSpec.configure do |config| 5 | config.color = true # Use color in STDOUT 6 | config.formatter = :documentation # Use the specified formatter 7 | config.log_level = :warn 8 | end 9 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'test' 2 | maintainer 'Sous Chefs' 3 | maintainer_email 'help@sous-chefs.org' 4 | license 'Apache-2.0' 5 | description 'A test cookbook for lvm' 6 | version '0.1.0' 7 | 8 | # The 'test' recipe loop_devices resource requires ruby 2.4.x to operate 9 | # therefore a minimum chef client needed is 13.0 10 | chef_version '>= 13.0' 11 | 12 | depends 'lvm' 13 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/create.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: create 4 | # 5 | # Copyright:: 2013-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | apt_update 'update' 21 | 22 | include_recipe 'lvm' 23 | 24 | # The test device to use 25 | devices = [ 26 | '/dev/loop10', 27 | '/dev/loop11', 28 | '/dev/loop12', 29 | '/dev/loop13', 30 | '/dev/loop14', 31 | '/dev/loop15', 32 | '/dev/loop16', 33 | '/dev/loop17', 34 | ] 35 | 36 | loop_devices 'loop_devices' do 37 | devices devices 38 | action :create 39 | end 40 | 41 | # Creates the physical device 42 | 43 | log 'Creating physical volume for test' 44 | devices.each do |device| 45 | lvm_physical_volume device 46 | end 47 | 48 | # Verify that the create action is idempotent 49 | lvm_physical_volume devices.first 50 | 51 | # Creates the volume group 52 | # 53 | lvm_volume_group 'vg-data' do 54 | physical_volumes ['/dev/loop10', '/dev/loop11', '/dev/loop12', '/dev/loop13'] 55 | 56 | logical_volume 'logs' do 57 | size '10M' 58 | filesystem 'ext2' 59 | mount_point location: '/mnt/logs', options: 'noatime,nodiratime' 60 | stripes 2 61 | end 62 | 63 | logical_volume 'home' do 64 | size '5M' 65 | filesystem 'ext2' 66 | mount_point '/mnt/home' 67 | stripes 1 68 | mirrors 2 69 | end 70 | end 71 | 72 | lvm_volume_group 'vg-test' do 73 | physical_volumes ['/dev/loop14', '/dev/loop15', '/dev/loop16'] 74 | end 75 | 76 | lvm_volume_group 'vg-test-extend' do 77 | action :extend 78 | name 'vg-test' 79 | physical_volumes ['/dev/loop14', '/dev/loop15', '/dev/loop16', '/dev/loop17'] 80 | end 81 | # Creates the logical volume 82 | # 83 | lvm_logical_volume 'test' do 84 | group 'vg-test' 85 | size '50%VG' 86 | filesystem 'ext3' 87 | mount_point '/mnt/test' 88 | ignore_skipped_cluster true 89 | end 90 | 91 | # Creates a small logical volume 92 | # 93 | lvm_logical_volume 'small' do 94 | group 'vg-test' 95 | size '2%VG' 96 | filesystem 'ext3' 97 | mount_point '/mnt/small' 98 | end 99 | 100 | # Set the directory attributes of the mounted volume 101 | # 102 | directory '/mnt/small' do 103 | mode '0555' 104 | owner 1 105 | group 1 106 | only_if { File.stat('/mnt/small') != 0100555 } 107 | end 108 | 109 | # Creates a small logical volume 110 | # 111 | lvm_logical_volume 'small' do 112 | group 'vg-test' 113 | size '2%VG' 114 | filesystem 'ext3' 115 | mount_point '/mnt/small' 116 | end 117 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/create_thin.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: create_thin 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | apt_update 'update' 21 | 22 | include_recipe 'lvm' 23 | 24 | devices = [ 25 | '/dev/loop10', 26 | '/dev/loop11', 27 | '/dev/loop12', 28 | '/dev/loop13', 29 | ] 30 | 31 | loop_devices 'loop_devices' do 32 | devices devices 33 | action :create 34 | end 35 | 36 | log 'Creating physical volume for test' 37 | devices.each do |device| 38 | lvm_physical_volume device 39 | end 40 | 41 | # create a volume group and use the shortcut methods for creating a thin pool and thin volumes to test that they work 42 | lvm_volume_group 'vg-data' do 43 | physical_volumes ['/dev/loop10', '/dev/loop11'] 44 | 45 | thin_pool 'tpool' do 46 | size '24M' 47 | 48 | thin_volume 'tvol01' do 49 | filesystem 'ext2' 50 | mount_point '/mnt/tvol01' 51 | size '40M' 52 | end 53 | 54 | # a thin volume that's larger than the pool 55 | thin_volume 'tvol02' do 56 | filesystem 'ext2' 57 | mount_point '/mnt/tvol02' 58 | size '1G' 59 | end 60 | end 61 | end 62 | 63 | lvm_volume_group 'vg-test' do 64 | physical_volumes ['/dev/loop12', '/dev/loop13'] 65 | end 66 | 67 | lvm_thin_pool 'lv-thin' do 68 | group 'vg-test' 69 | size '10%VG' 70 | end 71 | 72 | lvm_thin_volume 'thin_vol_1' do 73 | group 'vg-test' 74 | pool 'lv-thin' 75 | size '16M' 76 | filesystem 'ext3' 77 | mount_point '/mnt/thin1' 78 | end 79 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/remove.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: remove 4 | # 5 | # Copyright:: 2013-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | apt_update 'update' 21 | 22 | include_recipe 'lvm' 23 | 24 | # The test device to use 25 | devices = [ 26 | '/dev/loop10', 27 | '/dev/loop11', 28 | '/dev/loop12', 29 | '/dev/loop13', 30 | ] 31 | 32 | loop_devices 'loop_devices' do 33 | devices devices 34 | action :create 35 | end 36 | 37 | # Creates the physical device 38 | 39 | log 'Creating physical volume for test' 40 | devices.each do |device| 41 | lvm_physical_volume device 42 | end 43 | 44 | # Verify that the create action is idempotent 45 | lvm_physical_volume devices.first 46 | 47 | # Creates the volume group 48 | # 49 | lvm_volume_group 'vg-rmdata' do 50 | physical_volumes ['/dev/loop10', '/dev/loop11', '/dev/loop12', '/dev/loop13'] 51 | 52 | logical_volume 'rmlogs' do 53 | size '10M' 54 | filesystem 'ext2' 55 | mount_point location: '/mnt/rmlogs', options: 'noatime,nodiratime' 56 | stripes 2 57 | end 58 | 59 | logical_volume 'rmtest' do 60 | size '5M' 61 | filesystem 'ext4' 62 | mount_point '/mnt/rmtest' 63 | stripes 1 64 | mirrors 2 65 | end 66 | end 67 | 68 | # Removes a lvm_logical_volume 69 | # Leaves the mount location/directory 70 | # 71 | lvm_logical_volume 'rmlogs' do 72 | group 'vg-rmdata' 73 | mount_point '/mnt/rmlogs' 74 | action :remove 75 | end 76 | 77 | # Removes a lvm_logical_volume 78 | # Removes the mount location/directory 79 | # 80 | lvm_logical_volume 'rmtest' do 81 | group 'vg-rmdata' 82 | mount_point '/mnt/rmtest' 83 | remove_mount_point true 84 | action :remove 85 | end 86 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/resize.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: create 4 | # 5 | # Copyright:: 2013-2019, Chef Software, Inc. 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | apt_update 'update' 21 | 22 | include_recipe 'lvm' 23 | 24 | execute 'extend loop10 device' do 25 | command <<-EOF 26 | dd if=/dev/zero bs=512 count=65536 >> /vfile0 27 | losetup -c /dev/loop10 28 | touch /vfile0.extended 29 | EOF 30 | not_if { ::File.exist?('/vfile0.extended') } 31 | end 32 | 33 | lvm_physical_volume 'loop10_resize' do 34 | name '/dev/loop10' 35 | action :resize 36 | end 37 | 38 | # Create a LV to resize 39 | # 40 | lvm_logical_volume 'small_resize' do 41 | action :create 42 | group 'vg-test' 43 | size '8M' 44 | filesystem 'ext3' 45 | mount_point '/mnt/small_resize' 46 | end 47 | 48 | # Resize a lv based off explicit size 49 | # 50 | lvm_logical_volume 'small_resize_test' do 51 | action :resize 52 | name 'small_resize' 53 | group 'vg-test' 54 | size '16M' 55 | filesystem 'ext3' 56 | mount_point '/mnt/small_resize' 57 | end 58 | 59 | # Create a LV to resize 60 | # 61 | lvm_logical_volume 'percent_resize' do 62 | action :create 63 | group 'vg-test' 64 | size '5%VG' 65 | filesystem 'ext3' 66 | mount_point '/mnt/percent_resize' 67 | end 68 | 69 | # Resize a lv based off percent 70 | # 71 | lvm_logical_volume 'percent_resize_test' do 72 | action :resize 73 | name 'percent_resize' 74 | group 'vg-test' 75 | size '10%VG' 76 | filesystem 'ext3' 77 | mount_point '/mnt/percent_resize' 78 | end 79 | 80 | # Create a LV to resize 81 | # 82 | lvm_logical_volume 'small_noresize' do 83 | action :create 84 | group 'vg-test' 85 | size '8M' 86 | filesystem 'ext3' 87 | mount_point '/mnt/small_noresize' 88 | end 89 | 90 | # Resize a lv based off explicit size 91 | # Should stay the same size 92 | # 93 | lvm_logical_volume 'small_noresize_test' do 94 | action :resize 95 | name 'small_noresize' 96 | group 'vg-test' 97 | size '8M' 98 | filesystem 'ext3' 99 | mount_point '/mnt/small_noresize' 100 | end 101 | 102 | # Create a LV to resize 103 | # 104 | lvm_logical_volume 'percent_noresize' do 105 | action :create 106 | group 'vg-test' 107 | size '5%VG' 108 | filesystem 'ext3' 109 | mount_point '/mnt/percent_noresize' 110 | end 111 | 112 | # Resize a lv based off percent 113 | # Should stay the same size 114 | # 115 | lvm_logical_volume 'percent_noresize_test' do 116 | action :resize 117 | name 'percent_noresize' 118 | group 'vg-test' 119 | size '5%VG' 120 | filesystem 'ext3' 121 | mount_point '/mnt/percent_noresize' 122 | end 123 | 124 | # Create a LV to resize for later option test 125 | # RAW volume (no filesystem) 126 | # 127 | lvm_logical_volume 'small_resize_raw' do 128 | action :create 129 | group 'vg-test' 130 | size '8M' 131 | end 132 | 133 | # Resize a lv based off explicit size using an option parameter 134 | # RAW volume (no filesystem) 135 | # 136 | lvm_logical_volume 'small_resize_raw_test' do 137 | action :resize 138 | name 'small_resize_raw' 139 | group 'vg-test' 140 | size '16M' 141 | filesystem 'RAW' 142 | lv_params '--nofsck' 143 | end 144 | 145 | # Resize a lv based off percent 146 | # Should stay the same size 147 | # 148 | lvm_logical_volume 'remainder_resize' do 149 | action [:create, :resize] 150 | name 'remainder_resize' 151 | group 'vg-test' 152 | size '2' 153 | filesystem 'ext3' 154 | take_up_free_space true 155 | mount_point '/mnt/remainder_resize' 156 | end 157 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/resize_thin.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: resize_thin 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # Resize a thin volume 21 | # Volume was created in create_thin recipe 22 | # 23 | lvm_thin_volume 'thin_vol_1_resize' do 24 | action [:resize] 25 | name 'thin_vol_1' 26 | group 'vg-test' 27 | pool 'lv-thin' 28 | size '32M' 29 | filesystem 'ext3' 30 | mount_point '/mnt/thin1' 31 | end 32 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/resize_thin_pool_meta_data.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook:: test 3 | # Recipe:: resize_thin_pool_meta_data 4 | # 5 | # Copyright:: 2016-2017, Ontario Systems, LLC 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distribued on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | 20 | # Resize a thin volume 21 | # Volume was created in create_thin recipe 22 | # 23 | lvm_thin_pool_meta_data 'lv-thin_tmeta_data_resize' do 24 | action [:resize] 25 | name 'lv-thin_tmeta' 26 | group 'vg-test' 27 | pool 'lv-thin' 28 | size '128M' 29 | filesystem 'ext3' 30 | mount_point '/mnt/thin1' 31 | end 32 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/test_notify.rb: -------------------------------------------------------------------------------- 1 | ## this recipe is purely used in chefspec to verify you can test notifications 2 | 3 | file '/tmp/test_notify' 4 | 5 | lvm_physical_volume '/dev/test_notify_pv' do 6 | notifies :create, 'file[/tmp/test_notify]', :immediately 7 | end 8 | 9 | lvm_volume_group 'notify_vg' do 10 | notifies :create, 'file[/tmp/test_notify]', :immediately 11 | end 12 | 13 | lvm_logical_volume 'test_notify_lv' do 14 | group 'notify_vg' 15 | size '2%VG' 16 | filesystem 'ext4' 17 | notifies :create, 'file[/tmp/test_notify]', :immediately 18 | end 19 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/resources/loop_devices.rb: -------------------------------------------------------------------------------- 1 | provides :loop_devices 2 | unified_mode true 3 | 4 | property :devices, Array, name_property: true 5 | 6 | action :create do 7 | Array(new_resource.devices).each do |device| 8 | next if shell_out!('pvs').stdout.match?(device) 9 | converge_if_changed do 10 | num = device.slice(/\d+/) 11 | shell_out!("dd if=/dev/zero of=/vfile#{num} bs=2048 count=65536") 12 | shell_out!("losetup #{device} /vfile#{num}") 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/integration/create/create_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'pvs' do 2 | its('stdout') { should match '/dev/loop10 vg-data' } 3 | its('stdout') { should match '/dev/loop11 vg-data' } 4 | its('stdout') { should match '/dev/loop12 vg-data' } 5 | its('stdout') { should match '/dev/loop13 vg-data' } 6 | its('stdout') { should match '/dev/loop14 vg-test' } 7 | its('stdout') { should match '/dev/loop15 vg-test' } 8 | its('stdout') { should match '/dev/loop16 vg-test' } 9 | its('stdout') { should match '/dev/loop17 vg-test' } 10 | end 11 | 12 | describe command 'vgs' do 13 | its('stdout') { should match /vg-data\s+4 2 0 wz--n- 496.00m 444.00m/ } 14 | its('stdout') { should match /vg-test\s+4 2 0 wz--n- 496.00m 240.00m/ } 15 | end 16 | 17 | describe command 'lvs' do 18 | its('stdout') { should match /logs\s+vg-data\s+-wi-ao---- 16.00m/ } 19 | its('stdout') { should match /home\s+vg-data\s+rwi-aor--- 8.00m/ } 20 | its('stdout') { should match /test\s+vg-test\s+-wi-ao---- 248.00m/ } 21 | end 22 | 23 | describe mount '/mnt/logs' do 24 | it { should be_mounted } 25 | its('device') { should eq '/dev/mapper/vg--data-logs' } 26 | its('type') { should eq 'ext2' } 27 | end 28 | 29 | describe mount '/mnt/home' do 30 | it { should be_mounted } 31 | its('device') { should eq '/dev/mapper/vg--data-home' } 32 | its('type') { should eq 'ext2' } 33 | end 34 | 35 | describe mount '/mnt/test' do 36 | it { should be_mounted } 37 | its('device') { should eq '/dev/mapper/vg--test-test' } 38 | its('type') { should eq 'ext3' } 39 | end 40 | 41 | describe mount '/mnt/small' do 42 | it { should be_mounted } 43 | its('device') { should eq '/dev/mapper/vg--test-small' } 44 | its('type') { should eq 'ext3' } 45 | end 46 | 47 | describe directory '/mnt/small' do 48 | its('mode') { should cmp '0555' } 49 | end 50 | -------------------------------------------------------------------------------- /test/integration/create_thin/create_thin_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'pvs' do 2 | its('stdout') { should match '/dev/loop10 vg-data' } 3 | its('stdout') { should match '/dev/loop11 vg-data' } 4 | its('stdout') { should match '/dev/loop12 vg-test' } 5 | its('stdout') { should match '/dev/loop13 vg-test' } 6 | end 7 | 8 | describe command 'lvs' do 9 | its('stdout') { should match /tpool\s+vg-data\s+twi-aotz--\s+24.00m/ } 10 | its('stdout') { should match /tvol01\s+vg-data\s+Vwi-aotz--\s+40.00m\s+tpool/ } 11 | its('stdout') { should match /tvol02\s+vg-data\s+Vwi-aotz--\s+1.00g\s+tpool/ } 12 | end 13 | 14 | describe mount '/mnt/tvol01' do 15 | it { should be_mounted } 16 | its('device') { should eq '/dev/mapper/vg--data-tvol01' } 17 | its('type') { should eq 'ext2' } 18 | end 19 | 20 | describe mount '/mnt/tvol02' do 21 | it { should be_mounted } 22 | its('device') { should eq '/dev/mapper/vg--data-tvol02' } 23 | its('type') { should eq 'ext2' } 24 | end 25 | -------------------------------------------------------------------------------- /test/integration/remove/remove_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'pvs' do 2 | its('stdout') { should match %r{/dev/loop10\s+vg-rmdata\s+lvm2\s+a--\s+124.00m\s+124.00m} } 3 | its('stdout') { should match %r{/dev/loop11\s+vg-rmdata\s+lvm2\s+a--\s+124.00m\s+124.00m} } 4 | its('stdout') { should match %r{/dev/loop12\s+vg-rmdata\s+lvm2\s+a--\s+124.00m\s+124.00m} } 5 | its('stdout') { should match %r{/dev/loop13\s+vg-rmdata\s+lvm2\s+a--\s+124.00m\s+124.00m} } 6 | end 7 | 8 | describe command 'lvs' do 9 | its('stdout') { should_not match 'rmlogs' } 10 | its('stdout') { should_not match 'rmtest' } 11 | end 12 | 13 | describe directory '/mnt/rmlogs' do 14 | it { should exist } 15 | its('mode') { should cmp '0755' } 16 | end 17 | 18 | describe directory '/mnt/rmtest' do 19 | it { should_not exist } 20 | end 21 | -------------------------------------------------------------------------------- /test/integration/resize/resize_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'lvs' do 2 | its('stdout') { should match /percent_resize\s+vg-test\s+-wi-ao----\s+48.00m/ } 3 | its('stdout') { should match /percent_noresize\s+vg-test\s+-wi-ao----\s+24.00m/ } 4 | its('stdout') { should match /small_resize\s+vg-test\s+-wi-ao----\s+16.00m/ } 5 | its('stdout') { should match /small_noresize\s+vg-test\s+-wi-ao----\s+8.00m/ } 6 | its('stdout') { should match /remainder_resize\s+vg-test\s+-wi-ao----\s+128.00m/ } 7 | end 8 | 9 | describe command 'vgs' do 10 | its('stdout') { should match /vg-test\s+4\s+8\s+0\s+wz--n-\s+496.00m\s+0/ } 11 | end 12 | 13 | describe command 'pvs' do 14 | its('stdout') { should match %r{dev/loop10\s+vg-data\s+lvm2\s+a--\s+124.00m\s+104.00m} } 15 | end 16 | -------------------------------------------------------------------------------- /test/integration/resize_thin/resize_thin_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'lvs' do 2 | its('stdout') { should match /thin_vol_1\s+vg-test\s+Vwi-aotz--\s+32.00m\s+lv-thin/ } 3 | end 4 | -------------------------------------------------------------------------------- /test/integration/resize_thin_pool_meta_data/resize_thin_pool_meta_data_spec.rb: -------------------------------------------------------------------------------- 1 | describe command 'lvs --options meta_data_lv,lv_metadata_size' do 2 | its('stdout') { should match /\[lv-thin_tmeta\]\s+128.00m/ } 3 | end 4 | --------------------------------------------------------------------------------