Create physnet bridges+ports and patch to br-int 25/41925/21
authorJosh <jhershbe@redhat.com>
Sun, 17 Jul 2016 12:09:54 +0000 (14:09 +0200)
committerSam Hague <shague@redhat.com>
Sat, 30 Jul 2016 10:37:44 +0000 (10:37 +0000)
NB: This commit depends on changes in the ovsdb
project: https://git.opendaylight.org/gerrit/#/c/41946/

AND NOW ALSO:
https://git.opendaylight.org/gerrit/#/c/42693/

Assume "provider_mappings=physnet1:ABC". ABC will either be (in this
order) (1) the name of a port already configured on br-int, (2) the name
of a bridge already configured on OVS, or (3) the name of a physical
interface. So for each option:

(1) ABC is a port already on br-int
At OVSDB node add/update event:
  no op
When adding the ElanInterface to the ElanInstance:
  ABC is the name of the port, use that

(2) ABC is the name of a bridge on OVS
At OVSDB node add/update event:
  patch the bridge to br-int, br-int side port name is ABC-patch
When adding the ElanInterface to the ElanInstance:
  ABC-patch is the name of the port, use that

(3) ABC is the name of a NIC
At OVSDB node add/update event:
  add the port directly to br-int
When adding the ElanInterface to the ElanInstance:
  ABC is the name of the port, use that

Change-Id: Ibf6851d420c8197e11a6503b950fa381b829499c
Signed-off-by: Josh <jhershbe@redhat.com>
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanBridgeManager.java [new file with mode: 0644]
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanOvsdbNodeListener.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/BridgeUtils.java [deleted file]

diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanBridgeManager.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanBridgeManager.java
new file mode 100644 (file)
index 0000000..b8c2ba7
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2016 Red Hat, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.elan.internal;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.ovsdb.utils.config.ConfigProperties;
+import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
+import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+
+import java.util.Collections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class provides functions for creating bridges via OVSDB, specifically the br-int bridge.
+ * Note and TODO: br-ex is temporary. vpnservice does not require it but for the time being it is
+ * left here because devstack expects it.
+ */
+public class ElanBridgeManager {
+    private static final Logger LOG = LoggerFactory.getLogger(ElanBridgeManager.class);
+
+    public static final String PROVIDER_MAPPINGS_KEY = "provider_mappings";
+    private static final String INTEGRATION_BRIDGE = "br-int";
+    private static final String EXTERNAL_BRIDGE = "br-ex";
+    private static final String INT_SIDE_PATCH_PORT_SUFFIX = "-expatch";
+    private static final String EX_SIDE_PATCH_PORT_SUFFIX = "-patch";
+
+    private final MdsalUtils mdsalUtils;
+    final SouthboundUtils southboundUtils;
+    private Random random;
+
+    /**
+     * Construct a new ElanBridgeManager
+     * @param dataBroker
+     */
+    public ElanBridgeManager(DataBroker dataBroker) {
+        //TODO: ClusterAware!!!??
+        this.mdsalUtils = new MdsalUtils(dataBroker);
+        this.southboundUtils = new SouthboundUtils(mdsalUtils);
+        this.random = new Random(System.currentTimeMillis());
+    }
+
+    /**
+     * Is OVS running in userspace mode?
+     * @return true if the ovsdb.userspace.enabled variable is set to true
+     */
+    public boolean isUserSpaceEnabled() {
+        final String enabledPropertyStr = ConfigProperties.getProperty(this.getClass(), "ovsdb.userspace.enabled");
+        return enabledPropertyStr != null && enabledPropertyStr.equalsIgnoreCase("yes");
+    }
+
+    /**
+     * Is the Node object an OVSDB node?
+     * @param node unidentified node object
+     * @return true if the Node is an OVSDB node
+     */
+    public boolean isOvsdbNode(Node node) {
+        return southboundUtils.extractNodeAugmentation(node) != null;
+    }
+
+    /**
+     * Is this Node the integration bridge (br-int)
+     * @param node unidentified noe object
+     * @return true if the Node is a bridge and it is the integration bridge
+     */
+    public boolean isIntegrationBridge(Node node) {
+        if (!isBridgeNode(node)) {
+            return false;
+        }
+
+        String bridgeName = southboundUtils.extractBridgeName(node);
+        if (bridgeName == null) {
+            return false;
+        }
+
+        return bridgeName.equals(INTEGRATION_BRIDGE);
+    }
+
+    /**
+     * Is this node a bridge?
+     * @param node unidentified node object
+     * @return true if this node is a bridge
+     */
+    public boolean isBridgeNode(Node node) {
+        return southboundUtils.extractBridgeAugmentation(node) != null;
+    }
+
+    /**
+     * Advance the "preperation" of the OVSDB node. This re-entrant method advances the state of an OVSDB
+     * node towards the prepared state where all bridges and patch ports are created and active. This method
+     * should be invoked for the OVSDB node and the integration bridge node BUT IT IS SAFE TO INVOKE IT ON ANY NODE.
+     * @param node A node
+     * @param generateIntBridgeMac whether or not the int bridge's mac should be set to a random value
+     */
+    public void processNodePrep(Node node, boolean generateIntBridgeMac) {
+        if (isOvsdbNode(node)) {
+            ensureBridgesExist(node, generateIntBridgeMac);
+
+            //if br-int already exists, we can add provider networks
+            Node brIntNode = southboundUtils.readBridgeNode(node, INTEGRATION_BRIDGE);
+            if (brIntNode != null) {
+                if(!addControllerToBridge(node, brIntNode, INTEGRATION_BRIDGE)) {
+                    LOG.error("Failed to set controller to existing integration bridge {}", brIntNode);
+                }
+
+                prepareIntegrationBridge(node, brIntNode);
+            }
+            return;
+        }
+
+        Node ovsdbNode = southboundUtils.readOvsdbNode(node);
+        if (ovsdbNode == null) {
+            LOG.error("Node is neither bridge nor ovsdb {}", node);
+            return;
+        }
+
+        if (isIntegrationBridge(node)) {
+            prepareIntegrationBridge(ovsdbNode, node);
+        }
+
+    }
+
+    private void prepareIntegrationBridge(Node ovsdbNode, Node brIntNode) {
+        Optional<Map<String, String>> providerMappings = getOpenvswitchOtherConfigMap(ovsdbNode, PROVIDER_MAPPINGS_KEY);
+
+        for (String value : providerMappings.or(Collections.emptyMap()).values()) {
+            if (southboundUtils.extractTerminationPointAugmentation(brIntNode, value) != null) {
+                LOG.debug("prepareIntegrationBridge: port {} already exists on {}", value, INTEGRATION_BRIDGE);
+                continue;
+            }
+
+            Node exBridgeNode = southboundUtils.readBridgeNode(ovsdbNode, value);
+            if (exBridgeNode != null) {
+                LOG.debug("prepareIntegrationBridge: bridge {} found. Patching to {}", value, INTEGRATION_BRIDGE);
+                patchBridgeToBrInt(brIntNode, exBridgeNode, value);
+            } else {
+                LOG.debug("prepareIntegrationBridge: adding interface {} to {}", value, INTEGRATION_BRIDGE);
+                if (!addPortToBridge(brIntNode, INTEGRATION_BRIDGE, value)) {
+                    LOG.error("Failed to add {} port to {}", value, brIntNode);
+                }
+            }
+
+        }
+
+    }
+
+    private void patchBridgeToBrInt(Node intBridgeNode, Node exBridgeNode, String physnetBridgeName) {
+
+        String portNameInt = getIntSidePatchPortName(physnetBridgeName);
+        String portNameExt = getExSidePatchPortName(physnetBridgeName);
+        if (!addPatchPort(intBridgeNode, INTEGRATION_BRIDGE, portNameInt, portNameExt)) {
+            LOG.error("Failed to add patch port {} to {}", portNameInt, intBridgeNode);
+            return;
+        }
+
+        if (!addPatchPort(exBridgeNode, physnetBridgeName, portNameExt, portNameInt)) {
+            LOG.error("Failed to add patch port {} to {}", portNameExt, exBridgeNode);
+            return;
+        }
+    }
+
+    private void ensureBridgesExist(Node ovsdbNode, boolean generateIntBridgeMac) {
+
+        try {
+            createIntegrationBridge(ovsdbNode, generateIntBridgeMac);
+            //TODO: Get rid of this:
+            createExternalBridge(ovsdbNode);
+        } catch (Exception e) {
+            LOG.error("Error creating bridge on " + ovsdbNode, e);
+        }
+    }
+
+    private boolean createIntegrationBridge(Node ovsdbNode, boolean generateIntBridgeMac) {
+        LOG.debug("ElanBridgeManager.createIntegrationBridge, skipping if exists");
+        if (!addBridge(ovsdbNode, INTEGRATION_BRIDGE,
+                generateIntBridgeMac ? generateRandomMac() : null)) {
+            LOG.warn("Integration Bridge Creation failed");
+            return false;
+        }
+        return true;
+    }
+
+    private boolean createExternalBridge(Node ovsdbNode) {
+        LOG.debug("ElanBridgeManager.createExternalBridge, skipping if exists");
+        if (!addBridge(ovsdbNode, EXTERNAL_BRIDGE, null)) {
+            LOG.warn("External Bridge Creation failed");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Add a bridge to the OVSDB node but check that it does not exist in the CONFIGURATION or OPERATIONAL md-sals first
+     * @param ovsdbNode Which OVSDB node
+     * @param bridgeName Name of the bridge
+     * @param mac mac address to set on the bridge or null
+     * @return true if no errors occurred
+     */
+    public boolean addBridge(Node ovsdbNode, String bridgeName, String mac) {
+        boolean rv = true;
+        if ((!southboundUtils.isBridgeOnOvsdbNode(ovsdbNode, bridgeName)) ||
+                (southboundUtils.getBridgeFromConfig(ovsdbNode, bridgeName) == null)) {
+            Class<? extends DatapathTypeBase> dpType = null;
+            if (isUserSpaceEnabled()) {
+                dpType = DatapathTypeNetdev.class;
+            }
+            rv = southboundUtils.addBridge(ovsdbNode, bridgeName, southboundUtils.getControllersFromOvsdbNode(ovsdbNode), dpType, mac);
+        }
+        return rv;
+    }
+
+    private boolean addControllerToBridge(Node ovsdbNode, Node bridgeNode, String bridgeName) {
+        return southboundUtils.setBridgeController(ovsdbNode, bridgeNode,
+                            bridgeName, southboundUtils.getControllersFromOvsdbNode(ovsdbNode));
+    }
+
+    /**
+     * Extract OpenvSwitch other-config to key value map.
+     * @param node OVSDB node
+     * @param key key to extract from other-config
+     * @return Optional of key-value Map
+     */
+    public Optional<Map<String, String>> getOpenvswitchOtherConfigMap(Node node, String key) {
+        String providerMappings = southboundUtils.getOpenvswitchOtherConfig(node, key);
+        return extractMultiKeyValueToMap(providerMappings);
+    }
+
+    /**
+     * Get the OVS node physical interface name from provider mappings.
+     * @param node OVSDB node
+     * @param physicalNetworkName name of physical network
+     */
+    public String getProviderMappingValue(Node node, String physicalNetworkName) {
+        Optional<Map<String, String>> providerMappings = getOpenvswitchOtherConfigMap(node, PROVIDER_MAPPINGS_KEY);
+        if (!providerMappings.isPresent()) {
+            LOG.trace("Physical network {} not found in {}", physicalNetworkName, PROVIDER_MAPPINGS_KEY);
+            return null;
+        }
+
+        return providerMappings.get().get(physicalNetworkName);
+    }
+
+    /**
+     * Get the name of the port in br-int for the given provider-mapping value. This is either a patch port to a bridge
+     * with providerMappingValue - patch-&lt;providerMappingValue&gt; or simply a port with the same name as
+     * providerMappingValue
+     * @param ovsdbNode ovsdbNode
+     * @param providerMappingValue this is the last part of provider_mappings=net_name:THIS
+     * @return the name of the port on br-int
+     */
+    public String getIntBridgePortNameFor(Node ovsdbNode, String providerMappingValue) {
+        String res = providerMappingValue;
+        if (southboundUtils.isBridgeOnOvsdbNode(ovsdbNode, providerMappingValue)) {
+            res = getIntSidePatchPortName(providerMappingValue);
+        }
+
+        return res;
+    }
+    /**
+     * Get the name of the patch-port which is patched to the bridge containing interfaceName
+     * @param interfaceName The external interface
+     * @return
+     */
+    public static String getIntSidePatchPortName(String interfaceName) {
+        return interfaceName + INT_SIDE_PATCH_PORT_SUFFIX;
+    }
+
+    private String getExSidePatchPortName(String physicalInterfaceName) {
+        return physicalInterfaceName + EX_SIDE_PATCH_PORT_SUFFIX;
+    }
+
+    /**
+     * Add a port to a bridge
+     * @param node the bridge node
+     * @param bridgeName name of the bridge
+     * @param portName name of port to add
+     * @return true if successful in writing to mdsal
+     */
+    public boolean addPortToBridge (Node node, String bridgeName, String portName) {
+        boolean rv = true;
+
+        if (southboundUtils.extractTerminationPointAugmentation(node, portName) == null) {
+            rv = southboundUtils.addTerminationPoint(node, bridgeName, portName, null);
+
+            if (rv) {
+                LOG.debug("addPortToBridge: node: {}, bridge: {}, portname: {} status: success",
+                        node.getNodeId().getValue(), bridgeName, portName);
+            } else {
+                LOG.error("addPortToBridge: node: {}, bridge: {}, portname: {} status: FAILED",
+                        node.getNodeId().getValue(), bridgeName, portName);
+            }
+        } else {
+            LOG.trace("addPortToBridge: node: {}, bridge: {}, portname: {} status: not_needed",
+                    node.getNodeId().getValue(), bridgeName, portName);
+        }
+
+        return rv;
+    }
+
+    /**
+     * Add a patch port to a bridge
+     * @param node the bridge node
+     * @param bridgeName name of the bridge
+     * @param portName name of the port
+     * @param peerPortName name of the port's peer (the other side)
+     * @return true if successful
+     */
+    public boolean addPatchPort (Node node, String bridgeName, String portName, String peerPortName) {
+        boolean rv = true;
+
+        if (southboundUtils.extractTerminationPointAugmentation(node, portName) == null) {
+            rv = southboundUtils.addPatchTerminationPoint(node, bridgeName, portName, peerPortName);
+
+            if (rv) {
+                LOG.info("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: success",
+                        node.getNodeId().getValue(), bridgeName, portName, peerPortName);
+            } else {
+                LOG.error("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: FAILED",
+                        node.getNodeId().getValue(), bridgeName, portName, peerPortName);
+            }
+        } else {
+            LOG.trace("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: not_needed",
+                    node.getNodeId().getValue(), bridgeName, portName, peerPortName);
+        }
+
+        return rv;
+    }
+
+    private String generateRandomMac() {
+        byte[] macBytes = new byte[6];
+        random.nextBytes(macBytes);
+        macBytes[0] &= 0xfc; //the two low bits of the first byte need to be zero
+
+        StringBuilder stringBuilder = new StringBuilder();
+
+        int i = 0;
+        while(true) {
+            stringBuilder.append(String.format("%02x", macBytes[i++]));
+            if (i >= 6) {
+                break;
+            }
+            stringBuilder.append(':');
+        }
+
+        return stringBuilder.toString();
+    }
+
+    private static Optional<Map<String, String>> extractMultiKeyValueToMap(String multiKeyValueStr) {
+        if (Strings.isNullOrEmpty(multiKeyValueStr)) {
+            return Optional.absent();
+        }
+
+        Map<String, String> valueMap = new HashMap<>();
+        Splitter splitter = Splitter.on(",");
+        for (String keyValue : splitter.split(multiKeyValueStr)) {
+            String[] split = keyValue.split(":", 2);
+            if (split != null && split.length == 2) {
+                valueMap.put(split[0], split[1]);
+            }
+        }
+
+        return Optional.of(valueMap);
+    }
+}
index 5813dbe49c9c156a9a932ff77c39e36fde707c34..bbecd083cd4fa2efb4c53d4af433feaf7a9c9b4b 100644 (file)
@@ -11,8 +11,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.netvirt.elan.utils.BridgeUtils;
-import org.opendaylight.netvirt.elan.utils.ElanConstants;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
@@ -32,7 +31,8 @@ public class ElanOvsdbNodeListener extends AbstractDataChangeListener<Node> {
     private static final Logger logger = LoggerFactory.getLogger(ElanOvsdbNodeListener.class);
 
     private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private BridgeUtils bridgeUtils;
+    private ElanBridgeManager bridgeMgr;
+    private IElanService elanProvider;
     private boolean generateIntBridgeMac;
 
     /**
@@ -40,9 +40,10 @@ public class ElanOvsdbNodeListener extends AbstractDataChangeListener<Node> {
      * @param db the DataBroker
      * @param generateIntBridgeMac true if the integration bridge should be given a fixed, random MAC address
      */
-    public ElanOvsdbNodeListener(final DataBroker db, boolean generateIntBridgeMac) {
+    public ElanOvsdbNodeListener(final DataBroker db, boolean generateIntBridgeMac, ElanBridgeManager bridgeMgr, IElanService elanProvider) {
         super(Node.class);
-        this.bridgeUtils = new BridgeUtils(db);
+        this.bridgeMgr = bridgeMgr;
+        this.elanProvider = elanProvider;
         this.generateIntBridgeMac = generateIntBridgeMac;
         registerListener(db);
     }
@@ -70,12 +71,18 @@ public class ElanOvsdbNodeListener extends AbstractDataChangeListener<Node> {
 
     @Override
     protected void update(InstanceIdentifier<Node> identifier, Node original, Node update) {
+        logger.debug("ElanOvsdbNodeListener.update, updated node detected. original: {} new: {}", original, update);
+        doNodeUpdate(update);
     }
 
     @Override
-    protected void add(InstanceIdentifier<Node> identifier, Node add) {
-        logger.debug("ElanOvsdbNodeListener.add, new bridge detected{}", add);
-        bridgeUtils.prepareNode(add, generateIntBridgeMac);
+    protected void add(InstanceIdentifier<Node> identifier, Node node) {
+        logger.debug("ElanOvsdbNodeListener.add, new node detected {}", node);
+        doNodeUpdate(node);
+    }
+
+    private void doNodeUpdate(Node node) {
+        bridgeMgr.processNodePrep(node, generateIntBridgeMac);
     }
 
 }
index 4b23d07321c14945ae40e6d002a4992e4b03ffb4..8861fa6744821659459ff6c3531b0db24d0dedb0 100644 (file)
@@ -67,6 +67,8 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
     private OdlInterfaceRpcService interfaceManagerRpcService;
     private ElanInstanceManager elanInstanceManager;
     private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
+    private ElanBridgeManager bridgeMgr;
+
     public IdManagerService getIdManager() {
         return idManager;
     }
@@ -178,7 +180,8 @@ public class ElanServiceProvider implements BindingAwareProvider, IElanService,
             getDataStoreJobCoordinator();
             broker = session.getSALService(DataBroker.class);
 
-            elanOvsdbNodeListener = new ElanOvsdbNodeListener(broker, generateIntBridgeMac);
+            bridgeMgr = new ElanBridgeManager(broker);
+            elanOvsdbNodeListener = new ElanOvsdbNodeListener(broker, generateIntBridgeMac, bridgeMgr, this);
             ElanUtils.setElanServiceProvider(this);
             elanForwardingEntriesHandler = ElanForwardingEntriesHandler.getElanForwardingEntriesHandler(this);
             elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager(this);
diff --git a/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/BridgeUtils.java b/vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/BridgeUtils.java
deleted file mode 100644 (file)
index 186a43b..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2016 Red Hat, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netvirt.elan.utils;
-
-import com.google.common.collect.ImmutableBiMap;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.ovsdb.utils.config.ConfigProperties;
-import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
-import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeNetdev;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeSecure;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeStandalone;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-import java.security.InvalidParameterException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class provides functions for creating bridges via OVSDB, specifically the br-int bridge.
- * Note and TODO: br-ex is temporary. vpnservice does not require it but for the time being it is
- * left here because devstack expects it.
- */
-public class BridgeUtils {
-    private static final Logger LOG = LoggerFactory.getLogger(BridgeUtils.class);
-
-    private static final ImmutableBiMap<Class<? extends OvsdbFailModeBase>,String> OVSDB_FAIL_MODE_MAP
-            = new ImmutableBiMap.Builder<Class<? extends OvsdbFailModeBase>,String>()
-            .put(OvsdbFailModeStandalone.class,"standalone")
-            .put(OvsdbFailModeSecure.class,"secure")
-            .build();
-
-    private static final String DISABLE_IN_BAND = "disable-in-band";
-    private static final String INTEGRATION_BRIDGE = "br-int";
-    private static final String EXTERNAL_BRIDGE = "br-ex";
-
-    private final MdsalUtils mdsalUtils;
-    private final SouthboundUtils southboundUtils;
-    private Random random;
-
-
-    /**
-     * Construct a new BridgeUtils
-     * @param dataBroker
-     */
-    public BridgeUtils(DataBroker dataBroker) {
-        //TODO: ClusterAware!!!??
-        this.mdsalUtils = new MdsalUtils(dataBroker);
-        this.southboundUtils = new SouthboundUtils(mdsalUtils);
-        this.random = new Random(System.currentTimeMillis());
-    }
-
-    /**
-     * Is OVS running in userspace mode?
-     * @return true if the ovsdb.userspace.enabled variable is set to true
-     */
-    public boolean isUserSpaceEnabled() {
-        final String enabledPropertyStr = ConfigProperties.getProperty(this.getClass(), "ovsdb.userspace.enabled");
-        return enabledPropertyStr != null && enabledPropertyStr.equalsIgnoreCase("yes");
-    }
-
-    /**
-     * Is vpnservice handling L3 as well? This function is deprocated because br-ex is temporary as mentioned above
-     * @return true if the ovsdb.l3.fwd.enable is set to true
-     */
-    @Deprecated
-    public boolean isL3ForwardingEnabled() {
-        final String enabledPropertyStr = ConfigProperties.getProperty(this.getClass(), "ovsdb.l3.fwd.enabled");
-        return enabledPropertyStr != null && enabledPropertyStr.equalsIgnoreCase("yes");
-    }
-
-    /**
-     * Prepare the OVSDB node for netvirt, create br-int
-     * @param ovsdbNode The OVSDB node
-     * @param generateIntBridgeMac should BrigeUtil set br-int's mac address to a random address. If this vlaue is false, the dpid may change as ports are added to the bridge
-     */
-    public void prepareNode(Node ovsdbNode, boolean generateIntBridgeMac) {
-        try {
-            createIntegrationBridge(ovsdbNode, generateIntBridgeMac);
-        } catch (Exception e) {
-            LOG.error("Error creating Integration Bridge on {}", ovsdbNode, e);
-            return;
-        }
-
-        try {
-            if (isL3ForwardingEnabled()) {
-                createExternalBridge(ovsdbNode);
-            }
-        } catch (Exception e) {
-            LOG.error("Error creating External Bridge on {}", ovsdbNode, e);
-            return;
-        }
-        // this node is an ovsdb node so it doesn't have a bridge
-        // so either look up the bridges or just wait for the bridge update to come in
-        // and add the flows there.
-        //networkingProviderManager.getProvider(node).initializeFlowRules(node);
-    }
-
-    private boolean createIntegrationBridge(Node ovsdbNode, boolean generateIntBridgeMac) {
-        LOG.debug("BridgeUtils.createIntegrationBridge, skipping if exists");
-        if (!addBridge(ovsdbNode, INTEGRATION_BRIDGE,
-                generateIntBridgeMac ? generateRandomMac() : null)) {
-            LOG.warn("Integration Bridge Creation failed");
-            return false;
-        }
-        return true;
-    }
-
-    private boolean createExternalBridge(Node ovsdbNode) {
-        LOG.debug("BridgeUtils.createExternalBridge, skipping if exists");
-        if (!addBridge(ovsdbNode, EXTERNAL_BRIDGE, null)) {
-            LOG.warn("External Bridge Creation failed");
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Add a bridge to the OVSDB node but check that it does not exist in the CONFIGURATION or OPERATIONAL md-sals first
-     * @param ovsdbNode Which OVSDB node
-     * @param bridgeName Name of the bridge
-     * @param mac mac address to set on the bridge or null
-     * @return true if no errors occurred
-     */
-    public boolean addBridge(Node ovsdbNode, String bridgeName, String mac) {
-        boolean rv = true;
-        if ((!isBridgeOnOvsdbNode(ovsdbNode, bridgeName)) ||
-                (getBridgeFromConfig(ovsdbNode, bridgeName) == null)) {
-            Class<? extends DatapathTypeBase> dpType = null;
-            if (isUserSpaceEnabled()) {
-                dpType = DatapathTypeNetdev.class;
-            }
-            rv = addBridge(ovsdbNode, bridgeName, southboundUtils.getControllersFromOvsdbNode(ovsdbNode), dpType, mac);
-        }
-        return rv;
-    }
-
-    /**
-     * Add a bridge to the OVSDB node
-     * @param ovsdbNode Which OVSDB node
-     * @param bridgeName Name of the bridge
-     * @param controllersStr OVSDB's controller
-     * @param dpType datapath type
-     * @param mac mac address to set on the bridge or null
-     * @return true if the write to md-sal was successful
-     */
-    public boolean addBridge(Node ovsdbNode, String bridgeName, List<String> controllersStr,
-                             final Class<? extends DatapathTypeBase> dpType, String mac) {
-        boolean result = false;
-
-        LOG.debug("addBridge: node: {}, bridgeName: {}, controller(s): {}", ovsdbNode, bridgeName, controllersStr);
-        ConnectionInfo connectionInfo = southboundUtils.getConnectionInfo(ovsdbNode);
-        if (connectionInfo == null) {
-            throw new InvalidParameterException("Could not find ConnectionInfo");
-        }
-
-        NodeBuilder bridgeNodeBuilder = new NodeBuilder();
-        InstanceIdentifier<Node> bridgeIid = southboundUtils.createInstanceIdentifier(ovsdbNode.getKey(), bridgeName);
-        NodeId bridgeNodeId = southboundUtils.createManagedNodeId(bridgeIid);
-        bridgeNodeBuilder.setNodeId(bridgeNodeId);
-
-        OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
-        ovsdbBridgeAugmentationBuilder.setControllerEntry(createControllerEntries(controllersStr));
-        ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
-        ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
-        ovsdbBridgeAugmentationBuilder.setFailMode( OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
-
-        BridgeOtherConfigsBuilder bridgeOtherConfigsBuilder = new BridgeOtherConfigsBuilder();
-        bridgeOtherConfigsBuilder.setBridgeOtherConfigKey(DISABLE_IN_BAND);
-        bridgeOtherConfigsBuilder.setBridgeOtherConfigValue("true");
-
-        List<BridgeOtherConfigs> bridgeOtherConfigsList = new ArrayList<>();
-        bridgeOtherConfigsList.add(bridgeOtherConfigsBuilder.build());
-        if (mac != null) {
-            BridgeOtherConfigsBuilder macOtherConfigBuilder = new BridgeOtherConfigsBuilder();
-            macOtherConfigBuilder.setBridgeOtherConfigKey("hwaddr");
-            macOtherConfigBuilder.setBridgeOtherConfigValue(mac);
-            bridgeOtherConfigsList.add(macOtherConfigBuilder.build());
-        }
-
-        ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(bridgeOtherConfigsList);
-        setManagedByForBridge(ovsdbBridgeAugmentationBuilder, ovsdbNode.getKey());
-        if (dpType != null) {
-            ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
-        }
-
-        if (isOvsdbNodeDpdk(ovsdbNode)) {
-            ovsdbBridgeAugmentationBuilder.setDatapathType(DatapathTypeNetdev.class);
-        }
-
-        bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
-
-        Node node = bridgeNodeBuilder.build();
-        result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, bridgeIid, node);
-        LOG.debug("addBridge: result: {}", result);
-
-        return result;
-    }
-
-    private List<ControllerEntry> createControllerEntries(List<String> controllersStr) {
-        List<ControllerEntry> controllerEntries = new ArrayList<>();
-        if (controllersStr != null) {
-            for (String controllerStr : controllersStr) {
-                ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
-                controllerEntryBuilder.setTarget(new Uri(controllerStr));
-                controllerEntries.add(controllerEntryBuilder.build());
-            }
-        }
-        return controllerEntries;
-    }
-
-    private List<ProtocolEntry> createMdsalProtocols() {
-        List<ProtocolEntry> protocolList = new ArrayList<>();
-        ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
-                southboundUtils.OVSDB_PROTOCOL_MAP.inverse();
-        protocolList.add(new ProtocolEntryBuilder().
-                setProtocol(mapper.get("OpenFlow13")).build());
-        return protocolList;
-    }
-
-    private void setManagedByForBridge(OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
-                                       NodeKey ovsdbNodeKey) {
-        InstanceIdentifier<Node> connectionNodePath = southboundUtils.createInstanceIdentifier(ovsdbNodeKey.getNodeId());
-        ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
-    }
-
-    private boolean isOvsdbNodeDpdk(Node ovsdbNode) {
-        boolean found = false;
-        OvsdbNodeAugmentation ovsdbNodeAugmentation = southboundUtils.extractNodeAugmentation(ovsdbNode);
-        if (ovsdbNodeAugmentation != null) {
-            List<InterfaceTypeEntry> ifTypes = ovsdbNodeAugmentation.getInterfaceTypeEntry();
-            if (ifTypes != null) {
-                for (InterfaceTypeEntry ifType : ifTypes) {
-                    if (ifType.getInterfaceType().equals(InterfaceTypeDpdk.class)) {
-                        found = true;
-                        break;
-                    }
-                }
-            }
-        }
-        return found;
-    }
-
-    private boolean isBridgeOnOvsdbNode(Node ovsdbNode, String bridgeName) {
-        boolean found = false;
-        //TODO: MAKE SURE extract function is right
-        OvsdbNodeAugmentation ovsdbNodeAugmentation = southboundUtils.extractNodeAugmentation(ovsdbNode);
-        if (ovsdbNodeAugmentation != null) {
-            List<ManagedNodeEntry> managedNodes = ovsdbNodeAugmentation.getManagedNodeEntry();
-            if (managedNodes != null) {
-                for (ManagedNodeEntry managedNode : managedNodes) {
-                    InstanceIdentifier<?> bridgeIid = managedNode.getBridgeRef().getValue();
-                    if (bridgeIid.toString().contains(bridgeName)) {
-                        found = true;
-                        break;
-                    }
-                }
-            }
-        }
-        return found;
-    }
-
-    private OvsdbBridgeAugmentation getBridgeFromConfig(Node node, String bridge) {
-        OvsdbBridgeAugmentation ovsdbBridgeAugmentation = null;
-        InstanceIdentifier<Node> bridgeIid =
-                southboundUtils.createInstanceIdentifier(node.getKey(), bridge);
-        Node bridgeNode = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, bridgeIid);
-        if (bridgeNode != null) {
-            ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
-        }
-        return ovsdbBridgeAugmentation;
-    }
-
-    private String generateRandomMac() {
-        byte[] macBytes = new byte[6];
-        random.nextBytes(macBytes);
-        macBytes[0] &= 0xfc; //the two low bits of the first byte need to be zero
-
-        StringBuilder stringBuilder = new StringBuilder();
-
-        int i = 0;
-        while(true) {
-            stringBuilder.append(String.format("%02x", macBytes[i++]));
-            if (i >= 6) {
-                break;
-            }
-            stringBuilder.append(':');
-        }
-
-        return stringBuilder.toString();
-    }
-}