Skip to content

Commit 122c6b2

Browse files
authored
Merge pull request ceph#54648 from rhcs-dashboard/fs-rename-fix
mgr/dashboard: fs rename only when fs is offline Reviewed-by: Pedro Gonzalez Gomez <[email protected]> Reviewed-by: Ankush Behl <[email protected]> Reviewed-by: ivoalmeida <NOT@FOUND>
2 parents a34821a + 2c8faf2 commit 122c6b2

File tree

13 files changed

+169
-16
lines changed

13 files changed

+169
-16
lines changed

src/pybind/mgr/dashboard/controllers/cephfs.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,13 +335,16 @@ def fs_status(self, fs_id):
335335

336336
standby_table = self.get_standby_table(fsmap['standbys'], mds_versions)
337337

338+
flags = mdsmap['flags_state']
339+
338340
return {
339341
"cephfs": {
340342
"id": fs_id,
341343
"name": mdsmap['fs_name'],
342344
"client_count": client_count,
343345
"ranks": rank_table,
344-
"pools": pools_table
346+
"pools": pools_table,
347+
"flags": flags,
345348
},
346349
"standbys": standby_table,
347350
"versions": mds_versions

src/pybind/mgr/dashboard/frontend/cypress/e2e/filesystems/filesystems.e2e-spec.feature

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,20 @@ Feature: CephFS Management
1212
And I click on "Create File System" button
1313
Then I should see a row with "test_cephfs"
1414

15-
Scenario: Edit CephFS Volume
16-
Given I am on the "cephfs" page
17-
And I select a row "test_cephfs"
18-
And I click on "Edit" button
19-
And enter "name" "test_cephfs_edit"
20-
And I click on "Edit File System" button
21-
Then I should see a row with "test_cephfs_edit"
15+
# Should be uncommented once the pre-requisite is fixed
16+
# Scenario: Edit CephFS Volume
17+
# Given I am on the "cephfs" page
18+
# And I select a row "test_cephfs"
19+
# And I click on "Edit" button
20+
# And enter "name" "test_cephfs_edit"
21+
# And I click on "Edit File System" button
22+
# Then I should see a row with "test_cephfs_edit"
2223

2324
Scenario: Remove CephFS Volume
2425
Given I am on the "cephfs" page
25-
And I select a row "test_cephfs_edit"
26+
And I select a row "test_cephfs"
2627
And I click on "Remove" button from the table actions
2728
Then I should see the modal
2829
And I check the tick box in modal
2930
And I click on "Remove File System" button
30-
Then I should not see a row with "test_cephfs_edit"
31+
Then I should not see a row with "test_cephfs"

src/pybind/mgr/dashboard/frontend/src/app/app-routing.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ const routes: Routes = [
361361
data: { breadcrumbs: ActionLabels.CREATE }
362362
},
363363
{
364-
path: `${URLVerbs.EDIT}/:name`,
364+
path: `${URLVerbs.EDIT}/:id`,
365365
component: CephfsVolumeFormComponent,
366366
data: { breadcrumbs: ActionLabels.EDIT }
367367
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515
i18n
1616
*ngIf="!editing">Orchestrator is not configured. Deploy MDS daemons manually after creating the volume.</cd-alert-panel>
1717
</ng-container>
18+
19+
<cd-alert-panel type="info"
20+
class="m-3"
21+
spacingClass="mt-3"
22+
i18n
23+
*ngIf="editing && disableRename">
24+
<p>The File System can only be renamed if it is shutdown and `refuse_client_session` is set to true.
25+
Follow the steps below in the command line and refresh the page:</p>
26+
<cd-code-block [codes]="[fsFailCmd]"></cd-code-block>
27+
<cd-code-block [codes]="[fsSetCmd]"></cd-code-block>
28+
</cd-alert-panel>
29+
1830
<div class="card-body">
1931
<!-- Name -->
2032
<div class="form-group row">
@@ -98,6 +110,7 @@
98110
<cd-form-button-panel (submitActionEvent)="submit()"
99111
[form]="form"
100112
[submitText]="(action | titlecase) + ' ' + (resource | upperFirst)"
113+
[disabled]="editing ? disableRename: false"
101114
wrappingClass="text-right"></cd-form-button-panel>
102115
</div>
103116
</div>

src/pybind/mgr/dashboard/frontend/src/app/ceph/cephfs/cephfs-form/cephfs-form.component.spec.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,42 @@ describe('CephfsVolumeFormComponent', () => {
7878
expect(label).toBeNull();
7979
expect(hosts).toBeNull();
8080
});
81+
82+
it('should disable renaming and show info alert if disableRename is true', () => {
83+
component.disableRename = true;
84+
component.ngOnInit();
85+
fixture.detectChanges();
86+
const alertPanel = fixture.debugElement.query(By.css('cd-alert-panel'));
87+
expect(alertPanel).not.toBeNull();
88+
});
89+
90+
it('should not show the alert if disableRename is false', () => {
91+
component.disableRename = false;
92+
component.ngOnInit();
93+
fixture.detectChanges();
94+
const alertPanel = fixture.debugElement.query(By.css('cd-alert-panel'));
95+
expect(alertPanel).toBeNull();
96+
});
97+
98+
it('should disable the submit button only if disableRename is true', () => {
99+
component.disableRename = true;
100+
component.ngOnInit();
101+
fixture.detectChanges();
102+
const submitButton = fixture.debugElement.query(By.css('button[type=submit]'));
103+
expect(submitButton.nativeElement.disabled).toBeTruthy();
104+
105+
// the submit button should only be disabled when the form is in edit mode
106+
component.editing = false;
107+
component.ngOnInit();
108+
fixture.detectChanges();
109+
expect(submitButton.nativeElement.disabled).toBeFalsy();
110+
111+
// submit button should be enabled if disableRename is false
112+
component.editing = true;
113+
component.disableRename = false;
114+
component.ngOnInit();
115+
fixture.detectChanges();
116+
expect(submitButton.nativeElement.disabled).toBeFalsy();
117+
});
81118
});
82119
});

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ export class CephfsVolumeFormComponent extends CdForm implements OnInit {
5151
labels: string[];
5252
hasOrchestrator: boolean;
5353
currentVolumeName: string;
54+
fsId: number;
55+
disableRename: boolean = true;
56+
57+
fsFailCmd: string;
58+
fsSetCmd: string;
5459

5560
constructor(
5661
private router: Router,
@@ -101,9 +106,22 @@ export class CephfsVolumeFormComponent extends CdForm implements OnInit {
101106

102107
ngOnInit() {
103108
if (this.editing) {
104-
this.route.params.subscribe((params: { name: string }) => {
105-
this.currentVolumeName = params.name;
109+
this.route.params.subscribe((params: { id: string }) => {
110+
this.fsId = Number(params.id);
111+
});
112+
113+
this.cephfsService.getCephfs(this.fsId).subscribe((resp: object) => {
114+
this.currentVolumeName = resp['cephfs']['name'];
106115
this.form.get('name').setValue(this.currentVolumeName);
116+
117+
this.disableRename = !(
118+
!resp['cephfs']['flags']['joinable'] && resp['cephfs']['flags']['refuse_client_session']
119+
);
120+
if (this.disableRename) {
121+
this.form.get('name').disable();
122+
this.fsFailCmd = `ceph fs fail ${this.currentVolumeName}`;
123+
this.fsSetCmd = `ceph fs set ${this.currentVolumeName} refuse_client_session true`;
124+
}
107125
});
108126
} else {
109127
const hostContext = new CdTableFetchDataContext(() => undefined);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export class CephfsListComponent extends ListWithDetails implements OnInit {
8787
permission: 'update',
8888
icon: Icons.edit,
8989
click: () =>
90-
this.router.navigate([this.urlBuilder.getEdit(this.selection.first().mdsmap.fs_name)])
90+
this.router.navigate([this.urlBuilder.getEdit(String(this.selection.first().id))])
9191
},
9292
{
9393
permission: 'delete',
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<ng-container *ngIf="codes.length > 1; else singleCodeBlock">
2+
<pre id="bigCodeBlock">
3+
<span *ngFor="let code of codes"
4+
class="d-flex p-2 align-items-center justify-content-between text-dark">
5+
<span>{{code}}</span>
6+
<cd-copy-2-clipboard-button
7+
[source]="code"
8+
[byId]="false"></cd-copy-2-clipboard-button>
9+
</span>
10+
</pre>
11+
</ng-container>
12+
13+
<ng-template #singleCodeBlock>
14+
<pre class="d-flex p-2 align-items-center justify-content-between text-dark"
15+
id="singleCodeBlock">
16+
<span>{{codes}}</span>
17+
<cd-copy-2-clipboard-button
18+
[source]="codes"
19+
[byId]="false"></cd-copy-2-clipboard-button>
20+
</pre>
21+
</ng-template>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@use './src/styles/vendor/variables' as vv;
2+
3+
pre {
4+
background-color: vv.$code-block-bg;
5+
border-radius: 0.5rem;
6+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { CodeBlockComponent } from './code-block.component';
4+
import { configureTestBed } from '~/testing/unit-test-helper';
5+
6+
describe('CodeBlockComponent', () => {
7+
let component: CodeBlockComponent;
8+
let fixture: ComponentFixture<CodeBlockComponent>;
9+
10+
configureTestBed({
11+
declarations: [CodeBlockComponent]
12+
});
13+
14+
beforeEach(() => {
15+
fixture = TestBed.createComponent(CodeBlockComponent);
16+
component = fixture.componentInstance;
17+
component.codes = [];
18+
fixture.detectChanges();
19+
});
20+
21+
it('should create', () => {
22+
expect(component).toBeTruthy();
23+
});
24+
25+
it('should show single codeblock if there are only one code', () => {
26+
component.codes = ['code'];
27+
fixture.detectChanges();
28+
expect(fixture.nativeElement.querySelector('#singleCodeBlock')).not.toBeNull();
29+
expect(fixture.nativeElement.querySelector('#bigCodeBlock')).toBeNull();
30+
});
31+
32+
it('should show single codeblock if there are only one code', () => {
33+
component.codes = ['code1', 'code2'];
34+
fixture.detectChanges();
35+
expect(fixture.nativeElement.querySelector('#bigCodeBlock')).not.toBeNull();
36+
expect(fixture.nativeElement.querySelector('#singleCodeBlock')).toBeNull();
37+
});
38+
});

0 commit comments

Comments
 (0)