From: Tomas Cechvala Date: Sat, 12 Mar 2016 12:44:24 +0000 (+0100) Subject: Bug 5510 - making sure that br-int is created X-Git-Tag: release/boron~226^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=82956ef22f3278b9b635ec90b6f5f10439a2a771;p=groupbasedpolicy.git Bug 5510 - making sure that br-int is created When a node with OvsdbNodeAugmentation does not have reference to br-int node with OvsdbBridge augmentation, the missing bridge node is created by writing it into DS. Change-Id: Ie0054d311916ece0030ad63647ebe3ca3f06d797 Signed-off-by: Tomas Cechvala --- diff --git a/neutron-ovsdb/src/main/config/default-config.xml b/neutron-ovsdb/src/main/config/default-config.xml index 99272eda1..3953ededc 100644 --- a/neutron-ovsdb/src/main/config/default-config.xml +++ b/neutron-ovsdb/src/main/config/default-config.xml @@ -25,6 +25,14 @@ binding:binding-async-data-broker binding-data-broker + + + + br-int + tcp + 6653 + + diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/controller/config/yang/config/neutron_ovsdb/impl/NeutronOvsdbModule.java b/neutron-ovsdb/src/main/java/org/opendaylight/controller/config/yang/config/neutron_ovsdb/impl/NeutronOvsdbModule.java index d29e04f71..d8137644b 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/controller/config/yang/config/neutron_ovsdb/impl/NeutronOvsdbModule.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/controller/config/yang/config/neutron_ovsdb/impl/NeutronOvsdbModule.java @@ -33,7 +33,8 @@ public class NeutronOvsdbModule extends org.opendaylight.controller.config.yang. @Override public java.lang.AutoCloseable createInstance() { - final NeutronOvsdb neutronOvsdb = new NeutronOvsdb(getDataBrokerDependency(), getRpcRegistryDependency()); + final NeutronOvsdb neutronOvsdb = new NeutronOvsdb(getDataBrokerDependency(), getRpcRegistryDependency(), + getIntegrationBridgeSetting()); LOG.info("Neutron ovsdb started."); return neutronOvsdb; } diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/NeutronOvsdb.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/NeutronOvsdb.java index 24d9c58e0..f5d389f8f 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/NeutronOvsdb.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/NeutronOvsdb.java @@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.neutron.ovsdb; import static com.google.common.base.Preconditions.checkNotNull; +import org.opendaylight.controller.config.yang.config.neutron_ovsdb.impl.IntegrationBridgeSetting; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService; @@ -21,13 +22,14 @@ public class NeutronOvsdb implements AutoCloseable { private final OvsdbNodeListener ovsdbNodeListener; private final ProviderPhysicalNetworkListener provPhysNetListener; - public NeutronOvsdb(DataBroker dataProvider, RpcProviderRegistry rpcProvider) { + public NeutronOvsdb(DataBroker dataProvider, RpcProviderRegistry rpcProvider, + IntegrationBridgeSetting integrationbridgeSettings) { checkNotNull(dataProvider); checkNotNull(rpcProvider); EndpointService epService = rpcProvider.getRpcService(EndpointService.class); tpListener = new TerminationPointDataChangeListener(dataProvider, epService); - ovsdbNodeListener = new OvsdbNodeListener(dataProvider); + ovsdbNodeListener = new OvsdbNodeListener(dataProvider, integrationbridgeSettings); portByEndpointListener = new PortByEndpointListener(dataProvider); provPhysNetListener = new ProviderPhysicalNetworkListener(dataProvider); } 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 0794b77d6..f8fc121da 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,40 +7,79 @@ */ package org.opendaylight.groupbasedpolicy.neutron.ovsdb; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.Nonnull; +import org.opendaylight.controller.config.yang.config.neutron_ovsdb.impl.IntegrationBridgeSetting; 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.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper; +import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronOvsdbIidFactory; +import org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper; +import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; 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.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet; 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.DatapathTypeBase; +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.OvsdbFailModeSecure; 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.ControllerEntryKey; +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.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.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.base.Strings; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; public class OvsdbNodeListener extends DataTreeChangeHandler { @@ -48,16 +87,19 @@ public class OvsdbNodeListener extends DataTreeChangeHandler { 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 final String BRIDGE_SEPARATOR = "/bridge/"; + private static IntegrationBridgeSetting intBrSettings; private final Map providerPortNameByBridgeRef = new HashMap<>(); private final Map, NeutronBridgeWithExtPort> bridgeByNodeIid = new HashMap<>(); - public OvsdbNodeListener(DataBroker dataProvider) { + public OvsdbNodeListener(DataBroker dataProvider, IntegrationBridgeSetting brSettings) { super(dataProvider, new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(NetworkTopology.class) .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) .child(Node.class))); + intBrSettings = brSettings; } @Override @@ -66,19 +108,44 @@ 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 == false) { + final Node bridge = createBridge(rootIdentifier, + managerToControllerEntries(ovsdbNode.getManagerEntry()), intBrSettings.getName()); + InstanceIdentifier bridgeNodeIid = NeutronOvsdbIidFactory.nodeIid( + rootIdentifier.firstKeyOf(Topology.class).getTopologyId(), bridge.getNodeId()); + WriteTransaction wTx = dataProvider.newWriteOnlyTransaction(); + wTx.merge(LogicalDatastoreType.CONFIGURATION, bridgeNodeIid, bridge, true); + Futures.addCallback(wTx.submit(), new FutureCallback() { + @Override + public void onSuccess(Void result) { + LOG.info("Bridge {} written to datastore." + bridge.getNodeId().getValue()); + } + + @Override + public void onFailure(Throwable t) { + LOG.error("Failed to write bridge {}. Message: {}" + bridge.getNodeId().getValue(), + t.getMessage()); + } + }); + } + } OvsdbBridgeAugmentation ovsdbBridge = node.getAugmentation(OvsdbBridgeAugmentation.class); if (ovsdbBridge != null) { LOG.trace("OVSDB bridge created: {} \n {}", rootIdentifier, node); @@ -278,6 +345,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; diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/NeutronOvsdbIidFactory.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/NeutronOvsdbIidFactory.java index 5fad3aa63..4133b61c3 100644 --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/NeutronOvsdbIidFactory.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/NeutronOvsdbIidFactory.java @@ -16,22 +16,26 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gb import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPortKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.ExternalGatewaysAsL3Endpoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.neutron.by.gbp.mappings.external.gateways.as.l3.endpoints.ExternalGatewayAsL3Endpoint; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation; 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.NodeId; import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; 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.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; public class NeutronOvsdbIidFactory { - public static InstanceIdentifier ovsdbNodeAugmentationIid(TopologyId ovsdbTopologyId) { + public static InstanceIdentifier topologyIid(TopologyId ovsdbTopologyId) { return InstanceIdentifier.create(NetworkTopology.class) - .child(Topology.class, new TopologyKey(ovsdbTopologyId)) + .child(Topology.class, new TopologyKey(ovsdbTopologyId)); + } + + public static InstanceIdentifier ovsdbNodeAugmentationIid(TopologyId ovsdbTopologyId) { + return topologyIid(ovsdbTopologyId) .child(Node.class) .augmentation(OvsdbNodeAugmentation.class); } @@ -56,11 +60,15 @@ public class NeutronOvsdbIidFactory { return InstanceIdentifier.builder(Mappings.class).child(NeutronByGbpMappings.class).build(); } + public static InstanceIdentifier nodeIid(TopologyId ovsdbTopologyId, NodeId nodeId) { + return topologyIid(ovsdbTopologyId).child(Node.class, new NodeKey(nodeId)); + } + public static InstanceIdentifier nodeIid( - NodeId nodeId) { + org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nodeId) { return InstanceIdentifier.builder(Nodes.class) .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, - new NodeKey(nodeId)) + new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(nodeId)) .build(); } } diff --git a/neutron-ovsdb/src/main/yang/neutron-ovsdb-impl.yang b/neutron-ovsdb/src/main/yang/neutron-ovsdb-impl.yang index dda939db0..5f3e3052c 100644 --- a/neutron-ovsdb/src/main/yang/neutron-ovsdb-impl.yang +++ b/neutron-ovsdb/src/main/yang/neutron-ovsdb-impl.yang @@ -47,6 +47,22 @@ module neutron-ovsdb-impl { } } + container integration-bridge-setting { + leaf name { + mandatory true; + type string; + } + leaf openflow-port { + mandatory true; + type uint16; + } + leaf openflow-protocol { + mandatory true; + type string { + pattern "^tcp$|^udp$"; + } + } + } } } }