Beispiel #1
0
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()
Beispiel #2
0
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()        
Beispiel #3
0
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')