def shutdown(self, e=None): LOGGER.warning('Shut down!') if e: LOGGER.critical(e) try: for client in self.clients: client.shutdown() except Exception as e: LOGGER.error('Something went wrong while shutting down clients') LOGGER.error(e) try: if self.tcpdump_proc: self.tcpdump_proc.send_signal(signal.SIGINT) except Exception as e: LOGGER.error('Something went wrong while shutting down TCPDUMP') LOGGER.error(e) try: if self.backend_mgr: self.backend_mgr.shutdown() except Exception as e: LOGGER.error( 'Something went wrong while shutting down Docker containers') LOGGER.error(e)
def execute(self): server_socket = None error = None try: # first start docker instances self.backend_mgr.spawn_backends() with socket(AF_INET, SOCK_STREAM) as server_socket: server_socket.bind((self.host, self.port)) server_socket.listen(self.config.clients) server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) LOGGER.info('Listening on %s:%d', self.host, self.port) # accept N clients for the experiment LOGGER.info('Waiting for %d clients to connect...', self.config.clients) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # wait for all clients to connect for i in range(self.config.clients): conn, addr = server_socket.accept() set_keepalive_linux(conn, max_fails=100) # 5 minutes client = AsyncClient(conn, addr, self._gen_config_for_client(i)) self.clients.append(client) LOGGER.info('{} out of {} clients connected: {}:{}'.format( i + 1, self.config.clients, *addr)) # send config client.send_config() # wait for clients to finish sending configs for c in self.clients: c.wait_for_tasks() # send traces, two clients at the time LOGGER.info('Pushing step files to clients...') # grouper is a generator, so wrap it in a list chunks = list(grouper(self.clients, 2, fillvalue=NullClient())) # use list comprehensions to avoid laziness (map()) step_data = [ open(p, 'rb').read() for p in self.config.trace_steps ] step_chksums = [hashlib.md5(d).hexdigest() for d in step_data] steps = zip(itertools.count(start=1), step_chksums, step_data) for chunk, step in itertools.product(chunks, steps): for c in chunk: c.send_step(*step) for c in chunk: c.wait_for_tasks() # execute runs! for r in range(self.config.runs): self.__execute_run(r) except ShutdownException: pass except Exception as e: error = e finally: try: if server_socket: # server_socket.shutdown(SHUT_RDWR) server_socket.close() except Exception as e: LOGGER.critical('Error closing server socket.') LOGGER.critical(e) self.shutdown(e=error)