From f14c87f015a99221467a127568b13b9fa717a29f Mon Sep 17 00:00:00 2001 From: Craig Vyvial Date: Thu, 19 Dec 2013 14:03:45 -0600 Subject: [PATCH] move datastore manager to the datastore version This moves the datastore manager field to the datastore version object so that we can have managers per datastore version and they can be shared if nessesary. implements blueprint move-manager-to-datastore-version Change-Id: I1c889a01005ec482bcd44e0e19475bc972e1af04 --- bin/trove-manage | 19 ++++-- run_tests.py | 8 ++- trove/datastore/models.py | 23 ++++--- .../versions/017_update_datastores.py | 63 +++++++++++++++++++ trove/extensions/mgmt/instances/models.py | 5 +- trove/instance/models.py | 2 +- trove/taskmanager/api.py | 3 +- trove/taskmanager/models.py | 11 ++-- trove/tests/unittests/mgmt/test_models.py | 38 +++++++++-- 9 files changed, 141 insertions(+), 31 deletions(-) create mode 100644 trove/db/sqlalchemy/migrate_repo/versions/017_update_datastores.py diff --git a/bin/trove-manage b/bin/trove-manage index 5c0c501af5..2764a1009b 100755 --- a/bin/trove-manage +++ b/bin/trove-manage @@ -67,19 +67,21 @@ class Commands(object): kwargs[arg] = getattr(CONF.action, arg) exec_method(**kwargs) - def datastore_update(self, datastore_name, manager, default_version): + def datastore_update(self, datastore_name, default_version): try: - datastore_models.update_datastore(datastore_name, manager, + datastore_models.update_datastore(datastore_name, default_version) print("Datastore '%s' updated." % datastore_name) except exception.DatastoreVersionNotFound as e: print(e) - def datastore_version_update(self, datastore, version_name, image_id, - packages, active): + def datastore_version_update(self, datastore, version_name, manager, + image_id, packages, active): try: datastore_models.update_datastore_version(datastore, - version_name, image_id, + version_name, + manager, + image_id, packages, active) print("Datastore version '%s' updated." % version_name) except exception.DatastoreNotFound as e: @@ -100,22 +102,27 @@ def main(): def actions(subparser): parser = subparser.add_parser('db_sync') parser.add_argument('--repo_path') + parser = subparser.add_parser('db_upgrade') parser.add_argument('--version') parser.add_argument('--repo_path') + parser = subparser.add_parser('db_downgrade') parser.add_argument('version') parser.add_argument('--repo_path') + parser = subparser.add_parser('datastore_update') parser.add_argument('datastore_name') - parser.add_argument('manager') parser.add_argument('default_version') + parser = subparser.add_parser('datastore_version_update') parser.add_argument('datastore') parser.add_argument('version_name') + parser.add_argument('manager') parser.add_argument('image_id') parser.add_argument('packages') parser.add_argument('active') + parser = subparser.add_parser('db_wipe') parser.add_argument('repo_path') diff --git a/run_tests.py b/run_tests.py index 7cbf7874bc..91ed7456e4 100644 --- a/run_tests.py +++ b/run_tests.py @@ -73,17 +73,20 @@ def initialize_trove(config_file): def datastore_init(): # Adds the datastore for mysql (needed to make most calls work). from trove.datastore import models + models.DBDatastore.create(id="a00000a0-00a0-0a00-00a0-000a000000aa", - name=CONFIG.dbaas_datastore, manager='mysql', + name=CONFIG.dbaas_datastore, default_version_id= "b00000b0-00b0-0b00-00b0-000b000000bb") models.DBDatastore.create(id="e00000e0-00e0-0e00-00e0-000e000000ee", - name='Test_Datastore_1', manager='manager1', + name='Test_Datastore_1', default_version_id=None) + models.DBDatastoreVersion.create(id="b00000b0-00b0-0b00-00b0-000b000000bb", datastore_id= "a00000a0-00a0-0a00-00a0-000a000000aa", name=CONFIG.dbaas_datastore_version, + manager="mysql", image_id= 'c00000c0-00c0-0c00-00c0-000c000000cc', packages='test packages', @@ -92,6 +95,7 @@ def datastore_init(): datastore_id= "a00000a0-00a0-0a00-00a0-000a000000aa", name='mysql_inactive_version', + manager="mysql", image_id= 'c00000c0-00c0-0c00-00c0-000c000000cc', packages=None, active=0) diff --git a/trove/datastore/models.py b/trove/datastore/models.py index 57369962d6..22958340ee 100644 --- a/trove/datastore/models.py +++ b/trove/datastore/models.py @@ -21,8 +21,10 @@ from trove.common import exception from trove.common import utils from trove.db import models as dbmodels from trove.db import get_db_api +from trove.openstack.common import log as logging +LOG = logging.getLogger(__name__) CONF = cfg.CONF db_api = get_db_api() @@ -36,13 +38,13 @@ def persisted_models(): class DBDatastore(dbmodels.DatabaseModelBase): - _data_fields = ['id', 'name', 'manager', 'default_version_id'] + _data_fields = ['id', 'name', 'default_version_id'] class DBDatastoreVersion(dbmodels.DatabaseModelBase): - _data_fields = ['id', 'datastore_id', 'name', 'image_id', 'packages', - 'active'] + _data_fields = ['id', 'datastore_id', 'name', 'manager', 'image_id', + 'packages', 'active'] class Datastore(object): @@ -68,10 +70,6 @@ class Datastore(object): def name(self): return self.db_info.name - @property - def manager(self): - return self.db_info.manager - @property def default_version_id(self): return self.db_info.default_version_id @@ -130,6 +128,10 @@ class DatastoreVersion(object): def active(self): return self.db_info.active + @property + def manager(self): + return self.db_info.manager + class DatastoreVersions(object): @@ -166,7 +168,7 @@ def get_datastore_version(type=None, version=None): return (datastore, datastore_version) -def update_datastore(name, manager, default_version): +def update_datastore(name, default_version): db_api.configure_db(CONF) if default_version: version = DatastoreVersion.load(default_version) @@ -180,13 +182,13 @@ def update_datastore(name, manager, default_version): datastore = DBDatastore() datastore.id = utils.generate_uuid() datastore.name = name - datastore.manager = manager if default_version: datastore.default_version_id = version.id db_api.save(datastore) -def update_datastore_version(datastore, name, image_id, packages, active): +def update_datastore_version(datastore, name, manager, image_id, packages, + active): db_api.configure_db(CONF) datastore = Datastore.load(datastore) try: @@ -197,6 +199,7 @@ def update_datastore_version(datastore, name, image_id, packages, active): version.id = utils.generate_uuid() version.name = name version.datastore_id = datastore.id + version.manager = manager version.image_id = image_id version.packages = packages version.active = active diff --git a/trove/db/sqlalchemy/migrate_repo/versions/017_update_datastores.py b/trove/db/sqlalchemy/migrate_repo/versions/017_update_datastores.py new file mode 100644 index 0000000000..a043b29018 --- /dev/null +++ b/trove/db/sqlalchemy/migrate_repo/versions/017_update_datastores.py @@ -0,0 +1,63 @@ +# Copyright 2012 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy.schema import Column +from sqlalchemy.schema import MetaData +from sqlalchemy.sql.expression import select + +from trove.db.sqlalchemy.migrate_repo.schema import String +from trove.db.sqlalchemy.migrate_repo.schema import Table + + +def migrate_datastore_manager(datastores, datastore_versions): + versions = select([datastore_versions]).execute() + for ds_v in versions: + ds = select([datastores]).\ + where(datastores.c.id == ds_v.datastore_id).\ + execute().fetchone() + datastore_versions.update().\ + where(datastore_versions.c.id == ds_v.id).\ + values(manager=ds.manager).\ + execute() + + +def upgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + datastores = Table('datastores', meta, autoload=True) + datastore_versions = Table('datastore_versions', meta, autoload=True) + + # add column to datastore_versions + manager = Column('manager', String(255)) + datastore_versions.create_column(manager) + migrate_datastore_manager(datastores, datastore_versions) + + # drop column from datastores + datastores.drop_column('manager') + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + datastores = Table('datastores', meta, autoload=True) + datastore_versions = Table('datastore_versions', meta, autoload=True) + + # drop column from datastore_versions + datastore_versions.drop_column('manager') + + # add column to datastores + manager = Column('manager', String(255)) + datastores.create_column(manager) diff --git a/trove/extensions/mgmt/instances/models.py b/trove/extensions/mgmt/instances/models.py index 9d056dcc59..e45290ffcb 100644 --- a/trove/extensions/mgmt/instances/models.py +++ b/trove/extensions/mgmt/instances/models.py @@ -207,7 +207,7 @@ class NotificationTransformer(object): 'tenant_id': instance.tenant_id } payload['service_id'] = self._get_service_id( - instance.datastore.manager, CONF.notification_service_id) + instance.datastore_version.manager, CONF.notification_service_id) return payload def __call__(self): @@ -250,7 +250,8 @@ class NovaNotificationTransformer(NotificationTransformer): instances): message = { 'instance_type': self._lookup_flavor(instance.flavor_id), - 'user_id': instance.server.user_id} + 'user_id': instance.server.user_id + } message.update(self.transform_instance(instance, audit_start, audit_end)) diff --git a/trove/instance/models.py b/trove/instance/models.py index 3dc660034a..30127ff3a2 100644 --- a/trove/instance/models.py +++ b/trove/instance/models.py @@ -509,7 +509,7 @@ class Instance(BuiltInstance): task_api.API(context).create_instance(db_info.id, name, flavor, image_id, databases, users, - datastore.manager, + datastore_version.manager, datastore_version.packages, volume_size, backup_id, availability_zone, diff --git a/trove/taskmanager/api.py b/trove/taskmanager/api.py index aa9fd0cb94..b8cf8e0bfc 100644 --- a/trove/taskmanager/api.py +++ b/trove/taskmanager/api.py @@ -111,7 +111,8 @@ class API(proxy.RpcProxy): image_id=image_id, databases=databases, users=users, - datastore_manager=datastore_manager, + datastore_manager= + datastore_manager, packages=packages, volume_size=volume_size, backup_id=backup_id, diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index aafeabadbb..063aa091d5 100644 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -117,7 +117,7 @@ class NotifyMixin(object): }) payload['service_id'] = self._get_service_id( - self.datastore.manager, CONF.notification_service_id) + self.datastore_version.manager, CONF.notification_service_id) # Update payload with all other kwargs payload.update(kwargs) @@ -1015,8 +1015,11 @@ class ResizeAction(ResizeActionBase): % self.instance.id) LOG.debug(_("Repairing config.")) try: - config = self._render_config(self.instance.datastore.manager, - self.old_flavor, self.instance.id) + config = self._render_config( + self.instance.datastore_version.manager, + self.old_flavor, + self.instance.id + ) config = {'config_contents': config.config_contents} self.instance.guest.reset_configuration(config) except GuestTimeout: @@ -1036,7 +1039,7 @@ class ResizeAction(ResizeActionBase): modify_at=timeutils.isotime(self.instance.updated)) def _start_mysql(self): - config = self._render_config(self.instance.datastore.manager, + config = self._render_config(self.instance.datastore_version.manager, self.new_flavor, self.instance.id) self.instance.guest.start_db_with_conf_changes(config.config_contents) diff --git a/trove/tests/unittests/mgmt/test_models.py b/trove/tests/unittests/mgmt/test_models.py index 7d129bd735..bda76d0eda 100644 --- a/trove/tests/unittests/mgmt/test_models.py +++ b/trove/tests/unittests/mgmt/test_models.py @@ -81,10 +81,19 @@ class TestNotificationTransformer(MockMgmtInstanceTest): when(DatabaseModelBase).find_all(deleted=False).thenReturn( [db_instance]) - stub_datastore = mock() - stub_datastore.datastore_id = "stub" - stub_datastore.manager = "mysql" - when(DatabaseModelBase).find_by(id=any()).thenReturn(stub_datastore) + stub_dsv_db_info = mock(datastore_models.DBDatastoreVersion) + stub_dsv_db_info.id = "test_datastore_version" + stub_dsv_db_info.datastore_id = "mysql_test_version" + stub_dsv_db_info.name = "test_datastore_name" + stub_dsv_db_info.image_id = "test_datastore_image_id" + stub_dsv_db_info.packages = "test_datastore_pacakges" + stub_dsv_db_info.active = 1 + stub_dsv_db_info.manager = "mysql" + stub_datastore_version = datastore_models.DatastoreVersion( + stub_dsv_db_info) + when(DatabaseModelBase).find_by(id=any()).thenReturn( + stub_datastore_version) + when(DatabaseModelBase).find_by(instance_id='1').thenReturn( InstanceServiceStatus(rd_instance.ServiceStatuses.BUILDING)) @@ -141,6 +150,19 @@ class TestNovaNotificationTransformer(MockMgmtInstanceTest): db_instance = MockMgmtInstanceTest.build_db_instance( status, task_status=InstanceTasks.BUILDING) + stub_dsv_db_info = mock(datastore_models.DBDatastoreVersion) + stub_dsv_db_info.id = "test_datastore_version" + stub_dsv_db_info.datastore_id = "mysql_test_version" + stub_dsv_db_info.name = "test_datastore_name" + stub_dsv_db_info.image_id = "test_datastore_image_id" + stub_dsv_db_info.packages = "test_datastore_pacakges" + stub_dsv_db_info.active = 1 + stub_dsv_db_info.manager = "mysql" + stub_datastore_version = datastore_models.DatastoreVersion( + stub_dsv_db_info) + when(DatabaseModelBase).find_by(id=any()).thenReturn( + stub_datastore_version) + server = mock(Server) server.user_id = 'test_user_id' mgmt_instance = mgmtmodels.SimpleMgmtInstance(self.context, @@ -179,8 +201,14 @@ class TestNovaNotificationTransformer(MockMgmtInstanceTest): server = mock(Server) server.user_id = 'test_user_id' + stub_datastore_version = mock() + stub_datastore_version.id = "stub_datastore_version" + stub_datastore_version.manager = "m0ng0" + when(datastore_models. + DatastoreVersion).load(any()).thenReturn(stub_datastore_version) + stub_datastore = mock() - stub_datastore.manager = "m0ng0" + stub_datastore.default_datastore_version = "stub_datastore_version" when(datastore_models. Datastore).load(any()).thenReturn(stub_datastore) mgmt_instance = mgmtmodels.SimpleMgmtInstance(self.context,