Source code for heat.engine.resources.wait_condition

#
#    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 collections

from oslo_log import log as logging

from heat.common import exception
from heat.common.i18n import _
from heat.engine.resources import signal_responder

LOG = logging.getLogger(__name__)


[docs]class BaseWaitConditionHandle(signal_responder.SignalResponder): """Base WaitConditionHandle resource. The main point of this class is to : - have no dependencies (so the instance can reference it) - create credentials to allow for signalling from the instance. - handle signals from the instance, validate and store result """ properties_schema = {} WAIT_STATUSES = ( STATUS_FAILURE, STATUS_SUCCESS, ) = ( 'FAILURE', 'SUCCESS', ) def _get_ec2_signed_url(self, signal_type=signal_responder.WAITCONDITION): stored = self.data().get('ec2_signed_url') if stored is not None: return stored url = super(BaseWaitConditionHandle, self)._get_ec2_signed_url(signal_type) self.data_set('ec2_signed_url', url) return url
[docs] def handle_create(self): super(BaseWaitConditionHandle, self).handle_create() self.resource_id_set(self._get_user_id())
def _status_ok(self, status): return status in self.WAIT_STATUSES def _metadata_format_ok(self, metadata): if not isinstance(metadata, collections.abc.Mapping): return False if set(metadata) != set(self.METADATA_KEYS): return False return self._status_ok(metadata[self.STATUS])
[docs] def normalise_signal_data(self, signal_data, latest_metadata): return signal_data
[docs] def handle_signal(self, details=None): write_attempts = [] def merge_signal_metadata(signal_data, latest_rsrc_metadata): signal_data = self.normalise_signal_data(signal_data, latest_rsrc_metadata) if not self._metadata_format_ok(signal_data): LOG.info("Metadata failed validation for %s", self.name) raise ValueError(_("Metadata format invalid")) new_entry = signal_data.copy() unique_id = str(new_entry.pop(self.UNIQUE_ID)) new_rsrc_metadata = latest_rsrc_metadata.copy() if unique_id in new_rsrc_metadata: LOG.info("Overwriting Metadata item for id %s!", unique_id) new_rsrc_metadata.update({unique_id: new_entry}) write_attempts.append(signal_data) return new_rsrc_metadata self.metadata_set(details, merge_metadata=merge_signal_metadata) data_written = write_attempts[-1] signal_reason = ('status:%s reason:%s' % (data_written[self.STATUS], data_written[self.REASON])) return signal_reason
[docs] def get_status(self): """Return a list of the Status values for the handle signals.""" return [v[self.STATUS] for v in self.metadata_get(refresh=True).values()]
[docs] def get_status_reason(self, status): """Return a list of reasons associated with a particular status.""" return [v[self.REASON] for v in self.metadata_get(refresh=True).values() if v[self.STATUS] == status]
[docs]class WaitConditionFailure(exception.Error): def __init__(self, wait_condition, handle): reasons = handle.get_status_reason(handle.STATUS_FAILURE) super(WaitConditionFailure, self).__init__(';'.join(reasons))
[docs]class WaitConditionTimeout(exception.Error): def __init__(self, wait_condition, handle): reasons = handle.get_status_reason(handle.STATUS_SUCCESS) vals = {'len': len(reasons), 'count': wait_condition.properties[wait_condition.COUNT]} if reasons: vals['reasons'] = ';'.join(reasons) message = (_('%(len)d of %(count)d received - %(reasons)s') % vals) else: message = (_('%(len)d of %(count)d received') % vals) super(WaitConditionTimeout, self).__init__(message)