[libvirt] [test-API PATCH 0/3] Console tests

This series adds two tests that check interactions with the domain's console. As a helper the first patch contains a new exception that signalizes a test error other than raised by libvirt. The two tests are not contained in any test cases yet, as they require a specific VM configuration to work correctly. Peter Krempa (3): utils: Add exception for general test errors repo: Add test for mutualy exclusive console access repo: Add test for console input and output operations repos/domain/console_io.py | 76 +++++++++++++++++++++++++++++++++++ repos/domain/console_mutex.py | 89 +++++++++++++++++++++++++++++++++++++++++ utils/Python/testError.py | 26 ++++++++++++ 3 files changed, 191 insertions(+), 0 deletions(-) create mode 100644 repos/domain/console_io.py create mode 100644 repos/domain/console_mutex.py create mode 100644 utils/Python/testError.py -- 1.7.3.4

This helper exception helps with reporting test errors that don't produce a libvirt exception. Eg. comparison of returned and expected value fails although the api call succeeded. --- utils/Python/testError.py | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) create mode 100644 utils/Python/testError.py diff --git a/utils/Python/testError.py b/utils/Python/testError.py new file mode 100644 index 0000000..8e7c44f --- /dev/null +++ b/utils/Python/testError.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# +# libvirt-test-API is copyright 2010 Red Hat, Inc. +# +# libvirt-test-API is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. This program is distributed in +# the hope that it will be useful, but WITHOUT ANY WARRANTY; without +# even the implied warranties of TITLE, NON-INFRINGEMENT, +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# The GPL text is available in the file COPYING that accompanies this +# distribution and at <http://www.gnu.org/licenses>. +# +# Filename: testError.py +# Summary: internal test error exception +# Description: An exception to signalize test failures that are +# separate from libvirt errors + +class TestError(Exception): + def __init__(self, msg=""): + self.msg=msg + + def __str__(self): + return self.msg -- 1.7.3.4

On 04/03/2012 09:20 PM, Peter Krempa wrote:
This helper exception helps with reporting test errors that don't produce a libvirt exception. Eg. comparison of returned and expected value fails although the api call succeeded. --- utils/Python/testError.py | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) create mode 100644 utils/Python/testError.py
diff --git a/utils/Python/testError.py b/utils/Python/testError.py new file mode 100644 index 0000000..8e7c44f --- /dev/null +++ b/utils/Python/testError.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# +# libvirt-test-API is copyright 2010 Red Hat, Inc. +# +# libvirt-test-API is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. This program is distributed in +# the hope that it will be useful, but WITHOUT ANY WARRANTY; without +# even the implied warranties of TITLE, NON-INFRINGEMENT, +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# The GPL text is available in the file COPYING that accompanies this +# distribution and at<http://www.gnu.org/licenses>. +# +# Filename: testError.py +# Summary: internal test error exception +# Description: An exception to signalize test failures that are +# separate from libvirt errors + +class TestError(Exception): + def __init__(self, msg=""): + self.msg=msg + + def __str__(self): + return self.msg
In testcases, return 0 on success, return 1 on failure, raise exception means something unexpected happened. If you want to tell failure of testing, the return value 1 is enough. There is a file named exception.py in the root of test-API, If we want to raise an exception to express unexpected failure of running testcases from the framework's point of view. We could add the TestError as a sublcass in it(or remove redundant error codes in it). Guannan Ren

This test case checks if the console connection code works in a safe way that the connection don't get messed up. --- repos/domain/console_mutex.py | 89 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 89 insertions(+), 0 deletions(-) create mode 100644 repos/domain/console_mutex.py diff --git a/repos/domain/console_mutex.py b/repos/domain/console_mutex.py new file mode 100644 index 0000000..f9df815 --- /dev/null +++ b/repos/domain/console_mutex.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +""" A test case to test console mutual exclusivity + mandatory arguments: guestname +""" +import libvirt +from libvirt import libvirtError + +from utils.Python import utils +from utils.Python.testError import TestError + +def usage(params): + """Verify parameter dictionary""" + logger = params['logger'] + keys = ['guestname'] + for key in keys: + if key not in params: + logger.error("%s is required" %key) + return 1 + +def console_mutex(params): + """Attach to console""" + logger = params['logger'] + guest = params['guestname'] + if "device" not in params: + device = "serial0" + else: + device = params['device'] + + util = utils.Utils() + uri = params['uri'] + + ret = 1 + + try: + logger.info("Connecting to hypervisor: " + uri) + conn = libvirt.open(uri) + dom = conn.lookupByName(guest) + + logger.info("Creating stream object") + stream = conn.newStream(0) + + logger.info("Forcibly open console on domain") + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE); + + logger.info("Creating another stream object") + stream2 = conn.newStream(0) + + logger.info("Open safe console connection while an existing one is open"); + failed = False + try: + dom.openConsole(device, stream2, libvirt.VIR_DOMAIN_CONSOLE_SAFE); + except libvirtError, e: + logger.info("Opening failed - OK") + failed = True + + if not failed: + raise TestError("Opening of console succeeded although shoud fail") + + logger.info("Abort the existing stream") + stream.abort() + + logger.info("Re-try connecting to the console") + dom.openConsole(device, stream2, libvirt.VIR_DOMAIN_CONSOLE_SAFE); + + logger.info("Re-try forcibly on already open console") + + logger.info("Creating stream object") + stream = conn.newStream(0) + + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE); + + except libvirtError, e: + logger.error("Libvirt call failed") + raise e; + + except TestError, e: + logger.error("Test failed: " + str(e)); + + else: + logger.info("All tests succeeded") + ret = 0 + + finally: + logger.info("Closing hypervisor connection") + conn.close() + + logger.info("Done") + + return ret -- 1.7.3.4

On 04/03/2012 09:20 PM, Peter Krempa wrote:
This test case checks if the console connection code works in a safe way that the connection don't get messed up. --- repos/domain/console_mutex.py | 89 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 89 insertions(+), 0 deletions(-) create mode 100644 repos/domain/console_mutex.py
diff --git a/repos/domain/console_mutex.py b/repos/domain/console_mutex.py new file mode 100644 index 0000000..f9df815 --- /dev/null +++ b/repos/domain/console_mutex.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +""" A test case to test console mutual exclusivity + mandatory arguments: guestname +""" +import libvirt +from libvirt import libvirtError + +from utils.Python import utils +from utils.Python.testError import TestError
we could just use logger.error(), then close hypervisor connection, then quit.
+ +def usage(params): + """Verify parameter dictionary""" + logger = params['logger'] + keys = ['guestname'] + for key in keys: + if key not in params: + logger.error("%s is required" %key) + return 1 + +def console_mutex(params): + """Attach to console""" + logger = params['logger']
call usage() to check for mandatory options
+ guest = params['guestname'] + if "device" not in params: + device = "serial0" + else: + device = params['device']
It's ok here, guest = params.get('device', 'serial0') get better.
+ + util = utils.Utils() + uri = params['uri'] + + ret = 1 + + try: + logger.info("Connecting to hypervisor: " + uri) + conn = libvirt.open(uri) + dom = conn.lookupByName(guest) + + logger.info("Creating stream object") + stream = conn.newStream(0) + + logger.info("Forcibly open console on domain") + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE); + + logger.info("Creating another stream object") + stream2 = conn.newStream(0) + + logger.info("Open safe console connection while an existing one is open");
the semicolon is optional. and same for the following appearance.
+ failed = False + try: + dom.openConsole(device, stream2, libvirt.VIR_DOMAIN_CONSOLE_SAFE); + except libvirtError, e: + logger.info("Opening failed - OK") + failed = True + + if not failed: + raise TestError("Opening of console succeeded although shoud fail") + + logger.info("Abort the existing stream") + stream.abort() + + logger.info("Re-try connecting to the console") + dom.openConsole(device, stream2, libvirt.VIR_DOMAIN_CONSOLE_SAFE); + + logger.info("Re-try forcibly on already open console") + + logger.info("Creating stream object") + stream = conn.newStream(0) + + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE); + + except libvirtError, e: + logger.error("Libvirt call failed") + raise e; + + except TestError, e: + logger.error("Test failed: " + str(e)); + + else: + logger.info("All tests succeeded") + ret = 0 + + finally: + logger.info("Closing hypervisor connection") + conn.close()
I really not sure about the stream, if we need to call stream.abort() in finally to close the certain FD at server part.
+ + logger.info("Done") + + return ret
The clean function is necessary for testcases. So we need to add another function named 'console_mutex_clean' to cleanup the testing environment messed by the testcase. The params is same as main function. If nothing need to clean, just write like this. def console_mutex_clean(params): """clean testing environment""" pass Guannan Ren

On 04/04/2012 08:32 AM, Guannan Ren wrote:
On 04/03/2012 09:20 PM, Peter Krempa wrote:
This test case checks if the console connection code works in a safe way that the connection don't get messed up. --- sure about the stream, if we need to call stream.abort() in finally to close the certain FD at server part.
+ + logger.info("Done") + + return ret
The clean function is necessary for testcases. So we need to add another function named 'console_mutex_clean' to cleanup the testing environment messed by the testcase. The params is same as main function. If nothing need to clean, just write like this.
def console_mutex_clean(params): """clean testing environment""" pass
Hm, this looks like a vast majority of the tests will not do anything in such an method. Wouldn't it be better in this case to make the tests as sublcasses of a new test class and when writing a test, the user would only need to override methods that he wishes to use?
Guannan Ren
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

This test checks if the console input and output work as desired. The test takes as an argument a string, that is sent to the console and another string that is expected to be read from the console. When those two compare successfuly the test succeeds. --- repos/domain/console_io.py | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 repos/domain/console_io.py diff --git a/repos/domain/console_io.py b/repos/domain/console_io.py new file mode 100644 index 0000000..6af206a --- /dev/null +++ b/repos/domain/console_io.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +""" A test case to test console mutual exclusivity + mandatory arguments: guestname + device + data + expect +""" +import libvirt +from libvirt import libvirtError + +from utils.Python import utils +from utils.Python.testError import TestError + +def usage(params): + """Verify parameter dictionary""" + logger = params['logger'] + keys = ['guestname', 'device', 'data', 'expect'] + for key in keys: + if key not in params: + logger.error("%s is required" %key) + return 1 + +def console_io(params): + """Attach to console""" + logger = params['logger'] + guest = params['guestname'] + device = params['device'] + data = params['data'] + expect = params['expect'] + + util = utils.Utils() + uri = params['uri'] + reply = "" + + ret = 1 + + try: + logger.info("Connecting to hypervisor: " + uri) + conn = libvirt.open(uri) + dom = conn.lookupByName(guest) + + logger.info("Creating stream object") + stream = conn.newStream(0) + + logger.info("Forcibly open console on domain") + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE); + + logger.info("Sending data: '" + data + "'") + stream.send(data) + + while len(reply) < len(expect): + recv = stream.recv(10); + reply += recv + logger.info("Recieved data: '" + recv + "'") + + if expect != reply: + raise TestError("Recieved data don't match expected string") + + except libvirtError, e: + logger.error("Libvirt call failed") + raise e; + + except TestError, e: + logger.error("Test failed: " + str(e)); + + else: + logger.info("All tests succeeded") + ret = 0 + + finally: + logger.info("Closing hypervisor connection") + conn.close() + + logger.info("Done") + + return ret -- 1.7.3.4

On 04/03/2012 09:20 PM, Peter Krempa wrote:
This test checks if the console input and output work as desired. The test takes as an argument a string, that is sent to the console and another string that is expected to be read from the console. When those two compare successfuly the test succeeds. --- repos/domain/console_io.py | 76 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 76 insertions(+), 0 deletions(-) create mode 100644 repos/domain/console_io.py
diff --git a/repos/domain/console_io.py b/repos/domain/console_io.py new file mode 100644 index 0000000..6af206a --- /dev/null +++ b/repos/domain/console_io.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +""" A test case to test console mutual exclusivity + mandatory arguments: guestname + device + data + expect +""" +import libvirt +from libvirt import libvirtError + +from utils.Python import utils +from utils.Python.testError import TestError
It'd better to raise 'TestError' exception from framework because of unexpected environment error, or something common for all of tests.
+ +def usage(params): + """Verify parameter dictionary""" + logger = params['logger'] + keys = ['guestname', 'device', 'data', 'expect'] + for key in keys: + if key not in params: + logger.error("%s is required" %key) + return 1 + +def console_io(params): + """Attach to console"""
call usage() here to check for mandatory options and values.
+ logger = params['logger'] + guest = params['guestname'] + device = params['device'] + data = params['data'] + expect = params['expect'] + + util = utils.Utils() + uri = params['uri'] + reply = "" + + ret = 1 + + try: + logger.info("Connecting to hypervisor: " + uri) + conn = libvirt.open(uri) + dom = conn.lookupByName(guest) + + logger.info("Creating stream object") + stream = conn.newStream(0) + + logger.info("Forcibly open console on domain") + dom.openConsole(device, stream, libvirt.VIR_DOMAIN_CONSOLE_FORCE);
the semicolon and the following are optional.
+ + logger.info("Sending data: '" + data + "'") + stream.send(data) + + while len(reply)< len(expect): + recv = stream.recv(10); + reply += recv + logger.info("Recieved data: '" + recv + "'") + + if expect != reply: + raise TestError("Recieved data don't match expected string") + + except libvirtError, e: + logger.error("Libvirt call failed") + raise e; + + except TestError, e: + logger.error("Test failed: " + str(e));
logger.error is enough I think.
+ + else: + logger.info("All tests succeeded") + ret = 0 + + finally: + logger.info("Closing hypervisor connection") + conn.close() + + logger.info("Done") + + return ret
we need a console_io_clean(params) function for use by clean flag in testcase config BTW, I tried the testcase, but don't know how to offer the options to let it run successful It always hang up, could you give a detailed comments. Guannan Ren
participants (2)
-
Guannan Ren
-
Peter Krempa