def run_experiment(test_id='', test_id_pfx='', *args, **kwargs): do_init_os = kwargs.get('do_init_os', '1') ecn = kwargs.get('ecn', '0') tcp_cc_algo = kwargs.get('tcp_cc_algo', 'default') duration = kwargs.get('duration', '') if duration == '': abort('No experiment duration specified') # create sub directory for test id prefix mkdir_p(test_id_pfx) # remove <test_id>* files in <test_id_pfx> directory if exists file_pattern = test_id_pfx + "/" + test_id + "_*" for f in glob.glob(file_pattern): os.remove(f) # log experiment in started list local('echo "%s" >> experiments_started.txt' % test_id) puts('\n[MAIN] Starting experiment %s \n' % test_id) tftpboot_dir = '' try: tftpboot_dir = config.TPCONF_tftpboot_dir except AttributeError: pass # initialise if tftpboot_dir != '' and do_init_os == '1': execute( get_host_info, netint='0', hosts=config.TPCONF_router + config.TPCONF_hosts) execute( init_os_hosts, file_prefix=test_id_pfx, local_dir=test_id_pfx) # reboot clear_type_cache() # clear host type cache disconnect_all() # close all connections time.sleep(30) # give hosts some time to settle down (after reboot) # initialise topology try: switch = '' port_prefix = '' port_offset = 0 try: switch = config.TPCONF_topology_switch port_prefix = config.TPCONF_topology_switch_port_prefix port_offset = config.TPCONF_topology_switch_port_offset except AttributeError: pass if config.TPCONF_config_topology == '1' and do_init_os == '1': # we cannot call init_topology directly, as it is decorated with # runs_once. in experiment.py we have empty host list whereas if we # run init_topology from command line we have the -H host list. executing # an runs_once task with empty host list (hosts set in execute call), it # will only be executed for the first host, which is not what we # want. in contrast if we have a host list in context, execute will be # executed once for each host (hence we need runs_once when called from # the command line). # sequentially configure switch execute(init_topology_switch, switch, port_prefix, port_offset, hosts = config.TPCONF_hosts) # configure hosts in parallel execute(init_topology_host, hosts = config.TPCONF_hosts) except AttributeError: pass file_cleanup(test_id_pfx) # remove any .start files execute( get_host_info, netmac='0', hosts=config.TPCONF_router + config.TPCONF_hosts) execute(sanity_checks) execute(init_hosts, *args, **kwargs) # first is the legacy case with single router and single queue definitions # second is the multiple router case with several routers and several queue # definitions if isinstance(config.TPCONF_router_queues, list): # start queues/pipes config_router_queues(config.TPCONF_router_queues, config.TPCONF_router, **kwargs) # show pipe setup execute(show_pipes, hosts=config.TPCONF_router) elif isinstance(config.TPCONF_router_queues, dict): for router in config.TPCONF_router_queues.keys(): # start queues/pipes for router r config_router_queues(config.TPCONF_router_queues[router], [router], **kwargs) # show pipe setup execute(show_pipes, hosts=[router]) # log config parameters execute( log_config_params, file_prefix=test_id, local_dir=test_id_pfx, hosts=['MAIN'], *args, **kwargs) # log host tcp settings execute( log_host_tcp, file_prefix=test_id, local_dir=test_id_pfx, hosts=['MAIN'], *args, **kwargs) # start all loggers execute( start_loggers, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir) # Start broadcast ping and loggers (if enabled) try: if config.TPCONF_bc_ping_enable == '1': # for multicast need IP of outgoing interface # which is router's control interface use_multicast = socket.gethostbyname( config.TPCONF_router[0].split(':')[0]) # get configured broadcast or multicast address bc_addr = '' try: bc_addr = config.TPCONF_bc_ping_address except AttributeError: # use default multicast address bc_addr = '224.0.1.199' execute( start_bc_ping_loggers, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir, bc_addr=bc_addr) try: bc_ping_rate = config.TPCONF_bc_ping_rate except AttributeError: bc_ping_rate = '1' # start the broadcst ping on the first router execute(start_bc_ping, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir, bc_addr=bc_addr, rate=bc_ping_rate, use_multicast=use_multicast, hosts = [config.TPCONF_router[0]]) except AttributeError: pass # start traffic generators sync_delay = 5.0 start_time = datetime.datetime.now() total_duration = float(duration) + sync_delay for t, c, v in sorted(config.TPCONF_traffic_gens, cmp=_cmp_timekeys): try: # delay everything to have synchronised start next_time = float(t) + sync_delay except ValueError: abort('Traffic generator entry key time must be a float') # add the kwargs parameter to the call of _param v = re.sub("(V_[a-zA-Z0-9_-]*)", "_param('\\1', kwargs)", v) # trim white space at both ends v = v.strip() if v[-1] != ',': v = v + ',' # add counter parameter v += ' counter="%s"' % c # add file prefix parameter v += ', file_prefix=test_id' # add remote dir v += ', remote_dir=\'%s\'' % config.TPCONF_remote_dir # add test id prefix to put files into correct directory v += ', local_dir=\'%s\'' % test_id_pfx # we don't need to check for presence of tools inside start functions v += ', check="0"' # set wait time until process is started now = datetime.datetime.now() dt_diff = now - start_time sec_diff = (dt_diff.days * 24 * 3600 + dt_diff.seconds) + \ (dt_diff.microseconds / 1000000.0) if next_time - sec_diff > 0: wait = str(next_time - sec_diff) else: wait = '0.0' v += ', wait="' + wait + '"' _nargs, _kwargs = eval('_args(%s)' % v) # get traffic generator duration try: traffic_duration = _kwargs ['duration'] except: traffic_duration = 0 # find the largest total_duration possible if next_time + traffic_duration > total_duration: total_duration = next_time + traffic_duration execute(*_nargs, **_kwargs) # print process list print_proc_list() # wait until finished (add additional 5 seconds to be sure) total_duration = float(total_duration) + 5.0 puts('\n[MAIN] Running experiment for %i seconds\n' % int(total_duration)) time.sleep(total_duration) # shut everything down and get log data execute(stop_processes, local_dir=test_id_pfx) execute( log_queue_stats, file_prefix=test_id, local_dir=test_id_pfx, hosts=config.TPCONF_router) # log test id in completed list local('echo "%s" >> experiments_completed.txt' % test_id) # kill any remaining processes execute(kill_old_processes, hosts=config.TPCONF_router + config.TPCONF_hosts) # done puts('\n[MAIN] COMPLETED experiment %s \n' % test_id)
def run_experiment(test_id='', test_id_pfx='', *args, **kwargs): do_init_os = kwargs.get('do_init_os', '1') ecn = kwargs.get('ecn', '0') tcp_cc_algo = kwargs.get('tcp_cc_algo', 'default') duration = kwargs.get('duration', '') if duration == '': abort('No experiment duration specified') # create sub directory for test id prefix mkdir_p(test_id_pfx) # log experiment in started list local('echo "%s" >> experiments_started.txt' % test_id) puts('\n[MAIN] Starting experiment %s \n' % test_id) tftpboot_dir = '' try: tftpboot_dir = config.TPCONF_tftpboot_dir except AttributeError: pass # initialise if tftpboot_dir != '' and do_init_os == '1': execute( get_host_info, netint='0', hosts=config.TPCONF_router + config.TPCONF_hosts) execute( init_os_hosts, file_prefix=test_id_pfx, local_dir=test_id_pfx) # reboot clear_type_cache() # clear host type cache disconnect_all() # close all connections time.sleep(30) # give hosts some time to settle down (after reboot) # initialise topology try: switch = '' port_prefix = '' port_offset = 0 try: switch = config.TPCONF_topology_switch port_prefix = config.TPCONF_topology_switch_port_prefix port_offset = config.TPCONF_topology_switch_port_offset except AttributeError: pass if config.TPCONF_config_topology == '1' and do_init_os == '1' and \ not len(config.TPCONF_router) > 1: # we cannot call init_topology directly, as it is decorated with # runs_once. in experiment.py we have empty host list whereas if we # run init_topology from command line we have the -H host list. executing # an runs_once task with empty host list (hosts set in execute call), it # will only be executed for the first host, which is not what we # want. in contrast if we have a host list in context, execute will be # executed once for each host (hence we need runs_once when called from # the command line). # sequentially configure switch execute(init_topology_switch, switch, port_prefix, port_offset, hosts = config.TPCONF_hosts) # configure hosts in parallel execute(init_topology_host, hosts = config.TPCONF_hosts) except AttributeError: pass file_cleanup(test_id_pfx) # remove any .start files execute( get_host_info, netmac='0', hosts=config.TPCONF_router + config.TPCONF_hosts) execute(sanity_checks) execute(init_hosts, *args, **kwargs) # first is the legacy case with single router and single queue definitions # second is the multiple router case with several routers and several queue # definitions if isinstance(config.TPCONF_router_queues, list): # start queues/pipes config_router_queues(config.TPCONF_router_queues, config.TPCONF_router, **kwargs) # show pipe setup execute(show_pipes, hosts=config.TPCONF_router) elif isinstance(config.TPCONF_router_queues, dict): for router in config.TPCONF_router_queues.keys(): # start queues/pipes for router r config_router_queues(config.TPCONF_router_queues[router], [router], **kwargs) # show pipe setup execute(show_pipes, hosts=[router]) # log config parameters execute( log_config_params, file_prefix=test_id, local_dir=test_id_pfx, hosts=['MAIN'], *args, **kwargs) # log host tcp settings execute( log_host_tcp, file_prefix=test_id, local_dir=test_id_pfx, hosts=['MAIN'], *args, **kwargs) # start all loggers execute( start_loggers, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir) # Start broadcast ping and loggers (if enabled) try: if config.TPCONF_bc_ping_enable == '1': # for multicast need IP of outgoing interface # which is router's control interface use_multicast = socket.gethostbyname( config.TPCONF_router[0].split(':')[0]) # get configured broadcast or multicast address bc_addr = '' try: bc_addr = config.TPCONF_bc_ping_address except AttributeError: # use default multicast address bc_addr = '224.0.1.199' execute( start_bc_ping_loggers, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir, bc_addr=bc_addr) try: bc_ping_rate = config.TPCONF_bc_ping_rate except AttributeError: bc_ping_rate = '1' # start the broadcst ping on the first router execute(start_bc_ping, file_prefix=test_id, local_dir=test_id_pfx, remote_dir=config.TPCONF_remote_dir, bc_addr=bc_addr, rate=bc_ping_rate, use_multicast=use_multicast, hosts = [config.TPCONF_router[0]]) except AttributeError: pass # start traffic generators sync_delay = 5.0 max_wait_time = sync_delay start_time = datetime.datetime.now() for t, c, v in sorted(config.TPCONF_traffic_gens, cmp=_cmp_timekeys): try: # delay everything to have synchronised start next_time = float(t) + sync_delay except ValueError: abort('Traffic generator entry key time must be a float') if next_time > max_wait_time: max_wait_time = next_time # add the kwargs parameter to the call of _param v = re.sub("(V_[a-zA-Z0-9_-]*)", "_param('\\1', kwargs)", v) # trim white space at both ends v = v.strip() if v[-1] != ',': v = v + ',' # add counter parameter v += ' counter="%s"' % c # add file prefix parameter v += ', file_prefix=test_id' # add remote dir v += ', remote_dir=\'%s\'' % config.TPCONF_remote_dir # add test id prefix to put files into correct directory v += ', local_dir=\'%s\'' % test_id_pfx # we don't need to check for presence of tools inside start functions v += ', check="0"' # set wait time until process is started now = datetime.datetime.now() dt_diff = now - start_time sec_diff = (dt_diff.days * 24 * 3600 + dt_diff.seconds) + \ (dt_diff.microseconds / 1000000.0) if next_time - sec_diff > 0: wait = str(next_time - sec_diff) else: wait = '0.0' v += ', wait="' + wait + '"' _nargs, _kwargs = eval('_args(%s)' % v) execute(*_nargs, **_kwargs) # print process list print_proc_list() # wait until finished (add additional 5 seconds to be sure) total_duration = float(duration) + max_wait_time + 5.0 puts('\n[MAIN] Running experiment for %i seconds\n' % int(total_duration)) time.sleep(total_duration) # shut everything down and get log data execute(stop_processes, local_dir=test_id_pfx) execute( log_queue_stats, file_prefix=test_id, local_dir=test_id_pfx, hosts=config.TPCONF_router) # log test id in completed list local('echo "%s" >> experiments_completed.txt' % test_id) # kill any remaining processes execute(kill_old_processes, hosts=config.TPCONF_router + config.TPCONF_hosts) # done puts('\n[MAIN] COMPLETED experiment %s \n' % test_id)