]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add CRUD API endpoints for consistency group snapshots 66686/head
authorImran Imtiaz <imran.imtiaz@uk.ibm.com>
Mon, 8 Dec 2025 07:59:03 +0000 (07:59 +0000)
committerImran Imtiaz <imran.imtiaz@uk.ibm.com>
Tue, 23 Dec 2025 10:08:49 +0000 (10:08 +0000)
Signed-off-by: Imran Imtiaz <imran.imtiaz@uk.ibm.com>
Fixes: https://tracker.ceph.com/issues/74258
Create a set of consistency group dashboard API endpoints to:

- List group snapshots
- Get details about a particular snapshot
- Create a snapshot
- Delete a snapshot

(rollback/update are handled separately)

Signed-off-by: Imran Imtiaz <imran.imtiaz@uk.ibm.com>
src/pybind/mgr/dashboard/controllers/rbd.py
src/pybind/mgr/dashboard/openapi.yaml

index 7d8cbd3afea11fd9575e7a21908d6374a9c1d90a..5cb83900ee8b131bec09bc8015a2ebb94a9dc9af 100644 (file)
@@ -6,7 +6,7 @@ import logging
 import math
 from datetime import datetime, timezone
 from functools import partial
-from typing import Any, Dict
+from typing import Any, Dict, Optional
 
 import cherrypy
 import rbd
@@ -50,6 +50,22 @@ RBD_GROUP_GET_SCHEMA = [{
     "images": ([str], '')
 }]
 
+RBD_GROUP_SNAPSHOT_LIST_SCHEMA = [{
+    "id": (str, 'snapshot id'),
+    "name": (str, 'snapshot name'),
+    "state": (int, 'snapshot state'),
+    "namespace_type": (int, 'namespace type')
+}]
+
+RBD_GROUP_SNAPSHOT_GET_SCHEMA = {
+    "id": (str, 'snapshot id'),
+    "name": (str, 'snapshot name'),
+    "state": (int, 'snapshot state'),
+    "namespace_type": (int, 'namespace type'),
+    "image_snap_name": (str, 'image snapshot name'),
+    "image_snaps": ([dict], 'image snapshots')
+}
+
 
 # pylint: disable=not-callable
 def RbdTask(name, metadata, wait_for):  # noqa: N802
@@ -593,3 +609,87 @@ class RbdGroup(RESTController):
             RbdService.validate_namespace(ioctx, namespace)
             ioctx.set_namespace(namespace)
             return group.remove_image(ioctx, image_name)
+
+
+@APIRouter('/block/pool/{pool_name}/group/{group_name}/snap', Scope.RBD_IMAGE)
+@APIDoc("RBD Group Snapshot Management API", "RbdGroupSnapshot")
+class RbdGroupSnapshot(RESTController):
+
+    RESOURCE_ID = "snapshot_name"
+
+    def __init__(self):
+        super().__init__()
+        self.rbd_inst = rbd.RBD()
+
+    @handle_rbd_error()
+    @EndpointDoc("List group snapshots",
+                 parameters={
+                     'pool_name': (str, 'Name of the pool'),
+                     'group_name': (str, 'Name of the group'),
+                 },
+                 responses={200: RBD_GROUP_SNAPSHOT_LIST_SCHEMA})
+    def list(self, pool_name: str, group_name: str, namespace: Optional[str] = None):
+        with mgr.rados.open_ioctx(pool_name) as ioctx:
+            RbdService.validate_namespace(ioctx, namespace)
+            ioctx.set_namespace(namespace)
+            group = rbd.Group(ioctx, group_name)
+            result = []
+            for snap in group.list_snaps():
+                result.append({
+                    'id': snap['id'],
+                    'name': snap['name'],
+                    'state': snap['state'],
+                    'namespace_type': snap['namespace_type']
+                })
+            return result
+
+    @handle_rbd_error()
+    @EndpointDoc("Get group snapshot information",
+                 parameters={
+                     'pool_name': (str, 'Name of the pool'),
+                     'group_name': (str, 'Name of the group'),
+                     'snapshot_name': (str, 'Name of the snapshot'),
+                 },
+                 responses={200: RBD_GROUP_SNAPSHOT_GET_SCHEMA})
+    def get(self, pool_name: str, group_name: str, snapshot_name: str,
+            namespace: Optional[str] = None):
+        with mgr.rados.open_ioctx(pool_name) as ioctx:
+            RbdService.validate_namespace(ioctx, namespace)
+            ioctx.set_namespace(namespace)
+            group = rbd.Group(ioctx, group_name)
+            return group.get_snap_info(snapshot_name)
+
+    @RbdTask('group_snap/create',
+             ['{pool_name}', '{group_name}', '{snapshot_name}'], 2.0)
+    @EndpointDoc("Create a group snapshot",
+                 parameters={
+                     'pool_name': (str, 'Name of the pool'),
+                     'group_name': (str, 'Name of the group'),
+                     'snapshot_name': (str, 'Name of the snapshot'),
+                     'flags': (int, 'Snapshot creation flags'),
+                 },
+                 responses={200: None})
+    def create(self, pool_name: str, group_name: str, snapshot_name: str,
+               namespace: Optional[str] = None, flags: int = 0):
+        with mgr.rados.open_ioctx(pool_name) as ioctx:
+            RbdService.validate_namespace(ioctx, namespace)
+            ioctx.set_namespace(namespace)
+            group = rbd.Group(ioctx, group_name)
+            return group.create_snap(snapshot_name, flags)
+
+    @RbdTask('group_snap/delete',
+             ['{pool_name}', '{group_name}', '{snapshot_name}'], 2.0)
+    @EndpointDoc("Delete a group snapshot",
+                 parameters={
+                     'pool_name': (str, 'Name of the pool'),
+                     'group_name': (str, 'Name of the group'),
+                     'snapshot_name': (str, 'Name of the snapshot'),
+                 },
+                 responses={200: None})
+    def delete(self, pool_name: str, group_name: str, snapshot_name: str,
+               namespace: Optional[str] = None):
+        with mgr.rados.open_ioctx(pool_name) as ioctx:
+            RbdService.validate_namespace(ioctx, namespace)
+            ioctx.set_namespace(namespace)
+            group = rbd.Group(ioctx, group_name)
+            return group.remove_snap(snapshot_name)
index 328422dd14bd746fa97578c377af3810d62843bb..dc17794bb8d43a4dded52f0f552e85572781e22a 100755 (executable)
@@ -1939,6 +1939,248 @@ paths:
       summary: Add image to a group
       tags:
       - RbdGroup
+  /api/block/pool/{pool_name}/group/{group_name}/snap:
+    get:
+      parameters:
+      - description: Name of the pool
+        in: path
+        name: pool_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the group
+        in: path
+        name: group_name
+        required: true
+        schema:
+          type: string
+      - allowEmptyValue: true
+        in: query
+        name: namespace
+        schema:
+          type: string
+      responses:
+        '200':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              schema:
+                items:
+                  properties:
+                    id:
+                      description: snapshot id
+                      type: string
+                    name:
+                      description: snapshot name
+                      type: string
+                    namespace_type:
+                      description: namespace type
+                      type: integer
+                    state:
+                      description: snapshot state
+                      type: integer
+                  type: object
+                required:
+                - id
+                - name
+                - state
+                - namespace_type
+                type: array
+          description: OK
+        '400':
+          description: Operation exception. Please check the response body for details.
+        '401':
+          description: Unauthenticated access. Please login first.
+        '403':
+          description: Unauthorized access. Please check your permissions.
+        '500':
+          description: Unexpected error. Please check the response body for the stack
+            trace.
+      security:
+      - jwt: []
+      summary: List group snapshots
+      tags:
+      - RbdGroupSnapshot
+    post:
+      parameters:
+      - description: Name of the pool
+        in: path
+        name: pool_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the group
+        in: path
+        name: group_name
+        required: true
+        schema:
+          type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              properties:
+                flags:
+                  default: 0
+                  description: Snapshot creation flags
+                  type: integer
+                namespace:
+                  type: string
+                snapshot_name:
+                  description: Name of the snapshot
+                  type: string
+              required:
+              - snapshot_name
+              type: object
+      responses:
+        '201':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Resource created.
+        '202':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Operation is still executing. Please check the task queue.
+        '400':
+          description: Operation exception. Please check the response body for details.
+        '401':
+          description: Unauthenticated access. Please login first.
+        '403':
+          description: Unauthorized access. Please check your permissions.
+        '500':
+          description: Unexpected error. Please check the response body for the stack
+            trace.
+      security:
+      - jwt: []
+      summary: Create a group snapshot
+      tags:
+      - RbdGroupSnapshot
+  /api/block/pool/{pool_name}/group/{group_name}/snap/{snapshot_name}:
+    delete:
+      parameters:
+      - description: Name of the pool
+        in: path
+        name: pool_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the group
+        in: path
+        name: group_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the snapshot
+        in: path
+        name: snapshot_name
+        required: true
+        schema:
+          type: string
+      - allowEmptyValue: true
+        in: query
+        name: namespace
+        schema:
+          type: string
+      responses:
+        '202':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Operation is still executing. Please check the task queue.
+        '204':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Resource deleted.
+        '400':
+          description: Operation exception. Please check the response body for details.
+        '401':
+          description: Unauthenticated access. Please login first.
+        '403':
+          description: Unauthorized access. Please check your permissions.
+        '500':
+          description: Unexpected error. Please check the response body for the stack
+            trace.
+      security:
+      - jwt: []
+      summary: Delete a group snapshot
+      tags:
+      - RbdGroupSnapshot
+    get:
+      parameters:
+      - description: Name of the pool
+        in: path
+        name: pool_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the group
+        in: path
+        name: group_name
+        required: true
+        schema:
+          type: string
+      - description: Name of the snapshot
+        in: path
+        name: snapshot_name
+        required: true
+        schema:
+          type: string
+      - allowEmptyValue: true
+        in: query
+        name: namespace
+        schema:
+          type: string
+      responses:
+        '200':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              schema:
+                properties:
+                  id:
+                    description: snapshot id
+                    type: string
+                  image_snap_name:
+                    description: image snapshot name
+                    type: string
+                  image_snaps:
+                    description: image snapshots
+                    items:
+                      type: object
+                    type: array
+                  name:
+                    description: snapshot name
+                    type: string
+                  namespace_type:
+                    description: namespace type
+                    type: integer
+                  state:
+                    description: snapshot state
+                    type: integer
+                required:
+                - id
+                - name
+                - state
+                - namespace_type
+                - image_snap_name
+                - image_snaps
+                type: object
+          description: OK
+        '400':
+          description: Operation exception. Please check the response body for details.
+        '401':
+          description: Unauthenticated access. Please login first.
+        '403':
+          description: Unauthorized access. Please check your permissions.
+        '500':
+          description: Unexpected error. Please check the response body for the stack
+            trace.
+      security:
+      - jwt: []
+      summary: Get group snapshot information
+      tags:
+      - RbdGroupSnapshot
   /api/block/pool/{pool_name}/namespace:
     get:
       parameters:
@@ -19806,6 +20048,8 @@ tags:
   name: Rbd
 - description: RBD Group Management API
   name: RbdGroup
+- description: RBD Group Snapshot Management API
+  name: RbdGroupSnapshot
 - description: RBD Mirroring Management API
   name: RbdMirroring
 - description: RBD Mirroring Pool Bootstrap Management API