ONOS-2184 VirtualHost CLI and REST api's

Change-Id: If0ebe4268f3161a34223eca58e3f1bdbb8d0c9be
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
index aaedb98..dca328d 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/VirtualNetworkWebResource.java
@@ -21,6 +21,7 @@
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.TenantId;
 import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualHost;
 import org.onosproject.incubator.net.virtual.VirtualLink;
 import org.onosproject.incubator.net.virtual.VirtualNetwork;
 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
@@ -390,6 +391,87 @@
     }
 
     /**
+     * Returns all virtual network hosts in a virtual network.
+     *
+     * @param networkId network identifier
+     * @return 200 OK with set of virtual network hosts
+     * @onos.rsModel VirtualHosts
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{networkId}/hosts")
+    public Response getVirtualHosts(@PathParam("networkId") long networkId) {
+        NetworkId nid = NetworkId.networkId(networkId);
+        Set<VirtualHost> vhosts = vnetService.getVirtualHosts(nid);
+        return ok(encodeArray(VirtualHost.class, "hosts", vhosts)).build();
+    }
+
+    /**
+     * Creates a virtual network host from the JSON input stream.
+     *
+     * @param networkId network identifier
+     * @param stream    virtual host JSON stream
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel VirtualHostPut
+     */
+    @POST
+    @Path("{networkId}/hosts")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response createVirtualHost(@PathParam("networkId") long networkId,
+                                      InputStream stream) {
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            JsonNode specifiedNetworkId = jsonTree.get("networkId");
+            if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
+                throw new IllegalArgumentException(INVALID_FIELD + "networkId");
+            }
+            final VirtualHost vhostReq = codec(VirtualHost.class).decode(jsonTree, this);
+            vnetAdminService.createVirtualHost(vhostReq.networkId(), vhostReq.id(),
+                                               vhostReq.mac(), vhostReq.vlan(),
+                                               vhostReq.location(), vhostReq.ipAddresses());
+            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
+                    .path("vnets").path(specifiedNetworkId.asText())
+                    .path("hosts");
+            return Response
+                    .created(locationBuilder.build())
+                    .build();
+        } catch (IOException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Removes the virtual network host from the JSON input stream.
+     *
+     * @param networkId network identifier
+     * @param stream    virtual host JSON stream
+     * @return 204 NO CONTENT
+     * @onos.rsModel VirtualHost
+     */
+    @DELETE
+    @Path("{networkId}/hosts")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response removeVirtualHost(@PathParam("networkId") long networkId,
+                                      InputStream stream) {
+        try {
+            ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+            JsonNode specifiedNetworkId = jsonTree.get("networkId");
+            if (specifiedNetworkId != null &&
+                    specifiedNetworkId.asLong() != (networkId)) {
+                throw new IllegalArgumentException(INVALID_FIELD + "networkId");
+            }
+            final VirtualHost vhostReq = codec(VirtualHost.class).decode(jsonTree, this);
+            vnetAdminService.removeVirtualHost(vhostReq.networkId(), vhostReq.id());
+        } catch (IOException e) {
+            throw new IllegalArgumentException(e);
+        }
+
+        return Response.noContent().build();
+    }
+
+    /**
      * Get the tenant identifier from the JSON stream.
      *
      * @param stream        TenantId JSON stream
diff --git a/web/api/src/main/resources/definitions/VirtualHost.json b/web/api/src/main/resources/definitions/VirtualHost.json
new file mode 100644
index 0000000..e27d148
--- /dev/null
+++ b/web/api/src/main/resources/definitions/VirtualHost.json
@@ -0,0 +1,60 @@
+{
+  "type": "object",
+  "title": "host",
+  "required": [
+    "networkId",
+    "id",
+    "mac",
+    "vlan",
+    "ipAddresses",
+    "location"
+  ],
+  "properties": {
+    "networkId": {
+      "type": "int64",
+      "description": "Network identifier",
+      "example": 3
+    },
+    "id": {
+      "type": "string",
+      "example": "46:E4:3C:A4:17:C8/-1"
+    },
+    "mac": {
+      "type": "string",
+      "example": "46:E4:3C:A4:17:C8"
+    },
+    "vlan": {
+      "type": "string",
+      "example": "-1"
+    },
+    "ipAddresses": {
+      "type": "array",
+      "xml": {
+        "name": "hosts",
+        "wrapped": true
+      },
+      "items": {
+        "type": "string",
+        "example": "127.0.0.1"
+      }
+    },
+    "location": {
+      "type": "object",
+      "title": "location",
+      "required": [
+        "elementId",
+        "port"
+      ],
+      "properties": {
+        "elementId": {
+          "type": "string",
+          "example": "of:0000000000000002"
+        },
+        "port": {
+          "type": "string",
+          "example": "3"
+        }
+      }
+    }
+  }
+}
diff --git a/web/api/src/main/resources/definitions/VirtualHostPut.json b/web/api/src/main/resources/definitions/VirtualHostPut.json
new file mode 100644
index 0000000..c0b8eba
--- /dev/null
+++ b/web/api/src/main/resources/definitions/VirtualHostPut.json
@@ -0,0 +1,55 @@
+{
+  "type": "object",
+  "title": "host",
+  "required": [
+    "networkId",
+    "mac",
+    "vlan",
+    "ipAddresses",
+    "location"
+  ],
+  "properties": {
+    "networkId": {
+      "type": "int64",
+      "description": "Network identifier",
+      "example": 3
+    },
+    "mac": {
+      "type": "string",
+      "example": "46:E4:3C:A4:17:C8"
+    },
+    "vlan": {
+      "type": "string",
+      "example": "-1"
+    },
+    "ipAddresses": {
+      "type": "array",
+      "xml": {
+        "name": "hosts",
+        "wrapped": true
+      },
+      "items": {
+        "type": "string",
+        "example": "127.0.0.1"
+      }
+    },
+    "location": {
+      "type": "object",
+      "title": "location",
+      "required": [
+        "elementId",
+        "port"
+      ],
+      "properties": {
+        "elementId": {
+          "type": "string",
+          "example": "of:0000000000000002"
+        },
+        "port": {
+          "type": "string",
+          "example": "3"
+        }
+      }
+    }
+  }
+}
diff --git a/web/api/src/main/resources/definitions/VirtualHosts.json b/web/api/src/main/resources/definitions/VirtualHosts.json
new file mode 100644
index 0000000..001867e
--- /dev/null
+++ b/web/api/src/main/resources/definitions/VirtualHosts.json
@@ -0,0 +1,76 @@
+{
+  "type": "object",
+  "title": "hosts",
+  "required": [
+    "hosts"
+  ],
+  "properties": {
+    "hosts": {
+      "type": "array",
+      "xml": {
+        "name": "hosts",
+        "wrapped": true
+      },
+      "items": {
+        "type": "object",
+        "title": "host",
+        "required": [
+          "networkId",
+          "id",
+          "mac",
+          "vlan",
+          "ipAddresses",
+          "location"
+        ],
+        "properties": {
+          "networkId": {
+            "type": "int64",
+            "description": "Network identifier",
+            "example": 3
+          },
+          "id": {
+            "type": "string",
+            "example": "46:E4:3C:A4:17:C8/-1"
+          },
+          "mac": {
+            "type": "string",
+            "example": "46:E4:3C:A4:17:C8"
+          },
+          "vlan": {
+            "type": "string",
+            "example": "-1"
+          },
+          "ipAddresses": {
+            "type": "array",
+            "xml": {
+              "name": "hosts",
+              "wrapped": true
+            },
+            "items": {
+              "type": "string",
+              "example": "127.0.0.1"
+            }
+          },
+          "location": {
+            "type": "object",
+            "title": "location",
+            "required": [
+              "elementId",
+              "port"
+            ],
+            "properties": {
+              "elementId": {
+                "type": "string",
+                "example": "of:0000000000000002"
+              },
+              "port": {
+                "type": "string",
+                "example": "3"
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}