'Return a task to update the resource.
Subclasses should provide a handle_update() method to customise update,
the base-class handle_update will fail by default.'

@scheduler.wrappertask
def update(self, after, before=None, prev_resource=None, update_templ_func=None):

    action = self.UPDATE
    assert isinstance(after, rsrc_defn.ResourceDefinition)
    if (before is None):
        before = self.frozen_definition()
    after_external_id = after.external_id()
    if (self.external_id != after_external_id):
        msg = (_('Update    to    property    %(prop)s    of    %(name)s    (%(res)s)') % {'prop': hot_tmpl.HOTemplate20161014.RES_EXTERNAL_ID, 'res': self.type(), 'name': self.name})
        exc = exception.NotSupported(feature=msg)
        raise exception.ResourceFailure(exc, self, action)
    elif (after_external_id is not None):
        LOG.debug('Skip    update    on    external    resource.')
        return
    (after_props, before_props) = self._prepare_update_props(after, before)
    (yield self._break_if_required(self.UPDATE, environment.HOOK_PRE_UPDATE))
    try:
        registry = self.stack.env.registry
        restr_actions = registry.get_rsrc_restricted_actions(self.name)
        if restr_actions:
            if (not self._check_restricted_actions(restr_actions, after, before, after_props, before_props, prev_resource)):
                if (update_templ_func is not None):
                    update_templ_func(persist=True)
                return
        elif (not self._needs_update(after, before, after_props, before_props, prev_resource)):
            if (update_templ_func is not None):
                update_templ_func(persist=True)
            if (self.status == self.FAILED):
                status_reason = _('Update    status    to    COMPLETE    for    FAILED    resource    neither    update    nor    replace.')
                self.state_set(self.action, self.COMPLETE, status_reason)
            return
        if (not self.stack.convergence):
            if ((self.action, self.status) in ((self.CREATE, self.IN_PROGRESS), (self.UPDATE, self.IN_PROGRESS), (self.ADOPT, self.IN_PROGRESS))):
                exc = Exception(_('Resource    update    already    requested'))
                raise exception.ResourceFailure(exc, self, action)
        LOG.info('updating    %s', self)
        self.updated_time = datetime.utcnow()
        with self._action_recorder(action, UpdateReplace):
            after_props.validate()
            tmpl_diff = self.update_template_diff(after.freeze(), before)
            if (tmpl_diff and self.needs_replace_with_tmpl_diff(tmpl_diff)):
                raise UpdateReplace(self)
            prop_diff = self.update_template_diff_properties(after_props, before_props)
            self.properties = before_props
            (yield self.action_handler_task(action, args=[after, tmpl_diff, prop_diff]))
            self.t = after
            self.reparse()
            self._update_stored_properties()
            if (update_templ_func is not None):
                update_templ_func(persist=False)
    except exception.ResourceActionRestricted as ae:
        failure = exception.ResourceFailure(ae, self, action)
        self._add_event(action, self.FAILED, six.text_type(ae))
        raise failure
    except UpdateReplace:
        self._prepare_update_replace(action)
        raise
    (yield self._break_if_required(self.UPDATE, environment.HOOK_POST_UPDATE))
