summaryrefslogtreecommitdiff
path: root/heat/engine
diff options
context:
space:
mode:
Diffstat (limited to 'heat/engine')
-rw-r--r--heat/engine/event.py63
-rw-r--r--heat/engine/resource.py38
-rw-r--r--heat/engine/stack.py2
3 files changed, 40 insertions, 63 deletions
diff --git a/heat/engine/event.py b/heat/engine/event.py
index c7865f734..498427ad8 100644
--- a/heat/engine/event.py
+++ b/heat/engine/event.py
@@ -11,19 +11,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
-from sqlalchemy.util.compat import pickle
-
-import oslo_db.exception
-from oslo_log import log as logging
-
from heat.common import identifier
from heat.objects import event as event_object
-
-LOG = logging.getLogger(__name__)
-
-MAX_EVENT_RESOURCE_PROPERTIES_SIZE = (1 << 16) - 1
+from heat.objects import resource_properties_data as rpd_objects
class Event(object):
@@ -45,10 +35,17 @@ class Event(object):
self.physical_resource_id = physical_resource_id
self.resource_name = resource_name
self.resource_type = resource_type
- try:
- self.resource_properties = dict(resource_properties)
- except ValueError as ex:
- self.resource_properties = {'Error': six.text_type(ex)}
+ self.rsrc_prop_data = None
+ if isinstance(resource_properties,
+ rpd_objects.ResourcePropertiesData):
+ self.rsrc_prop_data = resource_properties
+ self.resource_properties = self.rsrc_prop_data.data
+ elif resource_properties is None:
+ self.resource_properties = {}
+ else:
+ raise AssertionError(
+ _('resource_properties is unexpected type %s'),
+ type(resource_properties))
self.uuid = uuid
self.timestamp = timestamp
self.id = id
@@ -63,7 +60,6 @@ class Event(object):
'resource_status': self.status,
'resource_status_reason': self.reason,
'resource_type': self.resource_type,
- 'resource_properties': self.resource_properties,
}
if self.uuid is not None:
@@ -72,39 +68,10 @@ class Event(object):
if self.timestamp is not None:
ev['created_at'] = self.timestamp
- # Workaround: we don't want to attempt to store the
- # event.resource_properties column if the data is too large
- # (greater than permitted by BLOB). Otherwise, we end up with
- # an unsightly log message.
- rp_size = len(pickle.dumps(ev['resource_properties'],
- pickle.HIGHEST_PROTOCOL))
- if rp_size > MAX_EVENT_RESOURCE_PROPERTIES_SIZE:
- LOG.debug('event\'s resource_properties too large to store at '
- '%d bytes', rp_size)
- # Try truncating the largest value and see if that gets us under
- # the db column's size constraint.
- max_key, max_val = max(ev['resource_properties'].items(),
- key=lambda i: len(repr(i[1])))
- err = 'Resource properties are too large to store fully'
- ev['resource_properties'].update({'Error': err})
- ev['resource_properties'][max_key] = '<Deleted, too large>'
- rp_size = len(pickle.dumps(ev['resource_properties'],
- pickle.HIGHEST_PROTOCOL))
- if rp_size > MAX_EVENT_RESOURCE_PROPERTIES_SIZE:
- LOG.debug('event\'s resource_properties STILL too large '
- 'after truncating largest key at %d bytes', rp_size)
- err = 'Resource properties are too large to attempt to store'
- ev['resource_properties'] = {'Error': err}
+ if self.rsrc_prop_data:
+ ev['rsrc_prop_data_id'] = self.rsrc_prop_data.id
- # We should have worked around the issue, but let's be extra
- # careful.
- try:
- new_ev = event_object.Event.create(self.context, ev)
- except oslo_db.exception.DBError:
- # Give up and drop all properties..
- err = 'Resource properties are too large to store'
- ev['resource_properties'] = {'Error': err}
- new_ev = event_object.Event.create(self.context, ev)
+ new_ev = event_object.Event.create(self.context, ev)
self.id = new_ev.id
self.timestamp = new_ev.created_at
diff --git a/heat/engine/resource.py b/heat/engine/resource.py
index a5b369bb2..3326c5ed3 100644
--- a/heat/engine/resource.py
+++ b/heat/engine/resource.py
@@ -44,6 +44,7 @@ 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.objects import resource_properties_data as rpd_objects
from heat.objects import stack as stack_objects
from heat.rpc import client as rpc_client
@@ -249,6 +250,7 @@ class Resource(object):
self.uuid = None
self._data = None
self._rsrc_metadata = None
+ self._rsrc_prop_data = None
self._stored_properties_data = None
self.created_time = stack.created_time
self.updated_time = stack.updated_time
@@ -291,6 +293,7 @@ class Resource(object):
self._data = {}
self._rsrc_metadata = resource.rsrc_metadata
self._stored_properties_data = resource.properties_data
+ self._rsrc_prop_data = resource.rsrc_prop_data
self.created_time = resource.created_at
self.updated_time = resource.updated_at
self.needed_by = resource.needed_by
@@ -350,7 +353,7 @@ class Resource(object):
# Don't set physical_resource_id so that a create is triggered.
rs = {'stack_id': self.stack.id,
'name': self.name,
- 'properties_data': self._stored_properties_data,
+ 'rsrc_prop_data_id': self._create_or_replace_rsrc_prop_data(),
'needed_by': self.needed_by,
'requires': self.requires,
'replaces': self.id,
@@ -858,7 +861,10 @@ class Resource(object):
yield self.action_handler_task(action, args=handler_args)
def _update_stored_properties(self):
+ old_props = self._stored_properties_data
self._stored_properties_data = function.resolve(self.properties.data)
+ if self._stored_properties_data != old_props:
+ self._rsrc_prop_data = None
def preview(self):
"""Default implementation of Resource.preview.
@@ -1721,10 +1727,6 @@ class Resource(object):
def _store(self, metadata=None):
"""Create the resource in the database."""
-
- properties_data_encrypted, properties_data = (
- resource_objects.Resource.encrypt_properties_data(
- self._stored_properties_data))
if not self.root_stack_id:
self.root_stack_id = self.stack.root_stack_id()
try:
@@ -1735,8 +1737,8 @@ class Resource(object):
'physical_resource_id': self.resource_id,
'name': self.name,
'rsrc_metadata': metadata,
- 'properties_data': properties_data,
- 'properties_data_encrypted': properties_data_encrypted,
+ 'rsrc_prop_data_id':
+ self._create_or_replace_rsrc_prop_data(),
'needed_by': self.needed_by,
'requires': self.requires,
'replaces': self.replaces,
@@ -1744,7 +1746,6 @@ class Resource(object):
'current_template_id': self.current_template_id,
'stack_name': self.stack.name,
'root_stack_id': self.root_stack_id}
-
new_rs = resource_objects.Resource.create(self.context, rs)
self.id = new_rs.id
self.uuid = new_rs.uuid
@@ -1757,7 +1758,7 @@ class Resource(object):
"""Add a state change event to the database."""
physical_res_id = self.resource_id or self.physical_resource_name()
ev = event.Event(self.context, self.stack, action, status, reason,
- physical_res_id, self.properties,
+ physical_res_id, self._rsrc_prop_data,
self.name, self.type())
ev.store()
@@ -1769,18 +1770,15 @@ class Resource(object):
self.status = status
self.status_reason = reason
- properties_data_encrypted, properties_data = (
- resource_objects.Resource.encrypt_properties_data(
- self._stored_properties_data))
data = {
'action': self.action,
'status': self.status,
'status_reason': reason,
'stack_id': self.stack.id,
'updated_at': self.updated_time,
- 'properties_data': properties_data,
- 'properties_data_encrypted': properties_data_encrypted,
'needed_by': self.needed_by,
+ 'rsrc_prop_data_id': self._create_or_replace_rsrc_prop_data(),
+ 'properties_data': None,
'requires': self.requires,
'replaces': self.replaces,
'replaced_by': self.replaced_by,
@@ -2286,6 +2284,18 @@ class Resource(object):
self._data = None
return True
+ def _create_or_replace_rsrc_prop_data(self):
+ if self._rsrc_prop_data is not None:
+ return self._rsrc_prop_data.id
+
+ if not self._stored_properties_data:
+ return None
+
+ self._rsrc_prop_data = \
+ rpd_objects.ResourcePropertiesData(self.context).create(
+ self.context, self._stored_properties_data)
+ return self._rsrc_prop_data.id
+
def is_using_neutron(self):
try:
sess_client = self.client('neutron').httpclient
diff --git a/heat/engine/stack.py b/heat/engine/stack.py
index e6bcea5d4..bc3429f34 100644
--- a/heat/engine/stack.py
+++ b/heat/engine/stack.py
@@ -887,7 +887,7 @@ class Stack(collections.Mapping):
def _add_event(self, action, status, reason):
"""Add a state change event to the database."""
ev = event.Event(self.context, self, action, status, reason,
- self.id, {},
+ self.id, None,
self.name, 'OS::Heat::Stack')
ev.store()