Exemplo n.º 1
0
class TestOrchestrator(unittest.TestCase):
    def setUp(self):
        self.def_views = ['NF_CHAIN', 'PHY']
        self.nm = NetworkGraphManager(views=self.def_views,
                                      chain_view=self.def_views[0],
                                      res_view=self.def_views[1])


#     def test_initialization(self):

    def test_add_node(self):
        node_id = 0
        view = self.def_views[0]
        self.assertEqual(0, len(self.nm.graphs[view].node))
        self.nm.add_node(node_id, view)

        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[view].node))
        self.assertIsNotNone(self.nm.graphs[view][node_id])

        #can not add node1 again
        self.assertRaises(RuntimeError, self.nm.add_node, node_id, view)

        #with empty parameter list
        self.assertDictEqual(dict(), self.nm.graphs[view][node_id])
        self.assertEqual(0, len(self.nm.graphs[view].node[node_id]))

        node_id += 1
        #add new node with some parameter
        self.nm.add_node(node_id, view, weight=1, size=2)
        #node numero 2 created
        self.assertEqual(2, len(self.nm.graphs[view].node))
        self.assertIsNotNone(self.nm.graphs[view][node_id])
        #parameters added
        self.assertEqual(2, len(self.nm.graphs[view].node[node_id]))
        self.assertDictEqual({
            'weight': 1,
            'size': 2
        }, self.nm.graphs[view].node[node_id])

        #add new node to another view
        new_view = self.def_views[1]
        #add new node with some parameter
        self.nm.add_node(node_id, new_view, weight=1, size=2)
        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[new_view].node))
        self.assertIsNotNone(self.nm.graphs[new_view].node[node_id])
        #parameters added
        self.assertEqual(2, len(self.nm.graphs[new_view].node[node_id]))
        self.assertDictEqual({
            'weight': 1,
            'size': 2
        }, self.nm.graphs[new_view].node[node_id])

        #previous view remained untouched
        self.assertEqual(2, len(self.nm.graphs[view].node))

    def test_id_autoincrement(self):
        self.nm.auto_id = True

        node_id = 'A'
        view = self.def_views[0]
        self.assertEqual(0, len(self.nm.graphs[view].node))
        real_node_id = self.nm.add_node(node_id, view)

        #auto_id_node overrides the value of the id in the parameter list
        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[view].node))
        self.assertNotIn(node_id, self.nm.graphs[view].node)
        self.assertIsNotNone(self.nm.graphs[view].node[real_node_id])

        #node numero 2 created
        real_node_id2 = self.nm.add_node(node_id, view)
        self.assertEqual(2, len(self.nm.graphs[view].node))
        self.assertNotIn(node_id, self.nm.graphs[view].node)
        self.assertIsNotNone(self.nm.graphs[view].node[real_node_id2])

        self.nm.auto_id = False
        self.assertRaises(RuntimeError, self.nm.add_node, None, view)

    def test_remove_node(self):
        node_id = 0
        view = self.def_views[0]

        #empty graph
        self.assertEqual(0, len(self.nm.graphs[view].node))

        self.nm.add_node(node_id, view)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)

        self.nm.add_node(node_id + 1, view)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)

        self.nm.remove_node(node_id, view)
        #node removed
        self.assertNotIn(node_id, self.nm.graphs[view].node)

        self.nm.remove_node(node_id + 1, view)
        #node removed
        self.assertNotIn(node_id + 1, self.nm.graphs[view].node)

        #empty graph
        self.assertFalse(self.nm.graphs[view].graph)

    def test_modify_node(self):
        node_id = 0
        view = self.def_views[0]

        #node not in the graph
        self.assertNotIn(node_id, self.nm.graphs[view].node)

        #can not modify node which one does not exists
        self.assertRaises(RuntimeError, self.nm.modify_node, node_id, view)

        self.nm.add_node(node_id, view, weight=2, size=3)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)
        #check parameters
        self.assertEqual(2, self.nm.graphs[view].node[node_id]['weight'])
        self.assertEqual(3, self.nm.graphs[view].node[node_id]['size'])

        #modify size
        self.nm.modify_node(node_id, view, size=6)
        #check parameters
        self.assertEqual(2, self.nm.graphs[view].node[node_id]['weight'])
        self.assertEqual(6, self.nm.graphs[view].node[node_id]['size'])

    def test_add_remove_link(self):
        u = 1
        v = 2
        view = self.def_views[0]

        #add source and target
        self.nm.add_node(u, view)
        self.nm.add_node(v, view)

        #there is no link between u and v yet
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u, v))

        self.nm.add_link(u, v, view)

        #there is one link between u and v
        self.assertEqual(1, self.nm.graphs[view].number_of_edges(u, v))

        #test if there is only one link possible between nodes
        self.nm.add_link(u, v, view)

        #there is one link between u and v
        self.assertEqual(1, self.nm.graphs[view].number_of_edges(u, v))

        #remove link between u and v
        self.nm.remove_link(u, v, view)

        #there is no link between u and v
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u, v))

    def test_modify_link_parameters(self):
        u = 1
        v = 2
        view = self.def_views[0]

        #add source and target
        self.nm.add_node(u, view)
        self.nm.add_node(v, view)

        #there is no link between u and v yet
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u, v))

        self.nm.add_link(u, v, view, weight=2, length=4)

        self.assertIn('weight', self.nm.graphs[view].edge[u][v])
        self.assertIn('length', self.nm.graphs[view].edge[u][v])

        self.assertEqual(2, self.nm.graphs[view].edge[u][v]['weight'])
        self.assertEqual(4, self.nm.graphs[view].edge[u][v]['length'])

        #modify link's length
        self.nm.add_link(u, v, view, length=8)

        self.assertEqual(2, self.nm.graphs[view].edge[u][v]['weight'])
        self.assertEqual(8, self.nm.graphs[view].edge[u][v]['length'])

    def test_add_chains(self):
        self.nm.auto_id = True
        view = self.def_views[0]

        #empty graph
        self.assertEqual(0, len(self.nm.graphs[view].node))
        #add an empty chain and test return parameters
        (chain_id, start_id, end_id) = self.nm.add_new_chain()
        self.assertIn(chain_id, self.nm.chains)
        self.assertIn(start_id, self.nm.graphs[view].node)
        self.assertIn(end_id, self.nm.graphs[view].node)
        self.assertEqual(start_id, self.nm.chains[chain_id]['source'])
        self.assertEqual(end_id, self.nm.chains[chain_id]['target'])

        #Test if auto_id overrides parameters
        (chain_id, start_id, end_id) = self.nm.add_new_chain('start', 'end')
        self.assertNotEqual(start_id, 'start')
        self.assertNotEqual(end_id, 'end')
        self.assertIn(chain_id, self.nm.chains)
        self.assertNotIn('start', self.nm.graphs[view].node)
        self.assertNotIn('end', self.nm.graphs[view].node)
        self.assertNotEqual('start', self.nm.chains[chain_id]['source'])
        self.assertNotEqual('end', self.nm.chains[chain_id]['target'])

        self.nm.auto_id = False
        #controlled chain add without auto id
        (chain_id, start_id,
         end_id) = self.nm.add_new_chain('start', 'end', {'weight': 3},
                                         {'weight': 5})
        self.assertIn(chain_id, self.nm.chains)
        self.assertIn('start', self.nm.graphs[view].node)
        self.assertIn('end', self.nm.graphs[view].node)
        self.assertIn('weight', self.nm.graphs[view].node['start'])
        self.assertEqual(3, self.nm.graphs[view].node['start']['weight'])
        self.assertEqual(5, self.nm.graphs[view].node['end']['weight'])
        self.assertEqual('start', self.nm.chains[chain_id]['source'])
        self.assertEqual('end', self.nm.chains[chain_id]['target'])

    def test_orchestrator_helpers(self):
        res_view = self.def_views[1]

        self.nm.auto_id = False
        phy_s = self.nm.add_node('phy_s',
                                 res_view,
                                 node_type=NetworkGraphManager.NODE_TYPE_SAP)
        phy_t = self.nm.add_node('phy_t',
                                 res_view,
                                 node_type=NetworkGraphManager.NODE_TYPE_SAP)

        res_g = self.nm.get_graph(res_view)

        stnodes = Mapping.get_stnodes(res_g)
        #there is no path between nodes
        self.assertEqual(stnodes, [])

        self.nm.add_link(phy_s, phy_t, res_view)
        stnodes = Mapping.get_stnodes(res_g)
        self.assertEqual(stnodes, [(phy_s, phy_t)])

        self.nm.auto_id = True
        (view, s_node, t_node, nodes) = self._add_one_vnf_chain()

        g = self.nm.get_graph(view)

        stnodes = Mapping.get_stnodes(g)

        #check if SAPs are in stnodes list
        self.assertIn((t_node, s_node), stnodes)

        #only one endpoint pair in this basic chain view
        self.assertEqual(1, len(stnodes))

        #add another node, and check if the two new SAP is added
        (chain_id, s_node2, t_node2) = self.nm.add_new_chain()
        self.nm.add_link(s_node2, t_node2, view)

        stnodes = Mapping.get_stnodes(g)

        #check if SAPs are in stnodes list
        self.assertIn((s_node2, t_node2), stnodes)

        #now the view has two chain and two st pair
        self.assertEqual(2, len(stnodes))

        #add a vnf node with dummy type to the view
        dummy_id = self.nm.add_node(None, view, node_type='dummy')
        self.nm.add_link(s_node2, dummy_id, view)

        #add a normal vnf node to the view
        true_vnf = self.nm.add_node(
            None,
            view,
            node_type=NetworkGraphManager.NODE_TYPE_VNF,
            req={
                'cpu': 4,
                'mem': 3
            })
        self.nm.add_link(dummy_id, true_vnf, view)
        self.nm.add_link(true_vnf, t_node2, view)

        #add an unreachable vnf node to the view
        unreach_vnf = self.nm.add_node(
            None, view, node_type=NetworkGraphManager.NODE_TYPE_VNF)

        #add a broken chain
        (chain_id3, s_node3, t_node3) = self.nm.add_new_chain()
        broken_vnf = self.nm.add_node(
            None, view, node_type=NetworkGraphManager.NODE_TYPE_VNF)
        self.nm.add_link(s_node3, broken_vnf, view)

        stnodes = Mapping.get_stnodes(g)
        vnf_list = Mapping.get_accessible_vnf_list(stnodes, g)

        #dummy not in the vnf list, because its type
        self.assertNotIn(dummy_id, vnf_list)
        #broken not in the vnf list, because its chain is not valid
        self.assertNotIn(broken_vnf, vnf_list)
        #unreach not in the vnf list, because it is unreachable
        self.assertNotIn(unreach_vnf, vnf_list)

        self.assertIn(true_vnf, vnf_list)

        #Test, if we add a vnf to a phy node, resources are globally updated
        phy_view = self.def_views[1]
        phy_g = self.nm.get_graph(phy_view)
        phy_node1 = self.nm.add_node(None, phy_view, res={'cpu': 6, 'mem': 3})
        Mapping.add_vnf_to_host(true_vnf, phy_node1, g, phy_g)

        phy_node = self.nm.graphs[phy_view].node[phy_node1]
        self.assertEqual(2, phy_node['res']['cpu'])
        self.assertEqual(0, phy_node['res']['mem'])

    def test_default_sorter(self):
        view = self.def_views[0]
        self.nm.auto_id = True
        node1 = self.nm.add_node(None, view, req={'cpu': 4, 'mem': 3})
        node2 = self.nm.add_node(None, view, req={'cpu': 5, 'mem': 3})
        node3 = self.nm.add_node(None, view, req={'cpu': 4, 'mem': 1})

        vnf_list = {node1: node1, node2: node2, node3: node3}

        sorter = DefaultSorter()
        sorted = sorter.order_vnf_list(vnf_list, self.nm.graphs[view])

        #DefaultSorter sorts vnf list in ascending order first comparing
        #cpu needs than memory requirements

        self.assertEqual(sorted[0], node3)
        self.assertEqual(sorted[1], node1)
        self.assertEqual(sorted[2], node2)

        #Test if node chooser returns with res_node with highest available
        #resources
        phy_view = self.def_views[1]
        phy_node1 = self.nm.add_node(
            None,
            phy_view,
            res={
                'cpu': 1,
                'mem': 3
            },
            node_type=NetworkGraphManager.NODE_TYPE_HOST)
        phy_node2 = self.nm.add_node(
            None,
            phy_view,
            res={
                'cpu': 14,
                'mem': 3
            },
            node_type=NetworkGraphManager.NODE_TYPE_HOST)
        phy_node3 = self.nm.add_node(
            None,
            phy_view,
            res={
                'cpu': 4,
                'mem': 1
            },
            node_type=NetworkGraphManager.NODE_TYPE_HOST)

        vnf = Store()
        vnf.node = {'req': {'cpu': 1, 'mem': 1}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(host, phy_node2)

        #If there is not enough resource in physical nodes
        #get_node_for_vnf returns None
        vnf.node = {'req': {'cpu': 100, 'mem': 100}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(None, host)

        #if there is overlapping, highest cpu value wins
        #e.g: node1: cpu: 10, mem: 4; node2: cpu:5, mem: 7, than algorithm
        #returns with node1
        self.nm.modify_node(phy_node1, phy_view, res={'cpu': 9, 'mem': 13})
        vnf.node = {'req': {'cpu': 1, 'mem': 1}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(phy_node2, host)

    def test_orchestrating(self):
        res_view = 'RES'
        chain_view = 'CHAIN'
        self.nm = NetworkGraphManager(auto_id=False,
                                      views=[chain_view, res_view],
                                      chain_view=chain_view,
                                      res_view=res_view)

        #build a basic chain network
        (chain_id, start_id, end_id) = self.nm.add_new_chain('start1', 'end1')
        vnf_node_id = self.nm.add_node(
            'vnf1',
            chain_view,
            node_type=NetworkGraphManager.NODE_TYPE_VNF,
            req={
                'cpu': 4,
                'mem': 4
            })
        vnf_node_id2 = self.nm.add_node(
            'vnf2',
            chain_view,
            node_type=NetworkGraphManager.NODE_TYPE_VNF,
            req={
                'cpu': 7,
                'mem': 4
            })

        self.nm.add_link(start_id, vnf_node_id, chain_view)
        self.nm.add_link(vnf_node_id, vnf_node_id2, chain_view)
        self.nm.add_link(vnf_node_id2, end_id, chain_view)

        #build a basic phy network
        phy1_id = self.nm.add_node(
            'phy1',
            res_view,
            node_type=NetworkGraphManager.NODE_TYPE_HOST,
            res={
                'cpu': 2,
                'mem': 3
            })

        phy2_id = self.nm.add_node(
            'phy2',
            res_view,
            node_type=NetworkGraphManager.NODE_TYPE_HOST,
            res={
                'cpu': 4,
                'mem': 3
            })

        self.nm.add_link(phy1_id, phy2_id, res_view)

        chain_g = self.nm.get_graph(chain_view)
        res_g = self.nm.get_graph(res_view)
        #start end end nodes are not presented in the physical view
        self.assertRaises(RuntimeError, Mapping.map, chain_g, res_g,
                          DefaultSorter)

        self.nm.add_node('start1',
                         res_view,
                         node_type=NetworkGraphManager.NODE_TYPE_SAP)
        self.nm.add_node('end1',
                         res_view,
                         node_type=NetworkGraphManager.NODE_TYPE_SAP)
        #start end end nodes are not connected in the physical view
        self.assertRaises(RuntimeError, Mapping.map, chain_g, res_g,
                          DefaultSorter)

        self.nm.add_link('start1', 'end1', res_view)
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)

        #Not enough resource available in res view, so we get an empty pair list
        self.assertFalse(pair_list)

        self.nm.modify_node(phy2_id, res_view, res={'cpu': 11, 'mem': 8})
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)
        self.assertIn((vnf_node_id, phy2_id), pair_list)
        self.assertIn((vnf_node_id2, phy2_id), pair_list)

        self.nm.modify_node(phy2_id, res_view, res={'cpu': 8, 'mem': 4})
        self.nm.modify_node(phy1_id, res_view, res={'cpu': 7, 'mem': 4})
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)
        self.assertIn((vnf_node_id, phy2_id), pair_list)
        self.assertIn((vnf_node_id2, phy1_id), pair_list)

    def _add_one_vnf_chain(self):
        view = self.def_views[0]
        self.nm.auto_id = True

        (chain_id, start_id, end_id) = self.nm.add_new_chain()
        vnf_node_id = self.nm.add_node(
            None, view, node_type=NetworkGraphManager.NODE_TYPE_VNF)
        self.nm.add_link(start_id, vnf_node_id, view)
        self.nm.add_link(vnf_node_id, end_id, view)

        return (view, start_id, end_id, [vnf_node_id])
Exemplo n.º 2
0
class TestOrchestrator(unittest.TestCase):


    def setUp(self):
        self.def_views = ['NF_CHAIN', 'PHY']
        self.nm = NetworkGraphManager(views = self.def_views,
                                 chain_view = self.def_views[0],
                                 res_view = self.def_views[1])

#     def test_initialization(self):

    def test_add_node(self):
        node_id = 0
        view = self.def_views[0]
        self.assertEqual(0, len(self.nm.graphs[view].node))
        self.nm.add_node(node_id, view)

        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[view].node))
        self.assertIsNotNone(self.nm.graphs[view][node_id])

        #can not add node1 again
        self.assertRaises(RuntimeError, self.nm.add_node, node_id, view)

        #with empty parameter list
        self.assertDictEqual(dict(), self.nm.graphs[view][node_id])
        self.assertEqual(0, len(self.nm.graphs[view].node[node_id]))

        node_id += 1
        #add new node with some parameter
        self.nm.add_node(node_id, view, weight = 1, size = 2)
        #node numero 2 created
        self.assertEqual(2, len(self.nm.graphs[view].node))
        self.assertIsNotNone(self.nm.graphs[view][node_id])
        #parameters added
        self.assertEqual(2, len(self.nm.graphs[view].node[node_id]))
        self.assertDictEqual({'weight': 1, 'size': 2},
                             self.nm.graphs[view].node[node_id])

        #add new node to another view
        new_view = self.def_views[1]
        #add new node with some parameter
        self.nm.add_node(node_id, new_view, weight = 1, size = 2)
        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[new_view].node))
        self.assertIsNotNone(self.nm.graphs[new_view].node[node_id])
        #parameters added
        self.assertEqual(2, len(self.nm.graphs[new_view].node[node_id]))
        self.assertDictEqual({'weight': 1, 'size': 2},
                             self.nm.graphs[new_view].node[node_id])

        #previous view remained untouched
        self.assertEqual(2, len(self.nm.graphs[view].node))

    def test_id_autoincrement(self):
        self.nm.auto_id = True

        node_id = 'A'
        view = self.def_views[0]
        self.assertEqual(0, len(self.nm.graphs[view].node))
        real_node_id = self.nm.add_node(node_id, view)

        #auto_id_node overrides the value of the id in the parameter list
        #node numero 1 created
        self.assertEqual(1, len(self.nm.graphs[view].node))
        self.assertNotIn(node_id, self.nm.graphs[view].node)
        self.assertIsNotNone(self.nm.graphs[view].node[real_node_id])

        #node numero 2 created
        real_node_id2 = self.nm.add_node(node_id, view)
        self.assertEqual(2, len(self.nm.graphs[view].node))
        self.assertNotIn(node_id, self.nm.graphs[view].node)
        self.assertIsNotNone(self.nm.graphs[view].node[real_node_id2])

        self.nm.auto_id = False
        self.assertRaises(RuntimeError, self.nm.add_node, None, view)

    def test_remove_node(self):
        node_id = 0
        view = self.def_views[0]

        #empty graph
        self.assertEqual(0, len(self.nm.graphs[view].node))

        self.nm.add_node(node_id, view)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)

        self.nm.add_node(node_id+1, view)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)

        self.nm.remove_node(node_id, view)
        #node removed
        self.assertNotIn(node_id, self.nm.graphs[view].node)

        self.nm.remove_node(node_id+1, view)
        #node removed
        self.assertNotIn(node_id+1, self.nm.graphs[view].node)

        #empty graph
        self.assertFalse(self.nm.graphs[view].graph)

    def test_modify_node(self):
        node_id = 0
        view = self.def_views[0]

        #node not in the graph
        self.assertNotIn(node_id, self.nm.graphs[view].node)

        #can not modify node which one does not exists
        self.assertRaises(RuntimeError, self.nm.modify_node, node_id, view)

        self.nm.add_node(node_id, view, weight = 2, size = 3)
        #node inserted
        self.assertIn(node_id, self.nm.graphs[view].node)
        #check parameters
        self.assertEqual(2, self.nm.graphs[view].node[node_id]['weight'])
        self.assertEqual(3, self.nm.graphs[view].node[node_id]['size'])

        #modify size
        self.nm.modify_node(node_id, view, size = 6)
        #check parameters
        self.assertEqual(2, self.nm.graphs[view].node[node_id]['weight'])
        self.assertEqual(6, self.nm.graphs[view].node[node_id]['size'])

    def test_add_remove_link(self):
        u = 1
        v = 2
        view = self.def_views[0]

        #add source and target
        self.nm.add_node(u, view)
        self.nm.add_node(v, view)

        #there is no link between u and v yet
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u,v))

        self.nm.add_link(u, v, view)

        #there is one link between u and v
        self.assertEqual(1, self.nm.graphs[view].number_of_edges(u,v))

        #test if there is only one link possible between nodes
        self.nm.add_link(u, v, view)

        #there is one link between u and v
        self.assertEqual(1, self.nm.graphs[view].number_of_edges(u,v))

        #remove link between u and v
        self.nm.remove_link(u, v, view)

        #there is no link between u and v
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u,v))

    def test_modify_link_parameters(self):
        u = 1
        v = 2
        view = self.def_views[0]

        #add source and target
        self.nm.add_node(u, view)
        self.nm.add_node(v, view)

        #there is no link between u and v yet
        self.assertEqual(0, self.nm.graphs[view].number_of_edges(u,v))

        self.nm.add_link(u, v, view, weight = 2, length = 4)

        self.assertIn('weight', self.nm.graphs[view].edge[u][v])
        self.assertIn('length', self.nm.graphs[view].edge[u][v])

        self.assertEqual(2, self.nm.graphs[view].edge[u][v]['weight'])
        self.assertEqual(4, self.nm.graphs[view].edge[u][v]['length'])

        #modify link's length
        self.nm.add_link(u, v, view, length = 8)

        self.assertEqual(2, self.nm.graphs[view].edge[u][v]['weight'])
        self.assertEqual(8, self.nm.graphs[view].edge[u][v]['length'])

    def test_add_chains(self):
        self.nm.auto_id = True
        view = self.def_views[0]

        #empty graph
        self.assertEqual(0, len(self.nm.graphs[view].node))
        #add an empty chain and test return parameters
        (chain_id, start_id, end_id) = self.nm.add_new_chain()
        self.assertIn(chain_id, self.nm.chains)
        self.assertIn(start_id, self.nm.graphs[view].node)
        self.assertIn(end_id, self.nm.graphs[view].node)
        self.assertEqual(start_id, self.nm.chains[chain_id]['source'])
        self.assertEqual(end_id, self.nm.chains[chain_id]['target'])

        #Test if auto_id overrides parameters
        (chain_id, start_id, end_id) = self.nm.add_new_chain('start', 'end')
        self.assertNotEqual(start_id, 'start')
        self.assertNotEqual(end_id, 'end')
        self.assertIn(chain_id, self.nm.chains)
        self.assertNotIn('start', self.nm.graphs[view].node)
        self.assertNotIn('end', self.nm.graphs[view].node)
        self.assertNotEqual('start', self.nm.chains[chain_id]['source'])
        self.assertNotEqual('end', self.nm.chains[chain_id]['target'])

        self.nm.auto_id = False
        #controlled chain add without auto id
        (chain_id, start_id, end_id) = self.nm.add_new_chain('start', 'end',
                                                               {'weight' : 3},
                                                               {'weight' : 5})
        self.assertIn(chain_id, self.nm.chains)
        self.assertIn('start', self.nm.graphs[view].node)
        self.assertIn('end', self.nm.graphs[view].node)
        self.assertIn('weight', self.nm.graphs[view].node['start'])
        self.assertEqual(3, self.nm.graphs[view].node['start']['weight'])
        self.assertEqual(5, self.nm.graphs[view].node['end']['weight'])
        self.assertEqual('start', self.nm.chains[chain_id]['source'])
        self.assertEqual('end', self.nm.chains[chain_id]['target'])

    def test_orchestrator_helpers(self):
        res_view = self.def_views[1]

        self.nm.auto_id = False
        phy_s = self.nm.add_node('phy_s', res_view,
                                 node_type = NetworkGraphManager.NODE_TYPE_SAP)
        phy_t = self.nm.add_node('phy_t', res_view,
                                 node_type = NetworkGraphManager.NODE_TYPE_SAP)

        res_g = self.nm.get_graph(res_view)

        stnodes = Mapping.get_stnodes(res_g)
        #there is no path between nodes
        self.assertEqual(stnodes, [])

        self.nm.add_link(phy_s, phy_t, res_view)
        stnodes = Mapping.get_stnodes(res_g)
        self.assertEqual(stnodes, [(phy_s, phy_t)])


        self.nm.auto_id = True
        (view, s_node, t_node, nodes) = self._add_one_vnf_chain()

        g = self.nm.get_graph(view)

        stnodes = Mapping.get_stnodes(g)

        #check if SAPs are in stnodes list
        self.assertIn((t_node, s_node), stnodes)

        #only one endpoint pair in this basic chain view
        self.assertEqual(1, len(stnodes))

        #add another node, and check if the two new SAP is added
        (chain_id, s_node2, t_node2) = self.nm.add_new_chain()
        self.nm.add_link(s_node2, t_node2, view)

        stnodes = Mapping.get_stnodes(g)

        #check if SAPs are in stnodes list
        self.assertIn((s_node2, t_node2), stnodes)

        #now the view has two chain and two st pair
        self.assertEqual(2, len(stnodes))

        #add a vnf node with dummy type to the view
        dummy_id = self.nm.add_node(None, view, node_type = 'dummy')
        self.nm.add_link(s_node2, dummy_id, view)

        #add a normal vnf node to the view
        true_vnf = self.nm.add_node(None, view,
                                    node_type = NetworkGraphManager.NODE_TYPE_VNF,
                                    req = {'cpu': 4, 'mem': 3})
        self.nm.add_link(dummy_id, true_vnf, view)
        self.nm.add_link(true_vnf, t_node2, view)

        #add an unreachable vnf node to the view
        unreach_vnf = self.nm.add_node(None, view,
                                       node_type = NetworkGraphManager.NODE_TYPE_VNF)

        #add a broken chain
        (chain_id3, s_node3, t_node3) = self.nm.add_new_chain()
        broken_vnf = self.nm.add_node(None, view,
                                      node_type = NetworkGraphManager.NODE_TYPE_VNF)
        self.nm.add_link(s_node3, broken_vnf, view)


        stnodes = Mapping.get_stnodes(g)
        vnf_list = Mapping.get_accessible_vnf_list(stnodes, g)

        #dummy not in the vnf list, because its type
        self.assertNotIn(dummy_id, vnf_list)
        #broken not in the vnf list, because its chain is not valid
        self.assertNotIn(broken_vnf, vnf_list)
        #unreach not in the vnf list, because it is unreachable
        self.assertNotIn(unreach_vnf, vnf_list)

        self.assertIn(true_vnf, vnf_list)

        #Test, if we add a vnf to a phy node, resources are globally updated
        phy_view = self.def_views[1]
        phy_g = self.nm.get_graph(phy_view)
        phy_node1 = self.nm.add_node(None, phy_view, res = {'cpu': 6, 'mem': 3})
        Mapping.add_vnf_to_host(true_vnf, phy_node1, g, phy_g)

        phy_node = self.nm.graphs[phy_view].node[phy_node1]
        self.assertEqual(2, phy_node['res']['cpu'])
        self.assertEqual(0, phy_node['res']['mem'])

    def test_default_sorter(self):
        view = self.def_views[0]
        self.nm.auto_id = True
        node1 = self.nm.add_node(None, view, req = {'cpu': 4, 'mem': 3})
        node2 = self.nm.add_node(None, view, req = {'cpu': 5, 'mem': 3})
        node3 = self.nm.add_node(None, view, req = {'cpu': 4, 'mem': 1})

        vnf_list = {node1: node1, node2: node2, node3: node3}

        sorter = DefaultSorter()
        sorted = sorter.order_vnf_list(vnf_list, self.nm.graphs[view])

        #DefaultSorter sorts vnf list in ascending order first comparing
        #cpu needs than memory requirements

        self.assertEqual(sorted[0], node3)
        self.assertEqual(sorted[1], node1)
        self.assertEqual(sorted[2], node2)

        #Test if node chooser returns with res_node with highest available
        #resources
        phy_view = self.def_views[1]
        phy_node1 = self.nm.add_node(None, phy_view,
                                     res = {'cpu': 1, 'mem': 3},
                                     node_type = NetworkGraphManager.NODE_TYPE_HOST)
        phy_node2 = self.nm.add_node(None, phy_view,
                                     res = {'cpu': 14, 'mem': 3},
                                     node_type = NetworkGraphManager.NODE_TYPE_HOST)
        phy_node3 = self.nm.add_node(None, phy_view,
                                     res = {'cpu': 4, 'mem': 1},
                                     node_type = NetworkGraphManager.NODE_TYPE_HOST)

        vnf = Store()
        vnf.node = {'req': {'cpu': 1, 'mem': 1}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(host, phy_node2)

        #If there is not enough resource in physical nodes
        #get_node_for_vnf returns None
        vnf.node = {'req': {'cpu': 100, 'mem': 100}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(None, host)

        #if there is overlapping, highest cpu value wins
        #e.g: node1: cpu: 10, mem: 4; node2: cpu:5, mem: 7, than algorithm
        #returns with node1
        self.nm.modify_node(phy_node1, phy_view, res = {'cpu': 9, 'mem': 13})
        vnf.node = {'req': {'cpu': 1, 'mem': 1}}
        host = sorter.get_node_for_vnf(vnf, self.nm.graphs[view],
                                       self.nm.graphs[phy_view])

        self.assertEqual(phy_node2, host)


    def test_orchestrating(self):
        res_view = 'RES'
        chain_view = 'CHAIN'
        self.nm = NetworkGraphManager(auto_id = False,
                                 views = [chain_view, res_view],
                                 chain_view = chain_view,
                                 res_view = res_view)

        #build a basic chain network
        (chain_id, start_id, end_id) = self.nm.add_new_chain('start1', 'end1')
        vnf_node_id = self.nm.add_node('vnf1', chain_view,
                                       node_type = NetworkGraphManager.NODE_TYPE_VNF,
                                       req = {'cpu': 4, 'mem': 4})
        vnf_node_id2 = self.nm.add_node('vnf2', chain_view,
                                        node_type = NetworkGraphManager.NODE_TYPE_VNF,
                                        req = {'cpu': 7, 'mem': 4})

        self.nm.add_link(start_id, vnf_node_id, chain_view)
        self.nm.add_link(vnf_node_id, vnf_node_id2, chain_view)
        self.nm.add_link(vnf_node_id2, end_id, chain_view)

        #build a basic phy network
        phy1_id = self.nm.add_node('phy1', res_view,
                           node_type = NetworkGraphManager.NODE_TYPE_HOST,
                           res = {'cpu': 2, 'mem': 3})

        phy2_id = self.nm.add_node('phy2', res_view,
                           node_type = NetworkGraphManager.NODE_TYPE_HOST,
                           res = {'cpu': 4, 'mem': 3})

        self.nm.add_link(phy1_id, phy2_id, res_view)

        chain_g = self.nm.get_graph(chain_view)
        res_g = self.nm.get_graph(res_view)
        #start end end nodes are not presented in the physical view
        self.assertRaises(RuntimeError, Mapping.map,
                          chain_g, res_g, DefaultSorter)

        self.nm.add_node('start1', res_view,
                         node_type = NetworkGraphManager.NODE_TYPE_SAP)
        self.nm.add_node('end1', res_view,
                         node_type = NetworkGraphManager.NODE_TYPE_SAP)
        #start end end nodes are not connected in the physical view
        self.assertRaises(RuntimeError, Mapping.map,
                          chain_g, res_g, DefaultSorter)

        self.nm.add_link('start1', 'end1', res_view)
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)

        #Not enough resource available in res view, so we get an empty pair list
        self.assertFalse(pair_list)

        self.nm.modify_node(phy2_id, res_view, res = {'cpu': 11, 'mem': 8})
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)
        self.assertIn((vnf_node_id, phy2_id), pair_list)
        self.assertIn((vnf_node_id2, phy2_id), pair_list)

        self.nm.modify_node(phy2_id, res_view, res = {'cpu': 8, 'mem': 4})
        self.nm.modify_node(phy1_id, res_view, res = {'cpu': 7, 'mem': 4})
        pair_list = Mapping.map(chain_g, res_g, DefaultSorter)
        self.assertIn((vnf_node_id, phy2_id), pair_list)
        self.assertIn((vnf_node_id2, phy1_id), pair_list)

    def _add_one_vnf_chain(self):
        view = self.def_views[0]
        self.nm.auto_id = True

        (chain_id, start_id, end_id) = self.nm.add_new_chain()
        vnf_node_id = self.nm.add_node(None, view,
                                       node_type = NetworkGraphManager.NODE_TYPE_VNF)
        self.nm.add_link(start_id, vnf_node_id, view)
        self.nm.add_link(vnf_node_id, end_id, view)

        return (view, start_id, end_id, [vnf_node_id])