diff options
author | rtkapiper <andy.piper@arcticwolf.com> | 2023-07-11 18:23:03 +0000 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2023-07-14 16:03:24 +0000 |
commit | aa1a1a54989865587ebabefacd372245a85ecdce (patch) | |
tree | 7b81ed196412b82709553c84c33cdaed73eaa90b | |
parent | 33d56f35e39d0d3872d06400456d5f99f7986dc1 (diff) | |
download | vmdb2-aa1a1a54989865587ebabefacd372245a85ecdce.tar.gz |
lvscan_plugin: support for existing images with logical volumes
The lvscan_plugin is used to detect logical volumes in existing disk
images. The volumes are tagged by the plugin, enabling them to be
mounted.
-rw-r--r-- | vmdb/plugins/lvscan.mdwn | 23 | ||||
-rw-r--r-- | vmdb/plugins/lvscan_plugin.py | 74 |
2 files changed, 97 insertions, 0 deletions
diff --git a/vmdb/plugins/lvscan.mdwn b/vmdb/plugins/lvscan.mdwn new file mode 100644 index 0000000..ff4304c --- /dev/null +++ b/vmdb/plugins/lvscan.mdwn @@ -0,0 +1,23 @@ +Step: lvscan +----------------------------------------------------------------------------- + +Scans for existing LVM2 logical volumes (LVs) within a named volume group. +This is useful when using an existing image as input which has been +pre-populated with LVM logical volumes, allowing the volumes to be mounted. + +Step keys: + +* `lvscan` — REQUIRED; value is the name of the volume group containing + the logical volumes. + +* `tags` — REQUIRED; list of tags to apply to the discovered logical + volumes. The tags must match names of volumes in the volume group. Volumes + in the image which do not need to be mounted can be omitted from the tags + list + +Example (in the .vmdb file): + + - lvscan: the_volume_group + tags: + - lv_one + - lv_two diff --git a/vmdb/plugins/lvscan_plugin.py b/vmdb/plugins/lvscan_plugin.py new file mode 100644 index 0000000..08bf31d --- /dev/null +++ b/vmdb/plugins/lvscan_plugin.py @@ -0,0 +1,74 @@ +# Copyright 2023 Andy Piper +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# =*= License: GPL-3+ =*= + +import json + +import vmdb + + +class LvscanPlugin(vmdb.Plugin): + def enable(self): + self.app.step_runners.add(LvscanStepRunner()) + + +class LvscanStepRunner(vmdb.StepRunnerInterface): + def get_key_spec(self): + return {"lvscan": str, "tags": []} + + def run(self, values, settings, state): + for v in get_logical_volumes(values): + dev = v["lv_path"] + tag = v["lv_name"] + vmdb.progress(f"remembering {dev} as {tag}") + state.tags.append(tag) + state.tags.set_dev(tag, dev) + vmdb.runcmd(["lvchange", "-a", "y", dev]) + + def teardown(self, values, settings, state): + vgname = values["lvscan"] + vmdb.runcmd(["vgchange", "-an", vgname]) + + +def get_logical_volumes(values): + vgname = values["lvscan"] + tags = values["tags"] + vmdb.runcmd(["lvscan"]) + volumes = json.loads( + vmdb.runcmd( + [ + "lvdisplay", + "-C", + "-o", + "lv_name,vg_name,lv_path", + "--report-format", + "json", + ] + ) + )["report"][0]["lv"] + + # ensure all tags have a corresponding volume, but not all volumes need + # a matching tag + matched_vols = [ + v for v in volumes if v["lv_name"] in tags and v["vg_name"] == vgname + ] + if len(matched_vols) < len(tags): + matched_tags = [v["lv_name"] for v in matched_vols] + unmatched_tags = sorted(set(tags).difference(matched_tags)) + raise RuntimeError( + f'unmatched tags in volume group "{vgname}": {unmatched_tags}' + ) + return matched_vols |