From 480b80d0b790672a95f07da1caedc9f2fa38a566 Mon Sep 17 00:00:00 2001 From: "K.V Suneelu Verma" Date: Mon, 28 Nov 2016 12:59:20 +0530 Subject: [PATCH] bug 6579 added basic unit tests Added unit tests for the following commands McastMacsRemoteUpdateCommand UcastMacsRemoteUpdateCommand LogicalSwitchUpdateCommand When logical switch is configured ensure that op.insert is fired same with mcast mac and ucast mac also. Change-Id: Ie08664faa233776f82fb0a4ea8d6f0522a4b4810 Signed-off-by: K.V Suneelu Verma --- .../hwvtepsouthbound-impl/pom.xml | 29 +- .../DataChangeListenerTestBase.java | 241 +++++++++ .../HwvtepDataChangeListenerTest.java | 140 +++++ .../ovsdb/hwvtepsouthbound/TestBuilders.java | 165 ++++++ .../ovsdb/hwvtepsouthbound/hwvtep_schema.json | 495 ++++++++++++++++++ 5 files changed, 1069 insertions(+), 1 deletion(-) create mode 100644 hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java create mode 100644 hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListenerTest.java create mode 100644 hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/TestBuilders.java create mode 100644 hwvtepsouthbound/hwvtepsouthbound-impl/src/test/resources/org/opendaylight/ovsdb/hwvtepsouthbound/hwvtep_schema.json diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml b/hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml index 122e4e00b..d8d647c34 100644 --- a/hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml +++ b/hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml @@ -43,7 +43,24 @@ and is available at http://www.eclipse.org/legal/epl-v10.html ${project.version} - + + org.opendaylight.controller + sal-binding-broker-impl + test + + + org.opendaylight.controller + sal-binding-broker-impl + test + test-jar + + + org.slf4j + slf4j-simple + test + + + junit junit test @@ -53,6 +70,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mockito-all test + + org.powermock + powermock-api-mockito + test + + + org.powermock + powermock-module-junit4 + test + diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java new file mode 100644 index 000000000..ae0a87c8b --- /dev/null +++ b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/DataChangeListenerTestBase.java @@ -0,0 +1,241 @@ +/* + * 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 com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.util.concurrent.ListenableFuture; +import org.junit.After; +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest; +import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker; +import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl; +import org.opendaylight.ovsdb.lib.OvsdbClient; +import org.opendaylight.ovsdb.lib.OvsdbConnectionInfo; +import org.opendaylight.ovsdb.lib.operations.Comment; +import org.opendaylight.ovsdb.lib.operations.Insert; +import org.opendaylight.ovsdb.lib.operations.OperationResult; +import org.opendaylight.ovsdb.lib.operations.Operations; +import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; +import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable; +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.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder; +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.LogicalSwitches; +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.RemoteUcastMacs; +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.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.powermock.api.mockito.PowerMockito; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.net.InetAddress; +import java.util.List; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; +import static org.powermock.api.support.membermodification.MemberMatcher.field; +import static org.powermock.api.support.membermodification.MemberModifier.suppress; + +public class DataChangeListenerTestBase extends AbstractDataBrokerTest { + + static Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class); + + static DataBroker dataBroker; + + EntityOwnershipService entityOwnershipService; + OvsdbClient ovsdbClient; + DatabaseSchema dbSchema; + ListenableFuture listenableDbSchema = mock(ListenableFuture.class); + TransactionInvoker transactionInvoker; + OvsdbConnectionInfo connectionInfo; + Operations operations; + HwvtepDataChangeListener hwvtepDataChangeListener; + HwvtepConnectionManager hwvtepConnectionManager; + HwvtepConnectionInstance connectionInstance; + + ArgumentCaptor insertOpCapture; + ArgumentCaptor transactCaptor; + + String nodeUuid; + InstanceIdentifier nodeIid; + + @Before + public void setupTest() throws Exception { + /** + * Use the same databroker across tests ,otherwise the following exception is thrown + * Caused by: java.lang.RuntimeException: org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network. + * topology.rev131021.node.attributes.SupportingNode$StreamWriter: frozen class (cannot edit) + */ + if (dataBroker == null) { + dataBroker = getDataBroker(); + } + entityOwnershipService = mock(EntityOwnershipService.class); + loadSchema(); + mockConnectionInstance(); + mockConnectionManager(); + mockOperations(); + + nodeUuid = java.util.UUID.randomUUID().toString(); + nodeIid = createInstanceIdentifier(nodeUuid); + addNode(OPERATIONAL); + addNode(CONFIGURATION); + hwvtepDataChangeListener = new HwvtepDataChangeListener(dataBroker, hwvtepConnectionManager); + } + + @After + public void tearDown() throws Exception { + hwvtepDataChangeListener.close(); + deleteNode(OPERATIONAL); + deleteNode(CONFIGURATION); + } + + void loadSchema() { + try (InputStream resourceAsStream = DataChangeListenerTestBase.class.getResourceAsStream("hwvtep_schema.json")) { + ObjectMapper mapper = new ObjectMapper(); + JsonNode jsonNode = mapper.readTree(resourceAsStream); + dbSchema = DatabaseSchema.fromJson(HwvtepSchemaConstants.HARDWARE_VTEP, + jsonNode.get("result")); + listenableDbSchema = mock(ListenableFuture.class); + when(listenableDbSchema.get()).thenReturn(dbSchema); + } catch (Exception e) { + LOG.error("Failed to load schema", e); + } + } + + private void mockConnectionManager() throws IllegalAccessException { + hwvtepConnectionManager = PowerMockito.mock(HwvtepConnectionManager.class, Mockito.CALLS_REAL_METHODS); + field(HwvtepConnectionManager.class, "db").set(hwvtepConnectionManager, dataBroker); + field(HwvtepConnectionManager.class, "txInvoker").set(hwvtepConnectionManager, transactionInvoker); + field(HwvtepConnectionManager.class, "entityOwnershipService").set(hwvtepConnectionManager, entityOwnershipService); + suppress(PowerMockito.method(HwvtepConnectionManager.class, "getConnectionInstance", HwvtepPhysicalSwitchAttributes.class)); + when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(HwvtepPhysicalSwitchAttributes.class))). + thenReturn(connectionInstance); + when(hwvtepConnectionManager.getConnectionInstance(Mockito.any(Node.class))). + thenReturn(connectionInstance); + } + + void mockConnectionInstance() throws IllegalAccessException { + connectionInfo = mock(OvsdbConnectionInfo.class); + ovsdbClient = mock(OvsdbClient.class); + transactionInvoker = new TransactionInvokerImpl(dataBroker); + 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, "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()); + connectionInstance.createTransactInvokers(); + } + + void mockOperations() { + resetOperations(); + } + + /** + * resets the captures so that we can validate the captors of the immediate next execution + */ + void resetOperations() { + insertOpCapture = ArgumentCaptor.forClass(TypedBaseTable.class); + Insert insert = mock(Insert.class); + when(insert.withId(any(String.class))).thenReturn(insert); + Operations.op = PowerMockito.mock(Operations.class); + when(Operations.op.comment(any(String.class))).thenReturn(mock(Comment.class)); + when(Operations.op.insert(insertOpCapture.capture())).thenReturn(insert); + + ListenableFuture> ft = mock(ListenableFuture.class); + transactCaptor = ArgumentCaptor.forClass(List.class); + when(ovsdbClient.transact(any(DatabaseSchema.class), transactCaptor.capture())).thenReturn(ft); + } + + void addNode(LogicalDatastoreType logicalDatastoreType) throws Exception { + NodeBuilder nodeBuilder = prepareNode(nodeIid); + HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder(); + nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build()); + WriteTransaction transaction = dataBroker.newWriteOnlyTransaction(); + transaction.put(logicalDatastoreType, nodeIid, nodeBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS); + transaction.submit(); + } + + void deleteNode(LogicalDatastoreType logicalDatastoreType) { + ReadWriteTransaction tx = dataBroker.newReadWriteTransaction(); + tx.delete(logicalDatastoreType, nodeIid); + tx.submit(); + } + + void addData(LogicalDatastoreType logicalDatastoreType, Class dataObject, + String[]... data) { + NodeBuilder nodeBuilder = prepareNode(nodeIid); + HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder(); + if (LogicalSwitches.class == dataObject) { + TestBuilders.addLogicalSwitches(builder, data); + } + if (TerminationPoint.class == dataObject) { + TestBuilders.addGlobalTerminationPoints(nodeBuilder, nodeIid, data); + } + if (RemoteUcastMacs.class == dataObject) { + TestBuilders.addRemoteUcastMacs(nodeIid, builder, data); + } + if (RemoteMcastMacs.class == dataObject) { + TestBuilders.addRemoteMcastMacs(nodeIid, builder, data); + } + nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build()); + mergeNode(logicalDatastoreType, nodeIid, nodeBuilder); + } + + NodeBuilder prepareNode(InstanceIdentifier iid) { + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId()); + return nodeBuilder; + } + + Node mergeNode(LogicalDatastoreType datastoreType, InstanceIdentifier id, NodeBuilder nodeBuilder) { + Node node = nodeBuilder.build(); + WriteTransaction transaction = dataBroker.newWriteOnlyTransaction(); + transaction.merge(datastoreType, id, node, WriteTransaction.CREATE_MISSING_PARENTS); + transaction.submit(); + return node; + } + + public InstanceIdentifier createInstanceIdentifier(String nodeIdString) { + NodeId nodeId = new NodeId(new Uri(nodeIdString)); + NodeKey nodeKey = new NodeKey(nodeId); + TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID); + return InstanceIdentifier.builder(NetworkTopology.class) + .child(Topology.class, topoKey) + .child(Node.class, nodeKey) + .build(); + } +} diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListenerTest.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListenerTest.java new file mode 100644 index 000000000..4517c8420 --- /dev/null +++ b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListenerTest.java @@ -0,0 +1,140 @@ +/* + * 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 com.google.common.collect.Lists; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.opendaylight.ovsdb.lib.operations.Operations; +import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; +import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable; +import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch; +import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote; +import org.opendaylight.ovsdb.schema.hardwarevtep.UcastMacsRemote; +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.RemoteMcastMacs; +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.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Iterator; +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; +import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; + +/** + * Unit tests for the data-tree change listener. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({HwvtepConnectionInstance.class, HwvtepConnectionManager.class, Operations.class}) +public class HwvtepDataChangeListenerTest extends DataChangeListenerTestBase { + + static Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListenerTest.class); + + String[][] ucastMacs = new String[][]{ + {"20:00:00:00:00:01", "11.10.10.1", "192.168.122.20", "ls0"}, + {"20:00:00:00:00:02", "11.10.10.2", "192.168.122.20", "ls0"}, + {"20:00:00:00:00:03", "11.10.10.3", "192.168.122.30", "ls1"}, + {"20:00:00:00:00:04", "11.10.10.4", "192.168.122.30", "ls1"} + }; + + String[][] logicalSwitches = new String[][]{ + {"ls0", "100"}, + {"ls1", "200"}, + }; + + String[][] terminationPoints = new String[][]{ + {"192.168.122.10"}, + {"192.168.122.20"}, + {"192.168.122.30"}, + {"192.168.122.40"} + }; + + String[][] mcastMacs = new String[][]{ + {"FF:FF:FF:FF:FF:FF", "ls0", "192.168.122.20", "192.168.122.30"}, + {"FF:FF:FF:FF:FF:FF", "ls1", "192.168.122.10", "192.168.122.30"} + }; + + @Test + public void testLogicalSwitchAdd() throws Exception { + addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches); + verifyThatLogicalSwitchCreated(); + } + + @Test + public void testUcastMacAdd() throws Exception { + addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches); + addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches); + resetOperations(); + addData(CONFIGURATION, TerminationPoint.class, terminationPoints); + addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs); + //4 ucast macs + 2 termination points + verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class)); + //TODO add finer grained validation + } + + @Test + public void testMcastMacAdd() throws Exception { + addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches); + addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches); + resetOperations(); + addData(CONFIGURATION, TerminationPoint.class, terminationPoints); + addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs); + //2 mcast macs + 2 locator sets + 3 termination points + verify(Operations.op, times(7)).insert(Matchers.any()); + } + + @Test + public void testAddMacs() throws Exception { + addData(CONFIGURATION, LogicalSwitches.class, logicalSwitches); + addData(OPERATIONAL, LogicalSwitches.class, logicalSwitches); + resetOperations(); + addData(CONFIGURATION, TerminationPoint.class, terminationPoints); + addData(CONFIGURATION, RemoteUcastMacs.class, ucastMacs); + verify(Operations.op, times(6)).insert(any(UcastMacsRemote.class)); + + addData(OPERATIONAL, TerminationPoint.class, terminationPoints); + addData(OPERATIONAL, RemoteUcastMacs.class, ucastMacs); + + resetOperations(); + addData(CONFIGURATION, RemoteMcastMacs.class, mcastMacs); + //2 mcast mac + 2 locator sets ( termination point already added ) + verify(Operations.op, times(4)).insert(Matchers.any()); + } + + private void verifyThatLogicalSwitchCreated() { + verify(ovsdbClient, times(1)).transact(any(DatabaseSchema.class), any(List.class)); + verify(Operations.op, times(2)).insert(any(LogicalSwitch.class)); + + assertNotNull(insertOpCapture.getAllValues()); + assertTrue(insertOpCapture.getAllValues().size() == 2); + + List expected = Lists.newArrayList("ls0", "ls1"); + Iterator it = insertOpCapture.getAllValues().iterator(); + while (it.hasNext()) { + TypedBaseTable table = it.next(); + assertTrue(table instanceof LogicalSwitch); + LogicalSwitch ls = (LogicalSwitch)table; + assertTrue(expected.contains(ls.getName())); + expected.remove(ls.getName()); + it.next(); + } + } +} diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/TestBuilders.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/TestBuilders.java new file mode 100644 index 000000000..25628546e --- /dev/null +++ b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/java/org/opendaylight/ovsdb/hwvtepsouthbound/TestBuilders.java @@ -0,0 +1,165 @@ +/* + * 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 com.google.common.collect.Lists; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; +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.HwvtepGlobalAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef; +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.HwvtepPhysicalLocatorAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef; +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.LogicalSwitchesBuilder; +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.RemoteMcastMacsBuilder; +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.RemoteUcastMacsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId; +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.node.TerminationPoint; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class TestBuilders { + + public static final String VXLAN_OVER_IPV4 = "vxlan_over_ipv4"; + + public static void addLogicalSwitches(HwvtepGlobalAugmentationBuilder augmentationBuilder, String[]... data) { + List logicalSwitcheses = Lists.newArrayList(); + for (String row[] : data) { + logicalSwitcheses.add(TestBuilders.buildLogicalSwitch(row)); + } + augmentationBuilder.setLogicalSwitches(logicalSwitcheses); + } + + public static void addRemoteMcastMacs(InstanceIdentifier iid, + HwvtepGlobalAugmentationBuilder augmentationBuilder, String[]... data) { + List remoteMcastMacses = Lists.newArrayList(); + for (String row[] : data) { + String teps[] = Arrays.copyOfRange(row, 2, row.length); + remoteMcastMacses.add(TestBuilders.buildRemoteMcastMacs(iid, row[0], row[1], teps)); + } + augmentationBuilder.setRemoteMcastMacs(remoteMcastMacses); + } + + public static List addRemoteUcastMacs(InstanceIdentifier iid, + HwvtepGlobalAugmentationBuilder augmentationBuilder, + String[]... data) { + List remoteUcastMacses = Lists.newArrayList(); + for (String row[] : data) { + remoteUcastMacses.add(TestBuilders.buildRemoteUcastMacs(iid, row[0], row[1], row[2], row[3])); + } + augmentationBuilder.setRemoteUcastMacs(remoteUcastMacses); + return remoteUcastMacses; + } + + public static void addGlobalTerminationPoints(NodeBuilder nodeBuilder, InstanceIdentifier nodeIid, + String[]... data) { + List terminationPoints = Lists.newArrayList(); + for (String row[] : data) { + terminationPoints.add(TestBuilders.buildTerminationPoint(nodeIid, row[0])); + } + nodeBuilder.setTerminationPoint(terminationPoints); + } + + public static HwvtepLogicalSwitchRef buildLogicalSwitchesRef(InstanceIdentifier nodeIid, + String logicalSwitchName ) { + InstanceIdentifier lSwitchIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class) + .child(LogicalSwitches.class, new LogicalSwitchesKey(new HwvtepNodeName(logicalSwitchName))); + return new HwvtepLogicalSwitchRef(lSwitchIid); + } + + public static RemoteUcastMacs buildRemoteUcastMacs(InstanceIdentifier nodeIid, String vmMac, + String vmip, String tepIp, String logicalSwitchName) { + RemoteUcastMacsBuilder ucmlBuilder = new RemoteUcastMacsBuilder(); + ucmlBuilder.setIpaddr(new IpAddress(vmip.toCharArray())); + ucmlBuilder.setMacEntryKey(new MacAddress(vmMac)); + ucmlBuilder.setMacEntryUuid(getUUid(vmMac)); + ucmlBuilder.setLocatorRef(buildLocatorRef(nodeIid, tepIp)); + ucmlBuilder.setLogicalSwitchRef(buildLogicalSwitchesRef(nodeIid, logicalSwitchName)); + return ucmlBuilder.build(); + } + + public static TerminationPoint buildTerminationPoint(InstanceIdentifier nodeIid, String ip) { + TerminationPointKey tpKey = new TerminationPointKey(new TpId("vxlan_over_ipv4:"+ip)); + TerminationPointBuilder tpBuilder = new TerminationPointBuilder(); + if (nodeIid != null) { + tpBuilder.setKey(tpKey); + tpBuilder.setTpId(tpKey.getTpId()); + HwvtepPhysicalLocatorAugmentationBuilder tpAugmentationBuilder = + new HwvtepPhysicalLocatorAugmentationBuilder(); + tpAugmentationBuilder.setPhysicalLocatorUuid(getUUid(ip)); + tpAugmentationBuilder.setEncapsulationType(HwvtepSouthboundMapper.createEncapsulationType(VXLAN_OVER_IPV4)); + tpAugmentationBuilder.setDstIp(new IpAddress(ip.toCharArray())); + tpBuilder.addAugmentation(HwvtepPhysicalLocatorAugmentation.class, tpAugmentationBuilder.build()); + } + return tpBuilder.build(); + } + + public static LogicalSwitches buildLogicalSwitch(String... keys) { + String logicalSwitch = keys[0]; + String tunnelKey = keys[1]; + LogicalSwitchesBuilder logicalSwitchesBuilder = new LogicalSwitchesBuilder(); + logicalSwitchesBuilder.setKey(new LogicalSwitchesKey(new HwvtepNodeName(logicalSwitch))); + logicalSwitchesBuilder.setHwvtepNodeName(new HwvtepNodeName(logicalSwitch)); + logicalSwitchesBuilder.setTunnelKey(tunnelKey); + Uuid uuid = getUUid(logicalSwitch); + logicalSwitchesBuilder.setLogicalSwitchUuid(uuid); + return logicalSwitchesBuilder.build(); + } + + public static RemoteMcastMacs buildRemoteMcastMacs(InstanceIdentifier iid, String mac, + String logicalSwitchName,String tepIps[]) { + + RemoteMcastMacsBuilder mMacLocalBuilder = new RemoteMcastMacsBuilder(); + if (mac.equals(HwvtepSouthboundConstants.UNKNOWN_DST_STRING)) { + mMacLocalBuilder.setMacEntryKey(HwvtepSouthboundConstants.UNKNOWN_DST_MAC); + } else { + mMacLocalBuilder.setMacEntryKey(new MacAddress(mac)); + } + mMacLocalBuilder.setMacEntryUuid(getUUid(mac)); + mMacLocalBuilder.setLogicalSwitchRef(buildLogicalSwitchesRef(iid, logicalSwitchName)); + List locatorSets = Lists.newArrayList(); + for (String tepIp : tepIps) { + locatorSets.add(new LocatorSetBuilder().setLocatorRef( + buildLocatorRef(iid, tepIp)).build()); + } + mMacLocalBuilder.setLocatorSet(locatorSets); + return mMacLocalBuilder.build(); + } + + public static HwvtepPhysicalLocatorRef buildLocatorRef(InstanceIdentifier nodeIid,String tepIp) { + InstanceIdentifier tepId = buildTpId(nodeIid, tepIp); + return new HwvtepPhysicalLocatorRef(tepId); + } + + public static Uuid getUUid(String key) { + return new Uuid(UUID.nameUUIDFromBytes(key.getBytes()).toString()); + } + + public static InstanceIdentifier buildTpId(InstanceIdentifier nodeIid,String tepIp) { + String tpKeyStr = VXLAN_OVER_IPV4 +':'+tepIp; + TerminationPointKey tpKey = new TerminationPointKey(new TpId(tpKeyStr)); + return nodeIid.child(TerminationPoint.class, tpKey); + } +} diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/resources/org/opendaylight/ovsdb/hwvtepsouthbound/hwvtep_schema.json b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/resources/org/opendaylight/ovsdb/hwvtepsouthbound/hwvtep_schema.json new file mode 100644 index 000000000..3d34523f7 --- /dev/null +++ b/hwvtepsouthbound/hwvtepsouthbound-impl/src/test/resources/org/opendaylight/ovsdb/hwvtepsouthbound/hwvtep_schema.json @@ -0,0 +1,495 @@ +{ + "error": null, + "id": "0", + "result": { + "cksum": "58544667 7319", + "name": "hardware_vtep", + "tables": { + "Arp_Sources_Local": { + "columns": { + "locator": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + }, + "src_mac": { + "type": "string" + } + }, + "isRoot": true + }, + "Arp_Sources_Remote": { + "columns": { + "locator": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + }, + "src_mac": { + "type": "string" + } + }, + "isRoot": true + }, + "Global": { + "columns": { + "managers": { + "type": { + "key": { + "refTable": "Manager", + "type": "uuid" + }, + "max": "unlimited", + "min": 0 + } + }, + "switches": { + "type": { + "key": { + "refTable": "Physical_Switch", + "type": "uuid" + }, + "max": "unlimited", + "min": 0 + } + } + }, + "isRoot": true, + "maxRows": 1 + }, + "Logical_Binding_Stats": { + "columns": { + "bytes_from_local": { + "type": "integer" + }, + "bytes_to_local": { + "type": "integer" + }, + "packets_from_local": { + "type": "integer" + }, + "packets_to_local": { + "type": "integer" + } + } + }, + "Logical_Router": { + "columns": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "static_routes": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "switch_binding": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + } + }, + "indexes": [ + [ + "name" + ] + ], + "isRoot": true + }, + "Logical_Switch": { + "columns": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "_uuid": { + "type": "string" + }, + "tunnel_key": { + "type": { + "key": "integer", + "min": 0 + } + } + }, + "indexes": [ + [ + "name" + ] + ], + "isRoot": true + }, + "Manager": { + "columns": { + "inactivity_probe": { + "type": { + "key": "integer", + "min": 0 + } + }, + "is_connected": { + "ephemeral": true, + "type": "boolean" + }, + "max_backoff": { + "type": { + "key": { + "minInteger": 1000, + "type": "integer" + }, + "min": 0 + } + }, + "other_config": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "status": { + "ephemeral": true, + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "target": { + "type": "string" + } + }, + "indexes": [ + [ + "target" + ] + ] + }, + "Mcast_Macs_Local": { + "columns": { + "MAC": { + "type": "string" + }, + "ipaddr": { + "type": "string" + }, + "locator_set": { + "type": { + "key": { + "refTable": "Physical_Locator_Set", + "type": "uuid" + } + } + }, + "logical_switch": { + "type": { + "key": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + } + }, + "isRoot": true + }, + "Mcast_Macs_Remote": { + "columns": { + "MAC": { + "type": "string" + }, + "ipaddr": { + "type": "string" + }, + "locator_set": { + "type": { + "key": { + "refTable": "Physical_Locator_Set", + "type": "uuid" + } + } + }, + "logical_switch": { + "type": { + "key": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + } + }, + "isRoot": true + }, + "Physical_Locator": { + "columns": { + "dst_ip": { + "mutable": false, + "type": "string" + }, + "encapsulation_type": { + "mutable": false, + "type": { + "key": { + "enum": "vxlan_over_ipv4", + "type": "string" + } + } + } + }, + "indexes": [ + [ + "encapsulation_type", + "dst_ip" + ] + ] + }, + "Physical_Locator_Set": { + "columns": { + "locators": { + "mutable": false, + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + }, + "max": "unlimited" + } + } + } + }, + "Physical_Port": { + "columns": { + "description": { + "type": "string" + }, + "name": { + "type": "string" + }, + "port_fault_status": { + "ephemeral": true, + "type": { + "key": "string", + "max": "unlimited", + "min": 0 + } + }, + "vlan_bindings": { + "type": { + "key": { + "maxInteger": 4095, + "minInteger": 0, + "type": "integer" + }, + "max": "unlimited", + "min": 0, + "value": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + }, + "vlan_stats": { + "type": { + "key": { + "maxInteger": 4095, + "minInteger": 0, + "type": "integer" + }, + "max": "unlimited", + "min": 0, + "value": { + "refTable": "Logical_Binding_Stats", + "type": "uuid" + } + } + } + } + }, + "Physical_Switch": { + "columns": { + "description": { + "type": "string" + }, + "management_ips": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0 + } + }, + "name": { + "type": "string" + }, + "ports": { + "type": { + "key": { + "refTable": "Physical_Port", + "type": "uuid" + }, + "max": "unlimited", + "min": 0 + } + }, + "switch_fault_status": { + "ephemeral": true, + "type": { + "key": "string", + "max": "unlimited", + "min": 0 + } + }, + "tunnel_ips": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0 + } + }, + "tunnels": { + "type": { + "key": { + "refTable": "Tunnel", + "type": "uuid" + }, + "max": "unlimited", + "min": 0 + } + } + }, + "indexes": [ + [ + "name" + ] + ] + }, + "Tunnel": { + "columns": { + "bfd_config_local": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "bfd_config_remote": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "bfd_params": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "bfd_status": { + "type": { + "key": "string", + "max": "unlimited", + "min": 0, + "value": "string" + } + }, + "local": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + }, + "remote": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + } + } + }, + "Ucast_Macs_Local": { + "columns": { + "MAC": { + "type": "string" + }, + "ipaddr": { + "type": "string" + }, + "locator": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + }, + "logical_switch": { + "type": { + "key": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + } + }, + "isRoot": true + }, + "Ucast_Macs_Remote": { + "columns": { + "MAC": { + "type": "string" + }, + "ipaddr": { + "type": "string" + }, + "locator": { + "type": { + "key": { + "refTable": "Physical_Locator", + "type": "uuid" + } + } + }, + "logical_switch": { + "type": { + "key": { + "refTable": "Logical_Switch", + "type": "uuid" + } + } + } + }, + "isRoot": true + } + }, + "version": "1.3.0" + } +} -- 2.36.6