Added notion of a general Store abstraction and wired it up in ClusterStore.
diff --git a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
index 77a28f5..004f807 100644
--- a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
@@ -12,7 +12,9 @@
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.cluster.ClusterEvent;
 import org.onlab.onos.cluster.ClusterStore;
+import org.onlab.onos.cluster.ClusterStoreDelegate;
 import org.onlab.onos.cluster.ControllerNode;
 import org.onlab.onos.cluster.DefaultControllerNode;
 import org.onlab.onos.cluster.NodeId;
@@ -26,6 +28,8 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import static com.google.common.cache.CacheBuilder.newBuilder;
+import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_ACTIVATED;
+import static org.onlab.onos.cluster.ClusterEvent.Type.INSTANCE_DEACTIVATED;
 import static org.onlab.onos.cluster.ControllerNode.State;
 
 /**
@@ -33,14 +37,15 @@
  */
 @Component(immediate = true)
 @Service
-public class DistributedClusterStore extends AbstractDistributedStore
+public class DistributedClusterStore
+        extends AbstractDistributedStore<ClusterEvent, ClusterStoreDelegate>
         implements ClusterStore {
 
     private IMap<byte[], byte[]> rawNodes;
     private LoadingCache<NodeId, Optional<DefaultControllerNode>> nodes;
 
     private String listenerId;
-    private final MembershipListener listener = new InnerMembershipListener();
+    private final MembershipListener listener = new InternalMembershipListener();
     private final Map<NodeId, State> states = new ConcurrentHashMap<>();
 
     @Activate
@@ -106,11 +111,12 @@
     }
 
     // Adds a new node based on the specified member
-    private synchronized void addMember(Member member) {
+    private synchronized ControllerNode addMember(Member member) {
         DefaultControllerNode node = node(member);
         rawNodes.put(serialize(node.id()), serialize(node));
         nodes.put(node.id(), Optional.of(node));
         states.put(node.id(), State.ACTIVE);
+        return node;
     }
 
     // Creates a controller node descriptor from the Hazelcast member.
@@ -125,18 +131,20 @@
     }
 
     // Interceptor for membership events.
-    private class InnerMembershipListener implements MembershipListener {
+    private class InternalMembershipListener implements MembershipListener {
         @Override
         public void memberAdded(MembershipEvent membershipEvent) {
             log.info("Member {} added", membershipEvent.getMember());
-            addMember(membershipEvent.getMember());
+            ControllerNode node = addMember(membershipEvent.getMember());
+            notifyDelegate(new ClusterEvent(INSTANCE_ACTIVATED, node));
         }
 
         @Override
         public void memberRemoved(MembershipEvent membershipEvent) {
             log.info("Member {} removed", membershipEvent.getMember());
-            states.put(new NodeId(memberAddress(membershipEvent.getMember()).toString()),
-                       State.INACTIVE);
+            NodeId nodeId = new NodeId(memberAddress(membershipEvent.getMember()).toString());
+            states.put(nodeId, State.INACTIVE);
+            notifyDelegate(new ClusterEvent(INSTANCE_DEACTIVATED, getNode(nodeId)));
         }
 
         @Override
diff --git a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
index 92d6880..2a7f67a 100644
--- a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
@@ -13,6 +13,7 @@
 import org.onlab.onos.cluster.ClusterService;
 import org.onlab.onos.cluster.MastershipEvent;
 import org.onlab.onos.cluster.MastershipStore;
+import org.onlab.onos.cluster.MastershipStoreDelegate;
 import org.onlab.onos.cluster.NodeId;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.MastershipRole;
@@ -31,7 +32,8 @@
  */
 @Component(immediate = true)
 @Service
-public class DistributedMastershipStore extends AbstractDistributedStore
+public class DistributedMastershipStore
+        extends AbstractDistributedStore<MastershipEvent, MastershipStoreDelegate>
         implements MastershipStore {
 
     private IMap<byte[], byte[]> rawMasters;
diff --git a/core/store/src/main/java/org/onlab/onos/store/StoreService.java b/core/store/src/main/java/org/onlab/onos/store/common/StoreService.java
similarity index 95%
rename from core/store/src/main/java/org/onlab/onos/store/StoreService.java
rename to core/store/src/main/java/org/onlab/onos/store/common/StoreService.java
index b10cb7e..490183f 100644
--- a/core/store/src/main/java/org/onlab/onos/store/StoreService.java
+++ b/core/store/src/main/java/org/onlab/onos/store/common/StoreService.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store;
+package org.onlab.onos.store.common;
 
 import com.hazelcast.core.HazelcastInstance;
 
diff --git a/core/store/src/main/java/org/onlab/onos/store/package-info.java b/core/store/src/main/java/org/onlab/onos/store/common/package-info.java
similarity index 73%
rename from core/store/src/main/java/org/onlab/onos/store/package-info.java
rename to core/store/src/main/java/org/onlab/onos/store/common/package-info.java
index bea7fb0..cf19812 100644
--- a/core/store/src/main/java/org/onlab/onos/store/package-info.java
+++ b/core/store/src/main/java/org/onlab/onos/store/common/package-info.java
@@ -2,4 +2,4 @@
  * Common abstractions and facilities for implementing distributed store
  * using Hazelcast.
  */
-package org.onlab.onos.store;
+package org.onlab.onos.store.common;
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
index 631c6aa..52e8ed0 100644
--- a/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
@@ -21,6 +21,7 @@
 import org.onlab.onos.net.device.DeviceDescription;
 import org.onlab.onos.net.device.DeviceEvent;
 import org.onlab.onos.net.device.DeviceStore;
+import org.onlab.onos.net.device.DeviceStoreDelegate;
 import org.onlab.onos.net.device.PortDescription;
 import org.onlab.onos.net.provider.ProviderId;
 import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache;
@@ -48,7 +49,8 @@
  */
 @Component(immediate = true)
 @Service
-public class DistributedDeviceStore extends AbstractDistributedStore
+public class DistributedDeviceStore
+        extends AbstractDistributedStore<DeviceEvent, DeviceStoreDelegate>
         implements DeviceStore {
 
     private final Logger log = getLogger(getClass());
diff --git a/core/store/src/main/java/org/onlab/onos/store/impl/AbstractDistributedStore.java b/core/store/src/main/java/org/onlab/onos/store/impl/AbstractDistributedStore.java
index e11dda3..bca585d 100644
--- a/core/store/src/main/java/org/onlab/onos/store/impl/AbstractDistributedStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/impl/AbstractDistributedStore.java
@@ -10,7 +10,10 @@
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.onos.store.StoreService;
+import org.onlab.onos.event.Event;
+import org.onlab.onos.store.AbstractStore;
+import org.onlab.onos.store.StoreDelegate;
+import org.onlab.onos.store.common.StoreService;
 import org.slf4j.Logger;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -20,7 +23,8 @@
  * Abstraction of a distributed store based on Hazelcast.
  */
 @Component(componentAbstract = true)
-public abstract class AbstractDistributedStore {
+public abstract class AbstractDistributedStore<E extends Event, D extends StoreDelegate<E>>
+            extends AbstractStore<E, D> {
 
     protected final Logger log = getLogger(getClass());
 
diff --git a/core/store/src/main/java/org/onlab/onos/store/impl/OptionalCacheLoader.java b/core/store/src/main/java/org/onlab/onos/store/impl/OptionalCacheLoader.java
index 47a42ee..dddd128 100644
--- a/core/store/src/main/java/org/onlab/onos/store/impl/OptionalCacheLoader.java
+++ b/core/store/src/main/java/org/onlab/onos/store/impl/OptionalCacheLoader.java
@@ -2,7 +2,7 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-import org.onlab.onos.store.StoreService;
+import org.onlab.onos.store.common.StoreService;
 
 import com.google.common.base.Optional;
 import com.google.common.cache.CacheLoader;
diff --git a/core/store/src/main/java/org/onlab/onos/store/impl/StoreManager.java b/core/store/src/main/java/org/onlab/onos/store/impl/StoreManager.java
index 82472b7..77463fd 100644
--- a/core/store/src/main/java/org/onlab/onos/store/impl/StoreManager.java
+++ b/core/store/src/main/java/org/onlab/onos/store/impl/StoreManager.java
@@ -21,7 +21,7 @@
 import org.onlab.onos.net.Port;
 import org.onlab.onos.net.PortNumber;
 import org.onlab.onos.net.provider.ProviderId;
-import org.onlab.onos.store.StoreService;
+import org.onlab.onos.store.common.StoreService;
 import org.onlab.onos.store.serializers.DefaultPortSerializer;
 import org.onlab.onos.store.serializers.DeviceIdSerializer;
 import org.onlab.onos.store.serializers.IpPrefixSerializer;