merge network/monitoring cli commands
[osm/vim-emu.git] / emuvim / dcemulator / net.py
index 7b238b8..8379cd3 100755 (executable)
@@ -9,6 +9,8 @@ from mininet.node import Controller, OVSKernelSwitch, Switch, Docker, Host
 from mininet.cli import CLI
 from mininet.log import setLogLevel, info
 from mininet.link import TCLink, Link
 from mininet.cli import CLI
 from mininet.log import setLogLevel, info
 from mininet.link import TCLink, Link
+import networkx as nx
+from monitoring import DCNetworkMonitor
 
 from node import Datacenter, EmulatorCompute
 
 
 from node import Datacenter, EmulatorCompute
 
@@ -26,8 +28,15 @@ class DCNetwork(Dockernet):
         # create a Mininet/Dockernet network
         # call original Docker.__init__ and setup default controller
         Dockernet.__init__(
         # create a Mininet/Dockernet network
         # call original Docker.__init__ and setup default controller
         Dockernet.__init__(
-            self, controller=Controller, switch=OVSKernelSwitch, **kwargs)
-        self.addController('c0')
+            self, controller=RemoteController, switch=OVSKernelSwitch, **kwargs)
+        #self.addController('c0')
+
+        # graph of the complete DC network
+        self.DCNetwork_graph=nx.DiGraph()
+
+        # monitoring agent
+        self.monitor_agent = DCNetworkMonitor(self)
+
 
     def addDatacenter(self, label, metadata={}):
         """
 
     def addDatacenter(self, label, metadata={}):
         """
@@ -74,13 +83,37 @@ class DCNetwork(Dockernet):
             if not "ip" in params["params2"]:
                 params["params2"]["ip"] = self.getNextIp()
 
             if not "ip" in params["params2"]:
                 params["params2"]["ip"] = self.getNextIp()
 
-        return Dockernet.addLink(self, node1, node2, **params)  # TODO we need TCLinks with user defined performance here
+        link = Dockernet.addLink(self, node1, node2, **params)  # TODO we need TCLinks with user defined performance here
+
+        # add edge and assigned port number to graph in both directions between node1 and node2
+        self.DCNetwork_graph.add_edge(node1.name, node2.name, \
+                                      {'src_port': node1.ports[link.intf1], 'dst_port': node2.ports[link.intf2]})
+        self.DCNetwork_graph.add_edge(node2.name, node1.name, \
+                                       {'src_port': node2.ports[link.intf2], 'dst_port': node1.ports[link.intf1]})
+
+        return link
 
     def addDocker( self, label, **params ):
         """
         Wrapper for addDocker method to use custom container class.
         """
 
     def addDocker( self, label, **params ):
         """
         Wrapper for addDocker method to use custom container class.
         """
-        return Dockernet.addDocker(self, label, cls=EmulatorCompute, **params)
+        self.DCNetwork_graph.add_node(name)
+        return Dockernet.addDocker(self, name, cls=EmulatorCompute, **params)
+
+    def removeDocker( self, name, **params ):
+        """
+        Wrapper for removeDocker method to update graph.
+        """
+        self.DCNetwork_graph.remove_node(name)
+        return Dockernet.removeDocker(self, name, **params)
+
+    def addSwitch( self, name, add_to_graph=True, **params ):
+        """
+        Wrapper for addSwitch method to store switch also in graph.
+        """
+        if add_to_graph:
+            self.DCNetwork_graph.add_node(name)
+        return Dockernet.addSwitch(self, name, protocols='OpenFlow10,OpenFlow12,OpenFlow13', **params)
 
     def getAllContainers(self):
         """
 
     def getAllContainers(self):
         """
@@ -102,3 +135,46 @@ class DCNetwork(Dockernet):
 
     def CLI(self):
         CLI(self)
 
     def CLI(self):
         CLI(self)
+
+    # to remove chain do setChain( src, dst, cmd='del-flows')
+    def setChain(self, vnf_src_name, vnf_dst_name, cmd='add-flow'):
+        # get shortest path
+        path = nx.shortest_path(self.DCNetwork_graph, vnf_src_name, vnf_dst_name)
+        logging.info("Path between {0} and {1}: {2}".format(vnf_src_name, vnf_dst_name, path))
+
+        current_hop = vnf_src_name
+        for i in range(0,len(path)):
+            next_hop = path[path.index(current_hop)+1]
+            next_node = self.getNodeByName(next_hop)
+
+            if next_hop == vnf_dst_name:
+                return 0
+            elif not isinstance( next_node, OVSSwitch ):
+                logging.info("Next node: {0} is not a switch".format(next_hop1))
+                return 0
+
+
+            switch_inport = self.DCNetwork_graph[current_hop][next_hop]['dst_port']
+            next2_hop = path[path.index(current_hop)+2]
+            switch_outport = self.DCNetwork_graph[next_hop][next2_hop]['src_port']
+
+            logging.info("add flow in switch: {0} in_port: {1} out_port: {2}".format(next_node.name, switch_inport, switch_outport))
+            # set of entry via ovs-ofctl
+            # TODO use rest API of ryu to set flow entries to correct witch dpid
+            if isinstance( next_node, OVSSwitch ):
+                match = 'in_port=%s' % switch_inport
+
+                if cmd=='add-flow':
+                    action = 'action=%s' % switch_outport
+                    s = ','
+                    ofcmd = s.join([match,action])
+                elif cmd=='del-flows':
+                    ofcmd = match
+                else:
+                    ofcmd=''
+
+                next_node.dpctl(cmd, ofcmd)
+
+            current_hop = next_hop
+
+        return 1
\ No newline at end of file