import javax.annotation.Nonnull;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommand;
private EntityOwnershipCandidateRegistration deviceOwnershipCandidateRegistration;
private HwvtepGlobalAugmentation initialCreatedData = null;
private HwvtepDeviceInfo deviceInfo;
+ private DataBroker dataBroker;
HwvtepConnectionInstance (ConnectionInfo key, OvsdbClient client,
- InstanceIdentifier<Node> iid, TransactionInvoker txInvoker) {
+ InstanceIdentifier<Node> iid, TransactionInvoker txInvoker, DataBroker dataBroker) {
this.connectionInfo = key;
this.client = client;
this.instanceIdentifier = iid;
this.txInvoker = txInvoker;
- this.deviceInfo = new HwvtepDeviceInfo();
+ this.deviceInfo = new HwvtepDeviceInfo(this);
+ this.dataBroker = dataBroker;
}
public void transact(TransactCommand command) {
*/
}
+ public DataBroker getDataBroker() {
+ return dataBroker;
+ }
+
public ListenableFuture<List<String>> getDatabases() {
return client.getDatabases();
}
}
hwvtepConnectionInstance = new HwvtepConnectionInstance(key, externalClient, getInstanceIdentifier(key),
- txInvoker);
+ txInvoker, db);
hwvtepConnectionInstance.createTransactInvokers();
return hwvtepConnectionInstance;
}
package org.opendaylight.ovsdb.hwvtepsouthbound;
-import java.util.HashMap;
-import java.util.Map;
-
import org.opendaylight.ovsdb.lib.notation.UUID;
import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
+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.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/*
* HwvtepDeviceInfo is used to store some of the table entries received
*
*/
public class HwvtepDeviceInfo {
+
+ private static final Logger LOG = LoggerFactory.getLogger(HwvtepDeviceInfo.class);
+
+ public enum DeviceDataStatus {
+ IN_TRANSIT,
+ UNAVAILABLE,
+ AVAILABLE
+ }
+
+ public static class DeviceData {
+ private final InstanceIdentifier key;
+ private final UUID uuid;
+ private final Object data;
+ private final DeviceDataStatus status;
+
+ public DeviceData(InstanceIdentifier key, UUID uuid, Object data, DeviceDataStatus status) {
+ this.data = data;
+ this.key = key;
+ this.status = status;
+ this.uuid = uuid;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public DeviceDataStatus getStatus() {
+ return status;
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+ }
+
+ //TODO remove this
private Map<UUID, LogicalSwitch> logicalSwitches = null;
private Map<UUID, PhysicalSwitch> physicalSwitches = null;
private Map<UUID, PhysicalLocator> physicalLocators = null;
private Map<UUID, UUID> mapTunnelToPhysicalSwitch = null;
- public HwvtepDeviceInfo() {
+ private HwvtepConnectionInstance connectionInstance;
+
+ private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData = new ConcurrentHashMap<>();
+ private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData = new ConcurrentHashMap<>();
+ private Map<Class<? extends Identifiable>, Map<UUID, Object>> uuidVsData = new ConcurrentHashMap<>();
+
+ public HwvtepDeviceInfo(HwvtepConnectionInstance hwvtepConnectionInstance) {
+ this.connectionInstance = hwvtepConnectionInstance;
this.logicalSwitches = new HashMap<>();
this.physicalSwitches = new HashMap<>();
this.physicalLocators = new HashMap<>();
return mapTunnelToPhysicalSwitch;
}
+ public boolean isKeyInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
+ return deviceData != null && DeviceDataStatus.IN_TRANSIT == deviceData.status;
+ }
+
+ public boolean isConfigDataAvailable(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key) != null;
+ }
+
+ public void updateConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key, Object data) {
+ HwvtepSouthboundUtil.updateData(configKeyVsData, cls, key,
+ new DeviceData(key, null, data, DeviceDataStatus.AVAILABLE));
+ }
+
+ public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
+ }
+
+ public void markKeyAsInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
+ new DeviceData(key, null, null, DeviceDataStatus.IN_TRANSIT));
+ }
+
+ public void updateDeviceOpData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid, Object data) {
+ HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
+ new DeviceData(key, uuid, data, DeviceDataStatus.AVAILABLE));
+ HwvtepSouthboundUtil.updateData(uuidVsData, cls, uuid, data);
+ }
+
+ public void clearDeviceOpData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
+ if (deviceData != null && deviceData.uuid != null) {
+ HwvtepSouthboundUtil.clearData(uuidVsData, cls, deviceData.uuid);
+ }
+ HwvtepSouthboundUtil.clearData(opKeyVsData, cls, key);
+ }
+
+ public Object getDeviceOpData(Class<? extends Identifiable> cls, UUID uuid) {
+ return HwvtepSouthboundUtil.getData(uuidVsData, cls, uuid);
+ }
+
+ public DeviceData getDeviceOpData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ return HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
+ }
+
+ public UUID getUUID(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ DeviceData data = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
+ if (data != null) {
+ return data.uuid;
+ }
+ return null;
+ }
}
package org.opendaylight.ovsdb.hwvtepsouthbound;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalSwitchAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.ConnectionInfo;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.CheckedFuture;
-
-import java.util.concurrent.ExecutionException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
public class HwvtepSouthboundUtil {
public static void schemaMismatchLog(String column, String table, SchemaVersionMismatchException ex) {
LOG.debug(SCHEMA_VERSION_MISMATCH, column, table, "hw_vtep", ex.getMessage());
}
+
+ public static <KeyType, D> void updateData(Map<Class<? extends Identifiable>, Map<KeyType, D>> map,
+ Class<? extends Identifiable> cls, KeyType key, D data) {
+ if (key == null) {
+ return;
+ }
+ if (!map.containsKey(cls)) {
+ map.put(cls, new ConcurrentHashMap<>());
+ }
+ map.get(cls).put(key, data);
+ }
+
+ public static <KeyType, D> D getData(Map<Class<? extends Identifiable>, Map<KeyType, D>> map,
+ Class<? extends Identifiable> cls, KeyType key) {
+ if (key == null) {
+ return null;
+ }
+ if (map.containsKey(cls)) {
+ return map.get(cls).get(key);
+ }
+ return null;
+ }
+
+ public static <KeyType, D> boolean containsKey(Map<Class<? extends Identifiable>, Map<KeyType, D>> map,
+ Class<? extends Identifiable> cls, KeyType key) {
+ if (key == null) {
+ return false;
+ }
+ if (map.containsKey(cls)) {
+ return map.get(cls).containsKey(key);
+ }
+ return false;
+ }
+
+ public static <KeyType, D> void clearData(Map<Class<? extends Identifiable>, Map<KeyType, D>> map,
+ Class<? extends Identifiable> cls, KeyType key) {
+ if (key == null) {
+ return;
+ }
+ if (map.containsKey(cls)) {
+ map.get(cls).remove(key);
+ }
+ }
}
package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
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.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.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.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 com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+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<InstanceIdentifier<Node>, Node> operationalNodes = new HashMap<>();
private ReadWriteTransaction transaction;
HashMap<InstanceIdentifier<TerminationPoint>, UUID> inflightLocators = Maps.newHashMap();
+ private HwvtepDeviceInfo deviceInfo;
+ private HwvtepConnectionInstance connectionInstance;
+ private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, UUID>> currentTxUUIDs = new ConcurrentHashMap<>();
+ private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, Boolean>> currentTxDeletedKeys = new ConcurrentHashMap<>();
public HwvtepOperationalState(DataBroker db, Collection<DataTreeModification<Node>> changes) {
Map<InstanceIdentifier<Node>, Node> nodeCreateOrUpdate =
}
}
- private Optional<Node> getGlobalNode(InstanceIdentifier<?> iid) {
+ public HwvtepOperationalState(HwvtepConnectionInstance connectionInstance) {
+ this.connectionInstance = connectionInstance;
+ this.deviceInfo = connectionInstance.getDeviceInfo();
+ transaction = connectionInstance.getDataBroker().newReadWriteTransaction();
+ Optional<Node> readNode = HwvtepSouthboundUtil.readNode(transaction, connectionInstance.getInstanceIdentifier());
+ if (readNode.isPresent()) {
+ operationalNodes.put(connectionInstance.getInstanceIdentifier(), readNode.get());
+ }
+ }
+
+ public Optional<Node> getGlobalNode(InstanceIdentifier<?> iid) {
InstanceIdentifier<Node> nodeIid = iid.firstIdentifierOf(Node.class);
return Optional.fromNullable(operationalNodes.get(nodeIid));
}
List<TerminationPoint> tpList = nodeOptional.get();
for (TerminationPoint tp : tpList) {
HwvtepPhysicalPortAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalPortAugmentation.class);
- if (hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
+ if (hppAugmentation != null && hppAugmentation.getHwvtepNodeName().equals(hwvtepNodeName)) {
return Optional.fromNullable(hppAugmentation);
}
}
List<TerminationPoint> tpList = nodeOptional.get();
for (TerminationPoint tp : tpList) {
HwvtepPhysicalLocatorAugmentation hppAugmentation = tp.getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
- if (hppAugmentation.getDstIp().equals(dstIp)
+ if (hppAugmentation != null && hppAugmentation.getDstIp().equals(dstIp)
&& hppAugmentation.getEncapsulationType().equals(encapType)) {
return Optional.fromNullable(hppAugmentation);
}
public UUID getPhysicalLocatorInFlight(InstanceIdentifier<TerminationPoint> iid) {
return inflightLocators.get(iid);
}
+
+ public HwvtepConnectionInstance getConnectionInstance() {
+ return connectionInstance;
+ }
+
+ public HwvtepDeviceInfo getDeviceInfo() {
+ return deviceInfo;
+ }
+
+ public void updateCurrentTxData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid) {
+ HwvtepSouthboundUtil.updateData(currentTxUUIDs, cls, key, uuid);
+ deviceInfo.markKeyAsInTransit(cls, key);
+ }
+
+ public void updateCurrentTxDeleteData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ HwvtepSouthboundUtil.updateData(currentTxDeletedKeys, cls, key, Boolean.TRUE);
+ }
+
+ public UUID getUUIDFromCurrentTx(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ return HwvtepSouthboundUtil.getData(currentTxUUIDs, cls, key);
+ }
+
+ public boolean isKeyPartOfCurrentTx(Class<? extends Identifiable> cls, InstanceIdentifier key) {
+ return HwvtepSouthboundUtil.containsKey(currentTxUUIDs, cls, key);
+ }
+
+ public Set<InstanceIdentifier> getDeletedKeysInCurrentTx(Class<? extends Identifiable> cls) {
+ if (currentTxDeletedKeys.containsKey(cls)) {
+ return currentTxDeletedKeys.get(cls).keySet();
+ }
+ return Collections.EMPTY_SET;
+ }
+
}
* topology.rev131021.node.attributes.SupportingNode$StreamWriter: frozen class (cannot edit)
*/
if (dataBroker == null) {
- dataBroker = getDataBroker();
+ dataBroker = super.getDataBroker();
}
entityOwnershipService = mock(EntityOwnershipService.class);
+ nodeUuid = java.util.UUID.randomUUID().toString();
+ nodeIid = createInstanceIdentifier(nodeUuid);
loadSchema();
mockConnectionInstance();
mockConnectionManager();
mockOperations();
- nodeUuid = java.util.UUID.randomUUID().toString();
- nodeIid = createInstanceIdentifier(nodeUuid);
addNode(OPERATIONAL);
addNode(CONFIGURATION);
hwvtepDataChangeListener = new HwvtepDataChangeListener(dataBroker, hwvtepConnectionManager);
connectionInstance = PowerMockito.mock(HwvtepConnectionInstance.class, Mockito.CALLS_REAL_METHODS);
field(HwvtepConnectionInstance.class, "instanceIdentifier").set(connectionInstance, nodeIid);
field(HwvtepConnectionInstance.class, "txInvoker").set(connectionInstance, transactionInvoker);
- field(HwvtepConnectionInstance.class, "deviceInfo").set(connectionInstance, new HwvtepDeviceInfo());
+ field(HwvtepConnectionInstance.class, "deviceInfo").set(connectionInstance, new HwvtepDeviceInfo(connectionInstance));
field(HwvtepConnectionInstance.class, "client").set(connectionInstance, ovsdbClient);
when(connectionInstance.getConnectionInfo()).thenReturn(connectionInfo);
when(connectionInstance.getConnectionInfo().getRemoteAddress()).thenReturn(mock(InetAddress.class));
when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
doReturn(listenableDbSchema).when(connectionInstance).getSchema(anyString());
+ when(connectionInstance.getDataBroker()).thenReturn(dataBroker);
+ when(connectionInstance.getInstanceIdentifier()).thenReturn(nodeIid);
connectionInstance.createTransactInvokers();
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.ovsdb.hwvtepsouthbound.transact.HwvtepOperationalState;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.operations.Operations;
+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.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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({HwvtepConnectionInstance.class, HwvtepConnectionManager.class, Operations.class})
+public class HwvtepOperationalStateTest extends DataChangeListenerTestBase {
+
+ UUID uuid = new UUID("ls0");
+
+ @Test
+ public void testUpdateCurrentTxData() throws Exception {
+ InstanceIdentifier<LogicalSwitches> lsIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class).
+ child(LogicalSwitches.class, new LogicalSwitchesKey(new HwvtepNodeName("ls0")));
+
+ HwvtepOperationalState opState = new HwvtepOperationalState(connectionInstance);
+
+ UUID resultUuid = opState.getUUIDFromCurrentTx(LogicalSwitches.class, lsIid);
+ assertNull(resultUuid);
+
+ opState.updateCurrentTxData(LogicalSwitches.class, lsIid, uuid);
+ resultUuid = opState.getUUIDFromCurrentTx(LogicalSwitches.class, lsIid);
+ assertEquals(uuid, resultUuid);
+
+ boolean result = opState.getDeviceInfo().isKeyInTransit(LogicalSwitches.class, lsIid);
+ assertTrue(result);
+
+ opState.getDeviceInfo().updateDeviceOpData(LogicalSwitches.class, lsIid, uuid, lsIid);
+ result = opState.getDeviceInfo().isKeyInTransit(LogicalSwitches.class, lsIid);
+ assertFalse(result);
+
+ result = opState.getDeviceInfo().isConfigDataAvailable(LogicalSwitches.class, lsIid);
+ assertFalse(result);
+
+ opState.getDeviceInfo().updateConfigData(LogicalSwitches.class, lsIid, null);
+ result = opState.getDeviceInfo().isConfigDataAvailable(LogicalSwitches.class, lsIid);
+ assertTrue(result);
+ }
+}