mirror of
https://github.com/ceph/ceph
synced 2025-02-21 18:17:42 +00:00
Merge pull request #52645 from rhcs-dashboard/cephfs-vol-rm
mgr/dashboard: cephfs volume rm and rename Reviewed-by: Pegonzal <NOT@FOUND> Reviewed-by: cloudbehl <NOT@FOUND> Reviewed-by: Nizamudeen A <nia@redhat.com>
This commit is contained in:
commit
91f75abf4c
@ -15,7 +15,8 @@ from ..services.ceph_service import CephService
|
|||||||
from ..services.cephfs import CephFS as CephFS_
|
from ..services.cephfs import CephFS as CephFS_
|
||||||
from ..services.exception import handle_cephfs_error
|
from ..services.exception import handle_cephfs_error
|
||||||
from ..tools import ViewCache
|
from ..tools import ViewCache
|
||||||
from . import APIDoc, APIRouter, EndpointDoc, RESTController, UIRouter, allow_empty_body
|
from . import APIDoc, APIRouter, DeletePermission, Endpoint, EndpointDoc, \
|
||||||
|
RESTController, UIRouter, UpdatePermission, allow_empty_body
|
||||||
|
|
||||||
GET_QUOTAS_SCHEMA = {
|
GET_QUOTAS_SCHEMA = {
|
||||||
'max_bytes': (int, ''),
|
'max_bytes': (int, ''),
|
||||||
@ -63,6 +64,41 @@ class CephFS(RESTController):
|
|||||||
f'Error creating volume {name} with placement {str(service_spec)}: {err}')
|
f'Error creating volume {name} with placement {str(service_spec)}: {err}')
|
||||||
return f'Volume {name} created successfully'
|
return f'Volume {name} created successfully'
|
||||||
|
|
||||||
|
@EndpointDoc("Remove CephFS Volume",
|
||||||
|
parameters={
|
||||||
|
'name': (str, 'File System Name'),
|
||||||
|
})
|
||||||
|
@allow_empty_body
|
||||||
|
@Endpoint('DELETE')
|
||||||
|
@DeletePermission
|
||||||
|
def remove(self, name):
|
||||||
|
error_code, _, err = mgr.remote('volumes', '_cmd_fs_volume_rm', None,
|
||||||
|
{'vol_name': name,
|
||||||
|
'yes-i-really-mean-it': "--yes-i-really-mean-it"})
|
||||||
|
if error_code != 0:
|
||||||
|
raise DashboardException(
|
||||||
|
msg=f'Error deleting volume {name}: {err}',
|
||||||
|
component='cephfs')
|
||||||
|
return f'Volume {name} removed successfully'
|
||||||
|
|
||||||
|
@EndpointDoc("Rename CephFS Volume",
|
||||||
|
parameters={
|
||||||
|
'name': (str, 'Existing FS Name'),
|
||||||
|
'new_name': (str, 'New FS Name'),
|
||||||
|
})
|
||||||
|
@allow_empty_body
|
||||||
|
@UpdatePermission
|
||||||
|
@Endpoint('PUT')
|
||||||
|
def rename(self, name: str, new_name: str):
|
||||||
|
error_code, _, err = mgr.remote('volumes', '_cmd_fs_volume_rename', None,
|
||||||
|
{'vol_name': name, 'new_vol_name': new_name,
|
||||||
|
'yes_i_really_mean_it': True})
|
||||||
|
if error_code != 0:
|
||||||
|
raise DashboardException(
|
||||||
|
msg=f'Error renaming volume {name} to {new_name}: {err}',
|
||||||
|
component='cephfs')
|
||||||
|
return f'Volume {name} renamed successfully to {new_name}'
|
||||||
|
|
||||||
def get(self, fs_id):
|
def get(self, fs_id):
|
||||||
fs_id = self.fs_id_to_int(fs_id)
|
fs_id = self.fs_id_to_int(fs_id)
|
||||||
return self.fs_status(fs_id)
|
return self.fs_status(fs_id)
|
||||||
|
@ -4,11 +4,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
|
||||||
|
import { ToastrModule } from 'ngx-toastr';
|
||||||
|
|
||||||
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
|
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
|
||||||
import { SharedModule } from '~/app/shared/shared.module';
|
import { SharedModule } from '~/app/shared/shared.module';
|
||||||
import { configureTestBed } from '~/testing/unit-test-helper';
|
import { configureTestBed } from '~/testing/unit-test-helper';
|
||||||
|
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
|
||||||
import { CephfsVolumeFormComponent } from '../cephfs-form/cephfs-form.component';
|
import { CephfsVolumeFormComponent } from '../cephfs-form/cephfs-form.component';
|
||||||
|
import { ModalService } from '~/app/shared/services/modal.service';
|
||||||
|
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
|
||||||
import { CephfsListComponent } from './cephfs-list.component';
|
import { CephfsListComponent } from './cephfs-list.component';
|
||||||
|
import { CephfsService } from '~/app/shared/api/cephfs.service';
|
||||||
|
|
||||||
@Component({ selector: 'cd-cephfs-tabs', template: '' })
|
@Component({ selector: 'cd-cephfs-tabs', template: '' })
|
||||||
class CephfsTabsStubComponent {
|
class CephfsTabsStubComponent {
|
||||||
@ -19,19 +25,73 @@ class CephfsTabsStubComponent {
|
|||||||
describe('CephfsListComponent', () => {
|
describe('CephfsListComponent', () => {
|
||||||
let component: CephfsListComponent;
|
let component: CephfsListComponent;
|
||||||
let fixture: ComponentFixture<CephfsListComponent>;
|
let fixture: ComponentFixture<CephfsListComponent>;
|
||||||
|
let cephfsService: CephfsService;
|
||||||
|
|
||||||
configureTestBed({
|
configureTestBed({
|
||||||
imports: [BrowserAnimationsModule, SharedModule, HttpClientTestingModule, RouterTestingModule],
|
imports: [
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
SharedModule,
|
||||||
|
HttpClientTestingModule,
|
||||||
|
ToastrModule.forRoot(),
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
declarations: [CephfsListComponent, CephfsTabsStubComponent, CephfsVolumeFormComponent]
|
declarations: [CephfsListComponent, CephfsTabsStubComponent, CephfsVolumeFormComponent]
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(CephfsListComponent);
|
fixture = TestBed.createComponent(CephfsListComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
cephfsService = TestBed.inject(CephfsService);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('volume deletion', () => {
|
||||||
|
let taskWrapper: TaskWrapperService;
|
||||||
|
let modalRef: any;
|
||||||
|
|
||||||
|
const setSelectedVolume = (volName: string) =>
|
||||||
|
(component.selection.selected = [{ mdsmap: { fs_name: volName } }]);
|
||||||
|
|
||||||
|
const callDeletion = () => {
|
||||||
|
component.removeVolumeModal();
|
||||||
|
expect(modalRef).toBeTruthy();
|
||||||
|
const deletion: CriticalConfirmationModalComponent = modalRef && modalRef.componentInstance;
|
||||||
|
deletion.submitActionObservable();
|
||||||
|
};
|
||||||
|
|
||||||
|
const testVolumeDeletion = (volName: string) => {
|
||||||
|
setSelectedVolume(volName);
|
||||||
|
callDeletion();
|
||||||
|
expect(cephfsService.remove).toHaveBeenCalledWith(volName);
|
||||||
|
expect(taskWrapper.wrapTaskAroundCall).toHaveBeenCalledWith({
|
||||||
|
task: {
|
||||||
|
name: 'cephfs/remove',
|
||||||
|
metadata: {
|
||||||
|
volumeName: volName
|
||||||
|
}
|
||||||
|
},
|
||||||
|
call: undefined // because of stub
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
spyOn(TestBed.inject(ModalService), 'show').and.callFake((deletionClass, initialState) => {
|
||||||
|
modalRef = {
|
||||||
|
componentInstance: Object.assign(new deletionClass(), initialState)
|
||||||
|
};
|
||||||
|
return modalRef;
|
||||||
|
});
|
||||||
|
spyOn(cephfsService, 'remove').and.stub();
|
||||||
|
taskWrapper = TestBed.inject(TaskWrapperService);
|
||||||
|
spyOn(taskWrapper, 'wrapTaskAroundCall').and.callThrough();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete cephfs volume', () => {
|
||||||
|
testVolumeDeletion('somevolumeName');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -2,11 +2,17 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { Permissions } from '~/app/shared/models/permissions';
|
import { Permissions } from '~/app/shared/models/permissions';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { CephfsService } from '~/app/shared/api/cephfs.service';
|
import { CephfsService } from '~/app/shared/api/cephfs.service';
|
||||||
|
import { ConfigurationService } from '~/app/shared/api/configuration.service';
|
||||||
import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
|
import { ListWithDetails } from '~/app/shared/classes/list-with-details.class';
|
||||||
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
|
|
||||||
import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
|
import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
|
||||||
|
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
|
||||||
import { Icons } from '~/app/shared/enum/icons.enum';
|
import { Icons } from '~/app/shared/enum/icons.enum';
|
||||||
|
import { CriticalConfirmationModalComponent } from '~/app/shared/components/critical-confirmation-modal/critical-confirmation-modal.component';
|
||||||
|
import { NotificationType } from '~/app/shared/enum/notification-type.enum';
|
||||||
|
import { FormModalComponent } from '~/app/shared/components/form-modal/form-modal.component';
|
||||||
import { CdTableAction } from '~/app/shared/models/cd-table-action';
|
import { CdTableAction } from '~/app/shared/models/cd-table-action';
|
||||||
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
|
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
|
||||||
import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
|
import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
|
||||||
@ -14,6 +20,10 @@ import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
|
|||||||
import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
|
import { CdDatePipe } from '~/app/shared/pipes/cd-date.pipe';
|
||||||
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
||||||
import { URLBuilderService } from '~/app/shared/services/url-builder.service';
|
import { URLBuilderService } from '~/app/shared/services/url-builder.service';
|
||||||
|
import { ModalService } from '~/app/shared/services/modal.service';
|
||||||
|
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
|
||||||
|
import { FinishedTask } from '~/app/shared/models/finished-task';
|
||||||
|
import { NotificationService } from '~/app/shared/services/notification.service';
|
||||||
|
|
||||||
const BASE_URL = 'cephfs';
|
const BASE_URL = 'cephfs';
|
||||||
|
|
||||||
@ -29,6 +39,8 @@ export class CephfsListComponent extends ListWithDetails implements OnInit {
|
|||||||
selection = new CdTableSelection();
|
selection = new CdTableSelection();
|
||||||
tableActions: CdTableAction[];
|
tableActions: CdTableAction[];
|
||||||
permissions: Permissions;
|
permissions: Permissions;
|
||||||
|
icons = Icons;
|
||||||
|
monAllowPoolDelete = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authStorageService: AuthStorageService,
|
private authStorageService: AuthStorageService,
|
||||||
@ -36,7 +48,11 @@ export class CephfsListComponent extends ListWithDetails implements OnInit {
|
|||||||
private cdDatePipe: CdDatePipe,
|
private cdDatePipe: CdDatePipe,
|
||||||
public actionLabels: ActionLabelsI18n,
|
public actionLabels: ActionLabelsI18n,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private urlBuilder: URLBuilderService
|
private urlBuilder: URLBuilderService,
|
||||||
|
private configurationService: ConfigurationService,
|
||||||
|
private modalService: ModalService,
|
||||||
|
private taskWrapper: TaskWrapperService,
|
||||||
|
public notificationService: NotificationService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.permissions = this.authStorageService.getPermissions();
|
this.permissions = this.authStorageService.getPermissions();
|
||||||
@ -69,8 +85,32 @@ export class CephfsListComponent extends ListWithDetails implements OnInit {
|
|||||||
icon: Icons.add,
|
icon: Icons.add,
|
||||||
click: () => this.router.navigate([this.urlBuilder.getCreate()]),
|
click: () => this.router.navigate([this.urlBuilder.getCreate()]),
|
||||||
canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
|
canBePrimary: (selection: CdTableSelection) => !selection.hasSelection
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: this.actionLabels.EDIT,
|
||||||
|
permission: 'update',
|
||||||
|
icon: Icons.edit,
|
||||||
|
click: () => this.editAction()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permission: 'delete',
|
||||||
|
icon: Icons.destroy,
|
||||||
|
click: () => this.removeVolumeModal(),
|
||||||
|
name: this.actionLabels.REMOVE,
|
||||||
|
disable: this.getDisableDesc.bind(this)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (this.permissions.configOpt.read) {
|
||||||
|
this.configurationService.get('mon_allow_pool_delete').subscribe((data: any) => {
|
||||||
|
if (_.has(data, 'value')) {
|
||||||
|
const monSection = _.find(data.value, (v) => {
|
||||||
|
return v.section === 'mon';
|
||||||
|
}) || { value: false };
|
||||||
|
this.monAllowPoolDelete = monSection.value === 'true' ? true : false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFilesystems(context: CdTableFetchDataContext) {
|
loadFilesystems(context: CdTableFetchDataContext) {
|
||||||
@ -87,4 +127,56 @@ export class CephfsListComponent extends ListWithDetails implements OnInit {
|
|||||||
updateSelection(selection: CdTableSelection) {
|
updateSelection(selection: CdTableSelection) {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeVolumeModal() {
|
||||||
|
const volName = this.selection.first().mdsmap['fs_name'];
|
||||||
|
this.modalService.show(CriticalConfirmationModalComponent, {
|
||||||
|
itemDescription: 'Volume',
|
||||||
|
itemNames: [volName],
|
||||||
|
actionDescription: 'remove',
|
||||||
|
submitActionObservable: () =>
|
||||||
|
this.taskWrapper.wrapTaskAroundCall({
|
||||||
|
task: new FinishedTask('cephfs/remove', { volumeName: volName }),
|
||||||
|
call: this.cephfsService.remove(volName)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisableDesc(): boolean | string {
|
||||||
|
if (this.selection?.hasSelection) {
|
||||||
|
if (!this.monAllowPoolDelete) {
|
||||||
|
return $localize`Volume deletion is disabled by the mon_allow_pool_delete configuration setting.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
editAction() {
|
||||||
|
const selectedVolume = this.selection.first().mdsmap['fs_name'];
|
||||||
|
|
||||||
|
this.modalService.show(FormModalComponent, {
|
||||||
|
titleText: $localize`Edit Volume: ${selectedVolume}`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
name: 'volumeName',
|
||||||
|
value: selectedVolume,
|
||||||
|
label: $localize`Name`,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
submitButtonText: $localize`Edit Volume`,
|
||||||
|
onSubmit: (values: any) => {
|
||||||
|
this.cephfsService.rename(selectedVolume, values.volumeName).subscribe(() => {
|
||||||
|
this.notificationService.show(
|
||||||
|
NotificationType.success,
|
||||||
|
$localize`Updated Volume '${selectedVolume}'`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
import { Component, Input, OnChanges, OnInit, ViewChild } from '@angular/core';
|
||||||
import { Observable, ReplaySubject, of } from 'rxjs';
|
import { Observable, ReplaySubject, of } from 'rxjs';
|
||||||
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
|
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ import { Permissions } from '~/app/shared/models/permissions';
|
|||||||
templateUrl: './cephfs-subvolume-group.component.html',
|
templateUrl: './cephfs-subvolume-group.component.html',
|
||||||
styleUrls: ['./cephfs-subvolume-group.component.scss']
|
styleUrls: ['./cephfs-subvolume-group.component.scss']
|
||||||
})
|
})
|
||||||
export class CephfsSubvolumeGroupComponent implements OnInit {
|
export class CephfsSubvolumeGroupComponent implements OnInit, OnChanges {
|
||||||
@ViewChild('quotaUsageTpl', { static: true })
|
@ViewChild('quotaUsageTpl', { static: true })
|
||||||
quotaUsageTpl: any;
|
quotaUsageTpl: any;
|
||||||
|
|
||||||
|
@ -95,4 +95,20 @@ describe('CephfsService', () => {
|
|||||||
expect(req.request.method).toBe('PUT');
|
expect(req.request.method).toBe('PUT');
|
||||||
expect(req.request.body).toEqual({ max_bytes: 1024, max_files: 10 });
|
expect(req.request.body).toEqual({ max_bytes: 1024, max_files: 10 });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should rename the cephfs volume', () => {
|
||||||
|
const volName = 'testvol';
|
||||||
|
const newVolName = 'newtestvol';
|
||||||
|
service.rename(volName, newVolName).subscribe();
|
||||||
|
const req = httpTesting.expectOne('api/cephfs/rename');
|
||||||
|
expect(req.request.method).toBe('PUT');
|
||||||
|
expect(req.request.body).toEqual({ name: 'testvol', new_name: 'newtestvol' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove the cephfs volume', () => {
|
||||||
|
const volName = 'testvol';
|
||||||
|
service.remove(volName).subscribe();
|
||||||
|
const req = httpTesting.expectOne(`api/cephfs/remove/${volName}`);
|
||||||
|
expect(req.request.method).toBe('DELETE');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -87,4 +87,20 @@ export class CephfsService {
|
|||||||
isCephFsPool(pool: any) {
|
isCephFsPool(pool: any) {
|
||||||
return _.indexOf(pool.application_metadata, 'cephfs') !== -1 && !pool.pool_name.includes('/');
|
return _.indexOf(pool.application_metadata, 'cephfs') !== -1 && !pool.pool_name.includes('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove(name: string) {
|
||||||
|
return this.http.delete(`${this.baseURL}/remove/${name}`, {
|
||||||
|
observe: 'response'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
rename(vol_name: string, new_vol_name: string) {
|
||||||
|
let requestBody = {
|
||||||
|
name: vol_name,
|
||||||
|
new_name: new_vol_name
|
||||||
|
};
|
||||||
|
return this.http.put(`${this.baseURL}/rename`, requestBody, {
|
||||||
|
observe: 'response'
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,6 +361,9 @@ export class TaskMessageService {
|
|||||||
),
|
),
|
||||||
'cephfs/subvolume/group/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
|
'cephfs/subvolume/group/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
|
||||||
this.subvolumegroup(metadata)
|
this.subvolumegroup(metadata)
|
||||||
|
),
|
||||||
|
'cephfs/remove': this.newTaskMessage(this.commonOperations.remove, (metadata) =>
|
||||||
|
this.volume(metadata)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1681,6 +1681,83 @@ paths:
|
|||||||
- jwt: []
|
- jwt: []
|
||||||
tags:
|
tags:
|
||||||
- Cephfs
|
- Cephfs
|
||||||
|
/api/cephfs/remove/{name}:
|
||||||
|
delete:
|
||||||
|
parameters:
|
||||||
|
- description: File System Name
|
||||||
|
in: path
|
||||||
|
name: name
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
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: []
|
||||||
|
summary: Remove CephFS Volume
|
||||||
|
tags:
|
||||||
|
- Cephfs
|
||||||
|
/api/cephfs/rename:
|
||||||
|
put:
|
||||||
|
parameters: []
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Existing FS Name
|
||||||
|
type: string
|
||||||
|
new_name:
|
||||||
|
description: New FS Name
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- new_name
|
||||||
|
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: []
|
||||||
|
summary: Rename CephFS Volume
|
||||||
|
tags:
|
||||||
|
- Cephfs
|
||||||
/api/cephfs/subvolume:
|
/api/cephfs/subvolume:
|
||||||
post:
|
post:
|
||||||
parameters: []
|
parameters: []
|
||||||
|
Loading…
Reference in New Issue
Block a user