Esempio n. 1
0
def _call_agent(session,
                instance,
                vm_ref,
                method,
                addl_args=None,
                timeout=None,
                success_codes=None):
    """Abstracts out the interaction with the agent xenapi plugin."""
    if addl_args is None:
        addl_args = {}
    if timeout is None:
        timeout = CONF.xenserver.agent_timeout
    if success_codes is None:
        success_codes = ['0']

    # always fetch domid because VM may have rebooted
    dom_id = session.VM.get_domid(vm_ref)
    uuid = uuidutils.generate_uuid()
    args = {
        'id': uuid,
        'dom_id': str(dom_id),
        'timeout': str(timeout),
    }

    try:
        ret = method(session, uuid, dom_id, timeout, **addl_args)
    except XenAPI.Failure as e:
        err_msg = e.details[-1].splitlines()[-1]
        if 'TIMEOUT:' in err_msg:
            LOG.error(
                'TIMEOUT: The call to %(method)s timed out. '
                'args=%(args)r', {
                    'method': method,
                    'args': args
                },
                instance=instance)
            raise exception.AgentTimeout(method=method.__name__)
        elif 'REBOOT:' in err_msg:
            LOG.debug(
                'REBOOT: The call to %(method)s detected a reboot. '
                'args=%(args)r', {
                    'method': method,
                    'args': args
                },
                instance=instance)
            _wait_for_new_dom_id(session, vm_ref, dom_id, method)
            return _call_agent(session, instance, vm_ref, method, addl_args,
                               timeout, success_codes)
        elif 'NOT IMPLEMENTED:' in err_msg:
            LOG.error(
                'NOT IMPLEMENTED: The call to %(method)s is not '
                'supported by the agent. args=%(args)r', {
                    'method': method,
                    'args': args
                },
                instance=instance)
            raise exception.AgentNotImplemented(method=method.__name__)
        else:
            LOG.error(
                'The call to %(method)s returned an error: %(e)s. '
                'args=%(args)r', {
                    'method': method,
                    'args': args,
                    'e': e
                },
                instance=instance)
            raise exception.AgentError(method=method.__name__)

    if not isinstance(ret, dict):
        try:
            ret = jsonutils.loads(ret)
        except TypeError:
            LOG.error(
                'The agent call to %(method)s returned an invalid '
                'response: %(ret)r. args=%(args)r', {
                    'method': method,
                    'ret': ret,
                    'args': args
                },
                instance=instance)
            raise exception.AgentError(method=method.__name__)

    if ret['returncode'] not in success_codes:
        LOG.error(
            'The agent call to %(method)s returned '
            'an error: %(ret)r. args=%(args)r', {
                'method': method,
                'ret': ret,
                'args': args
            },
            instance=instance)
        raise exception.AgentError(method=method.__name__)

    LOG.debug(
        'The agent call to %(method)s was successful: '
        '%(ret)r. args=%(args)r', {
            'method': method,
            'ret': ret,
            'args': args
        },
        instance=instance)

    # Some old versions of the Windows agent have a trailing \\r\\n
    # (ie CRLF escaped) for some reason. Strip that off.
    return ret['message'].replace('\\r\\n', '')
Esempio n. 2
0
def _call_agent(session,
                instance,
                vm_ref,
                method,
                addl_args=None,
                timeout=None,
                success_codes=None):
    """Abstracts out the interaction with the agent xenapi plugin."""
    if addl_args is None:
        addl_args = {}
    if timeout is None:
        timeout = CONF.xenserver.agent_timeout
    if success_codes is None:
        success_codes = ['0']

    vm_rec = session.call_xenapi("VM.get_record", vm_ref)

    args = {
        'id': str(uuid.uuid4()),
        'dom_id': vm_rec['domid'],
        'timeout': str(timeout),
    }
    args.update(addl_args)

    try:
        ret = session.call_plugin('agent', method, args)
    except session.XenAPI.Failure as e:
        err_msg = e.details[-1].splitlines()[-1]
        if 'TIMEOUT:' in err_msg:
            LOG.error(_('TIMEOUT: The call to %(method)s timed out. '
                        'args=%(args)r'), {
                            'method': method,
                            'args': args
                        },
                      instance=instance)
            raise exception.AgentTimeout(method=method)
        elif 'NOT IMPLEMENTED:' in err_msg:
            LOG.error(_('NOT IMPLEMENTED: The call to %(method)s is not '
                        'supported by the agent. args=%(args)r'), {
                            'method': method,
                            'args': args
                        },
                      instance=instance)
            raise exception.AgentNotImplemented(method=method)
        else:
            LOG.error(_('The call to %(method)s returned an error: %(e)s. '
                        'args=%(args)r'), {
                            'method': method,
                            'args': args,
                            'e': e
                        },
                      instance=instance)
            raise exception.AgentError(method=method)

    if not isinstance(ret, dict):
        try:
            ret = jsonutils.loads(ret)
        except TypeError:
            LOG.error(_('The agent call to %(method)s returned an invalid '
                        'response: %(ret)r. args=%(args)r'), {
                            'method': method,
                            'ret': ret,
                            'args': args
                        },
                      instance=instance)
            raise exception.AgentError(method=method)

    if ret['returncode'] not in success_codes:
        LOG.error(_('The agent call to %(method)s returned an '
                    'an error: %(ret)r. args=%(args)r'), {
                        'method': method,
                        'ret': ret,
                        'args': args
                    },
                  instance=instance)
        raise exception.AgentError(method=method)

    LOG.debug(_('The agent call to %(method)s was successful: '
                '%(ret)r. args=%(args)r'), {
                    'method': method,
                    'ret': ret,
                    'args': args
                },
              instance=instance)

    # Some old versions of the Windows agent have a trailing \\r\\n
    # (ie CRLF escaped) for some reason. Strip that off.
    return ret['message'].replace('\\r\\n', '')