diff --git a/trove/cmd/manage.py b/trove/cmd/manage.py index 8bccb60d6e..e456451e2b 100644 --- a/trove/cmd/manage.py +++ b/trove/cmd/manage.py @@ -85,18 +85,21 @@ class Commands(object): def db_load_datastore_config_parameters(self, datastore, datastore_version_name, - config_file_location): + config_file_location, + version=None): print("Loading config parameters for datastore (%s) version (%s)" % (datastore, datastore_version_name)) config_models.load_datastore_configuration_parameters( - datastore, datastore_version_name, config_file_location) + datastore, datastore_version_name, config_file_location, + version_number=version) def db_remove_datastore_config_parameters(self, datastore, - datastore_version_name): + datastore_version_name, + version=None): print("Removing config parameters for datastore (%s) version (%s)" % (datastore, datastore_version_name)) config_models.remove_datastore_configuration_parameters( - datastore, datastore_version_name) + datastore, datastore_version_name, version_number=version) def datastore_version_flavor_add(self, datastore_name, datastore_version_name, flavor_ids, @@ -282,6 +285,11 @@ def main(): 'config_file_location', help='Fully qualified file path to the configuration group ' 'parameter validation rules.') + parser.add_argument( + '--version', + help='The version number of the datastore version, e.g. 5.7.30. ' + 'If not specified, use as default ' + 'value.') parser = subparser.add_parser( 'db_remove_datastore_config_parameters', @@ -293,6 +301,11 @@ def main(): parser.add_argument( 'datastore_version_name', help='Name of the datastore version.') + parser.add_argument( + '--version', + help='The version number of the datastore version, e.g. 5.7.30. ' + 'If not specified, use as default ' + 'value.') parser = subparser.add_parser( 'datastore_version_flavor_add', diff --git a/trove/common/apischema.py b/trove/common/apischema.py index d1dec14608..4c799992cb 100644 --- a/trove/common/apischema.py +++ b/trove/common/apischema.py @@ -821,7 +821,8 @@ configuration = { "additionalProperties": True, "properties": { "type": non_empty_string, - "version": non_empty_string + "version": non_empty_string, + "version_number": non_empty_string } } } diff --git a/trove/configuration/models.py b/trove/configuration/models.py index 294ef42c60..8ec9747742 100644 --- a/trove/configuration/models.py +++ b/trove/configuration/models.py @@ -354,17 +354,16 @@ def create_or_update_datastore_configuration_parameter(name, data_type=data_type, max_size=max_size, min_size=min_size, - deleted=False, ) get_db_api().save(config) -def load_datastore_configuration_parameters(datastore, - datastore_version, - config_file): +def load_datastore_configuration_parameters(datastore, datastore_version, + config_file, version_number=None): get_db_api().configure_db(CONF) (ds, ds_v) = dstore_models.get_datastore_version( - type=datastore, version=datastore_version, return_inactive=True) + type=datastore, version=datastore_version, return_inactive=True, + version_number=version_number) with open(config_file) as f: config = json.load(f) for param in config['configuration-parameters']: @@ -378,10 +377,12 @@ def load_datastore_configuration_parameters(datastore, ) -def remove_datastore_configuration_parameters(datastore, datastore_version): +def remove_datastore_configuration_parameters(datastore, datastore_version, + version_number=None): get_db_api().configure_db(CONF) (ds, ds_version) = dstore_models.get_datastore_version( - type=datastore, version=datastore_version, return_inactive=True) + type=datastore, version=datastore_version, return_inactive=True, + version_number=version_number) db_params = DatastoreConfigurationParameters.load_parameters(ds_version.id) for db_param in db_params: db_param.delete() diff --git a/trove/db/sqlalchemy/migrate_repo/versions/044_remove_datastore_configuration_parameters_deleted.py b/trove/db/sqlalchemy/migrate_repo/versions/044_remove_datastore_configuration_parameters_deleted.py index 7ce81d6a1c..7b34b00035 100644 --- a/trove/db/sqlalchemy/migrate_repo/versions/044_remove_datastore_configuration_parameters_deleted.py +++ b/trove/db/sqlalchemy/migrate_repo/versions/044_remove_datastore_configuration_parameters_deleted.py @@ -11,19 +11,20 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +import sqlalchemy +from sqlalchemy import schema -from sqlalchemy.schema import MetaData +from trove.db.sqlalchemy.migrate_repo import schema as trove_schema -from trove.db.sqlalchemy.migrate_repo.schema import Table - -meta = MetaData() +meta = schema.MetaData() def upgrade(migrate_engine): meta.bind = migrate_engine - ds_config_param = Table('datastore_configuration_parameters', meta, - autoload=True) + ds_config_param = trove_schema.Table('datastore_configuration_parameters', + meta, + autoload=True) # Remove records with deleted=1 if 'deleted' in ds_config_param.c: @@ -35,3 +36,32 @@ def upgrade(migrate_engine): if migrate_engine.name != "sqlite": ds_config_param.drop_column('deleted') ds_config_param.drop_column('deleted_at') + else: + # It is not possible to remove a column from a table in SQLite. + # SQLite is just for testing, so we re-create the table. + ds_config_param.drop() + meta.clear() + trove_schema.Table('datastore_versions', meta, autoload=True) + new_table = trove_schema.Table( + 'datastore_configuration_parameters', + meta, + schema.Column('id', trove_schema.String(36), + primary_key=True, nullable=False), + schema.Column('name', trove_schema.String(128), + primary_key=True, nullable=False), + schema.Column('datastore_version_id', trove_schema.String(36), + sqlalchemy.ForeignKey("datastore_versions.id"), + primary_key=True, nullable=False), + schema.Column('restart_required', trove_schema.Boolean(), + nullable=False, default=False), + schema.Column('max_size', trove_schema.String(40)), + schema.Column('min_size', trove_schema.String(40)), + schema.Column('data_type', trove_schema.String(128), + nullable=False), + schema.UniqueConstraint( + 'datastore_version_id', 'name', + name=('UQ_datastore_configuration_parameters_datastore_' + 'version_id_name') + ) + ) + trove_schema.create_tables([new_table]) diff --git a/trove/extensions/mgmt/datastores/service.py b/trove/extensions/mgmt/datastores/service.py index be9999f20f..7eeb899e57 100644 --- a/trove/extensions/mgmt/datastores/service.py +++ b/trove/extensions/mgmt/datastores/service.py @@ -188,6 +188,13 @@ class DatastoreVersionController(wsgi.Controller): {'tenant': tenant_id, 'version': datastore_version.name, 'datastore': datastore.name}) + # Remove the config parameters associated with the datastore version + LOG.debug(f"Deleting config parameters for datastore version {id}") + db_params = config_model.DatastoreConfigurationParameters. \ + load_parameters(id) + for db_param in db_params: + db_param.delete() + if datastore.default_version_id == datastore_version.id: models.update_datastore(datastore.name, None) datastore_version.delete() diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index 786ebbdbcc..c31d7787b9 100755 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -2100,7 +2100,7 @@ class RebuildAction(ResizeActionBase): LOG.info(f"Sending rebuild request to the instance {self.instance.id}") self.instance.guest.rebuild( - self.instance.datastore_version.name, + self.instance.datastore_version.version, config_contents=config_contents, config_overrides=overrides) LOG.info(f"Waiting for instance {self.instance.id} healthy") diff --git a/trove/tests/unittests/extensions/mgmt/datastores/test_service.py b/trove/tests/unittests/extensions/mgmt/datastores/test_service.py index 8b7be4660b..79af2b07f6 100644 --- a/trove/tests/unittests/extensions/mgmt/datastores/test_service.py +++ b/trove/tests/unittests/extensions/mgmt/datastores/test_service.py @@ -21,6 +21,7 @@ import jsonschema from trove.common import clients from trove.common import exception +from trove.configuration import models as config_models from trove.datastore import models from trove.extensions.mgmt.datastores.service import DatastoreVersionController from trove.tests.unittests import trove_testtools @@ -318,6 +319,12 @@ class TestDatastoreVersionController(trove_testtools.TestCase): self.ds_name, name, 'mysql', self.random_uuid(), '', '', 1) ver = models.DatastoreVersion.load(self.ds, name) + # Add config param for the datastore version. Should be automatically + # removed. + param_name = self.random_name('param') + config_models.create_or_update_datastore_configuration_parameter( + param_name, ver.id, False, 'string', None, None) + output = self.version_controller.delete(MagicMock(), mock.ANY, ver.id) @@ -327,6 +334,12 @@ class TestDatastoreVersionController(trove_testtools.TestCase): exception.DatastoreVersionNotFound, models.DatastoreVersion.load_by_uuid, ver.id) + config_params_cls = config_models.DatastoreConfigurationParameters + self.assertRaises( + exception.NotFound, + config_params_cls.load_parameter_by_name, + ver.id, param_name) + def test_index(self): output = self.version_controller.index(MagicMock(), mock.ANY) self.assertEqual(200, output.status)