예제 #1
0
 def __init__(self):
     threading.Thread.__init__(self)
     self.__connect__()
     self.req_number = 0
     self.samples_number = -1
     
     #Get the Topology from Topology Server
     self.__get_topology__()
     
     #Create the minimum spanning tree from the topology graph        
     complete_group = self.__get_complete_group__()
     self.paths_by_source = {}
     
     #Copy the array because it will be changed during the calc path's process
     temp_hosts = complete_group.hosts[0:]
     
     self.dc = NoxAppCollector()
     self.dc.write_header()
     self.dc.collect_begin_mst(len(self.topology.hosts), time.time())
     current = 1
     for host in complete_group.hosts:
         #begin_mst_time = time.time()
         mst = MSTParser(self.topology, host).get_mst( algorithm = 'prim' )
         
         #begin_dp_time = time.time()
         mst_dict = self.__generate_mst_dic__(mst)
         weight_dict = self.__calc_weight__(host, mst_dict)
         paths = self.my__calc_paths_by_source__(host, temp_hosts, mst_dict, weight_dict)
         
         #begin_bt_time = time.time()
         #mst = self.__duplicate_paths__(mst)
         #paths = self.__calc_paths_by_source__(mst, host, temp_hosts)
         #end_time = time.time()
         
         #print 'Programacao Dinamica:\n\t', _paths
         #print '\n'
         #print 'Backing Tracking:\n\t', paths
         #print '\n'
         #print 'MST Time:', repr (begin_dp_time - begin_mst_time)
         #print 'Tempo da Programao Dinamica:', repr (begin_bt_time - begin_dp_time)
         #print 'Tempo do Backing Tracking:', repr (end_time - begin_bt_time)
         #sys.exit()
         self.paths_by_source[host.id] = paths
         current += 1
         
     self.dc.collect_end_mst(len(self.topology.hosts), time.time())
     
     #Get the actual Multicast Group from the Topology Server
     self.__get_group__()
     self.path_to_host = self.paths_by_source[self.current_source]
     #Calculate the initial installation hops
     self.dc.collect_begin_paths(len(self.active_hosts), time.time())
     self.__calcultate_initial_hops__()
     
     #Generate the initial openflow installations list
     self.current_installs = self.__generate_installs__()
     self.installs_by_router = {}
     for install in self.current_installs:
         self.installs_by_router[install.routerId] = install
     
     self.dc.collect_end_paths(len(self.active_hosts), time.time())
     
     #Set the begin configurations status
     self.installs_to_remove = []
     self.installs_to_do = self.current_installs
     
     self.dc.collect_event_effects(None, len(self.installs_to_do), len(self.installs_to_remove), time.time())
     
     self.has_installation = True
     
     #Start listening to events
     self.nox = None
예제 #2
0
class InstallationManager(threading.Thread):
    def get_installs_to_remove(self):
        return self.installs_to_remove
    
    def get_installs_to_do(self):
        return self.installs_to_do
    
    def __init__(self):
        threading.Thread.__init__(self)
        self.__connect__()
        self.req_number = 0
        self.samples_number = -1
        
        #Get the Topology from Topology Server
        self.__get_topology__()
        
        #Create the minimum spanning tree from the topology graph        
        complete_group = self.__get_complete_group__()
        self.paths_by_source = {}
        
        #Copy the array because it will be changed during the calc path's process
        temp_hosts = complete_group.hosts[0:]
        
        self.dc = NoxAppCollector()
        self.dc.write_header()
        self.dc.collect_begin_mst(len(self.topology.hosts), time.time())
        current = 1
        for host in complete_group.hosts:
            #begin_mst_time = time.time()
            mst = MSTParser(self.topology, host).get_mst( algorithm = 'prim' )
            
            #begin_dp_time = time.time()
            mst_dict = self.__generate_mst_dic__(mst)
            weight_dict = self.__calc_weight__(host, mst_dict)
            paths = self.my__calc_paths_by_source__(host, temp_hosts, mst_dict, weight_dict)
            
            #begin_bt_time = time.time()
            #mst = self.__duplicate_paths__(mst)
            #paths = self.__calc_paths_by_source__(mst, host, temp_hosts)
            #end_time = time.time()
            
            #print 'Programacao Dinamica:\n\t', _paths
            #print '\n'
            #print 'Backing Tracking:\n\t', paths
            #print '\n'
            #print 'MST Time:', repr (begin_dp_time - begin_mst_time)
            #print 'Tempo da Programao Dinamica:', repr (begin_bt_time - begin_dp_time)
            #print 'Tempo do Backing Tracking:', repr (end_time - begin_bt_time)
            #sys.exit()
            self.paths_by_source[host.id] = paths
            current += 1
            
        self.dc.collect_end_mst(len(self.topology.hosts), time.time())
        
        #Get the actual Multicast Group from the Topology Server
        self.__get_group__()
        self.path_to_host = self.paths_by_source[self.current_source]
        #Calculate the initial installation hops
        self.dc.collect_begin_paths(len(self.active_hosts), time.time())
        self.__calcultate_initial_hops__()
        
        #Generate the initial openflow installations list
        self.current_installs = self.__generate_installs__()
        self.installs_by_router = {}
        for install in self.current_installs:
            self.installs_by_router[install.routerId] = install
        
        self.dc.collect_end_paths(len(self.active_hosts), time.time())
        
        #Set the begin configurations status
        self.installs_to_remove = []
        self.installs_to_do = self.current_installs
        
        self.dc.collect_event_effects(None, len(self.installs_to_do), len(self.installs_to_remove), time.time())
        
        self.has_installation = True
        
        #Start listening to events
        self.nox = None
        #self.start()
        
    def __connect__(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        address = ('localhost', 8887)
        s.connect( address )
        clientSocket = LongMessageSocket(s)
        self.socket = clientSocket
        
    def __belong__(self, element, vlist):
        for i in vlist:
            if i == element:
                return 1
        return 0
        
    def __next_req_number__(self):
        self.req_number = self.req_number +1
        return self.req_number
        
    def __get_topology__(self):
        request = Request()
        request.id = self.__next_req_number__()
        request.action = request.ACTION.GET_TOPOLOGY
        jsonMessage = request.toJson()
        
        self.socket.send( jsonMessage )
        jsonTopology = self.socket.recv()
        self.topology = TopologyFactory().decodeJson( jsonTopology )
        
    def __get_path__(self, source, destiny, mpath, mst):
        mpath.append(source)
        for t in mst:
            node1, node2, weight = t
            if node1 == str(source):
                if node2 == str(destiny):
                    mpath.append(int(node2))
                    return mpath
                
                srctemp = int(node2)
                if self.__belong__(srctemp, mpath) == 0:
                    mpath = self.__get_path__(srctemp, destiny, mpath, mst)
                    last = mpath[len(mpath)-1]
                    if last == destiny:
                        break
                    else:
                        mpath.pop()
        return mpath
    
    def __generate_mst_dic__(self, mst):
        mst_dictionary = {}
        for t in mst:
            node1, node2, weight = t
            if mst_dictionary.has_key(int(node1)):
                mst_dictionary[int(node1)].append(int(node2))
            else:
                mst_dictionary[int(node1)] = []
                mst_dictionary[int(node1)].append(int(node2))
                
            if mst_dictionary.has_key(int(node2)):
                mst_dictionary[int(node2)].append(int(node1))
            else:
                mst_dictionary[int(node2)] = []
                mst_dictionary[int(node2)].append(int(node1))
        
        return mst_dictionary
    
    def __calc_weight__(self, source, mst_dict):
        weight_dict = {}
        calculated_nodes = []
        nodes_to_calculate = []
        weight_dict[source.id] = 0
        for node in mst_dict[source.id]:
            nodes_to_calculate.append((node, 1))
        
        calculated_nodes.append(source.id)
        
        while len(nodes_to_calculate) > 0:
            nodeid, weight = nodes_to_calculate.pop(0)
            if nodeid not in calculated_nodes:
                weight_dict[nodeid] = weight
                calculated_nodes.append(nodeid)
                for child_node in mst_dict[nodeid]:
                    nodes_to_calculate.append((child_node, weight + 1))
                    
        return weight_dict
    
    def __calc_path__(self, source, destiny, mst_dict, weight_dict):
        path = []
        path.insert(0, destiny)
        linked_nodes = mst_dict[destiny]
        next_node = linked_nodes[0]
        next_node_weight = weight_dict[linked_nodes[0]]
        while True:
            for node in linked_nodes:
                if node == source:
                    path.insert(0, node)
                    return path
                elif weight_dict[node] < next_node_weight:
                    next_node = node
                    next_node_weight = weight_dict[node]
                    
            path.insert(0, next_node)     
            linked_nodes = mst_dict[next_node]
            next_node = linked_nodes[0]
            next_node_weight = weight_dict[linked_nodes[0]]

    
    def get_path(self, nodeid):
        return self.path_to_host[nodeid]
    
    def get_all_paths(self):
        paths = []
        for path in self.path_to_host.values():
            paths.append(path)
        
        return paths
    
    def __get_complete_group__(self):
        request = Request()
        request.id = self.__next_req_number__()
        request.action = request.ACTION.GET_COMPLETE_GROUP
        jsonMessage = request.toJson()
        
        self.socket.send( jsonMessage )
        jsonGroup = self.socket.recv()
        
        group = GroupFactory().decodeJson( jsonGroup )
        return group;
        
        
    def __calc_paths_by_source__(self, mst, multicast_source, hosts):
        path_to_host = {}
        for host in hosts:
            if host.id != multicast_source.id:
                opath = []
                self.__get_path__(multicast_source.id, host.id, opath, mst)
                path_to_host[host.id] = opath
                
        
        #hosts.append(multicast_source)
        return path_to_host
    
    def my__calc_paths_by_source__(self, source, hosts, mst_dict, weight_dict):
        path_to_host = {}
        for destiny in hosts:
            if destiny.id != source.id:
                path_to_host[destiny.id] = self.__calc_path__(source.id, destiny.id, mst_dict, weight_dict)
                
        
        #hosts.append(multicast_source)
        return path_to_host
        
    def __get_group__(self):
        request = Request()
        request.id = self.__next_req_number__()
        request.action = request.ACTION.GET_GROUP
        jsonMessage = request.toJson()
        
        self.socket.send( jsonMessage )
        jsonGroup = self.socket.recv()
        group = GroupFactory().decodeJson( jsonGroup )
        self.current_source = group.source
        self.active_hosts = []
        for host in group.hosts:
            self.active_hosts.append(host.id)
        
    def __duplicate_paths__(self, mst):
        tmp = []
        tmp.extend(mst)
        for mytuple in mst:
            node1,node2,peso = mytuple
            t = node2, node1, peso
            tmp.append(t)
        return tmp
        
    def __calcultate_initial_hops__(self):
        #Get the paths to all the active hosts
        paths = []
        for host in self.active_hosts:
            paths.append(self.path_to_host[host])
            
        #Generate the list of point-to-point installations
        self.hops = self.__calcule_hops__(paths)
        self.hops.sort()
        
    def __calcule_hops__(self, paths):
        hops = []
        for path in paths:
            for i in range(1, len(path)-1):
                # (NODEID, PREVIOUS_NODE, NEXT_NODE)
                hop = [path[i], path[i-1], path[i+1]]
                if hop not in hops:
                    hops.append(hop)
                    
        return hops
        
    def __generate_installs__(self):
        topo = self.topology;
        
        # Copy the self.hops to the local variable hops
        # It's need because we will modify the variable in the process
        hops = self.hops[0:]
        
        all_installs = []
        while len(hops) > 0:
            hop = hops.pop(0)
            installPath = InstallPath()
            installPath.routerId = hop[0]
            router = topo.getRouterById(installPath.routerId)
            installPath.inputPort = router.getPortByNode(hop[1])
            
            nodeid = hop[2]
            if topo.isHost(nodeid):
                host = topo.getHostById(nodeid)
                installPath.needRewrite = True
                installPath.dst_ip = host.ip
                installPath.dst_mac = host.mac
            
            installPath.addOutputPort( router.getPortByNode(nodeid) )
            
            while len(hops) > 0 and installPath.routerId == hops[0][0]:
                temp = hops.pop(0)
                    
                nodeid = temp[2]
                if topo.isHost(nodeid):
                    host = topo.getHostById(nodeid)
                    installPath.needRewrite = True
                    installPath.dst_ip = host.ip
                    installPath.dst_mac = host.mac
            
                installPath.addOutputPort( router.getPortByNode(nodeid) )
                
            all_installs.append(installPath)
            
        return all_installs
    
    def collect_begin_installs(self):
        temp_time = time.time()
        self.dc.collect_begin_installing_flows(len(self.topology.hosts), len(self.active_hosts), temp_time)
        
    def collect_end_installs(self):
        temp_time = time.time()
        self.dc.collect_end_installing_flows(len(self.topology.hosts), len(self.active_hosts), temp_time)
    
    def run(self):
        #Send a Request Start to the server
        #request = Request()
        #request.id = self.__next_req_number__()
        #request.action = request.ACTION.START
        #jsonMessage = request.toJson()
        #self.socket.send( jsonMessage )
        
        #Send a Request Register for Events
        request = Request()
        request.id = self.__next_req_number__()
        request.action = request.ACTION.REGISTER_FOR_EVENTS
        jsonMessage = request.toJson()
        self.socket.send( jsonMessage )
        #sleep(1)
        last_entry = False
        samples_collected = 0
        
        while True:
            if self.samples_number != -1:
                if samples_collected < self.samples_number:
                        request = Request()
                        request.id = self.__next_req_number__()
                        if last_entry:
                            request.action = request.ACTION.EXIT_EVENT
                            last_entry = False
                        else:
                            request.action = request.ACTION.ENTRY_EVENT
                            last_entry = True
                            
                        jsonMessage = request.toJson()
                        self.socket.send( jsonMessage )
                        samples_collected += 1
                else:
                    print '\n\n\n\n\n\n\n'
                    print '***************** Experiment Finished! *******************'
                    sys.exit()
            
            jsonEvent = self.socket.recv()
            event = EventFactory().decodeJson( jsonEvent )
            if event.type == "entry":
                #print 'Entry Event received.'
                temp_time = time.time()
                self.dc.collect_begin_paths(len(self.active_hosts), temp_time)
                self.entry_event(event)
                temp_time = time.time()
                self.dc.collect_end_paths(len(self.active_hosts), temp_time)
            elif event.type == "exit":
                #print 'Exit Event received.'
                temp_time = time.time()
                self.dc.collect_begin_paths(len(self.active_hosts), temp_time)
                self.exit_event(event)
                temp_time = time.time()
                self.dc.collect_end_paths(len(self.active_hosts), temp_time)
            elif event.type == "changeSource":
                #print 'Change Source Event received'
                temp_time = time.time()
                self.dc.collect_begin_paths(len(self.active_hosts), temp_time)
                self.change_source_event(event)
                temp_time = time.time()
                self.dc.collect_end_paths(len(self.active_hosts), temp_time)
            else:
                #print 'Invalid event received.'
                continue
            
            if self.nox != None:
                temp_time = time.time()
                self.dc.collect_event_effects(event, len(self.installs_to_do), len(self.installs_to_remove), temp_time)
                self.collect_begin_installs()
                self.nox.install_routes()
                self.collect_end_installs()
            else:
                print '\n\nInstalls to do:'
                for install in self.get_installs_to_do():
                    print '\t', install
        
                print '\n\nInstalls to remove:'
                for install in self.get_installs_to_remove():
                    print '\t', install
                
            
    def entry_event(self, event):
        new_paths = []
        for host in event.hosts:
            new_paths.append( self.path_to_host[host.id])
            self.active_hosts.append(host.id)
            
        new_hops = self.__calcule_hops__(new_paths)
        has_changes = False
        for hop in new_hops:
            if hop not in self.hops:
                has_changes = True
                self.hops.append(hop)
        
        if not has_changes:
            # Nothing change at all.
            return
        
        self.hops.sort()
        
        new_installs = self.__generate_installs__()
        self.installs_to_do = []
        self.installs_to_remove = []
        for install in new_installs:
            old_install = self.installs_by_router.get(install.routerId)
            if old_install == None:
                #There wasn't a installation in this router
                self.installs_by_router[install.routerId] = install
                self.installs_to_do.append(install)
            else:
                #There was a previous installation in this router
                if (old_install.outputPorts == install.outputPorts 
                        and old_install.inputPort == install.inputPort):
                    #The installation is the same, just ignore.
                    pass
                else:
                    #The installation is different!
                    #self.installs_to_remove.append(old_install) #TODO: Verify if it's realy necessary
                    self.installs_to_do.append(install)
                    self.installs_by_router[install.routerId] = install
        
    def exit_event(self, event):
        for host in event.hosts:
            self.active_hosts.remove(host.id)
            
        paths = []
        for host in self.active_hosts:
            paths.append(self.path_to_host[host])
            
        self.hops = self.__calcule_hops__(paths)
        self.hops.sort()
        
        new_installs = self.__generate_installs__()
        self.installs_to_do = []
        self.installs_to_remove = []
        keep_routers = []
        for install in new_installs:
            old_install = self.installs_by_router.get(install.routerId)
            keep_routers.append(install.routerId)
            if old_install == None:
                #There wasn't a installation in this router
                self.installs_by_router[install.routerId] = install
                self.installs_to_do.append(install)
            else:
                #There was a previous installation in this router
                if (old_install.outputPorts == install.outputPorts 
                        and old_install.inputPort == install.inputPort):
                    #The installation is the same, just ignore.
                    pass
                else:
                    #The installation is different!
                    #self.installs_to_remove.append(old_install) #TODO: Verify if it's realy necessary
                    self.installs_to_do.append(install)
                    self.installs_by_router[install.routerId] = install
                    
        for routerId in self.installs_by_router.keys():
            if routerId not in keep_routers:
                self.installs_to_remove.append( self.installs_by_router.pop(routerId) )
                
    def change_source_event(self, event):
        new_source_id = event.source
        if new_source_id in self.active_hosts:
            self.active_hosts.remove(new_source_id)
        
        self.current_source = new_source_id
        self.path_to_host = self.paths_by_source[self.current_source]   
        
        paths = []
        for host in self.active_hosts:
            paths.append(self.path_to_host[host])
            
        self.hops = self.__calcule_hops__(paths)
        self.hops.sort()
        
        new_installs = self.__generate_installs__()
        self.installs_to_do = []
        self.installs_to_remove = []
        keep_routers = []
        for install in new_installs:
            old_install = self.installs_by_router.get(install.routerId)
            keep_routers.append(install.routerId)
            if old_install == None:
                #There wasn't a installation in this router
                self.installs_by_router[install.routerId] = install
                self.installs_to_do.append(install)
            else:
                #There was a previous installation in this router
                if (old_install.outputPorts == install.outputPorts 
                        and old_install.inputPort == install.inputPort):
                    #The installation is the same, just ignore.
                    pass
                else:
                    #The installation is different!
                    #self.installs_to_remove.append(old_install) #TODO: Verify if it's realy necessary
                    self.installs_to_do.append(install)
                    self.installs_by_router[install.routerId] = install
                    
        for routerId in self.installs_by_router.keys():
            if routerId not in keep_routers:
                self.installs_to_remove.append( self.installs_by_router.pop(routerId) )