]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts
import ceph 16.2.7
[ceph.git] / ceph / src / pybind / mgr / dashboard / frontend / src / app / shared / services / task-message.service.ts
1 import { Injectable } from '@angular/core';
2
3 import { Components } from '../enum/components.enum';
4 import { FinishedTask } from '../models/finished-task';
5 import { ImageSpec } from '../models/image-spec';
6 import { Task } from '../models/task';
7
8 export class TaskMessageOperation {
9 running: string;
10 failure: string;
11 success: string;
12
13 constructor(running: string, failure: string, success: string) {
14 this.running = running;
15 this.failure = failure;
16 this.success = success;
17 }
18 }
19
20 class TaskMessage {
21 operation: TaskMessageOperation;
22 involves: (object: any) => string;
23 errors: (metadata: any) => object;
24
25 failure(metadata: any): string {
26 return $localize`Failed to ${this.operation.failure} ${this.involves(metadata)}`;
27 }
28
29 running(metadata: any): string {
30 return `${this.operation.running} ${this.involves(metadata)}`;
31 }
32
33 success(metadata: any): string {
34 return `${this.operation.success} ${this.involves(metadata)}`;
35 }
36
37 constructor(
38 operation: TaskMessageOperation,
39 involves: (metadata: any) => string,
40 errors?: (metadata: any) => object
41 ) {
42 this.operation = operation;
43 this.involves = involves;
44 this.errors = errors || (() => ({}));
45 }
46 }
47
48 @Injectable({
49 providedIn: 'root'
50 })
51 export class TaskMessageService {
52 defaultMessage = this.newTaskMessage(
53 new TaskMessageOperation($localize`Executing`, $localize`execute`, $localize`Executed`),
54 (metadata) => {
55 return (
56 (metadata && (Components[metadata.component] || metadata.component)) ||
57 $localize`unknown task`
58 );
59 },
60 () => {
61 return {};
62 }
63 );
64
65 commonOperations = {
66 create: new TaskMessageOperation($localize`Creating`, $localize`create`, $localize`Created`),
67 update: new TaskMessageOperation($localize`Updating`, $localize`update`, $localize`Updated`),
68 delete: new TaskMessageOperation($localize`Deleting`, $localize`delete`, $localize`Deleted`),
69 add: new TaskMessageOperation($localize`Adding`, $localize`add`, $localize`Added`),
70 remove: new TaskMessageOperation($localize`Removing`, $localize`remove`, $localize`Removed`),
71 import: new TaskMessageOperation($localize`Importing`, $localize`import`, $localize`Imported`)
72 };
73
74 rbd = {
75 default: (metadata: any) => $localize`RBD '${metadata.image_spec}'`,
76 create: (metadata: any) => {
77 const id = new ImageSpec(
78 metadata.pool_name,
79 metadata.namespace,
80 metadata.image_name
81 ).toString();
82 return $localize`RBD '${id}'`;
83 },
84 child: (metadata: any) => {
85 const id = new ImageSpec(
86 metadata.child_pool_name,
87 metadata.child_namespace,
88 metadata.child_image_name
89 ).toString();
90 return $localize`RBD '${id}'`;
91 },
92 destination: (metadata: any) => {
93 const id = new ImageSpec(
94 metadata.dest_pool_name,
95 metadata.dest_namespace,
96 metadata.dest_image_name
97 ).toString();
98 return $localize`RBD '${id}'`;
99 },
100 snapshot: (metadata: any) =>
101 $localize`RBD snapshot '${metadata.image_spec}@${metadata.snapshot_name}'`
102 };
103
104 rbd_mirroring = {
105 site_name: () => $localize`mirroring site name`,
106 bootstrap: () => $localize`bootstrap token`,
107 pool: (metadata: any) => $localize`mirror mode for pool '${metadata.pool_name}'`,
108 pool_peer: (metadata: any) => $localize`mirror peer for pool '${metadata.pool_name}'`
109 };
110
111 grafana = {
112 update_dashboards: () => $localize`all dashboards`
113 };
114
115 messages = {
116 // Host tasks
117 'host/add': this.newTaskMessage(this.commonOperations.add, (metadata) => this.host(metadata)),
118 'host/remove': this.newTaskMessage(this.commonOperations.remove, (metadata) =>
119 this.host(metadata)
120 ),
121 'host/identify_device': this.newTaskMessage(
122 new TaskMessageOperation($localize`Identifying`, $localize`identify`, $localize`Identified`),
123 (metadata) => $localize`device '${metadata.device}' on host '${metadata.hostname}'`
124 ),
125 // OSD tasks
126 'osd/create': this.newTaskMessage(
127 this.commonOperations.create,
128 (metadata) => $localize`OSDs (DriveGroups: ${metadata.tracking_id})`
129 ),
130 'osd/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
131 this.osd(metadata)
132 ),
133 // Pool tasks
134 'pool/create': this.newTaskMessage(
135 this.commonOperations.create,
136 (metadata) => this.pool(metadata),
137 (metadata) => ({
138 '17': $localize`Name is already used by ${this.pool(metadata)}.`
139 })
140 ),
141 'pool/edit': this.newTaskMessage(
142 this.commonOperations.update,
143 (metadata) => this.pool(metadata),
144 (metadata) => ({
145 '17': $localize`Name is already used by ${this.pool(metadata)}.`
146 })
147 ),
148 'pool/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
149 this.pool(metadata)
150 ),
151 // Erasure code profile tasks
152 'ecp/create': this.newTaskMessage(
153 this.commonOperations.create,
154 (metadata) => this.ecp(metadata),
155 (metadata) => ({
156 '17': $localize`Name is already used by ${this.ecp(metadata)}.`
157 })
158 ),
159 'ecp/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
160 this.ecp(metadata)
161 ),
162 // Crush rule tasks
163 'crushRule/create': this.newTaskMessage(
164 this.commonOperations.create,
165 (metadata) => this.crushRule(metadata),
166 (metadata) => ({
167 '17': $localize`Name is already used by ${this.crushRule(metadata)}.`
168 })
169 ),
170 'crushRule/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
171 this.crushRule(metadata)
172 ),
173 // RBD tasks
174 'rbd/create': this.newTaskMessage(
175 this.commonOperations.create,
176 this.rbd.create,
177 (metadata) => ({
178 '17': $localize`Name is already used by ${this.rbd.create(metadata)}.`
179 })
180 ),
181 'rbd/edit': this.newTaskMessage(this.commonOperations.update, this.rbd.default, (metadata) => ({
182 '17': $localize`Name is already used by ${this.rbd.default(metadata)}.`
183 })),
184 'rbd/delete': this.newTaskMessage(
185 this.commonOperations.delete,
186 this.rbd.default,
187 (metadata) => ({
188 '16': $localize`${this.rbd.default(metadata)} is busy.`,
189 '39': $localize`${this.rbd.default(metadata)} contains snapshots.`
190 })
191 ),
192 'rbd/clone': this.newTaskMessage(
193 new TaskMessageOperation($localize`Cloning`, $localize`clone`, $localize`Cloned`),
194 this.rbd.child,
195 (metadata) => ({
196 '17': $localize`Name is already used by ${this.rbd.child(metadata)}.`,
197 '22': $localize`Snapshot of ${this.rbd.child(metadata)} must be protected.`
198 })
199 ),
200 'rbd/copy': this.newTaskMessage(
201 new TaskMessageOperation($localize`Copying`, $localize`copy`, $localize`Copied`),
202 this.rbd.destination,
203 (metadata) => ({
204 '17': $localize`Name is already used by ${this.rbd.destination(metadata)}.`
205 })
206 ),
207 'rbd/flatten': this.newTaskMessage(
208 new TaskMessageOperation($localize`Flattening`, $localize`flatten`, $localize`Flattened`),
209 this.rbd.default
210 ),
211 // RBD snapshot tasks
212 'rbd/snap/create': this.newTaskMessage(
213 this.commonOperations.create,
214 this.rbd.snapshot,
215 (metadata) => ({
216 '17': $localize`Name is already used by ${this.rbd.snapshot(metadata)}.`
217 })
218 ),
219 'rbd/snap/edit': this.newTaskMessage(
220 this.commonOperations.update,
221 this.rbd.snapshot,
222 (metadata) => ({
223 '16': $localize`Cannot unprotect ${this.rbd.snapshot(
224 metadata
225 )} because it contains child images.`
226 })
227 ),
228 'rbd/snap/delete': this.newTaskMessage(
229 this.commonOperations.delete,
230 this.rbd.snapshot,
231 (metadata) => ({
232 '16': $localize`Cannot delete ${this.rbd.snapshot(metadata)} because it's protected.`
233 })
234 ),
235 'rbd/snap/rollback': this.newTaskMessage(
236 new TaskMessageOperation(
237 $localize`Rolling back`,
238 $localize`rollback`,
239 $localize`Rolled back`
240 ),
241 this.rbd.snapshot
242 ),
243 // RBD trash tasks
244 'rbd/trash/move': this.newTaskMessage(
245 new TaskMessageOperation($localize`Moving`, $localize`move`, $localize`Moved`),
246 (metadata) => $localize`image '${metadata.image_spec}' to trash`,
247 () => ({
248 2: $localize`Could not find image.`
249 })
250 ),
251 'rbd/trash/restore': this.newTaskMessage(
252 new TaskMessageOperation($localize`Restoring`, $localize`restore`, $localize`Restored`),
253 (metadata) => $localize`image '${metadata.image_id_spec}' into '${metadata.new_image_name}'`,
254 (metadata) => ({
255 17: $localize`Image name '${metadata.new_image_name}' is already in use.`
256 })
257 ),
258 'rbd/trash/remove': this.newTaskMessage(
259 new TaskMessageOperation($localize`Deleting`, $localize`delete`, $localize`Deleted`),
260 (metadata) => $localize`image '${metadata.image_id_spec}'`
261 ),
262 'rbd/trash/purge': this.newTaskMessage(
263 new TaskMessageOperation($localize`Purging`, $localize`purge`, $localize`Purged`),
264 (metadata) => {
265 let message = $localize`all pools`;
266 if (metadata.pool_name) {
267 message = `'${metadata.pool_name}'`;
268 }
269 return $localize`images from ${message}`;
270 }
271 ),
272 // RBD mirroring tasks
273 'rbd/mirroring/site_name/edit': this.newTaskMessage(
274 this.commonOperations.update,
275 this.rbd_mirroring.site_name,
276 () => ({})
277 ),
278 'rbd/mirroring/bootstrap/create': this.newTaskMessage(
279 this.commonOperations.create,
280 this.rbd_mirroring.bootstrap,
281 () => ({})
282 ),
283 'rbd/mirroring/bootstrap/import': this.newTaskMessage(
284 this.commonOperations.import,
285 this.rbd_mirroring.bootstrap,
286 () => ({})
287 ),
288 'rbd/mirroring/pool/edit': this.newTaskMessage(
289 this.commonOperations.update,
290 this.rbd_mirroring.pool,
291 () => ({
292 16: $localize`Cannot disable mirroring because it contains a peer.`
293 })
294 ),
295 'rbd/mirroring/peer/add': this.newTaskMessage(
296 this.commonOperations.create,
297 this.rbd_mirroring.pool_peer,
298 () => ({})
299 ),
300 'rbd/mirroring/peer/edit': this.newTaskMessage(
301 this.commonOperations.update,
302 this.rbd_mirroring.pool_peer,
303 () => ({})
304 ),
305 'rbd/mirroring/peer/delete': this.newTaskMessage(
306 this.commonOperations.delete,
307 this.rbd_mirroring.pool_peer,
308 () => ({})
309 ),
310 // iSCSI target tasks
311 'iscsi/target/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
312 this.iscsiTarget(metadata)
313 ),
314 'iscsi/target/edit': this.newTaskMessage(this.commonOperations.update, (metadata) =>
315 this.iscsiTarget(metadata)
316 ),
317 'iscsi/target/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
318 this.iscsiTarget(metadata)
319 ),
320 'nfs/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
321 this.nfs(metadata)
322 ),
323 'nfs/edit': this.newTaskMessage(this.commonOperations.update, (metadata) => this.nfs(metadata)),
324 'nfs/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
325 this.nfs(metadata)
326 ),
327 // Grafana tasks
328 'grafana/dashboards/update': this.newTaskMessage(
329 this.commonOperations.update,
330 this.grafana.update_dashboards,
331 () => ({})
332 ),
333 // Service tasks
334 'service/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
335 this.service(metadata)
336 ),
337 'service/edit': this.newTaskMessage(this.commonOperations.update, (metadata) =>
338 this.service(metadata)
339 ),
340 'service/delete': this.newTaskMessage(this.commonOperations.delete, (metadata) =>
341 this.service(metadata)
342 )
343 };
344
345 newTaskMessage(
346 operation: TaskMessageOperation,
347 involves: (metadata: any) => string,
348 errors?: (metadata: any) => object
349 ) {
350 return new TaskMessage(operation, involves, errors);
351 }
352
353 host(metadata: any) {
354 return $localize`host '${metadata.hostname}'`;
355 }
356
357 osd(metadata: any) {
358 return $localize`OSD '${metadata.svc_id}'`;
359 }
360
361 pool(metadata: any) {
362 return $localize`pool '${metadata.pool_name}'`;
363 }
364
365 ecp(metadata: any) {
366 return $localize`erasure code profile '${metadata.name}'`;
367 }
368
369 crushRule(metadata: any) {
370 return $localize`crush rule '${metadata.name}'`;
371 }
372
373 iscsiTarget(metadata: any) {
374 return $localize`target '${metadata.target_iqn}'`;
375 }
376
377 nfs(metadata: any) {
378 return $localize`NFS '${metadata.cluster_id}\:${
379 metadata.export_id ? metadata.export_id : metadata.path
380 }'`;
381 }
382
383 service(metadata: any) {
384 return $localize`Service '${metadata.service_name}'`;
385 }
386
387 _getTaskTitle(task: Task) {
388 if (task.name && task.name.startsWith('progress/')) {
389 // we don't fill the failure string because, at least for now, all
390 // progress module tasks will be considered successful
391 return this.newTaskMessage(
392 new TaskMessageOperation(
393 task.name.replace('progress/', ''),
394 '',
395 task.name.replace('progress/', '')
396 ),
397 (_metadata) => ''
398 );
399 }
400 return this.messages[task.name] || this.defaultMessage;
401 }
402
403 getSuccessTitle(task: FinishedTask) {
404 return this._getTaskTitle(task).success(task.metadata);
405 }
406
407 getErrorMessage(task: FinishedTask) {
408 return (
409 this._getTaskTitle(task).errors(task.metadata)[task.exception.code] || task.exception.detail
410 );
411 }
412
413 getErrorTitle(task: Task) {
414 return this._getTaskTitle(task).failure(task.metadata);
415 }
416
417 getRunningTitle(task: Task) {
418 return this._getTaskTitle(task).running(task.metadata);
419 }
420
421 getRunningText(task: Task) {
422 return this._getTaskTitle(task).operation.running;
423 }
424 }