f'Failed to create subvolume snapshot {snap_name}: {err}'
)
return f'Subvolume snapshot {snap_name} created successfully'
+
+ def delete(self, vol_name: str, subvol_name: str, snap_name: str, group_name='', force=True):
+ params = {'vol_name': vol_name, 'sub_name': subvol_name, 'snap_name': snap_name}
+ if group_name:
+ params['group_name'] = group_name
+ params['force'] = str_to_bool(force)
+ error_code, _, err = mgr.remote('volumes', '_cmd_fs_subvolume_snapshot_rm', None,
+ params)
+ if error_code != 0:
+ raise DashboardException(
+ f'Failed to delete subvolume snapshot {snap_name}: {err}'
+ )
+ return f'Subvolume snapshot {snap_name} removed successfully'
import { CephfsSubvolumeSnapshotsListComponent } from './cephfs-subvolume-snapshots-list.component';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { SharedModule } from '~/app/shared/shared.module';
+import { ToastrModule } from 'ngx-toastr';
describe('CephfsSubvolumeSnapshotsListComponent', () => {
let component: CephfsSubvolumeSnapshotsListComponent;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [CephfsSubvolumeSnapshotsListComponent],
- imports: [HttpClientTestingModule, SharedModule]
+ imports: [HttpClientTestingModule, SharedModule, ToastrModule.forRoot()]
}).compileComponents();
fixture = TestBed.createComponent(CephfsSubvolumeSnapshotsListComponent);
import { Permissions } from '~/app/shared/models/permissions';
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
+import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
+import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { FinishedTask } from '~/app/shared/models/finished-task';
+import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
@Component({
selector: 'cd-cephfs-subvolume-snapshots-list',
tableActions: CdTableAction[];
selection = new CdTableSelection();
permissions: Permissions;
+ modalRef: NgbModalRef;
subVolumes$: Observable<CephfsSubvolume[]>;
snapshots$: Observable<any[]>;
private actionLabels: ActionLabelsI18n,
private modalService: ModalService,
private authStorageService: AuthStorageService,
- private cdDatePipe: CdDatePipe
+ private cdDatePipe: CdDatePipe,
+ private taskWrapper: TaskWrapperService
) {
this.permissions = this.authStorageService.getPermissions();
}
permission: 'create',
icon: Icons.add,
click: () => this.openModal()
+ },
+ {
+ name: this.actionLabels.REMOVE,
+ permission: 'delete',
+ icon: Icons.destroy,
+ click: () => this.deleteSnapshot()
}
];
updateSelection(selection: CdTableSelection) {
this.selection = selection;
}
+
+ deleteSnapshot() {
+ const snapshotName = this.selection.first().name;
+ const subVolumeName = this.activeSubVolumeName;
+ const subVolumeGroupName = this.activeGroupName;
+ const fsName = this.fsName;
+ this.modalRef = this.modalService.show(CriticalConfirmationModalComponent, {
+ actionDescription: 'Remove',
+ itemNames: [snapshotName],
+ itemDescription: 'Snapshot',
+ submitAction: () =>
+ this.taskWrapper
+ .wrapTaskAroundCall({
+ task: new FinishedTask('cephfs/subvolume/snapshot/delete', {
+ fsName: fsName,
+ subVolumeName: subVolumeName,
+ subVolumeGroupName: subVolumeGroupName,
+ snapshotName: snapshotName
+ }),
+ call: this.cephfsSubvolumeService.deleteSnapshot(
+ fsName,
+ subVolumeName,
+ snapshotName,
+ subVolumeGroupName
+ )
+ })
+ .subscribe({
+ complete: () => this.modalRef.close(),
+ error: () => this.modalRef.componentInstance.stopLoadingSpinner()
+ })
+ });
+ }
}
{ observe: 'response' }
);
}
+
+ deleteSnapshot(fsName: string, subVolumeName: string, snapshotName: string, groupName = '') {
+ return this.http.delete(`${this.baseURL}/snapshot/${fsName}/${subVolumeName}`, {
+ params: {
+ snap_name: snapshotName,
+ group_name: groupName
+ },
+ observe: 'response'
+ });
+ }
}
'cephfs/subvolume/snapshot/create': this.newTaskMessage(
this.commonOperations.create,
(metadata) => this.snapshot(metadata)
+ ),
+ 'cephfs/subvolume/snapshot/delete': this.newTaskMessage(
+ this.commonOperations.delete,
+ (metadata) => this.snapshot(metadata)
)
};
tags:
- CephfsSubvolumeSnapshot
/api/cephfs/subvolume/snapshot/{vol_name}/{subvol_name}:
+ delete:
+ parameters:
+ - in: path
+ name: vol_name
+ required: true
+ schema:
+ type: string
+ - in: path
+ name: subvol_name
+ required: true
+ schema:
+ type: string
+ - in: query
+ name: snap_name
+ required: true
+ schema:
+ type: string
+ - default: ''
+ in: query
+ name: group_name
+ schema:
+ type: string
+ - default: true
+ in: query
+ name: force
+ schema:
+ type: boolean
+ responses:
+ '202':
+ content:
+ application/vnd.ceph.api.v1.0+json:
+ type: object
+ description: Operation is still executing. Please check the task queue.
+ '204':
+ content:
+ application/vnd.ceph.api.v1.0+json:
+ type: object
+ description: Resource deleted.
+ '400':
+ description: Operation exception. Please check the response body for details.
+ '401':
+ description: Unauthenticated access. Please login first.
+ '403':
+ description: Unauthorized access. Please check your permissions.
+ '500':
+ description: Unexpected error. Please check the response body for the stack
+ trace.
+ security:
+ - jwt: []
+ tags:
+ - CephfsSubvolumeSnapshot
get:
parameters:
- in: path