def __init__(self, exec_path, nodeid, bind_ip, webuiport, comport, masterip=None, masterport=None): self.ismaster = True self.exec_path = exec_path self.nodeid = nodeid self.bindip = bind_ip self.webuiport = webuiport self.comport = comport self.masterip = masterip self.masterport = masterport self.user_appdata_directory = None self.started_at = time.time() self.last_tick_at = self.started_at self.uptime = 0 self.public_ip = "Not yet known" if platform.system() == "Darwin": self.user_appdata_directory = os.path.expanduser("~/Library/ServerSync/%s" % (self.nodeid)) elif platform.system() == "Linux": self.user_appdata_directory = os.path.expanduser("~/.config/ServerSync/%s" % (self.nodeid)) # inspired by Google Chrome location elif platform.system() == "Windows": self.user_appdata_directory = os.path.expanduser("~\\AppData\\Local\\ServerSync\\%s" % (self.nodeid)) else: raise("Platform not supported") if masterip is None: self.print("Setting up node %s as master\n" % (nodeid)) else : self.ismaster = False self.print("Setting up node %s.\n" % (nodeid)) self.print(" will ask peer list to node at %s:%s\n" % (masterip, masterport)) self.print("Control panel is on port %s\n" % (webuiport)) self.print("Listen for other nodes on port %s\n" % (comport)) # create a directory for the application if not aready exists if not os.path.exists(self.user_appdata_directory): os.makedirs(self.user_appdata_directory) self.updater = Updater() #m = multiprocessing.Manager() self.q_peerstore_in = multiprocessing.Queue() #m.Queue() #for networked multiprocessing self.q_peerstore_out = multiprocessing.Queue() self.q_comwebserver_in = multiprocessing.Queue() #m.Queue() #for networked multiprocessing self.q_comwebserver_out = multiprocessing.Queue() self.q_client_in = multiprocessing.Queue() self.q_client_out = multiprocessing.Queue() self.q_uiwebserver_in = multiprocessing.Queue() self.q_uiwebserver_out = multiprocessing.Queue() self.q_logger_in = multiprocessing.Queue() self.q_logger_out = multiprocessing.Queue() self.q_console_out = multiprocessing.Queue() self.peerstore = PeerStore(THREAD_SLEEP_TIME, self.q_peerstore_in, self.q_peerstore_out, "PeerStore", self.user_appdata_directory, self.comport, self.nodeid, self.masterip, self.masterport) self.uiwebserver = UIWebServer(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_uiwebserver_in, self.q_uiwebserver_out, self.webuiport, self.nodeid, "UIWebServer") self.logger = Logger(THREAD_SLEEP_TIME, self.q_logger_in, self.q_logger_out, self.nodeid, "Logger") self.comwebserver = ComWebServer(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_comwebserver_in, self.q_comwebserver_out, self.comport, self.nodeid, "ComWebServer") self.client = Client(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_client_in, self.q_client_out, self.nodeid, "Client") self.console = Console(self.q_console_out, sys.stdin, sys.stdout, self.nodeid, "Console") self.running = False self.should_restart = False
class ServerSync(object): def __init__(self, exec_path, nodeid, bind_ip, webuiport, comport, masterip=None, masterport=None): self.ismaster = True self.exec_path = exec_path self.nodeid = nodeid self.bindip = bind_ip self.webuiport = webuiport self.comport = comport self.masterip = masterip self.masterport = masterport self.user_appdata_directory = None self.started_at = time.time() self.last_tick_at = self.started_at self.uptime = 0 self.public_ip = "Not yet known" if platform.system() == "Darwin": self.user_appdata_directory = os.path.expanduser("~/Library/ServerSync/%s" % (self.nodeid)) elif platform.system() == "Linux": self.user_appdata_directory = os.path.expanduser("~/.config/ServerSync/%s" % (self.nodeid)) # inspired by Google Chrome location elif platform.system() == "Windows": self.user_appdata_directory = os.path.expanduser("~\\AppData\\Local\\ServerSync\\%s" % (self.nodeid)) else: raise("Platform not supported") if masterip is None: self.print("Setting up node %s as master\n" % (nodeid)) else : self.ismaster = False self.print("Setting up node %s.\n" % (nodeid)) self.print(" will ask peer list to node at %s:%s\n" % (masterip, masterport)) self.print("Control panel is on port %s\n" % (webuiport)) self.print("Listen for other nodes on port %s\n" % (comport)) # create a directory for the application if not aready exists if not os.path.exists(self.user_appdata_directory): os.makedirs(self.user_appdata_directory) self.updater = Updater() #m = multiprocessing.Manager() self.q_peerstore_in = multiprocessing.Queue() #m.Queue() #for networked multiprocessing self.q_peerstore_out = multiprocessing.Queue() self.q_comwebserver_in = multiprocessing.Queue() #m.Queue() #for networked multiprocessing self.q_comwebserver_out = multiprocessing.Queue() self.q_client_in = multiprocessing.Queue() self.q_client_out = multiprocessing.Queue() self.q_uiwebserver_in = multiprocessing.Queue() self.q_uiwebserver_out = multiprocessing.Queue() self.q_logger_in = multiprocessing.Queue() self.q_logger_out = multiprocessing.Queue() self.q_console_out = multiprocessing.Queue() self.peerstore = PeerStore(THREAD_SLEEP_TIME, self.q_peerstore_in, self.q_peerstore_out, "PeerStore", self.user_appdata_directory, self.comport, self.nodeid, self.masterip, self.masterport) self.uiwebserver = UIWebServer(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_uiwebserver_in, self.q_uiwebserver_out, self.webuiport, self.nodeid, "UIWebServer") self.logger = Logger(THREAD_SLEEP_TIME, self.q_logger_in, self.q_logger_out, self.nodeid, "Logger") self.comwebserver = ComWebServer(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_comwebserver_in, self.q_comwebserver_out, self.comport, self.nodeid, "ComWebServer") self.client = Client(THREAD_SLEEP_TIME, self.exec_path, self.bindip, self.q_client_in, self.q_client_out, self.nodeid, "Client") self.console = Console(self.q_console_out, sys.stdin, sys.stdout, self.nodeid, "Console") self.running = False self.should_restart = False def start(self): # we will fork the subprocesses now so we disable the signal handling for them # we will enable it later signal.signal(signal.SIGINT, signal.SIG_IGN) # start process self.comwebserver.start() self.uiwebserver.start() self.client.start() self.logger.start() self.peerstore.start() # catch CTRL+C signal.signal(signal.SIGINT, self.signal_handler) # start threads self.console.start() self.running = True self.q_logger_in.put(Message("System", "Logger", "register", ["System"])) while(self.running): time.sleep(MAIN_SLEEP_TIME) m = self.process_queues() # each second we send a tick to some of the processes telling them since how manytime we run if int(time.time() - self.last_tick_at) >= 1: self.last_tick_at = time.time() self.uptime = int(time.time() - self.started_at) self.q_peerstore_in.put(Message(self.nodeid, "PeerStore", "tick", [self.uptime])) self.q_comwebserver_in.put(Message(self.nodeid, "ComWebServer", "tick", [self.uptime])) self.q_uiwebserver_in.put(Message(self.nodeid, "UIWebServer", "tick", [self.uptime])) self.q_logger_in.put(Message(self.nodeid, "Logger", "tick", [self.uptime])) # We send poison pill to threads only if they are not configured to loop based on a sleep time (blocking queues) if THREAD_SLEEP_TIME is 0: self.poison_pill_queues() self.print("Shutdown client and server processes...\n") # ask the client and server process to shut down, except if we received a kill signal self.print("Wait for gracefull stop\n") self.q_client_in.put(Message(self.nodeid, "Client", "kill", [])) self.q_comwebserver_in.put(Message(self.nodeid, "ComWebServer", "kill", [])) self.q_uiwebserver_in.put(Message(self.nodeid, "UIWebServer", "kill", [])) self.q_logger_in.put(Message(self.nodeid, "Logger", "kill", [])) self.q_peerstore_in.put(Message(self.nodeid, "PeerStore", "kill", [])) time.sleep(1) # read what remains in the queues self.process_queues() # Wait for the worker to finish self.comwebserver.join() self.print("ComWebServer joined\n") self.uiwebserver.join() self.print("UIWebServer joined\n") self.logger.join() self.print("Logger joined\n") self.client.join() self.print("Client joined\n") self.peerstore.join() self.print("PeerStore joined\n") self.console.cancel() self.print("Console joined\n") self.print("Stopped\n") return self.should_restart def poison_pill_queues(self): self.q_comwebserver_in.put(Message(self.nodeid, "ComWebServer", "pill", [])) self.q_uiwebserver_in.put(Message(self.nodeid, "UIWebServer", "pill", [])) self.q_logger_in.put(Message(self.nodeid, "Logger", "pill", [])) self.q_peerstore_in.put(Message(self.nodeid, "PeerStore", "pill", [])) def process_queues(self): q_comwebserver_out_empty = False q_client_out_empty = False q_uiwebserver_out_empty = False q_logger_out_empty = False q_peerstore_out_empty = False q_console_out_empty = False while (not q_comwebserver_out_empty) or (not q_client_out_empty) or (not q_uiwebserver_out_empty) or (not q_logger_out_empty) or (not q_peerstore_out_empty) or (not q_console_out_empty): try: m = self.q_console_out.get(False) self.dispatch_message(m) except Exception as e: q_console_out_empty = True try: m = self.q_uiwebserver_out.get(False) self.dispatch_message(m) except Exception as e: q_uiwebserver_out_empty = True try: m = self.q_logger_out.get(False) self.dispatch_message(m) except Exception as e: q_logger_out_empty = True try: m = self.q_comwebserver_out.get(False) self.dispatch_message(m) except Exception as e: q_comwebserver_out_empty = True try: m = self.q_peerstore_out.get(False) self.dispatch_message(m) except Exception as e: q_peerstore_out_empty = True try: m = self.q_client_out.get(False) self.dispatch_message(m) except Exception as e: q_client_out_empty = True def dispatch_message(self, message): try: # # intercept message like exit/quit/restart # if message.destination == "System": if message.command == "halt" or message.command == "stop": self.running = False elif message.command == "restart": self.running = False self.should_restart = True elif message.command == "PublicIpDiscovered": self.public_ip = message.arguments[0] elif message.command == "GetVersion": self.print("\n\nreceived Get Version FROM %s\n\n" % (message.sender_id)) m = Message("System", message.sender_id, "GetVersion_ret", [{ "current_version": self.updater.current_version, "new_version": self.updater.new_version_available }], communication_id=message.communication_id) self.q_uiwebserver_in.put(m) elif message.command == "increment": message.destination = "UIWebServer" # useless step ? the message wil not be dispatched anymore, no nee to change its dest self.q_uiwebserver_in.put(message) elif message.command == "uptime": m = Message("System", "Logger", "print", ["Running since %s (hh:mm:ss)\n" % (time.strftime('%H:%M:%S', time.gmtime(self.uptime)))]) self.q_logger_in.put(m) elif message.command == "print": self.print("%s %s %s\n"%(message.sender_id, message.command, message.arguments)) elif message.command == "exception": self.print("%s Catched exception: %s \n"%(message.sender_id, [message.arguments[0]])) elif message.command == "NodeInfo": m = Message("System", message.sender_id, "NodeInfo_ret", [{"ismaster": self.ismaster, "nodeid": self.nodeid, "webuiport": self.webuiport, "comport": self.comport, "masterip": self.masterip, "masterport": self.masterport, "user_appdata_directory": self.user_appdata_directory, "started_at": self.started_at, "uptime": self.uptime, "public_ip": self.public_ip, "version": self.updater.current_version }], communication_id=message.communication_id) self.q_uiwebserver_in.put(m) # # we also intercept print comands # elif message.destination == "Logger": if self.running: self.q_logger_in.put(message) else: # if no logger running we fallback to the system print self.print("%s %s %s\n"%(message.sender_id, message.command, message.arguments)) elif message.destination == "PeerStore": self.q_peerstore_in.put(message) elif message.destination == "UIWebServer": self.q_uiwebserver_in.put(message) elif message.destination == "ComWebServer": self.q_comwebserver_in.put(message) elif message.destination == "Client": self.q_client_in.put(message) # # dispatch other messages # else : self.print("Message dispatcher received a msg for the unknown destination '%s'\n" % (message.destination)) except Exception as e: self.print("Exception while dispatching message '%s'\n" % ([e])) def print(self, message): sys.stdout.write("%s => %s" % (datetime.datetime.utcnow().strftime("%Y %b %d %H:%M:%S %Z "), message)) sys.stdout.flush() def signal_handler(self, sig, frame): if sig == signal.SIGINT: self.print("Please type 'halt' or 'stop' to close the program or 'restart' to full restart\n")