'Determine whether the current volume state of an application is
divergent from the volume configuration for that application in a way
that merits an application restart right now.
Many actual divergences are allowed and ignored:
- The volume metadata.  This metadata only exists in the
configuration.  It is always missing from the state object.
- The volume size.  The dataset agent is not reliably capable of
performing resizes (if we wait for the actual and configured
sizes to match, we might have to wait forever).
- The volume\'s deleted state.  The application will be allowed to
continue to use a volume that has been marked for deletion until
the application is explicitly stopped.
:param NodeState node_state: The known local state of this node.
:param AttachedVolume state: The known state of the volume of an
application being considered.  Or ``None`` if it is known not to
have a volume.
:param AttachedVolume configuration: The configured state of the volume
of the application being considered.  Or ``None`` if it is
configured to not have a volume.
:return: If the state differs from the configuration in a way which
needs to be corrected by the convergence agent (for example, the
application is configured with a volume but is running without
one), ``True``.  If it does not differ or only differs in the
allowed ways mentioned above, ``False``.'

def _restart_for_volume_change(self, node_state, state, configuration):

    def log(restart, reason=None):
        Message.new(message_type=_eliot_system(u'restart_for_volume_change'), restart=restart, state_is_none=(state is None), configuration_is_none=(configuration is None), reason=reason).write()
        return restart
    def restart_if_available(dataset_id):
        '\n                                                Considering    that    we    would    like    to    restart    the    application    with    a\n                                                volume    using    the    given    dataset_id,    determine    whether    we    can\n                                                actually    do    so    at    this    time.\n\n                                                If    the    indicated    dataset    has    no    manifestation    on    this    node,    we    will\n                                                not    be    able    to    start    the    application    again    after    stopping    it.        So\n                                                leave    it    running    until    such    a    manifestation    exists.\n\n                                                :param    unicode    dataset_id:    The    identifier    of    the    dataset    we    want.\n\n                                                :return:    If    there    is    a    manifestation    of    the    given    dataset    on    this\n                                                                node,    ``True``.        Otherwise,    ``False``.\n                                                '
        if (dataset_id in node_state.manifestations):
            return log(True, 'have    configured    dataset')
        else:
            return log(False, 'missing    configured    dataset')
    state_id = getattr(getattr(state, 'manifestation', None), 'dataset_id', None)
    config_id = getattr(getattr(configuration, 'manifestation', None), 'dataset_id', None)
    if (state_id == config_id):
        return log(False, 'dataset    matches')
    elif (config_id is None):
        return log(True, 'volume    removed')
    else:
        return restart_if_available(config_id)
