mirror of
https://github.com/ceph/ceph
synced 2025-02-22 18:47:18 +00:00
mgr/dashboard: create subvolumegroup
Fixes: https://tracker.ceph.com/issues/62363 Signed-off-by: Pedro Gonzalez Gomez <pegonzal@redhat.com>
This commit is contained in:
parent
75389ba061
commit
c5e39cb921
@ -683,12 +683,12 @@ class CephFSSubvolumeGroups(RESTController):
|
||||
def get(self, vol_name):
|
||||
if not vol_name:
|
||||
raise DashboardException(
|
||||
'Error listing subvolume groups')
|
||||
f'Error listing subvolume groups for {vol_name}')
|
||||
error_code, out, err = mgr.remote('volumes', '_cmd_fs_subvolumegroup_ls',
|
||||
None, {'vol_name': vol_name})
|
||||
if error_code != 0:
|
||||
raise DashboardException(
|
||||
'Error listing subvolume groups')
|
||||
f'Error listing subvolume groups for {vol_name}')
|
||||
subvolume_groups = json.loads(out)
|
||||
for group in subvolume_groups:
|
||||
error_code, out, err = mgr.remote('volumes', '_cmd_fs_subvolumegroup_info',
|
||||
@ -700,3 +700,11 @@ class CephFSSubvolumeGroups(RESTController):
|
||||
)
|
||||
group['info'] = json.loads(out)
|
||||
return subvolume_groups
|
||||
|
||||
def create(self, vol_name: str, group_name: str, **kwargs):
|
||||
error_code, _, err = mgr.remote('volumes', '_cmd_fs_subvolumegroup_create', None, {
|
||||
'vol_name': vol_name, 'group_name': group_name, **kwargs})
|
||||
if error_code != 0:
|
||||
raise DashboardException(
|
||||
f'Failed to create subvolume group {group_name}: {err}'
|
||||
)
|
||||
|
@ -5,7 +5,17 @@
|
||||
columnMode="flex"
|
||||
[columns]="columns"
|
||||
selectionType="single"
|
||||
[hasDetails]="false">
|
||||
[hasDetails]="false"
|
||||
(fetchData)="fetchData()">
|
||||
|
||||
<div class="table-actions btn-toolbar">
|
||||
<cd-table-actions [permission]="permissions.cephfs"
|
||||
[selection]="selection"
|
||||
class="btn-group"
|
||||
id="cephfs-subvolumegropup-actions"
|
||||
[tableActions]="tableActions">
|
||||
</cd-table-actions>
|
||||
</div>
|
||||
</cd-table>
|
||||
</ng-container>
|
||||
|
||||
|
@ -1,13 +1,20 @@
|
||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { Observable, ReplaySubject, of } from 'rxjs';
|
||||
import { catchError, shareReplay, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
|
||||
import { CellTemplate } from '~/app/shared/enum/cell-template.enum';
|
||||
import { Icons } from '~/app/shared/enum/icons.enum';
|
||||
import { CdTableAction } from '~/app/shared/models/cd-table-action';
|
||||
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
|
||||
import { CdTableFetchDataContext } from '~/app/shared/models/cd-table-fetch-data-context';
|
||||
import { CdTableSelection } from '~/app/shared/models/cd-table-selection';
|
||||
import { CephfsSubvolumeGroup } from '~/app/shared/models/cephfs-subvolume-group.model';
|
||||
import { CephfsSubvolumegroupFormComponent } from '../cephfs-subvolumegroup-form/cephfs-subvolumegroup-form.component';
|
||||
import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
|
||||
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
|
||||
import { ModalService } from '~/app/shared/services/modal.service';
|
||||
import { Permissions } from '~/app/shared/models/permissions';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-cephfs-subvolume-group',
|
||||
@ -32,14 +39,26 @@ export class CephfsSubvolumeGroupComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
fsName: any;
|
||||
@Input() pools: any[];
|
||||
|
||||
columns: CdTableColumn[];
|
||||
tableActions: CdTableAction[];
|
||||
context: CdTableFetchDataContext;
|
||||
selection = new CdTableSelection();
|
||||
icons = Icons;
|
||||
permissions: Permissions;
|
||||
|
||||
subvolumeGroup$: Observable<CephfsSubvolumeGroup[]>;
|
||||
subject = new ReplaySubject<CephfsSubvolumeGroup[]>();
|
||||
|
||||
constructor(private cephfsSubvolumeGroup: CephfsSubvolumeGroupService) {}
|
||||
constructor(
|
||||
private cephfsSubvolumeGroup: CephfsSubvolumeGroupService,
|
||||
private actionLabels: ActionLabelsI18n,
|
||||
private modalService: ModalService,
|
||||
private authStorageService: AuthStorageService
|
||||
) {
|
||||
this.permissions = this.authStorageService.getPermissions();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.columns = [
|
||||
@ -78,15 +97,43 @@ export class CephfsSubvolumeGroupComponent implements OnInit {
|
||||
cellTransformation: CellTemplate.timeAgo
|
||||
}
|
||||
];
|
||||
|
||||
this.tableActions = [
|
||||
{
|
||||
name: this.actionLabels.CREATE,
|
||||
permission: 'create',
|
||||
icon: Icons.add,
|
||||
click: () =>
|
||||
this.modalService.show(
|
||||
CephfsSubvolumegroupFormComponent,
|
||||
{
|
||||
fsName: this.fsName,
|
||||
pools: this.pools
|
||||
},
|
||||
{ size: 'lg' }
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
this.subvolumeGroup$ = this.subject.pipe(
|
||||
switchMap(() =>
|
||||
this.cephfsSubvolumeGroup.get(this.fsName).pipe(
|
||||
catchError(() => {
|
||||
this.context.error();
|
||||
return of(null);
|
||||
})
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
);
|
||||
}
|
||||
|
||||
fetchData() {
|
||||
this.subject.next();
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.subvolumeGroup$ = this.cephfsSubvolumeGroup.get(this.fsName).pipe(
|
||||
catchError(() => {
|
||||
this.context.error();
|
||||
return of(null);
|
||||
})
|
||||
);
|
||||
this.subject.next();
|
||||
}
|
||||
|
||||
updateSelection(selection: CdTableSelection) {
|
||||
|
@ -0,0 +1,139 @@
|
||||
<cd-modal [modalRef]="activeModal">
|
||||
<ng-container i18n="form title"
|
||||
class="modal-title">{{ action | titlecase }} {{ resource | upperFirst }}</ng-container>
|
||||
|
||||
<ng-container class="modal-content">
|
||||
<form name="subvolumegroupForm"
|
||||
#formDir="ngForm"
|
||||
[formGroup]="subvolumegroupForm"
|
||||
novalidate>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label required"
|
||||
for="subvolumegroupName"
|
||||
i18n>Name</label>
|
||||
<div class="cd-col-form-input">
|
||||
<input class="form-control"
|
||||
type="text"
|
||||
placeholder="subvolumegroup name..."
|
||||
id="subvolumegroupName"
|
||||
name="subvolumegroupName"
|
||||
formControlName="subvolumegroupName"
|
||||
autofocus>
|
||||
<span class="invalid-feedback"
|
||||
*ngIf="subvolumegroupForm.showError('subvolumegroupName', formDir, 'required')"
|
||||
i18n>This field is required.</span>
|
||||
<span class="invalid-feedback"
|
||||
*ngIf="subvolumegroupForm.showError('subvolumegroupName', formDir, 'notUnique')"
|
||||
i18n>The subvolumegroup already exists.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Volume name -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="volumeName"
|
||||
i18n>Volume name</label>
|
||||
<div class="cd-col-form-input">
|
||||
<input class="form-control"
|
||||
id="volumeName"
|
||||
name="volumeName"
|
||||
formControlName="volumeName">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Size -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="size"
|
||||
i18n>Size
|
||||
<cd-helper>The size of the subvolumegropup is specified by setting a quota on it.
|
||||
If left blank or put 0, then quota will be infinite</cd-helper>
|
||||
</label>
|
||||
<div class="cd-col-form-input">
|
||||
<input class="form-control"
|
||||
type="text"
|
||||
id="size"
|
||||
name="size"
|
||||
formControlName="size"
|
||||
i18n-placeholder
|
||||
placeholder="e.g., 10GiB"
|
||||
defaultUnit="GiB"
|
||||
cdDimlessBinary>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CephFS Pools -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="pool"
|
||||
i18n>Pool
|
||||
<cd-helper>By default, the data_pool_layout of the parent directory is selected.</cd-helper>
|
||||
</label>
|
||||
<div class="cd-col-form-input">
|
||||
<select class="form-select"
|
||||
id="pool"
|
||||
name="pool"
|
||||
formControlName="pool">
|
||||
<option *ngFor="let pool of dataPools"
|
||||
[value]="pool.pool">{{ pool.pool }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- UID -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="uid"
|
||||
i18n>UID</label>
|
||||
<div class="cd-col-form-input">
|
||||
<input class="form-control"
|
||||
type="number"
|
||||
placeholder="subvolumegroup UID..."
|
||||
id="uid"
|
||||
name="uid"
|
||||
formControlName="uid">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GID -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="gid"
|
||||
i18n>GID</label>
|
||||
<div class="cd-col-form-input">
|
||||
<input class="form-control"
|
||||
type="number"
|
||||
placeholder="subvolumegroup GID..."
|
||||
id="gid"
|
||||
name="gid"
|
||||
formControlName="gid">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mode -->
|
||||
<div class="form-group row">
|
||||
<label class="cd-col-form-label"
|
||||
for="mode"
|
||||
i18n>Mode
|
||||
<cd-helper>Permissions for the directory. Default mode is 755 which is rwxr-xr-x</cd-helper>
|
||||
</label>
|
||||
<div class="cd-col-form-input">
|
||||
<cd-checked-table-form [data]="scopePermissions"
|
||||
[columns]="columns"
|
||||
[form]="subvolumegroupForm"
|
||||
inputField="mode"
|
||||
[isTableForOctalMode]="true"
|
||||
[scopes]="scopes"></cd-checked-table-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<cd-form-button-panel (submitActionEvent)="submit()"
|
||||
[form]="subvolumegroupForm"
|
||||
[submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"></cd-form-button-panel>
|
||||
</div>
|
||||
</form>
|
||||
</ng-container>
|
||||
</cd-modal>
|
@ -0,0 +1,39 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CephfsSubvolumegroupFormComponent } from './cephfs-subvolumegroup-form.component';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
import { SharedModule } from '~/app/shared/shared.module';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
|
||||
describe('CephfsSubvolumegroupFormComponent', () => {
|
||||
let component: CephfsSubvolumegroupFormComponent;
|
||||
let fixture: ComponentFixture<CephfsSubvolumegroupFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [CephfsSubvolumegroupFormComponent],
|
||||
providers: [NgbActiveModal],
|
||||
imports: [
|
||||
SharedModule,
|
||||
ToastrModule.forRoot(),
|
||||
ReactiveFormsModule,
|
||||
HttpClientTestingModule,
|
||||
RouterTestingModule
|
||||
]
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CephfsSubvolumegroupFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.pools = [];
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,135 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, Validators } from '@angular/forms';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { CephfsSubvolumeGroupService } from '~/app/shared/api/cephfs-subvolume-group.service';
|
||||
import { ActionLabelsI18n, URLVerbs } from '~/app/shared/constants/app.constants';
|
||||
import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
|
||||
import { FinishedTask } from '~/app/shared/models/finished-task';
|
||||
import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
|
||||
import { Pool } from '../../pool/pool';
|
||||
import { FormatterService } from '~/app/shared/services/formatter.service';
|
||||
import { CdTableColumn } from '~/app/shared/models/cd-table-column';
|
||||
import _ from 'lodash';
|
||||
import { CdValidators } from '~/app/shared/forms/cd-validators';
|
||||
|
||||
@Component({
|
||||
selector: 'cd-cephfs-subvolumegroup-form',
|
||||
templateUrl: './cephfs-subvolumegroup-form.component.html',
|
||||
styleUrls: ['./cephfs-subvolumegroup-form.component.scss']
|
||||
})
|
||||
export class CephfsSubvolumegroupFormComponent implements OnInit {
|
||||
fsName: string;
|
||||
pools: Pool[];
|
||||
|
||||
subvolumegroupForm: CdFormGroup;
|
||||
|
||||
action: string;
|
||||
resource: string;
|
||||
|
||||
dataPools: Pool[];
|
||||
|
||||
columns: CdTableColumn[];
|
||||
scopePermissions: Array<any> = [];
|
||||
scopes: string[] = ['owner', 'group', 'others'];
|
||||
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
private actionLabels: ActionLabelsI18n,
|
||||
private taskWrapper: TaskWrapperService,
|
||||
private cephfsSubvolumeGroupService: CephfsSubvolumeGroupService,
|
||||
private formatter: FormatterService
|
||||
) {
|
||||
this.action = this.actionLabels.CREATE;
|
||||
this.resource = $localize`subvolume group`;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.columns = [
|
||||
{
|
||||
prop: 'scope',
|
||||
name: $localize`All`,
|
||||
flexGrow: 0.5
|
||||
},
|
||||
{
|
||||
prop: 'read',
|
||||
name: $localize`Read`,
|
||||
flexGrow: 0.5,
|
||||
cellClass: 'text-center'
|
||||
},
|
||||
{
|
||||
prop: 'write',
|
||||
name: $localize`Write`,
|
||||
flexGrow: 0.5,
|
||||
cellClass: 'text-center'
|
||||
},
|
||||
{
|
||||
prop: 'execute',
|
||||
name: $localize`Execute`,
|
||||
flexGrow: 0.5,
|
||||
cellClass: 'text-center'
|
||||
}
|
||||
];
|
||||
|
||||
this.dataPools = this.pools.filter((pool) => pool.type === 'data');
|
||||
this.createForm();
|
||||
}
|
||||
|
||||
createForm() {
|
||||
this.subvolumegroupForm = new CdFormGroup({
|
||||
volumeName: new FormControl({ value: this.fsName, disabled: true }),
|
||||
subvolumegroupName: new FormControl('', {
|
||||
validators: [Validators.required],
|
||||
asyncValidators: [
|
||||
CdValidators.unique(
|
||||
this.cephfsSubvolumeGroupService.exists,
|
||||
this.cephfsSubvolumeGroupService,
|
||||
null,
|
||||
null,
|
||||
this.fsName
|
||||
)
|
||||
]
|
||||
}),
|
||||
pool: new FormControl(this.dataPools[0]?.pool, {
|
||||
validators: [Validators.required]
|
||||
}),
|
||||
size: new FormControl(null, {
|
||||
updateOn: 'blur'
|
||||
}),
|
||||
uid: new FormControl(null),
|
||||
gid: new FormControl(null),
|
||||
mode: new FormControl({})
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
const subvolumegroupName = this.subvolumegroupForm.getValue('subvolumegroupName');
|
||||
const pool = this.subvolumegroupForm.getValue('pool');
|
||||
const size = this.formatter.toBytes(this.subvolumegroupForm.getValue('size'));
|
||||
const uid = this.subvolumegroupForm.getValue('uid');
|
||||
const gid = this.subvolumegroupForm.getValue('gid');
|
||||
const mode = this.formatter.toOctalPermission(this.subvolumegroupForm.getValue('mode'));
|
||||
this.taskWrapper
|
||||
.wrapTaskAroundCall({
|
||||
task: new FinishedTask('cephfs/subvolume/group/' + URLVerbs.CREATE, {
|
||||
subvolumegroupName: subvolumegroupName
|
||||
}),
|
||||
call: this.cephfsSubvolumeGroupService.create(
|
||||
this.fsName,
|
||||
subvolumegroupName,
|
||||
pool,
|
||||
size,
|
||||
uid,
|
||||
gid,
|
||||
mode
|
||||
)
|
||||
})
|
||||
.subscribe({
|
||||
error: () => {
|
||||
this.subvolumegroupForm.setErrors({ cdSubmitButton: true });
|
||||
},
|
||||
complete: () => {
|
||||
this.activeModal.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -24,7 +24,8 @@
|
||||
<a ngbNavLink
|
||||
i18n>Subvolume groups</a>
|
||||
<ng-template ngbNavContent>
|
||||
<cd-cephfs-subvolume-group [fsName]="selection.mdsmap.fs_name">
|
||||
<cd-cephfs-subvolume-group [fsName]="selection.mdsmap.fs_name"
|
||||
[pools]="details.pools">
|
||||
</cd-cephfs-subvolume-group>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
@ -18,6 +18,7 @@ import { CephfsTabsComponent } from './cephfs-tabs/cephfs-tabs.component';
|
||||
import { CephfsSubvolumeListComponent } from './cephfs-subvolume-list/cephfs-subvolume-list.component';
|
||||
import { CephfsSubvolumeFormComponent } from './cephfs-subvolume-form/cephfs-subvolume-form.component';
|
||||
import { CephfsSubvolumeGroupComponent } from './cephfs-subvolume-group/cephfs-subvolume-group.component';
|
||||
import { CephfsSubvolumegroupFormComponent } from './cephfs-subvolumegroup-form/cephfs-subvolumegroup-form.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -43,7 +44,8 @@ import { CephfsSubvolumeGroupComponent } from './cephfs-subvolume-group/cephfs-s
|
||||
CephfsSubvolumeListComponent,
|
||||
CephfsSubvolumeFormComponent,
|
||||
CephfsDirectoriesComponent,
|
||||
CephfsSubvolumeGroupComponent
|
||||
CephfsSubvolumeGroupComponent,
|
||||
CephfsSubvolumegroupFormComponent
|
||||
]
|
||||
})
|
||||
export class CephfsModule {}
|
||||
|
@ -1,7 +1,9 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { CephfsSubvolumeGroup } from '../models/cephfs-subvolume-group.model';
|
||||
import _ from 'lodash';
|
||||
import { mapTo, catchError } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -14,4 +16,48 @@ export class CephfsSubvolumeGroupService {
|
||||
get(volName: string): Observable<CephfsSubvolumeGroup[]> {
|
||||
return this.http.get<CephfsSubvolumeGroup[]>(`${this.baseURL}/${volName}`);
|
||||
}
|
||||
|
||||
create(
|
||||
volName: string,
|
||||
groupName: string,
|
||||
poolName: string,
|
||||
size: number,
|
||||
uid: number,
|
||||
gid: number,
|
||||
mode: string
|
||||
) {
|
||||
return this.http.post(
|
||||
this.baseURL,
|
||||
{
|
||||
vol_name: volName,
|
||||
group_name: groupName,
|
||||
pool_layout: poolName,
|
||||
size: size,
|
||||
uid: uid,
|
||||
gid: gid,
|
||||
mode: mode
|
||||
},
|
||||
{ observe: 'response' }
|
||||
);
|
||||
}
|
||||
|
||||
info(volName: string, groupName: string) {
|
||||
return this.http.get(`${this.baseURL}/${volName}/info`, {
|
||||
params: {
|
||||
group_name: groupName
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exists(groupName: string, volName: string) {
|
||||
return this.info(volName, groupName).pipe(
|
||||
mapTo(true),
|
||||
catchError((error: Event) => {
|
||||
if (_.isFunction(error.preventDefault)) {
|
||||
error.preventDefault();
|
||||
}
|
||||
return of(false);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -358,6 +358,9 @@ export class TaskMessageService {
|
||||
),
|
||||
'cephfs/subvolume/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
|
||||
this.subvolume(metadata)
|
||||
),
|
||||
'cephfs/subvolume/group/create': this.newTaskMessage(this.commonOperations.create, (metadata) =>
|
||||
this.subvolumegroup(metadata)
|
||||
)
|
||||
};
|
||||
|
||||
@ -422,6 +425,10 @@ export class TaskMessageService {
|
||||
return $localize`subvolume '${metadata.subVolumeName}'`;
|
||||
}
|
||||
|
||||
subvolumegroup(metadata: any) {
|
||||
return $localize`subvolume group '${metadata.subvolumegroupName}'`;
|
||||
}
|
||||
|
||||
crudMessageId(id: string) {
|
||||
return $localize`${id}`;
|
||||
}
|
||||
|
@ -1721,6 +1721,46 @@ paths:
|
||||
- jwt: []
|
||||
tags:
|
||||
- CephFSSubvolume
|
||||
/api/cephfs/subvolume/group:
|
||||
post:
|
||||
parameters: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
group_name:
|
||||
type: string
|
||||
vol_name:
|
||||
type: string
|
||||
required:
|
||||
- vol_name
|
||||
- group_name
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/vnd.ceph.api.v1.0+json:
|
||||
type: object
|
||||
description: Resource created.
|
||||
'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:
|
||||
- CephfsSubvolumeGroup
|
||||
/api/cephfs/subvolume/group/{vol_name}:
|
||||
get:
|
||||
parameters:
|
||||
|
Loading…
Reference in New Issue
Block a user