Karaf cli command to display the hwvtep cache data 85/82885/3
authorChandra Shekar S <chandra.shekar.s@ericsson.com>
Tue, 2 Jul 2019 10:09:41 +0000 (15:39 +0530)
committerChandra Shekar S <chandra.shekar.s@ericsson.com>
Wed, 3 Jul 2019 13:42:51 +0000 (19:12 +0530)
JIRA: OVSDB-482

The hwvtep configuration data is pushed to the tor by the hwvtep plugin.
The hwvtep plugin has the caches (config and operational caches) which holds
the hwvtep configuration. The hwvtep configuration push to the tor is also
dependent on the data that is present in caches.
For ex : To push the vlanbinding data to the PhysicalPort , the operational
cache is checked first, if present in the operational cache get the uuid of
that PhysicalPort and the send/push the vlanbinding to the tor.

Today it is hard to know/check what is present in the cache. In case if there
any issue in updating the cache, it is hard to debug/analyse the issue as no way
to know what is present in the cache.

If we have mechanism/cli command which gives the information of the hwvtep
caches, it will be very helpful to debug or analyze such cache missing issues.

This is for adding the karaf cli command which displays the hwvtep caches contents.
This command has two options :
1. Hwvtep nodeid as the input. Displays cache information of input hwvtep node.
2. Without any input. Displays the cache information of all hwvtep nodes.

Change-Id: I4301a784d83aa28f5ef4737fc44d052f323e11df
Signed-off-by: Chandra Shekar S <chandra.shekar.s@ericsson.com>
hwvtepsouthbound/hwvtepsouthbound-impl/pom.xml
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDeviceInfo.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundProvider.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/cli/HwvtepCacheDisplayCmd.java [new file with mode: 0644]

index ca0da14f062ac912919c7fa8ff28117d89191d86..444cd9137cc7721b4360475b2f8105ac8dd5179a 100644 (file)
@@ -111,6 +111,10 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>powermock-reflect</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.karaf.shell</groupId>
+      <artifactId>org.apache.karaf.shell.core</artifactId>
+    </dependency>
   </dependencies>
 
   <build>
@@ -127,7 +131,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <artifactId>maven-bundle-plugin</artifactId>
         <configuration>
           <instructions>
-            <Karaf-Commands>org.opendaylight.ovsdb.hwvtepsouthbound.TransactionHistoryCmd</Karaf-Commands>
+            <Karaf-Commands>org.opendaylight.ovsdb.hwvtepsouthbound.cli*</Karaf-Commands>
             <Private-Package>org.opendaylight.ovsdb.schema.hardwarevtep</Private-Package>
             <Export-Package>org.opendaylight.ovsdb.hwvtepsouthbound.*,org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hwvtepsouthbound.impl.rev150901.*</Export-Package>
           </instructions>
index 91166fad49525a517d42067361fef5a4cc0f8ba3..39ac1e7eca558c1bea179cfd43946789e19139f4 100644 (file)
@@ -20,6 +20,7 @@ import java.net.ConnectException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -647,4 +648,8 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         */
         ON_DISCONNECT
     }
+
+    public Map<InstanceIdentifier<Node>, HwvtepConnectionInstance> getAllConnectedInstances() {
+        return Collections.unmodifiableMap(nodeIidVsConnectionInstance);
+    }
 }
index 6229bd3542893ba1eb7e731087d71d0f2e240c56..e8f82cd2852751aa8c5ec3e159a844e9cea7558c 100644 (file)
@@ -9,10 +9,13 @@
 package org.opendaylight.ovsdb.hwvtepsouthbound;
 
 import com.google.common.collect.Sets;
+
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+
 import java.util.concurrent.ConcurrentHashMap;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependentJob;
@@ -212,6 +215,10 @@ public class HwvtepDeviceInfo {
         return null;
     }
 
+    public Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> getConfigData() {
+        return Collections.unmodifiableMap(configKeyVsData);
+    }
+
     public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
         HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
     }
@@ -423,4 +430,12 @@ public class HwvtepDeviceInfo {
     public void addToDeviceUpdate(TransactionType transactionType, Object object) {
         deviceUpdateHistory.addToHistory(transactionType, object);
     }
+
+    public Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> getOperData() {
+        return Collections.unmodifiableMap(opKeyVsData);
+    }
+
+    public Map<Class<? extends Identifiable>, Map<UUID, DeviceData>> getUuidData() {
+        return Collections.unmodifiableMap(uuidVsData);
+    }
 }
index 1c9af4e5d3231f3bbaba096e4d42c9e4209bffe6..b8dd802751359b84fd2a57e36a7a4f3547358404 100644 (file)
@@ -17,6 +17,7 @@ import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import org.apache.aries.blueprint.annotation.service.Reference;
+import org.apache.aries.blueprint.annotation.service.Service;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
@@ -47,6 +48,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @Singleton
+@Service(classes = HwvtepSouthboundProvider.class) // only because HwvtepCacheDisplayCmd needs a @Reference to this
 public class HwvtepSouthboundProvider implements ClusteredDataTreeChangeListener<Topology>, AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(HwvtepSouthboundProvider.class);
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/cli/HwvtepCacheDisplayCmd.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/cli/HwvtepCacheDisplayCmd.java
new file mode 100644 (file)
index 0000000..3f5f468
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2019 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.cli;
+
+import java.io.PrintStream;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepConnectionInstance;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundProvider;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+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.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.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.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;
+
+@Service
+@Command(scope = "hwvtep", name = "cache", description = "Disply hwvtep cache")
+public class HwvtepCacheDisplayCmd implements Action {
+
+    @Argument(name = "nodeid", description = "Node Id",
+            required = false, multiValued = false)
+    private String nodeid;
+
+    @Reference
+    private HwvtepSouthboundProvider hwvtepSouthboundProvider;
+
+    private static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri("hwvtep:1"));
+    private static final String SEPERATOR = "#######################################################";
+    private static final String SECTION_SEPERATOR = "==================================================="
+            + "=============================";
+
+
+    @Override
+    @SuppressWarnings("checkstyle:RegexpSinglelineJava")
+    public Object execute() throws Exception {
+        Map<InstanceIdentifier<Node>, HwvtepConnectionInstance> allConnectedInstances =
+                hwvtepSouthboundProvider.getHwvtepConnectionManager().getAllConnectedInstances();
+        if (nodeid == null) {
+            allConnectedInstances.entrySet().forEach((entry) -> {
+                System.out.println(SEPERATOR + " START " + SEPERATOR);
+                print(entry.getKey(), entry.getValue());
+                System.out.println(SEPERATOR + " END " + SEPERATOR);
+                System.out.println();
+                System.out.println();
+            });
+        } else {
+            System.out.println(SEPERATOR + " START " + SEPERATOR);
+            print(getIid(), allConnectedInstances.get(getIid()));
+            System.out.println(SEPERATOR + " END " + SEPERATOR);
+        }
+        return null;
+    }
+
+    private InstanceIdentifier<Node> getIid() {
+        NodeId nodeId = new NodeId(new Uri(nodeid));
+        NodeKey nodeKey = new NodeKey(nodeId);
+        TopologyKey topoKey = new TopologyKey(HWVTEP_TOPOLOGY_ID);
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, topoKey)
+                .child(Node.class, nodeKey)
+                .build();
+    }
+
+    @SuppressWarnings("checkstyle:RegexpSinglelineJava")
+    private void print(InstanceIdentifier<Node> iid,
+                                           HwvtepConnectionInstance connectionInstance) {
+        PrintStream printStream = System.out;
+        printStream.print("Printing for Node :  ");
+        printStream.println(iid.firstKeyOf(Node.class).getNodeId().getValue());
+
+        printStream.println(SECTION_SEPERATOR);
+        printStream.println("Config data");
+        printStream.println(SECTION_SEPERATOR);
+        HwvtepDeviceInfo deviceInfo = connectionInstance.getDeviceInfo();
+        deviceInfo.getConfigData().entrySet().forEach((entry) -> {
+            printEntry(printStream, entry);
+        });
+
+
+        printStream.println(SECTION_SEPERATOR);
+        printStream.println("Oper data");
+        printStream.println(SECTION_SEPERATOR);
+        deviceInfo.getOperData().entrySet().forEach((entry) -> {
+            printEntry(printStream, entry);
+        });
+
+        printStream.println(SECTION_SEPERATOR);
+        printStream.println("Uuid data");
+        printStream.println(SECTION_SEPERATOR);
+        deviceInfo.getUuidData().entrySet().forEach((entry) -> {
+            printEntryUUID(printStream, entry);
+        });
+        printStream.println(SECTION_SEPERATOR);
+        printStream.println(SECTION_SEPERATOR);
+
+    }
+
+    private void printEntry(PrintStream console, Map.Entry<Class<? extends Identifiable>,
+            Map<InstanceIdentifier, HwvtepDeviceInfo.DeviceData>> entry) {
+        Class<? extends Identifiable> cls = entry.getKey();
+        Map<InstanceIdentifier, HwvtepDeviceInfo.DeviceData> map = entry.getValue();
+        String clsName = cls.getSimpleName();
+        console.println(clsName + " - ");
+        map.values().forEach((deviceData) -> {
+            printTable(console, clsName, deviceData);
+        });
+    }
+
+    private void printTable(PrintStream console, String clsName, HwvtepDeviceInfo.DeviceData deviceData) {
+        console.print("    ");
+        if (clsName.equals("LogicalSwitches")) {
+            printLogicalSwitches(console, deviceData);
+        } else if (clsName.equals("RemoteMcastMacs")) {
+            printRemoteMcasts(console, deviceData);
+        } else if (clsName.equals("RemoteUcastMacs")) {
+            printRemoteUcasts(console, deviceData);
+        } else if (clsName.equals("TerminationPoint") || clsName.equals("VlanBindings")) {
+            printTerminationPoint(console, deviceData);
+        } else if (clsName.equals("Node")) {
+            printNode(console, deviceData);
+        } else {
+            printCommon(console, deviceData);
+        }
+
+        if (deviceData.getData() == null && deviceData.getStatus() != HwvtepDeviceInfo.DeviceDataStatus.IN_TRANSIT) {
+            console.print("data null unexpected ");
+        }
+        console.print(" ");
+        console.print(deviceData.getStatus());
+        console.print(" ");
+        console.println(deviceData.getUuid());
+    }
+
+    private void printLogicalSwitches(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        InstanceIdentifier<LogicalSwitches> ls = deviceData.getKey();
+        console.print(ls.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue());
+    }
+
+    private void printRemoteMcasts(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        InstanceIdentifier<RemoteMcastMacs> remoteMcastMacsIid = deviceData.getKey();
+        String macAddress = remoteMcastMacsIid.firstKeyOf(RemoteMcastMacs.class).getMacEntryKey().getValue();
+        String logicalSwitchRef = remoteMcastMacsIid.firstKeyOf(RemoteMcastMacs.class).getLogicalSwitchRef().getValue()
+                .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+        StringBuilder macEntryDetails = new StringBuilder(macAddress).append("   LogicalSwitchRef  ")
+                .append(logicalSwitchRef);
+        console.print(macEntryDetails);
+    }
+
+    private void printRemoteUcasts(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        InstanceIdentifier<RemoteUcastMacs> remoteUcastMacsIid = deviceData.getKey();
+        String macAddress = remoteUcastMacsIid.firstKeyOf(RemoteUcastMacs.class).getMacEntryKey().getValue();
+        String logicalSwitchRef = remoteUcastMacsIid.firstKeyOf(RemoteUcastMacs.class).getLogicalSwitchRef().getValue()
+                .firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+        StringBuilder macEntryDetails = new StringBuilder(macAddress).append("   LogicalSwitchRef  ")
+                .append(logicalSwitchRef);
+        console.print(macEntryDetails);
+    }
+
+    private void printTerminationPoint(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        InstanceIdentifier<TerminationPoint> terminationPointIid = deviceData.getKey();
+        console.print(terminationPointIid.firstKeyOf(TerminationPoint.class).getTpId().getValue());
+    }
+
+    private void printNode(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        InstanceIdentifier<Node> ls = deviceData.getKey();
+        console.print(ls.firstKeyOf(Node.class).getNodeId().getValue());
+    }
+
+    private void printCommon(PrintStream console, HwvtepDeviceInfo.DeviceData deviceData) {
+        console.print(deviceData.getKey());
+        console.print(" ");
+        if (deviceData.getData() == null && deviceData.getStatus() != HwvtepDeviceInfo.DeviceDataStatus.IN_TRANSIT) {
+            console.print("data null unexpected ");
+        }
+        console.print(deviceData.getStatus());
+        console.print(" ");
+        console.println(deviceData.getUuid());
+    }
+
+    private void printEntryUUID(PrintStream console, Map.Entry<Class<? extends Identifiable>, Map<UUID,
+            HwvtepDeviceInfo.DeviceData>> entry) {
+        Class<? extends Identifiable> cls = entry.getKey();
+        Map<UUID, HwvtepDeviceInfo.DeviceData> map = entry.getValue();
+        String clsName = cls.getSimpleName();
+        console.println(clsName + " - ");
+        map.values().forEach((deviceData) -> {
+            printTable(console, clsName, deviceData);
+        });
+    }
+
+
+}