From 2f1f55c08abaa55db488322813b9e960491ac206 Mon Sep 17 00:00:00 2001 From: guodan1 Date: Wed, 14 Nov 2018 20:34:03 +0800 Subject: [PATCH] mgr/dashboard: Allow renaming an existing Pool fixes: http://tracker.ceph.com/issues/36560 Signed-off-by: guodan1 --- src/pybind/mgr/dashboard/controllers/pool.py | 13 ++++-- .../pool-form/pool-form.component.spec.ts | 20 +++++---- .../pool/pool-form/pool-form.component.ts | 44 ++++++++++++++----- .../src/app/shared/api/pool.service.ts | 10 ++++- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/pool.py b/src/pybind/mgr/dashboard/controllers/pool.py index 1964204d88e..cdd9a7110d4 100644 --- a/src/pybind/mgr/dashboard/controllers/pool.py +++ b/src/pybind/mgr/dashboard/controllers/pool.py @@ -91,6 +91,7 @@ class Pool(RESTController): self._set_pool_values(pool, application_metadata, flags, False, kwargs) def _set_pool_values(self, pool, application_metadata, flags, update_existing, kwargs): + update_name = False if update_existing: current_pool = self._get(pool) self._handle_update_compression_args(current_pool.get('options'), kwargs) @@ -116,9 +117,15 @@ class Pool(RESTController): CephService.send_command('mon', 'osd pool set', pool=pool, var=key, val=str(value)) for key, value in kwargs.items(): - set_key(key, value) - if key == 'pg_num': - set_key('pgp_num', value) + if key == 'pool': + update_name = True + destpool = value + else: + set_key(key, value) + if key == 'pg_num': + set_key('pgp_num', value) + if update_name: + CephService.send_command('mon', 'osd pool rename', srcpool=pool, destpool=destpool) def _handle_update_compression_args(self, options, kwargs): if kwargs.get('compression_mode') == 'unset' and options is not None: diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts index 133578afec4..9507b5fb84a 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.spec.ts @@ -221,6 +221,7 @@ describe('PoolFormComponent', () => { }); it('validates name', () => { + expect(component.editing).toBeFalsy(); formHelper.expectError('name', 'required'); formHelper.expectValidChange('name', 'some-name'); component.info.pool_names.push('someExistingPoolName'); @@ -990,18 +991,19 @@ describe('PoolFormComponent', () => { }); it('disabled inputs', () => { - const disabled = [ - 'name', - 'poolType', - 'crushRule', - 'size', - 'erasureProfile', - 'ecOverwrites' - ]; + const disabled = ['poolType', 'crushRule', 'size', 'erasureProfile', 'ecOverwrites']; disabled.forEach((controlName) => { return expect(form.get(controlName).disabled).toBeTruthy(); }); - const enabled = ['pgNum', 'mode', 'algorithm', 'minBlobSize', 'maxBlobSize', 'ratio']; + const enabled = [ + 'name', + 'pgNum', + 'mode', + 'algorithm', + 'minBlobSize', + 'maxBlobSize', + 'ratio' + ]; enabled.forEach((controlName) => { return expect(form.get(controlName).enabled).toBeTruthy(); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts index 7931368babd..a17802a574c 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/pool/pool-form/pool-form.component.ts @@ -100,14 +100,7 @@ export class PoolFormComponent implements OnInit { this.form = new CdFormGroup( { name: new FormControl('', { - validators: [ - Validators.pattern('[A-Za-z0-9_-]+'), - Validators.required, - CdValidators.custom( - 'uniqueName', - (value) => this.info && this.info.pool_names.indexOf(value) !== -1 - ) - ] + validators: [Validators.pattern('[A-Za-z0-9_-]+'), Validators.required] }), poolType: new FormControl('', { validators: [Validators.required] @@ -178,8 +171,8 @@ export class PoolFormComponent implements OnInit { } private disableForEdit() { - ['name', 'poolType', 'crushRule', 'size', 'erasureProfile', 'ecOverwrites'].forEach( - (controlName) => this.form.get(controlName).disable() + ['poolType', 'crushRule', 'size', 'erasureProfile', 'ecOverwrites'].forEach((controlName) => + this.form.get(controlName).disable() ); } @@ -380,6 +373,20 @@ export class PoolFormComponent implements OnInit { .setValidators( CdValidators.custom('noDecrease', (pgs) => this.data.pool && pgs < this.data.pool.pg_num) ); + this.form + .get('name') + .setValidators([ + this.form.get('name').validator, + CdValidators.custom( + 'uniqueName', + (name) => + this.data.pool && + this.info && + this.info.pool_names.indexOf(name) !== -1 && + this.info.pool_names.indexOf(name) !== + this.info.pool_names.indexOf(this.data.pool.pool_name) + ) + ]); } else { CdValidators.validateIf( this.form.get('size'), @@ -395,6 +402,15 @@ export class PoolFormComponent implements OnInit { ) ] ); + this.form + .get('name') + .setValidators([ + this.form.get('name').validator, + CdValidators.custom( + 'uniqueName', + (name) => this.info && this.info.pool_names.indexOf(name) !== -1 + ) + ]); } this.setCompressionValidators(); } @@ -543,6 +559,12 @@ export class PoolFormComponent implements OnInit { formControlName: 'mode', editable: true, replaceFn: () => 'unset' + }, + { + externalFieldName: 'srcpool', + formControlName: 'name', + editable: true, + replaceFn: () => this.data.pool.pool_name } ]); } @@ -598,7 +620,7 @@ export class PoolFormComponent implements OnInit { this.taskWrapper .wrapTaskAroundCall({ task: new FinishedTask('pool/' + (this.editing ? 'edit' : 'create'), { - pool_name: pool.pool + pool_name: pool.hasOwnProperty('srcpool') ? pool.srcpool : pool.pool }), call: this.poolService[this.editing ? 'update' : 'create'](pool) }) diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts index 59f4eec6867..30a5c6ecaaa 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/api/pool.service.ts @@ -21,8 +21,14 @@ export class PoolService { } update(pool) { - const name = pool.pool; - delete pool.pool; + let name: string; + if (pool.hasOwnProperty('srcpool')) { + name = pool.srcpool; + delete pool.srcpool; + } else { + name = pool.pool; + delete pool.pool; + } return this.http.put(`${this.apiPath}/${name}`, pool, { observe: 'response' }); } -- 2.39.5