split it-utils: ovsdb-it-utils + netvirt-it-utils
[netvirt.git] / openstack / net-virt-sfc / it / src / test / java / org / opendaylight / netvirt / openstack / netvirt / sfc / it / NetvirtSfcIT.java
1 /*
2  * Copyright © 2015 Red Hat, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netvirt.openstack.netvirt.sfc.it;
10
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.ops4j.pax.exam.CoreOptions.composite;
17 import static org.ops4j.pax.exam.CoreOptions.maven;
18 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
19 import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties;
20 import static org.ops4j.pax.exam.CoreOptions.vmOption;
21 import static org.ops4j.pax.exam.CoreOptions.when;
22 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
23 import static org.ops4j.pax.exam.MavenUtils.asInProject;
24 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
25 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
26 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
27
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Properties;
34 import java.util.concurrent.atomic.AtomicBoolean;
35
36 import org.junit.After;
37 import org.junit.Assert;
38 import org.junit.Before;
39 import org.junit.Ignore;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
43 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
44 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
45 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
46 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.AclUtils;
47 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.ClassifierUtils;
48 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.RenderedServicePathUtils;
49 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.ServiceFunctionChainUtils;
50 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.ServiceFunctionPathUtils;
51 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.ServiceFunctionUtils;
52 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.SfcConfigUtils;
53 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
54 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.PipelineOrchestrator;
55 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
56 import org.opendaylight.netvirt.openstack.netvirt.sfc.NshUtils;
57 import org.opendaylight.netvirt.openstack.netvirt.sfc.SfcUtils;
58 import org.opendaylight.netvirt.openstack.netvirt.sfc.standalone.openflow13.SfcClassifier;
59 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.NetvirtConfigUtils;
60 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.ServiceFunctionForwarderUtils;
61 import org.opendaylight.netvirt.openstack.netvirt.sfc.it.utils.NetvirtSfcUtils;
62 import org.opendaylight.netvirt.openstack.netvirt.sfc.workaround.services.FlowNames;
63 import org.opendaylight.netvirt.utils.netvirt.it.utils.NetvirtItUtils;
64 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
65 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.OvsdbItUtils;
66 import org.opendaylight.ovsdb.utils.ovsdb.it.utils.NodeInfo;
67 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
68 import org.opendaylight.netvirt.utils.mdsal.utils.MdsalUtils;
69 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
70 import org.opendaylight.ovsdb.utils.mdsal.utils.NotifyingDataChangeListener;
71 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
72 import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
73 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
74 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SftType;
75 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
77 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
78 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
79 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
80 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctions;
81 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.ServiceFunctionsBuilder;
82 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
83 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunctionBuilder;
84 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChains;
85 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.ServiceFunctionChainsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChain;
87 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.ServiceFunctionChainBuilder;
88 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunction;
89 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfc.rev140701.service.function.chain.grouping.service.function.chain.SfcServiceFunctionBuilder;
90 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
91 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwardersBuilder;
92 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
93 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
94 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
95 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
96 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
97 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
98 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfig;
99 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.of.renderer.rev151123.SfcOfRendererConfigBuilder;
100 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessLists;
101 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.AccessListsBuilder;
102 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.AclBuilder;
103 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.AccessListEntriesBuilder;
104 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.AceBuilder;
105 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.ActionsBuilder;
106 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev150317.access.lists.acl.access.list.entries.ace.MatchesBuilder;
107 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
108 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
109 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfig;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.providers.config.rev160109.NetvirtProvidersConfigBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.Classifiers;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.ClassifiersBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.ClassifierBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.SffsBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.classifier.rev150105.classifiers.classifier.sffs.SffBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.Sfc;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.sfc.rev150105.SfcBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
125 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
126 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
127 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
128 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
129 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
130 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
131 import org.opendaylight.yangtools.concepts.Builder;
132 import org.opendaylight.yangtools.yang.binding.DataObject;
133 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
134 import org.ops4j.pax.exam.Configuration;
135 import org.ops4j.pax.exam.Option;
136 import org.ops4j.pax.exam.junit.PaxExam;
137 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
138 import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel;
139 import org.ops4j.pax.exam.options.MavenUrlReference;
140 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
141 import org.ops4j.pax.exam.spi.reactors.PerClass;
142 import org.slf4j.Logger;
143 import org.slf4j.LoggerFactory;
144
145 import com.google.common.collect.Maps;
146
147 @RunWith(PaxExam.class)
148 @ExamReactorStrategy(PerClass.class)
149 public class NetvirtSfcIT extends AbstractMdsalTestBase {
150     private static final Logger LOG = LoggerFactory.getLogger(NetvirtSfcIT.class);
151     private static AclUtils aclUtils = new AclUtils();
152     private static ClassifierUtils classifierUtils = new ClassifierUtils();
153     private static NetvirtSfcUtils netvirtSfcUtils = new NetvirtSfcUtils();
154     private static ServiceFunctionUtils serviceFunctionUtils = new ServiceFunctionUtils();
155     private static ServiceFunctionForwarderUtils serviceFunctionForwarderUtils = new ServiceFunctionForwarderUtils();
156     private static ServiceFunctionChainUtils serviceFunctionChainUtils = new ServiceFunctionChainUtils();
157     private static ServiceFunctionPathUtils serviceFunctionPathUtils = new ServiceFunctionPathUtils();
158     private static RenderedServicePathUtils renderedServicePathUtils = new RenderedServicePathUtils();
159     private static SfcConfigUtils sfcConfigUtils = new SfcConfigUtils();
160     private static NetvirtConfigUtils netvirtConfigUtils = new NetvirtConfigUtils();
161     private static MdsalUtils mdsalUtils;
162     private static AtomicBoolean setup = new AtomicBoolean(false);
163     private static SouthboundUtils southboundUtils;
164     private static SfcUtils sfcUtils;
165     private static String addressStr;
166     private static String portStr;
167     private static String connectionType;
168     private static String controllerStr;
169     private static boolean ovsdb_wait = false;
170     private static String userSpaceEnabled = "no";
171     private static PipelineOrchestrator pipelineOrchestrator;
172     private static Southbound southbound;
173     private static DataBroker dataBroker;
174     private static OvsdbItUtils itUtils;
175     private static NetvirtItUtils nvItUtils;
176     public static final String CONTROLLER_IPADDRESS = "ovsdb.controller.address";
177     public static final String SERVER_IPADDRESS = "ovsdbserver.ipaddress";
178     public static final String SERVER_PORT = "ovsdbserver.port";
179     public static final String CONNECTION_TYPE = "ovsdbserver.connection";
180     public static final String CONNECTION_TYPE_ACTIVE = "active";
181     public static final String CONNECTION_TYPE_PASSIVE = "passive";
182     public static final String DEFAULT_SERVER_PORT = "6640";
183     public static final String USERSPACE_ENABLED = "ovsdb.userspace.enabled";
184     public static final String INTEGRATION_BRIDGE_NAME = "br-int";
185     private static final String NETVIRT_TOPOLOGY_ID = "netvirt:1";
186     private static final String OVSDB_TRACE = "ovsdb.trace";
187     private static final String OVSDB_WAIT = "ovsdb.wait";
188     private static final String SF1NAME = "firewall-72";
189     private static final String SF2NAME = "dpi-72";
190     private static final String SF1IP = "10.2.1.1";//"192.168.50.70";//"192.168.120.31";
191     private static final String SF2IP = "10.2.1.2";
192     private static final String SF1DPLNAME = "sf1";
193     private static final String SF2DPLNAME = "sf2";
194     // Use 192.168.50.70 when running against vagrant vm for workaround testing, eg. netvirtsfc-env.
195     // Use 192.168.1.129 (or whatever address is dhcp'ed) for tacker-vm.
196     // "192.168.50.70"; "127.0.0.1"; "192.168.1.129";
197     private static final String SFF1IP = "192.168.50.70";
198     private static final String SFF2IP = "127.0.0.1";
199     private static final String SFF1NAME = "sff1";
200     private static final String SFF2NAME = "sff2";
201     private static final String SFFDPL1NAME = "vxgpe";
202     private static final String SFFDPL2NAME = "vxgpe";
203     private static final String SN1NAME = "ovsdb1";
204     private static final String SN2NAME = "ovsdb2";
205     private static final String BRIDGE1NAME= "br-int";
206     private static final String BRIDGE2NAME= "br-int";
207     private static final String ACLNAME= "httpAcl";
208     private static final String RULENAME= "httpRule";
209     private static final String SFCNAME = "SFC";
210     private static final String SFCPATH = "SFC-Path";
211     private static final String RSPNAME = SFCPATH + "_rsp";
212     private static final String SFCSF1NAME = "firewall-abstract";
213     private static final SftType SFCSF1TYPE = new SftType("firewall");
214     private static final int GPEUDPPORT = 6633;
215
216     @Override
217     public String getModuleName() {
218         return "netvirt-sfc-impl";
219     }
220
221     @Override
222     public String getInstanceName() {
223         return "netvirt-sfc-impl";
224     }
225
226     @Override
227     public MavenUrlReference getFeatureRepo() {
228         return maven()
229                 .groupId("org.opendaylight.netvirt")
230                 .artifactId("openstack.net-virt-sfc-features")
231                 .classifier("features")
232                 .type("xml")
233                 .versionAsInProject();
234     }
235
236     @Override
237     public String getFeatureName() {
238         return "odl-ovsdb-sfc-test";
239     }
240
241     @Configuration
242     @Override
243     public Option[] config() {
244         Option[] parentOptions = super.config();
245         Option[] propertiesOptions = getPropertiesOptions();
246         Option[] otherOptions = getOtherOptions();
247         Option[] options = new Option[parentOptions.length + propertiesOptions.length + otherOptions.length];
248         System.arraycopy(parentOptions, 0, options, 0, parentOptions.length);
249         System.arraycopy(propertiesOptions, 0, options, parentOptions.length, propertiesOptions.length);
250         System.arraycopy(otherOptions, 0, options, parentOptions.length + propertiesOptions.length,
251                 otherOptions.length);
252         return options;
253     }
254
255     private Option[] getOtherOptions() {
256         return new Option[] {
257                 wrappedBundle(
258                         mavenBundle("org.opendaylight.netvirt", "utils.mdsal-openflow")
259                                 .version(asInProject())
260                                 .type("jar")),
261                 configureConsole().startLocalConsole(),
262                 //vmOption("-verbose:class"),
263                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
264                 keepRuntimeFolder()
265         };
266     }
267
268     public Option[] getPropertiesOptions() {
269         return new Option[] {
270                 propagateSystemProperties(SERVER_IPADDRESS, SERVER_PORT, CONNECTION_TYPE,
271                         CONTROLLER_IPADDRESS, OVSDB_TRACE, OVSDB_WAIT, USERSPACE_ENABLED),
272         };
273     }
274
275     @Override
276     public Option getLoggingOption() {
277         return composite(
278                 when(Boolean.getBoolean(OVSDB_TRACE)).useOptions(
279                         editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
280                                 "log4j.logger.org.opendaylight.ovsdb",
281                                 LogLevelOption.LogLevel.TRACE.name())),
282                 //editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
283                 //        "log4j.logger.org.opendaylight.ovsdb",
284                 //        LogLevelOption.LogLevel.TRACE.name()),
285                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
286                         "log4j.logger.org.opendaylight.ovsdb.library",
287                         LogLevel.INFO.name()),
288                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
289                         logConfiguration(NetvirtSfcIT.class),
290                         LogLevel.INFO.name()),
291                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
292                         "log4j.logger.org.opendaylight.netvirt.openstack.netvirt.sfc",
293                         LogLevel.TRACE.name()),
294                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
295                         "log4j.logger.org.opendaylight.netvirt.openstack.netvirt.providers.openflow13",
296                         LogLevel.TRACE.name()),
297                 editConfigurationFilePut(ORG_OPS4J_PAX_LOGGING_CFG,
298                         "log4j.logger.org.opendaylight.sfc",
299                         LogLevel.TRACE.name()),
300                 super.getLoggingOption());
301     }
302
303     protected String usage() {
304         return "Integration Test needs a valid connection configuration as follows :\n"
305                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
306                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
307     }
308
309     private void getProperties() {
310         Properties props = System.getProperties();
311         addressStr = props.getProperty(SERVER_IPADDRESS);
312         portStr = props.getProperty(SERVER_PORT, DEFAULT_SERVER_PORT);
313         connectionType = props.getProperty(CONNECTION_TYPE, "active");
314         controllerStr = props.getProperty(CONTROLLER_IPADDRESS, "0.0.0.0");
315         userSpaceEnabled = props.getProperty(USERSPACE_ENABLED, "no");
316         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}, controller ip: {}, " +
317                         "userspace.enabled: {}",
318                 connectionType, addressStr, portStr, controllerStr, userSpaceEnabled);
319         if (connectionType.equalsIgnoreCase(CONNECTION_TYPE_ACTIVE)) {
320             if (addressStr == null) {
321                 fail(usage());
322             }
323         }
324         LOG.info("getProperties {}: {}", OVSDB_TRACE, props.getProperty(OVSDB_TRACE));
325         LOG.info("getProperties {}: {}", OVSDB_WAIT, props.getProperty(OVSDB_WAIT));
326         if (props.getProperty(OVSDB_WAIT) != null && props.getProperty(OVSDB_WAIT).equals("true")) {
327             ovsdb_wait = true;
328         }
329     }
330
331     @Before
332     @Override
333     public void setup() {
334         if (setup.get()) {
335             LOG.info("Skipping setUp, already initialized");
336             return;
337         }
338
339         try {
340             Thread.sleep(1000);
341             super.setup();
342         } catch (Exception e) {
343             LOG.warn("Failed to setup test", e);
344             fail("Failed to setup test: " + e);
345         }
346
347         getProperties();
348
349         dataBroker = getDatabroker(getProviderContext());
350         itUtils = new OvsdbItUtils(dataBroker);
351         nvItUtils = new NetvirtItUtils(dataBroker);
352         mdsalUtils = new MdsalUtils(dataBroker);
353         org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils sbMdsalUtils =
354                 new org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils(dataBroker);
355         assertNotNull("mdsalUtils should not be null", mdsalUtils);
356         southboundUtils = new SouthboundUtils(sbMdsalUtils);
357         sfcUtils = new SfcUtils(mdsalUtils);
358         assertTrue("Did not find " + NETVIRT_TOPOLOGY_ID, getNetvirtTopology());
359         southbound = (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
360         assertNotNull("southbound should not be null", southbound);
361         pipelineOrchestrator =
362                 (PipelineOrchestrator) ServiceHelper.getGlobalInstance(PipelineOrchestrator.class, this);
363         assertNotNull("pipelineOrchestrator should not be null", pipelineOrchestrator);
364
365         setup.set(true);
366     }
367
368     @After
369     public void teardown() {
370         closeWaitFors();
371     }
372
373     private ProviderContext getProviderContext() {
374         ProviderContext providerContext = null;
375         for (int i=0; i < 60; i++) {
376             providerContext = getSession();
377             if (providerContext != null) {
378                 break;
379             } else {
380                 try {
381                     Thread.sleep(1000);
382                 } catch (InterruptedException e) {
383                     LOG.warn("Interrupted while waiting for provider context", e);
384                 }
385             }
386         }
387         assertNotNull("providercontext should not be null", providerContext);
388         /* One more second to let the provider finish initialization */
389         try {
390             Thread.sleep(1000);
391         } catch (InterruptedException e) {
392             LOG.warn("Interrupted while waiting for other provider", e);
393         }
394         return providerContext;
395     }
396
397     private DataBroker getDatabroker(ProviderContext providerContext) {
398         DataBroker dataBroker = providerContext.getSALService(DataBroker.class);
399         assertNotNull("dataBroker should not be null", dataBroker);
400         return dataBroker;
401     }
402
403     private Boolean getNetvirtTopology() {
404         LOG.info("getNetvirtTopology: looking for {}...", NETVIRT_TOPOLOGY_ID);
405         Boolean found = false;
406         final TopologyId topologyId = new TopologyId(new Uri(NETVIRT_TOPOLOGY_ID));
407         InstanceIdentifier<Topology> path =
408                 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, new TopologyKey(topologyId));
409         for (int i = 0; i < 60; i++) {
410             Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
411             if (topology != null) {
412                 LOG.info("getNetvirtTopology: found {}...", NETVIRT_TOPOLOGY_ID);
413                 found = true;
414                 break;
415             } else {
416                 LOG.info("getNetvirtTopology: still looking ({})...", i);
417                 try {
418                     Thread.sleep(1000);
419                 } catch (InterruptedException e) {
420                     LOG.warn("Interrupted while waiting for {}", NETVIRT_TOPOLOGY_ID, e);
421                 }
422             }
423         }
424         return found;
425     }
426
427     private AccessListsBuilder accessListsBuilder() {
428         return accessListsBuilder(false);
429     }
430
431     private AccessListsBuilder accessListsBuilder(boolean renderRsp) {
432         String ruleName = RULENAME;
433         String sfcName = SFCNAME;
434         MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
435         LOG.info("Matches: {}", matchesBuilder.build());
436         ActionsBuilder actionsBuilder = aclUtils.actionsBuilder(new ActionsBuilder(), sfcName, renderRsp);
437         AceBuilder accessListEntryBuilder =
438                 aclUtils.aceBuilder(new AceBuilder(), ruleName, matchesBuilder, actionsBuilder);
439         AccessListEntriesBuilder accessListEntriesBuilder =
440                 aclUtils.accessListEntriesBuidler(new AccessListEntriesBuilder(), accessListEntryBuilder);
441         AclBuilder accessListBuilder =
442                 aclUtils.aclBuilder(new AclBuilder(), ACLNAME, accessListEntriesBuilder);
443         AccessListsBuilder accessListsBuilder =
444                 aclUtils.accesslistsbuilder(new AccessListsBuilder(), accessListBuilder);
445         LOG.info("AccessLists: {}", accessListsBuilder.build());
446         return accessListsBuilder;
447     }
448
449     @Test
450     public void testAccessLists() throws InterruptedException {
451         testModel(accessListsBuilder(), AccessLists.class, 0);
452     }
453
454     private ClassifiersBuilder classifiersBuilder() {
455         SffBuilder sffBuilder = classifierUtils.sffBuilder(new SffBuilder(), SFF1NAME);
456         SffsBuilder sffsBuilder = classifierUtils.sffsBuilder(new SffsBuilder(), sffBuilder);
457         ClassifierBuilder classifierBuilder = classifierUtils.classifierBuilder(new ClassifierBuilder(),
458                 "classifierName", ACLNAME, sffsBuilder);
459         ClassifiersBuilder classifiersBuilder = classifierUtils.classifiersBuilder(new ClassifiersBuilder(),
460                 classifierBuilder);
461         LOG.info("Classifiers: {}", classifiersBuilder.build());
462         return classifiersBuilder;
463     }
464
465     @Test
466     public void testClassifiers() throws InterruptedException {
467         testModel(classifiersBuilder(), Classifiers.class, 0);
468     }
469
470     private SfcBuilder netvirtSfcBuilder() {
471         return netvirtSfcUtils.sfcBuilder(new SfcBuilder(), "sfc");
472     }
473
474     @Test
475     public void testNetvirtSfcModel() throws InterruptedException {
476         testModel(netvirtSfcBuilder(), Sfc.class, 0);
477     }
478
479     private <T extends DataObject> void testModelPut(Builder<T> builder, Class<T> clazz) {
480         InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
481         assertTrue(mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, path, builder.build()));
482         T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
483         assertNotNull(clazz.getSimpleName() + " should not be null", result);
484     }
485
486     private <T extends DataObject> void testModelDelete(Builder<T> builder, Class<T> clazz)
487             throws InterruptedException {
488         InstanceIdentifier<T> path = InstanceIdentifier.create(clazz);
489         assertTrue("Failed to remove " + clazz.getSimpleName(),
490                 mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, path));
491         T result = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
492         assertNull(clazz.getSimpleName() + " should be null", result);
493     }
494
495     private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz, long wait)
496             throws InterruptedException {
497         testModelPut(builder, clazz);
498         Thread.sleep(wait);
499         testModelDelete(builder, clazz);
500     }
501
502     private <T extends DataObject> void testModel(Builder<T> builder, Class<T> clazz)
503             throws InterruptedException {
504         testModelPut(builder, clazz);
505         Thread.sleep(1000);
506         testModelDelete(builder, clazz);
507     }
508
509     private ServiceFunctionsBuilder serviceFunctionsBuilder() {
510         String sf1Name = SF1NAME;
511         String sf1Ip = SF1IP;
512         String sff1Name = SFF1NAME;
513         String sf1DplName = SF1DPLNAME;
514         int port = GPEUDPPORT;
515
516         ServiceFunctionBuilder serviceFunctionBuilder =
517                 serviceFunctionUtils.serviceFunctionBuilder(sf1Ip, port, sf1DplName, sff1Name, sf1Name);
518         List<ServiceFunction> serviceFunctionList = serviceFunctionUtils.list(
519                 new ArrayList<ServiceFunction>(), serviceFunctionBuilder);
520
521         ServiceFunctionsBuilder serviceFunctionsBuilder =
522                 serviceFunctionUtils.serviceFunctionsBuilder(new ServiceFunctionsBuilder(),
523                         serviceFunctionList);
524         LOG.info("ServiceFunctions: {}", serviceFunctionsBuilder.build());
525         return serviceFunctionsBuilder;
526     }
527
528     private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder() {
529         return serviceFunctionForwardersBuilder(null);
530     }
531
532     private ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder(OvsdbNodeRef ovsdbNodeRef) {
533         String sf1Name = SF1NAME;
534         String sf1Ip = SF1IP;
535         String sf1DplName = SF1DPLNAME;
536         String sff1Ip = SFF1IP;
537         String sff1Name = SFF1NAME;
538         String sffDpl1Name = SFFDPL1NAME;
539         String sn1Name = SN1NAME;
540         String bridge1Name= BRIDGE1NAME;
541         int port = GPEUDPPORT;
542
543         ServiceFunctionForwarderBuilder serviceFunctionForwarderBuilder =
544                 serviceFunctionForwarderUtils.serviceFunctionForwarderBuilder(
545                         sff1Name, sff1Ip, port, sffDpl1Name, sf1Ip, sn1Name, bridge1Name, sf1Name, sf1DplName,
546                         ovsdbNodeRef);
547         List<ServiceFunctionForwarder>  serviceFunctionForwarderList = serviceFunctionForwarderUtils.list(
548                 new ArrayList<ServiceFunctionForwarder>(), serviceFunctionForwarderBuilder);
549
550         ServiceFunctionForwardersBuilder serviceFunctionForwardersBuilder =
551                 serviceFunctionForwarderUtils.serviceFunctionForwardersBuilder(
552                         new ServiceFunctionForwardersBuilder(), serviceFunctionForwarderList);
553         LOG.info("ServiceFunctionForwarders: {}", serviceFunctionForwardersBuilder.build());
554         return serviceFunctionForwardersBuilder;
555     }
556
557     private ServiceFunctionChainsBuilder serviceFunctionChainsBuilder() {
558         String sf1Name = SFCSF1NAME;
559         SftType sfType = SFCSF1TYPE;
560         String sfcName = SFCNAME;
561
562         SfcServiceFunctionBuilder sfcServiceFunctionBuilder = serviceFunctionChainUtils.sfcServiceFunctionBuilder(
563                 new SfcServiceFunctionBuilder(), sf1Name, sfType);
564         List<SfcServiceFunction> sfcServiceFunctionList =
565                 serviceFunctionChainUtils.list(new ArrayList<SfcServiceFunction>(), sfcServiceFunctionBuilder);
566
567         ServiceFunctionChainBuilder serviceFunctionChainBuilder =
568                 serviceFunctionChainUtils.serviceFunctionChainBuilder(
569                         new ServiceFunctionChainBuilder(), sfcName, false, sfcServiceFunctionList);
570         ServiceFunctionChainsBuilder serviceFunctionChainsBuilder =
571                 serviceFunctionChainUtils.serviceFunctionChainsBuilder(
572                         new ServiceFunctionChainsBuilder(),
573                         serviceFunctionChainUtils.list(new ArrayList<ServiceFunctionChain>(),
574                                 serviceFunctionChainBuilder));
575         LOG.info("ServiceFunctionChains: {}", serviceFunctionChainBuilder.build());
576         return serviceFunctionChainsBuilder;
577     }
578
579     private ServiceFunctionPathsBuilder serviceFunctionPathsBuilder() {
580         String sfpName = SFCPATH;
581         String sfcName = SFCNAME;
582         short startingIndex = 255;
583
584         ServiceFunctionPathBuilder serviceFunctionPathBuilder =
585                 serviceFunctionPathUtils.serviceFunctionPathBuilder(
586                         new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
587         ServiceFunctionPathsBuilder serviceFunctionPathsBuilder =
588                 serviceFunctionPathUtils.serviceFunctionPathsBuilder(
589                         serviceFunctionPathUtils.list(new ArrayList<ServiceFunctionPath>(),
590                                 serviceFunctionPathBuilder));
591         LOG.info("ServiceFunctionPaths: {}", serviceFunctionPathsBuilder.build());
592         return serviceFunctionPathsBuilder;
593     }
594
595     private SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder(short tableOffset, short egressTable) {
596         SfcOfRendererConfigBuilder sfcOfRendererConfigBuilder =
597                 sfcConfigUtils.sfcOfRendererConfigBuilder(new SfcOfRendererConfigBuilder(), tableOffset, egressTable);
598         LOG.info("SfcOfRendererConfig: {}", sfcOfRendererConfigBuilder.build());
599         return sfcOfRendererConfigBuilder;
600     }
601
602     private NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder(short tableOffset) {
603         NetvirtProvidersConfigBuilder netvirtProvidersConfigBuilder =
604                 netvirtConfigUtils.netvirtProvidersConfigBuilder(new NetvirtProvidersConfigBuilder(), tableOffset);
605         LOG.info("NetvirtProvidersConfig: {}", netvirtProvidersConfigBuilder.build());
606         return netvirtProvidersConfigBuilder;
607     }
608
609     @Test
610     public void testSfcModel() throws InterruptedException {
611         int timeout = 1000;
612         testModel(serviceFunctionsBuilder(), ServiceFunctions.class, timeout);
613         testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class, timeout);
614         testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class, timeout);
615         testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class, timeout);
616     }
617
618     @Test
619     public void testSfcModels() throws InterruptedException {
620         testModel(serviceFunctionsBuilder(), ServiceFunctions.class);
621         testModel(serviceFunctionForwardersBuilder(), ServiceFunctionForwarders.class);
622         testModel(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
623         testModel(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
624
625         testModel(accessListsBuilder(), AccessLists.class);
626         testModel(classifiersBuilder(), Classifiers.class);
627     }
628
629     /**
630      * Test that the NetvirtSfc SfcClassifierService is added to the Netvirt pipeline. The test
631      * sets the table offset and verifies the correct flow is programmed with the offset.
632      */
633     @Test
634     public void testNetvirtSfcPipeline() throws InterruptedException {
635         short netvirtTableOffset = 1;
636         testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
637
638         NodeInfo nodeInfo = itUtils.createNodeInfo(SouthboundUtils.getConnectionInfo(addressStr, portStr), waitList);
639         nodeInfo.connect();
640
641         String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
642         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER));
643
644         nodeInfo.disconnect();
645     }
646
647     /**
648      * Test the full NetvirtSfc functionality by creating everything needed to realize a chain and
649      * then verify all flows have been created.
650      * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
651      * @throws InterruptedException
652      */
653     @Test
654     public void testNetvirtSfcAll() throws Exception {
655         if (userSpaceEnabled.equals("yes")) {
656             LOG.info("testNetvirtSfcAll: skipping test because userSpaceEnabled {}", userSpaceEnabled);
657             return;
658         }
659
660         String sfpName = SFCPATH;
661         String sfcName = SFCNAME;
662         short startingIndex = 255;
663
664         short netvirtTableOffset = 1;
665         testModelPut(netvirtProvidersConfigBuilder(netvirtTableOffset), NetvirtProvidersConfig.class);
666         short sfcTableoffset = 150;
667         short egressTable = pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
668         testModelPut(sfcOfRendererConfigBuilder(sfcTableoffset, egressTable), SfcOfRendererConfig.class);
669
670         NodeInfo nodeInfo = itUtils.createNodeInfo(SouthboundUtils.getConnectionInfo(addressStr, portStr), waitList);
671         nodeInfo.connect();
672
673         String flowId = "DEFAULT_PIPELINE_FLOW_" + pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER);
674         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER));
675
676         Map<String, String> externalIds = Maps.newHashMap();
677         externalIds.put("attached-mac", "f6:00:00:0f:00:01");
678         southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, SF1DPLNAME, "internal", null, externalIds);
679         externalIds.clear();
680         externalIds.put("attached-mac", "f6:00:00:0c:00:01");
681         southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, "vm1", "internal");
682         externalIds.clear();
683         externalIds.put("attached-mac", "f6:00:00:0c:00:02");
684         southboundUtils.addTerminationPoint(nodeInfo.bridgeNode, "vm2", "internal");
685
686         InstanceIdentifier<TerminationPoint> tpIid =
687                 southboundUtils.createTerminationPointInstanceIdentifier(nodeInfo.bridgeNode, SFFDPL1NAME);
688         final NotifyingDataChangeListener portOperationalListener =
689                 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, tpIid, waitList);
690         portOperationalListener.registerDataChangeListener(dataBroker);
691
692         InstanceIdentifier<RenderedServicePath> rspIid = sfcUtils.getRspId(RSPNAME);
693         final NotifyingDataChangeListener rspOperationalListener =
694                 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, rspIid, waitList);
695         rspOperationalListener.registerDataChangeListener(dataBroker);
696
697         OvsdbBridgeAugmentation bridgeAugmentation = southbound.extractBridgeAugmentation(nodeInfo.bridgeNode);
698         OvsdbNodeRef ovsdbNodeRef = null;
699         if (bridgeAugmentation != null) {
700             ovsdbNodeRef = bridgeAugmentation.getManagedBy();
701         }
702
703         testModelPut(serviceFunctionsBuilder(), ServiceFunctions.class);
704         testModelPut(serviceFunctionForwardersBuilder(ovsdbNodeRef), ServiceFunctionForwarders.class);
705         testModelPut(serviceFunctionChainsBuilder(), ServiceFunctionChains.class);
706         testModelPut(serviceFunctionPathsBuilder(), ServiceFunctionPaths.class);
707
708         testModelPut(accessListsBuilder(false), AccessLists.class);
709         testModelPut(classifiersBuilder(), Classifiers.class);
710         ServiceFunctionPathBuilder serviceFunctionPathBuilder =
711                 serviceFunctionPathUtils.serviceFunctionPathBuilder(
712                         new ServiceFunctionPathBuilder(), sfpName, sfcName, startingIndex, false);
713         SfcProviderRenderedPathAPI.createRenderedServicePathAndState(serviceFunctionPathBuilder.build(),
714                 renderedServicePathUtils.createRenderedPathInputBuilder(new CreateRenderedPathInputBuilder(),
715                         SFCPATH, RSPNAME).build());
716
717         portOperationalListener.waitForCreation();
718         long vxGpeOfPort = southbound.getOFPort(nodeInfo.bridgeNode, SFFDPL1NAME);
719         assertNotEquals("vxGpePort was not found", 0, vxGpeOfPort);
720
721         rspOperationalListener.waitForCreation();
722         RenderedServicePath rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, rspIid);
723         assertNotNull("RSP was not found", rsp);
724
725         flowId = FlowNames.getSfcIngressClass(RULENAME, rsp.getPathId(), rsp.getStartingIndex());
726         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER));
727         RenderedServicePathHop lastHop = sfcUtils.getLastHop(rsp);
728         short lastServiceindex = (short)((lastHop.getServiceIndex()).intValue() - 1);
729         flowId = FlowNames.getSfcEgressClass(vxGpeOfPort, rsp.getPathId(), lastServiceindex);
730         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER));
731         flowId = FlowNames.getSfcEgressClassBypass(rsp.getPathId(), lastServiceindex, 1);
732         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.CLASSIFIER));
733         flowId = FlowNames.getArpResponder(SF1IP);
734         nvItUtils.verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.ARP_RESPONDER));
735         // Only verify these flows if NetVirt adds them and not SFC
736         //flowId = FlowNames.getSfEgress(GPEUDPPORT);
737         //verifyFlow(nodeInfo.datapathId, flowId, pipelineOrchestrator.getTable(Service.SFC_CLASSIFIER));
738         //flowId = FlowNames.getSfIngress(GPEUDPPORT, SF1IP);
739         //verifyFlow(nodeInfo.datapathId, flowId, Service.CLASSIFIER.getTable());
740
741         LOG.info("check for flows!!!!!!!!!!!!!");
742         Thread.sleep(30000);
743         InstanceIdentifier<Flow> flowIid = createFlowIid(nodeInfo.datapathId, flowId,
744                 pipelineOrchestrator.getTable(Service.CLASSIFIER));
745
746         final NotifyingDataChangeListener flowConfigurationListener =
747                 new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, flowIid, waitList);
748         flowConfigurationListener.registerDataChangeListener(dataBroker);
749         final NotifyingDataChangeListener flowOperationalListener =
750                 new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, flowIid, waitList);
751         flowOperationalListener.registerDataChangeListener(dataBroker);
752
753         deleteRsp(RSPNAME);
754         rspOperationalListener.waitForDeletion();
755         rsp = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, rspIid);
756         assertNull("RSP should not be found", rsp);
757
758         flowConfigurationListener.waitForDeletion();
759         Flow flow = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, flowIid);
760         assertNull("Flow should not be found in CONFIGURATION " + flowIid, flow);
761
762         flowOperationalListener.waitForDeletion();
763         flow = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, flowIid);
764         assertNull("Flow should not be found in OPERATIONAL " + flowIid, flow);
765
766         nodeInfo.disconnect();
767     }
768
769     private void deleteRsp(String rspName) {
770         RenderedServicePathKey renderedServicePathKey =
771                 new RenderedServicePathKey(RspName.getDefaultInstance(rspName));
772         InstanceIdentifier<RenderedServicePath> path =
773                 InstanceIdentifier.create(RenderedServicePaths.class)
774                         .child(RenderedServicePath.class, renderedServicePathKey);
775         mdsalUtils.delete(LogicalDatastoreType.OPERATIONAL, path);
776     }
777
778     /**
779      * Test the standalone NetvirtSfc implementation
780      * NOTE: This test requires an OVS with the NSH v8 patch, otherwise it will fail miserably.
781      * @throws InterruptedException
782      */
783     @Ignore
784     @Test
785     public void testStandalone() throws InterruptedException {
786         String bridgeName = "sw1";
787         ConnectionInfo connectionInfo = SouthboundUtils.getConnectionInfo(addressStr, portStr);
788         assertNotNull("connection failed", southboundUtils.connectOvsdbNode(connectionInfo));
789         Node ovsdbNode = southboundUtils.getOvsdbNode(connectionInfo);
790         assertNotNull("node is not connected", ovsdbNode);
791
792         String controllerTarget = "tcp:192.168.50.1:6653";
793         List<ControllerEntry> setControllerEntry = southboundUtils.createControllerEntry(controllerTarget);
794         Assert.assertTrue(southboundUtils.addBridge(connectionInfo, null, bridgeName, null, true,
795                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
796                 setControllerEntry, null, "00:00:00:00:00:00:00:01"));
797         assertTrue("Controller " + SouthboundUtils.connectionInfoToString(connectionInfo)
798                 + " is not connected", itUtils.isControllerConnected(connectionInfo));
799
800         Node bridgeNode = southbound.getBridgeNode(ovsdbNode, bridgeName);
801         assertNotNull("bridge " + bridgeName + " was not found", bridgeNode);
802         long datapathId = southbound.getDataPathId(bridgeNode);
803         String datapathIdString = southbound.getDatapathId(bridgeNode);
804         LOG.info("testNetVirt: bridgeNode: {}, datapathId: {} - {}", bridgeNode, datapathIdString, datapathId);
805         assertNotEquals("datapathId was not found", datapathId, 0);
806
807         SfcClassifier sfcClassifier = new SfcClassifier(dataBroker, southbound, mdsalUtils);
808         //sfcClassifier.programLocalInPort(datapathId, "4096", (long)1, (short)0, (short)50, true);
809
810         NshUtils nshUtils = new NshUtils(new Ipv4Address("192.168.50.71"), new PortNumber(6633),
811                 (long)10, (short)255, (long)4096, (long)4096);
812         MatchesBuilder matchesBuilder = aclUtils.matchesBuilder(new MatchesBuilder(), 80);
813         sfcClassifier.programSfcClassiferFlows(datapathId, (short)0, "test", matchesBuilder.build(),
814                 nshUtils, (long)2, true);
815
816         //nshUtils = new NshUtils(null, null, (long)10, (short)253, 0, 0);
817         //sfcClassifier.programEgressSfcClassiferFlows(datapathId, (short)0, "test", null,
818         //        nshUtils, (long)2, (long)3, true);
819
820         //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
821         //FlowBuilder flowBuilder = getLocalInPortFlow(datapathId, "4096", (long) 1,
822         //                                             pipelineOrchestrator.getTable(Service.CLASSIFIER));
823         //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
824         //assertNotNull("Could not find flow in config", flow);
825         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
826         //assertNotNull("Could not find flow in operational", flow);
827
828         //MatchBuilder matchBuilder = sfcClassifier.buildMatch(matchesBuilder.build());
829         //NodeBuilder nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
830         //FlowBuilder flowBuilder = getSfcClassifierFlow(datapathId,
831         //        pipelineOrchestrator.getTable(Service.CLASSIFIER), "test", null,
832         //        nshUtils, (long) 2, matchBuilder);
833         //Flow flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
834         //assertNotNull("Could not find flow in config", flow);
835         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
836         //assertNotNull("Could not find flow in operational", flow);
837
838         //nodeBuilder = FlowUtils.createNodeBuilder(datapathId);
839         //flowBuilder = getEgressSfcClassifierFlow(datapathId,
840                                                    //pipelineOrchestrator.getTable(Service.CLASSIFIER),
841                                                    //"test", nshUtils, (long) 2);
842         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.CONFIGURATION);
843         //assertNotNull("Could not find flow in config", flow);
844         //flow = getFlow(flowBuilder, nodeBuilder, LogicalDatastoreType.OPERATIONAL);
845         //assertNotNull("Could not find flow in operational", flow);
846
847         LOG.info("***** Go look for flows *****");
848         Thread.sleep(30000);
849         assertTrue(southboundUtils.deleteBridge(connectionInfo, bridgeName));
850         Thread.sleep(1000);
851         assertTrue(southboundUtils.deleteBridge(connectionInfo, INTEGRATION_BRIDGE_NAME));
852         Thread.sleep(1000);
853         assertTrue(southboundUtils.disconnectOvsdbNode(connectionInfo));
854     }
855
856     private InstanceIdentifier<Flow> createFlowIid(long datapathId, String flowId, short table) {
857         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder =
858                 FlowUtils.createNodeBuilder(datapathId);
859         FlowBuilder flowBuilder =
860                 FlowUtils.initFlowBuilder(new FlowBuilder(), flowId, table);
861         return FlowUtils.createFlowPath(flowBuilder, nodeBuilder);
862     }
863
864     private Flow getFlow (
865             FlowBuilder flowBuilder,
866             org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder nodeBuilder,
867             LogicalDatastoreType store) throws InterruptedException {
868
869         Flow flow = null;
870         for (int i = 0; i < 10; i++) {
871             LOG.info("getFlow try {} from {}: looking for flow: {}, node: {}",
872                     i, store, flowBuilder.build(), nodeBuilder.build());
873             flow = FlowUtils.getFlow(flowBuilder, nodeBuilder, dataBroker.newReadOnlyTransaction(), store);
874             if (flow != null) {
875                 LOG.info("getFlow try {} from {}: found flow: {}", i, store, flow);
876                 break;
877             }
878             Thread.sleep(1000);
879         }
880         return flow;
881     }
882
883     private void readwait() {
884         if (ovsdb_wait) {
885             LOG.warn("Waiting, kill with ps -ef | grep java, kill xxx... ");
886             try {
887                 System.in.read();
888             } catch (IOException e) {
889                 e.printStackTrace();
890             }
891         }
892     }
893
894     private List<NotifyingDataChangeListener> waitList = new ArrayList<>();
895
896     private void closeWaitFors() {
897         for (Iterator<NotifyingDataChangeListener> iterator = waitList.iterator(); iterator.hasNext();) {
898             NotifyingDataChangeListener listener = iterator.next();
899             iterator.remove();
900             try {
901                 listener.close();
902             } catch (Exception ex) {
903                 LOG.warn("Failed to close registration {}", listener, ex);
904             }
905         }
906         LOG.info("waitList size {}", waitList.size());
907     }
908
909 }