BUG5764: Hwvtep tunnel update/delete not reflected correctly
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transactions / md / HwvtepTunnelUpdateCommand.java
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transactions/md/HwvtepTunnelUpdateCommand.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/transactions/md/HwvtepTunnelUpdateCommand.java
new file mode 100644 (file)
index 0000000..f3fc4a3
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * 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.transactions.md;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.HwvtepSouthboundMapper;
+import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
+import org.opendaylight.ovsdb.lib.message.TableUpdates;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
+import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
+import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
+import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
+import org.opendaylight.ovsdb.schema.hardwarevtep.Tunnel;
+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.HwvtepPhysicalLocatorRef;
+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.TunnelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdLocalConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdLocalConfigsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdParamsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdRemoteConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdRemoteConfigsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdStatusBuilder;
+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.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class HwvtepTunnelUpdateCommand extends AbstractTransactionCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepTunnelUpdateCommand.class);
+    private Map<UUID, Tunnel> updatedTunnelRows;
+
+    public HwvtepTunnelUpdateCommand(HwvtepConnectionInstance key, TableUpdates updates, DatabaseSchema dbSchema) {
+        super(key, updates, dbSchema);
+        try {
+            updatedTunnelRows = TyperUtils.extractRowsUpdated(Tunnel.class, getUpdates(), getDbSchema());
+        } catch (IllegalArgumentException e) {
+            LOG.debug("Tunnel Table not supported on this HWVTEP device", e.getMessage());
+        }
+    }
+
+    @Override
+    public void execute(ReadWriteTransaction transaction) {
+        if(updatedTunnelRows != null && !updatedTunnelRows.isEmpty()) {
+            for (Tunnel tunnel : updatedTunnelRows.values()) {
+                try {
+                    updateTunnel(transaction, tunnel);
+                } catch (Exception e) {
+                    LOG.warn("Exception updating tunnel {}", tunnel, e);
+                }
+            }
+        }
+    }
+
+    private void updateTunnel(ReadWriteTransaction transaction, Tunnel tunnel) {
+        Preconditions.checkNotNull(tunnel.getLocalColumn().getData());
+        Preconditions.checkNotNull(tunnel.getRemoteColumn().getData());
+        final InstanceIdentifier<Node> connectionIId = getOvsdbConnectionInstance().getInstanceIdentifier();
+        Optional<Node> connection = HwvtepSouthboundUtil.readNode(transaction, connectionIId);
+        PhysicalSwitch pSwitch =
+                        getOvsdbConnectionInstance().getDeviceInfo().getPhysicalSwitchForTunnel(tunnel.getUuid());
+        InstanceIdentifier<Node> psIid =
+                        HwvtepSouthboundMapper.createInstanceIdentifier(getOvsdbConnectionInstance(), pSwitch);
+        InstanceIdentifier<Tunnels> tunnelIid = getInstanceIdentifier(psIid, tunnel);
+        if (connection.isPresent() && pSwitch != null && tunnelIid != null) {
+            TunnelsBuilder tBuilder = new TunnelsBuilder();
+            tBuilder.setLocalLocatorRef(new HwvtepPhysicalLocatorRef(
+                            getPhysicalLocatorRefFromUUID(psIid, (tunnel.getLocalColumn().getData()))));
+            tBuilder.setRemoteLocatorRef(new HwvtepPhysicalLocatorRef(
+                            getPhysicalLocatorRefFromUUID(psIid, (tunnel.getRemoteColumn().getData()))));
+            tBuilder.setTunnelUuid(new Uuid(tunnel.getUuid().toString()));
+            setBfdLocalConfigs(tBuilder, tunnel);
+            setBfdRemoteConfigs(tBuilder, tunnel);
+            setBfdParams(tBuilder, tunnel);
+            setBfdStatus(tBuilder, tunnel);
+            Tunnels updatedTunnel = tBuilder.build();
+            LOG.trace("Built with the intent to store tunnel data {}", updatedTunnel);
+            transaction.merge(LogicalDatastoreType.OPERATIONAL, tunnelIid, updatedTunnel);
+            // TODO: Deletion of Tunnel BFD config and params
+        } else {
+            LOG.warn("Insuficient information. Unable to update tunnel {}", tunnel.getUuid());
+        }
+    }
+
+    private void setBfdLocalConfigs(TunnelsBuilder tBuilder, Tunnel tunnel) {
+        Map<String, String> localConfigs = tunnel.getBfdConfigLocalColumn().getData();
+        if(localConfigs != null && !localConfigs.isEmpty()) {
+            Set<String> localConfigKeys = localConfigs.keySet();
+            List<BfdLocalConfigs> localConfigsList = new ArrayList<>();
+            String localConfigValue = null;
+            for(String localConfigKey: localConfigKeys) {
+                localConfigValue = localConfigs.get(localConfigKey);
+                if(localConfigValue != null && localConfigKey != null) {
+                    localConfigsList.add(new BfdLocalConfigsBuilder()
+                        .setBfdLocalConfigKey(localConfigKey)
+                        .setBfdLocalConfigValue(localConfigValue)
+                        .build());
+                }
+            }
+            tBuilder.setBfdLocalConfigs(localConfigsList);
+        }
+    }
+
+    private void setBfdRemoteConfigs(TunnelsBuilder tBuilder, Tunnel tunnel) {
+        Map<String, String> remoteConfigs = tunnel.getBfdConfigRemoteColumn().getData();
+        if(remoteConfigs != null && !remoteConfigs.isEmpty()) {
+            Set<String> remoteConfigKeys = remoteConfigs.keySet();
+            List<BfdRemoteConfigs> remoteConfigsList = new ArrayList<>();
+            String remoteConfigValue = null;
+            for(String remoteConfigKey: remoteConfigKeys) {
+                remoteConfigValue = remoteConfigs.get(remoteConfigKey);
+                if(remoteConfigValue != null && remoteConfigKey != null) {
+                    remoteConfigsList.add(new BfdRemoteConfigsBuilder()
+                        .setBfdRemoteConfigKey(remoteConfigKey)
+                        .setBfdRemoteConfigValue(remoteConfigValue)
+                        .build());
+                }
+            }
+            tBuilder.setBfdRemoteConfigs(remoteConfigsList);
+        }
+    }
+
+
+    private void setBfdParams(TunnelsBuilder tBuilder, Tunnel tunnel) {
+        Map<String, String> params = tunnel.getBfdParamsColumn().getData();
+        if(params != null && !params.isEmpty()) {
+            Set<String> paramKeys = params.keySet();
+            List<BfdParams> paramsList = new ArrayList<>();
+            String paramValue = null;
+            for(String paramKey: paramKeys) {
+                paramValue = params.get(paramKey);
+                if(paramValue != null && paramKey != null) {
+                    paramsList.add(new BfdParamsBuilder()
+                        .setBfdParamKey(paramKey)
+                        .setBfdParamValue(paramValue)
+                        .build());
+                }
+            }
+            tBuilder.setBfdParams(paramsList);
+        }
+    }
+
+    private void setBfdStatus(TunnelsBuilder tBuilder, Tunnel tunnel) {
+        Map<String, String> status = tunnel.getBfdStatusColumn().getData();
+        if(status != null && !status.isEmpty()) {
+            Set<String> paramKeys = status.keySet();
+            List<BfdStatus> statusList = new ArrayList<>();
+            String paramValue = null;
+            for(String paramKey: paramKeys) {
+                paramValue = status.get(paramKey);
+                if(paramValue != null && paramKey != null) {
+                    statusList.add(new BfdStatusBuilder()
+                        .setBfdStatusKey(paramKey)
+                        .setBfdStatusValue(paramValue)
+                        .build());
+                }
+            }
+            tBuilder.setBfdStatus(statusList);
+        }
+    }
+
+    private InstanceIdentifier<Tunnels> getInstanceIdentifier(InstanceIdentifier<Node> psIid, Tunnel tunnel) {
+        InstanceIdentifier<Tunnels> result = null;
+        InstanceIdentifier<TerminationPoint> localTpPath =
+                        getPhysicalLocatorRefFromUUID(getOvsdbConnectionInstance().getInstanceIdentifier(),
+                                                        (tunnel.getLocalColumn().getData()));
+        InstanceIdentifier<TerminationPoint> remoteTpPath =
+                        getPhysicalLocatorRefFromUUID(getOvsdbConnectionInstance().getInstanceIdentifier(),
+                                                        (tunnel.getRemoteColumn().getData()));
+        if(remoteTpPath != null && localTpPath != null ) {
+            result = HwvtepSouthboundMapper.createInstanceIdentifier(psIid, localTpPath, remoteTpPath);
+        }
+        return result;
+    }
+
+    private InstanceIdentifier<TerminationPoint> getPhysicalLocatorRefFromUUID(InstanceIdentifier<Node> nodeIid,
+                                                                               UUID uuid) {
+        PhysicalLocator pLoc = getOvsdbConnectionInstance().getDeviceInfo().getPhysicalLocator(uuid);
+        if(pLoc == null) {
+            LOG.trace("Available PhysicalLocators: ",
+                            getOvsdbConnectionInstance().getDeviceInfo().getPhysicalLocators());
+            return null;
+        }
+        return HwvtepSouthboundMapper.createInstanceIdentifier(nodeIid, pLoc);
+    }
+
+}