diff options
author | John Estabrook <jestabro@vyos.io> | 2023-09-19 21:36:55 -0500 |
---|---|---|
committer | John Estabrook <jestabro@vyos.io> | 2023-09-20 15:32:07 -0500 |
commit | 2d3f3297b575f88662495e14a7c7324ff73b6bfc (patch) | |
tree | 4da9e0719aea09fac6099cd3ba40c08902dfe5e7 | |
parent | 42736111facf08ac37b86e6fc3cbd395aab166bc (diff) | |
download | vyos-1x-2d3f3297b575f88662495e14a7c7324ff73b6bfc.tar.gz vyos-1x-2d3f3297b575f88662495e14a7c7324ff73b6bfc.zip |
op-mode: raid: T5608: define add/delete raid member
-rw-r--r-- | op-mode-definitions/raid.xml.in | 69 | ||||
-rw-r--r-- | python/vyos/raid.py | 71 | ||||
-rwxr-xr-x | src/op_mode/raid.py | 44 |
3 files changed, 184 insertions, 0 deletions
diff --git a/op-mode-definitions/raid.xml.in b/op-mode-definitions/raid.xml.in new file mode 100644 index 000000000..5d0c9ef3d --- /dev/null +++ b/op-mode-definitions/raid.xml.in @@ -0,0 +1,69 @@ +<?xml version="1.0"?> +<interfaceDefinition> + <node name="add"> + <children> + <tagNode name="raid"> + <properties> + <help>Add a RAID set element</help> + <completionHelp> + <script>${vyos_completion_dir}/list_raidset.sh</script> + </completionHelp> + </properties> + <children> + <node name="by-id"> + <properties> + <help>Add a member by disk id to a RAID set</help> + </properties> + <children> + <tagNode name="member"> + <properties> + <help>Add a member to a RAID set</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/raid.py add --raid-set-name $3 --by-id --member $6</command> + </tagNode> + </children> + </node> + <tagNode name="member"> + <properties> + <help>Add a member to a RAID set</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/raid.py add --raid-set-name $3 --member $5</command> + </tagNode> + </children> + </tagNode> + </children> + </node> + <node name="delete"> + <children> + <tagNode name="raid"> + <properties> + <help>Add a RAID set element</help> + <completionHelp> + <script>${vyos_completion_dir}/list_raidset.sh</script> + </completionHelp> + </properties> + <children> + <node name="by-id"> + <properties> + <help>Add a member by disk id to a RAID set</help> + </properties> + <children> + <tagNode name="member"> + <properties> + <help>Add a member to a RAID set</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/raid.py delete --raid-set-name $3 --by-id --member $6</command> + </tagNode> + </children> + </node> + <tagNode name="member"> + <properties> + <help>Add a member to a RAID set</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/raid.py delete --raid-set-name $3 --member $5</command> + </tagNode> + </children> + </tagNode> + </children> + </node> +</interfaceDefinition> diff --git a/python/vyos/raid.py b/python/vyos/raid.py new file mode 100644 index 000000000..7fb794817 --- /dev/null +++ b/python/vyos/raid.py @@ -0,0 +1,71 @@ +# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +from vyos.utils.disk import device_from_id +from vyos.utils.process import cmd + +def raid_sets(): + """ + Returns a list of RAID sets + """ + with open('/proc/mdstat') as f: + return [line.split()[0].rstrip(':') for line in f if line.startswith('md')] + +def raid_set_members(raid_set_name: str): + """ + Returns a list of members of a RAID set + """ + with open('/proc/mdstat') as f: + for line in f: + if line.startswith(raid_set_name): + return [l.split('[')[0] for l in line.split()[4:]] + return [] + +def partitions(): + """ + Returns a list of partitions + """ + with open('/proc/partitions') as f: + p = [l.strip().split()[-1] for l in list(f) if l.strip()] + p.remove('name') + return p + +def add_raid_member(raid_set_name: str, member: str, by_id: bool = False): + """ + Add a member to an existing RAID set + """ + if by_id: + member = device_from_id(member) + if raid_set_name not in raid_sets(): + raise ValueError(f"RAID set {raid_set_name} does not exist") + if member not in partitions(): + raise ValueError(f"Partition {member} does not exist") + if member in raid_set_members(raid_set_name): + raise ValueError(f"Partition {member} is already a member of RAID set {raid_set_name}") + cmd(f'mdadm --add /dev/{raid_set_name} /dev/{member}') + disk = cmd(f'lsblk -ndo PKNAME /dev/{member}') + cmd(f'grub-install /dev/{disk}') + +def delete_raid_member(raid_set_name: str, member: str, by_id: bool = False): + """ + Delete a member from an existing RAID set + """ + if by_id: + member = device_from_id(member) + if raid_set_name not in raid_sets(): + raise ValueError(f"RAID set {raid_set_name} does not exist") + if member not in raid_set_members(raid_set_name): + raise ValueError(f"Partition {member} is not a member of RAID set {raid_set_name}") + cmd(f'mdadm --remove /dev/{raid_set_name} /dev/{member}') diff --git a/src/op_mode/raid.py b/src/op_mode/raid.py new file mode 100755 index 000000000..fed8ae2c3 --- /dev/null +++ b/src/op_mode/raid.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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/>. +# +# +import sys + +import vyos.opmode +from vyos.raid import add_raid_member +from vyos.raid import delete_raid_member + +def add(raid_set_name: str, member: str, by_id: bool = False): + try: + add_raid_member(raid_set_name, member, by_id) + except ValueError as e: + raise vyos.opmode.IncorrectValue(str(e)) + +def delete(raid_set_name: str, member: str, by_id: bool = False): + try: + delete_raid_member(raid_set_name, member, by_id) + except ValueError as e: + raise vyos.opmode.IncorrectValue(str(e)) + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) + |