Merge "Add CellMapping object"

This commit is contained in:
Jenkins 2015-03-19 07:25:52 +00:00 committed by Gerrit Code Review
commit b9beb69b27
6 changed files with 282 additions and 0 deletions

View File

@ -1857,3 +1857,7 @@ class ImageCPUPinningForbidden(Forbidden):
class UnsupportedPolicyException(Invalid):
msg_fmt = _("ServerGroup policy is not supported: %(reason)s")
class CellMappingNotFound(NotFound):
msg_fmt = _("Cell %(uuid)s has no mapping.")

View File

@ -28,6 +28,7 @@ def register_all():
__import__('nova.objects.aggregate')
__import__('nova.objects.bandwidth_usage')
__import__('nova.objects.block_device')
__import__('nova.objects.cell_mapping')
__import__('nova.objects.compute_node')
__import__('nova.objects.dns_domain')
__import__('nova.objects.ec2')

View File

@ -0,0 +1,105 @@
# 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 nova.db.sqlalchemy import api as db_api
from nova.db.sqlalchemy import api_models
from nova import exception
from nova.objects import base
from nova.objects import fields
class CellMapping(base.NovaTimestampObject, base.NovaObject):
# Version 1.0: Initial version
VERSION = '1.0'
fields = {
'id': fields.IntegerField(read_only=True),
'uuid': fields.UUIDField(),
'name': fields.StringField(nullable=True),
'transport_url': fields.StringField(),
'database_connection': fields.StringField(),
}
@staticmethod
def _from_db_object(context, cell_mapping, db_cell_mapping):
for key in cell_mapping.fields:
setattr(cell_mapping, key, db_cell_mapping[key])
cell_mapping.obj_reset_changes()
cell_mapping._context = context
return cell_mapping
@staticmethod
def _get_by_uuid_from_db(context, uuid):
session = db_api.get_api_session()
with session.begin():
db_mapping = session.query(api_models.CellMapping).filter_by(
uuid=uuid).first()
if not db_mapping:
raise exception.CellMappingNotFound(uuid=uuid)
return db_mapping
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid):
db_mapping = cls._get_by_uuid_from_db(context, uuid)
return cls._from_db_object(context, cls(), db_mapping)
@staticmethod
def _create_in_db(context, updates):
session = db_api.get_api_session()
db_mapping = api_models.CellMapping()
db_mapping.update(updates)
db_mapping.save(session)
return db_mapping
@base.remotable
def create(self):
db_mapping = self._create_in_db(self._context, self.obj_get_changes())
self._from_db_object(self._context, self, db_mapping)
@staticmethod
def _save_in_db(context, uuid, updates):
session = db_api.get_api_session()
with session.begin():
db_mapping = session.query(
api_models.CellMapping).filter_by(uuid=uuid).first()
if not db_mapping:
raise exception.CellMappingNotFound(uuid=uuid)
db_mapping.update(updates)
session.add(db_mapping)
return db_mapping
@base.remotable
def save(self):
changes = self.obj_get_changes()
db_mapping = self._save_in_db(self._context, self.uuid, changes)
self._from_db_object(self._context, self, db_mapping)
self.obj_reset_changes()
@staticmethod
def _destroy_in_db(context, uuid):
session = db_api.get_api_session()
with session.begin():
result = session.query(api_models.CellMapping).filter_by(
uuid=uuid).delete()
if not result:
raise exception.CellMappingNotFound(uuid=uuid)
@base.remotable
def destroy(self):
self._destroy_in_db(self._context, self.uuid)

View File

@ -0,0 +1,74 @@
# 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 oslo_utils import uuidutils
from nova import context
from nova import exception
from nova.objects import cell_mapping
from nova import test
from nova.tests import fixtures
class CellMappingTestCase(test.NoDBTestCase):
def setUp(self):
super(CellMappingTestCase, self).setUp()
self.useFixture(fixtures.Database(database='api'))
self.context = context.RequestContext('fake-user', 'fake-project')
self.mapping_obj = cell_mapping.CellMapping()
self.uuid = uuidutils.generate_uuid()
sample_mapping = {'uuid': '',
'name': 'fake-cell',
'transport_url': 'rabbit:///',
'database_connection': 'mysql:///'}
def _create_mapping(self, **kwargs):
args = self.sample_mapping.copy()
if 'uuid' not in kwargs:
args['uuid'] = self.uuid
args.update(kwargs)
return self.mapping_obj._create_in_db(self.context, args)
def test_get_by_uuid(self):
mapping = self._create_mapping()
db_mapping = self.mapping_obj._get_by_uuid_from_db(self.context,
mapping['uuid'])
for key in self.mapping_obj.fields.keys():
self.assertEqual(db_mapping[key], mapping[key])
def test_get_by_uuid_not_found(self):
self.assertRaises(exception.CellMappingNotFound,
self.mapping_obj._get_by_uuid_from_db, self.context, self.uuid)
def test_save_in_db(self):
mapping = self._create_mapping()
self.mapping_obj._save_in_db(self.context, mapping['uuid'],
{'name': 'meow'})
db_mapping = self.mapping_obj._get_by_uuid_from_db(self.context,
mapping['uuid'])
self.assertNotEqual(db_mapping['name'], mapping['name'])
for key in [key for key in self.mapping_obj.fields.keys()
if key not in ['name', 'updated_at']]:
self.assertEqual(db_mapping[key], mapping[key])
def test_destroy_in_db(self):
mapping = self._create_mapping()
self.mapping_obj._get_by_uuid_from_db(self.context, mapping['uuid'])
self.mapping_obj._destroy_in_db(self.context, mapping['uuid'])
self.assertRaises(exception.CellMappingNotFound,
self.mapping_obj._get_by_uuid_from_db, self.context,
mapping['uuid'])
def test_destroy_in_db_not_found(self):
self.assertRaises(exception.CellMappingNotFound,
self.mapping_obj._destroy_in_db, self.context, self.uuid)

View File

@ -0,0 +1,97 @@
# 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.
import mock
from oslo_utils import uuidutils
from nova import objects
from nova.objects import cell_mapping
from nova.tests.unit.objects import test_objects
def get_db_mapping(**updates):
db_mapping = {
'id': 1,
'uuid': uuidutils.generate_uuid(),
'name': 'cell1',
'transport_url': 'rabbit://',
'database_connection': 'sqlite:///',
'created_at': None,
'updated_at': None,
}
db_mapping.update(updates)
return db_mapping
class _TestCellMappingObject(object):
@mock.patch.object(cell_mapping.CellMapping, '_get_by_uuid_from_db')
def test_get_by_uuid(self, uuid_from_db):
db_mapping = get_db_mapping()
uuid_from_db.return_value = db_mapping
mapping_obj = objects.CellMapping().get_by_uuid(self.context,
db_mapping['uuid'])
uuid_from_db.assert_called_once_with(self.context, db_mapping['uuid'])
self.compare_obj(mapping_obj, db_mapping)
@mock.patch.object(cell_mapping.CellMapping, '_create_in_db')
def test_create(self, create_in_db):
uuid = uuidutils.generate_uuid()
db_mapping = get_db_mapping(uuid=uuid, name='test',
database_connection='mysql:///')
create_in_db.return_value = db_mapping
mapping_obj = objects.CellMapping(self.context)
mapping_obj.uuid = uuid
mapping_obj.name = 'test'
mapping_obj.database_connection = 'mysql:///'
mapping_obj.create()
create_in_db.assert_called_once_with(self.context,
{'uuid': uuid,
'name': 'test',
'database_connection': 'mysql:///'})
self.compare_obj(mapping_obj, db_mapping)
@mock.patch.object(cell_mapping.CellMapping, '_save_in_db')
def test_save(self, save_in_db):
uuid = uuidutils.generate_uuid()
db_mapping = get_db_mapping(database_connection='mysql:///')
save_in_db.return_value = db_mapping
mapping_obj = objects.CellMapping(self.context)
mapping_obj.uuid = uuid
mapping_obj.database_connection = 'mysql:///'
mapping_obj.save()
save_in_db.assert_called_once_with(self.context, uuid,
{'uuid': uuid,
'database_connection': 'mysql:///'})
self.compare_obj(mapping_obj, db_mapping)
@mock.patch.object(cell_mapping.CellMapping, '_destroy_in_db')
def test_destroy(self, destroy_in_db):
uuid = uuidutils.generate_uuid()
mapping_obj = objects.CellMapping(self.context)
mapping_obj.uuid = uuid
mapping_obj.destroy()
destroy_in_db.assert_called_once_with(self.context, uuid)
class TestCellMappingObject(test_objects._LocalTest,
_TestCellMappingObject):
pass
class TestRemoteCellMappingObject(test_objects._RemoteTest,
_TestCellMappingObject):
pass

View File

@ -1183,6 +1183,7 @@ object_data = {
'BandwidthUsageList': '1.2-5b564cbfd5ae6e106443c086938e7602',
'BlockDeviceMapping': '1.8-c87e9c7e5cfd6a402f32727aa74aca95',
'BlockDeviceMappingList': '1.9-0faaeebdca213010c791bc37a22546e3',
'CellMapping': '1.0-4b1616970814c3c819e10c7ef6b9c3d5',
'ComputeNode': '1.10-5f8cd6948ad98fcc0c39b79d49acc4b6',
'ComputeNodeList': '1.10-4ae1f844c247029fbcdb5fdccbe9e619',
'DNSDomain': '1.0-5bdc288d7c3b723ce86ede998fd5c9ba',