Add Chassis object.

Implements blueprint: ironic-object-model

Change-Id: I0e59ee964072d3ae0889a58ec739bc485dee2a87
This commit is contained in:
Roman Prykhodchenko 2013-06-19 16:27:27 +03:00
parent 14dd6ff33f
commit 8b5a467a38
4 changed files with 204 additions and 1 deletions

View File

@ -314,6 +314,7 @@ class Connection(api.Connection):
if count != 1:
raise exception.PortNotFound(port=port)
@objects.objectify(objects.Chassis)
def get_chassis(self, chassis):
query = model_query(models.Chassis)
query = add_identity_filter(query, chassis)
@ -323,12 +324,14 @@ class Connection(api.Connection):
except NoResultFound:
raise exception.ChassisNotFound(chassis=chassis)
@objects.objectify(objects.Chassis)
def create_chassis(self, values):
chassis = models.Chassis()
chassis.update(values)
chassis.save()
return chassis
@objects.objectify(objects.Chassis)
def update_chassis(self, chassis, values):
session = get_session()
with session.begin():

View File

@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import functools
from ironic.objects import chassis
from ironic.objects import node
from ironic.objects import port
@ -19,6 +22,7 @@ from ironic.objects import port
def objectify(klass):
"""Decorator to convert database results into specified objects."""
def the_decorator(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
result = fn(*args, **kwargs)
try:
@ -30,9 +34,11 @@ def objectify(klass):
return wrapper
return the_decorator
Chassis = chassis.Chassis
Node = node.Node
Port = port.Port
__all__ = (Node,
__all__ = (Chassis,
Node,
Port,
objectify)

88
ironic/objects/chassis.py Normal file
View File

@ -0,0 +1,88 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# coding=utf-8
#
#
# 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 ironic.db import api as dbapi
from ironic.objects import base
from ironic.objects import utils
class Chassis(base.IronicObject):
dbapi = dbapi.get_instance()
fields = {
'id': int,
'uuid': utils.str_or_none,
'extra': utils.str_or_none,
}
@staticmethod
def _from_db_object(chassis, db_chassis):
"""Converts a database entity to a formal :class:`Chassis` object.
:param chassis: An object of :class:`Chassis`.
:param db_chassis: A DB model of a chassis.
:return: a :class:`Chassis` object.
"""
for field in chassis.fields:
chassis[field] = db_chassis[field]
chassis.obj_reset_changes()
return chassis
@base.remotable_classmethod
def get_by_uuid(cls, context, uuid=None):
"""Find a chassis based on uuid and return a :class:`Chassis` object.
:param uuid: the uuid of a chassis.
:returns: a :class:`Chassis` object.
"""
db_chassis = cls.dbapi.get_chassis(uuid)
return Chassis._from_db_object(cls(), db_chassis)
@base.remotable
def save(self, context):
"""Save updates to this Chassis.
Updates will be made column by column based on the result
of self.what_changed(). If expected_task_state is provided,
it will be checked against the in-database copy of the chassis
before updates are made.
:param context: Security context
"""
updates = {}
changes = self.obj_what_changed()
for field in changes:
updates[field] = self[field]
self.dbapi.update_chassis(self.uuid, updates)
self.obj_reset_changes()
@base.remotable
def refresh(self, context):
"""Loads and applies updates for this Chassis.
Loads a :class:`Chassis` with the same uuid from the database and
checks for updated attributes. Updates are applied from
the loaded chassis column by column, if there are any updates.
:param context: Security context
"""
current = self.__class__.get_by_uuid(context, uuid=self.uuid)
for field in self.fields:
if (hasattr(self, base.get_attrname(field)) and
self[field] != current[field]):
self[field] = current[field]

View File

@ -0,0 +1,106 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# coding=utf-8
#
#
# 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 ironic.common import context
from ironic.db import api as db_api
from ironic.db.sqlalchemy import models
from ironic import objects
from ironic.openstack.common import uuidutils
from ironic.tests.db import base
from ironic.tests.db import utils
class TestChassisObject(base.DbTestCase):
def setUp(self):
super(TestChassisObject, self).setUp()
self.fake_chassis = utils.get_test_chassis()
self.dbapi = db_api.get_instance()
self.ctxt = context.get_admin_context()
def test_load(self):
uuid = self.fake_chassis['uuid']
self.mox.StubOutWithMock(self.dbapi, 'get_chassis')
self.dbapi.get_chassis(uuid).AndReturn(self.fake_chassis)
self.mox.ReplayAll()
objects.Chassis.get_by_uuid(self.ctxt, uuid)
self.mox.VerifyAll()
def test_save(self):
uuid = self.fake_chassis['uuid']
self.mox.StubOutWithMock(self.dbapi, 'get_chassis')
self.mox.StubOutWithMock(self.dbapi, 'update_chassis')
self.dbapi.get_chassis(uuid).AndReturn(self.fake_chassis)
self.dbapi.update_chassis(uuid, {'extra': '{"test": 123}'})
self.mox.ReplayAll()
c = objects.Chassis.get_by_uuid(self.ctxt, uuid)
c.extra = '{"test": 123}'
c.save()
self.mox.VerifyAll()
def test_refresh(self):
uuid = self.fake_chassis['uuid']
new_uuid = uuidutils.generate_uuid()
self.mox.StubOutWithMock(self.dbapi, 'get_chassis')
self.dbapi.get_chassis(uuid).AndReturn(
dict(self.fake_chassis, uuid=uuid))
self.dbapi.get_chassis(uuid).AndReturn(
dict(self.fake_chassis, uuid=new_uuid))
self.mox.ReplayAll()
c = objects.Chassis.get_by_uuid(self.ctxt, uuid)
self.assertEqual(c.uuid, uuid)
c.refresh()
self.assertEqual(c.uuid, new_uuid)
self.mox.VerifyAll()
def test_objectify(self):
def _get_db_chassis():
c = models.Chassis()
c.update(self.fake_chassis)
return c
@objects.objectify(objects.Chassis)
def _convert_db_chassis():
return _get_db_chassis()
self.assertIsInstance(_get_db_chassis(), models.Chassis)
self.assertIsInstance(_convert_db_chassis(), objects.Chassis)
def test_objectify_many(self):
def _get_many_db_chassis():
chassis = []
for i in xrange(5):
c = models.Chassis()
c.update(self.fake_chassis)
chassis.append(c)
return chassis
@objects.objectify(objects.Chassis)
def _convert_many_db_chassis():
return _get_many_db_chassis()
for c in _get_many_db_chassis():
self.assertIsInstance(c, models.Chassis)
for c in _convert_many_db_chassis():
self.assertIsInstance(c, objects.Chassis)