Skip to content

Commit 4bd2fdc

Browse files
authored
Merge pull request ceph#59159 from rhcs-dashboard/rbd-table
mgr/dashboard: rbd table actions enhancements Reviewed-by: Pedro Gonzalez Gomez <[email protected]> Reviewed-by: Aashish Sharma <[email protected]> Reviewed-by: Ankush Behl <[email protected]> Reviewed-by: Nizamudeen A <[email protected]>
2 parents d3aa715 + 50ec384 commit 4bd2fdc

File tree

8 files changed

+75
-52
lines changed

8 files changed

+75
-52
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const RBDActionHelpers = {
2+
moveToTrash: $localize`Move an image to the trash. Images, even ones actively in-use by clones, can be moved to the trash and deleted at a later time.`,
3+
delete: $localize`Delete an rbd image (including all data blocks). If the image has snapshots, this fails and nothing is deleted.`,
4+
copy: $localize`Copy the content of a source image into the newly created destination image`,
5+
flatten: $localize`If the image is a clone, copy all shared blocks from the parent snapshot and make the child independent of the parent, severing the link between parent snap and child. `,
6+
enableMirroring: $localize`Mirroring needs to be enabled on the image to perform this action`,
7+
clonedSnapshot: $localize`This RBD has cloned snapshots. Please delete related RBDs before deleting this RBD`,
8+
secondayImageDelete: $localize`The image cannot be deleted as it is secondary`,
9+
primaryImageResync: $localize`Primary RBD images cannot be resynced`,
10+
invalidNameDisable: $localize`This RBD image has an invalid name and can't be managed by ceph.`,
11+
removingStatus: $localize`Action not possible for an RBD in status 'Removing'`,
12+
journalTooltipText: $localize`'Ensures reliable replication by logging changes before updating the image, but doubles write time, impacting performance. Not recommended for high-speed data processing tasks.`,
13+
snapshotTooltipText: $localize`This mode replicates RBD images between clusters using snapshots, efficiently copying data changes but requiring complete delta syncing during failover. Ideal for less demanding tasks due to its less granular approach compared to journaling.`
14+
};

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
novalidate>
88

99
<div i18n="form title"
10-
class="form-header">{{ action | titlecase }} {{ resource | upperFirst }}</div>
10+
class="form-header">{{ action | titlecase }} {{ resource | upperFirst }}
11+
<cd-help-text>
12+
<div *ngIf="action === 'Copy'">{{copyMessage}}
13+
</div>
14+
</cd-help-text>
15+
</div>
1116

1217
<!-- Parent -->
1318
<div class="form-item"
@@ -103,7 +108,7 @@
103108
<cd-alert-panel *ngIf="showMirrorDisableMessage"
104109
spacingClass="mt-2"
105110
[showTitle]="false"
106-
type="info">Mirroring can not be disabled on <b>Pool</b> mirror mode.
111+
type="info">Mirroring can not be disabled on <b>&nbsp;Pool&nbsp;</b> mirror mode.
107112
You need to change the mirror mode to enable this option.
108113
</cd-alert-panel>
109114
<cd-alert-panel *ngIf="currentPoolMirrorMode === 'disabled'"

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-form/rbd-form.component.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { RbdFormEditRequestModel } from './rbd-form-edit-request.model';
3434
import { RbdFormMode } from './rbd-form-mode.enum';
3535
import { RbdFormResponseModel } from './rbd-form-response.model';
3636
import { CdValidators } from '~/app/shared/forms/cd-validators';
37+
import { RBDActionHelpers } from '../rbd-contants';
3738

3839
class ExternalData {
3940
rbd: RbdFormResponseModel;
@@ -69,34 +70,28 @@ export class RbdFormComponent extends CdForm implements OnInit {
6970

7071
pool: string;
7172
peerConfigured = false;
72-
7373
advancedEnabled = false;
74-
7574
public rbdFormMode = RbdFormMode;
7675
mode: RbdFormMode;
77-
7876
response: RbdFormResponseModel;
7977
snapName: string;
80-
8178
defaultObjectSize = '4 MiB';
8279

8380
mirroringOptions = [
8481
{
8582
value: 'journal',
86-
text:
87-
'Ensures reliable replication by logging changes before updating the image, but doubles write time, impacting performance. Not recommended for high-speed data processing tasks.'
83+
text: RBDActionHelpers.journalTooltipText
8884
},
8985
{
9086
value: 'snapshot',
91-
text:
92-
'This mode replicates RBD images between clusters using snapshots, efficiently copying data changes but requiring complete delta syncing during failover. Ideal for less demanding tasks due to its less granular approach compared to journaling.'
87+
text: RBDActionHelpers.snapshotTooltipText
9388
}
9489
];
9590
poolMirrorMode: string;
9691
mirroring = false;
9792
currentPoolName = '';
9893
currentPoolMirrorMode = '';
99-
94+
copyMessage: string = RBDActionHelpers.copy;
10095
objectSizes: Array<string> = [
10196
'4 KiB',
10297
'8 KiB',

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ describe('RbdListComponent', () => {
128128
]
129129
});
130130
expect(component.getDeleteDisableDesc(component.selection)).toBe(
131-
'This RBD has cloned snapshots. Please delete related RBDs before deleting this RBD.'
131+
'This RBD has cloned snapshots. Please delete related RBDs before deleting this RBD'
132132
);
133133
});
134134

@@ -268,11 +268,11 @@ describe('RbdListComponent', () => {
268268
'Copy',
269269
'Flatten',
270270
'Resync',
271-
'Delete',
272-
'Move to Trash',
273271
'Remove Scheduling',
274272
'Promote',
275-
'Demote'
273+
'Demote',
274+
'Move to Trash',
275+
'Delete'
276276
],
277277
primary: {
278278
multiple: 'Create',
@@ -300,7 +300,7 @@ describe('RbdListComponent', () => {
300300
}
301301
},
302302
'create,delete': {
303-
actions: ['Create', 'Copy', 'Delete', 'Move to Trash'],
303+
actions: ['Create', 'Copy', 'Move to Trash', 'Delete'],
304304
primary: {
305305
multiple: 'Create',
306306
executing: 'Create',
@@ -322,11 +322,11 @@ describe('RbdListComponent', () => {
322322
'Edit',
323323
'Flatten',
324324
'Resync',
325-
'Delete',
326-
'Move to Trash',
327325
'Remove Scheduling',
328326
'Promote',
329-
'Demote'
327+
'Demote',
328+
'Move to Trash',
329+
'Delete'
330330
],
331331
primary: {
332332
multiple: '',
@@ -345,7 +345,7 @@ describe('RbdListComponent', () => {
345345
}
346346
},
347347
delete: {
348-
actions: ['Delete', 'Move to Trash'],
348+
actions: ['Move to Trash', 'Delete'],
349349
primary: {
350350
multiple: '',
351351
executing: '',

src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { DimlessBinaryPipe } from '~/app/shared/pipes/dimless-binary.pipe';
2323
import { DimlessPipe } from '~/app/shared/pipes/dimless.pipe';
2424
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
2525
import { CdTableServerSideService } from '~/app/shared/services/cd-table-server-side.service';
26-
// import { ModalService } from '~/app/shared/services/modal.service';
2726
import { TaskListService } from '~/app/shared/services/task-list.service';
2827
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
2928
import { URLBuilderService } from '~/app/shared/services/url-builder.service';
@@ -32,7 +31,7 @@ import { RbdParentModel } from '../rbd-form/rbd-parent.model';
3231
import { RbdTrashMoveModalComponent } from '../rbd-trash-move-modal/rbd-trash-move-modal.component';
3332
import { RBDImageFormat, RbdModel } from './rbd-model';
3433
import { ModalCdsService } from '~/app/shared/services/modal-cds.service';
35-
34+
import { RBDActionHelpers } from '../rbd-contants';
3635
const BASE_URL = 'block/rbd';
3736

3837
@Component({
@@ -83,7 +82,6 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
8382
count = 0;
8483
private tableContext: CdTableFetchDataContext = null;
8584
errorMessage: string;
86-
8785
builders = {
8886
'rbd/create': (metadata: object) =>
8987
this.createRbdFromTask(metadata['pool_name'], metadata['namespace'], metadata['image_name']),
@@ -159,8 +157,20 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
159157
icon: Icons.destroy,
160158
click: () => this.deleteRbdModal(),
161159
name: this.actionLabels.DELETE,
160+
title: RBDActionHelpers.delete,
162161
disable: (selection: CdTableSelection) => this.getDeleteDisableDesc(selection)
163162
};
163+
const moveAction: CdTableAction = {
164+
permission: 'delete',
165+
icon: Icons.trash,
166+
title: RBDActionHelpers.moveToTrash,
167+
click: () => this.trashRbdModal(),
168+
name: this.actionLabels.TRASH,
169+
disable: (selection: CdTableSelection) =>
170+
this.getRemovingStatusDesc(selection) ||
171+
this.getInvalidNameDisable(selection) ||
172+
selection.first().image_format === RBDImageFormat.V1
173+
};
164174
const resyncAction: CdTableAction = {
165175
permission: 'update',
166176
icon: Icons.refresh,
@@ -177,7 +187,8 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
177187
!!selection.first().cdExecuting,
178188
icon: Icons.copy,
179189
routerLink: () => `/block/rbd/copy/${getImageUri()}`,
180-
name: this.actionLabels.COPY
190+
name: this.actionLabels.COPY,
191+
title: RBDActionHelpers.copy
181192
};
182193
const flattenAction: CdTableAction = {
183194
permission: 'update',
@@ -188,18 +199,10 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
188199
!selection.first().parent,
189200
icon: Icons.flatten,
190201
click: () => this.flattenRbdModal(),
191-
name: this.actionLabels.FLATTEN
192-
};
193-
const moveAction: CdTableAction = {
194-
permission: 'delete',
195-
icon: Icons.trash,
196-
click: () => this.trashRbdModal(),
197-
name: this.actionLabels.TRASH,
198-
disable: (selection: CdTableSelection) =>
199-
this.getRemovingStatusDesc(selection) ||
200-
this.getInvalidNameDisable(selection) ||
201-
selection.first().image_format === RBDImageFormat.V1
202+
name: this.actionLabels.FLATTEN,
203+
title: RBDActionHelpers.flatten
202204
};
205+
203206
const removeSchedulingAction: CdTableAction = {
204207
permission: 'update',
205208
icon: Icons.edit,
@@ -217,9 +220,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
217220
name: this.actionLabels.PROMOTE,
218221
visible: () => this.selection.first() != null && !this.selection.first().primary,
219222
disable: () =>
220-
this.selection.first().mirror_mode === 'Disabled'
221-
? 'Mirroring needs to be enabled on the image to perform this action'
222-
: ''
223+
this.selection.first().mirror_mode === 'Disabled' ? RBDActionHelpers.enableMirroring : ''
223224
};
224225
const demoteAction: CdTableAction = {
225226
permission: 'update',
@@ -228,21 +229,19 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
228229
name: this.actionLabels.DEMOTE,
229230
visible: () => this.selection.first() != null && this.selection.first().primary,
230231
disable: () =>
231-
this.selection.first().mirror_mode === 'Disabled'
232-
? 'Mirroring needs to be enabled on the image to perform this action'
233-
: ''
232+
this.selection.first().mirror_mode === 'Disabled' ? RBDActionHelpers.enableMirroring : ''
234233
};
235234
this.tableActions = [
236235
addAction,
237236
editAction,
238237
copyAction,
239238
flattenAction,
240239
resyncAction,
241-
deleteAction,
242-
moveAction,
243240
removeSchedulingAction,
244241
promoteAction,
245-
demoteAction
242+
demoteAction,
243+
moveAction,
244+
deleteAction
246245
];
247246
}
248247

@@ -624,17 +623,23 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
624623
const first = selection.first();
625624

626625
if (first && this.hasClonedSnapshots(first)) {
627-
return $localize`This RBD has cloned snapshots. Please delete related RBDs before deleting this RBD.`;
626+
return RBDActionHelpers.clonedSnapshot;
628627
}
629-
630-
return this.getInvalidNameDisable(selection) || this.hasClonedSnapshots(selection.first());
628+
if (first && first.primary === false) {
629+
return RBDActionHelpers.secondayImageDelete;
630+
}
631+
return (
632+
this.getInvalidNameDisable(selection) ||
633+
this.hasClonedSnapshots(selection.first()) ||
634+
first.primary === false
635+
);
631636
}
632637

633638
getResyncDisableDesc(selection: CdTableSelection): string | boolean {
634639
const first = selection.first();
635640

636641
if (first && this.imageIsPrimary(first)) {
637-
return $localize`Primary RBD images cannot be resynced`;
642+
return RBDActionHelpers.primaryImageResync;
638643
}
639644

640645
return this.getInvalidNameDisable(selection);
@@ -647,7 +652,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
647652
const first = selection.first();
648653

649654
if (first?.name?.match(/[@/]/)) {
650-
return $localize`This RBD image has an invalid name and can't be managed by ceph.`;
655+
return RBDActionHelpers.invalidNameDisable;
651656
}
652657

653658
return !selection.first() || !selection.hasSingleSelection;
@@ -656,7 +661,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
656661
getRemovingStatusDesc(selection: CdTableSelection): string | boolean {
657662
const first = selection.first();
658663
if (first?.source === 'REMOVING') {
659-
return $localize`Action not possible for an RBD in status 'Removing'`;
664+
return RBDActionHelpers.removingStatus;
660665
}
661666
return false;
662667
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
::ng-deep legend .text-muted {
1+
.form-text {
22
font-size: small;
33
}

src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@ export class TableActionsComponent implements OnChanges, OnInit {
147147
useDisableDesc(action: CdTableAction) {
148148
if (action.disable) {
149149
const result = action.disable(this.selection);
150-
return _.isString(result) ? result : undefined;
150+
return _.isString(result) ? result : action.title ? action.title : undefined;
151+
} else if (action.title) {
152+
return action.title;
151153
}
152154
return undefined;
153155
}

src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-action.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export class CdTableAction {
1919
// The font awesome icon that will be used
2020
icon: string;
2121

22+
// For adding the default tooltip
23+
title?: string;
2224
/**
2325
* You can define the condition to disable the action.
2426
* By default all 'update' and 'delete' actions will only be enabled

0 commit comments

Comments
 (0)