From 2aaf83ee88b49e3a10543f8415f73652be606ecc Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Sun, 5 Jun 2016 17:35:12 +0300 Subject: singleton_daemon:verify RPC connectivity, shutdown the socket for immediate close --- .../trex_control_plane/server/singleton_daemon.py | 40 +++++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) (limited to 'scripts/automation/trex_control_plane/server') diff --git a/scripts/automation/trex_control_plane/server/singleton_daemon.py b/scripts/automation/trex_control_plane/server/singleton_daemon.py index 7cfbc3bc..81b384c5 100755 --- a/scripts/automation/trex_control_plane/server/singleton_daemon.py +++ b/scripts/automation/trex_control_plane/server/singleton_daemon.py @@ -6,6 +6,8 @@ import tempfile import types from subprocess import Popen from time import sleep +import outer_packages +import jsonrpclib # uses Unix sockets for determine running process. # (assumes used daemons will register proper socket) @@ -28,14 +30,14 @@ class SingletonDaemon(object): # returns True if daemon is running def is_running(self): - lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) try: - lock_socket.bind('\0' + self.tag) # the check is ~200000 faster and more reliable than checking via 'netstat' or 'ps' etc. + lock_socket = register_socket(self.tag) # the check is ~200000 faster and more reliable than checking via 'netstat' or 'ps' etc. + lock_socket.shutdown(socket.SHUT_RDWR) lock_socket.close() except socket.error: # Unix socket in use return True # Unix socket is not used, but maybe it's old version of daemon not using socket - return bool(self.get_pid()) + return bool(self.get_pid_by_listening_port()) # get pid of running daemon by registered Unix socket (most robust way) @@ -73,7 +75,7 @@ class SingletonDaemon(object): # kill daemon - def kill(self, timeout = 5): + def kill(self, timeout = 10): pid = self.get_pid() if not pid: return False @@ -88,17 +90,32 @@ class SingletonDaemon(object): ret_code, stdout, stderr = run_command('kill -9 %s' % pid) # unconditional kill if ret_code: raise Exception('Failed to run kill -9 command for %s: %s' % (self.name, [ret_code, stdout, stderr])) - poll_rate = 0.1 - for i in range(inr(timeout / poll_rate)): + for i in range(int(timeout / poll_rate)): if not self.is_running(): return True sleep(poll_rate) raise Exception('Could not kill %s, even with -9' % self.name) + # try connection as RPC client, return True upon success, False if fail + def check_connectivity(self, timeout = 5): + daemon = jsonrpclib.Server('http://127.0.0.1:%s/' % self.port) + poll_rate = 0.1 + for i in range(int(timeout/poll_rate)): + try: + daemon.not_existing_function_asdfasd() + except socket.error: # daemon is not up yet + sleep(poll_rate) + except Exception as e: # expect error of not supported function + if type(e.args) is tuple and\ + type(e.args[0]) is tuple and\ + e.args[0][0] == -32601: # error code is written hardcoded in JsonRPC Server + return True + raise + return False # start daemon # returns True if success, False if already running - def start(self, timeout = 5): + def start(self, timeout = 20): if self.is_running(): raise Exception('%s is already running' % self.name) if not self.run_cmd: @@ -112,6 +129,8 @@ class SingletonDaemon(object): if timeout > 0: poll_rate = 0.1 for i in range(int(timeout/poll_rate)): + if self.is_running(): + break sleep(poll_rate) if bool(proc.poll()): # process ended with error stdout_file.seek(0) @@ -120,7 +139,9 @@ class SingletonDaemon(object): elif proc.poll() == 0: # process runs other process, and ended break if self.is_running(): - return True + if self.check_connectivity(): + return True + raise Exception('Daemon process is running, but no connectivity') raise Exception('%s failed to run.' % self.name) # restart the daemon @@ -136,8 +157,9 @@ def register_socket(tag): lock_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) try: lock_socket.bind('\0%s' % tag) + return lock_socket except socket.error: - raise Exception('Error: process with tag %s is already running.' % tag) + raise socket.error('Error: process with tag %s is already running.' % tag) # runs command def run_command(command, timeout = 15, cwd = None): -- cgit 1.2.3-korg