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)
+