trove/trove/common/models.py

132 lines
4.1 KiB
Python

# Copyright 2010-2011 OpenStack Foundation
# 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.
"""Model classes that form the core of instances functionality."""
from oslo_utils.importutils import import_class
from trove.common import cfg
from trove.common import clients
from trove.common.i18n import _
CONF = cfg.CONF
class ModelBase(object):
"""
An object which can be stored in the database.
"""
_data_fields = []
_auto_generated_attrs = []
def _validate(self, errors):
"""Subclasses override this to offer additional validation.
For each validation error a key with the field name and an error
message is added to the dict.
"""
pass
def data(self, **options):
"""Called to serialize object to a dictionary."""
data_fields = self._data_fields + self._auto_generated_attrs
return {field: self[field] for field in data_fields}
def is_valid(self):
"""Called when persisting data to ensure the format is correct."""
self.errors = {}
self._validate(self.errors)
# self._validate_columns_type()
# self._before_validate()
# self._validate()
return self.errors == {}
def __setitem__(self, key, value):
"""Overloaded to cause this object to look like a data entity."""
setattr(self, key, value)
def __getitem__(self, key):
"""Overloaded to cause this object to look like a data entity."""
return getattr(self, key)
def __eq__(self, other):
"""Overloaded to cause this object to look like a data entity."""
if not hasattr(other, 'id'):
return False
return type(other) == type(self) and other.id == self.id
def __ne__(self, other):
"""Overloaded to cause this object to look like a data entity."""
return not self == other
def __hash__(self):
"""Overloaded to cause this object to look like a data entity."""
return self.id.__hash__()
class RemoteModelBase(ModelBase):
# This should be set by the remote model during init time
# The data() method will be using this
_data_object = None
def _data_item(self, data_object):
data_fields = self._data_fields + self._auto_generated_attrs
return {field: getattr(data_object, field) for field in data_fields}
# data magic that will allow for a list of _data_object or a single item
# if the object is a list, it will turn it into a list of hash's again
def data(self, **options):
if self._data_object is None:
raise LookupError(_("data object is None"))
if isinstance(self._data_object, list):
return [self._data_item(item) for item in self._data_object]
else:
return self._data_item(self._data_object)
class NetworkRemoteModelBase(RemoteModelBase):
network_driver = None
@classmethod
def get_driver(cls, context, region_name):
if not cls.network_driver:
cls.network_driver = import_class(CONF.network_driver)
return cls.network_driver(context, region_name)
class NovaRemoteModelBase(RemoteModelBase):
@classmethod
def get_client(cls, context, region_name):
return clients.create_nova_client(context, region_name)
class SwiftRemoteModelBase(RemoteModelBase):
@classmethod
def get_client(cls, context, region_name):
return clients.create_swift_client(context, region_name)
class CinderRemoteModelBase(RemoteModelBase):
@classmethod
def get_client(cls, context):
return clients.create_cinder_client(context)