]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add cephfs mirror fs overview page
authorPedro Gonzalez Gomez <pegonzal@ibm.com>
Fri, 19 Jun 2026 08:21:58 +0000 (10:21 +0200)
committerPedro Gonzalez Gomez <pegonzal@ibm.com>
Wed, 1 Jul 2026 05:31:57 +0000 (07:31 +0200)
Fixes: https://tracker.ceph.com/issues/77520
Signed-off-by: Pedro Gonzalez Gomez <pegonzal@ibm.com>
src/pybind/mgr/dashboard/controllers/cephfs.py
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-mirroring-fs-mirror-paths/cephfs-mirroring-fs-mirror-paths.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-mirroring-fs-mirror-paths/cephfs-mirroring-fs-mirror-paths.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-mirroring-fs-overview/cephfs-mirroring-fs-overview.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-mirroring-fs-overview/cephfs-mirroring-fs-overview.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-mirroring-fs-overview/cephfs-mirroring-fs-overview.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs.service.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/cephfs.model.ts
src/pybind/mgr/dashboard/frontend/src/styles/ceph-custom/_spacings.scss
src/pybind/mgr/dashboard/openapi.yaml
src/pybind/mgr/dashboard/tests/test_cephfs.py

index f2157381e4d52f9c1b5f2a26f352c548a8ca206f..afc146bd587796a49f9b48b6604aec4dcc15ff59 100644 (file)
@@ -63,6 +63,74 @@ DAEMON_STATUS_SCHEMA = [{
     }], 'List of filesystems on daemon'),
 }]
 
+MIRROR_SYNC_PHASE_SCHEMA = {
+    'state': (str, 'Phase state, e.g. completed, in-progress, or waiting'),
+    'duration': (str, 'Phase duration'),
+}
+
+MIRROR_SYNC_BYTES_PROGRESS_SCHEMA = {
+    'sync_bytes': (str, 'Bytes synced so far'),
+    'total_bytes': (str, 'Total bytes to sync'),
+    'sync_percent': (str, 'Sync completion percentage'),
+}
+
+MIRROR_SYNC_FILES_PROGRESS_SCHEMA = {
+    'sync_files': (str, 'Files synced so far'),
+    'total_files': (str, 'Total files to sync'),
+    'sync_percent': (str, 'Sync completion percentage'),
+}
+
+MIRROR_LAST_SYNCED_SNAP_SCHEMA = {
+    'id': (int, 'Snapshot ID'),
+    'name': (str, 'Snapshot name'),
+    'crawl_duration': (str, 'Time taken to scan directory'),
+    'datasync_queue_wait_duration': (str, 'Time in data sync queue'),
+    'sync_duration': (str, 'Snapshot sync duration'),
+    'sync_time_stamp': (str, 'Time of the last sync'),
+    'sync_bytes': (str, 'Bytes synced for the snapshot'),
+    'sync_files': (int, 'Number of files synced for the snapshot'),
+}
+
+MIRROR_CURRENT_SYNCING_SNAP_SCHEMA = {
+    'id': (int, 'Snapshot ID'),
+    'name': (str, 'Snapshot name'),
+    'sync-mode': (str, 'Snapshot sync mode: full or delta'),
+    'avg_read_throughput_bytes': (str, 'Average read throughput'),
+    'avg_write_throughput_bytes': (str, 'Average write throughput'),
+    'crawl': (MIRROR_SYNC_PHASE_SCHEMA, 'Directory crawl progress'),
+    'datasync_queue_wait': (MIRROR_SYNC_PHASE_SCHEMA, 'Data sync queue wait progress'),
+    'bytes': (MIRROR_SYNC_BYTES_PROGRESS_SCHEMA, 'Byte sync progress'),
+    'files': (MIRROR_SYNC_FILES_PROGRESS_SCHEMA, 'File sync progress'),
+    'eta': (str, 'Estimated time remaining for the current sync'),
+}
+
+MIRROR_PEER_SYNC_STAT_SCHEMA = {
+    'state': (str, 'Mirror sync state: idle, syncing, stale, or failed'),
+    'failure_reason': (str, 'Last sync failure reason when state is failed'),
+    'current_syncing_snap': (MIRROR_CURRENT_SYNCING_SNAP_SCHEMA,
+                             'Snapshot currently being synchronized'),
+    'last_synced_snap': (MIRROR_LAST_SYNCED_SNAP_SCHEMA,
+                         'Last successfully synchronized snapshot'),
+    'snaps_synced': (int, 'Total number of snapshots synchronized'),
+    'snaps_deleted': (int, 'Total number of snapshots deleted on the peer'),
+    'snaps_renamed': (int, 'Total number of snapshots renamed on the peer'),
+    'metrics_updated_at': (float, 'Wall-clock time when metrics were last updated'),
+}
+
+MIRROR_DIR_METRICS_SCHEMA = {
+    'peer': ({
+        'peer_uuid': (MIRROR_PEER_SYNC_STAT_SCHEMA,
+                      'Sync statistics keyed by peer UUID'),
+    }, 'Peer sync statistics for the mirrored directory'),
+}
+
+MIRROR_STATUS_SCHEMA = {
+    'metrics': ({
+        '/dir_path': (MIRROR_DIR_METRICS_SCHEMA,
+                      'Mirror directory metrics keyed by absolute path'),
+    }, 'Snapshot mirror sync metrics grouped by mirrored directory path'),
+}
+
 
 # pylint: disable=R0904
 @APIRouter('/cephfs', Scope.CEPHFS)
@@ -1444,14 +1512,22 @@ class CephFSMirror(RESTController):
             )
         return json.loads(out)
 
-    @Endpoint('GET', path='/snapshot-mirror-status')
+    @EndpointDoc("Get snapshot mirror sync metrics",
+                 parameters={
+                     'fs_name': (str, 'File system name'),
+                     'path': (str, 'Mirrored directory path'),
+                     'peer_id': (str, 'Peer UUID'),
+                 },
+                 responses={200: MIRROR_STATUS_SCHEMA})
+    @Endpoint('GET', path='/{fs_name}/status')
     @ReadPermission
-    def snapshot_mirror_status(self, fs_name: str, mirrored_dir_path=None, peer_uuid=None):
-        error_code, out, err = mgr.remote('mirroring', 'snapshot_mirror_status',
-                                          fs_name, mirrored_dir_path, peer_uuid)
+    def mirror_fs_status(self, fs_name: str, path: str = '', peer_id: str = ''):
+        error_code, out, err = mgr.remote(
+            'mirroring', 'snapshot_mirror_status', fs_name,
+            path or None, peer_id or None)
         if error_code != 0:
             raise DashboardException(
-                msg=f'Failed to get Cephfs snapshot mirror status: {err}',
+                msg=f'Failed to get Cephfs mirror status: {err}',
                 code=error_code,
                 component='cephfs.mirror'
             )
index 9670380c0be314c4f8ac0f51c61e1d733a68b9cd..0569eba8ef7105a029c4501716015a621bcb6a48 100644 (file)
@@ -3,7 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ActivatedRoute, convertToParamMap } from '@angular/router';
 import { of, throwError } from 'rxjs';
 
-import { CephfsService, SnapshotMirrorStatusResponse } from '~/app/shared/api/cephfs.service';
+import { CephfsService } from '~/app/shared/api/cephfs.service';
+import { MirrorStatusResponse } from '~/app/shared/models/cephfs.model';
 import { FormatterService } from '~/app/shared/services/formatter.service';
 import { CephfsMirroringFsMirrorPathsComponent } from './cephfs-mirroring-fs-mirror-paths.component';
 
@@ -13,7 +14,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
   let cephfsService: any;
   let formatterService: any;
 
-  const mockSnapshotMirrorStatusResponse: SnapshotMirrorStatusResponse = {
+  const mockMirrorStatusResponse: MirrorStatusResponse = {
     metrics: {
       '/path1': {
         peer: {
@@ -89,7 +90,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
 
   beforeEach(async () => {
     const cephfsServiceMock = {
-      getSnapshotMirrorStatus: jest.fn()
+      getMirrorStatus: jest.fn()
     };
 
     const formatterServiceMock = {
@@ -148,7 +149,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
   });
 
   it('should initialize columns and fetch fsName on init', () => {
-    cephfsService.getSnapshotMirrorStatus.mockReturnValue(of(mockSnapshotMirrorStatusResponse));
+    cephfsService.getMirrorStatus.mockReturnValue(of(mockMirrorStatusResponse));
 
     component.ngOnInit();
 
@@ -162,7 +163,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
 
     // Verify fsName is fetched and data is loaded
     expect(component.fsName).toBe('test-fs');
-    expect(cephfsService.getSnapshotMirrorStatus).toHaveBeenCalledWith('test-fs');
+    expect(cephfsService.getMirrorStatus).toHaveBeenCalledWith('test-fs');
   });
 
   describe('parseMirrorStatus', () => {
@@ -177,7 +178,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
     });
 
     it('should parse mirror status with current_syncing_snap structure', () => {
-      const result = component.parseMirrorStatus(mockSnapshotMirrorStatusResponse);
+      const result = component.parseMirrorStatus(mockMirrorStatusResponse);
 
       expect(result.length).toBe(2);
 
@@ -215,7 +216,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
     });
 
     it('should skip paths without peer data', () => {
-      const dataWithoutPeer: SnapshotMirrorStatusResponse = {
+      const dataWithoutPeer: MirrorStatusResponse = {
         metrics: {
           '/path1': {} as any
         }
@@ -226,7 +227,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
     });
 
     it('should use default values when optional fields are missing', () => {
-      const minimalData: SnapshotMirrorStatusResponse = {
+      const minimalData: MirrorStatusResponse = {
         metrics: {
           '/path1': {
             peer: {
@@ -361,19 +362,17 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
 
   describe('loadMirrorPaths', () => {
     it('should load mirror paths successfully', () => {
-      cephfsService.getSnapshotMirrorStatus.mockReturnValue(of(mockSnapshotMirrorStatusResponse));
+      cephfsService.getMirrorStatus.mockReturnValue(of(mockMirrorStatusResponse));
       component.fsName = 'test-fs';
 
       component.loadMirrorPaths();
 
-      expect(cephfsService.getSnapshotMirrorStatus).toHaveBeenCalledWith('test-fs');
+      expect(cephfsService.getMirrorStatus).toHaveBeenCalledWith('test-fs');
       expect(component.mirrorPaths.length).toBe(2);
     });
 
     it('should set empty array on error', () => {
-      cephfsService.getSnapshotMirrorStatus.mockReturnValue(
-        throwError(() => new Error('API Error'))
-      );
+      cephfsService.getMirrorStatus.mockReturnValue(throwError(() => new Error('API Error')));
       component.fsName = 'test-fs';
 
       component.loadMirrorPaths();
@@ -386,7 +385,7 @@ describe('CephfsMirroringFsMirrorPathsComponent', () => {
 
       component.loadMirrorPaths();
 
-      expect(cephfsService.getSnapshotMirrorStatus).not.toHaveBeenCalled();
+      expect(cephfsService.getMirrorStatus).not.toHaveBeenCalled();
     });
   });
 
index 991d663c7c19317911782c8eebc57cc1382e6332..af19d4002e7a125827b65fb27fcbe766dc4bae14 100644 (file)
@@ -8,11 +8,12 @@ import {
 } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { Subscription } from 'rxjs';
-import { CephfsService, SnapshotMirrorStatusResponse } from '~/app/shared/api/cephfs.service';
+import { CephfsService } from '~/app/shared/api/cephfs.service';
 import { CdTableColumn } from '~/app/shared/models/cd-table-column';
 import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
 import { ICON_TYPE } from '~/app/shared/enum/icons.enum';
 import { FormatterService } from '~/app/shared/services/formatter.service';
+import { MirrorStatusResponse } from '~/app/shared/models/cephfs.model';
 
 interface MirrorPath {
   path: string;
@@ -184,8 +185,8 @@ export class CephfsMirroringFsMirrorPathsComponent implements OnInit, OnDestroy
       return;
     }
 
-    this.cephfsService.getSnapshotMirrorStatus(this.fsName).subscribe(
-      (data: SnapshotMirrorStatusResponse) => {
+    this.cephfsService.getMirrorStatus(this.fsName).subscribe(
+      (data: MirrorStatusResponse) => {
         this.mirrorPaths = this.parseMirrorStatus(data);
         if (this.selectedPath) {
           this.selectedPath =
@@ -202,7 +203,7 @@ export class CephfsMirroringFsMirrorPathsComponent implements OnInit, OnDestroy
     );
   }
 
-  parseMirrorStatus(data: SnapshotMirrorStatusResponse): MirrorPath[] {
+  parseMirrorStatus(data: MirrorStatusResponse): MirrorPath[] {
     if (!data?.metrics) {
       return [];
     }
index 8bdd4bb214686b01af2614e340b2d52f1e90f87a..f40cca0503e07bd097f7117228e33309a1a1046e 100644 (file)
@@ -1,6 +1,144 @@
-<main class="cephfs-mirroring-fs-schedules">
-  <cds-tile>
-    <p class="cds--type-body-01"
-       i18n>Overview content will be available here.</p>
-  </cds-tile>
-</main>
+@let fsData = (fsData$ | async);
+<cds-tile class="cds-mb-5">
+  <div cdsGrid
+       [fullWidth]="true"
+       [narrow]="true">
+    <div cdsRow>
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="3"
+           class="border-subtle-right"
+           [columnNumbers]="{lg: 3, md: 3, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Mirror paths</span>
+        <span class="cds--type-heading-06">{{ fsData?.stats?.mirrorPaths }}</span>
+      </div>
+      <div cdsCol
+           class="cds-pl-6 border-subtle-right cds-center-inline-content"
+           [columnNumbers]="{lg: 3, md: 3, sm: 4}">
+        <div cdsStack="vertical"
+             [gap]="3"
+             class="cds-text-start">
+          <span class="cds--type-label-01"
+                i18n>Syncing paths</span>
+          <span class="cds--type-heading-06">{{ fsData?.stats?.syncingPaths }}</span>
+        </div>
+      </div>
+      <div cdsCol
+           class="cds-pl-7 border-subtle-right"
+           [columnNumbers]="{lg: 3, md: 3, sm: 4}">
+        <div cdsStack="vertical"
+             [gap]="3"
+             class="cds-text-start">
+          <span class="cds--type-label-01"
+                i18n>Last successful sync</span>
+          <span class="cds--type-heading-03">
+            @if (fsData?.sync?.syncedAt) {
+              {{ fsData.sync.path }} {{ fsData.sync.snapName }}: {{ fsData.sync.syncedAt | relativeDate }}
+            } @else if (fsData?.sync?.path || fsData?.sync?.snapName) {
+              {{ fsData.sync.path }} {{ fsData.sync.snapName }}
+            } @else {
+              -
+            }
+          </span>
+        </div>
+      </div>
+      <div cdsCol
+           class="cds-pl-6 cds-center-inline-content"
+           [columnNumbers]="{lg: 3, md: 3, sm: 4}">
+        <div cdsStack="vertical"
+             [gap]="3"
+             class="cds-text-start">
+          <span class="cds--type-label-01"
+                i18n>Failures</span>
+          <span cdsStack="horizontal"
+                [gap]="2"
+                class="vertical-align">
+            @if ((fsData?.stats?.failures ?? 0) > 0) {
+              <cd-icon type="error"
+                       [size]="iconSize.size20"></cd-icon>
+            }
+            <span class="cds--type-heading-06">{{ fsData?.stats?.failures }}</span>
+          </span>
+        </div>
+      </div>
+    </div>
+  </div>
+</cds-tile>
+
+<cds-tile class="cds-mb-5">
+  <div cdsGrid
+       [fullWidth]="true"
+       [narrow]="true">
+    <div cdsRow
+         class="cds-mb-5">
+      <div cdsCol
+           [columnNumbers]="{lg: 16, md: 8, sm: 4}">
+        <h4 class="cds--type-heading-03 cds-m-0"
+            i18n>Destination cluster</h4>
+      </div>
+    </div>
+    <div cdsRow
+         class="cds-mb-5">
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Cluster name</span>
+        <span class="cds--type-body-compact-01">{{ fsData?.destination?.clusterName }}</span>
+      </div>
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Filesystem name</span>
+        <span class="cds--type-body-compact-01">{{ fsData?.destination?.destinationFsName }}</span>
+      </div>
+    </div>
+    <div cdsRow
+         class="cds-mb-5">
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>FSID</span>
+        <span class="cds--type-body-compact-01">{{ fsData?.destination?.fsid }}</span>
+      </div>
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Monitor endpoint</span>
+        <span class="cds--type-body-compact-01">{{ fsData?.destination?.monitorEndpoint }}</span>
+      </div>
+    </div>
+    <div cdsRow>
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Bytes synced</span>
+        <span class="cds--type-body-compact-01">{{ fsData?.sync?.bytesSynced }}</span>
+      </div>
+      <div cdsCol
+           cdsStack="vertical"
+           [gap]="1"
+           [columnNumbers]="{lg: 4, md: 4, sm: 4}">
+        <span class="cds--type-label-01"
+              i18n>Last synced</span>
+        <span class="cds--type-body-compact-01">
+          @if (fsData?.sync?.syncedAt) {
+            {{ fsData.sync.syncedAt | relativeDate }}
+          } @else {
+            -
+          }
+        </span>
+      </div>
+    </div>
+  </div>
+</cds-tile>
index 2312db990e5b258896cb4f71fe3b027ac6f73f34..2f8ce03c5eec308a8ac8adeb623abd749ce4430b 100644 (file)
 import { NO_ERRORS_SCHEMA } from '@angular/core';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ActivatedRoute, convertToParamMap } from '@angular/router';
-import { of } from 'rxjs';
+import { BehaviorSubject, of } from 'rxjs';
+import { take } from 'rxjs/operators';
+
+import { CephfsService } from '~/app/shared/api/cephfs.service';
+import {
+  Daemon,
+  DaemonOverviewInfo,
+  MirroringFsOverviewData,
+  MirroringFsSyncInfo
+} from '~/app/shared/models/cephfs.model';
+import { RelativeDatePipe } from '~/app/shared/pipes/relative-date.pipe';
+import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service';
 
 import { CephfsMirroringFsOverviewComponent } from './cephfs-mirroring-fs-overview.component';
 
 describe('CephfsMirroringFsOverviewComponent', () => {
   let component: CephfsMirroringFsOverviewComponent;
   let fixture: ComponentFixture<CephfsMirroringFsOverviewComponent>;
+  let cephfsServiceMock: {
+    listDaemonStatus: jest.Mock;
+    listMirrorPeers: jest.Mock;
+    getMirrorStatus: jest.Mock;
+  };
+  let refreshInterval$: BehaviorSubject<null>;
+
+  const mockDaemonStatus: Daemon[] = [
+    {
+      daemon_id: 1,
+      filesystems: [
+        {
+          filesystem_id: 1,
+          id: '1',
+          name: 'myfs',
+          directory_count: 5,
+          peers: [
+            {
+              uuid: 'peer-uuid',
+              remote: {
+                client_name: 'client.mirror',
+                cluster_name: 'remote-cluster',
+                fs_name: 'remote_fs',
+                fsid: 'abc-123',
+                mon_host: '10.0.0.1:6789'
+              },
+              stats: {
+                failure_count: 2,
+                recovery_count: 1
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ];
+
+  const mockMirrorStatus = {
+    metrics: {
+      '/dir1': {
+        peer: {
+          'peer-uuid': {
+            state: 'idle',
+            last_synced_snap: {
+              name: 'snap1',
+              sync_bytes: '1.00 KiB',
+              sync_time_stamp: '9000.000000s'
+            },
+            metrics_updated_at: 1_700_000_000
+          }
+        }
+      },
+      '/dir2': {
+        peer: {
+          'peer-uuid': {
+            state: 'syncing'
+          }
+        }
+      }
+    }
+  };
 
   beforeEach(async () => {
+    refreshInterval$ = new BehaviorSubject<null>(null);
+    cephfsServiceMock = {
+      listDaemonStatus: jest.fn().mockReturnValue(of(mockDaemonStatus)),
+      listMirrorPeers: jest.fn().mockReturnValue(
+        of({
+          'peer-uuid': {
+            client_name: 'client.mirror',
+            site_name: 'remote-site',
+            fs_name: 'remote_fs'
+          }
+        })
+      ),
+      getMirrorStatus: jest.fn().mockReturnValue(of(mockMirrorStatus))
+    };
+
     await TestBed.configureTestingModule({
-      declarations: [CephfsMirroringFsOverviewComponent],
+      declarations: [CephfsMirroringFsOverviewComponent, RelativeDatePipe],
       providers: [
         {
           provide: ActivatedRoute,
@@ -20,6 +107,11 @@ describe('CephfsMirroringFsOverviewComponent', () => {
               paramMap: of(convertToParamMap({ fsName: 'myfs' }))
             }
           }
+        },
+        { provide: CephfsService, useValue: cephfsServiceMock },
+        {
+          provide: RefreshIntervalService,
+          useValue: { intervalData$: refreshInterval$.asObservable() }
         }
       ],
       schemas: [NO_ERRORS_SCHEMA]
@@ -29,13 +121,179 @@ describe('CephfsMirroringFsOverviewComponent', () => {
     component = fixture.componentInstance;
 
     fixture.detectChanges();
+    return fixture.whenStable();
   });
 
   it('should create', () => {
     expect(component).toBeTruthy();
   });
 
-  it('should read fsName from parent route params', () => {
-    expect(component.fsName).toBe('myfs');
+  it('should read fsName from parent route params', async () => {
+    const fsData = await component.fsData$.pipe(take(1)).toPromise();
+    expect(fsData?.fsName).toBe('myfs');
+  });
+
+  it('should populate fsData from daemon and mirror status', async () => {
+    const fsData = await component.fsData$.pipe(take(1)).toPromise();
+
+    expect(cephfsServiceMock.listDaemonStatus).toHaveBeenCalled();
+    expect(cephfsServiceMock.listMirrorPeers).toHaveBeenCalledWith('myfs');
+    expect(cephfsServiceMock.getMirrorStatus).toHaveBeenCalledWith('myfs', undefined, 'peer-uuid');
+    expect(fsData?.stats.mirrorPaths).toBe(5);
+    expect(fsData?.stats.failures).toBe(2);
+    expect(fsData?.destination.clusterName).toBe('remote-cluster');
+    expect(fsData?.destination.destinationFsName).toBe('remote_fs');
+    expect(fsData?.destination.fsid).toBe('abc-123');
+    expect(fsData?.destination.monitorEndpoint).toBe('10.0.0.1:6789');
+    expect(fsData?.destination.siteName).toBe('remote-site');
+    expect(fsData?.stats.syncingPaths).toBe(1);
+    expect(fsData?.sync.bytesSynced).toBe('1.00 KiB');
+    expect(fsData?.sync.path).toBe('/dir1');
+    expect(fsData?.sync.snapName).toBe('snap1');
+    expect(fsData?.sync.syncedAt).toBe(1_700_000_000);
+  });
+
+  it('should refresh overview data on interval tick', async () => {
+    await component.fsData$.pipe(take(1)).toPromise();
+    expect(cephfsServiceMock.listDaemonStatus).toHaveBeenCalledTimes(1);
+
+    refreshInterval$.next(null);
+    fixture.detectChanges();
+    await fixture.whenStable();
+
+    expect(cephfsServiceMock.listDaemonStatus).toHaveBeenCalledTimes(2);
+    expect(cephfsServiceMock.listMirrorPeers).toHaveBeenCalledTimes(2);
+    expect(cephfsServiceMock.getMirrorStatus).toHaveBeenCalledTimes(2);
+  });
+});
+
+describe('CephfsMirroringFsOverviewComponent helpers', () => {
+  let component: CephfsMirroringFsOverviewComponent;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [CephfsMirroringFsOverviewComponent],
+      providers: [
+        {
+          provide: ActivatedRoute,
+          useValue: { parent: { paramMap: of(convertToParamMap({ fsName: 'myfs' })) } }
+        },
+        {
+          provide: CephfsService,
+          useValue: {
+            listDaemonStatus: jest.fn(),
+            listMirrorPeers: jest.fn(),
+            getMirrorStatus: jest.fn()
+          }
+        },
+        { provide: RefreshIntervalService, useValue: { intervalData$: of(null) } }
+      ],
+      schemas: [NO_ERRORS_SCHEMA]
+    });
+    component = TestBed.createComponent(CephfsMirroringFsOverviewComponent).componentInstance;
+  });
+
+  const call = <T>(method: string, ...args: unknown[]): T =>
+    ((component as unknown) as Record<string, (...a: unknown[]) => T>)[method](...args);
+
+  it('getDaemonOverviewInfo returns defaults when filesystem is missing', () => {
+    const info = call<DaemonOverviewInfo>('getDaemonOverviewInfo', [], 'missing');
+    expect(info.mirrorPaths).toBe(0);
+    expect(info.peerUuid).toBeUndefined();
+  });
+
+  it('getDaemonOverviewInfo maps daemon peer data', () => {
+    const info = call<DaemonOverviewInfo>(
+      'getDaemonOverviewInfo',
+      [
+        {
+          filesystems: [
+            {
+              name: 'myfs',
+              directory_count: 3,
+              peers: [
+                {
+                  uuid: 'peer-1',
+                  remote: { cluster_name: 'remote', fs_name: 'dest', fsid: 'id', mon_host: 'mon' },
+                  stats: { failure_count: 1 }
+                }
+              ]
+            }
+          ]
+        }
+      ],
+      'myfs'
+    );
+
+    expect(info.mirrorPaths).toBe(3);
+    expect(info.failures).toBe(1);
+    expect(info.peerUuid).toBe('peer-1');
+    expect(info.clusterName).toBe('remote');
+  });
+
+  it('buildMirroringFsOverviewData uses empty sync when status is null', () => {
+    const data = call<MirroringFsOverviewData>(
+      'buildMirroringFsOverviewData',
+      'myfs',
+      {
+        mirrorPaths: 2,
+        failures: 0,
+        clusterName: 'c',
+        destinationFsName: 'd',
+        fsid: 'f',
+        monitorEndpoint: 'm',
+        peerUuid: 'peer-1'
+      },
+      { 'peer-1': { site_name: 'site-a' } },
+      null
+    );
+
+    expect(data.stats.syncingPaths).toBe(0);
+    expect(data.destination.siteName).toBe('site-a');
+    expect(data.sync.bytesSynced).toBe('-');
+  });
+
+  it('extractLatestSync counts syncing paths and picks latest snapshot', () => {
+    const sync = call<{ syncingPaths: number; info: MirroringFsSyncInfo }>('extractLatestSync', {
+      metrics: {
+        '/old': {
+          peer: {
+            p1: {
+              state: 'idle',
+              last_synced_snap: { name: 'old', sync_bytes: '1 B', sync_time_stamp: '1s' },
+              metrics_updated_at: 100
+            }
+          }
+        },
+        '/new': {
+          peer: {
+            p2: {
+              state: 'syncing',
+              last_synced_snap: { name: 'new', sync_bytes: '2 B', sync_time_stamp: '2s' },
+              metrics_updated_at: 200
+            }
+          }
+        }
+      }
+    });
+
+    expect(sync.syncingPaths).toBe(1);
+    expect(sync.info.snapName).toBe('new');
+    expect(sync.info.path).toBe('/new');
+    expect(sync.info.syncedAt).toBe(200);
+  });
+
+  it('isNewerMirrorSync prefers metrics_updated_at over sync timestamp', () => {
+    expect(call<boolean>('isNewerMirrorSync', '1s', 300, '9s', 200)).toBe(true);
+    expect(call<boolean>('isNewerMirrorSync', '9s', 100, '1s', 200)).toBe(false);
+  });
+
+  it('mirrorMetricsUpdatedAtToEpoch parses valid values and rejects invalid ones', () => {
+    expect(call<number | null>('mirrorMetricsUpdatedAtToEpoch', 1_700_000_000.9)).toBe(
+      1_700_000_000
+    );
+    expect(call<number | null>('mirrorMetricsUpdatedAtToEpoch', '1234.5')).toBe(1234);
+    expect(call<number | null>('mirrorMetricsUpdatedAtToEpoch', '')).toBeNull();
+    expect(call<number | null>('mirrorMetricsUpdatedAtToEpoch', 0)).toBeNull();
   });
 });
index 52e401a699a1edee4fccf5f04c209f640df58ca7..f0f94752eeec1fc0601c62761a12f02c8a3ee927 100644 (file)
-import { Component, OnInit, ViewEncapsulation } from '@angular/core';
-import { ActivatedRoute, ParamMap } from '@angular/router';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  DestroyRef,
+  inject,
+  ViewEncapsulation
+} from '@angular/core';
+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
+import { ActivatedRoute, convertToParamMap, ParamMap } from '@angular/router';
+import { EMPTY, forkJoin, Observable, of } from 'rxjs';
+import { catchError, exhaustMap, map, shareReplay, switchMap } from 'rxjs/operators';
+
+import { CephfsService } from '~/app/shared/api/cephfs.service';
+import {
+  Daemon,
+  DaemonOverviewInfo,
+  MirroringFsOverviewData,
+  MirroringFsSyncInfo,
+  MirrorPeerList,
+  MirrorStatusResponse
+} from '~/app/shared/models/cephfs.model';
+import { RefreshIntervalService } from '~/app/shared/services/refresh-interval.service';
+import { IconSize } from '~/app/shared/enum/icons.enum';
 
 @Component({
   selector: 'cd-cephfs-mirroring-fs-overview',
   templateUrl: './cephfs-mirroring-fs-overview.component.html',
   styleUrls: ['./cephfs-mirroring-fs-overview.component.scss'],
   standalone: false,
+  changeDetection: ChangeDetectionStrategy.OnPush,
   encapsulation: ViewEncapsulation.None
 })
-export class CephfsMirroringFsOverviewComponent implements OnInit {
-  fsName = '';
+export class CephfsMirroringFsOverviewComponent {
+  private readonly route = inject(ActivatedRoute);
+  private readonly cephfsService = inject(CephfsService);
+  private readonly refreshIntervalService = inject(RefreshIntervalService);
+  private readonly destroyRef = inject(DestroyRef);
+
+  readonly iconSize = IconSize;
+
+  private readonly fsName$ = (this.route.parent?.paramMap ?? of(convertToParamMap({}))).pipe(
+    map((paramMap: ParamMap) => paramMap.get('fsName') ?? '-')
+  );
+
+  readonly fsData$ = this.fsName$.pipe(
+    switchMap((fsName) => this.refreshIntervalObs(() => this.fetchFsData(fsName))),
+    shareReplay({ bufferSize: 1, refCount: true })
+  );
+
+  private refreshIntervalObs<T>(fn: () => Observable<T>): Observable<T> {
+    return this.refreshIntervalService.intervalData$.pipe(
+      exhaustMap(() => fn().pipe(catchError(() => EMPTY))),
+      takeUntilDestroyed(this.destroyRef)
+    );
+  }
+
+  private fetchFsData(fsName: string): Observable<MirroringFsOverviewData> {
+    return forkJoin({
+      daemons: this.cephfsService.listDaemonStatus().pipe(catchError(() => of([] as Daemon[]))),
+      peers: this.cephfsService
+        .listMirrorPeers(fsName)
+        .pipe(catchError(() => of({} as MirrorPeerList)))
+    }).pipe(
+      switchMap(({ daemons, peers }) => {
+        const daemonInfo = this.getDaemonOverviewInfo(daemons, fsName);
+        if (!daemonInfo.peerUuid) {
+          return of(this.buildMirroringFsOverviewData(fsName, daemonInfo, peers, null));
+        }
+
+        return this.cephfsService.getMirrorStatus(fsName, undefined, daemonInfo.peerUuid).pipe(
+          catchError(() => of({} as MirrorStatusResponse)),
+          map((status) => this.buildMirroringFsOverviewData(fsName, daemonInfo, peers, status))
+        );
+      })
+    );
+  }
+
+  private getDaemonOverviewInfo(daemons: Daemon[], fsName: string): DaemonOverviewInfo {
+    const empty: DaemonOverviewInfo = {
+      mirrorPaths: 0,
+      failures: 0,
+      clusterName: '-',
+      destinationFsName: '-',
+      fsid: '-',
+      monitorEndpoint: '-'
+    };
+
+    for (const daemon of daemons) {
+      const fs = daemon.filesystems?.find((filesystem) => filesystem.name === fsName);
+      if (!fs) {
+        continue;
+      }
+
+      const peer = fs.peers?.[0];
+      return {
+        mirrorPaths: fs.directory_count ?? 0,
+        failures: (fs.peers ?? []).reduce((sum, item) => sum + (item.stats?.failure_count ?? 0), 0),
+        clusterName: peer?.remote?.cluster_name ?? '-',
+        destinationFsName: peer?.remote?.fs_name ?? '-',
+        fsid: peer?.remote?.fsid ?? '-',
+        monitorEndpoint: peer?.remote?.mon_host ?? '-',
+        peerUuid: peer?.uuid
+      };
+    }
+
+    return empty;
+  }
+
+  private buildMirroringFsOverviewData(
+    fsName: string,
+    daemonInfo: DaemonOverviewInfo,
+    peers: MirrorPeerList,
+    status: MirrorStatusResponse | null
+  ): MirroringFsOverviewData {
+    const sync = status ? this.extractLatestSync(status) : this.emptySyncInfo();
+
+    return {
+      fsName,
+      stats: {
+        mirrorPaths: daemonInfo.mirrorPaths,
+        failures: daemonInfo.failures,
+        syncingPaths: sync.syncingPaths
+      },
+      destination: {
+        clusterName: daemonInfo.clusterName,
+        siteName: daemonInfo.peerUuid ? peers[daemonInfo.peerUuid]?.site_name ?? '-' : '-',
+        destinationFsName: daemonInfo.destinationFsName,
+        fsid: daemonInfo.fsid,
+        monitorEndpoint: daemonInfo.monitorEndpoint
+      },
+      sync: sync.info
+    };
+  }
+
+  private emptySyncInfo(): { syncingPaths: number; info: MirroringFsSyncInfo } {
+    return {
+      syncingPaths: 0,
+      info: {
+        bytesSynced: '-',
+        path: '',
+        snapName: '',
+        syncedAt: null
+      }
+    };
+  }
+
+  private extractLatestSync(
+    status: MirrorStatusResponse
+  ): {
+    syncingPaths: number;
+    info: MirroringFsSyncInfo;
+  } {
+    let syncingPaths = 0;
+    let latestSyncTime = '';
+    let latestMetricsUpdatedAt: number | string | undefined;
+    let latestSnapName = '';
+    let latestBytes = '';
+    let latestSyncPath = '';
 
-  constructor(private route: ActivatedRoute) {}
+    for (const [dirPath, dirMetrics] of Object.entries(status.metrics ?? {})) {
+      for (const dir of Object.values(dirMetrics.peer ?? {})) {
+        if (dir.state === 'syncing') {
+          syncingPaths++;
+        }
+
+        const snap = dir.last_synced_snap;
+        if (!snap) {
+          continue;
+        }
+
+        const syncTime = String(snap.sync_time_stamp ?? '');
+        const snapName = snap.name ?? '';
+        const metricsUpdatedAt = dir.metrics_updated_at;
+        if (
+          this.isNewerMirrorSync(syncTime, metricsUpdatedAt, latestSyncTime, latestMetricsUpdatedAt)
+        ) {
+          latestSyncTime = syncTime;
+          latestMetricsUpdatedAt = metricsUpdatedAt;
+          latestSnapName = snapName;
+          latestBytes = String(snap.sync_bytes ?? '');
+          latestSyncPath = dirPath;
+        } else if (!latestSnapName && snapName) {
+          latestSnapName = snapName;
+          latestBytes = latestBytes || String(snap.sync_bytes ?? '');
+          latestSyncPath = dirPath;
+          latestMetricsUpdatedAt = latestMetricsUpdatedAt ?? metricsUpdatedAt;
+        }
+      }
+    }
+
+    return {
+      syncingPaths,
+      info: {
+        bytesSynced: latestBytes || '-',
+        path: latestSyncPath,
+        snapName: latestSnapName,
+        syncedAt: this.mirrorMetricsUpdatedAtToEpoch(latestMetricsUpdatedAt)
+      }
+    };
+  }
+
+  private isNewerMirrorSync(
+    syncTime: string,
+    metricsUpdatedAt: number | string | undefined,
+    latestSyncTime: string,
+    latestMetricsUpdatedAt: number | string | undefined
+  ): boolean {
+    const newEpoch = this.mirrorMetricsUpdatedAtToEpoch(metricsUpdatedAt);
+    const latestEpoch = this.mirrorMetricsUpdatedAtToEpoch(latestMetricsUpdatedAt);
+    if (newEpoch !== null && latestEpoch !== null) {
+      return newEpoch >= latestEpoch;
+    }
+    return Boolean(syncTime && syncTime >= latestSyncTime);
+  }
 
-  ngOnInit(): void {
-    this.route.parent?.paramMap.subscribe((paramMap: ParamMap) => {
-      this.fsName = paramMap.get('fsName') ?? '';
-    });
+  private mirrorMetricsUpdatedAtToEpoch(
+    metricsUpdatedAt: number | string | undefined
+  ): number | null {
+    if (metricsUpdatedAt === undefined || metricsUpdatedAt === null || metricsUpdatedAt === '') {
+      return null;
+    }
+    const epoch =
+      typeof metricsUpdatedAt === 'number'
+        ? metricsUpdatedAt
+        : parseFloat(String(metricsUpdatedAt));
+    if (!Number.isFinite(epoch) || epoch <= 0) {
+      return null;
+    }
+    return Math.floor(epoch);
   }
 }
index 9baf1d277d52aa05b3165f1842344ea71356ea4d..b2fe9411d5adeb9d877389a68e22b35b598aca52 100644 (file)
@@ -7,7 +7,7 @@ import { Observable } from 'rxjs';
 import { cdEncode, cdEncodeNot } from '../decorators/cd-encode';
 import { CephfsDir, CephfsDirStatfs, CephfsQuotas } from '../models/cephfs-directory-models';
 import { shareReplay } from 'rxjs/operators';
-import { Daemon } from '../models/cephfs.model';
+import { Daemon, MirrorPeerList, MirrorStatusResponse } from '../models/cephfs.model';
 
 export interface SnapshotMirrorStatusResponse {
   metrics: {
@@ -219,22 +219,25 @@ export class CephfsService {
     });
   }
 
-  getSnapshotMirrorStatus(
+  listMirrorPeers(fsName: string): Observable<MirrorPeerList> {
+    return this.http.get<MirrorPeerList>(`${this.baseURL}/mirror/${fsName}`);
+  }
+
+  getMirrorStatus(
     fsName: string,
-    mirroredDirPath?: string,
-    peerUuid?: string
-  ): Observable<SnapshotMirrorStatusResponse> {
+    path?: string,
+    peerId?: string
+  ): Observable<MirrorStatusResponse> {
     let params = new HttpParams();
-    if (mirroredDirPath) {
-      params = params.append('mirrored_dir_path', mirroredDirPath);
+    if (path) {
+      params = params.set('path', path);
     }
-    if (peerUuid) {
-      params = params.append('peer_uuid', peerUuid);
+    if (peerId) {
+      params = params.set('peer_id', peerId);
     }
-    return this.http.get<SnapshotMirrorStatusResponse>(
-      `${this.baseURL}/mirror/snapshot-mirror-status/${fsName}`,
-      { params }
-    );
+    return this.http.get<MirrorStatusResponse>(`${this.baseURL}/mirror/${fsName}/status`, {
+      params
+    });
   }
 
   addMirrorDirectory(@cdEncodeNot fsName: string, @cdEncodeNot path: string): Observable<any> {
index 6053e86346c1c79b2cae875b94a7850dda8bd768..733c15bcbc909c36e666d120d35c74db5485b5f7 100644 (file)
@@ -16,6 +16,8 @@ export interface RemoteInfo {
   client_name: string;
   cluster_name: string;
   fs_name: string;
+  fsid?: string;
+  mon_host?: string;
 }
 
 export interface PeerStats {
@@ -132,6 +134,78 @@ export function mdsStateToStatus(state: string | undefined): MdsStatus {
 
 export type DaemonResponse = Daemon[];
 
+export interface MirrorPeerListEntry {
+  client_name: string;
+  site_name: string;
+  fs_name: string;
+}
+
+export type MirrorPeerList = Record<string, MirrorPeerListEntry>;
+
+export interface MirrorSyncedSnap {
+  id?: number;
+  name?: string;
+  sync_bytes?: number | string;
+  sync_duration?: number | string;
+  sync_time_stamp?: number | string;
+}
+
+export interface MirrorDirStatus {
+  state?: string;
+  last_synced_snap?: MirrorSyncedSnap;
+  current_syncing_snap?: MirrorSyncedSnap;
+  snaps_synced?: number;
+  metrics_updated_at?: number | string;
+}
+
+export interface MirrorDirMetrics {
+  peer?: Record<string, MirrorDirStatus>;
+}
+
+export type MirrorStatusMetrics = Record<string, MirrorDirMetrics>;
+
+export interface MirrorStatusResponse {
+  metrics?: MirrorStatusMetrics;
+}
+
+export interface DaemonOverviewInfo {
+  mirrorPaths: number;
+  failures: number;
+  clusterName: string;
+  destinationFsName: string;
+  fsid: string;
+  monitorEndpoint: string;
+  peerUuid?: string;
+}
+
+export interface MirroringFsOverviewStats {
+  mirrorPaths: number;
+  syncingPaths: number;
+  failures: number;
+}
+
+export interface MirroringFsDestinationCluster {
+  clusterName: string;
+  siteName: string;
+  destinationFsName: string;
+  fsid: string;
+  monitorEndpoint: string;
+}
+
+export interface MirroringFsSyncInfo {
+  bytesSynced: string;
+  path: string;
+  snapName: string;
+  syncedAt: number | null;
+}
+
+export interface MirroringFsOverviewData {
+  fsName: string;
+  stats: MirroringFsOverviewStats;
+  destination: MirroringFsDestinationCluster;
+  sync: MirroringFsSyncInfo;
+}
+
 export type MirroringEntityRow = {
   entity: string;
   mdsCaps: string;
index 2795bfa055291850e8348b7a072bd5164ed58967..8c3c22d7956eced230e3c75a6cd85a5f8536bea4 100644 (file)
 .cds-pt-6 {
   padding-top: layout.$spacing-06;
 }
+
+.cds-text-start {
+  text-align: start;
+}
+
+.cds-center-inline-content {
+  display: flex;
+  justify-content: center;
+
+  > .cds--stack-vertical {
+    width: fit-content;
+    text-align: start;
+  }
+}
index df6dabbb487aeb76784cdbec2f93b03fc5bff093..bfc8a52823ae3a0d317b1842920a79bcfa677318 100644 (file)
@@ -3457,47 +3457,6 @@ paths:
       summary: Enable mirroring for a filesystem
       tags:
       - CephfsMirror
-  /api/cephfs/mirror/snapshot-mirror-status/{fs_name}:
-    get:
-      parameters:
-      - in: path
-        name: fs_name
-        required: true
-        schema:
-          type: string
-      - allowEmptyValue: true
-        in: query
-        name: mirrored_dir_path
-        schema:
-          type: string
-      - allowEmptyValue: true
-        in: query
-        name: peer_uuid
-        schema:
-          type: string
-      responses:
-        '200':
-          content:
-            application/json:
-              schema:
-                type: object
-            application/vnd.ceph.api.v1.0+json:
-              schema:
-                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: []
-      tags:
-      - CephfsMirror
   /api/cephfs/mirror/token:
     post:
       parameters: []
@@ -3626,6 +3585,397 @@ paths:
       summary: Get peers
       tags:
       - CephfsMirror
+  /api/cephfs/mirror/{fs_name}/status:
+    get:
+      parameters:
+      - description: File system name
+        in: path
+        name: fs_name
+        required: true
+        schema:
+          type: string
+      - default: ''
+        description: Mirrored directory path
+        in: query
+        name: path
+        schema:
+          type: string
+      - default: ''
+        description: Peer UUID
+        in: query
+        name: peer_id
+        schema:
+          type: string
+      responses:
+        '200':
+          content:
+            application/json:
+              schema:
+                properties:
+                  metrics:
+                    description: Snapshot mirror sync metrics grouped by mirrored
+                      directory path
+                    properties:
+                      /dir_path:
+                        description: Mirror directory metrics keyed by absolute path
+                        properties:
+                          peer:
+                            description: Peer sync statistics for the mirrored directory
+                            properties:
+                              peer_uuid:
+                                description: Sync statistics keyed by peer UUID
+                                properties:
+                                  current_syncing_snap:
+                                    description: Snapshot currently being synchronized
+                                    properties:
+                                      avg_read_throughput_bytes:
+                                        description: Average read throughput
+                                        type: string
+                                      avg_write_throughput_bytes:
+                                        description: Average write throughput
+                                        type: string
+                                      bytes:
+                                        description: Byte sync progress
+                                        properties:
+                                          sync_bytes:
+                                            description: Bytes synced so far
+                                            type: string
+                                          sync_percent:
+                                            description: Sync completion percentage
+                                            type: string
+                                          total_bytes:
+                                            description: Total bytes to sync
+                                            type: string
+                                        required: &id024
+                                        - sync_bytes
+                                        - total_bytes
+                                        - sync_percent
+                                        type: object
+                                      crawl:
+                                        description: Directory crawl progress
+                                        properties:
+                                          duration:
+                                            description: Phase duration
+                                            type: string
+                                          state:
+                                            description: Phase state, e.g. completed,
+                                              in-progress, or waiting
+                                            type: string
+                                        required: &id025
+                                        - state
+                                        - duration
+                                        type: object
+                                      datasync_queue_wait:
+                                        description: Data sync queue wait progress
+                                        properties:
+                                          duration:
+                                            description: Phase duration
+                                            type: string
+                                          state:
+                                            description: Phase state, e.g. completed,
+                                              in-progress, or waiting
+                                            type: string
+                                        required: &id026
+                                        - state
+                                        - duration
+                                        type: object
+                                      eta:
+                                        description: Estimated time remaining for
+                                          the current sync
+                                        type: string
+                                      files:
+                                        description: File sync progress
+                                        properties:
+                                          sync_files:
+                                            description: Files synced so far
+                                            type: string
+                                          sync_percent:
+                                            description: Sync completion percentage
+                                            type: string
+                                          total_files:
+                                            description: Total files to sync
+                                            type: string
+                                        required: &id027
+                                        - sync_files
+                                        - total_files
+                                        - sync_percent
+                                        type: object
+                                      id:
+                                        description: Snapshot ID
+                                        type: integer
+                                      name:
+                                        description: Snapshot name
+                                        type: string
+                                      sync-mode:
+                                        description: 'Snapshot sync mode: full or
+                                          delta'
+                                        type: string
+                                    required: &id028
+                                    - id
+                                    - name
+                                    - sync-mode
+                                    - avg_read_throughput_bytes
+                                    - avg_write_throughput_bytes
+                                    - crawl
+                                    - datasync_queue_wait
+                                    - bytes
+                                    - files
+                                    - eta
+                                    type: object
+                                  failure_reason:
+                                    description: Last sync failure reason when state
+                                      is failed
+                                    type: string
+                                  last_synced_snap:
+                                    description: Last successfully synchronized snapshot
+                                    properties:
+                                      crawl_duration:
+                                        description: Time taken to scan directory
+                                        type: string
+                                      datasync_queue_wait_duration:
+                                        description: Time in data sync queue
+                                        type: string
+                                      id:
+                                        description: Snapshot ID
+                                        type: integer
+                                      name:
+                                        description: Snapshot name
+                                        type: string
+                                      sync_bytes:
+                                        description: Bytes synced for the snapshot
+                                        type: string
+                                      sync_duration:
+                                        description: Snapshot sync duration
+                                        type: string
+                                      sync_files:
+                                        description: Number of files synced for the
+                                          snapshot
+                                        type: integer
+                                      sync_time_stamp:
+                                        description: Time of the last sync
+                                        type: string
+                                    required: &id029
+                                    - id
+                                    - name
+                                    - crawl_duration
+                                    - datasync_queue_wait_duration
+                                    - sync_duration
+                                    - sync_time_stamp
+                                    - sync_bytes
+                                    - sync_files
+                                    type: object
+                                  metrics_updated_at:
+                                    description: Wall-clock time when metrics were
+                                      last updated
+                                    type: number
+                                  snaps_deleted:
+                                    description: Total number of snapshots deleted
+                                      on the peer
+                                    type: integer
+                                  snaps_renamed:
+                                    description: Total number of snapshots renamed
+                                      on the peer
+                                    type: integer
+                                  snaps_synced:
+                                    description: Total number of snapshots synchronized
+                                    type: integer
+                                  state:
+                                    description: 'Mirror sync state: idle, syncing,
+                                      stale, or failed'
+                                    type: string
+                                required: &id030
+                                - state
+                                - failure_reason
+                                - current_syncing_snap
+                                - last_synced_snap
+                                - snaps_synced
+                                - snaps_deleted
+                                - snaps_renamed
+                                - metrics_updated_at
+                                type: object
+                            required: &id031
+                            - peer_uuid
+                            type: object
+                        required: &id032
+                        - peer
+                        type: object
+                    required: &id033
+                    - /dir_path
+                    type: object
+                required: &id034
+                - metrics
+                type: object
+            application/vnd.ceph.api.v1.0+json:
+              schema:
+                properties:
+                  metrics:
+                    description: Snapshot mirror sync metrics grouped by mirrored
+                      directory path
+                    properties:
+                      /dir_path:
+                        description: Mirror directory metrics keyed by absolute path
+                        properties:
+                          peer:
+                            description: Peer sync statistics for the mirrored directory
+                            properties:
+                              peer_uuid:
+                                description: Sync statistics keyed by peer UUID
+                                properties:
+                                  current_syncing_snap:
+                                    description: Snapshot currently being synchronized
+                                    properties:
+                                      avg_read_throughput_bytes:
+                                        description: Average read throughput
+                                        type: string
+                                      avg_write_throughput_bytes:
+                                        description: Average write throughput
+                                        type: string
+                                      bytes:
+                                        description: Byte sync progress
+                                        properties:
+                                          sync_bytes:
+                                            description: Bytes synced so far
+                                            type: string
+                                          sync_percent:
+                                            description: Sync completion percentage
+                                            type: string
+                                          total_bytes:
+                                            description: Total bytes to sync
+                                            type: string
+                                        required: *id024
+                                        type: object
+                                      crawl:
+                                        description: Directory crawl progress
+                                        properties:
+                                          duration:
+                                            description: Phase duration
+                                            type: string
+                                          state:
+                                            description: Phase state, e.g. completed,
+                                              in-progress, or waiting
+                                            type: string
+                                        required: *id025
+                                        type: object
+                                      datasync_queue_wait:
+                                        description: Data sync queue wait progress
+                                        properties:
+                                          duration:
+                                            description: Phase duration
+                                            type: string
+                                          state:
+                                            description: Phase state, e.g. completed,
+                                              in-progress, or waiting
+                                            type: string
+                                        required: *id026
+                                        type: object
+                                      eta:
+                                        description: Estimated time remaining for
+                                          the current sync
+                                        type: string
+                                      files:
+                                        description: File sync progress
+                                        properties:
+                                          sync_files:
+                                            description: Files synced so far
+                                            type: string
+                                          sync_percent:
+                                            description: Sync completion percentage
+                                            type: string
+                                          total_files:
+                                            description: Total files to sync
+                                            type: string
+                                        required: *id027
+                                        type: object
+                                      id:
+                                        description: Snapshot ID
+                                        type: integer
+                                      name:
+                                        description: Snapshot name
+                                        type: string
+                                      sync-mode:
+                                        description: 'Snapshot sync mode: full or
+                                          delta'
+                                        type: string
+                                    required: *id028
+                                    type: object
+                                  failure_reason:
+                                    description: Last sync failure reason when state
+                                      is failed
+                                    type: string
+                                  last_synced_snap:
+                                    description: Last successfully synchronized snapshot
+                                    properties:
+                                      crawl_duration:
+                                        description: Time taken to scan directory
+                                        type: string
+                                      datasync_queue_wait_duration:
+                                        description: Time in data sync queue
+                                        type: string
+                                      id:
+                                        description: Snapshot ID
+                                        type: integer
+                                      name:
+                                        description: Snapshot name
+                                        type: string
+                                      sync_bytes:
+                                        description: Bytes synced for the snapshot
+                                        type: string
+                                      sync_duration:
+                                        description: Snapshot sync duration
+                                        type: string
+                                      sync_files:
+                                        description: Number of files synced for the
+                                          snapshot
+                                        type: integer
+                                      sync_time_stamp:
+                                        description: Time of the last sync
+                                        type: string
+                                    required: *id029
+                                    type: object
+                                  metrics_updated_at:
+                                    description: Wall-clock time when metrics were
+                                      last updated
+                                    type: number
+                                  snaps_deleted:
+                                    description: Total number of snapshots deleted
+                                      on the peer
+                                    type: integer
+                                  snaps_renamed:
+                                    description: Total number of snapshots renamed
+                                      on the peer
+                                    type: integer
+                                  snaps_synced:
+                                    description: Total number of snapshots synchronized
+                                    type: integer
+                                  state:
+                                    description: 'Mirror sync state: idle, syncing,
+                                      stale, or failed'
+                                    type: string
+                                required: *id030
+                                type: object
+                            required: *id031
+                            type: object
+                        required: *id032
+                        type: object
+                    required: *id033
+                    type: object
+                required: *id034
+                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 snapshot mirror sync metrics
+      tags:
+      - CephfsMirror
   /api/cephfs/mirror/{fs_name}/{peer_uuid}:
     delete:
       parameters:
@@ -5230,7 +5580,7 @@ paths:
                   max_files:
                     description: ''
                     type: integer
-                required: &id024
+                required: &id035
                 - max_bytes
                 - max_files
                 type: object
@@ -5243,7 +5593,7 @@ paths:
                   max_files:
                     description: ''
                     type: integer
-                required: *id024
+                required: *id035
                 type: object
           description: OK
         '400':
@@ -5517,7 +5867,7 @@ paths:
                   subdirs:
                     description: ''
                     type: integer
-                required: &id025
+                required: &id036
                 - bytes
                 - files
                 - subdirs
@@ -5534,7 +5884,7 @@ paths:
                   subdirs:
                     description: ''
                     type: integer
-                required: *id025
+                required: *id036
                 type: object
           description: OK
         '400':
@@ -6517,7 +6867,7 @@ paths:
                       description: Config option type
                       type: string
                   type: object
-                required: &id026
+                required: &id037
                 - name
                 - type
                 - level
@@ -6594,7 +6944,7 @@ paths:
                       description: Config option type
                       type: string
                   type: object
-                required: *id026
+                required: *id037
                 type: array
           description: OK
         '400':
@@ -6718,7 +7068,7 @@ paths:
                   type:
                     description: Type of Rule
                     type: integer
-                required: &id027
+                required: &id038
                 - rule_id
                 - rule_name
                 - ruleset
@@ -6753,7 +7103,7 @@ paths:
                   type:
                     description: Type of Rule
                     type: integer
-                required: *id027
+                required: *id038
                 type: object
           description: OK
         '400':
@@ -7016,7 +7366,7 @@ paths:
                       description: ''
                       type: string
                   type: object
-                required: &id028
+                required: &id039
                 - crush-failure-domain
                 - k
                 - m
@@ -7047,7 +7397,7 @@ paths:
                       description: ''
                       type: string
                   type: object
-                required: *id028
+                required: *id039
                 type: array
           description: OK
         '400':
@@ -7205,7 +7555,7 @@ paths:
                   rgw:
                     description: ''
                     type: boolean
-                required: &id029
+                required: &id040
                 - rbd
                 - mirroring
                 - iscsi
@@ -7234,7 +7584,7 @@ paths:
                   rgw:
                     description: ''
                     type: boolean
-                required: *id029
+                required: *id040
                 type: object
           description: OK
         '400':
@@ -7492,7 +7842,7 @@ paths:
                   instance:
                     description: grafana instance
                     type: string
-                required: &id030
+                required: &id041
                 - instance
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -7501,7 +7851,7 @@ paths:
                   instance:
                     description: grafana instance
                     type: string
-                required: *id030
+                required: *id041
                 type: object
           description: OK
         '400':
@@ -7722,7 +8072,7 @@ paths:
                       write_op_per_sec:
                         description: ''
                         type: integer
-                    required: &id031
+                    required: &id042
                     - read_bytes_sec
                     - read_op_per_sec
                     - recovering_bytes_per_sec
@@ -7744,12 +8094,12 @@ paths:
                           total_used_raw_bytes:
                             description: ''
                             type: integer
-                        required: &id032
+                        required: &id043
                         - total_avail_bytes
                         - total_bytes
                         - total_used_raw_bytes
                         type: object
-                    required: &id033
+                    required: &id044
                     - stats
                     type: object
                   fs_map:
@@ -7780,7 +8130,7 @@ paths:
                                     ro_compat:
                                       description: ''
                                       type: string
-                                  required: &id034
+                                  required: &id045
                                   - compat
                                   - ro_compat
                                   - incompat
@@ -7873,7 +8223,7 @@ paths:
                                 up:
                                   description: ''
                                   type: string
-                              required: &id035
+                              required: &id046
                               - session_autoclose
                               - balancer
                               - up
@@ -7907,12 +8257,12 @@ paths:
                             standbys:
                               description: ''
                               type: string
-                          required: &id036
+                          required: &id047
                           - mdsmap
                           - standbys
                           type: object
                         type: array
-                    required: &id037
+                    required: &id048
                     - filesystems
                     type: object
                   health:
@@ -7927,7 +8277,7 @@ paths:
                       status:
                         description: ''
                         type: string
-                    required: &id038
+                    required: &id049
                     - checks
                     - mutes
                     - status
@@ -7944,7 +8294,7 @@ paths:
                       up:
                         description: ''
                         type: integer
-                    required: &id039
+                    required: &id050
                     - up
                     - down
                     type: object
@@ -7957,7 +8307,7 @@ paths:
                       standbys:
                         description: ''
                         type: string
-                    required: &id040
+                    required: &id051
                     - active_name
                     - standbys
                     type: object
@@ -7970,7 +8320,7 @@ paths:
                           mons:
                             description: ''
                             type: string
-                        required: &id041
+                        required: &id052
                         - mons
                         type: object
                       quorum:
@@ -7978,7 +8328,7 @@ paths:
                         items:
                           type: integer
                         type: array
-                    required: &id042
+                    required: &id053
                     - monmap
                     - quorum
                     type: object
@@ -7995,12 +8345,12 @@ paths:
                             up:
                               description: ''
                               type: integer
-                          required: &id043
+                          required: &id054
                           - in
                           - up
                           type: object
                         type: array
-                    required: &id044
+                    required: &id055
                     - osds
                     type: object
                   pg_info:
@@ -8024,7 +8374,7 @@ paths:
                           num_objects_unfound:
                             description: ''
                             type: integer
-                        required: &id045
+                        required: &id056
                         - num_objects
                         - num_object_copies
                         - num_objects_degraded
@@ -8037,7 +8387,7 @@ paths:
                       statuses:
                         description: ''
                         type: string
-                    required: &id046
+                    required: &id057
                     - object_stats
                     - pgs_per_osd
                     - statuses
@@ -8051,7 +8401,7 @@ paths:
                   scrub_status:
                     description: ''
                     type: string
-                required: &id047
+                required: &id058
                 - client_perf
                 - df
                 - fs_map
@@ -8087,7 +8437,7 @@ paths:
                       write_op_per_sec:
                         description: ''
                         type: integer
-                    required: *id031
+                    required: *id042
                     type: object
                   df:
                     description: ''
@@ -8104,9 +8454,9 @@ paths:
                           total_used_raw_bytes:
                             description: ''
                             type: integer
-                        required: *id032
+                        required: *id043
                         type: object
-                    required: *id033
+                    required: *id044
                     type: object
                   fs_map:
                     description: ''
@@ -8136,7 +8486,7 @@ paths:
                                     ro_compat:
                                       description: ''
                                       type: string
-                                  required: *id034
+                                  required: *id045
                                   type: object
                                 created:
                                   description: ''
@@ -8226,15 +8576,15 @@ paths:
                                 up:
                                   description: ''
                                   type: string
-                              required: *id035
+                              required: *id046
                               type: object
                             standbys:
                               description: ''
                               type: string
-                          required: *id036
+                          required: *id047
                           type: object
                         type: array
-                    required: *id037
+                    required: *id048
                     type: object
                   health:
                     description: ''
@@ -8248,7 +8598,7 @@ paths:
                       status:
                         description: ''
                         type: string
-                    required: *id038
+                    required: *id049
                     type: object
                   hosts:
                     description: ''
@@ -8262,7 +8612,7 @@ paths:
                       up:
                         description: ''
                         type: integer
-                    required: *id039
+                    required: *id050
                     type: object
                   mgr_map:
                     description: ''
@@ -8273,7 +8623,7 @@ paths:
                       standbys:
                         description: ''
                         type: string
-                    required: *id040
+                    required: *id051
                     type: object
                   mon_status:
                     description: ''
@@ -8284,14 +8634,14 @@ paths:
                           mons:
                             description: ''
                             type: string
-                        required: *id041
+                        required: *id052
                         type: object
                       quorum:
                         description: ''
                         items:
                           type: integer
                         type: array
-                    required: *id042
+                    required: *id053
                     type: object
                   osd_map:
                     description: ''
@@ -8306,10 +8656,10 @@ paths:
                             up:
                               description: ''
                               type: integer
-                          required: *id043
+                          required: *id054
                           type: object
                         type: array
-                    required: *id044
+                    required: *id055
                     type: object
                   pg_info:
                     description: ''
@@ -8332,7 +8682,7 @@ paths:
                           num_objects_unfound:
                             description: ''
                             type: integer
-                        required: *id045
+                        required: *id056
                         type: object
                       pgs_per_osd:
                         description: ''
@@ -8340,7 +8690,7 @@ paths:
                       statuses:
                         description: ''
                         type: string
-                    required: *id046
+                    required: *id057
                     type: object
                   pools:
                     description: ''
@@ -8351,7 +8701,7 @@ paths:
                   scrub_status:
                     description: ''
                     type: string
-                required: *id047
+                required: *id058
                 type: object
           description: OK
         '400':
@@ -8389,7 +8739,7 @@ paths:
                       num_standbys:
                         description: Standby MDS count
                         type: integer
-                    required: &id048
+                    required: &id059
                     - num_active
                     - num_standbys
                     type: object
@@ -8417,16 +8767,16 @@ paths:
                                   message:
                                     description: Human-readable summary
                                     type: string
-                                required: &id049
+                                required: &id060
                                 - message
                                 - count
                                 type: object
-                            required: &id050
+                            required: &id061
                             - severity
                             - summary
                             - muted
                             type: object
-                        required: &id051
+                        required: &id062
                         - <check_name>
                         type: object
                       mutes:
@@ -8437,7 +8787,7 @@ paths:
                       status:
                         description: Overall health status
                         type: string
-                    required: &id052
+                    required: &id063
                     - status
                     - checks
                     - mutes
@@ -8451,7 +8801,7 @@ paths:
                       num_standbys:
                         description: Standby manager count
                         type: integer
-                    required: &id053
+                    required: &id064
                     - num_active
                     - num_standbys
                     type: object
@@ -8466,7 +8816,7 @@ paths:
                         items:
                           type: integer
                         type: array
-                    required: &id054
+                    required: &id065
                     - num_mons
                     - quorum
                     type: object
@@ -8485,7 +8835,7 @@ paths:
                       up:
                         description: Count of iSCSI gateways running
                         type: integer
-                    required: &id055
+                    required: &id066
                     - up
                     - down
                     type: object
@@ -8504,7 +8854,7 @@ paths:
                       up:
                         description: Number of OSDs up
                         type: integer
-                    required: &id056
+                    required: &id067
                     - in
                     - up
                     - num_osds
@@ -8534,7 +8884,7 @@ paths:
                             state_name:
                               description: Placement group state
                               type: string
-                          required: &id057
+                          required: &id068
                           - state_name
                           - count
                           type: object
@@ -8542,7 +8892,7 @@ paths:
                       recovering_bytes_per_sec:
                         description: Total recovery in bytes
                         type: integer
-                    required: &id058
+                    required: &id069
                     - pgs_by_state
                     - num_pools
                     - num_pgs
@@ -8550,7 +8900,7 @@ paths:
                     - bytes_total
                     - recovering_bytes_per_sec
                     type: object
-                required: &id059
+                required: &id070
                 - fsid
                 - health
                 - monmap
@@ -8578,7 +8928,7 @@ paths:
                       num_standbys:
                         description: Standby MDS count
                         type: integer
-                    required: *id048
+                    required: *id059
                     type: object
                   health:
                     description: Cluster health overview
@@ -8604,11 +8954,11 @@ paths:
                                   message:
                                     description: Human-readable summary
                                     type: string
-                                required: *id049
+                                required: *id060
                                 type: object
-                            required: *id050
+                            required: *id061
                             type: object
-                        required: *id051
+                        required: *id062
                         type: object
                       mutes:
                         description: List of muted check names
@@ -8618,7 +8968,7 @@ paths:
                       status:
                         description: Overall health status
                         type: string
-                    required: *id052
+                    required: *id063
                     type: object
                   mgrmap:
                     description: Manager map details
@@ -8629,7 +8979,7 @@ paths:
                       num_standbys:
                         description: Standby manager count
                         type: integer
-                    required: *id053
+                    required: *id064
                     type: object
                   monmap:
                     description: Monitor map details
@@ -8642,7 +8992,7 @@ paths:
                         items:
                           type: integer
                         type: array
-                    required: *id054
+                    required: *id065
                     type: object
                   num_hosts:
                     description: Count of hosts
@@ -8659,7 +9009,7 @@ paths:
                       up:
                         description: Count of iSCSI gateways running
                         type: integer
-                    required: *id055
+                    required: *id066
                     type: object
                   num_rgw_gateways:
                     description: Count of RGW gateway daemons running
@@ -8676,7 +9026,7 @@ paths:
                       up:
                         description: Number of OSDs up
                         type: integer
-                    required: *id056
+                    required: *id067
                     type: object
                   pgmap:
                     description: Placement group map details
@@ -8703,15 +9053,15 @@ paths:
                             state_name:
                               description: Placement group state
                               type: string
-                          required: *id057
+                          required: *id068
                           type: object
                         type: array
                       recovering_bytes_per_sec:
                         description: Total recovery in bytes
                         type: integer
-                    required: *id058
+                    required: *id069
                     type: object
-                required: *id059
+                required: *id070
                 type: object
           description: OK
         '400':
@@ -8800,7 +9150,7 @@ paths:
                         type:
                           description: type of service
                           type: string
-                      required: &id060
+                      required: &id071
                       - type
                       - count
                       type: object
@@ -8818,7 +9168,7 @@ paths:
                         type:
                           description: type of service
                           type: string
-                      required: &id061
+                      required: &id072
                       - type
                       - id
                       type: object
@@ -8832,14 +9182,14 @@ paths:
                       orchestrator:
                         description: ''
                         type: boolean
-                    required: &id062
+                    required: &id073
                     - ceph
                     - orchestrator
                     type: object
                   status:
                     description: ''
                     type: string
-                required: &id063
+                required: &id074
                 - hostname
                 - services
                 - service_instances
@@ -8877,7 +9227,7 @@ paths:
                         type:
                           description: type of service
                           type: string
-                      required: *id060
+                      required: *id071
                       type: object
                     type: array
                   service_type:
@@ -8893,7 +9243,7 @@ paths:
                         type:
                           description: type of service
                           type: string
-                      required: *id061
+                      required: *id072
                       type: object
                     type: array
                   sources:
@@ -8905,12 +9255,12 @@ paths:
                       orchestrator:
                         description: ''
                         type: boolean
-                    required: *id062
+                    required: *id073
                     type: object
                   status:
                     description: ''
                     type: string
-                required: *id063
+                required: *id074
                 type: object
           description: OK
         '400':
@@ -9313,7 +9663,7 @@ paths:
                                 IDENTsupport:
                                   description: ''
                                   type: string
-                              required: &id064
+                              required: &id075
                               - IDENTsupport
                               - IDENTstatus
                               - FAILsupport
@@ -9334,7 +9684,7 @@ paths:
                             transport:
                               description: ''
                               type: string
-                          required: &id065
+                          required: &id076
                           - serialNum
                           - transport
                           - mediaType
@@ -9372,7 +9722,7 @@ paths:
                               type:
                                 description: ''
                                 type: string
-                            required: &id066
+                            required: &id077
                             - name
                             - osd_id
                             - cluster_name
@@ -9437,7 +9787,7 @@ paths:
                                     start:
                                       description: ''
                                       type: string
-                                  required: &id067
+                                  required: &id078
                                   - start
                                   - sectors
                                   - sectorsize
@@ -9445,7 +9795,7 @@ paths:
                                   - human_readable_size
                                   - holders
                                   type: object
-                              required: &id068
+                              required: &id079
                               - partition_name
                               type: object
                             path:
@@ -9487,7 +9837,7 @@ paths:
                             vendor:
                               description: ''
                               type: string
-                          required: &id069
+                          required: &id080
                           - removable
                           - ro
                           - vendor
@@ -9507,7 +9857,7 @@ paths:
                           - path
                           - locked
                           type: object
-                      required: &id070
+                      required: &id081
                       - rejected_reasons
                       - available
                       - path
@@ -9527,7 +9877,7 @@ paths:
                   name:
                     description: Hostname
                     type: string
-                required: &id071
+                required: &id082
                 - name
                 - addr
                 - devices
@@ -9578,7 +9928,7 @@ paths:
                                 IDENTsupport:
                                   description: ''
                                   type: string
-                              required: *id064
+                              required: *id075
                               type: object
                             linkSpeed:
                               description: ''
@@ -9595,7 +9945,7 @@ paths:
                             transport:
                               description: ''
                               type: string
-                          required: *id065
+                          required: *id076
                           type: object
                         lvs:
                           description: ''
@@ -9625,7 +9975,7 @@ paths:
                               type:
                                 description: ''
                                 type: string
-                            required: *id066
+                            required: *id077
                             type: object
                           type: array
                         osd_ids:
@@ -9682,9 +10032,9 @@ paths:
                                     start:
                                       description: ''
                                       type: string
-                                  required: *id067
+                                  required: *id078
                                   type: object
-                              required: *id068
+                              required: *id079
                               type: object
                             path:
                               description: ''
@@ -9725,9 +10075,9 @@ paths:
                             vendor:
                               description: ''
                               type: string
-                          required: *id069
+                          required: *id080
                           type: object
-                      required: *id070
+                      required: *id081
                       type: object
                     type: array
                   labels:
@@ -9738,7 +10088,7 @@ paths:
                   name:
                     description: Hostname
                     type: string
-                required: *id071
+                required: *id082
                 type: object
           description: OK
         '400':
@@ -9809,7 +10159,7 @@ paths:
                       description: username
                       type: string
                   type: object
-                required: &id072
+                required: &id083
                 - user
                 - password
                 - mutual_user
@@ -9832,7 +10182,7 @@ paths:
                       description: username
                       type: string
                   type: object
-                required: *id072
+                required: *id083
                 type: array
           description: OK
         '400':
@@ -10173,13 +10523,13 @@ paths:
                                   type:
                                     description: ''
                                     type: string
-                                required: &id073
+                                required: &id084
                                 - type
                                 - addr
                                 - nonce
                                 type: object
                               type: array
-                          required: &id074
+                          required: &id085
                           - addrvec
                           type: object
                         channel:
@@ -10203,7 +10553,7 @@ paths:
                         stamp:
                           description: ''
                           type: string
-                      required: &id075
+                      required: &id086
                       - name
                       - rank
                       - addrs
@@ -10219,7 +10569,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id076
+                required: &id087
                 - clog
                 - audit_log
                 type: object
@@ -10246,10 +10596,10 @@ paths:
                                   type:
                                     description: ''
                                     type: string
-                                required: *id073
+                                required: *id084
                                 type: object
                               type: array
-                          required: *id074
+                          required: *id085
                           type: object
                         channel:
                           description: ''
@@ -10272,7 +10622,7 @@ paths:
                         stamp:
                           description: ''
                           type: string
-                      required: *id075
+                      required: *id086
                       type: object
                     type: array
                   clog:
@@ -10280,7 +10630,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id076
+                required: *id087
                 type: object
           description: OK
         '400':
@@ -10367,7 +10717,7 @@ paths:
                             type:
                               description: Type of the option
                               type: string
-                          required: &id077
+                          required: &id088
                           - name
                           - type
                           - level
@@ -10381,11 +10731,11 @@ paths:
                           - tags
                           - see_also
                           type: object
-                      required: &id078
+                      required: &id089
                       - Option_name
                       type: object
                   type: object
-                required: &id079
+                required: &id090
                 - name
                 - enabled
                 - always_on
@@ -10452,12 +10802,12 @@ paths:
                             type:
                               description: Type of the option
                               type: string
-                          required: *id077
+                          required: *id088
                           type: object
-                      required: *id078
+                      required: *id089
                       type: object
                   type: object
-                required: *id079
+                required: *id090
                 type: array
           description: OK
         '400':
@@ -10737,13 +11087,13 @@ paths:
                                   type:
                                     description: ''
                                     type: string
-                                required: &id080
+                                required: &id091
                                 - type
                                 - addr
                                 - nonce
                                 type: object
                               type: array
-                          required: &id081
+                          required: &id092
                           - addrvec
                           type: object
                         rank:
@@ -10757,13 +11107,13 @@ paths:
                               items:
                                 type: integer
                               type: array
-                          required: &id082
+                          required: &id093
                           - num_sessions
                           type: object
                         weight:
                           description: ''
                           type: integer
-                      required: &id083
+                      required: &id094
                       - rank
                       - name
                       - public_addrs
@@ -10801,7 +11151,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: &id084
+                              required: &id095
                               - features
                               - release
                               - num
@@ -10820,7 +11170,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: &id085
+                              required: &id096
                               - features
                               - release
                               - num
@@ -10839,7 +11189,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: &id086
+                              required: &id097
                               - features
                               - release
                               - num
@@ -10858,13 +11208,13 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: &id087
+                              required: &id098
                               - features
                               - release
                               - num
                               type: object
                             type: array
-                        required: &id088
+                        required: &id099
                         - mon
                         - mds
                         - client
@@ -10889,7 +11239,7 @@ paths:
                             items:
                               type: integer
                             type: array
-                        required: &id089
+                        required: &id100
                         - required_con
                         - required_mon
                         - quorum_con
@@ -10917,7 +11267,7 @@ paths:
                                 items:
                                   type: string
                                 type: array
-                            required: &id090
+                            required: &id101
                             - persistent
                             - optional
                             type: object
@@ -10965,13 +11315,13 @@ paths:
                                           type:
                                             description: ''
                                             type: string
-                                        required: &id091
+                                        required: &id102
                                         - type
                                         - addr
                                         - nonce
                                         type: object
                                       type: array
-                                  required: &id092
+                                  required: &id103
                                   - addrvec
                                   type: object
                                 rank:
@@ -10985,13 +11335,13 @@ paths:
                                       items:
                                         type: integer
                                       type: array
-                                  required: &id093
+                                  required: &id104
                                   - num_sessions
                                   type: object
                                 weight:
                                   description: ''
                                   type: integer
-                              required: &id094
+                              required: &id105
                               - rank
                               - name
                               - public_addrs
@@ -11002,7 +11352,7 @@ paths:
                               - stats
                               type: object
                             type: array
-                        required: &id095
+                        required: &id106
                         - epoch
                         - fsid
                         - modified
@@ -11039,7 +11389,7 @@ paths:
                         items:
                           type: string
                         type: array
-                    required: &id096
+                    required: &id107
                     - name
                     - rank
                     - state
@@ -11058,7 +11408,7 @@ paths:
                     items:
                       type: integer
                     type: array
-                required: &id097
+                required: &id108
                 - mon_status
                 - in_quorum
                 - out_quorum
@@ -11098,10 +11448,10 @@ paths:
                                   type:
                                     description: ''
                                     type: string
-                                required: *id080
+                                required: *id091
                                 type: object
                               type: array
-                          required: *id081
+                          required: *id092
                           type: object
                         rank:
                           description: ''
@@ -11114,12 +11464,12 @@ paths:
                               items:
                                 type: integer
                               type: array
-                          required: *id082
+                          required: *id093
                           type: object
                         weight:
                           description: ''
                           type: integer
-                      required: *id083
+                      required: *id094
                       type: object
                     type: array
                   mon_status:
@@ -11149,7 +11499,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: *id084
+                              required: *id095
                               type: object
                             type: array
                           mds:
@@ -11165,7 +11515,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: *id085
+                              required: *id096
                               type: object
                             type: array
                           mgr:
@@ -11181,7 +11531,7 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: *id086
+                              required: *id097
                               type: object
                             type: array
                           mon:
@@ -11197,10 +11547,10 @@ paths:
                                 release:
                                   description: ''
                                   type: string
-                              required: *id087
+                              required: *id098
                               type: object
                             type: array
-                        required: *id088
+                        required: *id099
                         type: object
                       features:
                         description: ''
@@ -11221,7 +11571,7 @@ paths:
                             items:
                               type: integer
                             type: array
-                        required: *id089
+                        required: *id100
                         type: object
                       monmap:
                         description: ''
@@ -11245,7 +11595,7 @@ paths:
                                 items:
                                   type: string
                                 type: array
-                            required: *id090
+                            required: *id101
                             type: object
                           fsid:
                             description: ''
@@ -11291,10 +11641,10 @@ paths:
                                           type:
                                             description: ''
                                             type: string
-                                        required: *id091
+                                        required: *id102
                                         type: object
                                       type: array
-                                  required: *id092
+                                  required: *id103
                                   type: object
                                 rank:
                                   description: ''
@@ -11307,15 +11657,15 @@ paths:
                                       items:
                                         type: integer
                                       type: array
-                                  required: *id093
+                                  required: *id104
                                   type: object
                                 weight:
                                   description: ''
                                   type: integer
-                              required: *id094
+                              required: *id105
                               type: object
                             type: array
-                        required: *id095
+                        required: *id106
                         type: object
                       name:
                         description: ''
@@ -11344,14 +11694,14 @@ paths:
                         items:
                           type: string
                         type: array
-                    required: *id096
+                    required: *id107
                     type: object
                   out_quorum:
                     description: ''
                     items:
                       type: integer
                     type: array
-                required: *id097
+                required: *id108
                 type: object
           description: OK
         '400':
@@ -11892,7 +12242,7 @@ paths:
                           squash:
                             description: Client squash policy
                             type: string
-                        required: &id098
+                        required: &id109
                         - addresses
                         - access_type
                         - squash
@@ -11919,7 +12269,7 @@ paths:
                         user_id:
                           description: User id
                           type: string
-                      required: &id099
+                      required: &id110
                       - name
                       type: object
                     path:
@@ -11945,7 +12295,7 @@ paths:
                         type: string
                       type: array
                   type: object
-                required: &id100
+                required: &id111
                 - export_id
                 - path
                 - cluster_id
@@ -11980,7 +12330,7 @@ paths:
                           squash:
                             description: Client squash policy
                             type: string
-                        required: *id098
+                        required: *id109
                         type: object
                       type: array
                     cluster_id:
@@ -12004,7 +12354,7 @@ paths:
                         user_id:
                           description: User id
                           type: string
-                      required: *id099
+                      required: *id110
                       type: object
                     path:
                       description: Export path
@@ -12029,7 +12379,7 @@ paths:
                         type: string
                       type: array
                   type: object
-                required: *id100
+                required: *id111
                 type: array
           description: OK
         '400':
@@ -12153,7 +12503,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: &id101
+                      required: &id112
                       - addresses
                       - access_type
                       - squash
@@ -12180,7 +12530,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: &id102
+                    required: &id113
                     - name
                     type: object
                   path:
@@ -12205,7 +12555,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id103
+                required: &id114
                 - export_id
                 - path
                 - cluster_id
@@ -12239,7 +12589,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: *id101
+                      required: *id112
                       type: object
                     type: array
                   cluster_id:
@@ -12263,7 +12613,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: *id102
+                    required: *id113
                     type: object
                   path:
                     description: Export path
@@ -12287,7 +12637,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id103
+                required: *id114
                 type: object
           description: Resource created.
         '202':
@@ -12399,7 +12749,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: &id104
+                      required: &id115
                       - addresses
                       - access_type
                       - squash
@@ -12426,7 +12776,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: &id105
+                    required: &id116
                     - name
                     type: object
                   path:
@@ -12451,7 +12801,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id106
+                required: &id117
                 - export_id
                 - path
                 - cluster_id
@@ -12485,7 +12835,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: *id104
+                      required: *id115
                       type: object
                     type: array
                   cluster_id:
@@ -12509,7 +12859,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: *id105
+                    required: *id116
                     type: object
                   path:
                     description: Export path
@@ -12533,7 +12883,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id106
+                required: *id117
                 type: object
           description: OK
         '400':
@@ -12665,7 +13015,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: &id107
+                      required: &id118
                       - addresses
                       - access_type
                       - squash
@@ -12692,7 +13042,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: &id108
+                    required: &id119
                     - name
                     type: object
                   path:
@@ -12717,7 +13067,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id109
+                required: &id120
                 - export_id
                 - path
                 - cluster_id
@@ -12751,7 +13101,7 @@ paths:
                         squash:
                           description: Client squash policy
                           type: string
-                      required: *id107
+                      required: *id118
                       type: object
                     type: array
                   cluster_id:
@@ -12775,7 +13125,7 @@ paths:
                       user_id:
                         description: User id
                         type: string
-                    required: *id108
+                    required: *id119
                     type: object
                   path:
                     description: Export path
@@ -12799,7 +13149,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id109
+                required: *id120
                 type: object
           description: Resource updated.
         '202':
@@ -15826,7 +16176,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id110
+                required: &id121
                 - list_of_flags
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -15837,7 +16187,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id110
+                required: *id121
                 type: object
           description: OK
         '400':
@@ -15886,7 +16236,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id111
+                required: &id122
                 - list_of_flags
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -15897,7 +16247,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id111
+                required: *id122
                 type: object
           description: Resource updated.
         '202':
@@ -15940,7 +16290,7 @@ paths:
                   osd:
                     description: OSD ID
                     type: integer
-                required: &id112
+                required: &id123
                 - osd
                 - flags
                 type: object
@@ -15955,7 +16305,7 @@ paths:
                   osd:
                     description: OSD ID
                     type: integer
-                required: *id112
+                required: *id123
                 type: object
           description: OK
         '400':
@@ -16028,7 +16378,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id113
+                required: &id124
                 - added
                 - removed
                 - ids
@@ -16051,7 +16401,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id113
+                required: *id124
                 type: object
           description: Resource updated.
         '202':
@@ -16148,7 +16498,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id114
+                required: &id125
                 - safe_to_destroy
                 - active
                 - missing_stats
@@ -16181,7 +16531,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id114
+                required: *id125
                 type: object
           description: OK
         '400':
@@ -16734,7 +17084,7 @@ paths:
                           value:
                             description: ''
                             type: integer
-                        required: &id115
+                        required: &id126
                         - description
                         - nick
                         - type
@@ -16742,10 +17092,10 @@ paths:
                         - units
                         - value
                         type: object
-                    required: &id116
+                    required: &id127
                     - .cache_bytes
                     type: object
-                required: &id117
+                required: &id128
                 - mon.a
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -16775,11 +17125,11 @@ paths:
                           value:
                             description: ''
                             type: integer
-                        required: *id115
+                        required: *id126
                         type: object
-                    required: *id116
+                    required: *id127
                     type: object
-                required: *id117
+                required: *id128
                 type: object
           description: OK
         '400':
@@ -17099,7 +17449,7 @@ paths:
                         type:
                           description: ''
                           type: string
-                      required: &id118
+                      required: &id129
                       - type
                       type: object
                     hit_set_period:
@@ -17141,7 +17491,7 @@ paths:
                         target_version:
                           description: ''
                           type: string
-                      required: &id119
+                      required: &id130
                       - ready_epoch
                       - last_epoch_started
                       - last_epoch_clean
@@ -17170,7 +17520,7 @@ paths:
                         pg_num_min:
                           description: ''
                           type: integer
-                      required: &id120
+                      required: &id131
                       - pg_num_min
                       - pg_num_max
                       type: object
@@ -17256,7 +17606,7 @@ paths:
                       description: ''
                       type: integer
                   type: object
-                required: &id121
+                required: &id132
                 - pool
                 - pool_name
                 - flags
@@ -17382,7 +17732,7 @@ paths:
                         type:
                           description: ''
                           type: string
-                      required: *id118
+                      required: *id129
                       type: object
                     hit_set_period:
                       description: ''
@@ -17423,7 +17773,7 @@ paths:
                         target_version:
                           description: ''
                           type: string
-                      required: *id119
+                      required: *id130
                       type: object
                     min_read_recency_for_promote:
                       description: ''
@@ -17446,7 +17796,7 @@ paths:
                         pg_num_min:
                           description: ''
                           type: integer
-                      required: *id120
+                      required: *id131
                       type: object
                     pg_autoscale_mode:
                       description: ''
@@ -17530,7 +17880,7 @@ paths:
                       description: ''
                       type: integer
                   type: object
-                required: *id121
+                required: *id132
                 type: array
           description: OK
         '400':
@@ -19601,7 +19951,7 @@ paths:
                       description: Zone Group
                       type: string
                   type: object
-                required: &id122
+                required: &id133
                 - id
                 - version
                 - server_hostname
@@ -19632,7 +19982,7 @@ paths:
                       description: Zone Group
                       type: string
                   type: object
-                required: *id122
+                required: *id133
                 type: array
           description: OK
         '400':
@@ -20859,7 +21209,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: &id123
+                required: &id134
                 - list_of_users
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -20870,7 +21220,7 @@ paths:
                     items:
                       type: string
                     type: array
-                required: *id123
+                required: *id134
                 type: object
           description: OK
         '400':
@@ -22695,14 +23045,14 @@ paths:
                           items:
                             type: string
                           type: array
-                      required: &id124
+                      required: &id135
                       - cephfs
                       type: object
                     system:
                       description: ''
                       type: boolean
                   type: object
-                required: &id125
+                required: &id136
                 - name
                 - description
                 - scopes_permissions
@@ -22726,13 +23076,13 @@ paths:
                           items:
                             type: string
                           type: array
-                      required: *id124
+                      required: *id135
                       type: object
                     system:
                       description: ''
                       type: boolean
                   type: object
-                required: *id125
+                required: *id136
                 type: array
           description: OK
         '400':
@@ -23139,7 +23489,7 @@ paths:
                       description: Certificate target (service name or hostname)
                       type: string
                   type: object
-                required: &id126
+                required: &id137
                 - cert_name
                 - scope
                 - signed_by
@@ -23182,7 +23532,7 @@ paths:
                       description: Certificate target (service name or hostname)
                       type: string
                   type: object
-                required: *id126
+                required: *id137
                 type: array
           description: OK
         '400':
@@ -23216,7 +23566,7 @@ paths:
                   certificate:
                     description: Root CA certificate in PEM format
                     type: string
-                required: &id127
+                required: &id138
                 - certificate
                 type: object
             application/vnd.ceph.api.v1.0+json:
@@ -23225,7 +23575,7 @@ paths:
                   certificate:
                     description: Root CA certificate in PEM format
                     type: string
-                required: *id127
+                required: *id138
                 type: object
           description: OK
         '400':
@@ -23493,7 +23843,7 @@ paths:
                       description: Settings Value
                       type: boolean
                   type: object
-                required: &id128
+                required: &id139
                 - name
                 - default
                 - type
@@ -23516,7 +23866,7 @@ paths:
                       description: Settings Value
                       type: boolean
                   type: object
-                required: *id128
+                required: *id139
                 type: array
           description: OK
         '400':
@@ -23727,7 +24077,7 @@ paths:
                               source_type:
                                 description: resource
                                 type: string
-                            required: &id129
+                            required: &id140
                             - source_type
                             - ref
                             type: object
@@ -23735,7 +24085,7 @@ paths:
                         realm:
                           description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                           type: string
-                      required: &id130
+                      required: &id141
                       - realm
                       - join_sources
                       type: object
@@ -23749,7 +24099,7 @@ paths:
                         count:
                           description: Number of instances to place
                           type: integer
-                      required: &id131
+                      required: &id142
                       - count
                       type: object
                     public_addrs:
@@ -23764,7 +24114,7 @@ paths:
                             description: Defines where the system will assign the
                               managed IPs.
                             type: string
-                        required: &id132
+                        required: &id143
                         - address
                         - destination
                         type: object
@@ -23782,13 +24132,13 @@ paths:
                           source_type:
                             description: resource
                             type: string
-                        required: &id133
+                        required: &id144
                         - source_type
                         - ref
                         type: object
                       type: array
                   type: object
-                required: &id134
+                required: &id145
                 - resource_type
                 - cluster_id
                 - auth_mode
@@ -23829,13 +24179,13 @@ paths:
                               source_type:
                                 description: resource
                                 type: string
-                            required: *id129
+                            required: *id140
                             type: object
                           type: array
                         realm:
                           description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                           type: string
-                      required: *id130
+                      required: *id141
                       type: object
                     intent:
                       description: Desired state of the resource, e.g., 'present'
@@ -23847,7 +24197,7 @@ paths:
                         count:
                           description: Number of instances to place
                           type: integer
-                      required: *id131
+                      required: *id142
                       type: object
                     public_addrs:
                       description: Public Address
@@ -23861,7 +24211,7 @@ paths:
                             description: Defines where the system will assign the
                               managed IPs.
                             type: string
-                        required: *id132
+                        required: *id143
                         type: object
                       type: array
                     resource_type:
@@ -23877,11 +24227,11 @@ paths:
                           source_type:
                             description: resource
                             type: string
-                        required: *id133
+                        required: *id144
                         type: object
                       type: array
                   type: object
-                required: *id134
+                required: *id145
                 type: array
           description: OK
         '400':
@@ -23954,7 +24304,7 @@ paths:
                                       source_type:
                                         description: resource
                                         type: string
-                                    required: &id135
+                                    required: &id146
                                     - source_type
                                     - ref
                                     type: object
@@ -23962,7 +24312,7 @@ paths:
                                 realm:
                                   description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                                   type: string
-                              required: &id136
+                              required: &id147
                               - realm
                               - join_sources
                               type: object
@@ -23976,7 +24326,7 @@ paths:
                                 count:
                                   description: Number of instances to place
                                   type: integer
-                              required: &id137
+                              required: &id148
                               - count
                               type: object
                             public_addrs:
@@ -23991,7 +24341,7 @@ paths:
                                     description: Defines where the system will assign
                                       the managed IPs.
                                     type: string
-                                required: &id138
+                                required: &id149
                                 - address
                                 - destination
                                 type: object
@@ -24010,12 +24360,12 @@ paths:
                                   source_type:
                                     description: resource
                                     type: string
-                                required: &id139
+                                required: &id150
                                 - source_type
                                 - ref
                                 type: object
                               type: array
-                          required: &id140
+                          required: &id151
                           - resource_type
                           - cluster_id
                           - auth_mode
@@ -24033,7 +24383,7 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: &id141
+                      required: &id152
                       - resource
                       - state
                       - success
@@ -24042,7 +24392,7 @@ paths:
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: &id142
+                required: &id153
                 - results
                 - success
                 type: object
@@ -24083,13 +24433,13 @@ paths:
                                       source_type:
                                         description: resource
                                         type: string
-                                    required: *id135
+                                    required: *id146
                                     type: object
                                   type: array
                                 realm:
                                   description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                                   type: string
-                              required: *id136
+                              required: *id147
                               type: object
                             intent:
                               description: Desired state of the resource, e.g., 'present'
@@ -24101,7 +24451,7 @@ paths:
                                 count:
                                   description: Number of instances to place
                                   type: integer
-                              required: *id137
+                              required: *id148
                               type: object
                             public_addrs:
                               description: Public Address
@@ -24115,7 +24465,7 @@ paths:
                                     description: Defines where the system will assign
                                       the managed IPs.
                                     type: string
-                                required: *id138
+                                required: *id149
                                 type: object
                               type: array
                             resource_type:
@@ -24132,10 +24482,10 @@ paths:
                                   source_type:
                                     description: resource
                                     type: string
-                                required: *id139
+                                required: *id150
                                 type: object
                               type: array
-                          required: *id140
+                          required: *id151
                           type: object
                         state:
                           description: The current state of the resource,                        e.g.,
@@ -24144,13 +24494,13 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: *id141
+                      required: *id152
                       type: object
                     type: array
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: *id142
+                required: *id153
                 type: object
           description: Resource created.
         '202':
@@ -24263,7 +24613,7 @@ paths:
                             source_type:
                               description: resource
                               type: string
-                          required: &id143
+                          required: &id154
                           - source_type
                           - ref
                           type: object
@@ -24271,7 +24621,7 @@ paths:
                       realm:
                         description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                         type: string
-                    required: &id144
+                    required: &id155
                     - realm
                     - join_sources
                     type: object
@@ -24285,7 +24635,7 @@ paths:
                       count:
                         description: Number of instances to place
                         type: integer
-                    required: &id145
+                    required: &id156
                     - count
                     type: object
                   public_addrs:
@@ -24300,7 +24650,7 @@ paths:
                           description: Defines where the system will assign the managed
                             IPs.
                           type: string
-                      required: &id146
+                      required: &id157
                       - address
                       - destination
                       type: object
@@ -24318,12 +24668,12 @@ paths:
                         source_type:
                           description: resource
                           type: string
-                      required: &id147
+                      required: &id158
                       - source_type
                       - ref
                       type: object
                     type: array
-                required: &id148
+                required: &id159
                 - resource_type
                 - cluster_id
                 - auth_mode
@@ -24363,13 +24713,13 @@ paths:
                             source_type:
                               description: resource
                               type: string
-                          required: *id143
+                          required: *id154
                           type: object
                         type: array
                       realm:
                         description: Domain realm, e.g., 'DOMAIN1.SINK.TEST'
                         type: string
-                    required: *id144
+                    required: *id155
                     type: object
                   intent:
                     description: Desired state of the resource, e.g., 'present' or
@@ -24381,7 +24731,7 @@ paths:
                       count:
                         description: Number of instances to place
                         type: integer
-                    required: *id145
+                    required: *id156
                     type: object
                   public_addrs:
                     description: Public Address
@@ -24395,7 +24745,7 @@ paths:
                           description: Defines where the system will assign the managed
                             IPs.
                           type: string
-                      required: *id146
+                      required: *id157
                       type: object
                     type: array
                   resource_type:
@@ -24411,10 +24761,10 @@ paths:
                         source_type:
                           description: resource
                           type: string
-                      required: *id147
+                      required: *id158
                       type: object
                     type: array
-                required: *id148
+                required: *id159
                 type: object
           description: OK
         '400':
@@ -24452,7 +24802,7 @@ paths:
                         username:
                           description: Username for authentication
                           type: string
-                      required: &id149
+                      required: &id160
                       - username
                       - password
                       type: object
@@ -24472,7 +24822,7 @@ paths:
                       description: ceph.smb.join.auth
                       type: string
                   type: object
-                required: &id150
+                required: &id161
                 - resource_type
                 - auth_id
                 - intent
@@ -24492,7 +24842,7 @@ paths:
                         username:
                           description: Username for authentication
                           type: string
-                      required: *id149
+                      required: *id160
                       type: object
                     auth_id:
                       description: Unique identifier for the join auth resource
@@ -24510,7 +24860,7 @@ paths:
                       description: ceph.smb.join.auth
                       type: string
                   type: object
-                required: *id150
+                required: *id161
                 type: array
           description: OK
         '400':
@@ -24563,7 +24913,7 @@ paths:
                                 username:
                                   description: Username for authentication
                                   type: string
-                              required: &id151
+                              required: &id162
                               - username
                               - password
                               type: object
@@ -24582,7 +24932,7 @@ paths:
                             resource_type:
                               description: ceph.smb.join.auth
                               type: string
-                          required: &id152
+                          required: &id163
                           - resource_type
                           - auth_id
                           - intent
@@ -24596,7 +24946,7 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: &id153
+                      required: &id164
                       - resource
                       - state
                       - success
@@ -24605,7 +24955,7 @@ paths:
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: &id154
+                required: &id165
                 - results
                 - success
                 type: object
@@ -24628,7 +24978,7 @@ paths:
                                 username:
                                   description: Username for authentication
                                   type: string
-                              required: *id151
+                              required: *id162
                               type: object
                             auth_id:
                               description: Unique identifier for the join auth resource
@@ -24645,7 +24995,7 @@ paths:
                             resource_type:
                               description: ceph.smb.join.auth
                               type: string
-                          required: *id152
+                          required: *id163
                           type: object
                         state:
                           description: The current state of the resource,                        e.g.,
@@ -24654,13 +25004,13 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: *id153
+                      required: *id164
                       type: object
                     type: array
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: *id154
+                required: *id165
                 type: object
           description: Resource created.
         '202':
@@ -24756,7 +25106,7 @@ paths:
                       username:
                         description: Username for authentication
                         type: string
-                    required: &id155
+                    required: &id166
                     - username
                     - password
                     type: object
@@ -24775,7 +25125,7 @@ paths:
                   resource_type:
                     description: ceph.smb.join.auth
                     type: string
-                required: &id156
+                required: &id167
                 - resource_type
                 - auth_id
                 - intent
@@ -24794,7 +25144,7 @@ paths:
                       username:
                         description: Username for authentication
                         type: string
-                    required: *id155
+                    required: *id166
                     type: object
                   auth_id:
                     description: Unique identifier for the join auth resource
@@ -24811,7 +25161,7 @@ paths:
                   resource_type:
                     description: ceph.smb.join.auth
                     type: string
-                required: *id156
+                required: *id167
                 type: object
           description: OK
         '400':
@@ -24867,7 +25217,7 @@ paths:
                       volume:
                         description: Name of the CephFS file system
                         type: string
-                    required: &id157
+                    required: &id168
                     - volume
                     - path
                     - provider
@@ -24911,7 +25261,7 @@ paths:
                   write_iops_limit:
                     description: 'QoS: max write IOPS (0=disabled)'
                     type: integer
-                required: &id158
+                required: &id169
                 - resource_type
                 - cluster_id
                 - share_id
@@ -24951,7 +25301,7 @@ paths:
                       volume:
                         description: Name of the CephFS file system
                         type: string
-                    required: *id157
+                    required: *id168
                     type: object
                   cluster_id:
                     description: Unique identifier for the cluster
@@ -24990,7 +25340,7 @@ paths:
                   write_iops_limit:
                     description: 'QoS: max write IOPS (0=disabled)'
                     type: integer
-                required: *id158
+                required: *id169
                 type: object
           description: OK
         '400':
@@ -25058,7 +25408,7 @@ paths:
                                 volume:
                                   description: Name of the CephFS file system
                                   type: string
-                              required: &id159
+                              required: &id170
                               - volume
                               - path
                               - provider
@@ -25102,7 +25452,7 @@ paths:
                             write_iops_limit:
                               description: 'QoS: max write IOPS (0=disabled)'
                               type: integer
-                          required: &id160
+                          required: &id171
                           - resource_type
                           - cluster_id
                           - share_id
@@ -25125,7 +25475,7 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: &id161
+                      required: &id172
                       - resource
                       - state
                       - success
@@ -25134,7 +25484,7 @@ paths:
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: &id162
+                required: &id173
                 - results
                 - success
                 type: object
@@ -25170,7 +25520,7 @@ paths:
                                 volume:
                                   description: Name of the CephFS file system
                                   type: string
-                              required: *id159
+                              required: *id170
                               type: object
                             cluster_id:
                               description: Unique identifier for the cluster
@@ -25209,7 +25559,7 @@ paths:
                             write_iops_limit:
                               description: 'QoS: max write IOPS (0=disabled)'
                               type: integer
-                          required: *id160
+                          required: *id171
                           type: object
                         state:
                           description: The current state of the resource,                        e.g.,
@@ -25218,13 +25568,13 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: *id161
+                      required: *id172
                       type: object
                     type: array
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: *id162
+                required: *id173
                 type: object
           description: Resource created.
         '202':
@@ -25417,7 +25767,7 @@ paths:
                       volume:
                         description: Name of the CephFS file system
                         type: string
-                    required: &id163
+                    required: &id174
                     - volume
                     - path
                     - provider
@@ -25461,7 +25811,7 @@ paths:
                   write_iops_limit:
                     description: 'QoS: max write IOPS (0=disabled)'
                     type: integer
-                required: &id164
+                required: &id175
                 - resource_type
                 - cluster_id
                 - share_id
@@ -25501,7 +25851,7 @@ paths:
                       volume:
                         description: Name of the CephFS file system
                         type: string
-                    required: *id163
+                    required: *id174
                     type: object
                   cluster_id:
                     description: Unique identifier for the cluster
@@ -25540,7 +25890,7 @@ paths:
                   write_iops_limit:
                     description: 'QoS: max write IOPS (0=disabled)'
                     type: integer
-                required: *id164
+                required: *id175
                 type: object
           description: OK
         '400':
@@ -25594,7 +25944,7 @@ paths:
                               name:
                                 description: The name of the group
                                 type: string
-                            required: &id165
+                            required: &id176
                             - name
                             type: object
                           type: array
@@ -25609,17 +25959,17 @@ paths:
                               password:
                                 description: The password for the user
                                 type: string
-                            required: &id166
+                            required: &id177
                             - name
                             - password
                             type: object
                           type: array
-                      required: &id167
+                      required: &id178
                       - users
                       - groups
                       type: object
                   type: object
-                required: &id168
+                required: &id179
                 - resource_type
                 - users_groups_id
                 - intent
@@ -25655,7 +26005,7 @@ paths:
                               name:
                                 description: The name of the group
                                 type: string
-                            required: *id165
+                            required: *id176
                             type: object
                           type: array
                         users:
@@ -25669,13 +26019,13 @@ paths:
                               password:
                                 description: The password for the user
                                 type: string
-                            required: *id166
+                            required: *id177
                             type: object
                           type: array
-                      required: *id167
+                      required: *id178
                       type: object
                   type: object
-                required: *id168
+                required: *id179
                 type: array
           description: OK
         '400':
@@ -25735,7 +26085,7 @@ paths:
                                           username:
                                             description: Username for authentication
                                             type: string
-                                        required: &id169
+                                        required: &id180
                                         - username
                                         - password
                                         type: object
@@ -25756,7 +26106,7 @@ paths:
                                       resource_type:
                                         description: ceph.smb.join.auth
                                         type: string
-                                    required: &id170
+                                    required: &id181
                                     - resource_type
                                     - auth_id
                                     - intent
@@ -25770,7 +26120,7 @@ paths:
                                   success:
                                     description: Indicates if the operation was successful
                                     type: boolean
-                                required: &id171
+                                required: &id182
                                 - resource
                                 - state
                                 - success
@@ -25780,7 +26130,7 @@ paths:
                               description: Indicates if the overall operation was
                                 successful
                               type: boolean
-                          required: &id172
+                          required: &id183
                           - results
                           - success
                           type: object
@@ -25791,7 +26141,7 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: &id173
+                      required: &id184
                       - resource
                       - state
                       - success
@@ -25800,7 +26150,7 @@ paths:
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: &id174
+                required: &id185
                 - results
                 - success
                 type: object
@@ -25830,7 +26180,7 @@ paths:
                                           username:
                                             description: Username for authentication
                                             type: string
-                                        required: *id169
+                                        required: *id180
                                         type: object
                                       auth_id:
                                         description: Unique identifier for the join
@@ -25849,7 +26199,7 @@ paths:
                                       resource_type:
                                         description: ceph.smb.join.auth
                                         type: string
-                                    required: *id170
+                                    required: *id181
                                     type: object
                                   state:
                                     description: The current state of the resource,                        e.g.,
@@ -25858,14 +26208,14 @@ paths:
                                   success:
                                     description: Indicates if the operation was successful
                                     type: boolean
-                                required: *id171
+                                required: *id182
                                 type: object
                               type: array
                             success:
                               description: Indicates if the overall operation was
                                 successful
                               type: boolean
-                          required: *id172
+                          required: *id183
                           type: object
                         state:
                           description: The current state of the resource,                        e.g.,
@@ -25874,13 +26224,13 @@ paths:
                         success:
                           description: Indicates if the operation was successful
                           type: boolean
-                      required: *id173
+                      required: *id184
                       type: object
                     type: array
                   success:
                     description: Indicates if the overall operation was successful
                     type: boolean
-                required: *id174
+                required: *id185
                 type: object
           description: Resource created.
         '202':
@@ -25992,7 +26342,7 @@ paths:
                             name:
                               description: The name of the group
                               type: string
-                          required: &id175
+                          required: &id186
                           - name
                           type: object
                         type: array
@@ -26007,16 +26357,16 @@ paths:
                             password:
                               description: The password for the user
                               type: string
-                          required: &id176
+                          required: &id187
                           - name
                           - password
                           type: object
                         type: array
-                    required: &id177
+                    required: &id188
                     - users
                     - groups
                     type: object
-                required: &id178
+                required: &id189
                 - resource_type
                 - users_groups_id
                 - intent
@@ -26051,7 +26401,7 @@ paths:
                             name:
                               description: The name of the group
                               type: string
-                          required: *id175
+                          required: *id186
                           type: object
                         type: array
                       users:
@@ -26065,12 +26415,12 @@ paths:
                             password:
                               description: The password for the user
                               type: string
-                          required: *id176
+                          required: *id187
                           type: object
                         type: array
-                    required: *id177
+                    required: *id188
                     type: object
-                required: *id178
+                required: *id189
                 type: object
           description: OK
         '400':
@@ -26123,7 +26473,7 @@ paths:
                             pool:
                               description: ''
                               type: integer
-                          required: &id179
+                          required: &id190
                           - pool
                           type: object
                         name:
@@ -26138,7 +26488,7 @@ paths:
                         success:
                           description: ''
                           type: boolean
-                      required: &id180
+                      required: &id191
                       - name
                       - metadata
                       - begin_time
@@ -26171,14 +26521,14 @@ paths:
                       warnings:
                         description: ''
                         type: integer
-                    required: &id181
+                    required: &id192
                     - warnings
                     - errors
                     type: object
                   version:
                     description: ''
                     type: string
-                required: &id182
+                required: &id193
                 - health_status
                 - mgr_id
                 - mgr_host
@@ -26218,7 +26568,7 @@ paths:
                             pool:
                               description: ''
                               type: integer
-                          required: *id179
+                          required: *id190
                           type: object
                         name:
                           description: ''
@@ -26232,7 +26582,7 @@ paths:
                         success:
                           description: ''
                           type: boolean
-                      required: *id180
+                      required: *id191
                       type: object
                     type: array
                   have_mon_connection:
@@ -26256,12 +26606,12 @@ paths:
                       warnings:
                         description: ''
                         type: integer
-                    required: *id181
+                    required: *id192
                     type: object
                   version:
                     description: ''
                     type: string
-                required: *id182
+                required: *id193
                 type: object
           description: OK
         '400':
@@ -26318,7 +26668,7 @@ paths:
                             pool:
                               description: ''
                               type: integer
-                          required: &id183
+                          required: &id194
                           - pool
                           type: object
                         name:
@@ -26333,7 +26683,7 @@ paths:
                         success:
                           description: ''
                           type: boolean
-                      required: &id184
+                      required: &id195
                       - name
                       - metadata
                       - begin_time
@@ -26345,7 +26695,7 @@ paths:
                       - exception
                       type: object
                     type: array
-                required: &id185
+                required: &id196
                 - executing_tasks
                 - finished_tasks
                 type: object
@@ -26377,7 +26727,7 @@ paths:
                             pool:
                               description: ''
                               type: integer
-                          required: *id183
+                          required: *id194
                           type: object
                         name:
                           description: finished tasks name
@@ -26391,10 +26741,10 @@ paths:
                         success:
                           description: ''
                           type: boolean
-                      required: *id184
+                      required: *id195
                       type: object
                     type: array
-                required: *id185
+                required: *id196
                 type: object
           description: OK
         '400':
@@ -26489,7 +26839,7 @@ paths:
                           mode:
                             description: ''
                             type: string
-                        required: &id186
+                        required: &id197
                         - active
                         - mode
                         type: object
@@ -26516,7 +26866,7 @@ paths:
                             items:
                               type: string
                             type: array
-                        required: &id187
+                        required: &id198
                         - cluster_changed
                         - active_changed
                         type: object
@@ -26537,7 +26887,7 @@ paths:
                               straw2:
                                 description: ''
                                 type: integer
-                            required: &id188
+                            required: &id199
                             - straw2
                             type: object
                           bucket_sizes:
@@ -26549,7 +26899,7 @@ paths:
                               '3':
                                 description: ''
                                 type: integer
-                            required: &id189
+                            required: &id200
                             - '1'
                             - '3'
                             type: object
@@ -26562,7 +26912,7 @@ paths:
                               '11':
                                 description: ''
                                 type: integer
-                            required: &id190
+                            required: &id201
                             - '1'
                             - '11'
                             type: object
@@ -26652,7 +27002,7 @@ paths:
                               straw_calc_version:
                                 description: ''
                                 type: integer
-                            required: &id191
+                            required: &id202
                             - choose_local_tries
                             - choose_local_fallback_tries
                             - choose_total_tries
@@ -26674,7 +27024,7 @@ paths:
                             - require_feature_tunables5
                             - has_v5_rules
                             type: object
-                        required: &id192
+                        required: &id203
                         - num_devices
                         - num_types
                         - num_buckets
@@ -26702,7 +27052,7 @@ paths:
                               ever_enabled_multiple:
                                 description: ''
                                 type: boolean
-                            required: &id193
+                            required: &id204
                             - enable_multiple
                             - ever_enabled_multiple
                             type: object
@@ -26717,7 +27067,7 @@ paths:
                           total_num_mds:
                             description: ''
                             type: integer
-                        required: &id194
+                        required: &id205
                         - count
                         - feature_flags
                         - num_standby_mds
@@ -26742,7 +27092,7 @@ paths:
                           num_with_osd:
                             description: ''
                             type: integer
-                        required: &id195
+                        required: &id206
                         - num
                         - num_with_mon
                         - num_with_mds
@@ -26767,7 +27117,7 @@ paths:
                                   x86_64:
                                     description: ''
                                     type: integer
-                                required: &id196
+                                required: &id207
                                 - x86_64
                                 type: object
                               ceph_version:
@@ -26776,7 +27126,7 @@ paths:
                                   ceph version 16.0.0-3151-gf202994fcf:
                                     description: ''
                                     type: integer
-                                required: &id197
+                                required: &id208
                                 - ceph version 16.0.0-3151-gf202994fcf
                                 type: object
                               cpu:
@@ -26785,7 +27135,7 @@ paths:
                                   Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz:
                                     description: ''
                                     type: integer
-                                required: &id198
+                                required: &id209
                                 - Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
                                 type: object
                               distro:
@@ -26794,7 +27144,7 @@ paths:
                                   centos:
                                     description: ''
                                     type: integer
-                                required: &id199
+                                required: &id210
                                 - centos
                                 type: object
                               distro_description:
@@ -26803,7 +27153,7 @@ paths:
                                   CentOS Linux 8 (Core):
                                     description: ''
                                     type: integer
-                                required: &id200
+                                required: &id211
                                 - CentOS Linux 8 (Core)
                                 type: object
                               kernel_description:
@@ -26812,7 +27162,7 @@ paths:
                                   '#1 SMP Wed Jul 1 19:53:01 UTC 2020':
                                     description: ''
                                     type: integer
-                                required: &id201
+                                required: &id212
                                 - '#1 SMP Wed Jul 1 19:53:01 UTC 2020'
                                 type: object
                               kernel_version:
@@ -26821,7 +27171,7 @@ paths:
                                   5.7.7-200.fc32.x86_64:
                                     description: ''
                                     type: integer
-                                required: &id202
+                                required: &id213
                                 - 5.7.7-200.fc32.x86_64
                                 type: object
                               os:
@@ -26830,10 +27180,10 @@ paths:
                                   Linux:
                                     description: ''
                                     type: integer
-                                required: &id203
+                                required: &id214
                                 - Linux
                                 type: object
-                            required: &id204
+                            required: &id215
                             - arch
                             - ceph_version
                             - os
@@ -26852,7 +27202,7 @@ paths:
                                   x86_64:
                                     description: ''
                                     type: integer
-                                required: &id205
+                                required: &id216
                                 - x86_64
                                 type: object
                               ceph_version:
@@ -26861,7 +27211,7 @@ paths:
                                   ceph version 16.0.0-3151-gf202994fcf:
                                     description: ''
                                     type: integer
-                                required: &id206
+                                required: &id217
                                 - ceph version 16.0.0-3151-gf202994fcf
                                 type: object
                               cpu:
@@ -26870,7 +27220,7 @@ paths:
                                   Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz:
                                     description: ''
                                     type: integer
-                                required: &id207
+                                required: &id218
                                 - Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
                                 type: object
                               distro:
@@ -26879,7 +27229,7 @@ paths:
                                   centos:
                                     description: ''
                                     type: integer
-                                required: &id208
+                                required: &id219
                                 - centos
                                 type: object
                               distro_description:
@@ -26888,7 +27238,7 @@ paths:
                                   CentOS Linux 8 (Core):
                                     description: ''
                                     type: integer
-                                required: &id209
+                                required: &id220
                                 - CentOS Linux 8 (Core)
                                 type: object
                               kernel_description:
@@ -26897,7 +27247,7 @@ paths:
                                   '#1 SMP Wed Jul 1 19:53:01 UTC 2020':
                                     description: ''
                                     type: integer
-                                required: &id210
+                                required: &id221
                                 - '#1 SMP Wed Jul 1 19:53:01 UTC 2020'
                                 type: object
                               kernel_version:
@@ -26906,7 +27256,7 @@ paths:
                                   5.7.7-200.fc32.x86_64:
                                     description: ''
                                     type: integer
-                                required: &id211
+                                required: &id222
                                 - 5.7.7-200.fc32.x86_64
                                 type: object
                               os:
@@ -26915,7 +27265,7 @@ paths:
                                   Linux:
                                     description: ''
                                     type: integer
-                                required: &id212
+                                required: &id223
                                 - Linux
                                 type: object
                               osd_objectstore:
@@ -26924,7 +27274,7 @@ paths:
                                   bluestore:
                                     description: ''
                                     type: integer
-                                required: &id213
+                                required: &id224
                                 - bluestore
                                 type: object
                               rotational:
@@ -26933,10 +27283,10 @@ paths:
                                   '1':
                                     description: ''
                                     type: integer
-                                required: &id214
+                                required: &id225
                                 - '1'
                                 type: object
-                            required: &id215
+                            required: &id226
                             - osd_objectstore
                             - rotational
                             - arch
@@ -26948,7 +27298,7 @@ paths:
                             - distro_description
                             - distro
                             type: object
-                        required: &id216
+                        required: &id227
                         - osd
                         - mon
                         type: object
@@ -26971,7 +27321,7 @@ paths:
                                 items:
                                   type: string
                                 type: array
-                            required: &id217
+                            required: &id228
                             - persistent
                             - optional
                             type: object
@@ -26990,7 +27340,7 @@ paths:
                           v2_addr_mons:
                             description: ''
                             type: integer
-                        required: &id218
+                        required: &id229
                         - count
                         - features
                         - min_mon_release
@@ -27014,7 +27364,7 @@ paths:
                           require_osd_release:
                             description: ''
                             type: string
-                        required: &id219
+                        required: &id230
                         - count
                         - require_osd_release
                         - require_min_compat_client
@@ -27057,7 +27407,7 @@ paths:
                             type:
                               description: ''
                               type: string
-                          required: &id220
+                          required: &id231
                           - pool
                           - type
                           - pg_num
@@ -27087,7 +27437,7 @@ paths:
                           num_pools:
                             description: ''
                             type: integer
-                        required: &id221
+                        required: &id232
                         - num_pools
                         - num_images_by_pool
                         - mirroring_by_pool
@@ -27118,7 +27468,7 @@ paths:
                           zones:
                             description: ''
                             type: integer
-                        required: &id222
+                        required: &id233
                         - count
                         - zones
                         - zonegroups
@@ -27130,7 +27480,7 @@ paths:
                           rgw:
                             description: ''
                             type: integer
-                        required: &id223
+                        required: &id234
                         - rgw
                         type: object
                       usage:
@@ -27151,14 +27501,14 @@ paths:
                           total_used_bytes:
                             description: ''
                             type: integer
-                        required: &id224
+                        required: &id235
                         - pools
                         - pg_num
                         - total_used_bytes
                         - total_bytes
                         - total_avail_bytes
                         type: object
-                    required: &id225
+                    required: &id236
                     - leaderboard
                     - report_version
                     - report_timestamp
@@ -27182,7 +27532,7 @@ paths:
                     - balancer
                     - crashes
                     type: object
-                required: &id226
+                required: &id237
                 - report
                 - device_report
                 type: object
@@ -27204,7 +27554,7 @@ paths:
                           mode:
                             description: ''
                             type: string
-                        required: *id186
+                        required: *id197
                         type: object
                       channels:
                         description: ''
@@ -27229,7 +27579,7 @@ paths:
                             items:
                               type: string
                             type: array
-                        required: *id187
+                        required: *id198
                         type: object
                       crashes:
                         description: ''
@@ -27248,7 +27598,7 @@ paths:
                               straw2:
                                 description: ''
                                 type: integer
-                            required: *id188
+                            required: *id199
                             type: object
                           bucket_sizes:
                             description: ''
@@ -27259,7 +27609,7 @@ paths:
                               '3':
                                 description: ''
                                 type: integer
-                            required: *id189
+                            required: *id200
                             type: object
                           bucket_types:
                             description: ''
@@ -27270,7 +27620,7 @@ paths:
                               '11':
                                 description: ''
                                 type: integer
-                            required: *id190
+                            required: *id201
                             type: object
                           compat_weight_set:
                             description: ''
@@ -27358,9 +27708,9 @@ paths:
                               straw_calc_version:
                                 description: ''
                                 type: integer
-                            required: *id191
+                            required: *id202
                             type: object
-                        required: *id192
+                        required: *id203
                         type: object
                       fs:
                         description: ''
@@ -27377,7 +27727,7 @@ paths:
                               ever_enabled_multiple:
                                 description: ''
                                 type: boolean
-                            required: *id193
+                            required: *id204
                             type: object
                           filesystems:
                             description: ''
@@ -27390,7 +27740,7 @@ paths:
                           total_num_mds:
                             description: ''
                             type: integer
-                        required: *id194
+                        required: *id205
                         type: object
                       hosts:
                         description: ''
@@ -27410,7 +27760,7 @@ paths:
                           num_with_osd:
                             description: ''
                             type: integer
-                        required: *id195
+                        required: *id206
                         type: object
                       leaderboard:
                         description: ''
@@ -27430,7 +27780,7 @@ paths:
                                   x86_64:
                                     description: ''
                                     type: integer
-                                required: *id196
+                                required: *id207
                                 type: object
                               ceph_version:
                                 description: ''
@@ -27438,7 +27788,7 @@ paths:
                                   ceph version 16.0.0-3151-gf202994fcf:
                                     description: ''
                                     type: integer
-                                required: *id197
+                                required: *id208
                                 type: object
                               cpu:
                                 description: ''
@@ -27446,7 +27796,7 @@ paths:
                                   Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz:
                                     description: ''
                                     type: integer
-                                required: *id198
+                                required: *id209
                                 type: object
                               distro:
                                 description: ''
@@ -27454,7 +27804,7 @@ paths:
                                   centos:
                                     description: ''
                                     type: integer
-                                required: *id199
+                                required: *id210
                                 type: object
                               distro_description:
                                 description: ''
@@ -27462,7 +27812,7 @@ paths:
                                   CentOS Linux 8 (Core):
                                     description: ''
                                     type: integer
-                                required: *id200
+                                required: *id211
                                 type: object
                               kernel_description:
                                 description: ''
@@ -27470,7 +27820,7 @@ paths:
                                   '#1 SMP Wed Jul 1 19:53:01 UTC 2020':
                                     description: ''
                                     type: integer
-                                required: *id201
+                                required: *id212
                                 type: object
                               kernel_version:
                                 description: ''
@@ -27478,7 +27828,7 @@ paths:
                                   5.7.7-200.fc32.x86_64:
                                     description: ''
                                     type: integer
-                                required: *id202
+                                required: *id213
                                 type: object
                               os:
                                 description: ''
@@ -27486,9 +27836,9 @@ paths:
                                   Linux:
                                     description: ''
                                     type: integer
-                                required: *id203
+                                required: *id214
                                 type: object
-                            required: *id204
+                            required: *id215
                             type: object
                           osd:
                             description: ''
@@ -27499,7 +27849,7 @@ paths:
                                   x86_64:
                                     description: ''
                                     type: integer
-                                required: *id205
+                                required: *id216
                                 type: object
                               ceph_version:
                                 description: ''
@@ -27507,7 +27857,7 @@ paths:
                                   ceph version 16.0.0-3151-gf202994fcf:
                                     description: ''
                                     type: integer
-                                required: *id206
+                                required: *id217
                                 type: object
                               cpu:
                                 description: ''
@@ -27515,7 +27865,7 @@ paths:
                                   Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz:
                                     description: ''
                                     type: integer
-                                required: *id207
+                                required: *id218
                                 type: object
                               distro:
                                 description: ''
@@ -27523,7 +27873,7 @@ paths:
                                   centos:
                                     description: ''
                                     type: integer
-                                required: *id208
+                                required: *id219
                                 type: object
                               distro_description:
                                 description: ''
@@ -27531,7 +27881,7 @@ paths:
                                   CentOS Linux 8 (Core):
                                     description: ''
                                     type: integer
-                                required: *id209
+                                required: *id220
                                 type: object
                               kernel_description:
                                 description: ''
@@ -27539,7 +27889,7 @@ paths:
                                   '#1 SMP Wed Jul 1 19:53:01 UTC 2020':
                                     description: ''
                                     type: integer
-                                required: *id210
+                                required: *id221
                                 type: object
                               kernel_version:
                                 description: ''
@@ -27547,7 +27897,7 @@ paths:
                                   5.7.7-200.fc32.x86_64:
                                     description: ''
                                     type: integer
-                                required: *id211
+                                required: *id222
                                 type: object
                               os:
                                 description: ''
@@ -27555,7 +27905,7 @@ paths:
                                   Linux:
                                     description: ''
                                     type: integer
-                                required: *id212
+                                required: *id223
                                 type: object
                               osd_objectstore:
                                 description: ''
@@ -27563,7 +27913,7 @@ paths:
                                   bluestore:
                                     description: ''
                                     type: integer
-                                required: *id213
+                                required: *id224
                                 type: object
                               rotational:
                                 description: ''
@@ -27571,11 +27921,11 @@ paths:
                                   '1':
                                     description: ''
                                     type: integer
-                                required: *id214
+                                required: *id225
                                 type: object
-                            required: *id215
+                            required: *id226
                             type: object
-                        required: *id216
+                        required: *id227
                         type: object
                       mon:
                         description: ''
@@ -27596,7 +27946,7 @@ paths:
                                 items:
                                   type: string
                                 type: array
-                            required: *id217
+                            required: *id228
                             type: object
                           ipv4_addr_mons:
                             description: ''
@@ -27613,7 +27963,7 @@ paths:
                           v2_addr_mons:
                             description: ''
                             type: integer
-                        required: *id218
+                        required: *id229
                         type: object
                       osd:
                         description: ''
@@ -27630,7 +27980,7 @@ paths:
                           require_osd_release:
                             description: ''
                             type: string
-                        required: *id219
+                        required: *id230
                         type: object
                       pools:
                         description: ''
@@ -27669,7 +28019,7 @@ paths:
                             type:
                               description: ''
                               type: string
-                          required: *id220
+                          required: *id231
                           type: object
                         type: array
                       rbd:
@@ -27688,7 +28038,7 @@ paths:
                           num_pools:
                             description: ''
                             type: integer
-                        required: *id221
+                        required: *id232
                         type: object
                       report_id:
                         description: ''
@@ -27716,7 +28066,7 @@ paths:
                           zones:
                             description: ''
                             type: integer
-                        required: *id222
+                        required: *id233
                         type: object
                       services:
                         description: ''
@@ -27724,7 +28074,7 @@ paths:
                           rgw:
                             description: ''
                             type: integer
-                        required: *id223
+                        required: *id234
                         type: object
                       usage:
                         description: ''
@@ -27744,11 +28094,11 @@ paths:
                           total_used_bytes:
                             description: ''
                             type: integer
-                        required: *id224
+                        required: *id235
                         type: object
-                    required: *id225
+                    required: *id236
                     type: object
-                required: *id226
+                required: *id237
                 type: object
           description: OK
         '400':
@@ -27800,7 +28150,7 @@ paths:
                   username:
                     description: Username of the user
                     type: string
-                required: &id227
+                required: &id238
                 - username
                 - roles
                 - name
@@ -27839,7 +28189,7 @@ paths:
                   username:
                     description: Username of the user
                     type: string
-                required: *id227
+                required: *id238
                 type: object
           description: OK
         '400':
index 9fde6b40d78795d3b8c011a15a0241edaa64db34..ec243edb494790916ddbe8a9709562294271a070 100644 (file)
@@ -301,6 +301,47 @@ class CephFSMirrorTest(ControllerTestCase):
         self.assertIn(error_message, response.get('detail', ''))
         mgr.remote.assert_called_once_with('mirroring', 'snapshot_mirror_ls', fs_name)
 
+    def test_mirror_status_success(self):
+        fs_name = 'test_fs'
+        peer_uuid = 'peer-uuid-123'
+        expected_status = {
+            'metrics': {
+                '/dir1': {
+                    'peer': {
+                        peer_uuid: {
+                            'state': 'idle',
+                            'last_synced_snap': {
+                                'name': 'snap1',
+                                'sync_bytes': '1.00 KiB',
+                                'sync_time_stamp': '1704189600.000000s'
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        mock_output = json.dumps(expected_status)
+        mgr.remote = Mock(return_value=(0, mock_output, ''))
+
+        self._get(f'/api/cephfs/mirror/{fs_name}/status?peer_id={peer_uuid}')
+        self.assertStatus(200)
+        self.assertJsonBody(expected_status)
+        mgr.remote.assert_called_once_with(
+            'mirroring', 'snapshot_mirror_status', fs_name, None, peer_uuid)
+
+    def test_mirror_status_error(self):
+        fs_name = 'test_fs'
+        error_message = 'no cephfs-mirror daemon available'
+        mgr.remote = Mock(return_value=(1, '', error_message))
+
+        self._get(f'/api/cephfs/mirror/{fs_name}/status')
+        self.assertStatus(400)
+        response = self.json_body()
+        self.assertIn('Failed to get Cephfs mirror status', response.get('detail', ''))
+        self.assertIn(error_message, response.get('detail', ''))
+        mgr.remote.assert_called_once_with(
+            'mirroring', 'snapshot_mirror_status', fs_name, None, None)
+
 
 class CephFSMirrorStatusTest(ControllerTestCase):