/* * Copyright (c) 2015, 2017 China Telecom Beijing Research Institute 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.ovsdb.hwvtepsouthbound.transact; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import org.apache.commons.lang3.tuple.Pair; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance; import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo; import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil; import org.opendaylight.ovsdb.lib.notation.UUID; import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; 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.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Acls; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.AclsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalMcastMacsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalRouters; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalRoutersKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey; 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.yang.binding.Identifiable; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; //TODO: need to be optimized, get entry by iid not name public class HwvtepOperationalState { private static final Logger LOG = LoggerFactory.getLogger(HwvtepOperationalState.class); private Map, Node> operationalNodes = new HashMap<>(); private ReadWriteTransaction transaction; HashMap, UUID> inflightLocators = new HashMap<>(); private HwvtepDeviceInfo deviceInfo; private HwvtepConnectionInstance connectionInstance; private Map, Map> currentTxUUIDs = new ConcurrentHashMap<>(); private Map, Map> currentTxDeletedKeys = new ConcurrentHashMap<>(); /* stores the modified and deleted data for each child type of each node id Map each updated/ deleted contains Map < child type, List> child type is the child of hwvtep Global augmentation */ private Map, Pair, List>, Map, List>>> modifiedData = new HashMap<>(); private boolean inReconciliation = false; private final DataBroker db; private final Collection> changes; public HwvtepOperationalState(DataBroker db, HwvtepConnectionInstance connectionInstance, Collection> changes) { this.connectionInstance = connectionInstance; this.deviceInfo = connectionInstance.getDeviceInfo(); this.db = db; this.changes = changes; this.transaction = db.newReadWriteTransaction(); } public HwvtepOperationalState(HwvtepConnectionInstance connectionInstance) { this.connectionInstance = connectionInstance; this.deviceInfo = connectionInstance.getDeviceInfo(); this.db = connectionInstance.getDataBroker(); this.changes = null; transaction = connectionInstance.getDataBroker().newReadWriteTransaction(); Optional readNode = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, connectionInstance.getInstanceIdentifier()); if (readNode.isPresent()) { operationalNodes.put(connectionInstance.getInstanceIdentifier(), readNode.get()); } } public HwvtepOperationalState(final DataBroker db, final HwvtepConnectionInstance connectionInstance, final Collection> changes, final Node globalOperNode, final Node psNode) { this(db, connectionInstance, changes); operationalNodes.put(connectionInstance.getInstanceIdentifier(), globalOperNode); HwvtepGlobalAugmentation globalAugmentation = globalOperNode.getAugmentation(HwvtepGlobalAugmentation.class); if (globalAugmentation != null) { if (!HwvtepSouthboundUtil.isEmpty(globalAugmentation.getSwitches())) { operationalNodes.put((InstanceIdentifier) globalAugmentation.getSwitches().get(0).getSwitchRef().getValue(), psNode); } } } public void readOperationalNodes() { if (inReconciliation) { return; } if (changes == null) { LOG.warn("Could not read operational nodes for {} as changes is", connectionInstance.getNodeId().getValue()); return; } Map, Node> nodeCreateOrUpdate = TransactUtils.extractCreatedOrUpdatedOrRemoved(changes, Node.class); if (nodeCreateOrUpdate != null) { transaction = db.newReadWriteTransaction(); for (Entry, Node> entry: nodeCreateOrUpdate.entrySet()) { Optional readNode = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, entry.getKey()); //add related globalNode or physicalSwitchNode to operationalNodes map //for example, when creating physical port, logical switch is needed //but logical switch is in HwvtepGlobalAugmentation rather than PhysicalSwitchAugmentation if (readNode.isPresent()) { operationalNodes.put(entry.getKey(), readNode.get()); HwvtepGlobalAugmentation hgAugmentation = readNode.get().getAugmentation(HwvtepGlobalAugmentation.class); PhysicalSwitchAugmentation psAugmentation = readNode.get().getAugmentation(PhysicalSwitchAugmentation.class); if (hgAugmentation != null && hgAugmentation.getSwitches() != null) { for (Switches pswitch : hgAugmentation.getSwitches()) { @SuppressWarnings("unchecked") InstanceIdentifier psNodeIid = (InstanceIdentifier) pswitch.getSwitchRef().getValue(); Optional psNode = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, psNodeIid); if (psNode.isPresent()) { operationalNodes.put(psNodeIid, psNode.get()); } } } if (psAugmentation != null) { @SuppressWarnings("unchecked") InstanceIdentifier hgNodeIid = (InstanceIdentifier) psAugmentation.getManagedBy().getValue(); Optional hgNode = new MdsalUtils(db).readOptional( LogicalDatastoreType.OPERATIONAL, hgNodeIid); if (hgNode.isPresent()) { operationalNodes.put(hgNodeIid, hgNode.get()); } } } } } } public Optional getGlobalNode(InstanceIdentifier iid) { InstanceIdentifier nodeIid = iid.firstIdentifierOf(Node.class); return Optional.fromNullable(operationalNodes.get(nodeIid)); } public Optional getHwvtepGlobalAugmentation(InstanceIdentifier iid) { Preconditions.checkNotNull(iid); Optional nodeOptional = getGlobalNode(iid); if (nodeOptional.isPresent()) { return Optional.fromNullable(nodeOptional.get().getAugmentation(HwvtepGlobalAugmentation.class)); } return Optional.absent(); } public Optional getPhysicalSwitchAugmentation(InstanceIdentifier iid) { Preconditions.checkNotNull(iid); Optional nodeOptional = getGlobalNode(iid); if (nodeOptional.isPresent()) { return Optional.fromNullable(nodeOptional.get().getAugmentation(PhysicalSwitchAugmentation.class)); } return Optional.absent(); } public Optional> getTerminationPointList(InstanceIdentifier iid) { Preconditions.checkNotNull(iid); Optional nodeOptional = getGlobalNode(iid); if (nodeOptional.isPresent() && nodeOptional.get().getTerminationPoint() != null) { return Optional.fromNullable(nodeOptional.get().getTerminationPoint()); } return Optional.absent(); } public Optional getLogicalSwitches(InstanceIdentifier iid, LogicalSwitchesKey logicalSwitchesKey) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); List lswitchList = null; if (hgAugmentation != null) { lswitchList = hgAugmentation.getLogicalSwitches(); } if (lswitchList != null) { for (LogicalSwitches lswitch: lswitchList) { if (lswitch.getKey().equals(logicalSwitchesKey)) { return Optional.fromNullable(lswitch); } } } } return Optional.absent(); } public Optional getTunnels(InstanceIdentifier iid, TunnelsKey tunnelsKey) { Preconditions.checkNotNull(iid); Optional psOptional = getPhysicalSwitchAugmentation(iid); if (psOptional.isPresent()) { PhysicalSwitchAugmentation psAugmentation = psOptional.get(); List tunnelList = null; if (psAugmentation != null) { tunnelList = psAugmentation.getTunnels(); } if (tunnelList != null) { for (Tunnels tunnel: tunnelList) { if (tunnel.getKey().equals(tunnelsKey)) { return Optional.fromNullable(tunnel); } } } } return Optional.absent(); } public Optional getPhysicalPortAugmentation(InstanceIdentifier iid, HwvtepNodeName hwvtepNodeName) { Preconditions.checkNotNull(iid); Optional> nodeOptional = getTerminationPointList(iid); if (nodeOptional.isPresent()) { List tpList = nodeOptional.get(); for (TerminationPoint tp : tpList) { HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class); if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) { return Optional.fromNullable(hppAugmentation); } } } return Optional.absent(); } public Optional getPhysicalLocatorAugmentation(InstanceIdentifier iid, IpAddress dstIp, Class encapType) { Preconditions.checkNotNull(iid); Optional> nodeOptional = getTerminationPointList(iid); if (nodeOptional.isPresent()) { List tpList = nodeOptional.get(); for (TerminationPoint tp : tpList) { HwvtepPhysicalLocatorAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalLocatorAugmentation.class); if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp) && hppAugmentation.getEncapsulationType().equals(encapType)) { return Optional.fromNullable(hppAugmentation); } } } return Optional.absent(); } public Optional getLocalMcastMacs(InstanceIdentifier iid, LocalMcastMacsKey key) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); List macList = null; if (hgAugmentation != null) { macList = hgAugmentation.getLocalMcastMacs(); } if (macList != null) { for (LocalMcastMacs mac: macList) { if (mac.getKey().equals(key)) { return Optional.fromNullable(mac); } } } } return Optional.absent(); } public Optional getRemoteMcastMacs(InstanceIdentifier iid, RemoteMcastMacsKey key) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); List macList = null; if (hgAugmentation != null) { macList = hgAugmentation.getRemoteMcastMacs(); } if (macList != null) { for (RemoteMcastMacs mac: macList) { if (mac.getKey().equals(key)) { return Optional.fromNullable(mac); } } } } return Optional.absent(); } public Optional getLocalUcastMacs(InstanceIdentifier iid, LocalUcastMacsKey key) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); List macList = null; if (hgAugmentation != null) { macList = hgAugmentation.getLocalUcastMacs(); } if (macList != null) { for (LocalUcastMacs mac: macList) { if (mac.getKey().equals(key)) { return Optional.fromNullable(mac); } } } } return Optional.absent(); } public Optional getRemoteUcastMacs(InstanceIdentifier iid, RemoteUcastMacsKey key) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); List macList = null; if (hgAugmentation != null) { macList = hgAugmentation.getRemoteUcastMacs(); } if (macList != null) { for (RemoteUcastMacs mac: macList) { if (mac.getKey().equals(key)) { return Optional.fromNullable(mac); } } } } return Optional.absent(); } public Optional getLogicalRouters(final InstanceIdentifier iid, final LogicalRoutersKey logicalRoutersKey) { Preconditions.checkNotNull(iid); Optional nodeOptional = getHwvtepGlobalAugmentation(iid); if (nodeOptional.isPresent()) { HwvtepGlobalAugmentation hgAugmentation = nodeOptional.get(); if (hgAugmentation != null && hgAugmentation.getLogicalRouters() != null) { for (LogicalRouters lrouter: hgAugmentation.getLogicalRouters()) { if (lrouter.getKey().equals(logicalRoutersKey)) { return Optional.fromNullable(lrouter); } } } } return Optional.absent(); } public Optional getPhysicalLocatorAugmentation(InstanceIdentifier iid) { Optional tp = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid); if (tp.isPresent()) { return Optional.fromNullable(tp.get().getAugmentation(HwvtepPhysicalLocatorAugmentation.class)); } return Optional.absent(); } public Optional getLogicalSwitches(InstanceIdentifier iid) { Optional lswitch = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid); return lswitch; } public Optional getTunnels(InstanceIdentifier iid) { Optional tunnels = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid); return tunnels; } public Optional getAcls(InstanceIdentifier iid) { Optional acl = new MdsalUtils(db).readOptional(LogicalDatastoreType.OPERATIONAL, iid); return acl; } public ReadWriteTransaction getReadWriteTransaction() { return transaction; } public void setPhysicalLocatorInFlight(InstanceIdentifier iid, UUID uuid) { inflightLocators.put(iid, uuid); } public UUID getPhysicalLocatorInFlight(InstanceIdentifier iid) { return inflightLocators.get(iid); } public HwvtepConnectionInstance getConnectionInstance() { return connectionInstance; } public HwvtepDeviceInfo getDeviceInfo() { return deviceInfo; } public void updateCurrentTxData(Class cls, InstanceIdentifier key, UUID uuid) { HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid); } public void updateCurrentTxDeleteData(Class cls, InstanceIdentifier key) { HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE); } public UUID getUUIDFromCurrentTx(Class cls, InstanceIdentifier key) { return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key); } public boolean isKeyPartOfCurrentTx(Class cls, InstanceIdentifier key) { return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key); } public Set getDeletedKeysInCurrentTx(Class cls) { if (currentTxDeletedKeys.containsKey(cls)) { return currentTxDeletedKeys.get(cls).keySet(); } return Collections.EMPTY_SET; } public List getUpdatedData(final InstanceIdentifier key, final Class cls) { List result = null; if (modifiedData.get(key) != null && modifiedData.get(key).getLeft() != null) { result = modifiedData.get(key).getLeft().get(cls); } if (result == null) { result = Collections.EMPTY_LIST; } return result; } public List getDeletedData(final InstanceIdentifier key, final Class cls) { List result = null; if (modifiedData.get(key) != null && modifiedData.get(key).getRight() != null) { result = modifiedData.get(key).getRight().get(cls); } if (result == null) { result = Collections.EMPTY_LIST; } return result; } public void setModifiedData(final Map, Pair, List>, Map, List>>> modifiedData) { this.modifiedData = modifiedData; } public boolean isInReconciliation() { return inReconciliation; } public void setInReconciliation(boolean inReconciliation) { this.inReconciliation = inReconciliation; } public DataBroker getDataBroker() { return db; } public void clearIntransitKeys() { currentTxUUIDs.forEach( (cls, map) -> { map.forEach( (iid, uuid) -> deviceInfo.clearInTransit(cls, iid)); }); currentTxDeletedKeys.forEach( (cls, map) -> { map.forEach( (iid, val) -> deviceInfo.clearInTransit(cls, iid)); }); currentTxUUIDs.clear(); currentTxDeletedKeys.clear(); deviceInfo.onOperDataAvailable(); } }