class Master(object): #------------------------------------------------------------------------------ def __init__(self): self.anime = Animation() host = '' # Bind server to all interfaces self.s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM) # Creating the socket using IPv4, UDP self.s.bind( (host, PORT)) # Binding Server to all interfaces and the chosen port. self.setup_tool = SetupTool() self.paths = self.setup_tool.parse_file('../config/paths.dat') self.setup_tool.get_setup_data('../config/session-setup.dat') self.clients_list = self.setup_tool.get_clients_list() self.query_type = self.setup_tool.get_query_type().split() self.repetitions = int(self.setup_tool.get_repetitions()) fLog = open( self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-master.log', 'w') fLog.close() # Refreshing results folder and temp folder for s in self.setup_tool.get_scenario_list(): self.setup_tool.refresh_folder(self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + s + '/') self.setup_tool.refresh_folder(self.paths['TEMP_FOLDER_PATH']) #------------------------------------------------------------------------------ # Hiago, this module is temporary. Don't worry about it def test_estimation_time(self): #Number of scenarios self.num_scen = len(self.query_type) self.iterations = len(self.query_type) * self.repetitions * len( self.clients_list) total_time = len(self.query_type) * self.repetitions * len( self.clients_list) * (int(self.setup_tool.get_limit()) + int(self.setup_tool.get_timeout()) + 10) duration = timedelta(seconds=total_time) self.start = datetime.now() self.end = self.start + duration self.write_to_log('\t>> Scenario run time\n\t\t>> Estimated: ' + str(duration) + '\n' + '\t\t>> Starting scenario at: ' + str(self.start) + '\n') print '\n>> Estimated run time: ', duration print '>> Starting scenario at: ', self.start print '>> Estimation to finish this scenario: ', self.end #------------------------------------------------------------------------------ def start(self): """ executes the tool in each scenario and register the results """ self.write_to_log('>> Session started at ' + str(datetime.now()) + '\n') print '>> Session started at ', datetime.now() self.check_connection() scen = 1 for scenario in self.setup_tool.get_scenario_list(): self.write_to_log('>> Running scenario ' + str(scen) + '\n') self.setup(scenario) self.validate() self.test_estimation_time() self.run(scenario) scen += 1 print '>> Session finished at ', datetime.now() #------------------------------------------------------------------------------ def check_connection(self): """ Check the connections between Server and Master, Client and Master """ self.write_to_log('>> Checking connection...\n') self.s.sendto('ping', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('ping', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) # wait 2 seconds for the answer before considering remote machine off-line. t = Timer(2, self.offline) t.start() server_status = False client_status = False try: while 1: buf, addr = self.s.recvfrom(1024) if buf == 'server pong': t.cancel() self.write_to_log('\t>> Server is alive.\n') server_status = True elif buf == 'client pong': t.cancel() self.write_to_log('\t>> Client is alive.\n') client_status = True else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def setup(self, scenario): """ Establishes connections and gets the necessary data to run the tests""" self.write_to_log('\t>> Setup phase...') self.s.sendto('setup', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('setup', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False self.num_of_records = self.setup_tool.parse_unity(scenario) if self.setup_tool.get_software( ) == 'bind' or self.setup_tool.get_software() == 'nsd': print '\nquery files\t\t|\tzone files' elif self.setup_tool.get_software( ) == 'pdns' or self.setup_tool.get_software() == 'mydns': print '\nquery files\t\t|\tMySQL' try: while 1: buf, addr = self.s.recvfrom(4096) if buf == 'server 100 OK': self.send_server_setup() elif buf == 'client 100 OK': self.send_client_setup() elif buf == 'server 400 Bad Request': self.write_to_log( '>> Message to server was corrupted. Sending again...') self.send_server_setup() elif buf == 'client 400 Bad Request': self.write_to_log( '>> Message to client was corrupted. Sending again...') self.send_client_setup() elif buf == 'server 200 OK': server_status = True elif buf == 'client 200 OK': client_status = True elif buf.startswith('q'): self.anime.double_hashtag_bar(int(buf.split(';')[1]), 1) elif buf.startswith('z'): self.anime.double_hashtag_bar(int(buf.split(';')[1]), 2) else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() self.write_to_log('done!\n') #------------------------------------------------------------------------------ def send_server_setup(self): """ Get data of scenario related to Server """ default = str(self.setup_tool.get_software() + ';' + self.setup_tool.get_processes() + ';' + self.setup_tool.get_processes_users() + ';' + str(self.num_of_records) + ';' + str(self.setup_tool.get_num_of_zones()) + ';' + self.setup_tool.get_domain_name() + ';' + self.setup_tool.get_server_ip_qry() + ';' + str(self.setup_tool.get_num_of_naptr()) + ';' + self.setup_tool.get_limit() + ';' + str(self.setup_tool.get_num_of_cpu()) + ';' + str(self.setup_tool.update_enabled()) + ';' + str(self.setup_tool.get_update_rate()) + ';') if self.setup_tool.get_software( ) == 'bind' or self.setup_tool.get_software() == 'nsd': software_specifics = str(self.setup_tool.get_server_pass() + ';' + self.setup_tool.get_create_zones() + ';' + self.setup_tool.get_restart_software()) elif self.setup_tool.get_software( ) == 'pdns' or self.setup_tool.get_software() == 'mydns': software_specifics = str(self.setup_tool.get_mysql_database() + ';' + self.setup_tool.get_mysql_user() + ';' + self.setup_tool.get_mysql_user_pass() + ';' + self.setup_tool.get_create_database()) self.s.sendto(default + software_specifics, (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) #------------------------------------------------------------------------------ def send_client_setup(self): """ Get data of scenario related to Client """ self.s.sendto( str(self.num_of_records) + ';' + str(self.setup_tool.get_num_of_zones()) + ';' + self.setup_tool.get_domain_name() + ';' + self.setup_tool.get_server_ip_qry() + ';' + self.setup_tool.get_limit() + ';' + self.setup_tool.get_create_q_files() + ';' + str(self.setup_tool.get_num_of_cpu()) + ';' + self.setup_tool.get_num_dnsperf_processes(), (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) #------------------------------------------------------------------------------ def offline(self): """ Reports that Client or Server is not connected """ self.s.sendto('ERROR!! Client or Server is offline.', ('127.0.0.1', PORT)) #------------------------------------------------------------------------------ def validate(self): """ Verify if the connections and other procedures to run the test at Client and Server are ready """ self.write_to_log( '\t>> Validating process, process users, server connectivity, query files and zone files...' ) self.s.sendto('validate', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('validate', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'client 200 OK': client_status = True self.write_to_log('\tclient OK') elif buf.startswith('server 200 OK'): server_status = True tmp = buf.split(';') tmp.pop(0) self.mem = tmp self.write_to_log('\tserver OK') else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: self.write_to_log('\n') break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() ##------------------------------------------------------------------------------ def run(self, scenario): """ Executes the tests in each scenario """ print '>> Starting queries...' for q in self.query_type: self.insert_header(scenario, q) for clients in self.clients_list: self.write_to_log('\t>> Clients: ' + str(clients) + '\n') for j in range(self.repetitions): self.write_to_log('\t\t>> Repetition ' + str(j + 1) + '/' + str(self.repetitions) + '\n') self.control_test(clients, q) self.write_to_file(scenario, q) self.control_tear_down() self.write_to_log('\t>> Scenario successfully completed at ' + str(datetime.now()) + '\n') print '>> Scenario successfully completed!' ##------------------------------------------------------------------------------ def write_to_log(self, string): """ Write information about some process about client at file 'enum-bench-tool-master.log'""" fLog = open( self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-master.log', 'a') fLog.write(string) fLog.close() ##------------------------------------------------------------------------------ def control_test(self, clients, q): """ Control the tests rate """ self.s.sendto( str(clients) + ' ' + q, (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('-', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False self.write_to_log('\t\t\t>> teste running...') try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'server 200 OK': server_status = True self.write_to_log('\tserver ok!') elif buf == 'client 200 OK': client_status = True self.write_to_log('\tclient ok!') else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: timeout_count_down = int(self.setup_tool.get_timeout()) self.write_to_log('\ttimeout...\n') while (timeout_count_down > 0): time.sleep(1.0) timeout_count_down -= 1 break except KeyboardInterrupt: print '\t>> Exiting...' exit() ##------------------------------------------------------------------------------ def write_to_file(self, scenario, q): """ Writes the results from Client and Server at file """ server_status = False client_status = False f_stats = open( self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + scenario + '/' + q[4:] + '.dat', 'a') self.write_to_log('\t\t>> Writing to file...') self.s.sendto('send-result', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('send-result', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) try: while 1: buf, addr = self.s.recvfrom(2048) if buf.startswith('server 200 OK'): server_status = True server_result = buf.split(';')[1] self.write_to_log('\tserver ok!') elif buf.startswith('client 200 OK'): client_status = True self.write_to_log('\tclient ok!') client_result = buf.split(';')[1] if server_status and client_status: self.write_to_log('\n') f_stats.write(client_result + server_result + '\n') f_stats.close() break except KeyboardInterrupt: print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def control_tear_down(self): """ Send to client and server the instruction to run the function 'tear_down' """ server_status = False client_status = False self.write_to_log('\n\t>> Teardown session...') self.s.sendto('tear-down', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('tear-down', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'server 200 OK': server_status = True self.write_to_log('\tserver ok!') elif buf == 'client 200 OK': client_status = True self.write_to_log('\tclient ok!') if server_status and client_status: self.write_to_log('\n') break except KeyboardInterrupt: print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def parse_error(self, buf): """ Reports an error at log file and abort the operations at Client and Server""" self.write_to_log('>> ' + buf + '\n') print '>> ' + buf self.s.sendto('abort', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('abort', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) print '>> Session aborted!' exit() #------------------------------------------------------------------------------ def insert_header(self, scenario, q): """ Insert a header with all process and unities involved""" f_stats = open( self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + scenario + '/' + q[4:] + '.dat', 'w') f_stats.write('# session:\t' + self.setup_tool.get_session_name() + '\n' + '# scenario:\t' + scenario + '\n' + '# records:\t' + q[4:] + '\n') for u in self.mem: f_stats.write('# ' + u + '\n') title = '#Clients\tCompleted\tLost\tthroughput\tLatency\t\t\t\tdnsperf\tnetwork\tnet_max' for process in self.setup_tool.get_processes().split(): title += '\t' + process unity = '#\t\t(%)\t(%)\t(qps)\tmean(s)\tstd\t\tcpu(%)\t(Mbps)\t(Mbps)' for process in self.setup_tool.get_processes().split(): unity += '\tcpu(%)' f_stats.write(title + '\n' + unity + '\n') f_stats.close()
class Master(object): #------------------------------------------------------------------------------ def __init__(self): self.anime = Animation () host = '' # Bind server to all interfaces self.s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) # Creating the socket using IPv4, UDP self.s.bind((host, PORT)) # Binding Server to all interfaces and the chosen port. self.setup_tool = SetupTool() self.paths = self.setup_tool.parse_file('../config/paths.dat') self.setup_tool.get_setup_data('../config/session-setup.dat') self.clients_list = self.setup_tool.get_clients_list() self.query_type = self.setup_tool.get_query_type().split() self.repetitions = int(self.setup_tool.get_repetitions()) fLog = open(self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-master.log', 'w') fLog.close() # Refreshing results folder and temp folder for s in self.setup_tool.get_scenario_list(): self.setup_tool.refresh_folder(self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + s + '/') self.setup_tool.refresh_folder(self.paths['TEMP_FOLDER_PATH']) #------------------------------------------------------------------------------ # Hiago, this module is temporary. Don't worry about it def test_estimation_time (self): #Number of scenarios self.num_scen = len (self.query_type) self.iterations = len(self.query_type) * self.repetitions * len(self.clients_list) total_time = len(self.query_type) * self.repetitions * len(self.clients_list) * (int(self.setup_tool.get_limit()) + int(self.setup_tool.get_timeout()) + 10) duration = timedelta (seconds=total_time) self.start = datetime.now() self.end = self.start + duration self.write_to_log('\t>> Scenario run time\n\t\t>> Estimated: ' + str(duration) + '\n' + '\t\t>> Starting scenario at: ' + str(self.start) + '\n') print '\n>> Estimated run time: ', duration print '>> Starting scenario at: ', self.start print '>> Estimation to finish this scenario: ', self.end #------------------------------------------------------------------------------ def start(self): """ executes the tool in each scenario and register the results """ self.write_to_log('>> Session started at ' + str(datetime.now()) + '\n') print '>> Session started at ', datetime.now() self.check_connection() scen = 1 for scenario in self.setup_tool.get_scenario_list(): self.write_to_log('>> Running scenario ' + str(scen) + '\n') self.setup(scenario) self.validate() self.test_estimation_time() self.run(scenario) scen += 1 print '>> Session finished at ', datetime.now() #------------------------------------------------------------------------------ def check_connection(self): """ Check the connections between Server and Master, Client and Master """ self.write_to_log('>> Checking connection...\n') self.s.sendto('ping', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('ping', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) # wait 2 seconds for the answer before considering remote machine off-line. t = Timer(2, self.offline) t.start() server_status = False client_status = False try: while 1: buf, addr = self.s.recvfrom(1024) if buf == 'server pong': t.cancel() self.write_to_log('\t>> Server is alive.\n') server_status = True elif buf == 'client pong': t.cancel() self.write_to_log('\t>> Client is alive.\n') client_status = True else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def setup(self, scenario): """ Establishes connections and gets the necessary data to run the tests""" self.write_to_log('\t>> Setup phase...') self.s.sendto('setup', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('setup', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False self.num_of_records = self.setup_tool.parse_unity(scenario) if self.setup_tool.get_software() == 'bind' or self.setup_tool.get_software() == 'nsd': print '\nquery files\t\t|\tzone files' elif self.setup_tool.get_software() == 'pdns' or self.setup_tool.get_software() == 'mydns': print '\nquery files\t\t|\tMySQL' try: while 1: buf, addr = self.s.recvfrom(4096) if buf == 'server 100 OK': self.send_server_setup() elif buf == 'client 100 OK': self.send_client_setup() elif buf == 'server 400 Bad Request': self.write_to_log('>> Message to server was corrupted. Sending again...') self.send_server_setup() elif buf == 'client 400 Bad Request': self.write_to_log('>> Message to client was corrupted. Sending again...') self.send_client_setup() elif buf == 'server 200 OK': server_status = True elif buf == 'client 200 OK': client_status = True elif buf.startswith('q'): self.anime.double_hashtag_bar(int(buf.split(';')[1]), 1) elif buf.startswith('z'): self.anime.double_hashtag_bar(int(buf.split(';')[1]), 2) else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() self.write_to_log('done!\n') #------------------------------------------------------------------------------ def send_server_setup (self): """ Get data of scenario related to Server """ default = str(self.setup_tool.get_software() + ';' + self.setup_tool.get_processes() + ';' + self.setup_tool.get_processes_users() + ';' + str(self.num_of_records) + ';' + str(self.setup_tool.get_num_of_zones()) + ';' + self.setup_tool.get_domain_name() + ';' + self.setup_tool.get_server_ip_qry() + ';' + str(self.setup_tool.get_num_of_naptr()) + ';' + self.setup_tool.get_limit() + ';' + str(self.setup_tool.get_num_of_cpu()) + ';' + str(self.setup_tool.update_enabled()) + ';' + str(self.setup_tool.get_update_rate()) + ';') if self.setup_tool.get_software() == 'bind' or self.setup_tool.get_software() == 'nsd': software_specifics = str(self.setup_tool.get_server_pass() + ';' + self.setup_tool.get_create_zones() + ';' + self.setup_tool.get_restart_software()) elif self.setup_tool.get_software() == 'pdns' or self.setup_tool.get_software() == 'mydns': software_specifics = str(self.setup_tool.get_mysql_database() + ';' + self.setup_tool.get_mysql_user() + ';' + self.setup_tool.get_mysql_user_pass() + ';' + self.setup_tool.get_create_database()) self.s.sendto(default + software_specifics, (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) #------------------------------------------------------------------------------ def send_client_setup(self): """ Get data of scenario related to Client """ self.s.sendto(str(self.num_of_records) + ';' + str(self.setup_tool.get_num_of_zones()) + ';' + self.setup_tool.get_domain_name() + ';' + self.setup_tool.get_server_ip_qry() + ';' + self.setup_tool.get_limit() + ';' + self.setup_tool.get_create_q_files() + ';' + str(self.setup_tool.get_num_of_cpu()) + ';' + self.setup_tool.get_num_dnsperf_processes(), (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) #------------------------------------------------------------------------------ def offline (self): """ Reports that Client or Server is not connected """ self.s.sendto('ERROR!! Client or Server is offline.', ('127.0.0.1', PORT)) #------------------------------------------------------------------------------ def validate(self): """ Verify if the connections and other procedures to run the test at Client and Server are ready """ self.write_to_log('\t>> Validating process, process users, server connectivity, query files and zone files...') self.s.sendto('validate', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('validate', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'client 200 OK': client_status = True self.write_to_log('\tclient OK') elif buf.startswith('server 200 OK'): server_status = True tmp = buf.split(';') tmp.pop(0) self.mem = tmp self.write_to_log('\tserver OK') else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: self.write_to_log('\n') break except KeyboardInterrupt: self.write_to_log('>> Ctrl+c pressed! Exiting...\n') print '\t>> Exiting...' exit() ##------------------------------------------------------------------------------ def run(self, scenario): """ Executes the tests in each scenario """ print '>> Starting queries...' for q in self.query_type: self.insert_header(scenario, q) for clients in self.clients_list: self.write_to_log('\t>> Clients: ' + str(clients) + '\n') for j in range(self.repetitions): self.write_to_log('\t\t>> Repetition ' + str(j + 1) + '/' + str(self.repetitions) + '\n') self.control_test(clients, q) self.write_to_file(scenario, q) self.control_tear_down() self.write_to_log('\t>> Scenario successfully completed at ' + str(datetime.now()) + '\n') print '>> Scenario successfully completed!' ##------------------------------------------------------------------------------ def write_to_log(self, string): """ Write information about some process about client at file 'enum-bench-tool-master.log'""" fLog = open(self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-master.log', 'a') fLog.write(string) fLog.close() ##------------------------------------------------------------------------------ def control_test(self, clients, q): """ Control the tests rate """ self.s.sendto(str(clients) + ' ' + q, (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('-', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) server_status = False client_status = False self.write_to_log('\t\t\t>> teste running...') try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'server 200 OK': server_status = True self.write_to_log('\tserver ok!') elif buf == 'client 200 OK': client_status = True self.write_to_log('\tclient ok!') else: if buf.find('ERROR') >= 0: self.parse_error(buf) if server_status and client_status: timeout_count_down = int(self.setup_tool.get_timeout()) self.write_to_log('\ttimeout...\n') while (timeout_count_down > 0): time.sleep (1.0) timeout_count_down -= 1 break except KeyboardInterrupt: print '\t>> Exiting...' exit () ##------------------------------------------------------------------------------ def write_to_file(self, scenario, q): """ Writes the results from Client and Server at file """ server_status = False client_status = False f_stats = open(self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + scenario + '/' + q[4:] + '.dat', 'a') self.write_to_log('\t\t>> Writing to file...') self.s.sendto('send-result', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('send-result', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) try: while 1: buf, addr = self.s.recvfrom(2048) if buf.startswith('server 200 OK'): server_status = True server_result = buf.split(';')[1] self.write_to_log('\tserver ok!') elif buf.startswith('client 200 OK'): client_status = True self.write_to_log('\tclient ok!') client_result = buf.split(';')[1] if server_status and client_status: self.write_to_log('\n') f_stats.write(client_result + server_result + '\n') f_stats.close() break except KeyboardInterrupt: print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def control_tear_down(self): """ Send to client and server the instruction to run the function 'tear_down' """ server_status = False client_status = False self.write_to_log('\n\t>> Teardown session...') self.s.sendto('tear-down', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('tear-down', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) try: while 1: buf, addr = self.s.recvfrom(2048) if buf == 'server 200 OK': server_status = True self.write_to_log('\tserver ok!') elif buf == 'client 200 OK': client_status = True self.write_to_log('\tclient ok!') if server_status and client_status: self.write_to_log('\n') break except KeyboardInterrupt: print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def parse_error(self, buf): """ Reports an error at log file and abort the operations at Client and Server""" self.write_to_log('>> ' + buf + '\n') print '>> ' + buf self.s.sendto('abort', (self.setup_tool.get_client_ip_ctrl(), CLIENTPORT)) self.s.sendto('abort', (self.setup_tool.get_server_ip_ctrl(), SERVERPORT)) print '>> Session aborted!' exit() #------------------------------------------------------------------------------ def insert_header(self, scenario, q): """ Insert a header with all process and unities involved""" f_stats = open(self.setup_tool.get_save_dir() + self.setup_tool.get_session_name() + '/' + scenario + '/' + q[4:] + '.dat', 'w') f_stats.write('# session:\t' + self.setup_tool.get_session_name() + '\n' + '# scenario:\t' + scenario + '\n' + '# records:\t' + q[4:] + '\n') for u in self.mem: f_stats.write('# ' + u + '\n') title = '#Clients\tCompleted\tLost\tthroughput\tLatency\t\t\t\tdnsperf\tnetwork\tnet_max' for process in self.setup_tool.get_processes().split(): title += '\t' + process unity = '#\t\t(%)\t(%)\t(qps)\tmean(s)\tstd\t\tcpu(%)\t(Mbps)\t(Mbps)' for process in self.setup_tool.get_processes().split(): unity += '\tcpu(%)' f_stats.write(title + '\n' + unity + '\n') f_stats.close()
class Client (object): def __init__(self): """Initializing the configurations at "Client" """ self.setup_tool = SetupTool() self.paths = self.setup_tool.parse_file('../config/paths.dat') host = '' # Bind server to all interfaces self.s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) # Creating the socket using IPv4, UDP self.s.bind((host, PORT)) # Binding Server to all interfaces and the chosen port. fLog = open(self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-client.log', 'w') fLog.close() #------------------------------------------------------------------------------ def standby(self): """ Starts a session that wait for instructions to start the configurations or run the software""" print '>> STANDBY MODE...' try: while 1: buf, addr = self.s.recvfrom (2048) self.addr = addr if buf == 'ping': self.s.sendto('client pong', self.addr) # Answering to confirm that client is ready to setup. if buf == 'setup': self.setup() elif buf == 'validate': if self.server_is_validated(): self.run() elif buf == 'abort': self.abort() except KeyboardInterrupt: print '\t>> Exiting...' exit() #------------------------------------------------------------------------------ def setup(self): """Generates configuration files at client""" print '>> Session started...' self.write_to_log('>> Starting new session.\n>> Command received: setup. Setting up session...') self.s.sendto('client 100 OK', self.addr) # Answering to confirm that client is ready to setup. while 1: # Waiting for setup data. buf, addr = self.s.recvfrom (4096) if self.setup_tool.get_client_setup_data(buf): break else: self.write_to_log('>> The message is corrupted. Requesting new message...\n') self.s.sendto('client 400 Bad Request', addr) if self.setup_tool.create_q_files(): QueryFileGenerator(self.setup_tool, self.s, addr) # This generate query files. else: self.s.sendto('q;100', addr) # Confirming success. self.s.sendto('client 200 OK', addr) self.write_to_log('done!\n') #------------------------------------------------------------------------------ def server_is_validated (self): """ Establishes connection with the server and tests the query files and zone files""" self.write_to_log('>> Command received: verify. Validating server, query files and zone files...') # Getting query samples of the queries stored in query files. tmp = [] tmp.append(self.setup_tool.get_fqdn(0, 0)) # authoritative and existent tmp.append(self.setup_tool.get_fqdn(0, 0 + self.setup_tool.get_zone_size())) # authoritative and non-existent tmp.append(self.setup_tool.get_fqdn_for_non_autho(0, 0)) # non-authoritative and non-existent # Using dig command to query the server. self.status = [] for k in tmp: output_file = open (self.paths['TEMP_FOLDER_PATH'] + 'dig-output.dat', 'w') call(['dig', '@' + self.setup_tool.get_server_ip_qry(), k, 'NAPTR'], stdout=output_file) output_file.close () self.dig_output_parser() # Verifying if the answers are ok. if (self.status == ['autho-exist', 'autho-non-exist', 'non-autho-non-exist']): self.s.sendto('client 200 OK', self.addr) self.write_to_log('done!\n') return True else: print '>> Session aborted!' self.write_to_log('>> ERROR!! Dig command reported strange behavior. Please verify server connectivity, zone files and query files.\n') self.s.sendto('ERROR!! Dig command reported strange behavior. Please verify server connectivity, zone files and query files.', self.addr) return False #------------------------------------------------------------------------------ def dig_output_parser(self): """Classifies the type of server between (authoritarian, non - authoritarian, existent and non - existent)""" f = open (self.paths['TEMP_FOLDER_PATH'] + 'dig-output.dat') for line in f: if line.startswith(';; flags:'): if line.split()[3] == 'aa': if (int(line.split()[8][:-1])): self.status.append('autho-exist') else: if (int(line.split()[10][:-1])): self.status.append('autho-non-exist') else: self.status.append('non-autho-non-exist') else: if (int(line.split()[7][:-1])): self.status.append('autho-exist') else: if (int(line.split()[9][:-1])): self.status.append('autho-non-exist') else: self.status.append('non-autho-non-exist') #------------------------------------------------------------------------------ def run (self): """ Is the function that receives the instructions from 'master' and calls the correspondent process""" self.completed = [] self.lost = [] self.qps = [] self.mean = [] self.std = [] self.cpu_repetitions = [] self.network_repetitions = [] self.network_max = [] self.write_to_log('>> Waiting for remote command from master...\n') try: while 1: # Receive from master the next instructions buf, addr = self.s.recvfrom (2048) if buf == 'send-result': self.send_result() elif buf == 'tear-down': self.tear_down() break elif buf == 'abort': self.abort() break else: self.num_clients_total = int(buf.split()[0]) self.query_file = buf.split()[1] self.num_dnsperf_processes = int(self.setup_tool.get_num_dnsperf_processes()) if not self.trigger_dnsperf(): break if not self.test_is_validated(): break except KeyboardInterrupt: print '\t>> Exiting...' exit (0) #------------------------------------------------------------------------------ def trigger_dnsperf(self): """ Executates the dnsperf tool which is an authoritative-server-specific DNS performance testing tool""" self.write_to_log('>> Command received: Trigger dnsperf') quotient = self.num_clients_total / self.num_dnsperf_processes rest = self.num_clients_total % self.num_dnsperf_processes if quotient: num_clients_per_process = str(quotient) for i in range(self.num_dnsperf_processes): if i == self.num_dnsperf_processes - 1: num_clients_per_process = str(quotient + rest) output_file = open(self.paths['TEMP_FOLDER_PATH'] + 'dnsperf-output-' + str(i) + '.dat', 'w') Popen(['dnsperf', '-s', self.setup_tool.get_server_ip_qry(), '-d', self.paths['QUERY_FILES_FOLDER_PATH'] + self.query_file + '-' + str(i) + '.dat', '-l', self.setup_tool.get_limit(), '-q', num_clients_per_process, '-H', '10', '-T', '1', '-c'], stdout=output_file) else: output_file = open(self.paths['TEMP_FOLDER_PATH'] + 'dnsperf-output-' + str(i) + '.dat', 'w') Popen(['dnsperf', '-s', self.setup_tool.get_server_ip_qry(), '-d', self.paths['QUERY_FILES_FOLDER_PATH'] + self.query_file + '-' + str(i) + '.dat', '-l', self.setup_tool.get_limit(), '-q', num_clients_per_process, '-H', '10', '-T', '1', '-c'], stdout=output_file) else: num_clients_per_process = '1' self.num_dnsperf_processes = rest for i in range(self.num_dnsperf_processes): output_file = open(self.paths['TEMP_FOLDER_PATH'] + 'dnsperf-output-' + str(i) + '.dat', 'w') Popen(['dnsperf', '-s', self.setup_tool.get_server_ip_qry(), '-d', self.paths['QUERY_FILES_FOLDER_PATH'] + self.query_file + '-' + str(i) + '.dat', '-l', self.setup_tool.get_limit(), '-q', num_clients_per_process, '-H', '10', '-T', '1', '-c'], stdout=output_file) self.write_to_log('\tdone!\n') ## Monitoring network flow self.trigger_bwm() ## Monitoring dnsperf cpu utilization if not self.trigger_top(): return False ## Waiting 10 seconds to make sure that all dnsperf process were finished. self.coutdown_timer(10) return True #------------------------------------------------------------------------------ def test_is_validated (self): """ Verifies if during the procedure there were usage of CPU and Network and gets the results to put them in lists""" self.write_to_log('>> Test completed. Validating test...') q_sent_total = 0.0 q_completed_total = 0 q_lost_total = 0 qps_total = 0.0 mean_total = 0.0 std_total = 0.0 for i in range(self.num_dnsperf_processes): f = open(self.paths['TEMP_FOLDER_PATH'] + 'dnsperf-output-' + str(i) + '.dat') for line in f: if line.startswith(' Queries sent:'): q_sent = int(line.split()[2]) elif line.startswith(' Queries completed:'): q_completed = int(line.split()[2]) elif line.startswith(' Queries lost:'): q_lost = int(line.split()[2]) elif line.startswith(' Queries per second:'): qps = float(line.split()[3]) elif line.startswith('Latency:'): mean = float(line.split()[8]) std = float(line.split()[11]) # PDNS HAS A BUG WHICH BREAKS THE VALIDATING TEST. I'M LOOKING FOR A SOLUTION. # FOR WHILE I'LL BELIEVE THAT SHIT DOESN'T HAPPEN! HOW INGENOUS AM I! # elif line.startswith(' Returned NOERROR:'): # noerror = int(line.split()[2]) # elif line.startswith(' Returned NXDOMAIN:'): # nxdomain = int(line.split()[2]) # elif line.startswith(' Returned REFUSED:') or line.startswith(' Returned SERVFAIL:'): # refused = int(line.split()[2]) # # # if self.setup_tool.get_software() != 'pdns': # PDNS has a bug which fails the validating test # # Validating test. # if self.query_file == 'qry-autho-exist.dat': # if noerror != q_completed: # self.write_to_log('>> ERROR!! Not querying only existing records.\n') # self.s.sendto('ERROR!! Not querying only existing records.', self.addr) # return False # elif self.query_file == 'qry-autho-non-exist.dat': # if nxdomain != q_completed: # self.write_to_log('>> ERROR!! Not querying only non existing records.') # self.s.sendto('ERROR!! Not querying only non existing records.', self.addr) # return False # elif self.query_file == 'qry-non-autho-non-exist.dat': # if refused != q_completed: # self.write_to_log('>> ERROR!! Not querying only non existing non authoritative records.\n') # self.s.sendto('ERROR!! Not querying only non existing non authoritative records.', self.addr) # return False q_sent_total += q_sent q_completed_total += q_completed q_lost_total += q_lost qps_total += qps mean_total += mean std_total += std self.completed.append(100 * q_completed_total / q_sent_total) self.lost.append(100 * q_lost_total / q_sent_total) self.mean.append(mean_total / self.num_dnsperf_processes) self.std.append(std_total / self.num_dnsperf_processes) self.qps.append(qps_total) if not self.get_dnsperf_cpu_usage(): return False if not self.get_network_usage(): return False self.write_to_log('done!\n') self.s.sendto('client 200 OK', self.addr) return True #------------------------------------------------------------------------------ def get_dnsperf_cpu_usage(self): """ Based on 'top' results gets the numbers that represents the usage of CPU during the process and put them is a list to return""" f = open(self.paths['TEMP_FOLDER_PATH'] + 'top-output-dnsperf.dat').readlines() cpu_samples = [] cpu_sum = 0 not_first_flag = False for line in f: if line.startswith('top - '): if not_first_flag: cpu_samples.append(cpu_sum) cpu_sum = 0 if line.find('dnsperf') > 0: not_first_flag = True cpu_sum += float(line.split()[8]) if not cpu_samples: self.write_to_log('>> ERROR!! Process dnsperf is not alive.\n') self.s.sendto('ERROR!! Process dnsperf is not alive.', self.addr) return False self.cpu_repetitions.append(numpy.mean(cpu_samples)) return True #------------------------------------------------------------------------------ def get_network_usage(self): """ Gets from log file from BWM the informations about network usage if they exists and returns them """ f = open(self.paths['TEMP_FOLDER_PATH'] + 'bwm.log').readlines() network_samples = [] for line in f: if line.split(';')[1] == 'eth0': #Hard code eth0. network_samples.append(8 * float(line.split(';')[4])) if not network_samples: self.write_to_log('>> ERROR!! Network file is empty.\n') self.s.sendto('>> ERROR!! Network file is empty.', self.addr) return False self.network_repetitions.append(numpy.mean(network_samples)) self.network_max.append(max(network_samples)) return True #------------------------------------------------------------------------------ def send_result (self): """ Gets the data, process them and sends their mean as final results at appropriate units """ self.write_to_log('>> Command received: send-result') completed = round(numpy.mean(self.completed), 3) lost = round(numpy.mean(self.lost), 3) qps = int(numpy.mean(self.qps)) mean = round(numpy.mean(self.mean), 6) std = round(numpy.mean(self.std), 6) cpu = round(numpy.mean(self.cpu_repetitions) / self.setup_tool.get_num_of_cpu(), 2) network_mean = round(numpy.mean(self.network_repetitions) * pow(10, -6), 2) ## The result is multiplied by potency due to transform the unity from bits to MegaBytes network_max = round(max(self.network_max) * pow(10, -6), 2) self.completed = [] self.lost = [] self.qps = [] self.mean = [] self.std = [] self.cpu_repetitions = [] self.network_repetitions = [] self.network_max = [] self.s.sendto('client 200 OK;' + str(self.num_clients_total) + '\t\t' + str(completed) + '\t' + str(lost) + '\t' + str(qps) + '\t' + str(mean) + '\t' + str(std) + '\t' + str(cpu) + '\t' + str(network_mean) + '\t' + str(network_max), self.addr) self.write_to_log('\tdone!\n') #------------------------------------------------------------------------------ def tear_down(self): """ Register at 'enum-bench-tool-client.log' that the procedure has finished""" self.write_to_log('>> Command received: tear-down.\n') self.s.sendto ('client 200 OK', self.addr) self.write_to_log('>> Session successfully completed!\n') print '>> Session successfully completed!' print '>> STANDBY MODE...' #------------------------------------------------------------------------------ def abort(self): """ Register at 'enum-bench-tool-client.log' that the procedure was aborted""" self.write_to_log('>> Command received: abort. Session aborted!\n') print '>> Session aborted!' print '>> STANDBY MODE...' #------------------------------------------------------------------------------ def write_to_log(self, string): """ Write information about some process about client at file 'enum-bench-tool-client.log'""" fLog = open(self.paths['LOG_FOLDER_PATH'] + 'enum-bench-tool-client.log', 'a') fLog.write(string) fLog.close() #------------------------------------------------------------------------------ def trigger_top(self): """ executes the top command which provides informations about selected process indicates by the PID """ self.write_to_log('>> Triggering Top...') pid_list = self.get_dnsperf_pid_list() if pid_list: pid_arg = '' # process id arguments for command top. for p in pid_list: pid_arg += ' -p ' + p else: return False call('top' + pid_arg + ' -d ' + '1' + ' -n ' + self.setup_tool.get_limit() + ' -b > ' + self.paths['TEMP_FOLDER_PATH'] + 'top-output-dnsperf.dat', shell=True) self.write_to_log('\tdone!\n') return True #------------------------------------------------------------------------------ def get_dnsperf_pid_list(self): """ Gets the dnsperf pid's(process identification number) to put them in a list if them exist""" pid_list = [] call("ps -C dnsperf | grep dnsperf | tr -c '0123456789 \n' '?' | cut -d '?' -f1 | tr -d ' ' > " + self.paths['TEMP_FOLDER_PATH'] + "dnsperf-pid.dat", shell=True) f = open(self.paths['TEMP_FOLDER_PATH'] + 'dnsperf-pid.dat').readlines() if f: for line in f: pid_list.append(line.rstrip()) else: self.write_to_log('>> ERROR: the process dnsperf is not alive.\n') self.s.sendto ('ERROR: the process dnsperf is not alive.', self.addr) return [] return pid_list #------------------------------------------------------------------------------ def coutdown_timer(self, interval): ## COLOCAR UM "N" no COUNTDOWN """ Regressive timmer """ timeout_count_down = interval while (timeout_count_down > 0): time.sleep (1.0) timeout_count_down -= 1 #------------------------------------------------------------------------------ def trigger_bwm(self): """ starts bwm tool with is as bandwidth monitor """ self.write_to_log('>> Triggering bwm-ng...') call(['rm', '-f', self.paths['TEMP_FOLDER_PATH'] + 'bwm.log']) #VERIFICAR SE NAO ABRE UM ARQUIVO "W" #Hard code 'eth0'. Popen(['bwm-ng', '-I', 'eth0', '-t', '1000', '-c', self.setup_tool.get_limit(), '-o', 'csv', '-F', self.paths['TEMP_FOLDER_PATH'] + 'bwm.log']) self.write_to_log('\tdone!\n')