You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
4.8 KiB
142 lines
4.8 KiB
# Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Tester feedback delegate."""
|
|
|
|
import logging
|
|
import xmlrpclib
|
|
|
|
import common
|
|
from autotest_lib.client.common_lib.feedback import tester_feedback_client
|
|
|
|
import query_delegate
|
|
|
|
|
|
class FeedbackDelegate(object):
|
|
"""An object for managing feedback RPC calls."""
|
|
|
|
def __init__(self, multiplexer):
|
|
self._multiplexer = multiplexer
|
|
self._clients = {}
|
|
|
|
|
|
def _get_client(self, client_id):
|
|
"""Returns the query dictionary for a client.
|
|
|
|
@param client_id: The client identifier.
|
|
|
|
@return: A dictionary mapping registered query numbers to query delegate
|
|
objects for the given client.
|
|
|
|
@raise xmlrpclib.Fault: The client was not registered.
|
|
"""
|
|
if client_id not in self._clients:
|
|
raise xmlrpclib.Fault('Unknown client (%s)' % client_id)
|
|
return self._clients[client_id]
|
|
|
|
|
|
def _get_delegate_cls(self, query_id):
|
|
"""Returns a query delegate class for a given query type.
|
|
|
|
@param query_id: The query type for which a delegate is needed.
|
|
|
|
@return: A query delegate class.
|
|
|
|
@raise xmlrpclib.Fault: Query type is invalid or unsupported.
|
|
"""
|
|
try:
|
|
return query_delegate.get_delegate_cls(query_id)
|
|
except ValueError:
|
|
raise xmlrpclib.Fault('Unknown query type (%s)' % query_id)
|
|
except NotImplementedError:
|
|
raise xmlrpclib.Fault('Unsupported query type (%s)' % query_id)
|
|
|
|
|
|
def new_client(self, client_id):
|
|
"""Register a new client.
|
|
|
|
A client identifier is unique for a given test and DUT: at any given
|
|
time, there's only one test that is using this identifier. That said,
|
|
a client identifier may be reused across different tests at different
|
|
times within the lifetime of the feedback delegate. In general, clients
|
|
are expected to unregister when they finish running. However, for the
|
|
delegate to be resilient to test crashes, we forgo this requirement and
|
|
only emit a warning.
|
|
|
|
@param client_id: The client identifier.
|
|
|
|
@return: True (avoiding None with XML-RPC).
|
|
"""
|
|
if client_id in self._clients:
|
|
logging.warning('Overwriting existing client entry %s; prior '
|
|
'instance did not shutdown properly?', client_id)
|
|
self._clients[client_id] = {}
|
|
return True
|
|
|
|
|
|
def delete_client(self, client_id):
|
|
"""Unregister a client.
|
|
|
|
@param client_id: The client identifier.
|
|
|
|
@return: True (avoiding None with XML-RPC).
|
|
"""
|
|
del self._clients[client_id]
|
|
return True
|
|
|
|
|
|
def new_query(self, client_id, query_id, query_num):
|
|
"""Register a new query from a client.
|
|
|
|
@param client_id: The client identifier.
|
|
@param query_id: The query type.
|
|
@param query_num: The query's unique number.
|
|
|
|
@return: True (avoiding None with XML-RPC).
|
|
|
|
@raise xmlrpclib.Fault: The client or query arguments are invalid.
|
|
"""
|
|
client = self._get_client(client_id)
|
|
if query_num in client:
|
|
raise xmlrpclib.Fault('New query (%s) is already registered' %
|
|
query_num)
|
|
test_name, dut_name = client_id.split(':')
|
|
client[query_num] = self._get_delegate_cls(query_id)(
|
|
test_name, dut_name, self._multiplexer)
|
|
return True
|
|
|
|
|
|
def query_call(self, client_id, query_num, query_method, kwargs_dict):
|
|
"""Perform a query call.
|
|
|
|
@param client_id: The client identifier.
|
|
@param query_num: The query unique number.
|
|
@param query_method: The method being called.
|
|
@param kwargs_dict: Extra arguments being passed to the method call.
|
|
|
|
@return: A pair containing a method return code (constant defined in
|
|
tester_feedback_client) and a description of the result
|
|
(string).
|
|
|
|
@raise: xmlrpclib.Fault: Method execution failed.
|
|
"""
|
|
try:
|
|
query = self._get_client(client_id)[query_num]
|
|
except KeyError:
|
|
raise xmlrpclib.Fault('Query %d unknown to client %s' %
|
|
(query_num, client_id))
|
|
|
|
# Route the query call to the appropriate method.
|
|
local_method = getattr(query, query_method, None)
|
|
if local_method is None:
|
|
ret = (tester_feedback_client.QUERY_RET_ERROR,
|
|
'Unknown query method (%s)' % query_method)
|
|
else:
|
|
ret = local_method(**kwargs_dict)
|
|
|
|
# If there's an explicit result, return it; otherwise, return success.
|
|
if ret is None:
|
|
return tester_feedback_client.QUERY_RET_SUCCESS, ''
|
|
return ret
|