summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2023-09-19 21:36:55 -0500
committerJohn Estabrook <jestabro@vyos.io>2023-09-20 15:32:07 -0500
commit2d3f3297b575f88662495e14a7c7324ff73b6bfc (patch)
tree4da9e0719aea09fac6099cd3ba40c08902dfe5e7
parent42736111facf08ac37b86e6fc3cbd395aab166bc (diff)
downloadvyos-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.in69
-rw-r--r--python/vyos/raid.py71
-rwxr-xr-xsrc/op_mode/raid.py44
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)
+