# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # 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. """ Implementation of SQLAlchemy backend """ import sys from glance.common import db from glance.common import exception from glance.common import flags from glance.common.db.sqlalchemy.session import get_session from glance.registry.db.sqlalchemy import models from sqlalchemy.orm import exc #from sqlalchemy.orm import joinedload_all # TODO(sirp): add back eager loading from sqlalchemy.orm import joinedload from sqlalchemy.sql import func FLAGS = flags.FLAGS # NOTE(vish): disabling docstring pylint because the docstrings are # in the interface definition # pylint: disable-msg=C0111 def _deleted(context): """Calculates whether to include deleted objects based on context. Currently just looks for a flag called deleted in the context dict. """ if not hasattr(context, 'get'): return False return context.get('deleted', False) ################### def image_create(_context, values): return _image_update(_context, values, None) def image_destroy(_context, image_id): session = get_session() with session.begin(): image_ref = models.Image.find(image_id, session=session) image_ref.delete(session=session) def image_get(context, image_id): session = get_session() try: return session.query(models.Image ).options(joinedload(models.Image.properties) ).filter_by(deleted=_deleted(context) ).filter_by(id=image_id ).one() except exc.NoResultFound: new_exc = exception.NotFound("No model for id %s" % image_id) raise new_exc.__class__, new_exc, sys.exc_info()[2] def image_get_all(context): session = get_session() return session.query(models.Image ).options(joinedload(models.Image.properties) ).filter_by(deleted=_deleted(context) ).all() def image_get_all_public(context, public): session = get_session() return session.query(models.Image ).options(joinedload(models.Image.properties) ).filter_by(deleted=_deleted(context) ).filter_by(is_public=public ).all() def image_get_by_str(context, str_id): return models.Image.find_by_str(str_id, deleted=_deleted(context)) def image_update(_context, image_id, values): return _image_update(_context, values, image_id) ################### def image_property_create(_context, values): _drop_protected_attrs(models.Image, values) image_property_ref = models.ImageProperty() image_property_ref.update(values) image_property_ref.save() return image_property_ref def _drop_protected_attrs(model_class, values): """Removed protected attributes from values dictionary using the models __protected_attributes__ field. """ for attr in model_class.__protected_attributes__: if attr in values: del values[attr] def _image_update(_context, values, image_id): """Used internally by image_create and image_update :param image_id: If None, create the image, otherwise, find and update it """ session = get_session() with session.begin(): _drop_protected_attrs(models.Image, values) values['size'] = int(values['size']) values['is_public'] = bool(values.get('is_public', False)) properties = values.pop('properties', {}) if image_id: image_ref = models.Image.find(image_id, session=session) else: image_ref = models.Image() image_ref.update(values) image_ref.save(session=session) for key, value in properties.iteritems(): prop_values = {'image_id': image_ref.id, 'key': key, 'value': value} image_property_create(_context, prop_values) return image_get(_context, image_ref.id)