Claudine Chiu
Committed by Gerrit Code Review

ONOS-2184 VirtualHost CLI and REST api's

Change-Id: If0ebe4268f3161a34223eca58e3f1bdbb8d0c9be
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.cli.net.vnet;
18 +
19 +import org.apache.karaf.shell.commands.Argument;
20 +import org.apache.karaf.shell.commands.Command;
21 +import org.apache.karaf.shell.commands.Option;
22 +import org.onlab.packet.IpAddress;
23 +import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.VlanId;
25 +import org.onosproject.cli.AbstractShellCommand;
26 +import org.onosproject.incubator.net.virtual.NetworkId;
27 +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
28 +import org.onosproject.net.DeviceId;
29 +import org.onosproject.net.HostId;
30 +import org.onosproject.net.HostLocation;
31 +import org.onosproject.net.PortNumber;
32 +
33 +import java.util.Arrays;
34 +import java.util.HashSet;
35 +import java.util.Set;
36 +
37 +/**
38 + * Creates a new virtual host.
39 + */
40 +@Command(scope = "onos", name = "vnet-create-host",
41 + description = "Creates a new virtual host in a network.")
42 +public class VirtualHostCreateCommand extends AbstractShellCommand {
43 +
44 + @Argument(index = 0, name = "networkId", description = "Network ID",
45 + required = true, multiValued = false)
46 + Long networkId = null;
47 +
48 + @Argument(index = 1, name = "mac", description = "Mac address",
49 + required = true, multiValued = false)
50 + String mac = null;
51 +
52 + @Argument(index = 2, name = "vlan", description = "Vlan",
53 + required = true, multiValued = false)
54 + short vlan;
55 +
56 + @Argument(index = 3, name = "hostLocationDeviceId", description = "Host location device ID",
57 + required = true, multiValued = false)
58 + String hostLocationDeviceId;
59 +
60 + @Argument(index = 4, name = "hostLocationPortNumber", description = "Host location port number",
61 + required = true, multiValued = false)
62 + long hostLocationPortNumber;
63 +
64 + // ip addresses
65 + @Option(name = "--hostIp", description = "Host IP addresses. Can be specified multiple times.",
66 + required = false, multiValued = true)
67 + protected String[] hostIpStrings;
68 +
69 + @Override
70 + protected void execute() {
71 + VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
72 +
73 + Set<IpAddress> hostIps = new HashSet<>();
74 + if (hostIpStrings != null) {
75 + Arrays.asList(hostIpStrings).stream().forEach(s -> hostIps.add(IpAddress.valueOf(s)));
76 + }
77 + HostLocation hostLocation = new HostLocation(DeviceId.deviceId(hostLocationDeviceId),
78 + PortNumber.portNumber(hostLocationPortNumber),
79 + System.currentTimeMillis());
80 + MacAddress macAddress = MacAddress.valueOf(mac);
81 + VlanId vlanId = VlanId.vlanId(vlan);
82 + service.createVirtualHost(NetworkId.networkId(networkId),
83 + HostId.hostId(macAddress, vlanId), macAddress, vlanId,
84 + hostLocation, hostIps);
85 + print("Virtual host successfully created.");
86 + }
87 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.cli.net.vnet;
18 +
19 +import org.apache.karaf.shell.commands.Argument;
20 +import org.apache.karaf.shell.commands.Command;
21 +import org.onosproject.cli.AbstractShellCommand;
22 +import org.onosproject.incubator.net.virtual.NetworkId;
23 +import org.onosproject.incubator.net.virtual.VirtualHost;
24 +import org.onosproject.incubator.net.virtual.VirtualNetworkService;
25 +
26 +import java.util.ArrayList;
27 +import java.util.List;
28 +
29 +/**
30 + * Lists all virtual hosts for the network ID.
31 + */
32 +@Command(scope = "onos", name = "vnet-hosts",
33 + description = "Lists all virtual hosts in a virtual network.")
34 +public class VirtualHostListCommand extends AbstractShellCommand {
35 +
36 + private static final String FMT_VIRTUAL_HOST =
37 + "id=%s, mac=%s, vlan=%s, location=%s, ips=%s";
38 +
39 + @Argument(index = 0, name = "networkId", description = "Network ID",
40 + required = true, multiValued = false)
41 + Long networkId = null;
42 +
43 + @Override
44 + protected void execute() {
45 + getSortedVirtualHosts().forEach(this::printVirtualHost);
46 + }
47 +
48 + /**
49 + * Returns the list of virtual hosts sorted using the device identifier.
50 + *
51 + * @return virtual host list
52 + */
53 + private List<VirtualHost> getSortedVirtualHosts() {
54 + VirtualNetworkService service = get(VirtualNetworkService.class);
55 +
56 + List<VirtualHost> virtualHosts = new ArrayList<>();
57 + virtualHosts.addAll(service.getVirtualHosts(NetworkId.networkId(networkId)));
58 + return virtualHosts;
59 + }
60 +
61 + /**
62 + * Prints out each virtual host.
63 + *
64 + * @param virtualHost virtual host
65 + */
66 + private void printVirtualHost(VirtualHost virtualHost) {
67 + print(FMT_VIRTUAL_HOST, virtualHost.id().toString(), virtualHost.mac().toString(),
68 + virtualHost.vlan().toString(), virtualHost.location().toString(),
69 + virtualHost.ipAddresses().toString());
70 + }
71 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.cli.net.vnet;
18 +
19 +import org.apache.karaf.shell.commands.Argument;
20 +import org.apache.karaf.shell.commands.Command;
21 +import org.onosproject.cli.AbstractShellCommand;
22 +import org.onosproject.incubator.net.virtual.NetworkId;
23 +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
24 +import org.onosproject.net.HostId;
25 +//import org.onosproject.net.HostId;
26 +
27 +/**
28 + * Removes a virtual host.
29 + */
30 +
31 +@Command(scope = "onos", name = "vnet-remove-host",
32 + description = "Removes a virtual host.")
33 +public class VirtualHostRemoveCommand extends AbstractShellCommand {
34 +
35 + @Argument(index = 0, name = "networkId", description = "Network ID",
36 + required = true, multiValued = false)
37 + Long networkId = null;
38 +
39 + @Argument(index = 1, name = "id", description = "Host ID",
40 + required = true, multiValued = false)
41 + String id = null;
42 +
43 + @Override
44 + protected void execute() {
45 + VirtualNetworkAdminService service = get(VirtualNetworkAdminService.class);
46 + service.removeVirtualHost(NetworkId.networkId(networkId), HostId.hostId(id));
47 + print("Virtual host successfully removed.");
48 + }
49 +}
...@@ -674,6 +674,15 @@ ...@@ -674,6 +674,15 @@
674 <command> 674 <command>
675 <action class="org.onosproject.cli.net.vnet.VirtualPortRemoveCommand"/> 675 <action class="org.onosproject.cli.net.vnet.VirtualPortRemoveCommand"/>
676 </command> 676 </command>
677 + <command>
678 + <action class="org.onosproject.cli.net.vnet.VirtualHostListCommand"/>
679 + </command>
680 + <command>
681 + <action class="org.onosproject.cli.net.vnet.VirtualHostCreateCommand"/>
682 + </command>
683 + <command>
684 + <action class="org.onosproject.cli.net.vnet.VirtualHostRemoveCommand"/>
685 + </command>
677 </command-bundle> 686 </command-bundle>
678 687
679 <bean id="reviewAppNameCompleter" class="org.onosproject.cli.security.ReviewApplicationNameCompleter"/> 688 <bean id="reviewAppNameCompleter" class="org.onosproject.cli.security.ReviewApplicationNameCompleter"/>
......
...@@ -30,6 +30,7 @@ import org.onosproject.core.Application; ...@@ -30,6 +30,7 @@ import org.onosproject.core.Application;
30 import org.onosproject.core.ApplicationId; 30 import org.onosproject.core.ApplicationId;
31 import org.onosproject.incubator.net.virtual.TenantId; 31 import org.onosproject.incubator.net.virtual.TenantId;
32 import org.onosproject.incubator.net.virtual.VirtualDevice; 32 import org.onosproject.incubator.net.virtual.VirtualDevice;
33 +import org.onosproject.incubator.net.virtual.VirtualHost;
33 import org.onosproject.incubator.net.virtual.VirtualLink; 34 import org.onosproject.incubator.net.virtual.VirtualLink;
34 import org.onosproject.incubator.net.virtual.VirtualNetwork; 35 import org.onosproject.incubator.net.virtual.VirtualNetwork;
35 import org.onosproject.incubator.net.virtual.VirtualPort; 36 import org.onosproject.incubator.net.virtual.VirtualPort;
...@@ -141,6 +142,7 @@ public class CodecManager implements CodecService { ...@@ -141,6 +142,7 @@ public class CodecManager implements CodecService {
141 registerCodec(VirtualDevice.class, new VirtualDeviceCodec()); 142 registerCodec(VirtualDevice.class, new VirtualDeviceCodec());
142 registerCodec(VirtualPort.class, new VirtualPortCodec()); 143 registerCodec(VirtualPort.class, new VirtualPortCodec());
143 registerCodec(VirtualLink.class, new VirtualLinkCodec()); 144 registerCodec(VirtualLink.class, new VirtualLinkCodec());
145 + registerCodec(VirtualHost.class, new VirtualHostCodec());
144 registerCodec(MastershipTerm.class, new MastershipTermCodec()); 146 registerCodec(MastershipTerm.class, new MastershipTermCodec());
145 registerCodec(MastershipRole.class, new MastershipRoleCodec()); 147 registerCodec(MastershipRole.class, new MastershipRoleCodec());
146 registerCodec(RoleInfo.class, new RoleInfoCodec()); 148 registerCodec(RoleInfo.class, new RoleInfoCodec());
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import com.fasterxml.jackson.databind.JsonNode;
19 +import com.fasterxml.jackson.databind.node.ArrayNode;
20 +import com.fasterxml.jackson.databind.node.ObjectNode;
21 +import org.onlab.packet.IpAddress;
22 +import org.onlab.packet.MacAddress;
23 +import org.onlab.packet.VlanId;
24 +import org.onosproject.codec.CodecContext;
25 +import org.onosproject.codec.JsonCodec;
26 +import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
27 +import org.onosproject.incubator.net.virtual.NetworkId;
28 +import org.onosproject.incubator.net.virtual.VirtualHost;
29 +import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.HostId;
31 +import org.onosproject.net.HostLocation;
32 +import org.onosproject.net.PortNumber;
33 +
34 +import java.util.HashSet;
35 +import java.util.Iterator;
36 +import java.util.Set;
37 +
38 +import static com.google.common.base.Preconditions.checkNotNull;
39 +import static org.onlab.util.Tools.nullIsIllegal;
40 +
41 +/**
42 + * Codec for the VirtualHost class.
43 + */
44 +public class VirtualHostCodec extends JsonCodec<VirtualHost> {
45 +
46 + // JSON field names
47 + private static final String NETWORK_ID = "networkId";
48 + private static final String HOST_ID = "id";
49 + private static final String MAC_ADDRESS = "mac";
50 + private static final String VLAN = "vlan";
51 + private static final String IP_ADDRESSES = "ipAddresses";
52 + private static final String HOST_LOCATION = "location";
53 +
54 + private static final String NULL_OBJECT_MSG = "VirtualHost cannot be null";
55 + private static final String MISSING_MEMBER_MSG = " member is required in VirtualHost";
56 +
57 + @Override
58 + public ObjectNode encode(VirtualHost vHost, CodecContext context) {
59 + checkNotNull(vHost, NULL_OBJECT_MSG);
60 +
61 + final JsonCodec<HostLocation> locationCodec =
62 + context.codec(HostLocation.class);
63 + final ObjectNode result = context.mapper().createObjectNode()
64 + .put(NETWORK_ID, vHost.networkId().toString())
65 + .put(HOST_ID, vHost.id().toString())
66 + .put(MAC_ADDRESS, vHost.mac().toString())
67 + .put(VLAN, vHost.vlan().toString());
68 +
69 + final ArrayNode jsonIpAddresses = result.putArray(IP_ADDRESSES);
70 + for (final IpAddress ipAddress : vHost.ipAddresses()) {
71 + jsonIpAddresses.add(ipAddress.toString());
72 + }
73 + result.set(IP_ADDRESSES, jsonIpAddresses);
74 + result.set(HOST_LOCATION, locationCodec.encode(vHost.location(), context));
75 +
76 + return result;
77 + }
78 +
79 + @Override
80 + public VirtualHost decode(ObjectNode json, CodecContext context) {
81 + if (json == null || !json.isObject()) {
82 + return null;
83 + }
84 +
85 + NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json)));
86 + MacAddress mac = MacAddress.valueOf(json.get("mac").asText());
87 + VlanId vlanId = VlanId.vlanId((short) json.get("vlan").asInt(VlanId.UNTAGGED));
88 + JsonNode locationNode = json.get("location");
89 + PortNumber portNumber = PortNumber.portNumber(locationNode.get("port").asText());
90 + DeviceId deviceId = DeviceId.deviceId(locationNode.get("elementId").asText());
91 + HostLocation hostLocation = new HostLocation(deviceId, portNumber, 0);
92 + HostId id = HostId.hostId(mac, vlanId);
93 +
94 + Iterator<JsonNode> ipStrings = json.get("ipAddresses").elements();
95 + Set<IpAddress> ips = new HashSet<>();
96 + while (ipStrings.hasNext()) {
97 + ips.add(IpAddress.valueOf(ipStrings.next().asText()));
98 + }
99 +
100 + return new DefaultVirtualHost(nId, id, mac, vlanId, hostLocation, ips);
101 + }
102 +
103 + /**
104 + * Extract member from JSON ObjectNode.
105 + *
106 + * @param key key for which value is needed
107 + * @param json JSON ObjectNode
108 + * @return member value
109 + */
110 + private String extractMember(String key, ObjectNode json) {
111 + return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText();
112 + }
113 +}
...@@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
21 import org.onosproject.incubator.net.virtual.NetworkId; 21 import org.onosproject.incubator.net.virtual.NetworkId;
22 import org.onosproject.incubator.net.virtual.TenantId; 22 import org.onosproject.incubator.net.virtual.TenantId;
23 import org.onosproject.incubator.net.virtual.VirtualDevice; 23 import org.onosproject.incubator.net.virtual.VirtualDevice;
24 +import org.onosproject.incubator.net.virtual.VirtualHost;
24 import org.onosproject.incubator.net.virtual.VirtualLink; 25 import org.onosproject.incubator.net.virtual.VirtualLink;
25 import org.onosproject.incubator.net.virtual.VirtualNetwork; 26 import org.onosproject.incubator.net.virtual.VirtualNetwork;
26 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; 27 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
...@@ -390,6 +391,87 @@ public class VirtualNetworkWebResource extends AbstractWebResource { ...@@ -390,6 +391,87 @@ public class VirtualNetworkWebResource extends AbstractWebResource {
390 } 391 }
391 392
392 /** 393 /**
394 + * Returns all virtual network hosts in a virtual network.
395 + *
396 + * @param networkId network identifier
397 + * @return 200 OK with set of virtual network hosts
398 + * @onos.rsModel VirtualHosts
399 + */
400 + @GET
401 + @Produces(MediaType.APPLICATION_JSON)
402 + @Path("{networkId}/hosts")
403 + public Response getVirtualHosts(@PathParam("networkId") long networkId) {
404 + NetworkId nid = NetworkId.networkId(networkId);
405 + Set<VirtualHost> vhosts = vnetService.getVirtualHosts(nid);
406 + return ok(encodeArray(VirtualHost.class, "hosts", vhosts)).build();
407 + }
408 +
409 + /**
410 + * Creates a virtual network host from the JSON input stream.
411 + *
412 + * @param networkId network identifier
413 + * @param stream virtual host JSON stream
414 + * @return status of the request - CREATED if the JSON is correct,
415 + * BAD_REQUEST if the JSON is invalid
416 + * @onos.rsModel VirtualHostPut
417 + */
418 + @POST
419 + @Path("{networkId}/hosts")
420 + @Consumes(MediaType.APPLICATION_JSON)
421 + @Produces(MediaType.APPLICATION_JSON)
422 + public Response createVirtualHost(@PathParam("networkId") long networkId,
423 + InputStream stream) {
424 + try {
425 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
426 + JsonNode specifiedNetworkId = jsonTree.get("networkId");
427 + if (specifiedNetworkId == null || specifiedNetworkId.asLong() != (networkId)) {
428 + throw new IllegalArgumentException(INVALID_FIELD + "networkId");
429 + }
430 + final VirtualHost vhostReq = codec(VirtualHost.class).decode(jsonTree, this);
431 + vnetAdminService.createVirtualHost(vhostReq.networkId(), vhostReq.id(),
432 + vhostReq.mac(), vhostReq.vlan(),
433 + vhostReq.location(), vhostReq.ipAddresses());
434 + UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
435 + .path("vnets").path(specifiedNetworkId.asText())
436 + .path("hosts");
437 + return Response
438 + .created(locationBuilder.build())
439 + .build();
440 + } catch (IOException e) {
441 + throw new IllegalArgumentException(e);
442 + }
443 + }
444 +
445 + /**
446 + * Removes the virtual network host from the JSON input stream.
447 + *
448 + * @param networkId network identifier
449 + * @param stream virtual host JSON stream
450 + * @return 204 NO CONTENT
451 + * @onos.rsModel VirtualHost
452 + */
453 + @DELETE
454 + @Path("{networkId}/hosts")
455 + @Consumes(MediaType.APPLICATION_JSON)
456 + public Response removeVirtualHost(@PathParam("networkId") long networkId,
457 + InputStream stream) {
458 + try {
459 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
460 + JsonNode specifiedNetworkId = jsonTree.get("networkId");
461 + if (specifiedNetworkId != null &&
462 + specifiedNetworkId.asLong() != (networkId)) {
463 + throw new IllegalArgumentException(INVALID_FIELD + "networkId");
464 + }
465 + final VirtualHost vhostReq = codec(VirtualHost.class).decode(jsonTree, this);
466 + vnetAdminService.removeVirtualHost(vhostReq.networkId(), vhostReq.id());
467 + } catch (IOException e) {
468 + throw new IllegalArgumentException(e);
469 + }
470 +
471 + return Response.noContent().build();
472 + }
473 +
474 + /**
393 * Get the tenant identifier from the JSON stream. 475 * Get the tenant identifier from the JSON stream.
394 * 476 *
395 * @param stream TenantId JSON stream 477 * @param stream TenantId JSON stream
......
1 +{
2 + "type": "object",
3 + "title": "host",
4 + "required": [
5 + "networkId",
6 + "id",
7 + "mac",
8 + "vlan",
9 + "ipAddresses",
10 + "location"
11 + ],
12 + "properties": {
13 + "networkId": {
14 + "type": "int64",
15 + "description": "Network identifier",
16 + "example": 3
17 + },
18 + "id": {
19 + "type": "string",
20 + "example": "46:E4:3C:A4:17:C8/-1"
21 + },
22 + "mac": {
23 + "type": "string",
24 + "example": "46:E4:3C:A4:17:C8"
25 + },
26 + "vlan": {
27 + "type": "string",
28 + "example": "-1"
29 + },
30 + "ipAddresses": {
31 + "type": "array",
32 + "xml": {
33 + "name": "hosts",
34 + "wrapped": true
35 + },
36 + "items": {
37 + "type": "string",
38 + "example": "127.0.0.1"
39 + }
40 + },
41 + "location": {
42 + "type": "object",
43 + "title": "location",
44 + "required": [
45 + "elementId",
46 + "port"
47 + ],
48 + "properties": {
49 + "elementId": {
50 + "type": "string",
51 + "example": "of:0000000000000002"
52 + },
53 + "port": {
54 + "type": "string",
55 + "example": "3"
56 + }
57 + }
58 + }
59 + }
60 +}
1 +{
2 + "type": "object",
3 + "title": "host",
4 + "required": [
5 + "networkId",
6 + "mac",
7 + "vlan",
8 + "ipAddresses",
9 + "location"
10 + ],
11 + "properties": {
12 + "networkId": {
13 + "type": "int64",
14 + "description": "Network identifier",
15 + "example": 3
16 + },
17 + "mac": {
18 + "type": "string",
19 + "example": "46:E4:3C:A4:17:C8"
20 + },
21 + "vlan": {
22 + "type": "string",
23 + "example": "-1"
24 + },
25 + "ipAddresses": {
26 + "type": "array",
27 + "xml": {
28 + "name": "hosts",
29 + "wrapped": true
30 + },
31 + "items": {
32 + "type": "string",
33 + "example": "127.0.0.1"
34 + }
35 + },
36 + "location": {
37 + "type": "object",
38 + "title": "location",
39 + "required": [
40 + "elementId",
41 + "port"
42 + ],
43 + "properties": {
44 + "elementId": {
45 + "type": "string",
46 + "example": "of:0000000000000002"
47 + },
48 + "port": {
49 + "type": "string",
50 + "example": "3"
51 + }
52 + }
53 + }
54 + }
55 +}
1 +{
2 + "type": "object",
3 + "title": "hosts",
4 + "required": [
5 + "hosts"
6 + ],
7 + "properties": {
8 + "hosts": {
9 + "type": "array",
10 + "xml": {
11 + "name": "hosts",
12 + "wrapped": true
13 + },
14 + "items": {
15 + "type": "object",
16 + "title": "host",
17 + "required": [
18 + "networkId",
19 + "id",
20 + "mac",
21 + "vlan",
22 + "ipAddresses",
23 + "location"
24 + ],
25 + "properties": {
26 + "networkId": {
27 + "type": "int64",
28 + "description": "Network identifier",
29 + "example": 3
30 + },
31 + "id": {
32 + "type": "string",
33 + "example": "46:E4:3C:A4:17:C8/-1"
34 + },
35 + "mac": {
36 + "type": "string",
37 + "example": "46:E4:3C:A4:17:C8"
38 + },
39 + "vlan": {
40 + "type": "string",
41 + "example": "-1"
42 + },
43 + "ipAddresses": {
44 + "type": "array",
45 + "xml": {
46 + "name": "hosts",
47 + "wrapped": true
48 + },
49 + "items": {
50 + "type": "string",
51 + "example": "127.0.0.1"
52 + }
53 + },
54 + "location": {
55 + "type": "object",
56 + "title": "location",
57 + "required": [
58 + "elementId",
59 + "port"
60 + ],
61 + "properties": {
62 + "elementId": {
63 + "type": "string",
64 + "example": "of:0000000000000002"
65 + },
66 + "port": {
67 + "type": "string",
68 + "example": "3"
69 + }
70 + }
71 + }
72 + }
73 + }
74 + }
75 + }
76 +}
...@@ -21,6 +21,7 @@ import com.eclipsesource.json.JsonArray; ...@@ -21,6 +21,7 @@ import com.eclipsesource.json.JsonArray;
21 import com.eclipsesource.json.JsonObject; 21 import com.eclipsesource.json.JsonObject;
22 import com.google.common.collect.ImmutableList; 22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableSet; 23 import com.google.common.collect.ImmutableSet;
24 +import com.google.common.collect.Sets;
24 import org.glassfish.jersey.client.ClientProperties; 25 import org.glassfish.jersey.client.ClientProperties;
25 import org.hamcrest.Description; 26 import org.hamcrest.Description;
26 import org.hamcrest.Matchers; 27 import org.hamcrest.Matchers;
...@@ -29,16 +30,21 @@ import org.junit.Before; ...@@ -29,16 +30,21 @@ import org.junit.Before;
29 import org.junit.Test; 30 import org.junit.Test;
30 import org.onlab.osgi.ServiceDirectory; 31 import org.onlab.osgi.ServiceDirectory;
31 import org.onlab.osgi.TestServiceDirectory; 32 import org.onlab.osgi.TestServiceDirectory;
33 +import org.onlab.packet.IpAddress;
34 +import org.onlab.packet.MacAddress;
35 +import org.onlab.packet.VlanId;
32 import org.onlab.rest.BaseResource; 36 import org.onlab.rest.BaseResource;
33 import org.onosproject.codec.CodecService; 37 import org.onosproject.codec.CodecService;
34 import org.onosproject.codec.impl.CodecManager; 38 import org.onosproject.codec.impl.CodecManager;
35 import org.onosproject.incubator.net.virtual.DefaultVirtualDevice; 39 import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
40 +import org.onosproject.incubator.net.virtual.DefaultVirtualHost;
36 import org.onosproject.incubator.net.virtual.DefaultVirtualLink; 41 import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
37 import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork; 42 import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork;
38 import org.onosproject.incubator.net.virtual.DefaultVirtualPort; 43 import org.onosproject.incubator.net.virtual.DefaultVirtualPort;
39 import org.onosproject.incubator.net.virtual.NetworkId; 44 import org.onosproject.incubator.net.virtual.NetworkId;
40 import org.onosproject.incubator.net.virtual.TenantId; 45 import org.onosproject.incubator.net.virtual.TenantId;
41 import org.onosproject.incubator.net.virtual.VirtualDevice; 46 import org.onosproject.incubator.net.virtual.VirtualDevice;
47 +import org.onosproject.incubator.net.virtual.VirtualHost;
42 import org.onosproject.incubator.net.virtual.VirtualLink; 48 import org.onosproject.incubator.net.virtual.VirtualLink;
43 import org.onosproject.incubator.net.virtual.VirtualNetwork; 49 import org.onosproject.incubator.net.virtual.VirtualNetwork;
44 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; 50 import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
...@@ -50,6 +56,8 @@ import org.onosproject.net.DefaultDevice; ...@@ -50,6 +56,8 @@ import org.onosproject.net.DefaultDevice;
50 import org.onosproject.net.DefaultPort; 56 import org.onosproject.net.DefaultPort;
51 import org.onosproject.net.Device; 57 import org.onosproject.net.Device;
52 import org.onosproject.net.DeviceId; 58 import org.onosproject.net.DeviceId;
59 +import org.onosproject.net.HostId;
60 +import org.onosproject.net.HostLocation;
53 import org.onosproject.net.NetTestTools; 61 import org.onosproject.net.NetTestTools;
54 import org.onosproject.net.Port; 62 import org.onosproject.net.Port;
55 import org.onosproject.net.PortNumber; 63 import org.onosproject.net.PortNumber;
...@@ -93,9 +101,8 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -93,9 +101,8 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
93 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class); 101 private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class);
94 private CodecManager codecService; 102 private CodecManager codecService;
95 103
96 - final HashSet<TenantId> tenantIdSet = new HashSet<>(); 104 + private final HashSet<VirtualDevice> vdevSet = new HashSet<>();
97 - final HashSet<VirtualDevice> vdevSet = new HashSet<>(); 105 + private final HashSet<VirtualPort> vportSet = new HashSet<>();
98 - final HashSet<VirtualPort> vportSet = new HashSet<>();
99 106
100 private static final String ID = "networkId"; 107 private static final String ID = "networkId";
101 private static final String TENANT_ID = "tenantId"; 108 private static final String TENANT_ID = "tenantId";
...@@ -104,7 +111,6 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -104,7 +111,6 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
104 private static final String PHYS_DEVICE_ID = "physDeviceId"; 111 private static final String PHYS_DEVICE_ID = "physDeviceId";
105 private static final String PHYS_PORT_NUM = "physPortNum"; 112 private static final String PHYS_PORT_NUM = "physPortNum";
106 113
107 - private final TenantId tenantId1 = TenantId.tenantId("TenantId1");
108 private final TenantId tenantId2 = TenantId.tenantId("TenantId2"); 114 private final TenantId tenantId2 = TenantId.tenantId("TenantId2");
109 private final TenantId tenantId3 = TenantId.tenantId("TenantId3"); 115 private final TenantId tenantId3 = TenantId.tenantId("TenantId3");
110 private final TenantId tenantId4 = TenantId.tenantId("TenantId4"); 116 private final TenantId tenantId4 = TenantId.tenantId("TenantId4");
...@@ -128,11 +134,10 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -128,11 +134,10 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
128 134
129 private final Device dev1 = NetTestTools.device("dev1"); 135 private final Device dev1 = NetTestTools.device("dev1");
130 private final Device dev2 = NetTestTools.device("dev2"); 136 private final Device dev2 = NetTestTools.device("dev2");
131 - private final Device dev21 = NetTestTools.device("dev21");
132 private final Device dev22 = NetTestTools.device("dev22"); 137 private final Device dev22 = NetTestTools.device("dev22");
133 138
134 - Port port1 = new DefaultPort(dev1, portNumber(1), true); 139 + private final Port port1 = new DefaultPort(dev1, portNumber(1), true);
135 - Port port2 = new DefaultPort(dev2, portNumber(2), true); 140 + private final Port port2 = new DefaultPort(dev2, portNumber(2), true);
136 141
137 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3, 142 private final VirtualPort vport22 = new DefaultVirtualPort(networkId3,
138 dev22, portNumber(22), port1); 143 dev22, portNumber(22), port1);
...@@ -156,6 +161,28 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -156,6 +161,28 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
156 .dst(cp21) 161 .dst(cp21)
157 .build(); 162 .build();
158 163
164 + private final MacAddress mac1 = MacAddress.valueOf("00:11:00:00:00:01");
165 + private final MacAddress mac2 = MacAddress.valueOf("00:22:00:00:00:02");
166 + private final VlanId vlan1 = VlanId.vlanId((short) 11);
167 + private final VlanId vlan2 = VlanId.vlanId((short) 22);
168 + private final IpAddress ip1 = IpAddress.valueOf("10.0.0.1");
169 + private final IpAddress ip2 = IpAddress.valueOf("10.0.0.2");
170 + private final IpAddress ip3 = IpAddress.valueOf("10.0.0.3");
171 +
172 + private final HostId hId1 = HostId.hostId(mac1, vlan1);
173 + private final HostId hId2 = HostId.hostId(mac2, vlan2);
174 + private final HostLocation loc1 = new HostLocation(devId1, portNumber(100), 123L);
175 + private final HostLocation loc2 = new HostLocation(devId2, portNumber(200), 123L);
176 + private final Set<IpAddress> ipSet1 = Sets.newHashSet(ip1, ip2);
177 + private final Set<IpAddress> ipSet2 = Sets.newHashSet(ip1, ip3);
178 + private final VirtualHost vhost1 = new DefaultVirtualHost(networkId1, hId1,
179 + mac1, vlan1, loc1, ipSet1);
180 + private final VirtualHost vhost2 = new DefaultVirtualHost(networkId2, hId2,
181 + mac2, vlan2, loc2, ipSet2);
182 +
183 +
184 +
185 +
159 /** 186 /**
160 * Sets up the global values for all the tests. 187 * Sets up the global values for all the tests.
161 */ 188 */
...@@ -177,15 +204,15 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -177,15 +204,15 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
177 * Hamcrest matcher to check that a virtual network entity representation in JSON matches 204 * Hamcrest matcher to check that a virtual network entity representation in JSON matches
178 * the actual virtual network entity. 205 * the actual virtual network entity.
179 */ 206 */
180 - public static class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> { 207 + private static final class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> {
181 private final T vnetEntity; 208 private final T vnetEntity;
182 private List<String> jsonFieldNames; 209 private List<String> jsonFieldNames;
183 private String reason = ""; 210 private String reason = "";
184 private BiFunction<T, String, String> getValue; // get vnetEntity's value 211 private BiFunction<T, String, String> getValue; // get vnetEntity's value
185 212
186 - public JsonObjectMatcher(T vnetEntityValue, 213 + private JsonObjectMatcher(T vnetEntityValue,
187 - List<String> jsonFieldNames1, 214 + List<String> jsonFieldNames1,
188 - BiFunction<T, String, String> getValue1) { 215 + BiFunction<T, String, String> getValue1) {
189 vnetEntity = vnetEntityValue; 216 vnetEntity = vnetEntityValue;
190 jsonFieldNames = jsonFieldNames1; 217 jsonFieldNames = jsonFieldNames1;
191 getValue = getValue1; 218 getValue = getValue1;
...@@ -238,7 +265,7 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -238,7 +265,7 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
238 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON 265 * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON
239 * array of virtual network entities. 266 * array of virtual network entities.
240 */ 267 */
241 - public static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> { 268 + protected static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> {
242 private final T vnetEntity; 269 private final T vnetEntity;
243 private String reason = ""; 270 private String reason = "";
244 private Function<T, String> getKey; // gets vnetEntity's key 271 private Function<T, String> getKey; // gets vnetEntity's key
...@@ -246,10 +273,10 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -246,10 +273,10 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
246 private List<String> jsonFieldNames; // field/property names 273 private List<String> jsonFieldNames; // field/property names
247 private BiFunction<T, String, String> getValue; // get vnetEntity's value 274 private BiFunction<T, String, String> getValue; // get vnetEntity's value
248 275
249 - public JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1, 276 + protected JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1,
250 - BiPredicate<T, JsonObject> checkKey1, 277 + BiPredicate<T, JsonObject> checkKey1,
251 - List<String> jsonFieldNames1, 278 + List<String> jsonFieldNames1,
252 - BiFunction<T, String, String> getValue1) { 279 + BiFunction<T, String, String> getValue1) {
253 vnetEntity = vnetEntityValue; 280 vnetEntity = vnetEntityValue;
254 getKey = getKey1; 281 getKey = getKey1;
255 checkKey = checkKey1; 282 checkKey = checkKey1;
...@@ -292,9 +319,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -292,9 +319,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
292 /** 319 /**
293 * Array matcher for VirtualNetwork. 320 * Array matcher for VirtualNetwork.
294 */ 321 */
295 - public static class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> { 322 + private static final class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> {
296 323
297 - public VnetJsonArrayMatcher(VirtualNetwork vnetIn) { 324 + private VnetJsonArrayMatcher(VirtualNetwork vnetIn) {
298 super(vnetIn, 325 super(vnetIn,
299 vnet -> "Virtual network " + vnet.id().toString(), 326 vnet -> "Virtual network " + vnet.id().toString(),
300 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()), 327 (vnet, jsonObject) -> jsonObject.get(ID).asString().equals(vnet.id().toString()),
...@@ -571,9 +598,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -571,9 +598,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
571 /** 598 /**
572 * Array matcher for VirtualDevice. 599 * Array matcher for VirtualDevice.
573 */ 600 */
574 - public static class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> { 601 + private static final class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> {
575 602
576 - public VdevJsonArrayMatcher(VirtualDevice vdevIn) { 603 + private VdevJsonArrayMatcher(VirtualDevice vdevIn) {
577 super(vdevIn, 604 super(vdevIn,
578 vdev -> "Virtual device " + vdev.networkId().toString() 605 vdev -> "Virtual device " + vdev.networkId().toString()
579 + " " + vdev.id().toString(), 606 + " " + vdev.id().toString(),
...@@ -726,9 +753,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -726,9 +753,9 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
726 /** 753 /**
727 * Array matcher for VirtualPort. 754 * Array matcher for VirtualPort.
728 */ 755 */
729 - public static class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> { 756 + private static final class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> {
730 757
731 - public VportJsonArrayMatcher(VirtualPort vportIn) { 758 + private VportJsonArrayMatcher(VirtualPort vportIn) {
732 super(vportIn, 759 super(vportIn,
733 vport -> "Virtual port " + vport.networkId().toString() + " " 760 vport -> "Virtual port " + vport.networkId().toString() + " "
734 + vport.element().id().toString() + " " + vport.number().toString(), 761 + vport.element().id().toString() + " " + vport.number().toString(),
...@@ -887,11 +914,11 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -887,11 +914,11 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
887 * Hamcrest matcher to check that a virtual link representation in JSON matches 914 * Hamcrest matcher to check that a virtual link representation in JSON matches
888 * the actual virtual link. 915 * the actual virtual link.
889 */ 916 */
890 - public static class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher { 917 + private static final class VirtualLinkJsonMatcher extends LinksResourceTest.LinkJsonMatcher {
891 private final VirtualLink vlink; 918 private final VirtualLink vlink;
892 private String reason = ""; 919 private String reason = "";
893 920
894 - public VirtualLinkJsonMatcher(VirtualLink vlinkValue) { 921 + private VirtualLinkJsonMatcher(VirtualLink vlinkValue) {
895 super(vlinkValue); 922 super(vlinkValue);
896 vlink = vlinkValue; 923 vlink = vlinkValue;
897 } 924 }
...@@ -931,18 +958,16 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -931,18 +958,16 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
931 * Hamcrest matcher to check that a virtual link is represented properly in a JSON 958 * Hamcrest matcher to check that a virtual link is represented properly in a JSON
932 * array of links. 959 * array of links.
933 */ 960 */
934 - private static class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> { 961 + private static final class VirtualLinkJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
935 private final VirtualLink vlink; 962 private final VirtualLink vlink;
936 private String reason = ""; 963 private String reason = "";
937 964
938 - public VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) { 965 + private VirtualLinkJsonArrayMatcher(VirtualLink vlinkValue) {
939 vlink = vlinkValue; 966 vlink = vlinkValue;
940 } 967 }
941 968
942 @Override 969 @Override
943 public boolean matchesSafely(JsonArray json) { 970 public boolean matchesSafely(JsonArray json) {
944 - final int expectedAttributes = 2;
945 -
946 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size(); 971 for (int jsonLinkIndex = 0; jsonLinkIndex < json.size();
947 jsonLinkIndex++) { 972 jsonLinkIndex++) {
948 973
...@@ -1037,4 +1062,207 @@ public class VirtualNetworkWebResourceTest extends ResourceTest { ...@@ -1037,4 +1062,207 @@ public class VirtualNetworkWebResourceTest extends ResourceTest {
1037 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT)); 1062 assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1038 verify(mockVnetAdminService); 1063 verify(mockVnetAdminService);
1039 } 1064 }
1065 +
1066 + // Tests for Virtual Hosts
1067 +
1068 + /**
1069 + * Tests the result of the REST API GET when there are no virtual hosts.
1070 + */
1071 + @Test
1072 + public void testGetVirtualHostsEmptyArray() {
1073 + NetworkId networkId = networkId4;
1074 + expect(mockVnetService.getVirtualHosts(networkId)).andReturn(ImmutableSet.of()).anyTimes();
1075 + replay(mockVnetService);
1076 +
1077 + WebTarget wt = target();
1078 + String location = "vnets/" + networkId.toString() + "/hosts";
1079 + String response = wt.path(location).request().get(String.class);
1080 + assertThat(response, is("{\"hosts\":[]}"));
1081 +
1082 + verify(mockVnetService);
1083 + }
1084 +
1085 + /**
1086 + * Tests the result of the REST API GET when virtual hosts are defined.
1087 + */
1088 + @Test
1089 + public void testGetVirtualHostsArray() {
1090 + NetworkId networkId = networkId3;
1091 + final Set<VirtualHost> vhostSet = ImmutableSet.of(vhost1, vhost2);
1092 + expect(mockVnetService.getVirtualHosts(networkId)).andReturn(vhostSet).anyTimes();
1093 + replay(mockVnetService);
1094 +
1095 + WebTarget wt = target();
1096 + String location = "vnets/" + networkId.toString() + "/hosts";
1097 + String response = wt.path(location).request().get(String.class);
1098 + assertThat(response, containsString("{\"hosts\":["));
1099 +
1100 + final JsonObject result = Json.parse(response).asObject();
1101 + assertThat(result, notNullValue());
1102 +
1103 + assertThat(result.names(), hasSize(1));
1104 + assertThat(result.names().get(0), is("hosts"));
1105 +
1106 + final JsonArray vnetJsonArray = result.get("hosts").asArray();
1107 + assertThat(vnetJsonArray, notNullValue());
1108 + assertEquals("Virtual hosts array is not the correct size.",
1109 + vhostSet.size(), vnetJsonArray.size());
1110 +
1111 + vhostSet.forEach(vhost -> assertThat(vnetJsonArray, hasVhost(vhost)));
1112 +
1113 + verify(mockVnetService);
1114 + }
1115 +
1116 + /**
1117 + * Hamcrest matcher to check that a virtual host representation in JSON matches
1118 + * the actual virtual host.
1119 + */
1120 + private static final class VirtualHostJsonMatcher extends HostResourceTest.HostJsonMatcher {
1121 + private final VirtualHost vhost;
1122 + private String reason = "";
1123 +
1124 + private VirtualHostJsonMatcher(VirtualHost vhostValue) {
1125 + super(vhostValue);
1126 + vhost = vhostValue;
1127 + }
1128 +
1129 + @Override
1130 + public boolean matchesSafely(JsonObject jsonHost) {
1131 + if (!super.matchesSafely(jsonHost)) {
1132 + return false;
1133 + }
1134 + // check NetworkId
1135 + String jsonNetworkId = jsonHost.get(ID).asString();
1136 + String networkId = vhost.networkId().toString();
1137 + if (!jsonNetworkId.equals(networkId)) {
1138 + reason = ID + " was " + jsonNetworkId;
1139 + return false;
1140 + }
1141 + return true;
1142 + }
1143 +
1144 + @Override
1145 + public void describeTo(Description description) {
1146 + description.appendText(reason);
1147 + }
1148 + }
1149 +
1150 + /**
1151 + * Factory to allocate a virtual host matcher.
1152 + *
1153 + * @param vhost virtual host object we are looking for
1154 + * @return matcher
1155 + */
1156 + private static VirtualHostJsonMatcher matchesVirtualHost(VirtualHost vhost) {
1157 + return new VirtualHostJsonMatcher(vhost);
1158 + }
1159 +
1160 + /**
1161 + * Hamcrest matcher to check that a virtual host is represented properly in a JSON
1162 + * array of hosts.
1163 + */
1164 + private static final class VirtualHostJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
1165 + private final VirtualHost vhost;
1166 + private String reason = "";
1167 +
1168 + private VirtualHostJsonArrayMatcher(VirtualHost vhostValue) {
1169 + vhost = vhostValue;
1170 + }
1171 +
1172 + @Override
1173 + public boolean matchesSafely(JsonArray json) {
1174 + for (int jsonHostIndex = 0; jsonHostIndex < json.size();
1175 + jsonHostIndex++) {
1176 +
1177 + JsonObject jsonHost = json.get(jsonHostIndex).asObject();
1178 +
1179 + if (matchesVirtualHost(vhost).matchesSafely(jsonHost)) {
1180 + return true;
1181 + }
1182 + }
1183 + return false;
1184 + }
1185 +
1186 + @Override
1187 + public void describeTo(Description description) {
1188 + description.appendText(reason);
1189 + }
1190 + }
1191 +
1192 + /**
1193 + * Factory to allocate a virtual host array matcher.
1194 + *
1195 + * @param vhost virtual host object we are looking for
1196 + * @return matcher
1197 + */
1198 + private VirtualHostJsonArrayMatcher hasVhost(VirtualHost vhost) {
1199 + return new VirtualHostJsonArrayMatcher(vhost);
1200 + }
1201 +
1202 + /**
1203 + * Tests adding of new virtual host using POST via JSON stream.
1204 + */
1205 + @Test
1206 + public void testPostVirtualHost() {
1207 + NetworkId networkId = networkId3;
1208 + expect(mockVnetAdminService.createVirtualHost(networkId, hId1, mac1, vlan1, loc1, ipSet1))
1209 + .andReturn(vhost1);
1210 + replay(mockVnetAdminService);
1211 +
1212 + WebTarget wt = target();
1213 + InputStream jsonStream = VirtualNetworkWebResourceTest.class
1214 + .getResourceAsStream("post-virtual-host.json");
1215 + String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1216 + Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE)
1217 + .post(Entity.json(jsonStream));
1218 + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
1219 +
1220 + String location = response.getLocation().getPath();
1221 + assertThat(location, Matchers.startsWith("/" + reqLocation));
1222 +
1223 + verify(mockVnetAdminService);
1224 + }
1225 +
1226 + /**
1227 + * Tests adding of a null virtual host using POST via JSON stream.
1228 + */
1229 + @Test
1230 + public void testPostVirtualHostNullJsonStream() {
1231 + NetworkId networkId = networkId3;
1232 + replay(mockVnetAdminService);
1233 +
1234 + WebTarget wt = target();
1235 + try {
1236 + String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1237 + wt.path(reqLocation)
1238 + .request(MediaType.APPLICATION_JSON_TYPE)
1239 + .post(Entity.json(null), String.class);
1240 + fail("POST of null virtual host did not throw an exception");
1241 + } catch (BadRequestException ex) {
1242 + assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request"));
1243 + }
1244 +
1245 + verify(mockVnetAdminService);
1246 + }
1247 +
1248 + /**
1249 + * Tests removing a virtual host with DELETE request.
1250 + */
1251 + @Test
1252 + public void testDeleteVirtualHost() {
1253 + NetworkId networkId = networkId3;
1254 + mockVnetAdminService.removeVirtualHost(networkId, hId1);
1255 + expectLastCall();
1256 + replay(mockVnetAdminService);
1257 +
1258 + WebTarget wt = target()
1259 + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
1260 + InputStream jsonStream = VirtualNetworkWebResourceTest.class
1261 + .getResourceAsStream("post-virtual-host.json");
1262 + String reqLocation = "vnets/" + networkId.toString() + "/hosts";
1263 + Response response = wt.path(reqLocation).request().method("DELETE", Entity.json(jsonStream));
1264 +
1265 + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
1266 + verify(mockVnetAdminService);
1267 + }
1040 } 1268 }
......
1 +{
2 + "networkId": "3",
3 + "id": "00:11:00:00:00:01/11",
4 + "mac": "00:11:00:00:00:01",
5 + "vlan": "11",
6 + "location": {
7 + "elementId": "devid1",
8 + "port": "100"
9 + },
10 + "ipAddresses": [
11 + "10.0.0.1",
12 + "10.0.0.2"
13 + ]
14 +}