From: Ondrej Lichtner olichtne@redhat.com
Several Common modules had this typo for a long time without anyone noticing.
Reported-by: Jan Tluka jtluka@redhat.com Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Common/Config.py | 2 +- lnst/Common/GitVersion.py | 2 +- lnst/Common/LoggingHandler.py | 2 +- lnst/Common/Logs.py | 2 +- lnst/Common/ProcessManager.py | 4 ++-- lnst/Common/ShellProcess.py | 2 +- lnst/Common/Utils.py | 2 +- lnst/Common/Version.py | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/lnst/Common/Config.py b/lnst/Common/Config.py index 2edf854..c2044f7 100644 --- a/lnst/Common/Config.py +++ b/lnst/Common/Config.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/GitVersion.py b/lnst/Common/GitVersion.py index b24962a..fe088a2 100644 --- a/lnst/Common/GitVersion.py +++ b/lnst/Common/GitVersion.py @@ -8,7 +8,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/LoggingHandler.py b/lnst/Common/LoggingHandler.py index a236922..e2a5dff 100644 --- a/lnst/Common/LoggingHandler.py +++ b/lnst/Common/LoggingHandler.py @@ -10,7 +10,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py index 36e0580..06c8217 100644 --- a/lnst/Common/Logs.py +++ b/lnst/Common/Logs.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import os, sys, shutil diff --git a/lnst/Common/ProcessManager.py b/lnst/Common/ProcessManager.py index 1995d15..8c5f2e7 100644 --- a/lnst/Common/ProcessManager.py +++ b/lnst/Common/ProcessManager.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import os, signal, thread, logging @@ -91,4 +91,4 @@ lock.acquire() if os.waitpid != ProcessManager.waitpid: ProcessManager.std_waitpid = os.waitpid os.waitpid = ProcessManager.waitpid -lock.release() \ No newline at end of file +lock.release() diff --git a/lnst/Common/ShellProcess.py b/lnst/Common/ShellProcess.py index 58c4bd1..74c1c14 100644 --- a/lnst/Common/ShellProcess.py +++ b/lnst/Common/ShellProcess.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import pty, os, termios, time, signal, re, select diff --git a/lnst/Common/Utils.py b/lnst/Common/Utils.py index 93e9560..0a903be 100644 --- a/lnst/Common/Utils.py +++ b/lnst/Common/Utils.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import functools diff --git a/lnst/Common/Version.py b/lnst/Common/Version.py index b2da2d2..c7bacfd 100644 --- a/lnst/Common/Version.py +++ b/lnst/Common/Version.py @@ -7,7 +7,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
From: Ondrej Lichtner olichtne@redhat.com
Instead of just adding the list of hosts to be accessed from the recipe we add the controller so that we can also call some generic methods, e.g. waiting for a condition.
This also changes the .matched attribute to a property that accesses the appropriate attribute of the Controller object.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Controller/Controller.py | 4 ++-- lnst/Controller/Recipe.py | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/lnst/Controller/Controller.py b/lnst/Controller/Controller.py index 13e7fd8..3415f63 100644 --- a/lnst/Controller/Controller.py +++ b/lnst/Controller/Controller.py @@ -104,6 +104,8 @@ class Controller(object): if not isinstance(recipe, BaseRecipe): raise ControllerError("recipe argument must be a BaseRecipe instance.")
+ recipe._set_ctl(self) + req = recipe.req
self._mapper.set_pools(self._pools.get_pools()) @@ -118,14 +120,12 @@ class Controller(object): self._print_match_description(match) try: self._map_match(match, req) - recipe._set_hosts(self._hosts) recipe.test() except Exception as exc: logging.error("Recipe execution terminated by unexpected exception") log_exc_traceback() raise finally: - recipe._set_hosts(None) self._cleanup_slaves()
def _map_match(self, match, requested): diff --git a/lnst/Controller/Recipe.py b/lnst/Controller/Recipe.py index 39917b3..9380a35 100644 --- a/lnst/Controller/Recipe.py +++ b/lnst/Controller/Recipe.py @@ -80,7 +80,7 @@ class BaseRecipe(object): Next, the copied objects are loaded with values from kwargs and checked if mandatory Parameters have values. """ - self.matched = None + self._ctl = None self.req = _Requirements() self.params = Parameters() for attr in dir(self): @@ -105,8 +105,18 @@ class BaseRecipe(object): for key in kwargs.keys(): raise RecipeError("Unknown parameter {}".format(key))
- def _set_hosts(self, hosts): - self.matched = hosts + @property + def ctl(self): + return self._ctl + + @property + def matched(self): + if self.ctl is None: + return None + return self.ctl._hosts + + def _set_ctl(self, ctl): + self._ctl = ctl
def test(self): """Method to be implemented by the Tester"""
From: Ondrej Lichtner olichtne@redhat.com
The new wait_for_condition method is based on the older wait_for_finish, that passively waited for socket messages and looked for a job_finish message. The new method instead waits for socket messages for one second in a loop, on each iteration we call a provided condition method that MUST return a boolean and stop the wait when the return value is True (condition matched).
The old wait_for_finish method was renamed to wait_for_job_finish that now just calls the wait_for_condition method with a condition method that checks the Job.finished property.
Finally this patch merges the wait_for_result method with the send_message method, as every rpc message is expected to receive a result from the remote message call.
Commit also includes some updates to the Machine class replacing calls the old methods with the new ones.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Controller/Machine.py | 17 +++++++++------- lnst/Controller/MessageDispatcher.py | 39 +++++++++++++++++++----------------- 2 files changed, 31 insertions(+), 25 deletions(-)
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py index 7730d79..cd14f78 100644 --- a/lnst/Controller/Machine.py +++ b/lnst/Controller/Machine.py @@ -189,10 +189,7 @@ class Machine(object): "args": args, "kwargs": kwargs}
- self._msg_dispatcher.send_message(self, msg) - result = self._msg_dispatcher.wait_for_result(self) - - return result + return self._msg_dispatcher.send_message(self, msg)
def _init_connection(self): """ Initialize the slave connection @@ -382,7 +379,11 @@ class Machine(object): elif timeout == 0: logging.info("Waiting for Job %d on Host %s." % (job.id, self._id)) - result = self._msg_dispatcher.wait_for_finish(self, job.id) + + def condition(): + return job.finished + + self._msg_dispatcher.wait_for_condition(condition) except MachineError as exc: logging.error(str(exc)) res = False @@ -405,8 +406,10 @@ class Machine(object): logging.info("Waiting for Device creation on Host %s." % (self._id))
- while len(self._tmp_device_database) > 0: - result = self._msg_dispatcher.handle_messages() + def condition(): + return len(self._tmp_device_database) <= 0 + + self._msg_dispatcher.wait_for_condition(condition) except MachineError as exc: logging.error(str(exc)) res = False diff --git a/lnst/Controller/MessageDispatcher.py b/lnst/Controller/MessageDispatcher.py index 10b712a..abd3b21 100644 --- a/lnst/Controller/MessageDispatcher.py +++ b/lnst/Controller/MessageDispatcher.py @@ -93,18 +93,14 @@ class MessageDispatcher(ConnectionHandler):
def send_message(self, machine, data): soc = self.get_connection(machine) - - if data["type"] == "command": - data["args"] = remote_device_to_deviceref(data["args"]) - data["kwargs"] = remote_device_to_deviceref(data["kwargs"]) + data = remote_device_to_deviceref(data)
if send_data(soc, data) == False: msg = "Connection error from slave %s" % machine.get_id() raise ConnectionError(msg)
- def wait_for_result(self, machine): - wait = True - while wait: + result = None + while True: connected_slaves = self._connection_mapping.keys()
messages = self.check_connections() @@ -113,12 +109,11 @@ class MessageDispatcher(ConnectionHandler):
for msg in messages: if msg[1]["type"] == "result" and msg[0] == machine: - wait = False - result = msg[1]["result"] - - machine = self._machines[machine] - result = deviceref_to_remote_device(machine, - result) + if result is not None: + msg = ("Multiple result messages from the same slave " + "'{}'".format(machine.get_id())) + raise ConnectionError(msg) + result = msg[1] else: self._process_message(msg)
@@ -129,21 +124,29 @@ class MessageDispatcher(ConnectionHandler): " disconnected from the controller." raise ConnectionError(msg)
- return result + if result is not None: + return deviceref_to_remote_device(machine, result["result"])
- def wait_for_finish(self, machine, job_id): + def wait_for_job_finish(self, job): + def condition_check(): + return job.finished + self.wait_for_condition(condition_check) + return True + + def wait_for_condition(self, condition_check): wait = True while wait: connected_slaves = self._connection_mapping.keys()
- messages = self.check_connections() + messages = self.check_connections(timeout=1)
remaining_slaves = self._connection_mapping.keys()
for msg in messages: self._process_message(msg) - if msg[1]["type"] == "job_finished" and msg[0] == machine: - wait = False + wait = wait and not condition_check() + + wait = wait and not condition_check()
if connected_slaves != remaining_slaves: disconnected_slaves = set(connected_slaves) -\
From: Ondrej Lichtner olichtne@redhat.com
The wait method implements the old "wait for x seconds" functionality we've had in the old LNST. The method is exported to the tester/recipe throught the Controller class and uses the newly implemented wait_for_condition MessageDispatched method.
This implementation is an improvement compared to the older functionality as the Controller is still receiving and processing messages from slaves so conditions can wait for a specific update to the state of a slave and logging will still work during while we're waiting.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Controller/Controller.py | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/lnst/Controller/Controller.py b/lnst/Controller/Controller.py index 3415f63..0d30026 100644 --- a/lnst/Controller/Controller.py +++ b/lnst/Controller/Controller.py @@ -14,6 +14,7 @@ olichtne@redhat.com (Ondrej Lichtner)
import os import sys +import time import datetime import logging from lnst.Common.Logs import LoggingCtl, log_exc_traceback @@ -128,6 +129,17 @@ class Controller(object): finally: self._cleanup_slaves()
+ def wait(self, sec): + finish_time = time.time() + sec + logging.info("Suspending recipe execution for {} seconds, " + "messages from slaves will still be processed.". + format(sec)) + + def condition(): + return time.time() > finish_time + + self._msg_dispatcher.wait_for_condition(condition) + def _map_match(self, match, requested): self._machines = {} self._hosts = Hosts()
From: Ondrej Lichtner olichtne@redhat.com
When recipe execution fails before slaves are fully initialized the Controller calls cleanup and attempts to call the destroy_devices method on the slaves. If this happens before the InterfaceManager is created the call would crash the lnst-slave application. This commit fixes that.
Signed-off-by: Ondrej Lichtner olichtne@redhat.com --- lnst/Slave/NetTestSlave.py | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py index 9c5486c..795ec1d 100644 --- a/lnst/Slave/NetTestSlave.py +++ b/lnst/Slave/NetTestSlave.py @@ -234,6 +234,9 @@ class SlaveMethods: return matched
def destroy_devices(self): + if self._if_manager is None: + return + devices = self._if_manager.get_devices() for dev in devices: try:
On Fri, Jan 05, 2018 at 02:56:58PM +0100, olichtne@redhat.com wrote:
From: Ondrej Lichtner olichtne@redhat.com
Several Common modules had this typo for a long time without anyone noticing.
Reported-by: Jan Tluka jtluka@redhat.com Signed-off-by: Ondrej Lichtner olichtne@redhat.com
lnst/Common/Config.py | 2 +- lnst/Common/GitVersion.py | 2 +- lnst/Common/LoggingHandler.py | 2 +- lnst/Common/Logs.py | 2 +- lnst/Common/ProcessManager.py | 4 ++-- lnst/Common/ShellProcess.py | 2 +- lnst/Common/Utils.py | 2 +- lnst/Common/Version.py | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/lnst/Common/Config.py b/lnst/Common/Config.py index 2edf854..c2044f7 100644 --- a/lnst/Common/Config.py +++ b/lnst/Common/Config.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/GitVersion.py b/lnst/Common/GitVersion.py index b24962a..fe088a2 100644 --- a/lnst/Common/GitVersion.py +++ b/lnst/Common/GitVersion.py @@ -8,7 +8,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/LoggingHandler.py b/lnst/Common/LoggingHandler.py index a236922..e2a5dff 100644 --- a/lnst/Common/LoggingHandler.py +++ b/lnst/Common/LoggingHandler.py @@ -10,7 +10,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
diff --git a/lnst/Common/Logs.py b/lnst/Common/Logs.py index 36e0580..06c8217 100644 --- a/lnst/Common/Logs.py +++ b/lnst/Common/Logs.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import os, sys, shutil diff --git a/lnst/Common/ProcessManager.py b/lnst/Common/ProcessManager.py index 1995d15..8c5f2e7 100644 --- a/lnst/Common/ProcessManager.py +++ b/lnst/Common/ProcessManager.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import os, signal, thread, logging @@ -91,4 +91,4 @@ lock.acquire() if os.waitpid != ProcessManager.waitpid: ProcessManager.std_waitpid = os.waitpid os.waitpid = ProcessManager.waitpid -lock.release() \ No newline at end of file +lock.release() diff --git a/lnst/Common/ShellProcess.py b/lnst/Common/ShellProcess.py index 58c4bd1..74c1c14 100644 --- a/lnst/Common/ShellProcess.py +++ b/lnst/Common/ShellProcess.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import pty, os, termios, time, signal, re, select diff --git a/lnst/Common/Utils.py b/lnst/Common/Utils.py index 93e9560..0a903be 100644 --- a/lnst/Common/Utils.py +++ b/lnst/Common/Utils.py @@ -6,7 +6,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ jzupka@redhat.com (Jiri Zupka) """ import functools diff --git a/lnst/Common/Version.py b/lnst/Common/Version.py index b2da2d2..c7bacfd 100644 --- a/lnst/Common/Version.py +++ b/lnst/Common/Version.py @@ -7,7 +7,7 @@ Licensed under the GNU General Public License, version 2 as published by the Free Software Foundation; see COPYING for details. """
-__autor__ = """ +__author__ = """ olichtne@redhat.com (Ondrej Lichtner) """
-- 2.15.1
pushed
-Ondrej
lnst-developers@lists.fedorahosted.org