APIs to Get ovsdb device port errors and related apis

Change-Id: If4ba16d20b5544da7cbe84f2e167f4bc6242b89a
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index b81804a..fade592 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -334,4 +334,24 @@
      * Disconnects the OVSDB server.
      */
     void disconnect();
+
+    /**
+     * Gets created  ports for the particular bridgeId.
+     *
+     * @param portNames  the portNames which needs to checked for create
+     * @param bridgeId   bridgeIdentifier
+     * @return OvsdbPortNames  the created ports from port table for the bridgeId by considering input port list.
+     * Considered port as created if port's interface table also gets created,irrespective
+     * of ofport value(has errors or not)
+     */
+    public List<OvsdbPortName> getPorts(List<String> portNames, DeviceId bridgeId);
+
+    /**
+     * Gets error status for the given portNames.
+     *
+     * @param portNames  the portNames which need to be checked for errors
+     * @param bridgeId   bridgeIdentifier
+     * @return errorstatus true if input port list contains error, false otherwise
+     */
+    boolean getPortError(List<OvsdbPortName>  portNames, DeviceId bridgeId);
 }
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
index 03321da..598a97a 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
@@ -106,4 +106,7 @@
 
     /** Ovsdb Bridge table, Controller column name. */
     public static final String BRIDGE_CONTROLLER = "controller";
+
+    /** Openflow port Error. */
+    public static final int OFPORT_ERROR = -1;
 }
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 5523b81..11b7157 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -32,6 +32,8 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import java.util.Collections;
 import java.util.stream.Collectors;
 
 import org.onlab.packet.IpAddress;
@@ -55,6 +57,8 @@
 import org.onosproject.ovsdb.controller.OvsdbRowStore;
 import org.onosproject.ovsdb.controller.OvsdbStore;
 import org.onosproject.ovsdb.controller.OvsdbTableStore;
+import org.onosproject.ovsdb.rfc.exception.ColumnSchemaNotFoundException;
+import org.onosproject.ovsdb.rfc.exception.VersionMismatchException;
 import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
 import org.onosproject.ovsdb.rfc.message.OperationResult;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
@@ -122,6 +126,7 @@
 import static org.onosproject.ovsdb.controller.OvsdbConstant.TYPEVXLAN;
 import static org.onosproject.ovsdb.controller.OvsdbConstant.UUID;
 import static org.onosproject.ovsdb.controller.OvsdbConstant.BRIDGE_CONTROLLER;
+import static org.onosproject.ovsdb.controller.OvsdbConstant.OFPORT_ERROR;
 
 /**
  * An representation of an ovsdb client.
@@ -129,6 +134,7 @@
 public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientService {
 
     private static final int TRANSACTCONFIG_TIMEOUT = 3; //sec
+    private static final int OFPORT_ERROR_COMPARISON = 0;
 
     private final Logger log = LoggerFactory.getLogger(DefaultOvsdbClient.class);
 
@@ -1697,4 +1703,87 @@
         channel.disconnect();
         this.agent.removeConnectedNode(nodeId);
     }
+
+    @Override
+    public List<OvsdbPortName> getPorts(List<String> portNames, DeviceId deviceId) {
+        Uuid bridgeUuid = getBridgeUuid(deviceId);
+        if (bridgeUuid == null) {
+            log.error("Can't find the bridge for the deviceId {}", deviceId);
+            return Collections.emptyList();
+        }
+        DatabaseSchema dbSchema = schema.get(DATABASENAME);
+        Row bridgeRow = getRow(DATABASENAME, BRIDGE, bridgeUuid.value());
+        Bridge bridge = (Bridge) TableGenerator.getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
+        if (bridge == null) {
+            return Collections.emptyList();
+        }
+        OvsdbSet setPorts = (OvsdbSet) bridge.getPortsColumn().data();
+        Set<Uuid> portSet = setPorts.set();
+        if (portSet.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        Map<Uuid, Port> portMap = portSet.stream().collect(Collectors.toMap(
+                java.util.function.Function.identity(), port -> (Port) TableGenerator
+                        .getTable(dbSchema, getRow(DATABASENAME,
+                                PORT, port.value()), OvsdbTable.PORT)));
+
+        List<OvsdbPortName> portList = portMap.entrySet().stream().filter(port -> Objects.nonNull(port.getValue())
+                && portNames.contains(port.getValue().getName())
+                && Objects.nonNull(getInterfacebyPort(port.getKey().value(), port.getValue().getName())))
+                .map(port -> new OvsdbPortName(port.getValue().getName())).collect(Collectors.toList());
+
+        return Collections.unmodifiableList(portList);
+    }
+
+    @Override
+    public boolean getPortError(List<OvsdbPortName> portNames, DeviceId bridgeId) {
+        Uuid bridgeUuid = getBridgeUuid(bridgeId);
+
+        List<Interface> interfaceList = portNames.stream().collect(Collectors
+                .toMap(java.util.function.Function.identity(),
+                        port -> (Interface) getInterfacebyPort(getPortUuid(port.value(),
+                                bridgeUuid.value()), port.value())))
+                .entrySet().stream().filter(intf -> Objects.nonNull(intf.getValue())
+                        && ((OvsdbSet) intf.getValue().getOpenFlowPortColumn().data()).set()
+                        .stream().findAny().orElse(OFPORT_ERROR_COMPARISON).equals(OFPORT_ERROR))
+                .map(intf -> intf.getValue()).collect(Collectors.toList());
+
+        interfaceList.forEach(intf -> new Consumer<Interface>() {
+            @Override
+            public void accept(Interface intf) {
+                try {
+                    Set<String> setErrors = ((OvsdbSet) intf.getErrorColumn().data()).set();
+                    log.info("Port has errors. ofport value - {}, Interface - {} has error - {} ",
+                            intf.getOpenFlowPortColumn().data(), intf.getName(), setErrors.stream()
+                                    .findFirst().get());
+                } catch (ColumnSchemaNotFoundException | VersionMismatchException  e) {
+                    log.debug("Port has errors. ofport value - {}, Interface - {} has error - {} ",
+                            intf.getOpenFlowPortColumn().data(), intf.getName(), e);
+                }
+            }
+        }.accept(intf));
+
+        return !interfaceList.isEmpty();
+    }
+
+    private Interface getInterfacebyPort(String portUuid, String portName) {
+        DatabaseSchema dbSchema = schema.get(DATABASENAME);
+
+        Row portRow = getRow(DATABASENAME, PORT, portUuid);
+        Port port = (Port) TableGenerator.getTable(dbSchema, portRow,
+                OvsdbTable.PORT);
+        if (port == null) {
+            return null;
+        }
+
+        OvsdbSet setInterfaces = (OvsdbSet) port.getInterfacesColumn().data();
+        Set<Uuid> interfaces = setInterfaces.set();
+
+        return interfaces.stream().map(intf -> (Interface) TableGenerator
+                .getTable(dbSchema, getRow(DATABASENAME,
+                        INTERFACE, intf.value()), OvsdbTable.INTERFACE))
+                .filter(intf -> Objects.nonNull(intf) && portName.equalsIgnoreCase(intf.getName()))
+                .findFirst().orElse(null);
+    }
 }
diff --git a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
index c05a292..9da3378 100644
--- a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
+++ b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
@@ -16,6 +16,7 @@
 
 package org.onosproject.ovsdb.controller.driver;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
@@ -34,6 +35,7 @@
 import org.onosproject.ovsdb.controller.OvsdbPort;
 import org.onosproject.ovsdb.controller.OvsdbQos;
 import org.onosproject.ovsdb.controller.OvsdbQueue;
+import org.onosproject.ovsdb.controller.OvsdbPortName;
 import org.onosproject.ovsdb.rfc.message.TableUpdates;
 import org.onosproject.ovsdb.rfc.notation.Row;
 import org.onosproject.ovsdb.rfc.operations.Operation;
@@ -278,4 +280,14 @@
     public ListenableFuture<List<JsonNode>> transact(DatabaseSchema dbSchema, List<Operation> operations) {
         return null;
     }
+
+    @Override
+    public List<OvsdbPortName> getPorts(List<String> portNames, DeviceId bridgeId) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean getPortError(List<OvsdbPortName> portNames, DeviceId bridgeId) {
+        return false;
+    }
 }