Extend host structures to store multiple locations

Also update host location format in CLI and REST API

Change-Id: I0fbd655f642627dd3eb8a2925f83a3ee016fe4aa
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java
index b5f9b02..233d61d 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/HostCodec.java
@@ -47,7 +47,12 @@
             jsonIpAddresses.add(ipAddress.toString());
         }
         result.set("ipAddresses", jsonIpAddresses);
-        result.set("location", locationCodec.encode(host.location(), context));
+
+        final ArrayNode jsonLocations = result.putArray("locations");
+        for (final HostLocation location : host.locations()) {
+            jsonLocations.add(locationCodec.encode(location, context));
+        }
+        result.set("locations", jsonLocations);
 
         return annotate(result, host, context);
     }
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/VirtualHostCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/VirtualHostCodec.java
index 05ce81e..d6a7c80 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/VirtualHostCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/VirtualHostCodec.java
@@ -49,7 +49,7 @@
     static final String MAC_ADDRESS = "mac";
     static final String VLAN = "vlan";
     static final String IP_ADDRESSES = "ipAddresses";
-    static final String HOST_LOCATION = "location";
+    static final String HOST_LOCATION = "locations";
 
     private static final String NULL_OBJECT_MSG = "VirtualHost cannot be null";
     private static final String MISSING_MEMBER_MSG = " member is required in VirtualHost";
@@ -71,7 +71,12 @@
             jsonIpAddresses.add(ipAddress.toString());
         }
         result.set(IP_ADDRESSES, jsonIpAddresses);
-        result.set(HOST_LOCATION, locationCodec.encode(vHost.location(), context));
+
+        final ArrayNode jsonLocations = result.putArray("locations");
+        for (final HostLocation location : vHost.locations()) {
+            jsonLocations.add(locationCodec.encode(location, context));
+        }
+        result.set("locations", jsonLocations);
 
         return result;
     }
@@ -85,10 +90,15 @@
         NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
         MacAddress mac = MacAddress.valueOf(json.get("mac").asText());
         VlanId vlanId = VlanId.vlanId((short) json.get("vlan").asInt(VlanId.UNTAGGED));
-        JsonNode locationNode = json.get("location");
-        PortNumber portNumber = PortNumber.portNumber(locationNode.get("port").asText());
-        DeviceId deviceId = DeviceId.deviceId(locationNode.get("elementId").asText());
-        HostLocation hostLocation = new HostLocation(deviceId, portNumber, 0);
+
+        Set<HostLocation> locations = new HashSet<>();
+        JsonNode locationNodes = json.get("locations");
+        locationNodes.forEach(locationNode -> {
+            PortNumber portNumber = PortNumber.portNumber(locationNode.get("port").asText());
+            DeviceId deviceId = DeviceId.deviceId(locationNode.get("elementId").asText());
+            locations.add(new HostLocation(deviceId, portNumber, 0));
+        });
+
         HostId id = HostId.hostId(mac, vlanId);
 
         Iterator<JsonNode> ipStrings = json.get("ipAddresses").elements();
@@ -97,7 +107,7 @@
             ips.add(IpAddress.valueOf(ipStrings.next().asText()));
         }
 
-        return new DefaultVirtualHost(nId, id, mac, vlanId, hostLocation, ips);
+        return new DefaultVirtualHost(nId, id, mac, vlanId, locations, ips);
     }
 
     /**
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/VirtualHostCodecTest.java b/core/common/src/test/java/org/onosproject/codec/impl/VirtualHostCodecTest.java
index 1774242..661a1f3 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/VirtualHostCodecTest.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/VirtualHostCodecTest.java
@@ -81,9 +81,9 @@
                    is(TEST_MAC_ADDRESS));
         assertThat(node.get(VirtualHostCodec.VLAN).asInt(),
                    is((int) TEST_VLAN_ID));
-        assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get("elementId").asText(),
+        assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get(0).get("elementId").asText(),
                    is(location.deviceId().toString()));
-        assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get("port").asLong(),
+        assertThat(node.get(VirtualHostCodec.HOST_LOCATION).get(0).get("port").asLong(),
                    is(location.port().toLong()));
 
         JsonNode jsonIps = node.get(VirtualHostCodec.IP_ADDRESSES);
diff --git a/core/common/src/test/resources/org/onosproject/codec/impl/VirtualHost.json b/core/common/src/test/resources/org/onosproject/codec/impl/VirtualHost.json
index ab5a81b..818ce0b 100644
--- a/core/common/src/test/resources/org/onosproject/codec/impl/VirtualHost.json
+++ b/core/common/src/test/resources/org/onosproject/codec/impl/VirtualHost.json
@@ -6,8 +6,10 @@
     "1.1.1.1",
     "2.2.2.2"
   ],
-  "location": {
-    "elementId": "of:d1",
-    "port": "1"
-  }
+  "locations": [
+    {
+      "elementId": "of:d1",
+      "port": "1"
+    }
+  ]
 }