Versioned objects - Resource

implementation for versioned objects. This contains Resource

Implements: blueprint versioned-objects
Co-Authored-By: Michal Jastrzebski (inc0) <michal.jastrzebski@intel.com>
Change-Id: Id4a5724d68e93b51aaf45d75e5e5e564b5d87789
This commit is contained in:
ShaoHe Feng 2014-12-15 14:12:40 +01:00 committed by Michal Jastrzebski (inc0)
parent 8736c227cf
commit 49b30027a5
9 changed files with 192 additions and 30 deletions

View File

@ -30,7 +30,6 @@ from heat.common.i18n import _LW
from heat.common import identifier
from heat.common import short_id
from heat.common import timeutils
from heat.db import api as db_api
from heat.engine import attributes
from heat.engine import event
from heat.engine import function
@ -39,6 +38,7 @@ from heat.engine import resources
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.engine import support
from heat.objects import resource as resource_objects
from heat.objects import resource_data as resource_data_objects
from heat.rpc import client as rpc_client
@ -243,7 +243,7 @@ class Resource(object):
return self.t.metadata()
if self._rsrc_metadata is not None:
return self._rsrc_metadata
rs = db_api.resource_get(self.stack.context, self.id)
rs = resource_objects.Resource.get_obj(self.stack.context, self.id)
rs.refresh(attrs=['rsrc_metadata'])
self._rsrc_metadata = rs.rsrc_metadata
return rs.rsrc_metadata
@ -251,7 +251,7 @@ class Resource(object):
def metadata_set(self, metadata):
if self.id is None:
raise exception.ResourceNotAvailable(resource_name=self.name)
rs = db_api.resource_get(self.stack.context, self.id)
rs = resource_objects.Resource.get_obj(self.stack.context, self.id)
rs.update_and_save({'rsrc_metadata': metadata})
self._rsrc_metadata = metadata
@ -877,7 +877,7 @@ class Resource(object):
return
try:
db_api.resource_get(self.context, self.id).delete()
resource_objects.Resource.delete(self.context, self.id)
except exception.NotFound:
# Don't fail on delete if the db entry has
# not been created yet.
@ -889,7 +889,7 @@ class Resource(object):
self.resource_id = inst
if self.id is not None:
try:
rs = db_api.resource_get(self.context, self.id)
rs = resource_objects.Resource.get_obj(self.context, self.id)
rs.update_and_save({'nova_instance': self.resource_id})
except Exception as ex:
LOG.warn(_LW('db error %s'), ex)
@ -908,7 +908,7 @@ class Resource(object):
'properties_data': self._stored_properties_data,
'stack_name': self.stack.name}
new_rs = db_api.resource_create(self.context, rs)
new_rs = resource_objects.Resource.create(self.context, rs)
self.id = new_rs.id
self.uuid = new_rs.uuid
self.created_time = new_rs.created_at
@ -931,7 +931,7 @@ class Resource(object):
if self.id is not None:
try:
rs = db_api.resource_get(self.context, self.id)
rs = resource_objects.Resource.get_obj(self.context, self.id)
rs.update_and_save({
'action': self.action,
'status': self.status,

View File

@ -51,6 +51,7 @@ from heat.engine import stack_lock
from heat.engine import template as templatem
from heat.engine import watchrule
from heat.engine import worker
from heat.objects import resource as resource_objects
from heat.objects import stack as stack_object
from heat.openstack.common import service
from heat.openstack.common import threadgroup
@ -1136,8 +1137,9 @@ class EngineService(service.Service):
:param cnxt: RPC context.
:param physical_resource_id: The physical resource ID to look up.
"""
rs = db_api.resource_get_by_physical_resource_id(cnxt,
physical_resource_id)
rs = resource_objects.Resource.get_by_physical_resource_id(
cnxt,
physical_resource_id)
if not rs:
raise exception.PhysicalResourceNotFound(
resource_id=physical_resource_id)

4
heat/engine/stack.py Normal file → Executable file
View File

@ -41,6 +41,7 @@ from heat.engine import resources
from heat.engine import scheduler
from heat.engine import template as tmpl
from heat.engine import update
from heat.objects import resource as resource_objects
from heat.objects import stack as stack_object
from heat.rpc import api as rpc_api
@ -218,8 +219,9 @@ class Stack(collections.Mapping):
return None
if self._db_resources is None:
try:
self._db_resources = db_api.resource_get_all_by_stack(
_db_resources = resource_objects.Resource.get_all_by_stack(
self.context, self.id)
self._db_resources = _db_resources
except exception.NotFound:
return None
return self._db_resources.get(name)

View File

@ -15,10 +15,10 @@ from oslo_log import log as logging
import six
from heat.common.i18n import _LI
from heat.db import api as db_api
from heat.engine import dependencies
from heat.engine import resource
from heat.engine import scheduler
from heat.objects import resource as resource_objects
LOG = logging.getLogger(__name__)
@ -84,8 +84,8 @@ class StackUpdate(object):
@staticmethod
def _exchange_stacks(existing_res, prev_res):
db_api.resource_exchange_stacks(existing_res.stack.context,
existing_res.id, prev_res.id)
resource_objects.Resource.exchange_stacks(existing_res.stack.context,
existing_res.id, prev_res.id)
prev_stack, existing_stack = prev_res.stack, existing_res.stack
prev_stack.add_resource(existing_res)
existing_stack.add_resource(prev_res)

153
heat/objects/resource.py Executable file
View File

@ -0,0 +1,153 @@
# Copyright 2014 Intel Corp.
#
# 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.
"""
Resource object
"""
from oslo_versionedobjects import base
from oslo_versionedobjects import fields
from heat.db import api as db_api
from heat.objects import fields as heat_fields
from heat.objects import resource_data
from heat.objects import stack
class Resource(
base.VersionedObject,
base.VersionedObjectDictCompat,
base.ComparableVersionedObject,
):
fields = {
'id': fields.IntegerField(),
'uuid': fields.StringField(),
'stack_id': fields.StringField(nullable=False),
'created_at': fields.DateTimeField(read_only=True),
'updated_at': fields.DateTimeField(nullable=True),
'nova_instance': fields.StringField(nullable=True),
'name': fields.StringField(nullable=True),
'status': fields.StringField(nullable=True),
'status_reason': fields.StringField(nullable=True),
'action': fields.StringField(nullable=True),
'rsrc_metadata': heat_fields.JsonField(nullable=True),
'properties_data': heat_fields.JsonField(nullable=True),
'data': fields.ListOfObjectsField(
resource_data.ResourceData,
nullable=True
),
'stack': fields.ObjectField(stack.Stack, nullable=False),
'engine_id': fields.StringField(nullable=True),
'atomic_key': fields.IntegerField(nullable=True),
}
@staticmethod
def _from_db_object(resource, context, db_resource):
if db_resource is None:
return None
for field in resource.fields:
if field == 'data':
resource['data'] = map(
lambda resd: resource_data.ResourceData._from_db_object(
resource_data.ResourceData(context), resd
),
db_resource.data
)
else:
resource[field] = db_resource[field]
resource._context = context
resource.obj_reset_changes()
return resource
@classmethod
def get_obj(cls, context, resource_id):
resource_db = db_api.resource_get(context, resource_id)
resource = cls._from_db_object(cls(context), context, resource_db)
return resource
@classmethod
def get_all(cls, context):
resources_db = db_api.resource_get_all(context)
resources = [
(
resource_name,
cls._from_db_object(cls(context), context, resource_db)
)
for resource_name, resource_db in resources_db.iteritems()
]
return dict(resources)
@classmethod
def create(cls, context, values):
return db_api.resource_create(context, values)
@classmethod
def delete(cls, context, resource_id):
resource_db = db_api.resource_get(context, resource_id)
resource_db.delete()
@classmethod
def exchange_stacks(cls, context, resource_id1, resource_id2):
return db_api.resource_exchange_stacks(
context,
resource_id1,
resource_id2)
@classmethod
def get_all_by_stack(cls, context, stack_id):
resources_db = db_api.resource_get_all_by_stack(context, stack_id)
resources = [
(
resource_name,
cls._from_db_object(cls(context), context, resource_db)
)
for resource_name, resource_db in resources_db.iteritems()
]
return dict(resources)
@classmethod
def get_by_name_and_stack(cls, context, resource_name, stack_id):
resource_db = db_api.resource_get_by_name_and_stack(
context,
resource_name,
stack_id)
resource = cls._from_db_object(cls(context), context, resource_db)
return resource
@classmethod
def get_by_physical_resource_id(cls, context, physical_resource_id):
resource_db = db_api.resource_get_by_physical_resource_id(
context,
physical_resource_id)
resource = cls._from_db_object(cls(context), context, resource_db)
return resource
def update_and_save(cls, values):
resource_db = db_api.resource_get(cls._context, cls.id)
resource_db.update_and_save(values)
cls._refresh()
return resource_db
def _refresh(self):
return self.__class__._from_db_object(
self,
self._context,
self.__class__.get_obj(self._context, self.id))
def refresh(self, attrs=None):
resource_db = db_api.resource_get(self._context, self.id)
resource_db.refresh(attrs=attrs)
return self._refresh()

View File

@ -23,12 +23,12 @@ import six
from heat.common import exception
from heat.common import identifier
from heat.common import template_format
from heat.db import api as db_api
from heat.engine import environment
from heat.engine import parser
from heat.engine.resources.aws.cfn import wait_condition_handle as aws_wch
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.objects import resource as resource_objects
from heat.tests import common
from heat.tests import utils
@ -128,8 +128,8 @@ class WaitConditionTest(common.HeatTestCase):
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'WaitHandle', self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
@ -148,8 +148,8 @@ class WaitConditionTest(common.HeatTestCase):
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'WaitHandle', self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
@ -171,8 +171,8 @@ class WaitConditionTest(common.HeatTestCase):
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'WaitHandle', self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()
@ -192,8 +192,8 @@ class WaitConditionTest(common.HeatTestCase):
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'WaitHandle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'WaitHandle', self.stack.id)
self.assertEqual('WaitHandle', r.name)
self.m.VerifyAll()

View File

@ -19,12 +19,12 @@ import six
from heat.common import identifier
from heat.common import template_format
from heat.db import api as db_api
from heat.engine.clients.os import heat_plugin
from heat.engine import environment
from heat.engine import parser
from heat.engine import resource
from heat.engine.resources.openstack.heat import wait_condition_handle as h_wch
from heat.objects import resource as resource_objects
from heat.tests import common
from heat.tests import utils
@ -125,8 +125,8 @@ class HeatWaitConditionTest(common.HeatTestCase):
self.assertEqual((rsrc.CREATE, rsrc.COMPLETE),
rsrc.state)
r = db_api.resource_get_by_name_and_stack(None, 'wait_handle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'wait_handle', self.stack.id)
self.assertEqual('wait_handle', r.name)
self.m.VerifyAll()
@ -149,8 +149,8 @@ class HeatWaitConditionTest(common.HeatTestCase):
reason = rsrc.status_reason
self.assertTrue(reason.startswith('WaitConditionFailure:'))
r = db_api.resource_get_by_name_and_stack(None, 'wait_handle',
self.stack.id)
r = resource_objects.Resource.get_by_name_and_stack(
None, 'wait_handle', self.stack.id)
self.assertEqual('wait_handle', r.name)
self.m.VerifyAll()

View File

@ -48,6 +48,7 @@ from heat.engine import stack_lock
from heat.engine import template as templatem
from heat.engine import watchrule
from heat.engine import worker
from heat.objects import resource as resource_objects
from heat.objects import stack as stack_object
from heat.openstack.common import threadgroup
from heat.rpc import api as rpc_api
@ -3572,7 +3573,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
self.ctx, server_id=server.resource_id)
self.assertEqual([deployment], deployments)
rs = db_api.resource_get_by_physical_resource_id(self.ctx, server_id)
rs = resource_objects.Resource.get_by_physical_resource_id(
self.ctx, server_id)
self.assertEqual(deployment['config_id'],
rs.rsrc_metadata.get('deployments')[0]['id'])
@ -3618,7 +3620,8 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
# assert that metadata via metadata_software_deployments matches
# metadata via server resource
rs = db_api.resource_get_by_physical_resource_id(self.ctx, server_id)
rs = resource_objects.Resource.get_by_physical_resource_id(
self.ctx, server_id)
self.assertEqual(metadata,
rs.rsrc_metadata.get('deployments'))

View File

@ -34,6 +34,7 @@ from heat.engine import resources
from heat.engine import rsrc_defn
from heat.engine import scheduler
from heat.engine import template
from heat.objects import resource as resource_objects
from heat.objects import resource_data as resource_data_object
from heat.tests import common
from heat.tests import generic_resource as generic_rsrc
@ -329,7 +330,7 @@ class ResourceTest(common.HeatTestCase):
self.assertEqual(res.IN_PROGRESS, res.status)
self.assertEqual('test_store', res.status_reason)
db_res = db_api.resource_get(res.context, res.id)
db_res = resource_objects.Resource.get_obj(res.context, res.id)
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.IN_PROGRESS, db_res.status)
self.assertEqual('test_store', db_res.status_reason)
@ -338,6 +339,7 @@ class ResourceTest(common.HeatTestCase):
self.assertEqual(res.CREATE, res.action)
self.assertEqual(res.COMPLETE, res.status)
self.assertEqual('test_update', res.status_reason)
db_res.refresh()
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.COMPLETE, db_res.status)
self.assertEqual('test_update', db_res.status_reason)