2 * Copyright (c) 2015 Inocybe Technologies. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.Matchers.any;
15 import static org.mockito.Matchers.anyString;
16 import static org.mockito.Matchers.same;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.times;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
22 import java.lang.reflect.Field;
23 import java.net.InetAddress;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.List;
30 import java.util.Random;
32 import java.util.concurrent.BlockingQueue;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentMap;
36 import org.junit.Before;
37 import org.junit.Ignore;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.mockito.InjectMocks;
41 import org.mockito.Mock;
42 import org.mockito.Mockito;
43 import org.mockito.runners.MockitoJUnitRunner;
44 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
45 import org.opendaylight.neutron.spi.INeutronNetworkCRUD;
46 import org.opendaylight.neutron.spi.INeutronPortCRUD;
47 import org.opendaylight.neutron.spi.INeutronSubnetCRUD;
48 import org.opendaylight.neutron.spi.NeutronLoadBalancerPool;
49 import org.opendaylight.neutron.spi.NeutronNetwork;
50 import org.opendaylight.ovsdb.lib.notation.Column;
51 import org.opendaylight.ovsdb.lib.notation.Row;
52 import org.opendaylight.ovsdb.lib.notation.UUID;
53 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
54 import org.opendaylight.ovsdb.openstack.netvirt.AbstractEvent;
55 import org.opendaylight.ovsdb.openstack.netvirt.AbstractHandler;
56 import org.opendaylight.ovsdb.openstack.netvirt.LBaaSHandler;
57 import org.opendaylight.ovsdb.openstack.netvirt.LBaaSPoolHandler;
58 import org.opendaylight.ovsdb.openstack.netvirt.NetworkHandler;
59 import org.opendaylight.ovsdb.openstack.netvirt.NeutronCacheUtils;
60 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
61 import org.opendaylight.ovsdb.openstack.netvirt.api.BridgeConfigurationManager;
62 import org.opendaylight.ovsdb.openstack.netvirt.api.ClassifierProvider;
63 import org.opendaylight.ovsdb.openstack.netvirt.api.ConfigurationService;
64 import org.opendaylight.ovsdb.openstack.netvirt.api.Constants;
65 import org.opendaylight.ovsdb.openstack.netvirt.api.EgressAclProvider;
66 import org.opendaylight.ovsdb.openstack.netvirt.api.IngressAclProvider;
67 import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
68 import org.opendaylight.ovsdb.openstack.netvirt.api.SecurityServicesManager;
69 import org.opendaylight.ovsdb.openstack.netvirt.api.Status;
70 import org.opendaylight.ovsdb.openstack.netvirt.api.StatusCode;
71 import org.opendaylight.ovsdb.openstack.netvirt.api.TenantNetworkManager;
72 import org.opendaylight.ovsdb.openstack.netvirt.impl.EventDispatcherImpl;
73 //import org.opendaylight.ovsdb.plugin.api.OvsdbConnectionService;
74 import org.opendaylight.ovsdb.schema.openvswitch.Bridge;
75 import org.opendaylight.ovsdb.schema.openvswitch.Interface;
76 import org.opendaylight.ovsdb.schema.openvswitch.Port;
77 import org.opendaylight.ovsdb.utils.mdsal.node.StringConvertor;
78 //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
79 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
80 //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
81 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
83 //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
85 import org.osgi.framework.ServiceReference;
86 import org.powermock.api.mockito.PowerMockito;
87 import org.powermock.core.classloader.annotations.PrepareForTest;
88 import org.powermock.modules.junit4.PowerMockRunner;
91 * Unit test for {@link OF13Provider}
93 /* TODO SB_MIGRATION */
95 @PrepareForTest(OF13Provider.class)
96 @RunWith(PowerMockRunner.class)
97 public class OF13ProviderTest {
99 @InjectMocks private OF13Provider of13Provider;
100 @Mock private NeutronNetwork network;
101 @Mock private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node openflowNode;
102 @Mock private Node node;
103 @Mock private Node node2;
104 @Mock private Node node3;
105 @Mock private Interface intf;
107 @Mock private ConfigurationService configurationService;
108 @Mock private BridgeConfigurationManager bridgeConfigurationManager;
109 @Mock private TenantNetworkManager tenantNetworkManager;
110 /* TODO SB_MIGRATION */
111 //@Mock private OvsdbConnectionService connectionService;
112 @Mock private MdsalConsumer mdsalConsumer;
113 @Mock private SecurityServicesManager securityServicesManager;
114 @Mock private IngressAclProvider ingressAclProvider;
115 @Mock private EgressAclProvider egressAclProvider;
116 @Mock private ClassifierProvider classifierProvider;
117 @Mock private L2ForwardingProvider l2ForwardingProvider;
118 @Mock private DataBroker dataBroker;
122 public void setUp() throws Exception{
123 of13Provider = new OF13Provider();
125 //Setup mock dependency services.
126 configurationService = Mockito.mock(ConfigurationService.class);
127 bridgeConfigurationManager = Mockito.mock(BridgeConfigurationManager.class);
128 tenantNetworkManager = Mockito.mock(TenantNetworkManager.class);
129 /* TODO SB_MIGRATION */
130 //connectionService = Mockito.mock(OvsdbConnectionService.class);
131 mdsalConsumer = Mockito.mock(MdsalConsumer.class);
132 securityServicesManager = Mockito.mock(SecurityServicesManager.class);
133 ingressAclProvider = Mockito.mock(IngressAclProvider.class);
134 egressAclProvider = Mockito.mock(EgressAclProvider.class);
135 classifierProvider = Mockito.mock(ClassifierProvider.class);
136 l2ForwardingProvider = Mockito.mock(L2ForwardingProvider.class);
137 dataBroker = Mockito.mock(DataBroker.class);
139 this.SeedMockDependencies();
141 List<Node> nodeList = new ArrayList();
142 NodeId nodeId = new NodeId("Node1");
143 NodeKey nodeKey = new NodeKey(nodeId);
145 node = Mockito.mock(Node.class);
146 when(node.getNodeId()).thenReturn(nodeId);
147 when(node.getKey()).thenReturn(new NodeKey(nodeId));
148 when(configurationService.getTunnelEndPoint(node)).thenReturn(InetAddress.getByName("192.168.0.1"));
151 nodeId = new NodeId("Node2");
152 node2 = Mockito.mock(Node.class);
153 when(node2.getNodeId()).thenReturn(nodeId);
154 when(node2.getKey()).thenReturn(new NodeKey(nodeId));
155 when(configurationService.getTunnelEndPoint(node2)).thenReturn(InetAddress.getByName("192.168.0.2"));
158 nodeId = new NodeId("Node3");
159 node3 = Mockito.mock(Node.class);
160 when(node3.getNodeId()).thenReturn(nodeId);
161 when(node3.getKey()).thenReturn(new NodeKey(nodeId));
162 when(configurationService.getTunnelEndPoint(node3)).thenReturn(InetAddress.getByName("192.168.0.3"));
165 /* TODO SB_MIGRATION */
166 //when(connectionService.getNodes()).thenReturn(nodeList);
168 final String key = "key";
169 ConcurrentHashMap<String, Row> bridgeTable = new ConcurrentHashMap();
170 bridgeTable.put(key, new Row());
172 Row bridgeRow = Mockito.mock(Row.class);
173 Bridge bridge = Mockito.mock(Bridge.class);
176 Set<String> paths = new HashSet<String>(Arrays.asList(new String[] { "100"}));
177 Column<GenericTableSchema, Set<String>> dataPathIdColumns = Mockito.mock(Column.class);
179 when(dataPathIdColumns.getData()).thenReturn(paths);
180 when(bridge.getDatapathIdColumn()).thenReturn(dataPathIdColumns);
182 /* TODO SB_MIGRATION */
183 when(configurationService.getIntegrationBridgeName()).thenReturn(key);
184 //when(ovsdbConfigurationService.getTableName(node, Bridge.class)).thenReturn(key);
185 //when(ovsdbConfigurationService.getRows(node, key)).thenReturn(bridgeTable);
186 //when(ovsdbConfigurationService.getRow(node, ovsdbConfigurationService.getTableName(node, Bridge.class), key)).thenReturn(bridgeRow);
187 //when(ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeRow)).thenReturn(bridge);
189 Bridge bridge1 = Mockito.mock(Bridge.class);
190 when(bridge1.getName()).thenReturn(key);
191 //when(ovsdbConfigurationService.getTypedRow(node, Bridge.class, bridgeTable.get(key))).thenReturn(bridge1);
193 Port port = mock(Port.class);
194 Column<GenericTableSchema, Set<UUID>> itfaceColumns = mock(Column.class);
195 when(port.getInterfacesColumn()).thenReturn(itfaceColumns);
196 Set<UUID> ifaceUUIDs = new HashSet();
197 ifaceUUIDs.add(mock(UUID.class));
198 when(itfaceColumns.getData()).thenReturn(ifaceUUIDs );
199 //when(ovsdbConfigurationService.getTypedRow(any(Node.class), same(Port.class), any(Row.class))).thenReturn(port);
201 intf = mock(Interface.class);
203 Set<Long> ports = new HashSet<Long>(Arrays.asList(new Long[] { 21L, 23L ,80L}));
204 Column<GenericTableSchema, Set<Long>> openFlowPortColumns = Mockito.mock(Column.class);
205 when(openFlowPortColumns.getData()).thenReturn(ports);
207 when(intf.getName()).thenReturn("intf1");
208 when(intf.getOpenFlowPortColumn()).thenReturn(openFlowPortColumns);
210 Column<GenericTableSchema, Map<String, String>> externalIdColumns = mock(Column.class);
211 Map<String, String> externalIds = new HashMap();
212 externalIds.put(Constants.EXTERNAL_ID_INTERFACE_ID, "portUUID");
213 externalIds.put(Constants.EXTERNAL_ID_VM_MAC, "extMac");
214 when(externalIdColumns.getData()).thenReturn(externalIds);
216 when(intf.getExternalIdsColumn()).thenReturn(externalIdColumns);
217 //when(ovsdbConfigurationService.getTypedRow(any(Node.class), same(Interface.class), any(Row.class))).thenReturn(intf);
226 * hasPerTenantTunneling()
229 public void verifyObjectDefaultSettings(){
230 assertEquals("Error, getName() - Default provider name is invalid","OF13Provider",of13Provider.getName());
231 assertEquals("Error, supportsServices() - Support services is disabled", true, of13Provider.supportsServices());
232 assertEquals("Error, hasPerTenantTunneling() - Support for per tenant tunnelling is enabled", false, of13Provider.hasPerTenantTunneling());
237 * {@link OF13Provider#notifyFlowCapableNodeEventTest(Long, Action)}
240 public void notifyFlowCapableNodeEventTest(){
243 Action action = Action.ADD;
245 //of13Provider.notifyFlowCapableNodeEvent(flowId, action);
246 //verify(mdsalConsumer, times(1)).notifyFlowCapableNodeCreateEvent(Constants.OPENFLOW_NODE_PREFIX + flowId, action);
251 * {@link OF13Provider#initializeFlowRules(Node)}
254 public void initializeFlowRulesTest(){
256 Row row = Mockito.mock(Row.class);
257 //when(ovsdbConfigurationService.getTypedRow(node, Interface.class, row)).thenReturn(intf);
259 ConcurrentHashMap<String, Row> intfs = new ConcurrentHashMap();
260 intfs.put("intf1", row);
262 NeutronNetwork network = Mockito.mock(NeutronNetwork.class);
263 when(network.getProviderNetworkType()).thenReturn(NetworkHandler.NETWORK_TYPE_VLAN);
264 //when(tenantNetworkManager.getTenantNetwork(intf)).thenReturn(network);
265 //when(ovsdbConfigurationService.getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class))).thenReturn(intfs);
267 of13Provider.initializeFlowRules(node);
270 * The final phase of the initialization process is to call triggerInterfaceUpdates(node)
271 * This must call tenantNetworkManager.getTenantNetwork(Interface) for each interface.
272 * Verify that this is called once since we are initializing flow rules for only one interface.
274 /* TODO SB_MIGRATION */
275 //verify(tenantNetworkManager, times(1)).getTenantNetwork(intf);
280 * {@link OF13Provider#initializeOFFlowRulesTest(Node)}
283 public void initializeOFFlowRulesTest(){
284 /* TODO SB_MIGRATION */
285 //of13Provider.initializeOFFlowRules(openflowNode);
286 //verify(connectionService, times(1)).getNodes();
291 * {@link OF13Provider#handleInterfaceUpdateTest(NeutronNetwork, Node, Interface)}
294 public void handleInterfaceUpdateTest(){
295 NeutronNetwork network = Mockito.mock(NeutronNetwork.class);
298 * For Vlan network type, test ensures that all parameter validations
299 * passed by ensuring that ovsdbConfigurationService.getRows(node,"interface_table_name))
300 * is called at least once.
303 when(network.getProviderNetworkType()).thenReturn(NetworkHandler.NETWORK_TYPE_VLAN);
304 /* TODO SB_MIGRATION */
305 //this.of13Provider.handleInterfaceUpdate(network, node, intf);
306 //verify(ovsdbConfigurationService, times(1)).getRows(node, ovsdbConfigurationService.getTableName(node, Interface.class));
309 * Ideally we want to verify that the right rule tables are constructed for
310 * each type of network (vlan, gre, vxlan). However, to simplify things, we just
311 * verify that configurationService.getTunnelEndPoint() is called twice for the appropriate
312 * network types and for each of the two remaining nodes.
315 when(network.getProviderNetworkType()).thenReturn(NetworkHandler.NETWORK_TYPE_GRE);
316 /* TODO SB_MIGRATION */
317 //this.of13Provider.handleInterfaceUpdate(network, node, intf);this.of13Provider.handleInterfaceUpdate(network, node, intf);
318 /* TODO SB_MIGRATION */
319 //verify(configurationService, times(4)).getTunnelEndPoint(node);
321 when(network.getProviderNetworkType()).thenReturn(NetworkHandler.NETWORK_TYPE_VXLAN);
322 /* TODO SB_MIGRATION */
323 //this.of13Provider.handleInterfaceUpdate(network, node, intf);this.of13Provider.handleInterfaceUpdate(network, node, intf);
324 //verify(configurationService, times(8)).getTunnelEndPoint(node);
326 //assertEquals("Error, handleInterfaceUpdate(String, String) - is returning a non NULL value.", null, this.of13Provider.handleInterfaceUpdate("",""));
331 * {@link OF13Provider#handleInterfaceDelete(String, NeutronNetwork, Node, Interface, boolean)}
334 public void handleInterfaceDeleteTest(){
335 NeutronNetwork network = Mockito.mock(NeutronNetwork.class);
338 when(network.getProviderNetworkType()).thenReturn(NetworkHandler.NETWORK_TYPE_VLAN);
339 when(bridgeConfigurationManager.getAllPhysicalInterfaceNames(node)).thenReturn(Arrays.asList(new String[] { "eth0", "eth1" ,"eth2"}));
341 Column<GenericTableSchema, String> typeColumn = Mockito.mock(Column.class);
342 when(typeColumn.getData()).thenReturn(NetworkHandler.NETWORK_TYPE_VXLAN);
343 when(intf.getTypeColumn()).thenReturn(typeColumn);
345 Map<String, String> options = new HashMap();
346 options.put("local_ip", "192.168.0.1");
347 options.put("remote_ip", "10.0.12.0");
349 Column<GenericTableSchema, Map<String, String>> optionColumns = Mockito.mock(Column.class);
350 when(intf.getOptionsColumn()).thenReturn(optionColumns);
352 /* TODO SB_MIGRATION */
353 Status status = null;//this.of13Provider.handleInterfaceDelete("tunnel1", network, node, intf, true);
355 assertEquals("Error, handleInterfaceDelete(String, NeutronNetwor, Node, Interface, boolean) - returned the wrong status.", new Status(StatusCode.SUCCESS), status);
361 * {@link OF13Provider#createNodeBuilderTest(String)}
364 public void createNodeBuilderTest(){
365 final String nodeId="node1";
367 NodeBuilder builder = new NodeBuilder();
368 builder.setId(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(nodeId));
369 builder.setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(builder.getId()));
371 NodeBuilder builderStatic = OF13Provider.createNodeBuilder(nodeId);
373 assertEquals("Error, createNodeBuilder() returned an invalid Node Builder Id", builderStatic.getId(), builder.getId());
374 assertEquals("Error, createNodeBuilder() returned an invalid Node Builder key", builderStatic.getKey(), builder.getKey());
378 * Seeds mock dependencies into the of13Provider object
381 private void SeedMockDependencies() throws Exception{
383 SeedClassFieldValue(of13Provider, "configurationService", configurationService);
384 SeedClassFieldValue(of13Provider, "bridgeConfigurationManager", bridgeConfigurationManager);
385 SeedClassFieldValue(of13Provider, "tenantNetworkManager", tenantNetworkManager);
386 /* TODO SB_MIGRATION */
387 //SeedClassFieldValue(of13Provider, "ovsdbConfigurationService", ovsdbConfigurationService);
388 //SeedClassFieldValue(of13Provider, "connectionService", connectionService);
389 SeedClassFieldValue(of13Provider, "mdsalConsumer", mdsalConsumer);
390 SeedClassFieldValue(of13Provider, "securityServicesManager", securityServicesManager);
391 SeedClassFieldValue(of13Provider, "ingressAclProvider", ingressAclProvider);
392 SeedClassFieldValue(of13Provider, "egressAclProvider", egressAclProvider);
393 SeedClassFieldValue(of13Provider, "classifierProvider", classifierProvider);
394 SeedClassFieldValue(of13Provider, "l2ForwardingProvider", l2ForwardingProvider);
395 SeedClassFieldValue(of13Provider, "dataBroker", dataBroker);
399 * Get the specified field from OF13Provider using reflection
400 * @param instance - the class instance
401 * @param fieldName - the field to retrieve
403 * @return the desired field
405 private Object getClassField(OF13Provider instance, String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
406 Field field = OF13Provider.class.getDeclaredField(fieldName);
407 field.setAccessible(true);
408 return field.get(instance);
412 * Sets the internal value of a field from OF13Provider using reflection
416 * @throws NoSuchFieldException
417 * @throws SecurityException
418 * @throws IllegalArgumentException
419 * @throws IllegalAccessException
421 private void SeedClassFieldValue(OF13Provider instance, String fieldName, Object value)throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
423 Field field = OF13Provider.class.getDeclaredField(fieldName);
424 field.setAccessible(true);
425 field.set(instance, value);