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