提交 a0010a6c 编写于 作者: L Lucas Meneghel Rodrigues

Merge pull request #232 from lmr/remote-changes-sprint14

avocado.utils.remote: Changes to the .run() method
......@@ -72,13 +72,13 @@ class VMTestRunner(TestRunner):
urls = urls.split()
avocado_cmd = ('cd %s; avocado run --force-job-id %s --json - --archive %s' %
(self.remote_test_dir, self.result.stream.job_unique_id, " ".join(urls)))
stdout = self.result.vm.remote.run(avocado_cmd)
result = self.result.vm.remote.run(avocado_cmd, ignore_status=True)
try:
results = json.loads(stdout)
results = json.loads(result.stdout)
except Exception, details:
raise ValueError('Error loading JSON '
'(full output below): %s\n"""\n%s\n"""' %
(details, stdout))
(details, result.stdout))
return results
def run(self, params_list):
......
......@@ -430,6 +430,9 @@ class Test(unittest.TestCase):
log_exc_info(sys.exc_info())
cleanup_exception = details
whiteboard_file = os.path.join(self.logdir, 'whiteboard')
io.write_file(whiteboard_file, self.whiteboard)
if self.job is not None:
job_standalone = self.job.args is None
no_record_mode = (not job_standalone and
......
......@@ -18,6 +18,7 @@ Module to provide remote operations.
import getpass
import logging
import time
log = logging.getLogger('avocado.test')
......@@ -30,6 +31,10 @@ except ImportError:
else:
remote_capable = True
from avocado.core import output
from avocado.core import exceptions
from avocado.utils import process
class Remote(object):
......@@ -38,7 +43,7 @@ class Remote(object):
"""
def __init__(self, hostname, username=None, password=None,
port=22, timeout=60, attempts=3, quiet=True):
port=22, timeout=60, attempts=3, quiet=False):
"""
Creates an instance of :class:`Remote`.
......@@ -62,23 +67,45 @@ class Remote(object):
password=password,
port=port,
connection_timeout=timeout,
connection_attempts=attempts)
connection_attempts=attempts,
linewise=True)
def _setup_environment(self, **kwargs):
fabric.api.env.update(kwargs)
def run(self, command):
def run(self, command, ignore_status=False):
"""
Run a remote command.
:param command: the command string to execute.
:return: the result of the remote program's output.
:rtype: :class:`fabric.operations._AttributeString`.
:rtype: :class:`avocado.utils.process.CmdResult`.
"""
return fabric.operations.run(command,
quiet=self.quiet,
warn_only=True)
if not self.quiet:
log.info('[%s] Running command %s', self.hostname, command)
result = process.CmdResult()
stdout = output.LoggingFile(logger=logging.getLogger('avocado.test'))
stderr = output.LoggingFile(logger=logging.getLogger('avocado.test'))
start_time = time.time()
fabric_result = fabric.operations.run(command=command,
quiet=self.quiet,
stdout=stdout,
stderr=stderr,
warn_only=True)
end_time = time.time()
duration = end_time - start_time
result.command = command
result.stdout = str(fabric_result)
result.stderr = fabric_result.stderr
result.duration = duration
result.exit_status = fabric_result.return_code
result.failed = fabric_result.failed
result.succeeded = fabric_result.succeeded
if not ignore_status:
if result.failed:
raise exceptions.CmdError(command=command, result=result)
return result
def uptime(self):
"""
......@@ -86,8 +113,8 @@ class Remote(object):
:return: the uptime string or empty string if fails.
"""
res = self.run('uptime')
if res.succeeded:
res = self.run('uptime', ignore_status=True)
if res.exit_status == 0:
return res
else:
return ''
......@@ -107,6 +134,9 @@ class Remote(object):
:param local_path: the local path.
:param remote_path: the remote path.
"""
if not self.quiet:
log.info('[%s] Receive remote files %s -> %s', self.hostname,
local_path, remote_path)
with fabric.context_managers.quiet():
try:
fabric.operations.put(local_path,
......@@ -122,6 +152,9 @@ class Remote(object):
:param local_path: the local path.
:param remote_path: the remote path.
"""
if not self.quiet:
log.info('[%s] Receive remote files %s -> %s', self.hostname,
local_path, remote_path)
with fabric.context_managers.quiet():
try:
fabric.operations.get(remote_path,
......
......@@ -272,7 +272,8 @@ class VM(object):
:param password: the password.
"""
if not self.logged:
self.remote = remote.Remote(hostname, username, password)
self.remote = remote.Remote(hostname, username, password,
quiet=True)
res = self.remote.uptime()
if res.succeeded:
self.logged = True
......
......@@ -72,7 +72,11 @@ sleep length to be used by some other script or data analysis tool::
self.whiteboard = "%.2f" % self.params.sleep_length
The whiteboard can and should be exposed by files generated by the available test result
plugins. The `results.json` file already includes the whiteboard for each test.
plugins. The ``results.json`` file already includes the whiteboard for each test.
Additionally, we'll save a raw copy of the whiteboard contents on a file named
``whiteboard``, in the same level as the ``results.json`` file, for your convenience
(maybe you want to use the result of a benchmark directly with your custom made scripts
to analyze that particular benchmark result).
Accessing test parameters
=========================
......
......@@ -214,6 +214,29 @@ class OutputPluginTest(unittest.TestCase):
debug_log = second_line.split()[-1]
self.check_output_files(debug_log)
def test_verify_whiteboard_save(self):
tmpfile = tempfile.mktemp()
try:
os.chdir(basedir)
cmd_line = './scripts/avocado run whiteboard --json %s' % tmpfile
result = process.run(cmd_line, ignore_status=True)
expected_rc = 0
self.assertEqual(result.exit_status, expected_rc,
"Avocado did not return rc %d:\n%s" %
(expected_rc, result))
with open(tmpfile, 'r') as fp:
json_results = json.load(fp)
debug_log = json_results['debuglog']
debug_dir = os.path.dirname(debug_log)
test_result_dir = os.path.join(debug_dir, 'test-results', 'whiteboard.py')
whiteboard_path = os.path.join(test_result_dir, 'whiteboard')
self.assertTrue(os.path.exists(whiteboard_path),
'Missing whiteboard file %s' % whiteboard_path)
finally:
try:
os.remove(tmpfile)
except OSError:
pass
if __name__ == '__main__':
unittest.main()
......@@ -36,6 +36,7 @@ class AvocadoPass(test.Test):
def action(self):
variable = True
self.assertTrue(variable)
self.whiteboard = 'foo'
@unittest.skip("This class should not be tested per se")
......@@ -91,6 +92,13 @@ class TestClassTest(unittest.TestCase):
def testClassAttributesTaggedName(self):
self.assertEqual(self.tst_instance_pass.tagged_name, "AvocadoPass")
def testWhiteboardSave(self):
whiteboard_file = os.path.join(self.tst_instance_pass.logdir, 'whiteboard')
self.assertTrue(os.path.isfile(whiteboard_file))
with open(whiteboard_file, 'r') as whiteboard_file_obj:
whiteboard_contents = whiteboard_file_obj.read().strip()
self.assertTrue(whiteboard_contents, 'foo')
def testTaggedNameNewTests(self):
"""
New test instances should have crescent tag instances.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册