]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/mgr-modules/mgr-module-list/mgr-module-list.component.ts
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / ceph / cluster / mgr-modules / mgr-module-list / mgr-module-list.component.ts
CommitLineData
11fdf7f2
TL
1import { Component, ViewChild } from '@angular/core';
2
3import { I18n } from '@ngx-translate/i18n-polyfill';
4import { BlockUI, NgBlockUI } from 'ng-block-ui';
5import { timer as observableTimer } from 'rxjs';
6
7import { MgrModuleService } from '../../../../shared/api/mgr-module.service';
8import { TableComponent } from '../../../../shared/datatable/table/table.component';
9import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
10import { CdTableAction } from '../../../../shared/models/cd-table-action';
11import { CdTableColumn } from '../../../../shared/models/cd-table-column';
12import { CdTableFetchDataContext } from '../../../../shared/models/cd-table-fetch-data-context';
13import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
14import { Permission } from '../../../../shared/models/permissions';
15import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
16import { NotificationService } from '../../../../shared/services/notification.service';
17
18@Component({
19 selector: 'cd-mgr-module-list',
20 templateUrl: './mgr-module-list.component.html',
21 styleUrls: ['./mgr-module-list.component.scss']
22})
23export class MgrModuleListComponent {
24 @ViewChild(TableComponent)
25 table: TableComponent;
26 @BlockUI()
27 blockUI: NgBlockUI;
28
29 permission: Permission;
30 tableActions: CdTableAction[];
31 columns: CdTableColumn[] = [];
32 modules: object[] = [];
33 selection: CdTableSelection = new CdTableSelection();
34
35 constructor(
36 private authStorageService: AuthStorageService,
37 private mgrModuleService: MgrModuleService,
38 private notificationService: NotificationService,
39 private i18n: I18n
40 ) {
41 this.permission = this.authStorageService.getPermissions().configOpt;
42 this.columns = [
43 {
44 name: this.i18n('Name'),
45 prop: 'name',
46 flexGrow: 1
47 },
48 {
49 name: this.i18n('Enabled'),
50 prop: 'enabled',
51 flexGrow: 1,
52 cellClass: 'text-center',
53 cellTransformation: CellTemplate.checkIcon
54 }
55 ];
56 const getModuleUri = () =>
57 this.selection.first() && encodeURIComponent(this.selection.first().name);
58 this.tableActions = [
59 {
60 name: this.i18n('Edit'),
61 permission: 'update',
62 disable: () => {
63 if (!this.selection.hasSelection) {
64 return true;
65 }
66 // Disable the 'edit' button when the module has no options.
67 return Object.values(this.selection.first().options).length === 0;
68 },
69 routerLink: () => `/mgr-modules/edit/${getModuleUri()}`,
70 icon: 'fa-pencil'
71 },
72 {
73 name: this.i18n('Enable'),
74 permission: 'update',
75 click: () => this.updateModuleState(),
76 disable: () => this.isTableActionDisabled('enabled'),
77 icon: 'fa-play'
78 },
79 {
80 name: this.i18n('Disable'),
81 permission: 'update',
82 click: () => this.updateModuleState(),
83 disable: () => this.isTableActionDisabled('disabled'),
92f5a8d4 84 disableDesc: () => this.getTableActionDisabledDesc(),
11fdf7f2
TL
85 icon: 'fa-stop'
86 }
87 ];
88 }
89
90 getModuleList(context: CdTableFetchDataContext) {
91 this.mgrModuleService.list().subscribe(
92 (resp: object[]) => {
93 this.modules = resp;
94 },
95 () => {
96 context.error();
97 }
98 );
99 }
100
101 updateSelection(selection: CdTableSelection) {
102 this.selection = selection;
103 }
104
105 /**
106 * Check if the table action is disabled.
107 * @param state The expected module state, e.g. ``enabled`` or ``disabled``.
108 * @returns If the specified state is validated to true or no selection is
109 * done, then ``true`` is returned, otherwise ``false``.
110 */
111 isTableActionDisabled(state: 'enabled' | 'disabled') {
112 if (!this.selection.hasSelection) {
113 return true;
114 }
92f5a8d4 115 const selected = this.selection.first();
11fdf7f2
TL
116 // Make sure the user can't modify the run state of the 'Dashboard' module.
117 // This check is only done in the UI because the REST API should still be
118 // able to do so.
92f5a8d4
TL
119 if (selected.name === 'dashboard') {
120 return true;
121 }
122 // Always-on modules can't be disabled.
123 if (selected.always_on) {
11fdf7f2
TL
124 return true;
125 }
126 switch (state) {
127 case 'enabled':
92f5a8d4 128 return selected.enabled;
11fdf7f2 129 case 'disabled':
92f5a8d4
TL
130 return !selected.enabled;
131 }
132 }
133
134 getTableActionDisabledDesc(): string | undefined {
135 if (this.selection.hasSelection) {
136 const selected = this.selection.first();
137 if (selected.always_on) {
138 return this.i18n('This Manager module is always on.');
139 }
11fdf7f2
TL
140 }
141 }
142
143 /**
144 * Update the Ceph Mgr module state to enabled or disabled.
145 */
146 updateModuleState() {
147 if (!this.selection.hasSelection) {
148 return;
149 }
150
151 let $obs;
152 const fnWaitUntilReconnected = () => {
153 observableTimer(2000).subscribe(() => {
154 // Trigger an API request to check if the connection is
155 // re-established.
156 this.mgrModuleService.list().subscribe(
157 () => {
158 // Resume showing the notification toasties.
159 this.notificationService.suspendToasties(false);
160 // Unblock the whole UI.
161 this.blockUI.stop();
162 // Reload the data table content.
163 this.table.refreshBtn();
164 },
165 () => {
166 fnWaitUntilReconnected();
167 }
168 );
169 });
170 };
171
172 // Note, the Ceph Mgr is always restarted when a module
173 // is enabled/disabled.
174 const module = this.selection.first();
175 if (module.enabled) {
176 $obs = this.mgrModuleService.disable(module.name);
177 } else {
178 $obs = this.mgrModuleService.enable(module.name);
179 }
180 $obs.subscribe(
181 () => {},
182 () => {
183 // Suspend showing the notification toasties.
184 this.notificationService.suspendToasties(true);
185 // Block the whole UI to prevent user interactions until
186 // the connection to the backend is reestablished
187 this.blockUI.start(this.i18n('Reconnecting, please wait ...'));
188 fnWaitUntilReconnected();
189 }
190 );
191 }
192}