]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: cephfs subvolume remove 52869/head
authorNizamudeen A <nia@redhat.com>
Mon, 7 Aug 2023 15:32:55 +0000 (21:02 +0530)
committerNizamudeen A <nia@redhat.com>
Mon, 14 Aug 2023 13:49:16 +0000 (19:19 +0530)
Fixes: https://tracker.ceph.com/issues/62349
Signed-off-by: Nizamudeen A <nia@redhat.com>
src/pybind/mgr/dashboard/controllers/cephfs.py
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-subvolume-list/cephfs-subvolume-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-subvolume-list/cephfs-subvolume-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs-subvolume.service.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/api/cephfs-subvolume.service.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/services/task-message.service.ts
src/pybind/mgr/dashboard/openapi.yaml

index 0c845009ad262fb1ec8d526348017be7232e67bb..1596b73a12f86c34b7a2c2db023d12d1e99b9dba 100644 (file)
@@ -711,6 +711,27 @@ class CephFSSubvolume(RESTController):
 
         return f'Subvolume {subvol_name} created successfully'
 
+    def set(self, vol_name: str, subvol_name: str, size: str):
+        if size:
+            error_code, _, err = mgr.remote('volumes', '_cmd_fs_subvolume_resize', None, {
+                'vol_name': vol_name, 'sub_name': subvol_name, 'new_size': size})
+            if error_code != 0:
+                raise DashboardException(
+                    f'Failed to update subvolume {subvol_name}: {err}'
+                )
+
+        return f'Subvolume {subvol_name} updated successfully'
+
+    def delete(self, vol_name: str, subvol_name: str):
+        error_code, _, err = mgr.remote(
+            'volumes', '_cmd_fs_subvolume_rm', None, {
+                'vol_name': vol_name, 'sub_name': subvol_name})
+        if error_code != 0:
+            raise RuntimeError(
+                f'Failed to delete subvolume {subvol_name}: {err}'
+            )
+        return f'Subvolume {subvol_name} removed successfully'
+
 
 @APIRouter('/cephfs/subvolume/group', Scope.CEPHFS)
 @APIDoc("Cephfs Subvolume Group Management API", "CephfsSubvolumeGroup")
@@ -744,14 +765,3 @@ class CephFSSubvolumeGroups(RESTController):
             raise DashboardException(
                 f'Failed to create subvolume group {group_name}: {err}'
             )
-
-    def set(self, vol_name: str, subvol_name: str, size: str):
-        if size:
-            error_code, _, err = mgr.remote('volumes', '_cmd_fs_subvolume_resize', None, {
-                'vol_name': vol_name, 'sub_name': subvol_name, 'new_size': size})
-            if error_code != 0:
-                raise DashboardException(
-                    f'Failed to update subvolume {subvol_name}: {err}'
-                )
-
-        return f'Subvolume {subvol_name} updated successfully'
index cafbff71768cc01a00b44a6838b5e7feaa1dc871..b3e0b526fb1c800261aa93aa38dc7a062168b49b 100644 (file)
@@ -3,6 +3,8 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { CephfsSubvolumeListComponent } from './cephfs-subvolume-list.component';
 import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { SharedModule } from '~/app/shared/shared.module';
+import { ToastrModule } from 'ngx-toastr';
+import { RouterTestingModule } from '@angular/router/testing';
 
 describe('CephfsSubvolumeListComponent', () => {
   let component: CephfsSubvolumeListComponent;
@@ -11,7 +13,7 @@ describe('CephfsSubvolumeListComponent', () => {
   beforeEach(async () => {
     await TestBed.configureTestingModule({
       declarations: [CephfsSubvolumeListComponent],
-      imports: [HttpClientTestingModule, SharedModule]
+      imports: [HttpClientTestingModule, SharedModule, ToastrModule.forRoot(), RouterTestingModule]
     }).compileComponents();
   });
 
index 47953b34c89fe84bccffeef5610aaab0c17e3388..25b5ef14a58cc94467bad000cff1759ef376d25f 100644 (file)
@@ -14,6 +14,9 @@ import { ModalService } from '~/app/shared/services/modal.service';
 import { CephfsSubvolumeFormComponent } from '../cephfs-subvolume-form/cephfs-subvolume-form.component';
 import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
 import { Permissions } from '~/app/shared/models/permissions';
+import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
+import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
+import { FinishedTask } from '~/app/shared/models/finished-task';
 
 @Component({
   selector: 'cd-cephfs-subvolume-list',
@@ -53,7 +56,8 @@ export class CephfsSubvolumeListComponent implements OnInit, OnChanges {
     private cephfsSubVolume: CephfsSubvolumeService,
     private actionLabels: ActionLabelsI18n,
     private modalService: ModalService,
-    private authStorageService: AuthStorageService
+    private authStorageService: AuthStorageService,
+    private taskWrapper: TaskWrapperService
   ) {
     this.permissions = this.authStorageService.getPermissions();
   }
@@ -107,14 +111,21 @@ export class CephfsSubvolumeListComponent implements OnInit, OnChanges {
         name: this.actionLabels.CREATE,
         permission: 'create',
         icon: Icons.add,
-        click: () => this.openModal(),
-        canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
+        click: () =>
+          this.modalService.show(
+            CephfsSubvolumeFormComponent,
+            {
+              fsName: this.fsName,
+              pools: this.pools
+            },
+            { size: 'lg' }
+          )
       },
       {
-        name: this.actionLabels.EDIT,
-        permission: 'update',
-        icon: Icons.edit,
-        click: () => this.openModal(true)
+        name: this.actionLabels.REMOVE,
+        permission: 'delete',
+        icon: Icons.destroy,
+        click: () => this.removeSubVolumeModal()
       }
     ];
 
@@ -155,4 +166,18 @@ export class CephfsSubvolumeListComponent implements OnInit, OnChanges {
       { size: 'lg' }
     );
   }
+
+  removeSubVolumeModal() {
+    const name = this.selection.first().name;
+    this.modalService.show(CriticalConfirmationModalComponent, {
+      itemDescription: 'subvolume',
+      itemNames: [name],
+      actionDescription: 'remove',
+      submitActionObservable: () =>
+        this.taskWrapper.wrapTaskAroundCall({
+          task: new FinishedTask('cephfs/subvolume/remove', { subVolumeName: name }),
+          call: this.cephfsSubVolume.remove(this.fsName, name)
+        })
+    });
+  }
 }
index 0e65aa6c0d7486e6b116a5c6911a41f767b4e36f..e2d1db3e8f3a6457d8173cf1efcf25148c084796 100644 (file)
@@ -32,4 +32,10 @@ describe('CephfsSubvolumeService', () => {
     const req = httpTesting.expectOne('api/cephfs/subvolume/testFS');
     expect(req.request.method).toBe('GET');
   });
+
+  it('should call remove', () => {
+    service.remove('testFS', 'testSubvol').subscribe();
+    const req = httpTesting.expectOne('api/cephfs/subvolume/testFS?subvol_name=testSubvol');
+    expect(req.request.method).toBe('DELETE');
+  });
 });
index ca7bf095891c24173e5db34a8fb0a290acd9fdd5..67c7bb346a2b112faf700757c9059ad813eb873a 100644 (file)
@@ -51,6 +51,15 @@ export class CephfsSubvolumeService {
     });
   }
 
+  remove(fsName: string, subVolumeName: string) {
+    return this.http.delete(`${this.baseURL}/${fsName}`, {
+      params: {
+        subvol_name: subVolumeName
+      },
+      observe: 'response'
+    });
+  }
+
   exists(subVolumeName: string, fsName: string) {
     return this.info(fsName, subVolumeName).pipe(
       mapTo(true),
index 994adf2dcd8e5c21e755ee73465359eb3b2bb16b..766b31dbcbb25064ae77150b116130021a880d01 100644 (file)
@@ -365,6 +365,9 @@ export class TaskMessageService {
     'cephfs/subvolume/edit': this.newTaskMessage(this.commonOperations.update, (metadata) =>
       this.subvolume(metadata)
     ),
+    'cephfs/subvolume/remove': this.newTaskMessage(this.commonOperations.remove, (metadata) =>
+      this.subvolume(metadata)
+    ),
     'cephfs/subvolume/group/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
       this.subvolumegroup(metadata)
     )
index 86743ab1c4c73dfdaa980c95cf32a2f73d36f8bf..233a3c09bb0cd3a4978d9deb2caeb2e26061455b 100644 (file)
@@ -1865,37 +1865,30 @@ paths:
       - jwt: []
       tags:
       - CephfsSubvolumeGroup
-    put:
+  /api/cephfs/subvolume/{vol_name}:
+    delete:
       parameters:
       - in: path
         name: vol_name
         required: true
         schema:
           type: string
-      requestBody:
-        content:
-          application/json:
-            schema:
-              properties:
-                size:
-                  type: integer
-                subvol_name:
-                  type: string
-              required:
-              - subvol_name
-              - size
-              type: object
+      - in: query
+        name: subvol_name
+        required: true
+        schema:
+          type: string
       responses:
-        '200':
+        '202':
           content:
             application/vnd.ceph.api.v1.0+json:
               type: object
-          description: Resource updated.
-        '202':
+          description: Operation is still executing. Please check the task queue.
+        '204':
           content:
             application/vnd.ceph.api.v1.0+json:
               type: object
-          description: Operation is still executing. Please check the task queue.
+          description: Resource deleted.
         '400':
           description: Operation exception. Please check the response body for details.
         '401':
@@ -1908,8 +1901,7 @@ paths:
       security:
       - jwt: []
       tags:
-      - CephfsSubvolumeGroup
-  /api/cephfs/subvolume/{vol_name}:
+      - CephFSSubvolume
     get:
       parameters:
       - in: path
@@ -1936,6 +1928,50 @@ paths:
       - jwt: []
       tags:
       - CephFSSubvolume
+    put:
+      parameters:
+      - in: path
+        name: vol_name
+        required: true
+        schema:
+          type: string
+      requestBody:
+        content:
+          application/json:
+            schema:
+              properties:
+                size:
+                  type: integer
+                subvol_name:
+                  type: string
+              required:
+              - subvol_name
+              - size
+              type: object
+      responses:
+        '200':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Resource updated.
+        '202':
+          content:
+            application/vnd.ceph.api.v1.0+json:
+              type: object
+          description: Operation is still executing. Please check the task queue.
+        '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:
+      - CephFSSubvolume
   /api/cephfs/subvolume/{vol_name}/info:
     get:
       parameters: