def test_set_admin_password_silently_fails(self, mock_exchange, mock_add_fault): error = exception.AgentTimeout(method="fake") mock_exchange.side_effect = error agent_inst = self._create_agent(None) agent_inst.set_admin_password("new_pass") mock_add_fault.assert_called_once_with(error, mock.ANY)
def _wait_for_new_dom_id(session, vm_ref, old_dom_id, method): expiration = time.time() + CONF.xenserver.agent_timeout while True: dom_id = session.VM.get_domid(vm_ref) if dom_id and dom_id != "-1" and dom_id != old_dom_id: LOG.debug("Found new dom_id %s", dom_id) return if time.time() > expiration: LOG.debug("Timed out waiting for new dom_id %s", dom_id) raise exception.AgentTimeout(method=method.__name__) time.sleep(1)
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', '')
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', '')