Skip to content

Commit e608006

Browse files
authored
Merge pull request ceph#54853 from ivoalmeida/snapshot-schedule-module
mgr/dashboard: snap schedule module detect/enable Reviewed-by: Pedro Gonzalez Gomez <pegonzal@redhat.com> Reviewed-by: Ankush Behl <cloudbehl@gmail.com> Reviewed-by: Nizamudeen A <nia@redhat.com>
2 parents 41652f8 + a57036a commit e608006

File tree

3 files changed

+149
-40
lines changed

3 files changed

+149
-40
lines changed

src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.html

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,66 @@
1-
<ng-container *ngIf="isLoading$ | async">
2-
<cd-loading-panel>
3-
<span i18n>Loading snapshot schedules...</span>
4-
</cd-loading-panel>
5-
</ng-container>
1+
<cd-alert-panel
2+
*ngIf="(snapScheduleModuleStatus$ | async) === false"
3+
type="info"
4+
spacingClass="mb-3"
5+
i18n
6+
class="align-items-center"
7+
>
8+
In order to access the snapshot scheduler feature, the snap_scheduler module must be enabled
9+
<button
10+
class="btn btn-light mx-2"
11+
type="button"
12+
(click)="enableSnapshotSchedule()">
13+
Enable
14+
</button>
15+
</cd-alert-panel>
616

7-
<ng-template #pathTpl
8-
let-row="row">
17+
<ng-template
18+
#pathTpl
19+
let-row="row">
920
<span
1021
class="fw-bold"
1122
[ngbTooltip]="fullpathTpl"
12-
triggers="click:blur">{{row.path | path}}</span>
23+
triggers="click:blur">
24+
{{ row.path | path }}
25+
</span>
1326

14-
<span *ngIf="row.active; else inactiveStatusTpl">
15-
<i [ngClass]="[icons.success, icons.large]"
16-
ngbTooltip="{{row.path}} is active"
17-
class="text-success"></i>
27+
<span
28+
*ngIf="row.active; else inactiveStatusTpl">
29+
<i
30+
[ngClass]="[icons.success, icons.large]"
31+
ngbTooltip="{{ row.path }} is active"
32+
class="text-success"
33+
></i>
1834
</span>
1935

2036
<ng-template #inactiveStatusTpl>
21-
<i [ngClass]="[icons.warning, icons.large]"
22-
class="text-warning"
23-
ngbTooltip="{{row.path}} has been deactivated"></i>
37+
<i
38+
[ngClass]="[icons.warning, icons.large]"
39+
class="text-warning"
40+
ngbTooltip="{{ row.path }} has been deactivated"
41+
></i>
2442
</ng-template>
2543

2644
<ng-template #fullpathTpl>
27-
<span data-toggle="tooltip"
28-
[title]="row.path"
29-
class="font-monospace">{{ row.path }}
30-
<cd-copy-2-clipboard-button *ngIf="row.path"
31-
[source]="row.path"
32-
[byId]="false"
33-
[showIconOnly]="true">
34-
</cd-copy-2-clipboard-button>
35-
</span>
36-
</ng-template>
37-
45+
<span
46+
data-toggle="tooltip"
47+
[title]="row.path"
48+
class="font-monospace"
49+
>{{ row.path }}
50+
<cd-copy-2-clipboard-button
51+
*ngIf="row.path"
52+
[source]="row.path"
53+
[byId]="false"
54+
[showIconOnly]="true"
55+
>
56+
</cd-copy-2-clipboard-button>
57+
</span>
58+
</ng-template>
3859
</ng-template>
3960

4061
<cd-table
4162
[data]="snapshotSchedules$ | async"
63+
*ngIf="snapScheduleModuleStatus$ | async"
4264
columnMode="flex"
4365
[columns]="columns"
4466
selectionType="single"

src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-snapshotschedule-list/cephfs-snapshotschedule-list.component.ts

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
import { Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
1+
import {
2+
Component,
3+
Input,
4+
OnChanges,
5+
OnDestroy,
6+
OnInit,
7+
SimpleChanges,
8+
ViewChild
9+
} from '@angular/core';
210
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
3-
import { BehaviorSubject, Observable } from 'rxjs';
4-
import { finalize, shareReplay, switchMap } from 'rxjs/operators';
11+
import { BehaviorSubject, Observable, Subscription, of, timer } from 'rxjs';
12+
import { finalize, map, shareReplay, switchMap } from 'rxjs/operators';
513
import { CephfsSnapshotScheduleService } from '~/app/shared/api/cephfs-snapshot-schedule.service';
614
import { CdForm } from '~/app/shared/forms/cd-form';
715
import { CdTableAction } from '~/app/shared/models/cd-table-action';
@@ -14,21 +22,31 @@ import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
1422
import { ModalService } from '~/app/shared/services/modal.service';
1523
import { Icons } from '~/app/shared/enum/icons.enum';
1624
import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
25+
import { MgrModuleService } from '~/app/shared/api/mgr-module.service';
26+
import { NotificationService } from '~/app/shared/services/notification.service';
27+
import { BlockUI, NgBlockUI } from 'ng-block-ui';
28+
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
1729

1830
@Component({
1931
selector: 'cd-cephfs-snapshotschedule-list',
2032
templateUrl: './cephfs-snapshotschedule-list.component.html',
2133
styleUrls: ['./cephfs-snapshotschedule-list.component.scss']
2234
})
23-
export class CephfsSnapshotscheduleListComponent extends CdForm implements OnInit, OnChanges {
35+
export class CephfsSnapshotscheduleListComponent
36+
extends CdForm
37+
implements OnInit, OnChanges, OnDestroy {
2438
@Input() fsName!: string;
2539

2640
@ViewChild('pathTpl', { static: true })
2741
pathTpl: any;
2842

43+
@BlockUI()
44+
blockUI: NgBlockUI;
45+
2946
snapshotSchedules$!: Observable<SnapshotSchedule[]>;
3047
subject$ = new BehaviorSubject<SnapshotSchedule[]>([]);
31-
isLoading$ = new BehaviorSubject<boolean>(true);
48+
snapScheduleModuleStatus$ = new BehaviorSubject<boolean>(false);
49+
moduleServiceListSub!: Subscription;
3250
columns: CdTableColumn[] = [];
3351
tableActions: CdTableAction[] = [];
3452
context!: CdTableFetchDataContext;
@@ -39,10 +57,15 @@ export class CephfsSnapshotscheduleListComponent extends CdForm implements OnIni
3957
selectedName: string = '';
4058
icons = Icons;
4159

60+
MODULE_NAME = 'snap_schedule';
61+
ENABLE_MODULE_TIMER = 2 * 1000;
62+
4263
constructor(
4364
private snapshotScheduleService: CephfsSnapshotScheduleService,
4465
private authStorageService: AuthStorageService,
45-
private modalService: ModalService
66+
private modalService: ModalService,
67+
private mgrModuleService: MgrModuleService,
68+
private notificationService: NotificationService
4669
) {
4770
super();
4871
this.permissions = this.authStorageService.getPermissions();
@@ -55,13 +78,27 @@ export class CephfsSnapshotscheduleListComponent extends CdForm implements OnIni
5578
}
5679

5780
ngOnInit(): void {
81+
this.moduleServiceListSub = this.mgrModuleService
82+
.list()
83+
.pipe(
84+
map((modules: any[]) => modules.find((module) => module?.['name'] === this.MODULE_NAME))
85+
)
86+
.subscribe({
87+
next: (module: any) => this.snapScheduleModuleStatus$.next(module?.enabled)
88+
});
89+
5890
this.snapshotSchedules$ = this.subject$.pipe(
5991
switchMap(() =>
60-
this.snapshotScheduleService
61-
.getSnapshotScheduleList('/', this.fsName)
62-
.pipe(finalize(() => this.isLoading$.next(false)))
63-
),
64-
shareReplay(1)
92+
this.snapScheduleModuleStatus$.pipe(
93+
switchMap((status) => {
94+
if (!status) {
95+
return of([]);
96+
}
97+
return this.snapshotScheduleService.getSnapshotScheduleList('/', this.fsName);
98+
}),
99+
shareReplay(1)
100+
)
101+
)
65102
);
66103

67104
this.columns = [
@@ -78,6 +115,10 @@ export class CephfsSnapshotscheduleListComponent extends CdForm implements OnIni
78115
this.tableActions = [];
79116
}
80117

118+
ngOnDestroy(): void {
119+
this.moduleServiceListSub.unsubscribe();
120+
}
121+
81122
fetchData() {
82123
this.subject$.next([]);
83124
}
@@ -96,4 +137,48 @@ export class CephfsSnapshotscheduleListComponent extends CdForm implements OnIni
96137
{ size: 'lg' }
97138
);
98139
}
140+
141+
enableSnapshotSchedule() {
142+
let $obs;
143+
const fnWaitUntilReconnected = () => {
144+
timer(this.ENABLE_MODULE_TIMER).subscribe(() => {
145+
// Trigger an API request to check if the connection is
146+
// re-established.
147+
this.mgrModuleService.list().subscribe(
148+
() => {
149+
// Resume showing the notification toasties.
150+
this.notificationService.suspendToasties(false);
151+
// Unblock the whole UI.
152+
this.blockUI.stop();
153+
// Reload the data table content.
154+
this.notificationService.show(
155+
NotificationType.success,
156+
$localize`Enabled Snapshot Schedule Module`
157+
);
158+
// Reload the data table content.
159+
},
160+
() => {
161+
fnWaitUntilReconnected();
162+
}
163+
);
164+
});
165+
};
166+
167+
if (!this.snapScheduleModuleStatus$.value) {
168+
$obs = this.mgrModuleService
169+
.enable(this.MODULE_NAME)
170+
.pipe(finalize(() => this.snapScheduleModuleStatus$.next(true)));
171+
}
172+
$obs.subscribe(
173+
() => undefined,
174+
() => {
175+
// Suspend showing the notification toasties.
176+
this.notificationService.suspendToasties(true);
177+
// Block the whole UI to prevent user interactions until
178+
// the connection to the backend is reestablished
179+
this.blockUI.start($localize`Reconnecting, please wait ...`);
180+
fnWaitUntilReconnected();
181+
}
182+
);
183+
}
99184
}

src/pybind/mgr/dashboard/frontend/src/app/ceph/rgw/rgw-multisite-details/rgw-multisite-details.component.html

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
<cd-alert-panel *ngIf="!rgwModuleStatus"
55
type="info"
66
spacingClass="mb-3"
7+
class="d-flex align-items-center"
78
i18n>In order to access the import/export feature, the rgw module must be enabled
8-
<a class="text-decoration-underline"
9-
(click)="enableRgwModule()">
10-
Enable the Object Gateway Module</a>
9+
10+
<button class="btn btn-light mx-2"
11+
type="button"
12+
(click)="enableRgwModule()">Enable</button>
1113
</cd-alert-panel>
1214
<cd-alert-panel *ngIf="restartGatewayMessage"
1315
type="warning"

0 commit comments

Comments
 (0)