def __init__(self, remote="mlcneta.cs.wpi.edu", localdir="./", glommadir="", remotedir="", rootdir="./rdir", datasize="50M", round="0"): self.cmd = CommandWrapper() self.remote = remote self.trialroot = rootdir self.glommadir = glommadir self.remotedir = remotedir self.localdir = localdir self.local_udping_path = f"{self.trialroot}/udpLog.txt" self.local_pcap_path = f"{self.trialroot}/local.pcap" self.remote_pcap_path = f"{self.trialroot}/{self.remote}.pcap" self.amount = datasize self.round = round # Open Log File try: ERR_FILE = self.localdir + f"/errorlog_trial.txt" self.errorlog = open(ERR_FILE, 'a+') except: raise ValueError("cannot open error log file for trial")
def __init__(self, args): # Check singleton if ExperimentExecutor.__instance != None: raise RuntimeError( "Trying To Construct Extra New_Trial in Setup Phase") else: ExperimentExecutor.__instance = self self.args = args self.cmd = CommandWrapper() # Open Log File try: ERR_FILE = self.args[ "EXPERIMENT_DIR_LOCAL"] + f"/errorlog_executor.txt" self.errorlog = open(ERR_FILE, 'w+') except: raise ValueError("cannot open error log file") self.cmd.executeOneSCPCommand( host="glomma.cs.wpi.edu", localFilepath="./GlommaExecutor.py", remoteFilepath=self.args["EXPERIMENT_DIR_GLOMMA"], raiseOnError=True) for m_p in self.args["MACHINE_PROTOCOLS"]: machine = m_p[0] self.cmd.executeOneSCPCommand( host=machine, localFilepath="./RemoteExecutor.py", remoteFilepath=self.args["EXPERIMENT_DIR_REMOTE"], raiseOnError=True)
def __init__(self): """ Init supported fields """ # Check singleton if SetupWorker.__instance != None: raise RuntimeError("Trying To Construct Extra SetupWorker in Setup Phase") else: SetupWorker.__instance = self # Supported Protocols self.supportedProtocols = {"BBR", "CUBIC", "HYBLA", "PCC"} # Supported self.supportedMachines [including acronym dictionary for conversion] self.supportedMachines = { "MLCA": "mlcneta.cs.wpi.edu", "MLCB": "mlcnetb.cs.wpi.edu", "MLCC": "mlcnetc.cs.wpi.edu", "MLCD": "mlcnetd.cs.wpi.edu", "mlcneta.cs.wpi.edu": "mlcneta.cs.wpi.edu", "mlcnetb.cs.wpi.edu": "mlcnetb.cs.wpi.edu", "mlcnetc.cs.wpi.edu": "mlcnetc.cs.wpi.edu", "mlcnetd.cs.wpi.edu": "mlcnetd.cs.wpi.edu" } # Supported Proxy Modes self.supportedProxies = {"1", "2", "3"} # Default Global Parameters self.GLOBAL_PARAMETERS = { "EXPERIMENT_NAME": "EXAMPLE_EXPERIMENT", "EXPERIMENT_DIR_LOCAL": "./experiment/EXAMPLE_EXPERIMENT/", "EXPERIMENT_DIR_GLOMMA":"./experiment/EXAMPLE_EXPERIMENT/", "EXPERIMENT_DIR_REMOTE":"./experiment/EXAMPLE_EXPERIMENT/", "MACHINE_PROTOCOLS": [["mlcneta.cs.wpi.edu", "cubic"]], "PROXY_MODES": ["2", "3"], "BDP": 15000000, "WMEM": 60000000, "UDPING_FLAG": False, "VERBOSE": False, "SETUP_REPORT": True, "DATA_SIZE_AND_ROUNDS": [["1G", "50"]] } self.__global_parameter_setted = False self.__finished_sysconf_generation = False self.local_dir = None self.mlc_dir = None self.glomma_dir = None self.glomma_addr = "glomma.cs.wpi.edu" self.args = None self.cmd = CommandWrapper()
# This is the script to check glomma system configurations # TODO: Add more checking / testings to this file from CommandWrapper import CommandWrapper import re, configparser, inspect # Initialize cmd instance cmd = CommandWrapper() # To mark test functions def TEST(function): function.__is_test__ = True return function class TestFailException(Exception): """ Exception raised for failing customized tests """ def __init__(self, reason=""): self.message = reason super().__init__(self.message) def __str__(self): return f'Test Failed for: {self.message}' # To execute all test methods in a class def executeAllTestMethods(instance): methods = (getattr(instance, name) for name in dir(instance))
class Trial: def __init__(self, remote="mlcneta.cs.wpi.edu", localdir="./", glommadir="", remotedir="", rootdir="./rdir", datasize="50M", round="0"): self.cmd = CommandWrapper() self.remote = remote self.trialroot = rootdir self.glommadir = glommadir self.remotedir = remotedir self.localdir = localdir self.local_udping_path = f"{self.trialroot}/udpLog.txt" self.local_pcap_path = f"{self.trialroot}/local.pcap" self.remote_pcap_path = f"{self.trialroot}/{self.remote}.pcap" self.amount = datasize self.round = round # Open Log File try: ERR_FILE = self.localdir + f"/errorlog_trial.txt" self.errorlog = open(ERR_FILE, 'a+') except: raise ValueError("cannot open error log file for trial") # Simple SSH Checkings here def command_glomma(self, command): glomma_executor_path = self.glommadir + "/GlommaExecutor.py" out, err = self.cmd.executeOneSSHCommand( host="glomma.cs.wpi.edu", command=f"python3 {glomma_executor_path} {command}", getOut=True, raiseOnError=True) if "ok" in out: return if err: self.errorlog.write(f"#{self.round} - Glomma: SSH ERROR: {err}" ) # Simple Report mechanism def command_remote(self, command): remote_executor_path = self.remotedir + "/RemoteExecutor.py" out, err = self.cmd.executeOneSSHCommand( host=self.remote, command=f"python3 {remote_executor_path} {command}", getOut=True, raiseOnError=True) if "ok" in out: return if err: self.errorlog.write( f"#{self.round} - {self.remote}: SSH ERROR: {err}" ) # Simple Report mechanism def start(self): # self.command_glomma(command="-C CHECK_ROUTE") # Check Route self.command_glomma(command=f"-C CLEANUP") # CLEANUP G self.command_remote(command=f"-C CLEANUP") # CLEANUP M self.command_glomma( command=f"-C MAKEDIR -P {self.trialroot}") # Make Trial Root at G self.command_remote(command=f"-C S_UDPING") # Start UDPING at M self.command_glomma( command=f"-C S_UDPING -R {self.remote} -P {self.local_udping_path}" ) # Start UDPING at G self.command_glomma(command=f"-C S_TCPDUMP -P {self.local_pcap_path}" ) # Start TCPDUMP at G self.command_remote(command=f"-C S_TCPDUMP") # Start TCPDUMP at M self.command_remote(command=f"-C S_IPERF") # Start IPERF at M self.command_glomma( command=f"-C S_IPERF -R {self.remote} -A {self.amount}" ) # Start IPERF at G self.command_glomma(command=f"-C CLEANUP") # CLEANUP G self.command_remote(command=f"-C CLEANUP") # CLEANUP M self.command_glomma( command=f"-C S_SCP_PCAP -R {self.remote} -P {self.remote_pcap_path}" ) # Start SCP at G def __del__(self): # Close The File try: self.errorlog.close() except: raise ValueError("cannot close error log for trial")
class ExperimentExecutor: # Simple way to define singleton in a process __instance = None @staticmethod def getInstance(): """ Static access method. """ if ExperimentExecutor.__instance == None: ExperimentExecutor() return ExperimentExecutor.__instance def __init__(self, args): # Check singleton if ExperimentExecutor.__instance != None: raise RuntimeError( "Trying To Construct Extra New_Trial in Setup Phase") else: ExperimentExecutor.__instance = self self.args = args self.cmd = CommandWrapper() # Open Log File try: ERR_FILE = self.args[ "EXPERIMENT_DIR_LOCAL"] + f"/errorlog_executor.txt" self.errorlog = open(ERR_FILE, 'w+') except: raise ValueError("cannot open error log file") self.cmd.executeOneSCPCommand( host="glomma.cs.wpi.edu", localFilepath="./GlommaExecutor.py", remoteFilepath=self.args["EXPERIMENT_DIR_GLOMMA"], raiseOnError=True) for m_p in self.args["MACHINE_PROTOCOLS"]: machine = m_p[0] self.cmd.executeOneSCPCommand( host=machine, localFilepath="./RemoteExecutor.py", remoteFilepath=self.args["EXPERIMENT_DIR_REMOTE"], raiseOnError=True) #Wrapper For Print def PRINT(self, logfile, msg): print(msg) try: logfile.write(msg) except: print("LOG FILE ERROR") # Execute test on a specific machine with specific protocol once def executeTestOnce(self, machine, protocol, proxyMode, roundIndex, logfile, dataSize="50M"): """ Method to execute test once on a specific machine with specific protocol once @params: machine, protocol: being tested machine and protocol @params: roundIndex: current round (most outer loop) """ # Trial Constructor: # def __init__(self, name='experiment', dir='.', local='glomma', remote='mlc1.cs.wpi.edu', data=None) # Switch Proxy Mode msg = "Switching Proxy Mode to %d\n" % (proxyMode) self.PRINT(logfile, msg) # SIMPLE CHECKING HERE out = self.cmd.executeOneSSHCommand( host="glomma.cs.wpi.edu", command=f"python3 GlommaExecutor.py -C S_PROXY -A {proxyMode}", getOut=True)[0] if "OK" not in out: self.errorlog.write( f"FAIL TO SWITCH PROXY IN ROUND {roundIndex} with {machine}_{protocol}" ) # Print Round Start test_start_time = datetime.now() test_start_time_str = test_start_time.strftime("%Y-%m-%d-%H-%M-%S") msg = "# Round %d %s %s ProxyMode %d Started At : %s\n" % ( roundIndex, machine, protocol, proxyMode, test_start_time_str) self.PRINT(logfile, msg) # Trial title = f"{self.args['EXPERIMENT_DIR_GLOMMA']}/data/{machine}_{protocol}_Proxy{proxyMode}_{dataSize}_{roundIndex}" # Title of the trial. trial = Trial(localdir=self.args['EXPERIMENT_DIR_LOCAL'], glommadir=self.args['EXPERIMENT_DIR_GLOMMA'], remotedir=self.args['EXPERIMENT_DIR_REMOTE'], rootdir=title, datasize=dataSize, remote=machine) trial.start() test_end_time = datetime.now() test_end_time_str = test_end_time.strftime("%Y-%m-%d-%H-%M-%S") duration = divmod((test_end_time - test_start_time).total_seconds(), 60) msg = """# Round %d %s %s ProxyMode %d Ended At : %s Duration: %s \n""" % (roundIndex, machine, protocol, proxyMode, test_end_time_str, str(duration)) self.PRINT(logfile, msg) def __start(self, numOfTests=10, dataSize="50M"): # Open Log File try: LOG_FILE = self.args[ "EXPERIMENT_DIR_LOCAL"] + f"/{dataSize}_log.txt" logfile = open(LOG_FILE, 'w+') except: raise ValueError("cannot open logfile") print_msg = "" # Record Start time, and then End Time After Test Ends, for Analysis Purposes start_time = datetime.now() start_time_str = start_time.strftime("%Y-%m-%d-%H-%M-%S") print_msg = f"TEST Started At {start_time_str}\n" \ f"Rounds: {numOfTests}" self.PRINT(logfile, print_msg) # Main Loop For Testing current_time_str = "" for i in range(numOfTests): # Record The Time When A Round Starts current_time_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") print_msg = "\n**************************************** Round %d Started At [ %s ] ****************************************\n" % ( i, current_time_str) self.PRINT(logfile, print_msg) # Loop 2: Traverse (Machine, Protocol) groups for [machine, protocol] in self.args["MACHINE_PROTOCOLS"]: # Record The Time When A (Machine Protocol) Group Starts current_time_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") print_msg = "\n------------------------------ Round %d %s %s Started At [ %s ] ------------------------------\n" % ( i, machine, protocol, current_time_str) self.PRINT(logfile, print_msg) # Loop Body 3: Run Test With Proxy 2 Once and Proxy 3 Once (Machine, Protocol) self.executeTestOnce(machine, protocol, 2, i, logfile, dataSize) self.executeTestOnce(machine, protocol, 3, i, logfile, dataSize) # Record The Time When A (Machine Protocol) Group Ends current_time_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") print_msg = "\n------------------------------- Round %d %s %s Ended At [ %s ] -------------------------------\n" % ( i, machine, protocol, current_time_str) self.PRINT(logfile, print_msg) # Record The Time When A Round Ends current_time_str = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") print_msg = "\n***************************************** Round %d Ended At [ %s ] *****************************************\n" % ( i, current_time_str) self.PRINT(logfile, print_msg) # End of Testing Loop # Record Test Ending Time and Print Overall Statistics end_time = datetime.now() end_time_str = end_time.strftime("%Y-%m-%d-%H-%M-%S") duration = divmod((end_time - start_time).total_seconds(), 60) print_msg = "TEST Ended At " + end_time_str self.PRINT(logfile, print_msg) print_msg = """ \n\n ********** TEST ENDED ********** Start Time: %s End Time: %s Duration: %s """ % (start_time_str, end_time_str, str(duration)) self.PRINT(logfile, print_msg) # End of Recording # Close The File try: logfile.close() except: raise ValueError("cannot close logfile") def start(self): for size_and_round in self.args["DATA_SIZE_AND_ROUNDS"]: numoftest = int(size_and_round[1]) datasize = size_and_round[0] self.__start(numOfTests=numoftest, dataSize=datasize)
class SetupWorker: # Simple way to define singleton in a process __instance = None @staticmethod def getInstance(): """ Static access method. """ if SetupWorker.__instance == None: SetupWorker() return SetupWorker.__instance def __init__(self): """ Init supported fields """ # Check singleton if SetupWorker.__instance != None: raise RuntimeError("Trying To Construct Extra SetupWorker in Setup Phase") else: SetupWorker.__instance = self # Supported Protocols self.supportedProtocols = {"BBR", "CUBIC", "HYBLA", "PCC"} # Supported self.supportedMachines [including acronym dictionary for conversion] self.supportedMachines = { "MLCA": "mlcneta.cs.wpi.edu", "MLCB": "mlcnetb.cs.wpi.edu", "MLCC": "mlcnetc.cs.wpi.edu", "MLCD": "mlcnetd.cs.wpi.edu", "mlcneta.cs.wpi.edu": "mlcneta.cs.wpi.edu", "mlcnetb.cs.wpi.edu": "mlcnetb.cs.wpi.edu", "mlcnetc.cs.wpi.edu": "mlcnetc.cs.wpi.edu", "mlcnetd.cs.wpi.edu": "mlcnetd.cs.wpi.edu" } # Supported Proxy Modes self.supportedProxies = {"1", "2", "3"} # Default Global Parameters self.GLOBAL_PARAMETERS = { "EXPERIMENT_NAME": "EXAMPLE_EXPERIMENT", "EXPERIMENT_DIR_LOCAL": "./experiment/EXAMPLE_EXPERIMENT/", "EXPERIMENT_DIR_GLOMMA":"./experiment/EXAMPLE_EXPERIMENT/", "EXPERIMENT_DIR_REMOTE":"./experiment/EXAMPLE_EXPERIMENT/", "MACHINE_PROTOCOLS": [["mlcneta.cs.wpi.edu", "cubic"]], "PROXY_MODES": ["2", "3"], "BDP": 15000000, "WMEM": 60000000, "UDPING_FLAG": False, "VERBOSE": False, "SETUP_REPORT": True, "DATA_SIZE_AND_ROUNDS": [["1G", "50"]] } self.__global_parameter_setted = False self.__finished_sysconf_generation = False self.local_dir = None self.mlc_dir = None self.glomma_dir = None self.glomma_addr = "glomma.cs.wpi.edu" self.args = None self.cmd = CommandWrapper() def __check_args__(self): if not self.args: raise RuntimeError("Setup Phase: Called Setup Global Parameters Before Reads In Arguments") def __setupGlobalParameters(self): ''' Method to setup global parameters for trial ''' self.__check_args__() # Read config file if specified. Else use default values. if self.args.CONFIG_PATH: if not os.path.isfile(self.args.CONFIG_PATH): raise FileNotFoundError("Setup Phase: Setup Global Parameters: Configuration file does not exists") config = configparser.ConfigParser() config.read(self.args.CONFIG_PATH) # Experiment name # TODO: Currently set up directory names based on experiment name, guess it should be fine # TODO: Else, read optional EXPERIMENT_DIR_* from set up configuration file self.GLOBAL_PARAMETERS["EXPERIMENT_NAME"] = config["GENERAL PARAMETERS"]["EXPERIMENT_NAME"] self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"] = f"./experiment/{self.GLOBAL_PARAMETERS['EXPERIMENT_NAME']}" self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_GLOMMA"] = f"$HOME/experiment/{self.GLOBAL_PARAMETERS['EXPERIMENT_NAME']}" self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_REMOTE"] = f"$HOME/experiment/{self.GLOBAL_PARAMETERS['EXPERIMENT_NAME']}" # Process Machine Parameter in Configuration File. # Expected Format: MACHINE_PROTOCOLS = {MACHINE}_{PROTOCOL}, separated with comma MACHINE_PROTOCOLS = [x.strip() for x in config["GENERAL PARAMETERS"]["MACHINE_PROTOCOLS"].split(",")] MACHINE_PROTOCOLS = [x.split("_") for x in MACHINE_PROTOCOLS] # Split machine and protocol # Value checking for machine & protocols for m_p in MACHINE_PROTOCOLS: if m_p[0] not in self.supportedMachines: raise ValueError(f"Machine {m_p[0]} is not a supported machine. Check parameters, or check supported list in TestExecutor.py") elif m_p[1] not in self.supportedProtocols : raise ValueError(f"Protocol {m_p[1]} is not a supported protocol. Check parameters, or check supported list in TestExecutor.py") m_p[0] = self.supportedMachines[m_p[0]] # Convert acronyms to full remote names self.GLOBAL_PARAMETERS["MACHINE_PROTOCOLS"] = MACHINE_PROTOCOLS # Read proxy modes. Expected format: {PROXYMODE}, separated with comma PROXIES = [x.strip() for x in config["GENERAL PARAMETERS"]["PROXIES"].split(",")] for proxy in PROXIES: if proxy not in self.supportedProxies: raise ValueError(f"Proxy mode {proxy} is not supported. Check parameters, or check supported list in TestExecutor.py") self.GLOBAL_PARAMETERS["PROXY_MODES"] = PROXIES # Other general parameters self.GLOBAL_PARAMETERS["BDP"] = int(config["GENERAL PARAMETERS"]["BDP"]) self.GLOBAL_PARAMETERS["WMEM"] = int(myutil.NSP.eval(config["GENERAL PARAMETERS"]["WMEM"])) # Give up using python eval for security concerns # Trial related parameters self.GLOBAL_PARAMETERS["UDPING_FLAG"] = config["TRIAL PARAMETERS"].getboolean("UDPING") self.GLOBAL_PARAMETERS["VERBOSE"] = config["TRIAL PARAMETERS"].getboolean("VERBOSE") self.GLOBAL_PARAMETERS["SETUP_REPORT"] = config["TRIAL PARAMETERS"].getboolean("SETUP_REPORT") # Read proxy modes. Expected format: {DATASIZE_ROUND}, separated with comma DATA_SIZE_AND_ROUNDS = [x.strip() for x in config["TRIAL PARAMETERS"]["DATA_SIZE_AND_ROUNDS"].split(",")] for data_round in DATA_SIZE_AND_ROUNDS: if not myutil.DSRCHECKER.check(data_round): raise ValueError(f"Datasize_round {data_round} is not supported. Check parameters.") DATA_SIZE_AND_ROUNDS = [x.split("_") for x in DATA_SIZE_AND_ROUNDS] # Split datasize and rounds self.GLOBAL_PARAMETERS["DATA_SIZE_AND_ROUNDS"] = DATA_SIZE_AND_ROUNDS else: self.GLOBAL_PARAMETERS["EXPERIMENT_NAME"] = self.args.TESTNAME self.__global_parameter_setted = True print("Setup Phase: Global Parameters Set Up Completed") def getGlobalParameters(self): ''' Return GLOBAL_PARAMETERS ''' self.__check_args__() if not self.__global_parameter_setted: self.setupGlobalParameters() return self.GLOBAL_PARAMETERS def __setupLocalDirectory(self): ''' Method to set up directory at local (where the command to start experiments is executed) ''' self.__check_args__() if not self.__global_parameter_setted: self.setupGlobalParameters() if not os.path.exists(self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"]): os.makedirs(self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"]) print(f"Setup Phase: Made A New Experiment Directory At {self.GLOBAL_PARAMETERS['EXPERIMENT_DIR_LOCAL']}") self.local_dir = self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"] print("Setup Phase: Local Directory Setup Finished") def __setupRemoteDirectory(self): """ Method to set up remote directories (in current version, MLCs + Glomma) """ self.__check_args__() # Inner method for check and set a specific directory at host def __check_and_set_dir(host, dir_path, debug=False): # Inner worker method for check and set a specific sub path at host def __inner_worker(dir_path_inner): dir_checking_command = f"[ -d {dir_path_inner} ] && echo EXISTS || echo DNE" out, err = self.cmd.executeOneSSHCommand(host=host, command=dir_checking_command, getOut=True, raiseOnError=True) if "DNE" in out: self.cmd.executeOneSSHCommand(host=host, command=f"mkdir {dir_path_inner}", raiseOnError=True) # Split the dir into subpaths dir_hierachy = dir_path.split("/") # Iterate over subpaths, and check_and_set them one by one current_dir = "" while len(dir_hierachy): subpath = dir_hierachy.pop(0) # Get current subpath if subpath == "$HOME": # Skip if home current_dir += subpath continue current_dir += ("/" + subpath) # Add subpath to current dir if debug: print("Current Dir: ", current_dir) __inner_worker(current_dir) # Check and set the dir # End of Inner Method check_and_set_dir # Setup MLC dirs for m_p in self.GLOBAL_PARAMETERS["MACHINE_PROTOCOLS"]: machine = m_p[0] __check_and_set_dir(host=self.supportedMachines[machine], dir_path=self.GLOBAL_PARAMETERS['EXPERIMENT_DIR_REMOTE']) # Setup Glomma dir __check_and_set_dir(host=self.glomma_addr, dir_path=self.GLOBAL_PARAMETERS['EXPERIMENT_DIR_GLOMMA']) print("Setup Phase: Remote Directory Setup Finished") def __generateSysConfFiles(self): self.__check_args__() SCG = SysConfGenerator(self.GLOBAL_PARAMETERS) SCG.generateMlcSysConf() SCG.generateGlommaSysConf() self.__finished_sysconf_generation = True print("Setup Phase: System Configuration File Setup Finished") def __checkGlommaSysConf(self): self.__check_args__() if not self.__finished_sysconf_generation or not self.__global_parameter_setted: raise RuntimeError("Setup Phase: Called Check Glomma SysConf Before Generated It") glomma_sysconf_path = f'{self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"]}/glomma.machine_config' # Check if can find Glomma configuration file at local if not os.path.isfile(glomma_sysconf_path): raise FileNotFoundError("Setup Phase: Check Glomma SysConf: Cannot find file. Bugs exists. " "Check Generate SysConf Command") # First scp over glomma system configuration file, config checker, and command wrapper which config checker needs self.cmd.executeOneSCPCommand(host=self.glomma_addr, localFilepath=glomma_sysconf_path, remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_GLOMMA"], raiseOnError=True) self.cmd.executeOneSCPCommand(host=self.glomma_addr, localFilepath="./ConfigCheckerGlomma.py", remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_GLOMMA"], raiseOnError=True) self.cmd.executeOneSCPCommand(host=self.glomma_addr, localFilepath="./CommandWrapper.py", remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_GLOMMA"], raiseOnError=True) # Then run check file remote_checker_path = self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_GLOMMA"] + "/ConfigCheckerGlomma.py" out = self.cmd.executeOneSSHCommand(host=self.glomma_addr, command=f"""python3 {remote_checker_path}""", getOut=True, raiseOnError=True)[0] # Process out if "False" in out: out = out.split("\n")[0] raise RuntimeError("Setup Phase: ConfigCheckerGlomma Failed for ", out) print("Setup Phase: Glomma System Configuration Checked") def __checkRemoteSysConf(self): self.__check_args__() if not self.__finished_sysconf_generation or not self.__global_parameter_setted: raise RuntimeError("Setup Phase: Called Check Remote SysConf Before Generated It") def __inner_checking_worker(machine): machine_sysconf_path = f'{self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_LOCAL"]}/{machine}.machine_config' # Check if can find Machine configuration file at local if not os.path.isfile(machine_sysconf_path): raise FileNotFoundError(f"Setup Phase: Check {machine} SysConf: Cannot find file. Bugs exists. " "Check Generate SysConf Command") # First scp over machine system configuration file, config checker, and command wrapper which config checker needs self.cmd.executeOneSCPCommand(host=machine, localFilepath=machine_sysconf_path, remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_REMOTE"], raiseOnError=True) self.cmd.executeOneSCPCommand(host=machine, localFilepath="./ConfigCheckerRemote.py", remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_REMOTE"], raiseOnError=True) self.cmd.executeOneSCPCommand(host=machine, localFilepath="./CommandWrapper.py", remoteFilepath=self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_REMOTE"], raiseOnError=True) # Then run check file remote_checker_path = self.GLOBAL_PARAMETERS["EXPERIMENT_DIR_REMOTE"] + "/ConfigCheckerRemote.py" out = self.cmd.executeOneSSHCommand(host=machine, command=f"""python3 {remote_checker_path}""", getOut=True, raiseOnError=True)[0] # Process out if "False" in out: out = out.split("\n")[0] raise RuntimeError("Setup Phase: ConfigCheckerRemote Failed for ", out) for m_p in self.GLOBAL_PARAMETERS["MACHINE_PROTOCOLS"]: machine = m_p[0] __inner_checking_worker(machine) print(f"Setup Phase: {machine} Configuration Checked") print("Setup Phase: All Remote System Configuration Checked") def setup(self, args): ''' Reads in command line arguments ''' # if not isinstance(args, argparse.Namespace): # raise TypeError("Setup Phase: Read Arguments: Not argparse.Namespace instance.") self.args = args # Set up phase executions self.__setupGlobalParameters() self.__setupLocalDirectory() self.__setupRemoteDirectory() self.__generateSysConfFiles() self.__checkGlommaSysConf() self.__checkRemoteSysConf() # Report finishing # TODO: Add logging to setup phase return True