trove/reddwarf/database/models.py
2012-03-07 14:08:42 -06:00

208 lines
6.1 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010-2011 OpenStack LLC.
# 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."""
import logging
import netaddr
from reddwarf import db
from reddwarf.common import config
from reddwarf.common import exception
from reddwarf.common import utils
from novaclient.v1_1.client import Client
CONFIG = config.Config
LOG = logging.getLogger('reddwarf.database.models')
PROXY_ADMIN_USER = CONFIG.get('reddwarf_proxy_admin_user', 'admin')
PROXY_ADMIN_PASS = CONFIG.get('reddwarf_proxy_admin_pass',
'3de4922d8b6ac5a1aad9')
PROXY_ADMIN_TENANT_NAME = CONFIG.get('reddwarf_proxy_admin_tenant_name',
'admin')
PROXY_AUTH_URL = CONFIG.get('reddwarf_auth_url', 'http://0.0.0.0:5000/v2.0')
PROXY_TENANT_ID = CONFIG.get('reddwarf_tenant_id',
'f5f71240a97c411e977452370422d7cc')
class ModelBase(object):
_data_fields = []
_auto_generated_attrs = []
def _validate(self):
pass
def data(self, **options):
data_fields = self._data_fields + self._auto_generated_attrs
return dict([(field, self[field]) for field in data_fields])
def is_valid(self):
self.errors = {}
# self._validate_columns_type()
# self._before_validate()
# self._validate()
return self.errors == {}
def __setitem__(self, key, value):
setattr(self, key, value)
def __getitem__(self, key):
return getattr(self, key)
def __eq__(self, other):
if not hasattr(other, 'id'):
return False
return type(other) == type(self) and other.id == self.id
def __ne__(self, other):
return not self == other
def __hash__(self):
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
@classmethod
def get_client(cls, proxy_token):
client = Client(PROXY_ADMIN_USER, PROXY_ADMIN_PASS,
PROXY_ADMIN_TENANT_NAME, PROXY_AUTH_URL,
proxy_tenant_id=PROXY_TENANT_ID,
proxy_token=proxy_token,
region_name='RegionOne',
service_type='compute',
service_name="'Compute Service'")
client.authenticate()
return client
def data_item(self, data_object):
data_fields = self._data_fields + self._auto_generated_attrs
return dict([(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 Instance(RemoteModelBase):
_data_fields = ['name', 'status', 'updated', 'id', 'flavor']
def __init__(self, proxy_token, uuid):
self._data_object = self.get_client(proxy_token).servers.get(uuid)
@classmethod
def delete(cls, proxy_token, uuid):
return cls.get_client(proxy_token).servers.delete(uuid)
class Instances(Instance):
def __init__(self, proxy_token):
self._data_object = self.get_client(proxy_token).servers.list()
def __iter__(self):
for item in self._data_object:
yield item
class DatabaseModelBase(ModelBase):
_auto_generated_attrs = ['id']
@classmethod
def create(cls, **values):
values['id'] = utils.generate_uuid()
print values
# values['created_at'] = utils.utcnow()
instance = cls(**values).save()
# instance._notify_fields("create")
return instance
def save(self):
if not self.is_valid():
raise InvalidModelError(self.errors)
# self._convert_columns_to_proper_type()
# self._before_save()
self['updated_at'] = utils.utcnow()
LOG.debug("Saving %s: %s" % (self.__class__.__name__, self.__dict__))
return db.db_api.save(self)
def __init__(self, **kwargs):
self.merge_attributes(kwargs)
def merge_attributes(self, values):
"""dict.update() behaviour."""
for k, v in values.iteritems():
self[k] = v
@classmethod
def find_by(cls, **conditions):
model = cls.get_by(**conditions)
if model == None:
raise ModelNotFoundError(_("%s Not Found") % cls.__name__)
return model
@classmethod
def get_by(cls, **kwargs):
return db.db_api.find_by(cls, **cls._process_conditions(kwargs))
@classmethod
def _process_conditions(cls, raw_conditions):
"""Override in inheritors to format/modify any conditions."""
return raw_conditions
class DBInstance(DatabaseModelBase):
_data_fields = ['name', 'status']
class ServiceImage(DatabaseModelBase):
_data_fields = ['service_name', 'image_id']
def persisted_models():
return {
'instance': DBInstance,
'service_image': ServiceImage,
}
class InvalidModelError(exception.ReddwarfError):
message = _("The following values are invalid: %(errors)s")
def __init__(self, errors, message=None):
super(InvalidModelError, self).__init__(message, errors=errors)
class ModelNotFoundError(exception.ReddwarfError):
message = _("Not Found")