Add DataTreeChangeListener, user connections 61/28661/1
authorVishal Thapar <vishal.thapar@ericsson.com>
Wed, 21 Oct 2015 12:38:49 +0000 (18:08 +0530)
committerVishal Thapar <vishal.thapar@ericsson.com>
Wed, 21 Oct 2015 19:58:47 +0000 (01:28 +0530)
1. Adds DataTreeChangeListener
2. Support for user configured connections to OVSDB server
3. Provider changes as per https://git.opendaylight.org/gerrit/#/c/28568/

Pending items:
1. Updating DataStore on connections
2. HWVTEP command patterns and transactions support
3. UTs
4. ITs

Change-Id: I328ffbdad6d0eab2a90973f7eb6828cbc233d828
Signed-off-by: Vishal Thapar <vishal.thapar@ericsson.com>
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionInstance.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListener.java [new file with mode: 0644]
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepMonitorCallback.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundMapper.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundProvider.java

index b4055764ddeb5b99a17d60178f6f06e7b15d1467..45843d443aaa16fd11a0a6ec945055c5538f4311 100644 (file)
@@ -41,6 +41,7 @@ import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
 import org.opendaylight.ovsdb.lib.schema.TableSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TypedBaseTable;
+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.hwvtep.global.attributes.ConnectionInfo;
 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.Node;
@@ -63,6 +64,7 @@ public class HwvtepConnectionInstance implements OvsdbClient{
     private volatile boolean hasDeviceOwnership = false;
     private Entity connectedEntity;
     private EntityOwnershipCandidateRegistration deviceOwnershipCandidateRegistration;
+    private HwvtepGlobalAugmentation initialCreatedData = null;
 
 
     HwvtepConnectionInstance (ConnectionInfo key,OvsdbClient client,
@@ -81,13 +83,17 @@ public class HwvtepConnectionInstance implements OvsdbClient{
 
     public void registerCallbacks() {
         if ( this.callback == null) {
+            if(this.initialCreatedData != null) {
+                this.updateConnectionAttributes();
+            }
+
             try {
                 List<String> databases = getDatabases().get();
                 this.callback = new HwvtepMonitorCallback(this,txInvoker);
                 for (String database : databases) {
                     DatabaseSchema dbSchema = getSchema(database).get();
                     if (dbSchema != null) {
-                        monitorAllTables(database, dbSchema);
+                        monitorAllTables(database, dbSchema, HwvtepSchemaConstants.databaseName);
                     } else {
                         LOG.warn("No schema reported for database {} for key {}",database,connectionInfo);
                     }
@@ -115,11 +121,16 @@ public class HwvtepConnectionInstance implements OvsdbClient{
         }
     }
 
-    private void monitorAllTables(String database, DatabaseSchema dbSchema) {
+    private void monitorAllTables(String database, DatabaseSchema dbSchema, String filter) {
+        if((filter != null) && (!dbSchema.getName().equals(filter))) {
+            LOG.debug("Not monitoring tables in {}, filter: {}", dbSchema.getName(), filter);
+            return;
+        }
         Set<String> tables = dbSchema.getTables();
         if (tables != null) {
             List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
             for (String tableName : tables) {
+                LOG.debug("HwvtepSouthbound monitoring table {} in {}", tableName, dbSchema.getName());
                 GenericTableSchema tableSchema = dbSchema.table(tableName, GenericTableSchema.class);
                 Set<String> columns = tableSchema.getColumns();
                 MonitorRequestBuilder<GenericTableSchema> monitorBuilder = MonitorRequestBuilder.builder(tableSchema);
@@ -134,6 +145,17 @@ public class HwvtepConnectionInstance implements OvsdbClient{
         }
     }
 
+    private void updateConnectionAttributes() {
+        LOG.debug("Update attributes of ovsdb node ip: {} port: {}",
+                    this.initialCreatedData.getConnectionInfo().getRemoteIp(),
+                    this.initialCreatedData.getConnectionInfo().getRemotePort());
+        /*
+         * TODO: Do we have anything to update?
+         * Hwvtep doesn't have other_config or external_ids like
+         * Open_vSwitch. What else will be needed?
+         */
+    }
+
     public ListenableFuture<List<String>> getDatabases() {
         return client.getDatabases();
     }
@@ -270,4 +292,8 @@ public class HwvtepConnectionInstance implements OvsdbClient{
             setHasDeviceOwnership(Boolean.FALSE);
         }
     }
+
+    public void setHwvtepGlobalAugmentation(HwvtepGlobalAugmentation hwvtepGlobalData) {
+        this.initialCreatedData = hwvtepGlobalData;
+    }
 }
index 3a117bdccd1eb01ed1b649671f5ff280a0b0a496..fd6ebb5186b8f52a562e9a38d9c74e3983b9b007 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.ovsdb.hwvtepsouthbound;
 
 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -30,6 +32,7 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
+import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
 import org.opendaylight.ovsdb.lib.operations.Operation;
 import org.opendaylight.ovsdb.lib.operations.OperationResult;
 import org.opendaylight.ovsdb.lib.operations.Select;
@@ -37,6 +40,7 @@ import org.opendaylight.ovsdb.lib.schema.DatabaseSchema;
 import org.opendaylight.ovsdb.lib.schema.GenericTableSchema;
 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
 import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
+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.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.InstanceIdentifier;
@@ -84,7 +88,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
     public void connected(@Nonnull final OvsdbClient client) {
         HwvtepConnectionInstance hwClient = connectedButCallBacksNotRegistered(client);
         registerEntityForOwnership(hwClient);
-        LOG.trace("connected client: {}", hwClient);
+        LOG.trace("connected client: {}", client);
     }
 
     @Override
@@ -106,6 +110,32 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         LOG.trace("disconnected client: {}", client);
     }
 
+    public OvsdbClient connect(InstanceIdentifier<Node> iid, HwvtepGlobalAugmentation hwvtepGlobal) throws UnknownHostException {
+        InetAddress ip = HwvtepSouthboundMapper.createInetAddress(hwvtepGlobal.getConnectionInfo().getRemoteIp());
+        OvsdbClient client = OvsdbConnectionService.getService()
+                        .connect(ip, hwvtepGlobal.getConnectionInfo().getRemotePort().getValue());
+        if(client != null) {
+            putInstanceIdentifier(hwvtepGlobal.getConnectionInfo(), iid.firstIdentifierOf(Node.class));
+            HwvtepConnectionInstance hwvtepConnectionInstance = connectedButCallBacksNotRegistered(client);
+            hwvtepConnectionInstance.setHwvtepGlobalAugmentation(hwvtepGlobal);
+
+            // Register Cluster Ownership for ConnectionInfo
+            registerEntityForOwnership(hwvtepConnectionInstance);
+        } else {
+            LOG.warn("Failed to connect to OVSDB node: {}", hwvtepGlobal.getConnectionInfo());
+        }
+        return client;
+    }
+    public void disconnect(HwvtepGlobalAugmentation ovsdbNode) throws UnknownHostException {
+        HwvtepConnectionInstance client = getConnectionInstance(ovsdbNode.getConnectionInfo());
+        if (client != null) {
+            client.disconnect();
+            // Unregister Cluster Ownership for ConnectionInfo
+            unregisterEntityForOwnership(client);
+            removeInstanceIdentifier(ovsdbNode.getConnectionInfo());
+        }
+    }
+
     public HwvtepConnectionInstance connectedButCallBacksNotRegistered(final OvsdbClient externalClient) {
         LOG.info("OVSDB Connection from {}:{}",externalClient.getConnectionInfo().getRemoteAddress(),
                 externalClient.getConnectionInfo().getRemotePort());
@@ -180,6 +210,10 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
         instanceIdentifiers.remove(connectionInfo);
     }
 
+    public OvsdbClient getClient(ConnectionInfo connectionInfo) {
+        return getConnectionInstance(connectionInfo);
+    }
+
     private void registerEntityForOwnership(HwvtepConnectionInstance hwvtepConnectionInstance) {
 
         Entity candidateEntity = getEntityFromConnectionInstance(hwvtepConnectionInstance);
@@ -255,7 +289,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
 
     private Entity getEntityFromConnectionInstance(@Nonnull HwvtepConnectionInstance hwvtepConnectionInstance) {
         YangInstanceIdentifier entityId = null;
-        InstanceIdentifier<Node> iid = hwvtepConnectionInstance.getInstanceIdentifier();;
+        InstanceIdentifier<Node> iid = hwvtepConnectionInstance.getInstanceIdentifier();
         if ( iid == null ) {
             //TODO: Is Global the right one?
             Global hwvtepGlobalRow = getHwvtepGlobalTableEntry(hwvtepConnectionInstance);
@@ -296,7 +330,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
             // If entity has no owner, clean up the operational data store (it's possible because owner controller
             // might went down abruptly and didn't get a chance to clean up the operational data store.
             if (!ownershipChange.hasOwner()) {
-                LOG.debug("{} has no onwer, cleaning up the operational data store", ownershipChange.getEntity());
+                LOG.debug("{} has no owner, cleaning up the operational data store", ownershipChange.getEntity());
                 // Below code might look weird but it's required. We want to give first opportunity to the
                 // previous owner of the device to clean up the operational data store if there is no owner now.
                 // That way we will avoid lot of nasty md-sal exceptions because of concurrent delete.
diff --git a/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListener.java b/hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepDataChangeListener.java
new file mode 100644 (file)
index 0000000..f207895
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2015 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 java.net.UnknownHostException;
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.ovsdb.lib.OvsdbClient;
+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.hwvtep.global.attributes.ConnectionInfo;
+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.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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HwvtepDataChangeListener implements DataTreeChangeListener<Node>, AutoCloseable {
+
+    private ListenerRegistration<HwvtepDataChangeListener> registration;
+    private HwvtepConnectionManager hcm;
+    private DataBroker db;
+    private static final Logger LOG = LoggerFactory.getLogger(HwvtepDataChangeListener.class);
+
+    HwvtepDataChangeListener(DataBroker db, HwvtepConnectionManager hcm) {
+        LOG.info("Registering HwvtepDataChangeListener");
+        this.db = db;
+        this.hcm = hcm;
+        registerListener(db);
+    }
+
+    private void registerListener(final DataBroker db) {
+        final DataTreeIdentifier<Node> treeId =
+                        new DataTreeIdentifier<Node>(LogicalDatastoreType.CONFIGURATION, getWildcardPath());
+        try {
+            LOG.trace("Registering on path: {}", treeId);
+            registration = db.registerDataTreeChangeListener(treeId, HwvtepDataChangeListener.this);
+        } catch (final Exception e) {
+            LOG.warn("HwvtepDataChangeListener registration failed");
+            //TODO: Should we throw an exception here?
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        if(registration != null) {
+            registration.close();
+        }
+    }
+
+    @Override
+    public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
+        LOG.trace("onDataTreeChanged: {}", changes);
+
+        /* TODO:
+         * Currently only handling changes to Global.
+         * Rest will be added later.
+         */
+        connect(changes);
+        
+        updateConnections(changes);
+        
+        updateData(changes);
+        
+        disconnect(changes);
+        /*
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+                switch (mod.getModificationType()) {
+                case DELETE:
+                    LOG.trace("Data deleted: {}", mod.getDataBefore());
+                    //disconnect(mod);
+                    break;
+                case SUBTREE_MODIFIED:
+                    LOG.trace("Data modified: {} to {}", mod.getDataBefore(),mod.getDataAfter());
+                    updateConnections(mod);
+                    break;
+                case WRITE:
+                    if (mod.getDataBefore() == null) {
+                        LOG.trace("Data added: {}", mod.getDataAfter());
+                        connect(mod.getDataAfter());
+                    } else {
+                        LOG.trace("Data modified: {} to {}", mod.getDataBefore(),mod.getDataAfter());
+                        updateConnections(mod);
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+                }
+        }
+        */
+    }
+
+    private void connect(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node node = getCreated(mod);
+            if (node != null) {
+                HwvtepGlobalAugmentation hwvtepGlobal = node.getAugmentation(HwvtepGlobalAugmentation.class);
+                ConnectionInfo connection = hwvtepGlobal.getConnectionInfo();
+                InstanceIdentifier<Node> iid = hcm.getInstanceIdentifier(connection);
+                if (iid != null) {
+                    LOG.warn("Connection to device {} already exists. Plugin does not allow multiple connections "
+                                    + "to same device, hence dropping the request {}", connection, hwvtepGlobal);
+                } else {
+                    try {
+                        hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(node.getNodeId()), hwvtepGlobal);
+                    } catch (UnknownHostException e) {
+                        LOG.warn("Failed to connect to OVSDB node", e);
+                    }
+                }
+            }
+        }
+
+    }
+
+    private void updateConnections(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node updated = getUpdated(mod);
+            if (updated != null) {
+                Node original = getOriginal(mod);
+                HwvtepGlobalAugmentation hgUpdated = updated.getAugmentation(HwvtepGlobalAugmentation.class);
+                HwvtepGlobalAugmentation hgOriginal = original.getAugmentation(HwvtepGlobalAugmentation.class);
+                OvsdbClient client = hcm.getClient(hgUpdated.getConnectionInfo());
+                if (client == null) {
+                    try {
+                        hcm.disconnect(hgOriginal);
+                        hcm.connect(HwvtepSouthboundMapper.createInstanceIdentifier(original.getNodeId()), hgUpdated);
+                    } catch (UnknownHostException e) {
+                        LOG.warn("Failed to update connection on OVSDB Node", e);
+                    }
+                }
+            }
+        }
+
+    }
+
+    private void updateData(Collection<DataTreeModification<Node>> changes) {
+        /* TODO: 
+         * Get connection instances for each change
+         * Update data for each connection
+         * Requires Command patterns. TBD.
+         */
+        
+    }
+
+    private void disconnect(Collection<DataTreeModification<Node>> changes) {
+        for (DataTreeModification<Node> change : changes) {
+            final InstanceIdentifier<Node> key = change.getRootPath().getRootIdentifier();
+            final DataObjectModification<Node> mod = change.getRootNode();
+            Node deleted = getRemoved(mod);
+            if (deleted != null) {
+                HwvtepGlobalAugmentation hgDeleted = deleted.getAugmentation(HwvtepGlobalAugmentation.class);
+                try {
+                    hcm.disconnect(hgDeleted);
+                } catch (UnknownHostException e) {
+                    LOG.warn("Failed to disconnect OVSDB Node", e);
+                }
+            }
+        }
+    }
+
+    private Node getCreated(DataObjectModification<Node> mod) {
+        if((mod.getModificationType() == ModificationType.WRITE) 
+                        && (mod.getDataBefore() == null)){
+            return mod.getDataAfter();
+        }
+        return null;
+    }
+
+    private Node getRemoved(DataObjectModification<Node> mod) {
+        if(mod.getModificationType() == ModificationType.DELETE){
+            return mod.getDataBefore();
+        }
+        return null;
+    }
+
+    private Node getUpdated(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataAfter();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataAfter();
+                }
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    private Node getOriginal(DataObjectModification<Node> mod) {
+        Node node = null;
+        switch(mod.getModificationType()) {
+            case SUBTREE_MODIFIED:
+                node = mod.getDataBefore();
+                break;
+            case WRITE:
+                if(mod.getDataBefore() !=  null) {
+                    node = mod.getDataBefore();
+                }
+                break;
+            case DELETE:
+                node = mod.getDataBefore();
+                break;
+            default:
+                break;
+        }
+        return node;
+    }
+
+    private InstanceIdentifier<Node> getWildcardPath() {
+        InstanceIdentifier<Node> path = InstanceIdentifier
+                        .create(NetworkTopology.class)
+                        .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+                        .child(Node.class);
+        return path;
+    }
+}
index 104ee10438cd4dcf7385f0b60cba4c2136492b77..f73a0be23c60cfd66c0b2bab4d7f4fc23e2bc6ae 100644 (file)
@@ -28,7 +28,7 @@ public class HwvtepMonitorCallback implements MonitorCallBack {
 
     @Override
     public void update(TableUpdates result, DatabaseSchema dbSchema) {
-        LOG.debug("result: {} dbSchema: {}",result,dbSchema);
+        LOG.trace("result: {} dbSchema: {}",result,dbSchema.getName());
         txInvoker.invoke(new HwvtepOperationalCommandAggregator(key, result, dbSchema));
         LOG.trace("update exit");
     }
index 77cbcdb8a4a7be6aa96beb8dd54a3b6c5fd2bf8b..32be9a22d54146b51f12005e69589e0f9f0a292b 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.ovsdb.hwvtepsouthbound;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
+
 import org.opendaylight.ovsdb.lib.OvsdbClient;
 import org.opendaylight.ovsdb.schema.hardwarevtep.Global;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
@@ -106,6 +108,16 @@ public class HwvtepSouthboundMapper {
         return connectionInfoBuilder.build();
     }
 
+    public static InetAddress createInetAddress(IpAddress ip) throws UnknownHostException {
+        if (ip.getIpv4Address() != null) {
+            return InetAddress.getByName(ip.getIpv4Address().getValue());
+        } else if (ip.getIpv6Address() != null) {
+            return InetAddress.getByName(ip.getIpv6Address().getValue());
+        } else {
+            throw new UnknownHostException("IP Address has no value");
+        }
+    }
+
     public static InstanceIdentifier<Node> getInstanceIdentifier(Global global) {
         InstanceIdentifier<Node> iid = null;
         if (global.getManagersColumn() != null
index 75f944637a7958fe7edc89cc9ec5f56526c72802..622ca0364d4fba724d73d68dad5e121a49f4611a 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipC
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
@@ -52,6 +53,7 @@ public class HwvtepSouthboundProvider implements BindingAwareProvider, AutoClose
     private EntityOwnershipService entityOwnershipService;
     private EntityOwnershipCandidateRegistration registration;
     private HwvtepsbPluginInstanceEntityOwnershipListener providerOwnershipChangeListener;
+    private HwvtepDataChangeListener hwvtepDTListener;
 
     public HwvtepSouthboundProvider(
             EntityOwnershipService entityOwnershipServiceDependency) {
@@ -65,7 +67,7 @@ public class HwvtepSouthboundProvider implements BindingAwareProvider, AutoClose
         db = session.getSALService(DataBroker.class);
         txInvoker = new TransactionInvokerImpl(db);
         cm = new HwvtepConnectionManager(db, txInvoker, entityOwnershipService);
-        //TODO: Add DataChange Listener
+        hwvtepDTListener = new HwvtepDataChangeListener(db, cm);
 
         //Register listener for entityOnwership changes
         providerOwnershipChangeListener =
@@ -75,7 +77,18 @@ public class HwvtepSouthboundProvider implements BindingAwareProvider, AutoClose
         //register instance entity to get the ownership of the provider
         Entity instanceEntity = new Entity(ENTITY_TYPE, ENTITY_TYPE);
         try {
+            Optional<EntityOwnershipState> ownershipStateOpt = entityOwnershipService.getOwnershipState(instanceEntity);
             registration = entityOwnershipService.registerCandidate(instanceEntity);
+            if (ownershipStateOpt.isPresent()) {
+                EntityOwnershipState ownershipState = ownershipStateOpt.get();
+                if (ownershipState.hasOwner() && !ownershipState.isOwner()) {
+                    if (ovsdbConnection == null) {
+                        ovsdbConnection = new OvsdbConnectionService();
+                        ovsdbConnection.registerConnectionListener(cm);
+                        ovsdbConnection.startOvsdbManager(HwvtepSouthboundConstants.DEFAULT_OVSDB_PORT);
+                    }
+                }
+            }
         } catch (CandidateAlreadyRegisteredException e) {
             LOG.warn("HWVTEP Southbound Provider instance entity {} was already "
                     + "registered for {} ownership", instanceEntity, e);
@@ -97,6 +110,10 @@ public class HwvtepSouthboundProvider implements BindingAwareProvider, AutoClose
             providerOwnershipChangeListener.close();
             providerOwnershipChangeListener = null;
         }
+        if(hwvtepDTListener != null) {
+            hwvtepDTListener.close();
+            hwvtepDTListener = null;
+        }
     }
 
     private void initializeHwvtepTopology(LogicalDatastoreType type) {