X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=neutron-ovsdb%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fgroupbasedpolicy%2Fneutron%2Fovsdb%2FTerminationPointDataChangeListener.java;h=2cf2b78dfd96d2367b493c7c89e1109dc4e4e867;hb=e9b93945fe12111eb58baa076e4257a16a685037;hp=3753675f81cdb6dacd9dbaf0892be0823a08fb44;hpb=db0e754ce92ff3dde579aabb0817f40bc6e76f72;p=groupbasedpolicy.git diff --git a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java old mode 100644 new mode 100755 index 3753675f8..2cf2b78df --- a/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java +++ b/neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/TerminationPointDataChangeListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2015 Cisco Systems, 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, @@ -9,23 +9,41 @@ package org.opendaylight.groupbasedpolicy.neutron.ovsdb; import static com.google.common.base.Preconditions.checkNotNull; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.lookupEndpoint; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointRemoveLocation; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointWithLocation; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.checkOfOverlayConfig; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeConnectorIdString; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeIdString; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.removeTunnelsOfOverlayConfig; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.updateOfOverlayConfig; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronHelper.getEpKeyFromNeutronMapper; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.createTunnelPort; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getManagerNode; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint; +import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getTopologyNode; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; -import java.util.Map.Entry; - +import java.util.Map; 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.DataChangeScope; -import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.ovsdb.southbound.SouthboundConstants; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Uuid; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey; +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.OvsdbBridgeAugmentation; 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.OvsdbTerminationPointAugmentation; @@ -36,27 +54,15 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. 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.node.TerminationPoint; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getManagerNode; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getTopologyNode; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.createTunnelPort; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.OvsdbHelper.getOvsdbBridgeFromTerminationPoint; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.lookupEndpoint; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.EndpointHelper.updateEndpointWithLocation; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.NeutronHelper.getEpKeyFromNeutronMapper; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.checkOfOverlayConfig; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeIdString; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.getInventoryNodeConnectorIdString; -import static org.opendaylight.groupbasedpolicy.neutron.ovsdb.util.InventoryHelper.updateOfOverlayConfig; - -public class TerminationPointDataChangeListener implements DataChangeListener, AutoCloseable { +public class TerminationPointDataChangeListener implements DataTreeChangeListener, + AutoCloseable { private static final String NEUTRON_EXTERNAL_ID_KEY = "iface-id"; - private final ListenerRegistration registration; + private final ListenerRegistration registration; private final DataBroker dataBroker; private final EndpointService epService; private static final Logger LOG = LoggerFactory.getLogger(TerminationPointDataChangeListener.class); @@ -65,20 +71,20 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A public TerminationPointDataChangeListener(DataBroker dataBroker, EndpointService epService) { this.dataBroker = checkNotNull(dataBroker); this.epService = checkNotNull(epService); - InstanceIdentifier iid = InstanceIdentifier - .create(NetworkTopology.class) - .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) - .child(Node.class) - .child(TerminationPoint.class) - .augmentation(OvsdbTerminationPointAugmentation.class); - registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid, this, DataChangeScope.ONE); + InstanceIdentifier iid = InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID)) + .child(Node.class) + .child(TerminationPoint.class) + .augmentation(OvsdbTerminationPointAugmentation.class); + registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>( + LogicalDatastoreType.OPERATIONAL, iid), this); requiredTunnelTypes = createSupportedTunnelsList(); } private List createSupportedTunnelsList() { - List required = new ArrayList(); -// required.add(new VxlanGpeTunnelType()); + List required = new ArrayList<>(); required.add(new VxlanTunnelType()); + required.add(new VxlanGpeTunnelType()); return Collections.unmodifiableList(required); } @@ -87,53 +93,47 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A registration.close(); } - @Override - public void onDataChanged(AsyncDataChangeEvent, DataObject> change) { - - /* - * TerminationPoint notifications with OVSDB augmentations - * vSwitch ports. Iterate through the list of new ports. - */ - for (Entry, DataObject> entry: change.getCreatedData().entrySet()) { - if(entry.getValue() instanceof OvsdbTerminationPointAugmentation) { - OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation)entry.getValue(); - InstanceIdentifier ovsdbTpIid = - (InstanceIdentifier) entry.getKey(); - OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker); - processOvsdbBridge(ovsdbBridge, ovsdbTp,ovsdbTpIid); - } - } - - /* - * Updates - */ - for (Entry, DataObject> entry: change.getUpdatedData().entrySet()) { - if(entry.getValue() instanceof OvsdbTerminationPointAugmentation) { - OvsdbTerminationPointAugmentation ovsdbTp = (OvsdbTerminationPointAugmentation)entry.getValue(); - InstanceIdentifier ovsdbTpIid = - (InstanceIdentifier) entry.getKey(); - OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker); - processOvsdbBridge(ovsdbBridge, ovsdbTp,ovsdbTpIid); - } - } + /* + * When vSwitch is deleted, we loose data in operational DS to determine Iid of + * corresponding NodeId. + */ + private static final Map, NodeId> NODE_ID_BY_TERMIN_POINT = + new HashMap<>(); - /* - * Deletions - */ - for (InstanceIdentifier iid: change.getRemovedPaths()) { - if (iid instanceof OvsdbTerminationPointAugmentation) { - /* - * Remove the state from OfOverlay? - */ + @Override + public void onDataTreeChanged(Collection> changes) { + for (DataTreeModification change: changes) { + DataObjectModification rootNode = change.getRootNode(); + InstanceIdentifier ovsdbTpIid = change.getRootPath().getRootIdentifier(); + OvsdbTerminationPointAugmentation origOvsdbTp = rootNode.getDataBefore(); + switch (rootNode.getModificationType()) { + case SUBTREE_MODIFIED: + case WRITE: + OvsdbTerminationPointAugmentation updatedOvsdbTp = rootNode.getDataAfter(); + OvsdbBridgeAugmentation ovsdbBridge = getOvsdbBridgeFromTerminationPoint(ovsdbTpIid, dataBroker); + if (origOvsdbTp == null) { + NODE_ID_BY_TERMIN_POINT.put(ovsdbTpIid, + new NodeId(getInventoryNodeIdString(ovsdbBridge, ovsdbTpIid, dataBroker))); + } + + processOvsdbBridge(ovsdbBridge, updatedOvsdbTp, ovsdbTpIid); + break; + case DELETE: + processRemovedTp(NODE_ID_BY_TERMIN_POINT.get(ovsdbTpIid), origOvsdbTp, ovsdbTpIid); + break; + default: + break; } } } - private void processOvsdbBridge(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp, InstanceIdentifier ovsdbTpIid ) { + private void processOvsdbBridge(OvsdbBridgeAugmentation ovsdbBridge, OvsdbTerminationPointAugmentation ovsdbTp, + InstanceIdentifier ovsdbTpIid) { checkNotNull(ovsdbBridge); - if(ovsdbBridge.getBridgeName().getValue().equals(ovsdbTp.getName())) { - LOG.debug("Termination Point {} same as Bridge {}. Not processing",ovsdbTp.getName(),ovsdbBridge.getBridgeName().getValue()); + if (ovsdbBridge.getBridgeName().getValue().equals(ovsdbTp.getName())) { + LOG.debug("Termination Point {} same as Bridge {}. Not processing", ovsdbTp.getName(), + ovsdbBridge.getBridgeName().getValue()); return; } @@ -148,6 +148,11 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A return; } + InstanceIdentifier nodeIid = ovsdbTpIid.firstIdentifierOf(Node.class); + String externalId = getNeutronPortUuid(ovsdbTp); + Endpoint ep = null; + IpAddress hostIp = getIpFromOvsdb(ovsdbBridge); + /* * Ports created by Nova have an external_id field * in them, which is the Neutron port UUID. If a port @@ -158,17 +163,18 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A * (NodeId and NodeConnectorId from the inventory model) * and the port name, constructed using the port UUID. */ - String externalId = getNeutronPortUuid(ovsdbTp); - Endpoint ep = null; + if (externalId != null) { - EndpointKey epKey = getEpKeyFromNeutronMapper(new Uuid(externalId), dataBroker); + EndpointKey epKey = getEpKeyFromNeutronMapper(new UniqueId(externalId), dataBroker); if (epKey == null) { - LOG.debug("TerminationPoint {} with external ID {} is not in Neutron Map", ovsdbTp,externalId); + LOG.debug("TerminationPoint {} with external ID {} is not in Neutron Map", ovsdbTp, externalId); return; } - ep = lookupEndpoint(epKey, dataBroker); + ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction(); + ep = lookupEndpoint(epKey, transaction); if (ep == null) { - LOG.warn("TerminationPoint {} with external ID {} is in Neutron Map, but corresponding Endpoint {} isn't in Endpoint Repository", ovsdbTp,externalId,epKey); + LOG.warn("TerminationPoint {} with external ID {} is in Neutron Map, " + + "but corresponding Endpoint {} isn't in Endpoint Repository", ovsdbTp, externalId, epKey); return; } /* @@ -178,46 +184,112 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A * OfOverlay augmentation. If it hasn't, go see if the * tunnel ports exist, and if not, go and create them. */ - if (checkOfOverlayConfig(nodeIdString, requiredTunnelTypes, dataBroker) != true) { - - InstanceIdentifier nodeIid = ovsdbTpIid.firstIdentifierOf(Node.class); + if (!checkOfOverlayConfig(nodeIdString, requiredTunnelTypes, dataBroker)) { checkNotNull(nodeIid); - /* * Check to see if we need to create a * tunnel port on the parent node */ - createTunnelPorts(nodeIid, dataBroker); + createTunnelPorts(nodeIid); } } else { - LOG.debug("TerminationPoint {} has no external ID, not processing.",ovsdbTp); + LOG.debug("TerminationPoint {} had no external ID, not processing for external ID.", ovsdbTp); + } - IpAddress hostIp = getIpFromOvsdb(ovsdbBridge); + /* * This may be a notification for a tunnel we just created. * In that case, we need to update the Inventory Node's OfOverlay * augmentation with missing information */ + AbstractTunnelType tunnel = getTunnelType(ovsdbTp, requiredTunnelTypes); + if (tunnel != null) { + updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, tunnel, dataBroker); + } + if (externalId != null) { + ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction(); + updateEndpointWithLocation(ep, nodeIdString, nodeConnectorIdString, rwTx); + } + } + + /** + * If removed termination point was a tunnel port, + * removes attached tunnels (namely Vxlan-type) from OVSDB bridge, + * else removes location info from TP. + * + * @param nodeId {@link NodeId} + * @param ovsdbTp {@link OvsdbTerminationPointAugmentation} + * @param ovsdbTpIid termination point's IID {@link InstanceIdentifier} + */ + private void processRemovedTp(NodeId nodeId, OvsdbTerminationPointAugmentation ovsdbTp, + InstanceIdentifier ovsdbTpIid) { if (isTunnelPort(ovsdbTp, requiredTunnelTypes)) { - updateOfOverlayConfig(hostIp, nodeIdString, nodeConnectorIdString, requiredTunnelTypes, dataBroker); + removeTunnelsOfOverlayConfig(nodeId.getValue(), requiredTunnelTypes, dataBroker); + } else { + deleteLocationForTp(ovsdbTp); } + } + + /** + * Delete location on EP for given TP. + * + * @param ovsdbTp {@link OvsdbTerminationPointAugmentation} + */ + private void deleteLocationForTp(OvsdbTerminationPointAugmentation ovsdbTp) { + String externalId = getNeutronPortUuid(ovsdbTp); if (externalId != null) { - updateEndpointWithLocation(ep, nodeIdString, nodeConnectorIdString, ovsdbTp.getName(), epService); + EndpointKey epKey = getEpKeyFromNeutronMapper(new UniqueId(externalId), dataBroker); + if (epKey == null) { + LOG.debug("TerminationPoint {} with external ID {} is not in Neutron Map.", ovsdbTp, externalId); + return; + } + ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction(); + Endpoint ep = lookupEndpoint(epKey, readOnlyTransaction); + readOnlyTransaction.close(); + if (ep == null) { + LOG.warn("TerminationPoint {} with external ID {} is in Neutron Map," + + " but corresponding Endpoint {} isn't in Endpoint Repository.", ovsdbTp, externalId, epKey); + return; + } + updateEndpointRemoveLocation(ep, dataBroker.newReadWriteTransaction()); + } else { + LOG.debug("TerminationPoint {} has no external ID, not processing.", ovsdbTp); } } /** + * Check to see if the {@link OvsdbTerminationPointAugmentation} is also a Tunnel port that we + * care about. + * + * @param ovsdbTp {@link OvsdbTerminationPointAugmentation} + * @param requiredTunnelTypes {@link List} of tunnel types + */ + private static AbstractTunnelType getTunnelType(OvsdbTerminationPointAugmentation ovsdbTp, + List requiredTunnelTypes) { + if (ovsdbTp.getInterfaceType() != null) { + for (AbstractTunnelType tunnelType : requiredTunnelTypes) { + if (tunnelType.isValidTunnelPort(ovsdbTp)) { + return tunnelType; + } + } + } + return null; + } + + /* * Check to see if the {@link OvsdbTerminationPointAugmentation} * is also a Tunnel port that we care about. * - * @param ovsdbTp - * @param requiredTunnelTypes + * @param ovsdbTp {@link OvsdbTerminationPointAugmentation} + * + * @param requiredTunnelTypes {@link List} of tunnel types + * * @return true if it's a required tunnel port, false if it isn't */ - private boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp, - List requiredTunnelTypes) { + private static boolean isTunnelPort(OvsdbTerminationPointAugmentation ovsdbTp, + List requiredTunnelTypes) { if (ovsdbTp.getInterfaceType() != null) { - for (AbstractTunnelType tunnelType: requiredTunnelTypes) { + for (AbstractTunnelType tunnelType : requiredTunnelTypes) { if (tunnelType.isValidTunnelPort(ovsdbTp)) { return true; } @@ -226,21 +298,19 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A return false; } - /** * Get the Neutron Port UUID from an {@link OvsdbTerminationPointAugmentation}. * The Neutron Port UUID is stored as an "external-id" in the termination point. * - * @param ovsdbTp The OVSDB Termination Point augmentation + * @param ovsdbTp The {@link OvsdbTerminationPointAugmentation} * @return The String representation of the Neutron Port UUID, null if not present */ private String getNeutronPortUuid(OvsdbTerminationPointAugmentation ovsdbTp) { if (ovsdbTp.getInterfaceExternalIds() == null) { return null; } - for (InterfaceExternalIds id: ovsdbTp.getInterfaceExternalIds()) { - if (id.getExternalIdKey() != null - && id.getExternalIdKey().equals(NEUTRON_EXTERNAL_ID_KEY)) { + for (InterfaceExternalIds id : ovsdbTp.getInterfaceExternalIds()) { + if (id.getExternalIdKey() != null && id.getExternalIdKey().equals(NEUTRON_EXTERNAL_ID_KEY)) { if (id.getExternalIdValue() != null) { return id.getExternalIdValue(); @@ -254,10 +324,9 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A * Check to see if all tunnel ports are present, and if not, * create them. * - * @param tpIid - * @return + * @param nodeIid {@link InstanceIdentifier} */ - private void createTunnelPorts(InstanceIdentifier nodeIid, DataBroker dataBroker) { + private void createTunnelPorts(InstanceIdentifier nodeIid) { Node node = getTopologyNode(nodeIid, dataBroker); checkNotNull(node); @@ -271,19 +340,19 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A * See if this Topology Node has the required tunnel ports, * and if not, go and create them */ - for (AbstractTunnelType tunnelType: requiredTunnelTypes) { + for (AbstractTunnelType tunnelType : requiredTunnelTypes) { boolean tunnelPresent = false; - for (TerminationPoint tp: node.getTerminationPoint()) { - OvsdbTerminationPointAugmentation tpAug = - tp.getAugmentation(OvsdbTerminationPointAugmentation.class); + for (TerminationPoint tp : node.getTerminationPoint()) { + OvsdbTerminationPointAugmentation tpAug = tp.getAugmentation(OvsdbTerminationPointAugmentation.class); checkNotNull(tpAug); if (tunnelType.isValidTunnelPort(tpAug)) { tunnelPresent = true; + break; } } - if (tunnelPresent == false) { + if (!tunnelPresent) { createTunnelPort(nodeIid, node, tunnelType, dataBroker); } } @@ -302,7 +371,9 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A */ OvsdbNodeAugmentation managerNode = getManagerNode(ovsdbBridge, dataBroker); - if (managerNode == null) return null; + if (managerNode == null) { + return null; + } if (managerNode.getConnectionInfo() != null) { return managerNode.getConnectionInfo().getRemoteIp(); @@ -310,4 +381,3 @@ public class TerminationPointDataChangeListener implements DataChangeListener, A return null; } } -