From 9a5d82bf90d07f60a2e3edf737b65a7b1aad10bf Mon Sep 17 00:00:00 2001 From: Tim Simpson Date: Mon, 19 Nov 2012 09:18:55 -0600 Subject: [PATCH] No longer import db_api while parsing db __init__. The db_api field of reddwarf/db/__init__.py was grabbed by importing a module using utils.import_object. The imported module was always the sqlalchemy api module, which is nested under the file that imports it, which caused import errors in multiple contexts. This commit changes every use of db_api to call a function to load it first, which seems to fix these problems. Change-Id: I9515efe02831b521d7f14674e0a2913e476b207d Fixes: bug #1080706 --- bin/reddwarf-api | 4 ++-- bin/reddwarf-guestagent | 4 ++-- bin/reddwarf-manage | 17 +++++++++-------- bin/reddwarf-mgmt-taskmanager | 4 ++-- bin/reddwarf-server | 4 ++-- bin/reddwarf-taskmanager | 4 ++-- reddwarf/db/__init__.py | 27 +++++++++++++++++---------- reddwarf/db/models.py | 15 ++++++++++----- reddwarf/extensions/mysql/models.py | 7 +++---- reddwarf/openstack/common/utils.py | 10 +++++++--- run_tests.py | 6 ++++-- 11 files changed, 60 insertions(+), 42 deletions(-) diff --git a/bin/reddwarf-api b/bin/reddwarf-api index 118cfb3897..ec67dd58c8 100755 --- a/bin/reddwarf-api +++ b/bin/reddwarf-api @@ -36,7 +36,7 @@ if os.path.exists(os.path.join(possible_topdir, 'reddwarf', '__init__.py')): from reddwarf import version from reddwarf.common import config from reddwarf.common import wsgi -from reddwarf.db import db_api +from reddwarf.db import get_db_api def create_options(parser): @@ -62,7 +62,7 @@ if __name__ == '__main__': try: config.Config.load_paste_config('reddwarf', options, args) conf, app = config.Config.load_paste_app('reddwarf', options, args) - db_api.configure_db(conf) + get_db_api().configure_db(conf) server = wsgi.Server() server.start(app, int(options.get('port') or conf['bind_port']), conf['bind_host']) diff --git a/bin/reddwarf-guestagent b/bin/reddwarf-guestagent index 72d90c7581..8b827e37fd 100755 --- a/bin/reddwarf-guestagent +++ b/bin/reddwarf-guestagent @@ -40,7 +40,7 @@ from reddwarf import version from reddwarf.common import config from reddwarf.common import service # TODO(hub-cap): find out why the db api isint being imported properly -from reddwarf.db import db_api +from reddwarf.db import get_db_api if __name__ == '__main__': @@ -61,7 +61,7 @@ if __name__ == '__main__': # that is injected into the VM config.Config.append_to_config_values('reddwarf-guestagent', {'config_file': '/etc/guest_info'}, None) - db_api.configure_db(conf) + get_db_api().configure_db(conf) server = service.Service.create(binary='reddwarf-guestagent', host=config.Config.get('guest_id')) service.serve(server) diff --git a/bin/reddwarf-manage b/bin/reddwarf-manage index 319fe3a1b7..b435ee776d 100755 --- a/bin/reddwarf-manage +++ b/bin/reddwarf-manage @@ -36,7 +36,7 @@ if os.path.exists(os.path.join(possible_topdir, 'reddwarf', '__init__.py')): from reddwarf import version from reddwarf.common import config from reddwarf.common import utils -from reddwarf.db import db_api +from reddwarf.db import get_db_api from reddwarf.instance import models as instance_models @@ -57,24 +57,25 @@ def create_options(parser): class Commands(object): def __init__(self, conf): + self.db_api = get_db_api() self.conf = conf def db_sync(self): - db_api.db_sync(self.conf, repo_path=None) + self.db_api.db_sync(self.conf, repo_path=None) def db_upgrade(self, version=None, repo_path=None): - db_api.db_upgrade(self.conf, version, repo_path=None) + self.db_api.db_upgrade(self.conf, version, repo_path=None) def db_downgrade(self, version, repo_path=None): - db_api.db_downgrade(self.conf, version, repo_path=None) + self.db_api.db_downgrade(self.conf, version, repo_path=None) def execute(self, command_name, *args): if self.has(command_name): return getattr(self, command_name)(*args) def image_update(self, service_name, image_id): - db_api.configure_db(self.conf) - image = db_api.find_by(instance_models.ServiceImage, + self.db_api.configure_db(self.conf) + image = self.db_api.find_by(instance_models.ServiceImage, service_name=service_name) if image is None: # Create a new one @@ -82,13 +83,13 @@ class Commands(object): image.id = utils.generate_uuid() image.service_name = service_name image.image_id = image_id - db_api.save(image) + self.db_api.save(image) def db_wipe(self, repo_path, service_name, image_id): """Drops the database and recreates it.""" from reddwarf.instance import models from reddwarf.db.sqlalchemy import session - db_api.drop_db(self.conf) + self.db_api.drop_db(self.conf) self.db_sync() # Sets up database engine, so the next line will work... session.configure_db(self.conf) diff --git a/bin/reddwarf-mgmt-taskmanager b/bin/reddwarf-mgmt-taskmanager index a3145a96a4..a557227bc9 100644 --- a/bin/reddwarf-mgmt-taskmanager +++ b/bin/reddwarf-mgmt-taskmanager @@ -39,7 +39,7 @@ if os.path.exists(os.path.join(possible_topdir, 'reddwarf', '__init__.py')): from reddwarf import version from reddwarf.common import config from reddwarf.common import service -from reddwarf.db import db_api +from reddwarf.db import get_db_api if __name__ == '__main__': @@ -52,7 +52,7 @@ if __name__ == '__main__': try: conf, app = config.Config.load_paste_app('reddwarf-taskmanager', options, args) - db_api.configure_db(conf) + get_db_api().configure_db(conf) server = service.Service.create(binary='reddwarf-taskmanager', manager='reddwarf.taskmanager.manager.TaskManager', diff --git a/bin/reddwarf-server b/bin/reddwarf-server index 4480f24998..4072c26c93 100755 --- a/bin/reddwarf-server +++ b/bin/reddwarf-server @@ -36,7 +36,7 @@ if os.path.exists(os.path.join(possible_topdir, 'reddwarf', '__init__.py')): from reddwarf import version from reddwarf.common import config from reddwarf.common import wsgi -from reddwarf.db import db_api +from reddwarf.db import get_db_api def create_options(parser): @@ -75,7 +75,7 @@ if __name__ == '__main__': (options, args) = config.parse_options(oparser) config.Config.load_paste_config('reddwarf', options, args) conf, app = config.Config.load_paste_app('reddwarf', options, args) - db_api.configure_db(conf) + get_db_api().configure_db(conf) port = int(options.get('port') or conf['bind_port']) if options['fork']: pid = os.fork() diff --git a/bin/reddwarf-taskmanager b/bin/reddwarf-taskmanager index 04f11b60bd..42bec9d91a 100755 --- a/bin/reddwarf-taskmanager +++ b/bin/reddwarf-taskmanager @@ -39,7 +39,7 @@ if os.path.exists(os.path.join(possible_topdir, 'reddwarf', '__init__.py')): from reddwarf import version from reddwarf.common import config from reddwarf.common import service -from reddwarf.db import db_api +from reddwarf.db import get_db_api if __name__ == '__main__': @@ -52,7 +52,7 @@ if __name__ == '__main__': try: conf, app = config.Config.load_paste_app('reddwarf-taskmanager', options, args) - db_api.configure_db(conf) + get_db_api().configure_db(conf) server = service.Service.create(binary='reddwarf-taskmanager') service.serve(server) service.wait() diff --git a/reddwarf/db/__init__.py b/reddwarf/db/__init__.py index b928f9305b..4611714589 100644 --- a/reddwarf/db/__init__.py +++ b/reddwarf/db/__init__.py @@ -21,9 +21,12 @@ from reddwarf.common import utils from reddwarf.common import config -db_api = utils.import_object( - config.Config.get("db_api_implementation", - "reddwarf.db.sqlalchemy.api")) +db_api_opt = config.Config.get("db_api_implementation", + "reddwarf.db.sqlalchemy.api") + + +def get_db_api(): + return utils.import_object(db_api_opt) class Query(object): @@ -38,25 +41,29 @@ class Query(object): self._query_func = query_func self._model = model self._conditions = conditions + self.db_api = get_db_api() def all(self): - return db_api.list(self._query_func, self._model, **self._conditions) + return self.db_api.list(self._query_func, self._model, + **self._conditions) def count(self): - return db_api.count(self._query_func, self._model, **self._conditions) + return self.db_api.count(self._query_func, self._model, + **self._conditions) def __iter__(self): return iter(self.all()) def update(self, **values): - db_api.update_all(self._query_func, self._model, self._conditions, - values) + self.db_api.update_all(self._query_func, self._model, self._conditions, + values) def delete(self): - db_api.delete_all(self._query_func, self._model, **self._conditions) + self.db_api.delete_all(self._query_func, self._model, + **self._conditions) def limit(self, limit=200, marker=None, marker_column=None): - return db_api.find_all_by_limit( + return self.db_api.find_all_by_limit( self._query_func, self._model, self._conditions, @@ -75,7 +82,7 @@ class Queryable(object): def __getattr__(self, item): return lambda model, **conditions: Query( - model, query_func=getattr(db_api, item), **conditions) + model, query_func=getattr(get_db_api(), item), **conditions) db_query = Queryable() diff --git a/reddwarf/db/models.py b/reddwarf/db/models.py index ff4b5c34c5..2a26d300a2 100644 --- a/reddwarf/db/models.py +++ b/reddwarf/db/models.py @@ -14,7 +14,8 @@ import logging -from reddwarf import db +from reddwarf.db import get_db_api +from reddwarf.db import db_query from reddwarf.common import exception from reddwarf.common import models from reddwarf.common import pagination @@ -36,19 +37,23 @@ class DatabaseModelBase(models.ModelBase): raise exception.InvalidModelError(errors=instance.errors) return instance + @property + def db_api(self): + return get_db_api() + def save(self): if not self.is_valid(): raise exception.InvalidModelError(errors=self.errors) self['updated'] = utils.utcnow() LOG.debug(_("Saving %s: %s") % (self.__class__.__name__, self.__dict__)) - return db.db_api.save(self) + return self.db_api.save(self) def delete(self): self['updated'] = utils.utcnow() LOG.debug(_("Deleting %s: %s") % (self.__class__.__name__, self.__dict__)) - return db.db_api.delete(self) + return self.db_api.delete(self) def __init__(self, **kwargs): self.merge_attributes(kwargs) @@ -70,11 +75,11 @@ class DatabaseModelBase(models.ModelBase): @classmethod def get_by(cls, **kwargs): - return db.db_api.find_by(cls, **cls._process_conditions(kwargs)) + return get_db_api().find_by(cls, **cls._process_conditions(kwargs)) @classmethod def find_all(cls, **kwargs): - return db.db_query.find_all(cls, **cls._process_conditions(kwargs)) + return db_query.find_all(cls, **cls._process_conditions(kwargs)) @classmethod def _process_conditions(cls, raw_conditions): diff --git a/reddwarf/extensions/mysql/models.py b/reddwarf/extensions/mysql/models.py index 5e23957974..185f2b691e 100644 --- a/reddwarf/extensions/mysql/models.py +++ b/reddwarf/extensions/mysql/models.py @@ -21,11 +21,10 @@ Model classes that extend the instances functionality for MySQL instances. import logging -from reddwarf import db - from reddwarf.common import config from reddwarf.common import exception from reddwarf.common import utils +from reddwarf.db import get_db_api from reddwarf.instance import models as base_models from reddwarf.guestagent.db import models as guest_models from reddwarf.common.remote import create_guest_client @@ -121,11 +120,11 @@ class RootHistory(object): def save(self): LOG.debug(_("Saving %s: %s") % (self.__class__.__name__, self.__dict__)) - return db.db_api.save(self) + return get_db_api().save(self) @classmethod def load(cls, context, instance_id): - history = db.db_api.find_by(cls, id=instance_id) + history = get_db_api().find_by(cls, id=instance_id) return history @classmethod diff --git a/reddwarf/openstack/common/utils.py b/reddwarf/openstack/common/utils.py index 292dac3ff0..f383c6fadb 100644 --- a/reddwarf/openstack/common/utils.py +++ b/reddwarf/openstack/common/utils.py @@ -151,7 +151,8 @@ def import_class(import_str): __import__(mod_str) return getattr(sys.modules[mod_str], class_str) except (ImportError, ValueError, AttributeError): - raise exception.NotFound('Class %s cannot be found' % class_str) + raise exception.NotFound('Class from %s import %s cannot be found' + % (mod_str, class_str)) def import_object(import_str): @@ -159,8 +160,11 @@ def import_object(import_str): try: __import__(import_str) return sys.modules[import_str] - except ImportError: - return import_class(import_str) + except ImportError as ie: + try: + return import_class(import_str) + except exception.NotFound: + raise ie def isotime(at=None): diff --git a/run_tests.py b/run_tests.py index b438092d70..f6e90bdb16 100644 --- a/run_tests.py +++ b/run_tests.py @@ -30,11 +30,12 @@ def add_support_for_localization(): def initialize_reddwarf(config_file): # The test version of poll_until doesn't utilize LoopingCall. import optparse - from reddwarf.db import db_api + from reddwarf.db import get_db_api from reddwarf.common import config as rd_config from reddwarf.common import wsgi from reddwarf import version + db_api = get_db_api() def create_options(parser): parser.add_option('-p', '--port', dest="port", metavar="PORT", @@ -62,9 +63,10 @@ def initialize_reddwarf(config_file): def initialize_database(rd_conf): - from reddwarf.db import db_api + from reddwarf.db import get_db_api from reddwarf.instance import models from reddwarf.db.sqlalchemy import session + db_api = get_db_api() db_api.drop_db(rd_conf) # Destroys the database, if it exists. db_api.db_sync(rd_conf) session.configure_db(rd_conf)