From: Ivo Almeida Date: Sat, 25 Nov 2023 19:10:35 +0000 (+0000) Subject: mgr/dashboard: added snap-schedule api and ui list X-Git-Tag: v19.3.0~394^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F54750%2Fhead;p=ceph.git mgr/dashboard: added snap-schedule api and ui list Fixes: https://tracker.ceph.com/issues/63767 Signed-off-by: Ivo Almeida --- diff --git a/src/pybind/mgr/dashboard/controllers/cephfs.py b/src/pybind/mgr/dashboard/controllers/cephfs.py index eb1f764c472b..61b31eb809fd 100644 --- a/src/pybind/mgr/dashboard/controllers/cephfs.py +++ b/src/pybind/mgr/dashboard/controllers/cephfs.py @@ -863,3 +863,33 @@ class CephFSSubvolumeSnapshots(RESTController): ) snapshot['info'] = json.loads(out) return snapshots + + +@APIRouter('/cephfs/snaphost/schedule', Scope.CEPHFS) +@APIDoc("Cephfs Snapshot Scheduling API", "CephFSSnapshotSchedule") +class CephFSSnapshotSchedule(RESTController): + + def list(self, fs: str, path: str = '/', recursive: bool = True): + error_code, out, err = mgr.remote('snap_schedule', 'snap_schedule_list', + path, recursive, fs, 'plain') + + if len(out) == 0: + return [] + + snapshot_schedule_list = out.split('\n') + output = [] + + for snap in snapshot_schedule_list: + current_path = snap.strip().split(' ')[0] + error_code, status_out, err = mgr.remote('snap_schedule', 'snap_schedule_get', + current_path, fs, 'plain') + output.append(json.loads(status_out)) + + output_json = json.dumps(output) + + if error_code != 0: + raise DashboardException( + f'Failed to get list of snapshot schedules for path {path}: {err}' + ) + + return json.loads(output_json) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.html new file mode 100644 index 000000000000..2e270057d579 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.html @@ -0,0 +1,58 @@ + + + Loading snapshot schedules... + + + + + {{row.path | path}} + + + + + + + + + + + {{ row.path }} + + + + + + + + +
+ + +
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.scss new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.spec.ts new file mode 100644 index 000000000000..a20972f1cf85 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.spec.ts @@ -0,0 +1,30 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CephfsSnapshotscheduleListComponent } from './cephfs-snapshotschedule-list.component'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { SharedModule } from '~/app/shared/shared.module'; +import { ToastrModule } from 'ngx-toastr'; +import { RouterTestingModule } from '@angular/router/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { configureTestBed } from '~/testing/unit-test-helper'; + +describe('CephfsSnapshotscheduleListComponent', () => { + let component: CephfsSnapshotscheduleListComponent; + let fixture: ComponentFixture; + + configureTestBed({ + declarations: [CephfsSnapshotscheduleListComponent], + imports: [HttpClientTestingModule, SharedModule, ToastrModule.forRoot(), RouterTestingModule], + providers: [NgbActiveModal] + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CephfsSnapshotscheduleListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts new file mode 100644 index 000000000000..d5f24e897284 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts @@ -0,0 +1,99 @@ +import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { finalize, shareReplay, switchMap } from 'rxjs/operators'; +import { CephfsSnapshotScheduleService } from '~/app/shared/api/cephfs-snapshot-schedule.service'; +import { CdForm } from '~/app/shared/forms/cd-form'; +import { CdTableAction } from '~/app/shared/models/cd-table-action'; +import { CdTableColumn } from '~/app/shared/models/cd-table-column'; +import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context'; +import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; +import { Permissions } from '~/app/shared/models/permissions'; +import { SnapshotSchedule } from '~/app/shared/models/snapshot-schedule'; +import { AuthStorageService } from '~/app/shared/services/auth-storage.service'; +import { ModalService } from '~/app/shared/services/modal.service'; +import { Icons } from '~/app/shared/enum/icons.enum'; +import { CellTemplate } from '~/app/shared/enum/cell-template.enum'; + +@Component({ + selector: 'cd-cephfs-snapshotschedule-list', + templateUrl: './cephfs-snapshotschedule-list.component.html', + styleUrls: ['./cephfs-snapshotschedule-list.component.scss'] +}) +export class CephfsSnapshotscheduleListComponent extends CdForm implements OnInit, OnChanges { + @Input() fsName!: string; + + @ViewChild('pathTpl', { static: true }) + pathTpl: any; + + snapshotSchedules$!: Observable; + subject$ = new BehaviorSubject([]); + isLoading$ = new BehaviorSubject(true); + columns: CdTableColumn[] = []; + tableActions: CdTableAction[] = []; + context!: CdTableFetchDataContext; + selection = new CdTableSelection(); + permissions!: Permissions; + modalRef!: NgbModalRef; + errorMessage: string = ''; + selectedName: string = ''; + icons = Icons; + + constructor( + private snapshotScheduleService: CephfsSnapshotScheduleService, + private authStorageService: AuthStorageService, + private modalService: ModalService + ) { + super(); + this.permissions = this.authStorageService.getPermissions(); + } + + ngOnChanges(changes: SimpleChanges): void { + if (changes.fsName) { + this.subject$.next([]); + } + } + + ngOnInit(): void { + this.snapshotSchedules$ = this.subject$.pipe( + switchMap(() => + this.snapshotScheduleService + .getSnapshotScheduleList('/', this.fsName) + .pipe(finalize(() => this.isLoading$.next(false))) + ), + shareReplay(1) + ); + + this.columns = [ + { prop: 'path', name: $localize`Path`, flexGrow: 3, cellTemplate: this.pathTpl }, + { prop: 'subvol', name: $localize`Subvolume` }, + { prop: 'schedule', name: $localize`Repeat interval` }, + { prop: 'retention', name: $localize`Retention policy` }, + { prop: 'created_count', name: $localize`Created Count` }, + { prop: 'pruned_count', name: $localize`Deleted Count` }, + { prop: 'start', name: $localize`Start time`, cellTransformation: CellTemplate.timeAgo }, + { prop: 'created', name: $localize`Created`, cellTransformation: CellTemplate.timeAgo } + ]; + + this.tableActions = []; + } + + fetchData() { + this.subject$.next([]); + } + + updateSelection(selection: CdTableSelection) { + this.selection = selection; + } + + openModal(edit = false) { + this.modalService.show( + {}, + { + fsName: 'fs1', + isEdit: edit + }, + { size: 'lg' } + ); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.html index 6a50ad2e0786..87268858be50 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-tabs/cephfs-tabs.component.html @@ -1,71 +1,94 @@ -