Work toward ONOS-1451: Separate Event Key space per instance

Misc changes and cleanup:
* Added new class OnosInstanceId
* Replace (as appropriate) the string controllerId (and associated methods)
  with the new class OnosInstanceId
* Renaming: Host -> Device
  - Method getDeviceID -> getHostID
  - Changed Host Key ID prefix 'D' to 'H'
  - Few renaming of Host -> Device inside Javadoc

Change-Id: I59c20d68277ecde2f7df4e7097a4a52d5786df1b
diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
index e6e1f82..1194e18 100644
--- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
+++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
@@ -23,6 +23,7 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.onrc.onos.api.registry.ILocalSwitchMastershipListener;
 import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFType;
@@ -116,9 +117,11 @@
     public Map<String, String> getControllerNodeIPs();
 
     /**
-     * Gets the ID of the controller
+     * Gets the unique ID used to identify this ONOS instance in the cluster.
+     *
+     * @return ONOS Instance ID.
      */
-    public String getControllerId();
+    public OnosInstanceId getOnosInstanceId();
 
     /**
      * Add a switch listener
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index e34c958..a502711 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -68,6 +68,7 @@
 import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.core.registry.RegistryException;
 import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.jboss.netty.bootstrap.ServerBootstrap;
 import org.jboss.netty.buffer.ChannelBuffer;
@@ -180,7 +181,7 @@
     protected int workerThreads = 0;
     // The id for this controller node. Should be unique for each controller
     // node in a controller cluster.
-    protected String controllerId = "localhost";
+    private OnosInstanceId onosInstanceId = new OnosInstanceId("localhost");
 
     // The current role of the controller.
     // If the controller isn't configured to support roles, then this is null.
@@ -1648,8 +1649,8 @@
     }
 
     @Override
-    public String getControllerId() {
-        return controllerId;
+    public OnosInstanceId getOnosInstanceId() {
+        return onosInstanceId;
     }
 
     // **************
@@ -1814,18 +1815,18 @@
         log.debug("Number of worker threads set to {}", this.workerThreads);
         String controllerId = configParams.get("controllerid");
         if (controllerId != null) {
-            this.controllerId = controllerId;
+            this.onosInstanceId = new OnosInstanceId(controllerId);
         } else {
             //Try to get the hostname of the machine and use that for controller ID
             try {
                 String hostname = java.net.InetAddress.getLocalHost().getHostName();
-                this.controllerId = hostname;
+                this.onosInstanceId = new OnosInstanceId(hostname);
             } catch (UnknownHostException e) {
                 // Can't get hostname, we'll just use the default
             }
         }
 
-        log.debug("ControllerId set to {}", this.controllerId);
+        log.debug("ControllerId set to {}", this.onosInstanceId);
     }
 
     private void initVendorMessages() {
@@ -1880,7 +1881,7 @@
                     LogMessageDoc.CHECK_CONTROLLER)
     public void startupComponents() {
         try {
-            registryService.registerController(controllerId);
+            registryService.registerController(onosInstanceId.toString());
         } catch (RegistryException e) {
             log.warn("Registry service error: {}", e.getMessage());
         }
diff --git a/src/main/java/net/onrc/onos/core/datastore/topology/KVDevice.java b/src/main/java/net/onrc/onos/core/datastore/topology/KVDevice.java
index aa897be..2e4b138 100644
--- a/src/main/java/net/onrc/onos/core/datastore/topology/KVDevice.java
+++ b/src/main/java/net/onrc/onos/core/datastore/topology/KVDevice.java
@@ -53,26 +53,26 @@
     private TreeSet<byte[]> portIds;
 
     /**
-     * Generate a DeviceID from MAC address.
+     * Generate a HostID from MAC address.
      * <p/>
      * We're assuming MAC address can be an unique identifier for Host.
      *
      * @param mac MAC address
-     * @return DeviceID
+     * @return HostID
      */
-    public static byte[] getDeviceID(final byte[] mac) {
-        return HostEvent.getDeviceID(mac).array();
+    public static byte[] getHostID(final byte[] mac) {
+        return HostEvent.getHostID(mac).array();
     }
 
     /**
-     * Gets the MAC address from DeviceID.
+     * Gets the MAC address from HostID.
      *
-     * @param key DeviceID
+     * @param key HostID
      * @return MAC address
      */
     public static byte[] getMacFromKey(final byte[] key) {
         ByteBuffer keyBuf = ByteBuffer.wrap(key);
-        if (keyBuf.getChar() != 'D') {
+        if (keyBuf.getChar() != 'H') {
             throw new IllegalArgumentException("Invalid Host key");
         }
         byte[] mac = new byte[keyBuf.remaining()];
@@ -98,18 +98,18 @@
     public KVDevice(final byte[] mac, final String namespace) {
         super(DataStoreClient.getClient()
                 .getTable(namespace + DEVICE_TABLE_SUFFIX),
-                getDeviceID(mac), namespace);
+                getHostID(mac), namespace);
 
         this.mac = mac.clone();
         this.portIds = new TreeSet<>(ByteArrayComparator.BYTEARRAY_COMPARATOR);
     }
 
     /**
-     * Gets an instance from DeviceID in default namespace.
+     * Gets an instance from HostID in default namespace.
      * <p/>
      * Note: You need to call `read()` to get the DB content.
      *
-     * @param key DeviceID
+     * @param key HostID
      * @return KVDevice instance
      */
     public static KVDevice createFromKey(final byte[] key) {
@@ -117,11 +117,11 @@
     }
 
     /**
-     * Gets an instance from DeviceID in specified namespace.
+     * Gets an instance from HostID in specified namespace.
      * <p/>
      * Note: You need to call `read()` to get the DB content.
      *
-     * @param key DeviceID
+     * @param key HostID
      * @param namespace namespace to create this object in
      * @return KVDevice instance
      */
@@ -205,9 +205,9 @@
     }
 
     /**
-     * Gets the DeviceID.
+     * Gets the HostID.
      *
-     * @return DeviceID
+     * @return HostID
      */
     public byte[] getId() {
         return getKey();
diff --git a/src/main/java/net/onrc/onos/core/registry/IControllerRegistryService.java b/src/main/java/net/onrc/onos/core/registry/IControllerRegistryService.java
index 5af1ac1..cfc47c8 100644
--- a/src/main/java/net/onrc/onos/core/registry/IControllerRegistryService.java
+++ b/src/main/java/net/onrc/onos/core/registry/IControllerRegistryService.java
@@ -5,6 +5,7 @@
 import java.util.Map;
 
 import net.floodlightcontroller.core.module.IFloodlightService;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 /**
  * A registry service that allows ONOS to register controllers and switches
@@ -81,11 +82,11 @@
     public boolean isClusterLeader();
 
     /**
-     * Get the unique ID used to identify this controller in the cluster.
+     * Gets the unique ID used to identify this ONOS instance in the cluster.
      *
-     * @return controller ID.
+     * @return ONOS Instance ID.
      */
-    public String getControllerId();
+    public OnosInstanceId getOnosInstanceId();
 
     /**
      * Register a controller to the ONOS cluster. Must be called before
diff --git a/src/main/java/net/onrc/onos/core/registry/StandaloneRegistry.java b/src/main/java/net/onrc/onos/core/registry/StandaloneRegistry.java
index 0b552f1..bec8bb4 100644
--- a/src/main/java/net/onrc/onos/core/registry/StandaloneRegistry.java
+++ b/src/main/java/net/onrc/onos/core/registry/StandaloneRegistry.java
@@ -15,6 +15,7 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.onrc.onos.core.registry.web.RegistryWebRoutable;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.apache.commons.lang.NotImplementedException;
 import org.openflow.util.HexString;
@@ -32,7 +33,7 @@
 
     private IRestApiService restApi;
 
-    private String registeredControllerId;
+    private OnosInstanceId onosInstanceId;
     private Map<String, ControlChangeCallback> switchCallbacks;
 
     private long blockTop;
@@ -46,7 +47,7 @@
     @Override
     public void requestControl(long dpid, ControlChangeCallback cb)
             throws RegistryException {
-        if (registeredControllerId == null) {
+        if (onosInstanceId == null) {
             throw new IllegalStateException(
                     "Must register a controller before calling requestControl");
         }
@@ -83,32 +84,32 @@
     }
 
     @Override
-    public String getControllerId() {
-        return registeredControllerId;
+    public OnosInstanceId getOnosInstanceId() {
+        return onosInstanceId;
     }
 
     @Override
     public void registerController(String controllerId)
             throws RegistryException {
-        if (registeredControllerId != null) {
+        if (onosInstanceId != null) {
             throw new RegistryException(
-                    "Controller already registered with id " + registeredControllerId);
+                    "Controller already registered with id " + onosInstanceId);
         }
-        registeredControllerId = controllerId;
+        onosInstanceId = new OnosInstanceId(controllerId);
     }
 
     @Override
     public Collection<String> getAllControllers() throws RegistryException {
-        //List<String> l = new ArrayList<String>();
-        //l.add(registeredControllerId);
-        //return l;
-        return Collections.singletonList(registeredControllerId);
+        if (onosInstanceId == null) {
+            return new ArrayList<String>();
+        }
+        return Collections.singletonList(onosInstanceId.toString());
     }
 
     @Override
     public String getControllerForSwitch(long dpid) throws RegistryException {
         return (switchCallbacks.get(HexString.toHexString(dpid)) == null)
-                ? null : registeredControllerId;
+            ? null : onosInstanceId.toString();
     }
 
     @Override
@@ -120,7 +121,7 @@
             log.debug("Switch _{}", strSwitch);
             List<ControllerRegistryEntry> list =
                     new ArrayList<ControllerRegistryEntry>();
-            list.add(new ControllerRegistryEntry(registeredControllerId, 0));
+            list.add(new ControllerRegistryEntry(onosInstanceId.toString(), 0));
 
             switches.put(strSwitch, list);
         }
diff --git a/src/main/java/net/onrc/onos/core/registry/ZookeeperRegistry.java b/src/main/java/net/onrc/onos/core/registry/ZookeeperRegistry.java
index ce68ec2..fb7b573 100644
--- a/src/main/java/net/onrc/onos/core/registry/ZookeeperRegistry.java
+++ b/src/main/java/net/onrc/onos/core/registry/ZookeeperRegistry.java
@@ -22,6 +22,7 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.onrc.onos.core.registry.web.RegistryWebRoutable;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.curator.RetryPolicy;
@@ -60,7 +61,7 @@
 
     private static final Logger log = LoggerFactory.getLogger(ZookeeperRegistry.class);
 
-    private String controllerId;
+    private OnosInstanceId onosInstanceId;
 
     private IRestApiService restApi;
 
@@ -255,7 +256,7 @@
             throws RegistryException {
         log.info("Requesting control for {}", HexString.toHexString(dpid));
 
-        if (controllerId == null) {
+        if (onosInstanceId == null) {
             throw new IllegalStateException("Must register a controller before"
                     + " calling requestControl");
         }
@@ -270,7 +271,8 @@
         String latchPath = SWITCH_LATCHES_PATH + "/" + dpidStr;
 
         LeaderLatch latch =
-                new LeaderLatch(curatorFrameworkClient, latchPath, controllerId);
+            new LeaderLatch(curatorFrameworkClient, latchPath,
+                            onosInstanceId.toString());
         SwitchLeaderListener listener = new SwitchLeaderListener(dpidStr);
         latch.addListener(listener);
 
@@ -348,8 +350,8 @@
     }
 
     @Override
-    public String getControllerId() {
-        return controllerId;
+    public OnosInstanceId getOnosInstanceId() {
+        return onosInstanceId;
     }
 
     @Override
@@ -369,18 +371,18 @@
 
     @Override
     public void registerController(String id) throws RegistryException {
-        if (controllerId != null) {
+        if (onosInstanceId != null) {
             throw new RegistryException(
-                    "Controller already registered with id " + controllerId);
+                    "Controller already registered with id " + onosInstanceId);
         }
 
-        controllerId = id;
+        onosInstanceId = new OnosInstanceId(id);
 
         try {
             ServiceInstance<ControllerService> thisInstance =
                     ServiceInstance.<ControllerService>builder()
                     .name(CONTROLLER_SERVICE_NAME)
-                    .payload(new ControllerService(controllerId))
+                    .payload(new ControllerService(onosInstanceId.toString()))
                     .build();
 
             serviceDiscovery.registerService(thisInstance);
@@ -646,12 +648,13 @@
         // NOTE: We have to do it here, because during the init stage
         // we don't know the Controller ID.
         //
-        if (controllerId == null) {
-            log.error("Error on startup: unknown ControllerId");
+        if (onosInstanceId == null) {
+            log.error("Error on startup: unknown ONOS Instance ID");
+            return;
         }
         clusterLeaderLatch = new LeaderLatch(curatorFrameworkClient,
                 CLUSTER_LEADER_PATH,
-                controllerId);
+                onosInstanceId.toString());
         clusterLeaderListener = new ClusterLeaderListener();
         clusterLeaderLatch.addListener(clusterLeaderListener);
         try {
diff --git a/src/main/java/net/onrc/onos/core/topology/Host.java b/src/main/java/net/onrc/onos/core/topology/Host.java
index 71ede78..05849c5 100644
--- a/src/main/java/net/onrc/onos/core/topology/Host.java
+++ b/src/main/java/net/onrc/onos/core/topology/Host.java
@@ -16,27 +16,27 @@
 @JsonSerialize(using = HostSerializer.class)
 public interface Host extends ITopologyElement {
     /**
-     * Get the device MAC address.
+     * Gets the Host MAC address.
      *
-     * @return the device MAC address.
+     * @return the Host MAC address.
      */
     public MACAddress getMacAddress();
 
     /**
-     * Get the device attachment points.
+     * Gets the Host attachment points.
      * <p/>
      * TODO: There is only 1 attachment point right now.
      * TODO: Add requirement for Iteration order? Latest observed port first.
      *
-     * @return the device attachment points.
+     * @return the Host attachment points.
      */
     public Iterable<Port> getAttachmentPoints();
 
     /**
-     * Get the device last seen time.
+     * Gest the Host last seen time.
      * <p/>
      *
-     * @return the device last seen time. (UTC in ms)
+     * @return the Host last seen time. (UTC in ms)
      */
     public long getLastSeenTime();
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/HostEvent.java b/src/main/java/net/onrc/onos/core/topology/HostEvent.java
index c35764e..ebaf688 100644
--- a/src/main/java/net/onrc/onos/core/topology/HostEvent.java
+++ b/src/main/java/net/onrc/onos/core/topology/HostEvent.java
@@ -18,7 +18,7 @@
  * <p/>
  * Host event differ from other events.
  * Host Event represent add/remove of attachmentPoint.
- * Not add/remove of the DeviceObject itself.
+ * Not add/remove of the Host Object itself.
  * <p/>
  * Multiple attachmentPoints can be specified to batch events into 1 object.
  * Each should be treated as independent events.
@@ -146,16 +146,16 @@
     }
 
     // Assuming mac is unique cluster-wide
-    public static ByteBuffer getDeviceID(final byte[] mac) {
+    public static ByteBuffer getHostID(final byte[] mac) {
         return (ByteBuffer) ByteBuffer.allocate(2 + mac.length)
-                .putChar('D').put(mac).flip();
+                .putChar('H').put(mac).flip();
     }
 
     public byte[] getID() {
-        return getDeviceID(mac.toBytes()).array();
+        return getHostID(mac.toBytes()).array();
     }
 
     public ByteBuffer getIDasByteBuffer() {
-        return getDeviceID(mac.toBytes());
+        return getHostID(mac.toBytes());
     }
 }
diff --git a/src/main/java/net/onrc/onos/core/topology/HostImpl.java b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
index 3120015..289e1e0 100644
--- a/src/main/java/net/onrc/onos/core/topology/HostImpl.java
+++ b/src/main/java/net/onrc/onos/core/topology/HostImpl.java
@@ -77,7 +77,7 @@
      */
     @Override
     public String getType() {
-        // FIXME assuming device is always in packet layer for now.
+        // FIXME assuming Host is always in packet layer for now.
         return TopologyElement.TYPE_PACKET_LAYER;
     }
 
diff --git a/src/main/java/net/onrc/onos/core/topology/MastershipEvent.java b/src/main/java/net/onrc/onos/core/topology/MastershipEvent.java
index 5ed36a3..5668e2f 100644
--- a/src/main/java/net/onrc/onos/core/topology/MastershipEvent.java
+++ b/src/main/java/net/onrc/onos/core/topology/MastershipEvent.java
@@ -7,6 +7,7 @@
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.onrc.onos.core.topology.web.serializers.MastershipEventSerializer;
 import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.apache.commons.lang.Validate;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
@@ -22,7 +23,7 @@
 public class MastershipEvent extends TopologyElement<MastershipEvent> {
 
     private final Dpid dpid;
-    private final String onosInstanceId;
+    private final OnosInstanceId onosInstanceId;
     private final Role role;
 
     /**
@@ -42,7 +43,8 @@
      * @param onosInstanceId the ONOS Instance ID
      * @param role the ONOS instance role for the switch.
      */
-    public MastershipEvent(Dpid dpid, String onosInstanceId, Role role) {
+    public MastershipEvent(Dpid dpid, OnosInstanceId onosInstanceId,
+                           Role role) {
         Validate.notNull(dpid);
         Validate.notNull(onosInstanceId);
 
@@ -77,7 +79,7 @@
      *
      * @return the ONOS Instance ID.
      */
-    public String getOnosInstanceId() {
+    public OnosInstanceId getOnosInstanceId() {
         return onosInstanceId;
     }
 
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
index 3b6a5e9..cb7c54f 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
@@ -397,7 +397,8 @@
     public void controllerRoleChanged(Dpid dpid, Role role) {
         log.debug("Local switch controller mastership role changed: dpid = {} role = {}", dpid, role);
         MastershipEvent mastershipEvent =
-            new MastershipEvent(dpid, registryService.getControllerId(), role);
+            new MastershipEvent(dpid, registryService.getOnosInstanceId(),
+                                role);
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
@@ -414,7 +415,8 @@
         Role role = Role.SLAVE;         // TODO: Should be Role.UNKNOWN
 
         MastershipEvent mastershipEvent =
-            new MastershipEvent(dpid, registryService.getControllerId(), role);
+            new MastershipEvent(dpid, registryService.getOnosInstanceId(),
+                                role);
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
diff --git a/src/main/java/net/onrc/onos/core/topology/web/serializers/MastershipEventSerializer.java b/src/main/java/net/onrc/onos/core/topology/web/serializers/MastershipEventSerializer.java
index 296c605..d8c8da7 100644
--- a/src/main/java/net/onrc/onos/core/topology/web/serializers/MastershipEventSerializer.java
+++ b/src/main/java/net/onrc/onos/core/topology/web/serializers/MastershipEventSerializer.java
@@ -48,7 +48,7 @@
         jsonGenerator.writeStringField("dpid",
                                        mastershipEvent.getDpid().toString());
         jsonGenerator.writeStringField("onosInstanceId",
-                                       mastershipEvent.getOnosInstanceId());
+                                       mastershipEvent.getOnosInstanceId().toString());
         jsonGenerator.writeStringField("role",
                                        mastershipEvent.getRole().name());
         jsonGenerator.writeObjectFieldStart("stringAttributes");
diff --git a/src/main/java/net/onrc/onos/core/util/OnosInstanceId.java b/src/main/java/net/onrc/onos/core/util/OnosInstanceId.java
new file mode 100644
index 0000000..34e370a
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/util/OnosInstanceId.java
@@ -0,0 +1,47 @@
+package net.onrc.onos.core.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * The class representing an ONOS Instance ID.
+ *
+ * This class is immutable.
+ */
+public final class OnosInstanceId {
+    private final String id;
+
+    /**
+     * Constructor from a string value.
+     *
+     * @param id the value to use.
+     */
+    public OnosInstanceId(String id) {
+        this.id = checkNotNull(id);
+        checkArgument(!id.isEmpty(), "Empty ONOS Instance ID");
+    }
+
+    @Override
+    public int hashCode() {
+        return id.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (!(obj instanceof OnosInstanceId)) {
+            return false;
+        }
+
+        OnosInstanceId that = (OnosInstanceId) obj;
+        return this.id.equals(that.id);
+    }
+
+    @Override
+    public String toString() {
+        return id;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
index 47b2349..4ab832e 100644
--- a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
@@ -56,6 +56,7 @@
 import net.onrc.onos.core.util.IPv6;
 import net.onrc.onos.core.util.IPv6Net;
 import net.onrc.onos.core.util.LinkTuple;
+import net.onrc.onos.core.util.OnosInstanceId;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.Switch;
 import net.onrc.onos.core.util.SwitchPort;
@@ -201,18 +202,19 @@
         kryo.register(LinkTuple.class);
 
         // New data model-related classes
+        kryo.register(AdminStatus.class);
+        kryo.register(ConcurrentHashMap.class);
+        kryo.register(ConfigState.class);
         kryo.register(HostEvent.class);
         kryo.register(LinkedList.class);
         kryo.register(LinkEvent.class);
         kryo.register(MastershipEvent.class);
+        kryo.register(OnosInstanceId.class);
         kryo.register(PortEvent.class);
         kryo.register(Role.class);
         kryo.register(SwitchEvent.class);
-        kryo.register(TopologyEvent.class);
         kryo.register(TopologyElement.class);
-        kryo.register(ConcurrentHashMap.class);
-        kryo.register(ConfigState.class);
-        kryo.register(AdminStatus.class);
+        kryo.register(TopologyEvent.class);
 
         // Intent-related classes
         kryo.register(Path.class);
diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
index dec61fd..31e57c4 100644
--- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
+++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
@@ -44,6 +44,7 @@
 import net.floodlightcontroller.core.util.ListenerDispatcher;
 import net.onrc.onos.api.registry.ILocalSwitchMastershipListener;
 import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFPacketIn;
@@ -269,8 +270,8 @@
     }
 
     @Override
-    public String getControllerId() {
-        return "localhost";
+    public OnosInstanceId getOnosInstanceId() {
+        return new OnosInstanceId("localhost");
     }
 
     @Override
diff --git a/src/test/java/net/onrc/onos/core/registry/StandaloneRegistryTest.java b/src/test/java/net/onrc/onos/core/registry/StandaloneRegistryTest.java
index 6eb6687..88a1177 100644
--- a/src/test/java/net/onrc/onos/core/registry/StandaloneRegistryTest.java
+++ b/src/test/java/net/onrc/onos/core/registry/StandaloneRegistryTest.java
@@ -18,6 +18,7 @@
 
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.junit.After;
 import org.junit.Before;
@@ -185,25 +186,26 @@
     }
 
     /**
-     * Test if {@link StandaloneRegistry#getControllerId()} can return correct ID.
+     * Test if {@link StandaloneRegistry#getOnosInstanceId()} can return
+     * correct ID.
      *
      * @throws RegistryException
      */
     @Test
-    public void testGetControllerId() throws RegistryException {
+    public void testGetOnosInstanceId() throws RegistryException {
         String controllerIdToRegister = "test";
 
         // try before controller is registered
-        String controllerId = registry.getControllerId();
-        assertNull(controllerId);
+        OnosInstanceId onosInstanceId = registry.getOnosInstanceId();
+        assertNull(onosInstanceId);
 
         // register
         registry.registerController(controllerIdToRegister);
 
-        // call getControllerId and verify
-        controllerId = registry.getControllerId();
-        assertNotNull(controllerId);
-        assertEquals(controllerIdToRegister, controllerId);
+        // call getOnosInstanceId and verify
+        onosInstanceId = registry.getOnosInstanceId();
+        assertNotNull(onosInstanceId);
+        assertEquals(controllerIdToRegister, onosInstanceId.toString());
     }
 
     /**
diff --git a/src/test/java/net/onrc/onos/core/registry/ZookeeperRegistryTest.java b/src/test/java/net/onrc/onos/core/registry/ZookeeperRegistryTest.java
index ca56736..5490162 100644
--- a/src/test/java/net/onrc/onos/core/registry/ZookeeperRegistryTest.java
+++ b/src/test/java/net/onrc/onos/core/registry/ZookeeperRegistryTest.java
@@ -9,6 +9,7 @@
 import net.floodlightcontroller.test.FloodlightTestCase;
 import net.onrc.onos.core.registry.StandaloneRegistryTest.LoggingCallback;
 import net.onrc.onos.core.registry.ZookeeperRegistry.SwitchLeaderListener;
+import net.onrc.onos.core.util.OnosInstanceId;
 
 import org.apache.curator.RetryPolicy;
 import org.apache.curator.framework.CuratorFramework;
@@ -115,25 +116,26 @@
     }
 
     /**
-     * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
+     * Test if {@link ZookeeperRegistry#getOnosInstanceId()} correctly returns
+     * registered ID.
      *
      * @throws Exception
      */
     @Test
-    public void testGetControllerId() throws Exception {
+    public void testGetOnosInstanceId() throws Exception {
         String controllerIdToRegister = "controller1";
 
         // try before controller is registered
-        String controllerId = registry.getControllerId();
-        assertNull(controllerId);
+        OnosInstanceId onosInstanceId = registry.getOnosInstanceId();
+        assertNull(onosInstanceId);
 
         // register
         registry.registerController(controllerIdToRegister);
 
-        // call getControllerId and verify
-        controllerId = registry.getControllerId();
-        assertNotNull(controllerId);
-        assertEquals(controllerIdToRegister, controllerId);
+        // call getOnosInstanceId and verify
+        onosInstanceId = registry.getOnosInstanceId();
+        assertNotNull(onosInstanceId);
+        assertEquals(controllerIdToRegister, onosInstanceId.toString());
     }
 
     /**
diff --git a/src/test/java/net/onrc/onos/core/topology/TopologyManagerTest.java b/src/test/java/net/onrc/onos/core/topology/TopologyManagerTest.java
index 79dfc89..ae0a936 100644
--- a/src/test/java/net/onrc/onos/core/topology/TopologyManagerTest.java
+++ b/src/test/java/net/onrc/onos/core/topology/TopologyManagerTest.java
@@ -22,6 +22,7 @@
 import net.onrc.onos.core.metrics.OnosMetrics;
 import net.onrc.onos.core.registry.IControllerRegistryService;
 import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.OnosInstanceId;
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 import net.onrc.onos.core.util.TestUtils;
@@ -277,7 +278,8 @@
 
         // Generate a new Switch Mastership event
         Dpid dpid = new Dpid(100L);
-        String onosInstanceId = "ONOS-Test-Instance-ID";
+        OnosInstanceId onosInstanceId =
+            new OnosInstanceId("ONOS-Test-Instance-ID");
         Role role = Role.MASTER;
         MastershipEvent mastershipEvent =
             new MastershipEvent(dpid, onosInstanceId, role);
@@ -303,7 +305,8 @@
 
         // Generate a new Switch Mastership event
         Dpid dpid = new Dpid(100L);
-        String onosInstanceId = "ONOS-Test-Instance-ID";
+        OnosInstanceId onosInstanceId =
+            new OnosInstanceId("ONOS-Test-Instance-ID");
         Role role = Role.MASTER;
         MastershipEvent mastershipEvent =
             new MastershipEvent(dpid, onosInstanceId, role);
diff --git a/src/test/java/net/onrc/onos/core/util/OnosInstanceIdTest.java b/src/test/java/net/onrc/onos/core/util/OnosInstanceIdTest.java
new file mode 100644
index 0000000..bec3cd8
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/util/OnosInstanceIdTest.java
@@ -0,0 +1,79 @@
+package net.onrc.onos.core.util;
+
+import org.junit.Test;
+
+import static net.onrc.onos.core.util.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Tests for class {@link OnosInstanceId}.
+ */
+public class OnosInstanceIdTest {
+    /**
+     * Tests the immutability of {@link OnosInstanceId}.
+     */
+    @Test
+    public void testImmutable() {
+        assertThatClassIsImmutable(OnosInstanceId.class);
+    }
+
+    /**
+     * Tests valid class constructor for a string.
+     */
+    @Test
+    public void testConstructorForString() {
+        OnosInstanceId id = new OnosInstanceId("ONOS-ID");
+        assertEquals(id.toString(), "ONOS-ID");
+    }
+
+    /**
+     * Tests invalid class constructor for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidConstructorNullString() {
+        OnosInstanceId id = new OnosInstanceId(null);
+    }
+
+    /**
+     * Tests invalid class constructor for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidConstructors() {
+        // Check constructor for invalid ID: empty string
+        OnosInstanceId id = new OnosInstanceId("");
+    }
+
+    /**
+     * Tests equality of {@link OnosInstanceId}.
+     */
+    @Test
+    public void testEquality() {
+        OnosInstanceId id1 = new OnosInstanceId("ONOS-ID");
+        OnosInstanceId id2 = new OnosInstanceId("ONOS-ID");
+
+        assertThat(id1, is(id2));
+    }
+
+    /**
+     * Tests non-equality of {@link OnosInstanceId}.
+     */
+    @Test
+    public void testNonEquality() {
+        OnosInstanceId id1 = new OnosInstanceId("ONOS-ID1");
+        OnosInstanceId id2 = new OnosInstanceId("ONOS-ID2");
+
+        assertThat(id1, is(not(id2)));
+    }
+
+    /**
+     * Tests object string representation.
+     */
+    @Test
+    public void testToString() {
+        OnosInstanceId id = new OnosInstanceId("ONOS-ID");
+        assertEquals("ONOS-ID", id.toString());
+    }
+}