X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=inline;f=neutron-ovsdb%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fgroupbasedpolicy%2Fneutron%2Fovsdb%2FOvsdbNodeListener.java;h=09f8c2a23dc2a048170589747fddaaa6a9e33bd7;hb=02dd576a2ff7d7a8c304bd74a239c150be1ddd2b;hp=acf3603d7a378edcdc16ba9478a54ae315e5930f;hpb=89c185576bca121babefe6f3fef7d12f782ed8e2;p=groupbasedpolicy.git diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/OvsdbNodeListener.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/OvsdbNodeListener.java index acf3603d7..09f8c2a23 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/OvsdbNodeListener.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/OvsdbNodeListener.java @@ -7,9 +7,19 @@ */ package org.opendaylight.groupbasedpolicy.neutron.ovsdb; +import com.google.common.base.Function; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.MoreExecutors; + import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import javax.annotation.Nonnull; @@ -17,47 +27,63 @@ import javax.annotation.Nonnull; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper; +import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronOvsdbIidFactory; import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler; import org.opendaylight.ovsdb.southbound.SouthboundConstants; +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.groupbasedpolicy.neutron.ovsdb.params.rev160812.IntegrationBridgeSetting; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeSystem; 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.OvsdbBridgeProtocolOpenflow13; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef; 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.OvsdbTerminationPointAugmentation; +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.ProtocolEntryBuilder; 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.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigsKey; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; 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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Strings; - public class OvsdbNodeListener extends DataTreeChangeHandler { + static final String BRIDGE_SEPARATOR = "/bridge/"; + static final String NEUTRON_PROVIDER_MAPPINGS_KEY = "provider_mappings"; private static final Logger LOG = LoggerFactory.getLogger(OvsdbNodeListener.class); - public static final String NEUTRON_PROVIDER_MAPPINGS_KEY = "provider_mappings"; private static final String OF_SEPARATOR = ":"; private static final String OF_INVENTORY_PREFIX = "openflow"; + private static IntegrationBridgeSetting intBrSettings; private final Map providerPortNameByBridgeRef = new HashMap<>(); private final Map, NeutronBridgeWithExtPort> bridgeByNodeIid = new HashMap<>(); - public OvsdbNodeListener(DataBroker dataProvider) { - super(dataProvider, - new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, - InstanceIdentifier.create(NetworkTopology.class) - .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) - .child(Node.class))); + public OvsdbNodeListener(DataBroker dataProvider, IntegrationBridgeSetting brSettings) { + super(dataProvider); + intBrSettings = brSettings; + this.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, + InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) + .child(Node.class))); } @Override @@ -66,19 +92,46 @@ public class OvsdbNodeListener extends DataTreeChangeHandler { OvsdbNodeAugmentation ovsdbNode = node.getAugmentation(OvsdbNodeAugmentation.class); if (ovsdbNode != null) { LOG.trace("OVSDB node created: {} \n {}", rootIdentifier, node); - DataObjectModification ovsOtherConfigModification = - getProviderMappingsModification(rootNode); + DataObjectModification + ovsOtherConfigModification = getProviderMappingsModification(rootNode); + boolean integrationBridgePresent = false; if (isProviderPortNameChanged(ovsOtherConfigModification) && ovsdbNode.getManagedNodeEntry() != null) { String newProviderPortName = getProviderPortName(ovsOtherConfigModification.getDataAfter()); LOG.debug("provider_mappings created {} on node {}", newProviderPortName, node.getNodeId().getValue()); for (ManagedNodeEntry mngdNodeEntry : ovsdbNode.getManagedNodeEntry()) { - providerPortNameByBridgeRef.put(mngdNodeEntry.getBridgeRef(), newProviderPortName); + OvsdbBridgeRef bridgeRef = mngdNodeEntry.getBridgeRef(); + providerPortNameByBridgeRef.put(bridgeRef, newProviderPortName); LOG.trace("Added Provider port name {} by OVSDB bridge ref {}", newProviderPortName, mngdNodeEntry.getBridgeRef()); + NodeKey managedNodeKey = bridgeRef.getValue().firstKeyOf(Node.class); + if (intBrSettings != null && managedNodeKey.getNodeId().getValue() + .equals(intBrSettings.getName())) { + integrationBridgePresent = true; + } } } - } + if (intBrSettings != null && !integrationBridgePresent) { + final Node bridge = createBridge(rootIdentifier, + managerToControllerEntries(ovsdbNode.getManagerEntry()), intBrSettings.getName()); + InstanceIdentifier bridgeNodeIid = NeutronOvsdbIidFactory.nodeIid( + rootIdentifier.firstKeyOf(Topology.class).getTopologyId(), bridge.getNodeId()); + WriteTransaction writeTx = dataProvider.newWriteOnlyTransaction(); + writeTx.merge(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid, bridge, true); + Futures.addCallback(writeTx.submit(), new FutureCallback() { + @Override + public void onSuccess(Void result) { + LOG.info("Bridge {} written to datastore." + bridge.getNodeId().getValue()); + } + + @Override + public void onFailure(Throwable throwable) { + LOG.error("Failed to write bridge {}. Message: {}" + bridge.getNodeId().getValue(), + throwable.getMessage()); + } + }, MoreExecutors.directExecutor()); + } + } OvsdbBridgeAugmentation ovsdbBridge = node.getAugmentation(OvsdbBridgeAugmentation.class); if (ovsdbBridge != null) { LOG.trace("OVSDB bridge created: {} \n {}", rootIdentifier, node); @@ -143,6 +196,12 @@ public class OvsdbNodeListener extends DataTreeChangeHandler { } for (DataObjectModification ovsdbTpModification : ovsdbTpModifications) { OvsdbTerminationPointAugmentation newOvsdbTp = ovsdbTpModification.getDataAfter(); + + if (newOvsdbTp == null) { + LOG.trace("Termination Point is null. Not processing"); + continue; + } + if (ovsdbBridge.getBridgeName().getValue().equals(newOvsdbTp.getName())) { LOG.trace("Termination Point {} same as Bridge {}. Not processing", newOvsdbTp.getName(), ovsdbBridge.getBridgeName().getValue()); @@ -203,7 +262,8 @@ public class OvsdbNodeListener extends DataTreeChangeHandler { OvsdbTerminationPointAugmentation oldTp = ovsdbTpModification.getDataBefore(); OvsdbTerminationPointAugmentation newTp = ovsdbTpModification.getDataAfter(); if (oldTp != null && newTp != null) { - if (oldTp.getOfport() != null && newTp.getOfport() != null && oldTp.getOfport() != newTp.getOfport()) { + if (oldTp.getOfport() != null && newTp.getOfport() != null && !Objects.equals(oldTp.getOfport(), + newTp.getOfport())) { return true; } if (!(Strings.nullToEmpty(oldTp.getName())).equals(Strings.nullToEmpty(newTp.getName()))) { @@ -272,6 +332,59 @@ public class OvsdbNodeListener extends DataTreeChangeHandler { return ""; } + /** + * Extracts IP address from URI. + * + * @param uri in format protocol:ip:port + * @return IPv4 or IPv6 address as {@link String}. + */ + private static @Nonnull String getIpAddrFromUri(Uri uri) { + String otherConfig = uri.getValue(); + String[] elements = otherConfig.split(":"); + // IPv6 expression also contains colons + if (elements.length < 3) { + return ""; + } + StringBuilder sb = new StringBuilder(); + // first (protocol) and last (port) elements are filtered + for (int i = 1; i < elements.length - 1; i++) { + sb.append(elements[i]); + } + return sb.toString(); + } + + private List managerToControllerEntries(List managerEntries) { + return Lists.transform(managerEntries, new Function() { + + @Override + public ControllerEntry apply(ManagerEntry managerEntry) { + String ipAddr = getIpAddrFromUri(managerEntry.getTarget()); + Uri uri = new Uri(intBrSettings.getOpenflowProtocol() + OF_SEPARATOR + ipAddr + OF_SEPARATOR + + intBrSettings.getOpenflowPort()); + return new ControllerEntryBuilder().setTarget(new Uri(uri)).build(); + } + }); + } + + private Node createBridge(InstanceIdentifier managedByIid, List controllerEntries, + String bridgeName) { + OvsdbBridgeAugmentation br = new OvsdbBridgeAugmentationBuilder() + .setBridgeName(new OvsdbBridgeName(bridgeName)) + .setManagedBy(new OvsdbNodeRef(managedByIid)) + .setControllerEntry(controllerEntries) + .setDatapathType(DatapathTypeSystem.class) + .setProtocolEntry( + ImmutableList.of(new ProtocolEntryBuilder().setProtocol( + OvsdbBridgeProtocolOpenflow13.class).build())) + .build(); + NodeKey managerNodeKey = managedByIid.firstKeyOf(Node.class); + return new NodeBuilder().setNodeId( + new org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId( + managerNodeKey.getNodeId().getValue() + BRIDGE_SEPARATOR + bridgeName)) + .addAugmentation(OvsdbBridgeAugmentation.class, br) + .build(); + } + private static NodeId buildOfNodeId(OvsdbBridgeAugmentation ovsdbBridge) { if (ovsdbBridge.getDatapathId() == null) { return null;