Loop over an execution module until a condition is met.

    name
        The name of the execution module

    m_args
        The execution module's positional arguments

    m_kwargs
        The execution module's keyword arguments

    condition
        The condition which must be met for the loop to break. This
        should contain ``m_ret`` which is the return from the execution
        module.

    period
        The number of seconds to wait between executions

    timeout
        The timeout in seconds

def until(name,
          m_args=None,
          m_kwargs=None,
          condition=None,
          period=0,
          timeout=604800):
    '''
    Loop over an execution module until a condition is met.

    name
        The name of the execution module

    m_args
        The execution module's positional arguments

    m_kwargs
        The execution module's keyword arguments

    condition
        The condition which must be met for the loop to break. This
        should contain ``m_ret`` which is the return from the execution
        module.

    period
        The number of seconds to wait between executions

    timeout
        The timeout in seconds
    '''
    ret = {'name': name,
           'changes': {},
           'result': False,
           'comment': ''}

    if name not in __salt__:
        ret['comment'] = 'Cannot find module {0}'.format(name)
        return ret
    if condition is None:
        ret['comment'] = 'An exit condition must be specified'
        return ret
    if not isinstance(period, int):
        ret['comment'] = 'Period must be specified as an integer in seconds'
        return ret
    if not isinstance(timeout, int):
        ret['comment'] = 'Timeout must be specified as an integer in seconds'
        return ret
    if __opts__['test']:
        ret['comment'] = 'The execution module {0} will be run'.format(name)
        ret['result'] = None
        return ret
    if not m_args:
        m_args = []
    if not m_kwargs:
        m_kwargs = {}

    def timed_out():
        if time.time() >= timeout:
            return True
        return False

    timeout = time.time() + timeout

    while not timed_out():
        m_ret = __salt__[name](*m_args, **m_kwargs)
        if eval(condition):  # pylint: disable=W0123
            ret['result'] = True
            ret['comment'] = 'Condition {0} was met'.format(condition)
            return ret
        time.sleep(period)

    ret['comment'] = 'Timed out while waiting for condition {0}'.format(condition)
    return ret