Committed by
Gerrit Code Review
REST API's for tenants, virtual networks, virtual devices ad virtual ports.
Change-Id: I80abe14a083fce3dc6246118af8874028109388f REST API's for tenants, virtual networks, virtual devices ad virtual ports. Change-Id: Ib6c3d69d396e57822bae23f5bf3101c8b9c0b95c
Showing
18 changed files
with
1988 additions
and
2 deletions
... | @@ -26,6 +26,10 @@ import org.onosproject.cluster.ControllerNode; | ... | @@ -26,6 +26,10 @@ import org.onosproject.cluster.ControllerNode; |
26 | import org.onosproject.codec.CodecService; | 26 | import org.onosproject.codec.CodecService; |
27 | import org.onosproject.codec.JsonCodec; | 27 | import org.onosproject.codec.JsonCodec; |
28 | import org.onosproject.core.Application; | 28 | import org.onosproject.core.Application; |
29 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
30 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
31 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
32 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
29 | import org.onosproject.net.Annotations; | 33 | import org.onosproject.net.Annotations; |
30 | import org.onosproject.net.ConnectPoint; | 34 | import org.onosproject.net.ConnectPoint; |
31 | import org.onosproject.net.Device; | 35 | import org.onosproject.net.Device; |
... | @@ -126,6 +130,10 @@ public class CodecManager implements CodecService { | ... | @@ -126,6 +130,10 @@ public class CodecManager implements CodecService { |
126 | registerCodec(McastRoute.class, new McastRouteCodec()); | 130 | registerCodec(McastRoute.class, new McastRouteCodec()); |
127 | registerCodec(DeviceKey.class, new DeviceKeyCodec()); | 131 | registerCodec(DeviceKey.class, new DeviceKeyCodec()); |
128 | registerCodec(Region.class, new RegionCodec()); | 132 | registerCodec(Region.class, new RegionCodec()); |
133 | + registerCodec(TenantId.class, new TenantIdCodec()); | ||
134 | + registerCodec(VirtualNetwork.class, new VirtualNetworkCodec()); | ||
135 | + registerCodec(VirtualDevice.class, new VirtualDeviceCodec()); | ||
136 | + registerCodec(VirtualPort.class, new VirtualPortCodec()); | ||
129 | log.info("Started"); | 137 | log.info("Started"); |
130 | } | 138 | } |
131 | 139 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 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.node.ObjectNode; | ||
19 | +import org.onosproject.codec.CodecContext; | ||
20 | +import org.onosproject.codec.JsonCodec; | ||
21 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
22 | + | ||
23 | + | ||
24 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
25 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
26 | + | ||
27 | +/** | ||
28 | + * Codec for the TenantId class. | ||
29 | + */ | ||
30 | +public class TenantIdCodec extends JsonCodec<TenantId> { | ||
31 | + | ||
32 | + // JSON field names | ||
33 | + private static final String TENANT_ID = "id"; | ||
34 | + | ||
35 | + private static final String NULL_TENANT_MSG = "TenantId cannot be null"; | ||
36 | + private static final String MISSING_MEMBER_MSG = " member is required in TenantId"; | ||
37 | + | ||
38 | + @Override | ||
39 | + public ObjectNode encode(TenantId tenantId, CodecContext context) { | ||
40 | + checkNotNull(tenantId, NULL_TENANT_MSG); | ||
41 | + | ||
42 | + ObjectNode result = context.mapper().createObjectNode() | ||
43 | + .put(TENANT_ID, tenantId.id().toString()); | ||
44 | + | ||
45 | + return result; | ||
46 | + } | ||
47 | + | ||
48 | + @Override | ||
49 | + public TenantId decode(ObjectNode json, CodecContext context) { | ||
50 | + if (json == null || !json.isObject()) { | ||
51 | + return null; | ||
52 | + } | ||
53 | + | ||
54 | + TenantId tenantId = TenantId.tenantId(extractMember(TENANT_ID, json)); | ||
55 | + | ||
56 | + return tenantId; | ||
57 | + } | ||
58 | + | ||
59 | + private String extractMember(String key, ObjectNode json) { | ||
60 | + return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText(); | ||
61 | + } | ||
62 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.node.ObjectNode; | ||
19 | +import org.onosproject.codec.CodecContext; | ||
20 | +import org.onosproject.codec.JsonCodec; | ||
21 | +import org.onosproject.incubator.net.virtual.DefaultVirtualDevice; | ||
22 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
24 | +import org.onosproject.net.DeviceId; | ||
25 | + | ||
26 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
27 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
28 | + | ||
29 | +/** | ||
30 | + * Codec for the VirtualDevice class. | ||
31 | + */ | ||
32 | +public class VirtualDeviceCodec extends JsonCodec<VirtualDevice> { | ||
33 | + | ||
34 | + // JSON field names | ||
35 | + private static final String ID = "deviceId"; | ||
36 | + private static final String NETWORK_ID = "networkId"; | ||
37 | + | ||
38 | + private static final String NULL_OBJECT_MSG = "VirtualDevice cannot be null"; | ||
39 | + private static final String MISSING_MEMBER_MSG = " member is required in VirtualDevice"; | ||
40 | + | ||
41 | + @Override | ||
42 | + public ObjectNode encode(VirtualDevice vDev, CodecContext context) { | ||
43 | + checkNotNull(vDev, NULL_OBJECT_MSG); | ||
44 | + | ||
45 | + ObjectNode result = context.mapper().createObjectNode() | ||
46 | + .put(ID, vDev.id().toString()) | ||
47 | + .put(NETWORK_ID, vDev.networkId().toString()); | ||
48 | + | ||
49 | + return result; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public VirtualDevice decode(ObjectNode json, CodecContext context) { | ||
54 | + if (json == null || !json.isObject()) { | ||
55 | + return null; | ||
56 | + } | ||
57 | + | ||
58 | + DeviceId dId = DeviceId.deviceId(extractMember(ID, json)); | ||
59 | + NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json))); | ||
60 | + return new DefaultVirtualDevice(nId, dId); | ||
61 | + } | ||
62 | + | ||
63 | + private String extractMember(String key, ObjectNode json) { | ||
64 | + return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText(); | ||
65 | + } | ||
66 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.node.ObjectNode; | ||
19 | +import org.onosproject.codec.CodecContext; | ||
20 | +import org.onosproject.codec.JsonCodec; | ||
21 | +import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork; | ||
22 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
23 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
24 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
25 | + | ||
26 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
27 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
28 | + | ||
29 | +/** | ||
30 | + * Codec for the VirtualNetwork class. | ||
31 | + */ | ||
32 | +public class VirtualNetworkCodec extends JsonCodec<VirtualNetwork> { | ||
33 | + | ||
34 | + // JSON field names | ||
35 | + private static final String NETWORK_ID = "networkId"; | ||
36 | + private static final String TENANT_ID = "tenantId"; | ||
37 | + | ||
38 | + private static final String NULL_OBJECT_MSG = "VirtualNetwork cannot be null"; | ||
39 | + private static final String MISSING_MEMBER_MSG = " member is required in VirtualNetwork"; | ||
40 | + | ||
41 | + @Override | ||
42 | + public ObjectNode encode(VirtualNetwork vnet, CodecContext context) { | ||
43 | + checkNotNull(vnet, NULL_OBJECT_MSG); | ||
44 | + | ||
45 | + ObjectNode result = context.mapper().createObjectNode() | ||
46 | + .put(NETWORK_ID, vnet.id().toString()) | ||
47 | + .put(TENANT_ID, vnet.tenantId().toString()); | ||
48 | + | ||
49 | + return result; | ||
50 | + } | ||
51 | + | ||
52 | + @Override | ||
53 | + public VirtualNetwork decode(ObjectNode json, CodecContext context) { | ||
54 | + if (json == null || !json.isObject()) { | ||
55 | + return null; | ||
56 | + } | ||
57 | + | ||
58 | + NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json))); | ||
59 | + TenantId tId = TenantId.tenantId(extractMember(TENANT_ID, json)); | ||
60 | + return new DefaultVirtualNetwork(nId, tId); | ||
61 | + } | ||
62 | + | ||
63 | + private String extractMember(String key, ObjectNode json) { | ||
64 | + return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText(); | ||
65 | + } | ||
66 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.node.ObjectNode; | ||
19 | +import org.onosproject.codec.CodecContext; | ||
20 | +import org.onosproject.codec.JsonCodec; | ||
21 | +import org.onosproject.incubator.net.virtual.DefaultVirtualPort; | ||
22 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
24 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
25 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
26 | +import org.onosproject.net.DefaultAnnotations; | ||
27 | +import org.onosproject.net.DefaultDevice; | ||
28 | +import org.onosproject.net.DefaultPort; | ||
29 | +import org.onosproject.net.Device; | ||
30 | +import org.onosproject.net.DeviceId; | ||
31 | +import org.onosproject.net.Port; | ||
32 | +import org.onosproject.net.PortNumber; | ||
33 | + | ||
34 | +import java.util.Set; | ||
35 | + | ||
36 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
37 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
38 | + | ||
39 | +/** | ||
40 | + * Codec for the VirtualPort class. | ||
41 | + */ | ||
42 | +public class VirtualPortCodec extends JsonCodec<VirtualPort> { | ||
43 | + | ||
44 | + // JSON field names | ||
45 | + private static final String NETWORK_ID = "networkId"; | ||
46 | + private static final String DEVICE_ID = "deviceId"; | ||
47 | + private static final String PORT_NUM = "portNum"; | ||
48 | + private static final String PHYS_DEVICE_ID = "physDeviceId"; | ||
49 | + private static final String PHYS_PORT_NUM = "physPortNum"; | ||
50 | + | ||
51 | + private static final String NULL_OBJECT_MSG = "VirtualPort cannot be null"; | ||
52 | + private static final String MISSING_MEMBER_MSG = " member is required in VirtualPort"; | ||
53 | + private static final String INVALID_VIRTUAL_DEVICE = " is not a valid VirtualDevice"; | ||
54 | + | ||
55 | + @Override | ||
56 | + public ObjectNode encode(VirtualPort vPort, CodecContext context) { | ||
57 | + checkNotNull(vPort, NULL_OBJECT_MSG); | ||
58 | + | ||
59 | + ObjectNode result = context.mapper().createObjectNode() | ||
60 | + .put(NETWORK_ID, vPort.networkId().toString()) | ||
61 | + .put(DEVICE_ID, vPort.element().id().toString()) | ||
62 | + .put(PORT_NUM, vPort.number().toString()) | ||
63 | + .put(PHYS_DEVICE_ID, vPort.realizedBy().element().id().toString()) | ||
64 | + .put(PHYS_PORT_NUM, vPort.realizedBy().number().toString()); | ||
65 | + | ||
66 | + return result; | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + public VirtualPort decode(ObjectNode json, CodecContext context) { | ||
71 | + if (json == null || !json.isObject()) { | ||
72 | + return null; | ||
73 | + } | ||
74 | + | ||
75 | + NetworkId nId = NetworkId.networkId(Long.parseLong(extractMember(NETWORK_ID, json))); | ||
76 | + DeviceId dId = DeviceId.deviceId(extractMember(DEVICE_ID, json)); | ||
77 | + | ||
78 | + VirtualNetworkService vnetService = context.getService(VirtualNetworkService.class); | ||
79 | + Set<VirtualDevice> vDevs = vnetService.getVirtualDevices(nId); | ||
80 | + VirtualDevice vDev = vDevs.stream() | ||
81 | + .filter(virtualDevice -> virtualDevice.id().equals(dId)) | ||
82 | + .findFirst().orElse(null); | ||
83 | + nullIsIllegal(vDev, dId.toString() + INVALID_VIRTUAL_DEVICE); | ||
84 | + | ||
85 | + PortNumber portNum = PortNumber.portNumber(extractMember(PORT_NUM, json)); | ||
86 | + DeviceId physDId = DeviceId.deviceId(extractMember(PHYS_DEVICE_ID, json)); | ||
87 | + PortNumber physPortNum = PortNumber.portNumber(extractMember(PHYS_PORT_NUM, json)); | ||
88 | + | ||
89 | + DefaultAnnotations annotations = DefaultAnnotations.builder().build(); | ||
90 | + Device physDevice = new DefaultDevice(null, physDId, | ||
91 | + null, null, null, null, null, null, annotations); | ||
92 | + Port realizedBy = new DefaultPort(physDevice, physPortNum, true); | ||
93 | + return new DefaultVirtualPort(nId, vDev, portNum, realizedBy); | ||
94 | + } | ||
95 | + | ||
96 | + private String extractMember(String key, ObjectNode json) { | ||
97 | + return nullIsIllegal(json.get(key), key + MISSING_MEMBER_MSG).asText(); | ||
98 | + } | ||
99 | +} |
... | @@ -22,7 +22,7 @@ import org.onosproject.net.Port; | ... | @@ -22,7 +22,7 @@ import org.onosproject.net.Port; |
22 | * Representation of a virtual port. | 22 | * Representation of a virtual port. |
23 | */ | 23 | */ |
24 | @Beta | 24 | @Beta |
25 | -public interface VirtualPort extends Port { | 25 | +public interface VirtualPort extends VirtualElement, Port { |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * Returns the underlying port using which this port is realized. | 28 | * Returns the underlying port using which this port is realized. | ... | ... |
... | @@ -47,7 +47,9 @@ public class CoreWebApplication extends AbstractWebApplication { | ... | @@ -47,7 +47,9 @@ public class CoreWebApplication extends AbstractWebApplication { |
47 | FlowObjectiveWebResource.class, | 47 | FlowObjectiveWebResource.class, |
48 | MulticastRouteWebResource.class, | 48 | MulticastRouteWebResource.class, |
49 | DeviceKeyWebResource.class, | 49 | DeviceKeyWebResource.class, |
50 | - RegionsWebResource.class | 50 | + RegionsWebResource.class, |
51 | + TenantWebResource.class, | ||
52 | + VirtualNetworkWebResource.class | ||
51 | ); | 53 | ); |
52 | } | 54 | } |
53 | } | 55 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 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.rest.resources; | ||
18 | + | ||
19 | +import com.fasterxml.jackson.databind.JsonNode; | ||
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | +import org.onlab.util.ItemNotFoundException; | ||
22 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; | ||
24 | +import org.onosproject.rest.AbstractWebResource; | ||
25 | + | ||
26 | +import javax.ws.rs.Consumes; | ||
27 | +import javax.ws.rs.DELETE; | ||
28 | +import javax.ws.rs.GET; | ||
29 | +import javax.ws.rs.POST; | ||
30 | +import javax.ws.rs.Path; | ||
31 | +import javax.ws.rs.PathParam; | ||
32 | +import javax.ws.rs.Produces; | ||
33 | +import javax.ws.rs.core.Context; | ||
34 | +import javax.ws.rs.core.MediaType; | ||
35 | +import javax.ws.rs.core.Response; | ||
36 | +import javax.ws.rs.core.UriBuilder; | ||
37 | +import javax.ws.rs.core.UriInfo; | ||
38 | +import java.io.IOException; | ||
39 | +import java.io.InputStream; | ||
40 | + | ||
41 | +/** | ||
42 | + * Query and manage tenants of virtual networks. | ||
43 | + */ | ||
44 | +@Path("tenants") | ||
45 | +public class TenantWebResource extends AbstractWebResource { | ||
46 | + | ||
47 | + private static final String MISSING_TENANTID = "Missing tenant identifier"; | ||
48 | + private static final String TENANTID_NOT_FOUND = "Tenant identifier not found"; | ||
49 | + private static final String INVALID_TENANTID = "Invalid tenant identifier "; | ||
50 | + | ||
51 | + @Context | ||
52 | + UriInfo uriInfo; | ||
53 | + | ||
54 | + private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class); | ||
55 | + | ||
56 | + /** | ||
57 | + * Returns all tenants. | ||
58 | + * | ||
59 | + * @return 200 OK | ||
60 | + * @onos.rsModel TenantIds | ||
61 | + */ | ||
62 | + @GET | ||
63 | + @Produces(MediaType.APPLICATION_JSON) | ||
64 | + public Response getVirtualNetworkTenants() { | ||
65 | + Iterable<TenantId> tenantIds = vnetAdminService.getTenantIds(); | ||
66 | + return ok(encodeArray(TenantId.class, "tenants", tenantIds)).build(); | ||
67 | + } | ||
68 | + | ||
69 | + /** | ||
70 | + * Creates a tenant with the given tenant identifier. | ||
71 | + * | ||
72 | + * @param stream TenantId JSON stream | ||
73 | + * @return status of the request - CREATED if the JSON is correct, | ||
74 | + * BAD_REQUEST if the JSON is invalid | ||
75 | + * @onos.rsModel TenantId | ||
76 | + */ | ||
77 | + @POST | ||
78 | + @Consumes(MediaType.APPLICATION_JSON) | ||
79 | + @Produces(MediaType.APPLICATION_JSON) | ||
80 | + public Response addTenantId(InputStream stream) { | ||
81 | + try { | ||
82 | + final TenantId tid = getTenantIdFromJsonStream(stream); | ||
83 | + vnetAdminService.registerTenantId(tid); | ||
84 | + final TenantId resultTid = getExistingTenantId(vnetAdminService, tid); | ||
85 | + UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() | ||
86 | + .path("tenants") | ||
87 | + .path(resultTid.id()); | ||
88 | + return Response | ||
89 | + .created(locationBuilder.build()) | ||
90 | + .build(); | ||
91 | + } catch (IOException e) { | ||
92 | + throw new IllegalArgumentException(e); | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Removes the specified tenant with the specified tenant identifier. | ||
98 | + * | ||
99 | + * @param tenantId tenant identifier | ||
100 | + * @return 200 OK, 404 not found | ||
101 | + */ | ||
102 | + @DELETE | ||
103 | + @Path("{tenantId}") | ||
104 | + public Response removeTenantId(@PathParam("tenantId") String tenantId) { | ||
105 | + final TenantId tid = TenantId.tenantId(tenantId); | ||
106 | + final TenantId existingTid = getExistingTenantId(vnetAdminService, tid); | ||
107 | + vnetAdminService.unregisterTenantId(existingTid); | ||
108 | + return Response.ok().build(); | ||
109 | + } | ||
110 | + | ||
111 | + /** | ||
112 | + * Removes the specified tenant with the specified tenant identifier. | ||
113 | + * | ||
114 | + * @param stream deviceIds JSON stream | ||
115 | + * @return 200 OK, 404 not found | ||
116 | + * @onos.rsModel TenantId | ||
117 | + */ | ||
118 | + @DELETE | ||
119 | + public Response removeTenantId(InputStream stream) { | ||
120 | + try { | ||
121 | + final TenantId tid = getTenantIdFromJsonStream(stream); | ||
122 | + vnetAdminService.unregisterTenantId(tid); | ||
123 | + } catch (IOException e) { | ||
124 | + throw new IllegalArgumentException(e); | ||
125 | + } | ||
126 | + return Response.ok().build(); | ||
127 | + } | ||
128 | + | ||
129 | + /** | ||
130 | + * Get the tenant identifier from the JSON stream. | ||
131 | + * | ||
132 | + * @param stream TenantId JSON stream | ||
133 | + * @return TenantId | ||
134 | + * @throws IOException | ||
135 | + */ | ||
136 | + private TenantId getTenantIdFromJsonStream(InputStream stream) throws IOException { | ||
137 | + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | ||
138 | + JsonNode specifiedTenantId = jsonTree.get("id"); | ||
139 | + | ||
140 | + if (specifiedTenantId == null) { | ||
141 | + throw new IllegalArgumentException(MISSING_TENANTID); | ||
142 | + } | ||
143 | + return TenantId.tenantId(specifiedTenantId.asText()); | ||
144 | + } | ||
145 | + | ||
146 | + /** | ||
147 | + * Get the matching tenant identifier from existing tenant identifiers in system. | ||
148 | + * | ||
149 | + * @param vnetAdminSvc | ||
150 | + * @param tidIn tenant identifier | ||
151 | + * @return TenantId | ||
152 | + */ | ||
153 | + private static TenantId getExistingTenantId(VirtualNetworkAdminService vnetAdminSvc, | ||
154 | + TenantId tidIn) { | ||
155 | + final TenantId resultTid = vnetAdminSvc | ||
156 | + .getTenantIds() | ||
157 | + .stream() | ||
158 | + .filter(tenantId -> tenantId.equals(tidIn)) | ||
159 | + .findFirst() | ||
160 | + .orElseThrow(() -> new ItemNotFoundException(TENANTID_NOT_FOUND)); | ||
161 | + return resultTid; | ||
162 | + } | ||
163 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.rest.resources; | ||
18 | + | ||
19 | +import com.fasterxml.jackson.databind.JsonNode; | ||
20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
21 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
22 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
23 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
24 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
25 | +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; | ||
26 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
27 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
28 | +import org.onosproject.net.DefaultAnnotations; | ||
29 | +import org.onosproject.net.DefaultDevice; | ||
30 | +import org.onosproject.net.DefaultPort; | ||
31 | +import org.onosproject.net.Device; | ||
32 | +import org.onosproject.net.DeviceId; | ||
33 | +import org.onosproject.net.Port; | ||
34 | +import org.onosproject.net.PortNumber; | ||
35 | +import org.onosproject.rest.AbstractWebResource; | ||
36 | + | ||
37 | +import javax.ws.rs.Consumes; | ||
38 | +import javax.ws.rs.DELETE; | ||
39 | +import javax.ws.rs.GET; | ||
40 | +import javax.ws.rs.POST; | ||
41 | +import javax.ws.rs.Path; | ||
42 | +import javax.ws.rs.PathParam; | ||
43 | +import javax.ws.rs.Produces; | ||
44 | +import javax.ws.rs.core.Context; | ||
45 | +import javax.ws.rs.core.MediaType; | ||
46 | +import javax.ws.rs.core.Response; | ||
47 | +import javax.ws.rs.core.UriBuilder; | ||
48 | +import javax.ws.rs.core.UriInfo; | ||
49 | +import java.io.IOException; | ||
50 | +import java.io.InputStream; | ||
51 | +import java.util.Collection; | ||
52 | +import java.util.List; | ||
53 | +import java.util.Set; | ||
54 | +import java.util.stream.Collectors; | ||
55 | + | ||
56 | +/** | ||
57 | + * Query and Manage Virtual Network elements. | ||
58 | + */ | ||
59 | +@Path("vnets") | ||
60 | +public class VirtualNetworkWebResource extends AbstractWebResource { | ||
61 | + | ||
62 | + private static final String MISSING_FIELD = "Missing "; | ||
63 | + private static final String INVALID_FIELD = "Invalid "; | ||
64 | + | ||
65 | + private final VirtualNetworkAdminService vnetAdminService = get(VirtualNetworkAdminService.class); | ||
66 | + private final VirtualNetworkService vnetService = get(VirtualNetworkService.class); | ||
67 | + | ||
68 | + @Context | ||
69 | + UriInfo uriInfo; | ||
70 | + | ||
71 | + // VirtualNetwork | ||
72 | + // TODO Query vnets by tenant | ||
73 | + | ||
74 | + /** | ||
75 | + * Returns all virtual networks. | ||
76 | + * | ||
77 | + * @return 200 OK | ||
78 | + */ | ||
79 | + @GET | ||
80 | + @Produces(MediaType.APPLICATION_JSON) | ||
81 | + public Response getVirtualNetworks() { | ||
82 | + Set<TenantId> tenantIds = vnetAdminService.getTenantIds(); | ||
83 | + List<VirtualNetwork> allVnets = tenantIds.stream() | ||
84 | + .map(tenantId -> vnetService.getVirtualNetworks(tenantId)) | ||
85 | + .flatMap(Collection::stream) | ||
86 | + .collect(Collectors.toList()); | ||
87 | + return ok(encodeArray(VirtualNetwork.class, "vnets", allVnets)).build(); | ||
88 | + } | ||
89 | + | ||
90 | + /** | ||
91 | + * Creates a virtual network from the JSON input stream. | ||
92 | + * | ||
93 | + * @param stream TenantId JSON stream | ||
94 | + * @return status of the request - CREATED if the JSON is correct, | ||
95 | + * BAD_REQUEST if the JSON is invalid | ||
96 | + * @onos.rsModel TenantId | ||
97 | + */ | ||
98 | + @POST | ||
99 | + @Consumes(MediaType.APPLICATION_JSON) | ||
100 | + @Produces(MediaType.APPLICATION_JSON) | ||
101 | + public Response createVirtualNetwork(InputStream stream) { | ||
102 | + try { | ||
103 | + final TenantId tid = TenantId.tenantId(getFromJsonStream(stream, "id").asText()); | ||
104 | + VirtualNetwork newVnet = vnetAdminService.createVirtualNetwork(tid); | ||
105 | + UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() | ||
106 | + .path("vnets") | ||
107 | + .path(newVnet.id().toString()); | ||
108 | + return Response | ||
109 | + .created(locationBuilder.build()) | ||
110 | + .build(); | ||
111 | + } catch (IOException e) { | ||
112 | + throw new IllegalArgumentException(e); | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + /** | ||
117 | + * Removes the virtual network with the specified network identifier. | ||
118 | + * | ||
119 | + * @param networkId network identifier | ||
120 | + * @return 200 OK, 404 not found | ||
121 | + */ | ||
122 | + @DELETE | ||
123 | + @Path("{networkId}") | ||
124 | + public Response removeVirtualNetwork(@PathParam("networkId") long networkId) { | ||
125 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
126 | + vnetAdminService.removeVirtualNetwork(nid); | ||
127 | + return Response.ok().build(); | ||
128 | + } | ||
129 | + | ||
130 | + // VirtualDevice | ||
131 | + | ||
132 | + /** | ||
133 | + * Returns all virtual network devices in a virtual network. | ||
134 | + * | ||
135 | + * @param networkId network identifier | ||
136 | + * @return 200 OK | ||
137 | + */ | ||
138 | + @GET | ||
139 | + @Produces(MediaType.APPLICATION_JSON) | ||
140 | + @Path("{networkId}/devices") | ||
141 | + public Response getVirtualDevices(@PathParam("networkId") long networkId) { | ||
142 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
143 | + Set<VirtualDevice> vdevs = vnetService.getVirtualDevices(nid); | ||
144 | + return ok(encodeArray(VirtualDevice.class, "devices", vdevs)).build(); | ||
145 | + } | ||
146 | + | ||
147 | + /** | ||
148 | + * Creates a virtual device from the JSON input stream. | ||
149 | + * | ||
150 | + * @param networkId network identifier | ||
151 | + * @param stream Virtual device JSON stream | ||
152 | + * @return status of the request - CREATED if the JSON is correct, | ||
153 | + * BAD_REQUEST if the JSON is invalid | ||
154 | + * @onos.rsModel VirtualDevice | ||
155 | + */ | ||
156 | + @POST | ||
157 | + @Path("{networkId}/devices/") | ||
158 | + @Consumes(MediaType.APPLICATION_JSON) | ||
159 | + @Produces(MediaType.APPLICATION_JSON) | ||
160 | + public Response createVirtualDevice(@PathParam("networkId") long networkId, | ||
161 | + InputStream stream) { | ||
162 | + try { | ||
163 | + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | ||
164 | + final VirtualDevice vdevReq = codec(VirtualDevice.class).decode(jsonTree, this); | ||
165 | + JsonNode specifiedRegionId = jsonTree.get("networkId"); | ||
166 | + if (specifiedRegionId != null && | ||
167 | + specifiedRegionId.asLong() != (networkId)) { | ||
168 | + throw new IllegalArgumentException(INVALID_FIELD + "networkId"); | ||
169 | + } | ||
170 | + final VirtualDevice vdevRes = vnetAdminService.createVirtualDevice(vdevReq.networkId(), | ||
171 | + vdevReq.id()); | ||
172 | + UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() | ||
173 | + .path("vnets").path(specifiedRegionId.asText()) | ||
174 | + .path("devices").path(vdevRes.id().toString()); | ||
175 | + return Response | ||
176 | + .created(locationBuilder.build()) | ||
177 | + .build(); | ||
178 | + } catch (IOException e) { | ||
179 | + throw new IllegalArgumentException(e); | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
183 | + /** | ||
184 | + * Removes the virtual network device from the virtual network. | ||
185 | + * | ||
186 | + * @param networkId network identifier | ||
187 | + * @param deviceId device identifier | ||
188 | + * @return 200 OK, 404 not found | ||
189 | + */ | ||
190 | + @DELETE | ||
191 | + @Path("{networkId}/devices/{deviceId}") | ||
192 | + public Response removeVirtualDevice(@PathParam("networkId") long networkId, | ||
193 | + @PathParam("deviceId") String deviceId) { | ||
194 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
195 | + final DeviceId did = DeviceId.deviceId(deviceId); | ||
196 | + vnetAdminService.removeVirtualDevice(nid, did); | ||
197 | + return Response.ok().build(); | ||
198 | + } | ||
199 | + | ||
200 | + // VirtualPort | ||
201 | + | ||
202 | + /** | ||
203 | + * Returns all virtual network ports in a virtual device in a virtual network. | ||
204 | + * | ||
205 | + * @param networkId network identifier | ||
206 | + * @param deviceId virtual device identifier | ||
207 | + * @return 200 OK | ||
208 | + */ | ||
209 | + @GET | ||
210 | + @Produces(MediaType.APPLICATION_JSON) | ||
211 | + @Path("{networkId}/devices/{deviceId}/ports") | ||
212 | + public Response getVirtualPorts(@PathParam("networkId") long networkId, | ||
213 | + @PathParam("deviceId") String deviceId) { | ||
214 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
215 | + Iterable<VirtualPort> vports = vnetService.getVirtualPorts(nid, DeviceId.deviceId(deviceId)); | ||
216 | + return ok(encodeArray(VirtualPort.class, "ports", vports)).build(); | ||
217 | + } | ||
218 | + | ||
219 | + /** | ||
220 | + * Creates a virtual network port in a virtual device in a virtual network. | ||
221 | + * | ||
222 | + * @param networkId network identifier | ||
223 | + * @param virtDeviceId virtual device identifier | ||
224 | + * @param stream Virtual device JSON stream | ||
225 | + * @return status of the request - CREATED if the JSON is correct, | ||
226 | + * BAD_REQUEST if the JSON is invalid | ||
227 | + * @onos.rsModel VirtualPort | ||
228 | + */ | ||
229 | + @POST | ||
230 | + @Consumes(MediaType.APPLICATION_JSON) | ||
231 | + @Produces(MediaType.APPLICATION_JSON) | ||
232 | + @Path("{networkId}/devices/{deviceId}/ports") | ||
233 | + public Response createVirtualPort(@PathParam("networkId") long networkId, | ||
234 | + @PathParam("deviceId") String virtDeviceId, | ||
235 | + InputStream stream) { | ||
236 | + try { | ||
237 | + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | ||
238 | +// final VirtualPort vportReq = codec(VirtualPort.class).decode(jsonTree, this); | ||
239 | + JsonNode specifiedNetworkId = jsonTree.get("networkId"); | ||
240 | + JsonNode specifiedDeviceId = jsonTree.get("deviceId"); | ||
241 | + if (specifiedNetworkId != null && | ||
242 | + specifiedNetworkId.asLong() != (networkId)) { | ||
243 | + throw new IllegalArgumentException(INVALID_FIELD + "networkId"); | ||
244 | + } | ||
245 | + if (specifiedDeviceId != null && | ||
246 | + !specifiedDeviceId.asText().equals(virtDeviceId)) { | ||
247 | + throw new IllegalArgumentException(INVALID_FIELD + "deviceId"); | ||
248 | + } | ||
249 | + JsonNode specifiedPortNum = jsonTree.get("portNum"); | ||
250 | + JsonNode specifiedPhysDeviceId = jsonTree.get("physDeviceId"); | ||
251 | + JsonNode specifiedPhysPortNum = jsonTree.get("physPortNum"); | ||
252 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
253 | + DeviceId vdevId = DeviceId.deviceId(virtDeviceId); | ||
254 | + DefaultAnnotations annotations = DefaultAnnotations.builder().build(); | ||
255 | + Device physDevice = new DefaultDevice(null, DeviceId.deviceId(specifiedPhysDeviceId.asText()), | ||
256 | + null, null, null, null, null, null, annotations); | ||
257 | + Port realizedBy = new DefaultPort(physDevice, | ||
258 | + PortNumber.portNumber(specifiedPhysPortNum.asText()), true); | ||
259 | + VirtualPort vport = vnetAdminService.createVirtualPort(nid, vdevId, | ||
260 | + PortNumber.portNumber(specifiedPortNum.asText()), realizedBy); | ||
261 | + UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() | ||
262 | + .path("vnets").path(specifiedNetworkId.asText()) | ||
263 | + .path("devices").path(specifiedDeviceId.asText()) | ||
264 | + .path("ports").path(vport.number().toString()); | ||
265 | + return Response | ||
266 | + .created(locationBuilder.build()) | ||
267 | + .build(); | ||
268 | + } catch (IOException e) { | ||
269 | + throw new IllegalArgumentException(e); | ||
270 | + } | ||
271 | + } | ||
272 | + | ||
273 | + /** | ||
274 | + * Removes the virtual network port from the virtual device in a virtual network. | ||
275 | + * | ||
276 | + * @param networkId network identifier | ||
277 | + * @param deviceId virtual device identifier | ||
278 | + * @param portNum virtual port number | ||
279 | + * @return 200 OK, 404 not found | ||
280 | + */ | ||
281 | + @DELETE | ||
282 | + @Path("{networkId}/devices/{deviceId}/ports/{portNum}") | ||
283 | + public Response removeVirtualPort(@PathParam("networkId") long networkId, | ||
284 | + @PathParam("deviceId") String deviceId, | ||
285 | + @PathParam("portNum") long portNum) { | ||
286 | + final NetworkId nid = NetworkId.networkId(networkId); | ||
287 | + vnetAdminService.removeVirtualPort(nid, DeviceId.deviceId(deviceId), | ||
288 | + PortNumber.portNumber(portNum)); | ||
289 | + return Response.ok().build(); | ||
290 | + } | ||
291 | + | ||
292 | + // TODO VirtualLink | ||
293 | + | ||
294 | + /** | ||
295 | + * Get the tenant identifier from the JSON stream. | ||
296 | + * | ||
297 | + * @param stream TenantId JSON stream | ||
298 | + * @param jsonFieldName field name | ||
299 | + * @return JsonNode | ||
300 | + * @throws IOException | ||
301 | + */ | ||
302 | + private JsonNode getFromJsonStream(InputStream stream, String jsonFieldName) throws IOException { | ||
303 | + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | ||
304 | + JsonNode jsonNode = jsonTree.get(jsonFieldName); | ||
305 | + | ||
306 | + if (jsonNode == null) { | ||
307 | + throw new IllegalArgumentException(MISSING_FIELD + jsonFieldName); | ||
308 | + } | ||
309 | + return jsonNode; | ||
310 | + } | ||
311 | +} |
1 | +{ | ||
2 | + "type": "object", | ||
3 | + "title": "tenants", | ||
4 | + "required": [ | ||
5 | + "tenants" | ||
6 | + ], | ||
7 | + "properties": { | ||
8 | + "tenants": { | ||
9 | + "type": "array", | ||
10 | + "xml": { | ||
11 | + "name": "tenants", | ||
12 | + "wrapped": true | ||
13 | + }, | ||
14 | + "items": { | ||
15 | + "type": "object", | ||
16 | + "title": "tenant", | ||
17 | + "required": [ | ||
18 | + "id" | ||
19 | + ], | ||
20 | + "properties": { | ||
21 | + "id": { | ||
22 | + "type": "String", | ||
23 | + "example": "Tenant unique identifier" | ||
24 | + } | ||
25 | + } | ||
26 | + } | ||
27 | + } | ||
28 | + } | ||
29 | +} |
1 | +{ | ||
2 | + "type": "object", | ||
3 | + "title": "vdev", | ||
4 | + "required": [ | ||
5 | + "networkId", | ||
6 | + "deviceId" | ||
7 | + ], | ||
8 | + "properties": { | ||
9 | + "networkId": { | ||
10 | + "type": "String", | ||
11 | + "example": "Network identifier" | ||
12 | + }, | ||
13 | + "deviceId": { | ||
14 | + "type": "String", | ||
15 | + "example": "Device identifier" | ||
16 | + } | ||
17 | + } | ||
18 | +} |
1 | +{ | ||
2 | + "type": "object", | ||
3 | + "title": "vport", | ||
4 | + "required": [ | ||
5 | + "networkId", | ||
6 | + "deviceId", | ||
7 | + "portNum", | ||
8 | + "physDeviceId", | ||
9 | + "physPortNum" | ||
10 | + ], | ||
11 | + "properties": { | ||
12 | + "networkId": { | ||
13 | + "type": "String", | ||
14 | + "example": "Network identifier" | ||
15 | + }, | ||
16 | + "deviceId": { | ||
17 | + "type": "String", | ||
18 | + "example": "Virtual device identifier" | ||
19 | + }, | ||
20 | + "portNum": { | ||
21 | + "type": "String", | ||
22 | + "example": "Virtual device port number" | ||
23 | + }, | ||
24 | + "physDeviceId": { | ||
25 | + "type": "String", | ||
26 | + "example": "Physical device identifier" | ||
27 | + }, | ||
28 | + "physPortNum": { | ||
29 | + "type": "String", | ||
30 | + "example": "Physical device port number" | ||
31 | + } | ||
32 | + } | ||
33 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.rest.resources; | ||
18 | + | ||
19 | +import com.eclipsesource.json.Json; | ||
20 | +import com.eclipsesource.json.JsonArray; | ||
21 | +import com.eclipsesource.json.JsonObject; | ||
22 | +import com.google.common.collect.ImmutableSet; | ||
23 | +import org.glassfish.jersey.client.ClientProperties; | ||
24 | +import org.hamcrest.Description; | ||
25 | +import org.hamcrest.Matchers; | ||
26 | +import org.hamcrest.TypeSafeMatcher; | ||
27 | +import org.junit.Before; | ||
28 | +import org.junit.Test; | ||
29 | +import org.onlab.osgi.ServiceDirectory; | ||
30 | +import org.onlab.osgi.TestServiceDirectory; | ||
31 | +import org.onlab.rest.BaseResource; | ||
32 | +import org.onosproject.codec.CodecService; | ||
33 | +import org.onosproject.codec.impl.CodecManager; | ||
34 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
35 | +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; | ||
36 | + | ||
37 | +import javax.ws.rs.BadRequestException; | ||
38 | +import javax.ws.rs.NotFoundException; | ||
39 | +import javax.ws.rs.client.Entity; | ||
40 | +import javax.ws.rs.client.WebTarget; | ||
41 | +import javax.ws.rs.core.MediaType; | ||
42 | +import javax.ws.rs.core.Response; | ||
43 | +import java.io.InputStream; | ||
44 | +import java.net.HttpURLConnection; | ||
45 | +import java.util.HashSet; | ||
46 | + | ||
47 | +import static org.easymock.EasyMock.*; | ||
48 | +import static org.hamcrest.Matchers.*; | ||
49 | +import static org.junit.Assert.*; | ||
50 | + | ||
51 | +/** | ||
52 | + * Unit tests for tenant REST APIs. | ||
53 | + */ | ||
54 | +public class TenantWebResourceTest extends ResourceTest { | ||
55 | + | ||
56 | + private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class); | ||
57 | + | ||
58 | + final HashSet<TenantId> tenantIdSet = new HashSet<>(); | ||
59 | + | ||
60 | + private static final String ID = "id"; | ||
61 | + | ||
62 | + private final TenantId tenantId1 = TenantId.tenantId("TenantId1"); | ||
63 | + private final TenantId tenantId2 = TenantId.tenantId("TenantId2"); | ||
64 | + private final TenantId tenantId3 = TenantId.tenantId("TenantId3"); | ||
65 | + private final TenantId tenantId4 = TenantId.tenantId("TenantId4"); | ||
66 | + | ||
67 | + /** | ||
68 | + * Sets up the global values for all the tests. | ||
69 | + */ | ||
70 | + @Before | ||
71 | + public void setUpTest() { | ||
72 | + // Register the services needed for the test | ||
73 | + CodecManager codecService = new CodecManager(); | ||
74 | + codecService.activate(); | ||
75 | + ServiceDirectory testDirectory = | ||
76 | + new TestServiceDirectory() | ||
77 | + .add(VirtualNetworkAdminService.class, mockVnetAdminService) | ||
78 | + .add(CodecService.class, codecService); | ||
79 | + | ||
80 | + BaseResource.setServiceDirectory(testDirectory); | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * Hamcrest matcher to check that a tenant id representation in JSON matches | ||
85 | + * the actual tenant id. | ||
86 | + */ | ||
87 | + public static class TenantIdJsonMatcher extends TypeSafeMatcher<JsonObject> { | ||
88 | + private final TenantId tenantId; | ||
89 | + private String reason = ""; | ||
90 | + | ||
91 | + public TenantIdJsonMatcher(TenantId tenantIdValue) { | ||
92 | + tenantId = tenantIdValue; | ||
93 | + } | ||
94 | + | ||
95 | + @Override | ||
96 | + public boolean matchesSafely(JsonObject jsonHost) { | ||
97 | + // Check the tenant id | ||
98 | + final String jsonId = jsonHost.get(ID).asString(); | ||
99 | + if (!jsonId.equals(tenantId.id())) { | ||
100 | + reason = ID + " " + tenantId.id(); | ||
101 | + return false; | ||
102 | + } | ||
103 | + | ||
104 | + return true; | ||
105 | + } | ||
106 | + | ||
107 | + @Override | ||
108 | + public void describeTo(Description description) { | ||
109 | + description.appendText(reason); | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * Factory to allocate a tenant id array matcher. | ||
115 | + * | ||
116 | + * @param tenantId tenant id object we are looking for | ||
117 | + * @return matcher | ||
118 | + */ | ||
119 | + private static TenantIdJsonMatcher matchesTenantId(TenantId tenantId) { | ||
120 | + return new TenantIdJsonMatcher(tenantId); | ||
121 | + } | ||
122 | + | ||
123 | + /** | ||
124 | + * Hamcrest matcher to check that a tenant id is represented properly in a JSON | ||
125 | + * array of tenant ids. | ||
126 | + */ | ||
127 | + public static class TenantIdJsonArrayMatcher extends TypeSafeMatcher<JsonArray> { | ||
128 | + private final TenantId tenantId; | ||
129 | + private String reason = ""; | ||
130 | + | ||
131 | + public TenantIdJsonArrayMatcher(TenantId tenantIdValue) { | ||
132 | + tenantId = tenantIdValue; | ||
133 | + } | ||
134 | + | ||
135 | + @Override | ||
136 | + public boolean matchesSafely(JsonArray json) { | ||
137 | + boolean tenantIdFound = false; | ||
138 | + final int expectedAttributes = 1; | ||
139 | + for (int tenantIdIndex = 0; tenantIdIndex < json.size(); | ||
140 | + tenantIdIndex++) { | ||
141 | + | ||
142 | + final JsonObject jsonHost = json.get(tenantIdIndex).asObject(); | ||
143 | + | ||
144 | + // Only 1 attribute - ID. | ||
145 | + if (jsonHost.names().size() < expectedAttributes) { | ||
146 | + reason = "Found a tenant id with the wrong number of attributes"; | ||
147 | + return false; | ||
148 | + } | ||
149 | + | ||
150 | + final String jsonDeviceKeyId = jsonHost.get(ID).asString(); | ||
151 | + if (jsonDeviceKeyId.equals(tenantId.id())) { | ||
152 | + tenantIdFound = true; | ||
153 | + | ||
154 | + // We found the correct tenant id, check the tenant id attribute values | ||
155 | + assertThat(jsonHost, matchesTenantId(tenantId)); | ||
156 | + } | ||
157 | + } | ||
158 | + if (!tenantIdFound) { | ||
159 | + reason = "Tenant id " + tenantId.id() + " was not found"; | ||
160 | + return false; | ||
161 | + } | ||
162 | + return true; | ||
163 | + } | ||
164 | + | ||
165 | + @Override | ||
166 | + public void describeTo(Description description) { | ||
167 | + description.appendText(reason); | ||
168 | + } | ||
169 | + } | ||
170 | + | ||
171 | + /** | ||
172 | + * Factory to allocate a tenant id array matcher. | ||
173 | + * | ||
174 | + * @param tenantId tenant id object we are looking for | ||
175 | + * @return matcher | ||
176 | + */ | ||
177 | + private static TenantIdJsonArrayMatcher hasTenantId(TenantId tenantId) { | ||
178 | + return new TenantIdJsonArrayMatcher(tenantId); | ||
179 | + } | ||
180 | + | ||
181 | + /** | ||
182 | + * Tests the result of the REST API GET when there are no tenant ids. | ||
183 | + */ | ||
184 | + @Test | ||
185 | + public void testGetTenantsEmptyArray() { | ||
186 | + expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes(); | ||
187 | + replay(mockVnetAdminService); | ||
188 | + | ||
189 | + WebTarget wt = target(); | ||
190 | + String response = wt.path("tenants").request().get(String.class); | ||
191 | + assertThat(response, is("{\"tenants\":[]}")); | ||
192 | + | ||
193 | + verify(mockVnetAdminService); | ||
194 | + } | ||
195 | + | ||
196 | + /** | ||
197 | + * Tests the result of the REST API GET when tenant ids are defined. | ||
198 | + */ | ||
199 | + @Test | ||
200 | + public void testGetTenantIdsArray() { | ||
201 | + tenantIdSet.add(tenantId1); | ||
202 | + tenantIdSet.add(tenantId2); | ||
203 | + tenantIdSet.add(tenantId3); | ||
204 | + tenantIdSet.add(tenantId4); | ||
205 | + expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes(); | ||
206 | + replay(mockVnetAdminService); | ||
207 | + | ||
208 | + WebTarget wt = target(); | ||
209 | + String response = wt.path("tenants").request().get(String.class); | ||
210 | + assertThat(response, containsString("{\"tenants\":[")); | ||
211 | + | ||
212 | + final JsonObject result = Json.parse(response).asObject(); | ||
213 | + assertThat(result, notNullValue()); | ||
214 | + | ||
215 | + assertThat(result.names(), hasSize(1)); | ||
216 | + assertThat(result.names().get(0), is("tenants")); | ||
217 | + | ||
218 | + final JsonArray tenantIds = result.get("tenants").asArray(); | ||
219 | + assertThat(tenantIds, notNullValue()); | ||
220 | + assertEquals("Device keys array is not the correct size.", | ||
221 | + tenantIdSet.size(), tenantIds.size()); | ||
222 | + | ||
223 | + tenantIdSet.forEach(tenantId -> assertThat(tenantIds, hasTenantId(tenantId))); | ||
224 | + | ||
225 | + verify(mockVnetAdminService); | ||
226 | + } | ||
227 | + | ||
228 | + /** | ||
229 | + * Tests adding of new tenant id using POST via JSON stream. | ||
230 | + */ | ||
231 | + @Test | ||
232 | + public void testPost() { | ||
233 | + mockVnetAdminService.registerTenantId(anyObject()); | ||
234 | + tenantIdSet.add(tenantId2); | ||
235 | + expect(mockVnetAdminService.getTenantIds()).andReturn(tenantIdSet).anyTimes(); | ||
236 | + expectLastCall(); | ||
237 | + | ||
238 | + replay(mockVnetAdminService); | ||
239 | + | ||
240 | + WebTarget wt = target(); | ||
241 | + InputStream jsonStream = TenantWebResourceTest.class | ||
242 | + .getResourceAsStream("post-tenant.json"); | ||
243 | + | ||
244 | + Response response = wt.path("tenants").request(MediaType.APPLICATION_JSON_TYPE) | ||
245 | + .post(Entity.json(jsonStream)); | ||
246 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED)); | ||
247 | + | ||
248 | + String location = response.getLocation().getPath(); | ||
249 | + assertThat(location, Matchers.startsWith("/tenants/" + tenantId2)); | ||
250 | + | ||
251 | + verify(mockVnetAdminService); | ||
252 | + } | ||
253 | + | ||
254 | + /** | ||
255 | + * Tests adding of a null tenant id using POST via JSON stream. | ||
256 | + */ | ||
257 | + @Test | ||
258 | + public void testPostNullTenantId() { | ||
259 | + | ||
260 | + replay(mockVnetAdminService); | ||
261 | + | ||
262 | + WebTarget wt = target(); | ||
263 | + try { | ||
264 | + String response = wt.path("tenants") | ||
265 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
266 | + .post(Entity.json(null), String.class); | ||
267 | + fail("POST of null tenant id did not throw an exception"); | ||
268 | + } catch (BadRequestException ex) { | ||
269 | + assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request")); | ||
270 | + } | ||
271 | + | ||
272 | + verify(mockVnetAdminService); | ||
273 | + } | ||
274 | + | ||
275 | + /** | ||
276 | + * Tests removing a tenant id with DELETE request. | ||
277 | + */ | ||
278 | + @Test | ||
279 | + public void testDelete() { | ||
280 | + expect(mockVnetAdminService.getTenantIds()) | ||
281 | + .andReturn(ImmutableSet.of(tenantId2)).anyTimes(); | ||
282 | + mockVnetAdminService.unregisterTenantId(anyObject()); | ||
283 | + expectLastCall(); | ||
284 | + replay(mockVnetAdminService); | ||
285 | + | ||
286 | + WebTarget wt = target() | ||
287 | + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); | ||
288 | + Response response = wt.path("tenants/" + tenantId2) | ||
289 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
290 | + .delete(); | ||
291 | + | ||
292 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); | ||
293 | + | ||
294 | + verify(mockVnetAdminService); | ||
295 | + } | ||
296 | + | ||
297 | + /** | ||
298 | + * Tests removing a tenant id with DELETE request via JSON stream. | ||
299 | + */ | ||
300 | + @Test | ||
301 | + public void testDeleteViaJson() { | ||
302 | + mockVnetAdminService.unregisterTenantId(anyObject()); | ||
303 | + expectLastCall(); | ||
304 | + replay(mockVnetAdminService); | ||
305 | + | ||
306 | + WebTarget wt = target() | ||
307 | + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); | ||
308 | + InputStream jsonStream = TenantWebResourceTest.class | ||
309 | + .getResourceAsStream("post-tenant.json"); | ||
310 | + Response response = wt.request().method("DELETE", Entity.json(jsonStream)); | ||
311 | + | ||
312 | +// assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); | ||
313 | + | ||
314 | +// verify(mockVnetAdminService); | ||
315 | + } | ||
316 | + | ||
317 | + /** | ||
318 | + * Tests that a DELETE of a non-existent tenant id throws an exception. | ||
319 | + */ | ||
320 | + @Test | ||
321 | + public void testDeleteNonExistentDeviceKey() { | ||
322 | + expect(mockVnetAdminService.getTenantIds()) | ||
323 | + .andReturn(ImmutableSet.of()) | ||
324 | + .anyTimes(); | ||
325 | + expectLastCall(); | ||
326 | + | ||
327 | + replay(mockVnetAdminService); | ||
328 | + | ||
329 | + WebTarget wt = target(); | ||
330 | + | ||
331 | + try { | ||
332 | + wt.path("tenants/" + "NON_EXISTENT_TENANT_ID") | ||
333 | + .request() | ||
334 | + .delete(String.class); | ||
335 | + fail("Delete of a non-existent tenant did not throw an exception"); | ||
336 | + } catch (NotFoundException ex) { | ||
337 | + assertThat(ex.getMessage(), containsString("HTTP 404 Not Found")); | ||
338 | + } | ||
339 | + | ||
340 | + verify(mockVnetAdminService); | ||
341 | + } | ||
342 | +} |
1 | +/* | ||
2 | + * Copyright 2016 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.rest.resources; | ||
18 | + | ||
19 | +import com.eclipsesource.json.Json; | ||
20 | +import com.eclipsesource.json.JsonArray; | ||
21 | +import com.eclipsesource.json.JsonObject; | ||
22 | +import com.google.common.collect.ImmutableList; | ||
23 | +import com.google.common.collect.ImmutableSet; | ||
24 | +import org.glassfish.jersey.client.ClientProperties; | ||
25 | +import org.hamcrest.Description; | ||
26 | +import org.hamcrest.Matchers; | ||
27 | +import org.hamcrest.TypeSafeMatcher; | ||
28 | +import org.junit.Before; | ||
29 | +import org.junit.Test; | ||
30 | +import org.onlab.osgi.ServiceDirectory; | ||
31 | +import org.onlab.osgi.TestServiceDirectory; | ||
32 | +import org.onlab.rest.BaseResource; | ||
33 | +import org.onosproject.codec.CodecService; | ||
34 | +import org.onosproject.codec.impl.CodecManager; | ||
35 | +import org.onosproject.incubator.net.virtual.DefaultVirtualDevice; | ||
36 | +import org.onosproject.incubator.net.virtual.DefaultVirtualNetwork; | ||
37 | +import org.onosproject.incubator.net.virtual.DefaultVirtualPort; | ||
38 | +import org.onosproject.incubator.net.virtual.NetworkId; | ||
39 | +import org.onosproject.incubator.net.virtual.TenantId; | ||
40 | +import org.onosproject.incubator.net.virtual.VirtualDevice; | ||
41 | +import org.onosproject.incubator.net.virtual.VirtualNetwork; | ||
42 | +import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService; | ||
43 | +import org.onosproject.incubator.net.virtual.VirtualNetworkService; | ||
44 | +import org.onosproject.incubator.net.virtual.VirtualPort; | ||
45 | +import org.onosproject.net.DefaultAnnotations; | ||
46 | +import org.onosproject.net.DefaultDevice; | ||
47 | +import org.onosproject.net.DefaultPort; | ||
48 | +import org.onosproject.net.Device; | ||
49 | +import org.onosproject.net.DeviceId; | ||
50 | +import org.onosproject.net.NetTestTools; | ||
51 | +import org.onosproject.net.Port; | ||
52 | +import org.onosproject.net.PortNumber; | ||
53 | + | ||
54 | +import javax.ws.rs.BadRequestException; | ||
55 | +import javax.ws.rs.NotFoundException; | ||
56 | +import javax.ws.rs.client.Entity; | ||
57 | +import javax.ws.rs.client.WebTarget; | ||
58 | +import javax.ws.rs.core.MediaType; | ||
59 | +import javax.ws.rs.core.Response; | ||
60 | +import java.io.InputStream; | ||
61 | +import java.net.HttpURLConnection; | ||
62 | +import java.util.HashSet; | ||
63 | +import java.util.List; | ||
64 | +import java.util.function.BiFunction; | ||
65 | +import java.util.function.BiPredicate; | ||
66 | +import java.util.function.Function; | ||
67 | + | ||
68 | +import static org.easymock.EasyMock.*; | ||
69 | +import static org.hamcrest.Matchers.*; | ||
70 | +import static org.junit.Assert.*; | ||
71 | +import static org.onosproject.net.PortNumber.portNumber; | ||
72 | + | ||
73 | +/** | ||
74 | + * Unit tests for virtual network REST APIs. | ||
75 | + */ | ||
76 | +public class VirtualNetworkWebResourceTest extends ResourceTest { | ||
77 | + | ||
78 | + private final VirtualNetworkAdminService mockVnetAdminService = createMock(VirtualNetworkAdminService.class); | ||
79 | + private final VirtualNetworkService mockVnetService = createMock(VirtualNetworkService.class); | ||
80 | + private CodecManager codecService; | ||
81 | + | ||
82 | + final HashSet<TenantId> tenantIdSet = new HashSet<>(); | ||
83 | + final HashSet<VirtualNetwork> vnetSet = new HashSet<>(); | ||
84 | + final HashSet<VirtualDevice> vdevSet = new HashSet<>(); | ||
85 | + final HashSet<VirtualPort> vportSet = new HashSet<>(); | ||
86 | + | ||
87 | + private static final String ID = "networkId"; | ||
88 | + private static final String TENANT_ID = "tenantId"; | ||
89 | + private static final String DEVICE_ID = "deviceId"; | ||
90 | + private static final String PORT_NUM = "portNum"; | ||
91 | + private static final String PHYS_DEVICE_ID = "physDeviceId"; | ||
92 | + private static final String PHYS_PORT_NUM = "physPortNum"; | ||
93 | + | ||
94 | + private final TenantId tenantId1 = TenantId.tenantId("TenantId1"); | ||
95 | + private final TenantId tenantId2 = TenantId.tenantId("TenantId2"); | ||
96 | + private final TenantId tenantId3 = TenantId.tenantId("TenantId3"); | ||
97 | + private final TenantId tenantId4 = TenantId.tenantId("TenantId4"); | ||
98 | + | ||
99 | + private final NetworkId networkId1 = NetworkId.networkId(1); | ||
100 | + private final NetworkId networkId2 = NetworkId.networkId(2); | ||
101 | + private final NetworkId networkId3 = NetworkId.networkId(3); | ||
102 | + private final NetworkId networkId4 = NetworkId.networkId(4); | ||
103 | + | ||
104 | + private final VirtualNetwork vnet1 = new DefaultVirtualNetwork(networkId1, tenantId3); | ||
105 | + private final VirtualNetwork vnet2 = new DefaultVirtualNetwork(networkId2, tenantId3); | ||
106 | + private final VirtualNetwork vnet3 = new DefaultVirtualNetwork(networkId3, tenantId3); | ||
107 | + private final VirtualNetwork vnet4 = new DefaultVirtualNetwork(networkId4, tenantId3); | ||
108 | + | ||
109 | + private final DeviceId devId1 = DeviceId.deviceId("devId1"); | ||
110 | + private final DeviceId devId2 = DeviceId.deviceId("devId2"); | ||
111 | + private final DeviceId devId22 = DeviceId.deviceId("dev22"); | ||
112 | + | ||
113 | + private final VirtualDevice vdev1 = new DefaultVirtualDevice(networkId3, devId1); | ||
114 | + private final VirtualDevice vdev2 = new DefaultVirtualDevice(networkId3, devId2); | ||
115 | + | ||
116 | + private final Device dev1 = NetTestTools.device("dev1"); | ||
117 | + private final Device dev2 = NetTestTools.device("dev2"); | ||
118 | + private final Device dev22 = NetTestTools.device("dev22"); | ||
119 | + | ||
120 | + Port port1 = new DefaultPort(dev1, portNumber(1), true); | ||
121 | + Port port2 = new DefaultPort(dev2, portNumber(2), true); | ||
122 | + | ||
123 | + private final VirtualPort vport22 = new DefaultVirtualPort(networkId3, | ||
124 | + dev22, portNumber(22), port1); | ||
125 | + private final VirtualPort vport23 = new DefaultVirtualPort(networkId3, | ||
126 | + dev22, portNumber(23), port2); | ||
127 | + | ||
128 | + /** | ||
129 | + * Sets up the global values for all the tests. | ||
130 | + */ | ||
131 | + @Before | ||
132 | + public void setUpTest() { | ||
133 | + // Register the services needed for the test | ||
134 | + codecService = new CodecManager(); | ||
135 | + codecService.activate(); | ||
136 | + ServiceDirectory testDirectory = | ||
137 | + new TestServiceDirectory() | ||
138 | + .add(VirtualNetworkAdminService.class, mockVnetAdminService) | ||
139 | + .add(VirtualNetworkService.class, mockVnetService) | ||
140 | + .add(CodecService.class, codecService); | ||
141 | + | ||
142 | + BaseResource.setServiceDirectory(testDirectory); | ||
143 | + } | ||
144 | + | ||
145 | + /** | ||
146 | + * Hamcrest matcher to check that a virtual network entity representation in JSON matches | ||
147 | + * the actual virtual network entity. | ||
148 | + */ | ||
149 | + public static class JsonObjectMatcher<T> extends TypeSafeMatcher<JsonObject> { | ||
150 | + private final T vnetEntity; | ||
151 | + private List<String> jsonFieldNames; | ||
152 | + private String reason = ""; | ||
153 | + private BiFunction<T, String, String> getValue; // get vnetEntity's value | ||
154 | + | ||
155 | + public JsonObjectMatcher(T vnetEntityValue, | ||
156 | + List<String> jsonFieldNames1, | ||
157 | + BiFunction<T, String, String> getValue1) { | ||
158 | + vnetEntity = vnetEntityValue; | ||
159 | + jsonFieldNames = jsonFieldNames1; | ||
160 | + getValue = getValue1; | ||
161 | + } | ||
162 | + | ||
163 | + @Override | ||
164 | + public boolean matchesSafely(JsonObject jsonHost) { | ||
165 | + return jsonFieldNames | ||
166 | + .stream() | ||
167 | + .allMatch(s -> checkField(jsonHost, s, getValue.apply(vnetEntity, s))); | ||
168 | + } | ||
169 | + | ||
170 | + private boolean checkField(JsonObject jsonHost, String jsonFieldName, | ||
171 | + String objectValue) { | ||
172 | + final String jsonValue = jsonHost.get(jsonFieldName).asString(); | ||
173 | + if (!jsonValue.equals(objectValue)) { | ||
174 | + reason = jsonFieldName + " " + objectValue; | ||
175 | + return false; | ||
176 | + } | ||
177 | + return true; | ||
178 | + } | ||
179 | + | ||
180 | + @Override | ||
181 | + public void describeTo(Description description) { | ||
182 | + description.appendText(reason); | ||
183 | + } | ||
184 | + } | ||
185 | + | ||
186 | + /** | ||
187 | + * Factory to allocate a virtual network id array matcher. | ||
188 | + * | ||
189 | + * @param obj virtual network id object we are looking for | ||
190 | + * @return matcher | ||
191 | + */ | ||
192 | + /** | ||
193 | + * Factory to allocate a virtual network entity matcher. | ||
194 | + * | ||
195 | + * @param obj virtual network object we are looking for | ||
196 | + * @param jsonFieldNames JSON field names to check against | ||
197 | + * @param getValue function to retrieve value from virtual network object | ||
198 | + * @param <T> | ||
199 | + * @return JsonObjectMatcher | ||
200 | + */ | ||
201 | + private static <T> JsonObjectMatcher matchesVnetEntity(T obj, List<String> jsonFieldNames, | ||
202 | + BiFunction<T, String, String> getValue) { | ||
203 | + return new JsonObjectMatcher(obj, jsonFieldNames, getValue); | ||
204 | + } | ||
205 | + | ||
206 | + /** | ||
207 | + * Hamcrest matcher to check that a virtual network entity is represented properly in a JSON | ||
208 | + * array of virtual network entities. | ||
209 | + */ | ||
210 | + public static class JsonArrayMatcher<T> extends TypeSafeMatcher<JsonArray> { | ||
211 | + private final T vnetEntity; | ||
212 | + private String reason = ""; | ||
213 | + private Function<T, String> getKey; // gets vnetEntity's key | ||
214 | + private BiPredicate<T, JsonObject> checkKey; // check vnetEntity's key with JSON rep'n | ||
215 | + private List<String> jsonFieldNames; // field/property names | ||
216 | + private BiFunction<T, String, String> getValue; // get vnetEntity's value | ||
217 | + | ||
218 | + public JsonArrayMatcher(T vnetEntityValue, Function<T, String> getKey1, | ||
219 | + BiPredicate<T, JsonObject> checkKey1, | ||
220 | + List<String> jsonFieldNames1, | ||
221 | + BiFunction<T, String, String> getValue1) { | ||
222 | + vnetEntity = vnetEntityValue; | ||
223 | + getKey = getKey1; | ||
224 | + checkKey = checkKey1; | ||
225 | + jsonFieldNames = jsonFieldNames1; | ||
226 | + getValue = getValue1; | ||
227 | + } | ||
228 | + | ||
229 | + @Override | ||
230 | + public boolean matchesSafely(JsonArray json) { | ||
231 | + boolean itemFound = false; | ||
232 | + final int expectedAttributes = jsonFieldNames.size(); | ||
233 | + for (int jsonArrayIndex = 0; jsonArrayIndex < json.size(); | ||
234 | + jsonArrayIndex++) { | ||
235 | + | ||
236 | + final JsonObject jsonHost = json.get(jsonArrayIndex).asObject(); | ||
237 | + | ||
238 | + if (jsonHost.names().size() < expectedAttributes) { | ||
239 | + reason = "Found a virtual network with the wrong number of attributes"; | ||
240 | + return false; | ||
241 | + } | ||
242 | + | ||
243 | + if (checkKey != null && checkKey.test(vnetEntity, jsonHost)) { | ||
244 | + itemFound = true; | ||
245 | + assertThat(jsonHost, matchesVnetEntity(vnetEntity, jsonFieldNames, getValue)); | ||
246 | + } | ||
247 | + } | ||
248 | + if (!itemFound) { | ||
249 | + reason = getKey.apply(vnetEntity) + " was not found"; | ||
250 | + return false; | ||
251 | + } | ||
252 | + return true; | ||
253 | + } | ||
254 | + | ||
255 | + @Override | ||
256 | + public void describeTo(Description description) { | ||
257 | + description.appendText(reason); | ||
258 | + } | ||
259 | + } | ||
260 | + | ||
261 | + /** | ||
262 | + * Array matcher for VirtualNetwork. | ||
263 | + */ | ||
264 | + public static class VnetJsonArrayMatcher extends JsonArrayMatcher<VirtualNetwork> { | ||
265 | + | ||
266 | + public VnetJsonArrayMatcher(VirtualNetwork vnetIn) { | ||
267 | + super(vnetIn, | ||
268 | + vnet -> "Virtual network " + vnet.id().toString(), | ||
269 | + (vnet, jsonObject) -> { | ||
270 | + return jsonObject.get(ID).asString().equals(vnet.id().toString()); }, | ||
271 | + ImmutableList.of(ID, TENANT_ID), | ||
272 | + (vnet, s) -> { | ||
273 | + return s.equals(ID) ? vnet.id().toString() | ||
274 | + : s.equals(TENANT_ID) ? vnet.tenantId().toString() | ||
275 | + : null; | ||
276 | + } | ||
277 | + ); | ||
278 | + } | ||
279 | + } | ||
280 | + | ||
281 | + /** | ||
282 | + * Factory to allocate a virtual network array matcher. | ||
283 | + * | ||
284 | + * @param vnet virtual network object we are looking for | ||
285 | + * @return matcher | ||
286 | + */ | ||
287 | + private VnetJsonArrayMatcher hasVnet(VirtualNetwork vnet) { | ||
288 | + return new VnetJsonArrayMatcher(vnet); | ||
289 | + } | ||
290 | + | ||
291 | + // Tests for Virtual Networks | ||
292 | + | ||
293 | + /** | ||
294 | + * Tests the result of the REST API GET when there are no virtual networks. | ||
295 | + */ | ||
296 | + @Test | ||
297 | + public void testGetVirtualNetworksEmptyArray() { | ||
298 | + expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of()).anyTimes(); | ||
299 | + replay(mockVnetAdminService); | ||
300 | + expect(mockVnetService.getVirtualNetworks(tenantId4)).andReturn(ImmutableSet.of()).anyTimes(); | ||
301 | + replay(mockVnetService); | ||
302 | + | ||
303 | + WebTarget wt = target(); | ||
304 | + String response = wt.path("vnets").request().get(String.class); | ||
305 | + assertThat(response, is("{\"vnets\":[]}")); | ||
306 | + | ||
307 | + verify(mockVnetService); | ||
308 | + verify(mockVnetAdminService); | ||
309 | + } | ||
310 | + | ||
311 | + /** | ||
312 | + * Tests the result of the REST API GET when virtual networks are defined. | ||
313 | + */ | ||
314 | + @Test | ||
315 | + public void testGetVirtualNetworksArray() { | ||
316 | + expect(mockVnetAdminService.getTenantIds()).andReturn(ImmutableSet.of(tenantId3)).anyTimes(); | ||
317 | + replay(mockVnetAdminService); | ||
318 | + vnetSet.add(vnet1); | ||
319 | + vnetSet.add(vnet2); | ||
320 | + vnetSet.add(vnet3); | ||
321 | + vnetSet.add(vnet4); | ||
322 | + expect(mockVnetService.getVirtualNetworks(tenantId3)).andReturn(vnetSet).anyTimes(); | ||
323 | + replay(mockVnetService); | ||
324 | + | ||
325 | + WebTarget wt = target(); | ||
326 | + String response = wt.path("vnets").request().get(String.class); | ||
327 | + assertThat(response, containsString("{\"vnets\":[")); | ||
328 | + | ||
329 | + final JsonObject result = Json.parse(response).asObject(); | ||
330 | + assertThat(result, notNullValue()); | ||
331 | + | ||
332 | + assertThat(result.names(), hasSize(1)); | ||
333 | + assertThat(result.names().get(0), is("vnets")); | ||
334 | + | ||
335 | + final JsonArray vnetJsonArray = result.get("vnets").asArray(); | ||
336 | + assertThat(vnetJsonArray, notNullValue()); | ||
337 | + assertEquals("Virtual networks array is not the correct size.", | ||
338 | + vnetSet.size(), vnetJsonArray.size()); | ||
339 | + | ||
340 | + vnetSet.forEach(vnet -> assertThat(vnetJsonArray, hasVnet(vnet))); | ||
341 | + | ||
342 | + verify(mockVnetService); | ||
343 | + verify(mockVnetAdminService); | ||
344 | + } | ||
345 | + | ||
346 | + /** | ||
347 | + * Tests adding of new virtual network using POST via JSON stream. | ||
348 | + */ | ||
349 | + @Test | ||
350 | + public void testPostVirtualNetwork() { | ||
351 | + expect(mockVnetAdminService.createVirtualNetwork(tenantId2)).andReturn(vnet1); | ||
352 | + expectLastCall(); | ||
353 | + | ||
354 | + replay(mockVnetAdminService); | ||
355 | + | ||
356 | + WebTarget wt = target(); | ||
357 | + InputStream jsonStream = TenantWebResourceTest.class | ||
358 | + .getResourceAsStream("post-tenant.json"); | ||
359 | + | ||
360 | + Response response = wt.path("vnets").request(MediaType.APPLICATION_JSON_TYPE) | ||
361 | + .post(Entity.json(jsonStream)); | ||
362 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED)); | ||
363 | + | ||
364 | + String location = response.getLocation().getPath(); | ||
365 | + assertThat(location, Matchers.startsWith("/vnets/" + vnet1.id().toString())); | ||
366 | + | ||
367 | + verify(mockVnetAdminService); | ||
368 | + } | ||
369 | + | ||
370 | + /** | ||
371 | + * Tests adding of a null virtual network using POST via JSON stream. | ||
372 | + */ | ||
373 | + @Test | ||
374 | + public void testPostVirtualNetworkNullTenantId() { | ||
375 | + | ||
376 | + replay(mockVnetAdminService); | ||
377 | + | ||
378 | + WebTarget wt = target(); | ||
379 | + try { | ||
380 | + String response = wt.path("vnets") | ||
381 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
382 | + .post(Entity.json(null), String.class); | ||
383 | + fail("POST of null virtual network did not throw an exception"); | ||
384 | + } catch (BadRequestException ex) { | ||
385 | + assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request")); | ||
386 | + } | ||
387 | + | ||
388 | + verify(mockVnetAdminService); | ||
389 | + } | ||
390 | + | ||
391 | + /** | ||
392 | + * Tests removing a virtual network with DELETE request. | ||
393 | + */ | ||
394 | + @Test | ||
395 | + public void testDeleteVirtualNetwork() { | ||
396 | + mockVnetAdminService.removeVirtualNetwork(anyObject()); | ||
397 | + expectLastCall(); | ||
398 | + replay(mockVnetAdminService); | ||
399 | + | ||
400 | + WebTarget wt = target() | ||
401 | + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); | ||
402 | + Response response = wt.path("vnets/" + "2") | ||
403 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
404 | + .delete(); | ||
405 | + | ||
406 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); | ||
407 | + | ||
408 | + verify(mockVnetAdminService); | ||
409 | + } | ||
410 | + | ||
411 | + /** | ||
412 | + * Tests that a DELETE of a non-existent virtual network throws an exception. | ||
413 | + */ | ||
414 | + @Test | ||
415 | + public void testDeleteNetworkNonExistentNetworkId() { | ||
416 | + expect(mockVnetAdminService.getTenantIds()) | ||
417 | + .andReturn(ImmutableSet.of()) | ||
418 | + .anyTimes(); | ||
419 | + expectLastCall(); | ||
420 | + | ||
421 | + replay(mockVnetAdminService); | ||
422 | + | ||
423 | + WebTarget wt = target(); | ||
424 | + | ||
425 | + try { | ||
426 | + wt.path("vnets/" + "NON_EXISTENT_NETWORK_ID") | ||
427 | + .request() | ||
428 | + .delete(String.class); | ||
429 | + fail("Delete of a non-existent virtual network did not throw an exception"); | ||
430 | + } catch (NotFoundException ex) { | ||
431 | + assertThat(ex.getMessage(), containsString("HTTP 404 Not Found")); | ||
432 | + } | ||
433 | + | ||
434 | + verify(mockVnetAdminService); | ||
435 | + } | ||
436 | + | ||
437 | + // Tests for Virtual Device | ||
438 | + | ||
439 | + /** | ||
440 | + * Tests the result of the REST API GET when there are no virtual devices. | ||
441 | + */ | ||
442 | + @Test | ||
443 | + public void testGetVirtualDevicesEmptyArray() { | ||
444 | + NetworkId networkId = networkId4; | ||
445 | + expect(mockVnetService.getVirtualDevices(networkId)).andReturn(ImmutableSet.of()).anyTimes(); | ||
446 | + replay(mockVnetService); | ||
447 | + | ||
448 | + WebTarget wt = target(); | ||
449 | + String location = "vnets/" + networkId.toString() + "/devices"; | ||
450 | + String response = wt.path(location).request().get(String.class); | ||
451 | + assertThat(response, is("{\"devices\":[]}")); | ||
452 | + | ||
453 | + verify(mockVnetService); | ||
454 | + } | ||
455 | + | ||
456 | + /** | ||
457 | + * Tests the result of the REST API GET when virtual devices are defined. | ||
458 | + */ | ||
459 | + @Test | ||
460 | + public void testGetVirtualDevicesArray() { | ||
461 | + NetworkId networkId = networkId3; | ||
462 | + vdevSet.add(vdev1); | ||
463 | + vdevSet.add(vdev2); | ||
464 | + expect(mockVnetService.getVirtualDevices(networkId)).andReturn(vdevSet).anyTimes(); | ||
465 | + replay(mockVnetService); | ||
466 | + | ||
467 | + WebTarget wt = target(); | ||
468 | + String location = "vnets/" + networkId.toString() + "/devices"; | ||
469 | + String response = wt.path(location).request().get(String.class); | ||
470 | + assertThat(response, containsString("{\"devices\":[")); | ||
471 | + | ||
472 | + final JsonObject result = Json.parse(response).asObject(); | ||
473 | + assertThat(result, notNullValue()); | ||
474 | + | ||
475 | + assertThat(result.names(), hasSize(1)); | ||
476 | + assertThat(result.names().get(0), is("devices")); | ||
477 | + | ||
478 | + final JsonArray vnetJsonArray = result.get("devices").asArray(); | ||
479 | + assertThat(vnetJsonArray, notNullValue()); | ||
480 | + assertEquals("Virtual devices array is not the correct size.", | ||
481 | + vdevSet.size(), vnetJsonArray.size()); | ||
482 | + | ||
483 | + vdevSet.forEach(vdev -> assertThat(vnetJsonArray, hasVdev(vdev))); | ||
484 | + | ||
485 | + verify(mockVnetService); | ||
486 | + } | ||
487 | + | ||
488 | + /** | ||
489 | + * Array matcher for VirtualDevice. | ||
490 | + */ | ||
491 | + public static class VdevJsonArrayMatcher extends JsonArrayMatcher<VirtualDevice> { | ||
492 | + | ||
493 | + public VdevJsonArrayMatcher(VirtualDevice vdevIn) { | ||
494 | + super(vdevIn, | ||
495 | + vdev -> "Virtual device " + vdev.networkId().toString() | ||
496 | + + " " + vdev.id().toString(), | ||
497 | + (vdev, jsonObject) -> { | ||
498 | + return jsonObject.get(ID).asString().equals(vdev.networkId().toString()) | ||
499 | + && jsonObject.get(DEVICE_ID).asString().equals(vdev.id().toString()); }, | ||
500 | + ImmutableList.of(ID, DEVICE_ID), | ||
501 | + (vdev, s) -> { | ||
502 | + return s.equals(ID) ? vdev.networkId().toString() | ||
503 | + : s.equals(DEVICE_ID) ? vdev.id().toString() | ||
504 | + : null; | ||
505 | + } | ||
506 | + ); | ||
507 | + } | ||
508 | + } | ||
509 | + | ||
510 | + /** | ||
511 | + * Factory to allocate a virtual device array matcher. | ||
512 | + * | ||
513 | + * @param vdev virtual device object we are looking for | ||
514 | + * @return matcher | ||
515 | + */ | ||
516 | + private VdevJsonArrayMatcher hasVdev(VirtualDevice vdev) { | ||
517 | + return new VdevJsonArrayMatcher(vdev); | ||
518 | + } | ||
519 | + /** | ||
520 | + * Tests adding of new virtual device using POST via JSON stream. | ||
521 | + */ | ||
522 | + @Test | ||
523 | + public void testPostVirtualDevice() { | ||
524 | + NetworkId networkId = networkId3; | ||
525 | + DeviceId deviceId = devId2; | ||
526 | + expect(mockVnetAdminService.createVirtualDevice(networkId, deviceId)).andReturn(vdev2); | ||
527 | + expectLastCall(); | ||
528 | + | ||
529 | + replay(mockVnetAdminService); | ||
530 | + | ||
531 | + WebTarget wt = target(); | ||
532 | + InputStream jsonStream = VirtualNetworkWebResourceTest.class | ||
533 | + .getResourceAsStream("post-virtual-device.json"); | ||
534 | + String reqLocation = "vnets/" + networkId.toString() + "/devices"; | ||
535 | + Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE) | ||
536 | + .post(Entity.json(jsonStream)); | ||
537 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED)); | ||
538 | + | ||
539 | + String location = response.getLocation().getPath(); | ||
540 | + assertThat(location, Matchers.startsWith("/" + reqLocation + "/" + vdev2.id().toString())); | ||
541 | + | ||
542 | + verify(mockVnetAdminService); | ||
543 | + } | ||
544 | + | ||
545 | + /** | ||
546 | + * Tests adding of a null virtual device using POST via JSON stream. | ||
547 | + */ | ||
548 | + @Test | ||
549 | + public void testPostVirtualDeviceNullJsonStream() { | ||
550 | + NetworkId networkId = networkId3; | ||
551 | + replay(mockVnetAdminService); | ||
552 | + | ||
553 | + WebTarget wt = target(); | ||
554 | + try { | ||
555 | + String reqLocation = "vnets/" + networkId.toString() + "/devices"; | ||
556 | + String response = wt.path(reqLocation) | ||
557 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
558 | + .post(Entity.json(null), String.class); | ||
559 | + fail("POST of null virtual device did not throw an exception"); | ||
560 | + } catch (BadRequestException ex) { | ||
561 | + assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request")); | ||
562 | + } | ||
563 | + | ||
564 | + verify(mockVnetAdminService); | ||
565 | + } | ||
566 | + | ||
567 | + /** | ||
568 | + * Tests removing a virtual device with DELETE request. | ||
569 | + */ | ||
570 | + @Test | ||
571 | + public void testDeleteVirtualDevice() { | ||
572 | + NetworkId networkId = networkId3; | ||
573 | + DeviceId deviceId = devId2; | ||
574 | + mockVnetAdminService.removeVirtualDevice(networkId, deviceId); | ||
575 | + expectLastCall(); | ||
576 | + replay(mockVnetAdminService); | ||
577 | + | ||
578 | + WebTarget wt = target() | ||
579 | + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); | ||
580 | + String reqLocation = "vnets/" + networkId.toString() + "/devices/" + deviceId.toString(); | ||
581 | + Response response = wt.path(reqLocation) | ||
582 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
583 | + .delete(); | ||
584 | + | ||
585 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); | ||
586 | + | ||
587 | + verify(mockVnetAdminService); | ||
588 | + } | ||
589 | + | ||
590 | + // Tests for Virtual Ports | ||
591 | + | ||
592 | + /** | ||
593 | + * Tests the result of the REST API GET when there are no virtual ports. | ||
594 | + */ | ||
595 | + @Test | ||
596 | + public void testGetVirtualPortsEmptyArray() { | ||
597 | + NetworkId networkId = networkId4; | ||
598 | + DeviceId deviceId = devId2; | ||
599 | + expect(mockVnetService.getVirtualPorts(networkId, deviceId)) | ||
600 | + .andReturn(ImmutableSet.of()).anyTimes(); | ||
601 | + replay(mockVnetService); | ||
602 | + | ||
603 | + WebTarget wt = target(); | ||
604 | + String location = "vnets/" + networkId.toString() | ||
605 | + + "/devices/" + deviceId.toString() + "/ports"; | ||
606 | + String response = wt.path(location).request().get(String.class); | ||
607 | + assertThat(response, is("{\"ports\":[]}")); | ||
608 | + | ||
609 | + verify(mockVnetService); | ||
610 | + } | ||
611 | + | ||
612 | + /** | ||
613 | + * Tests the result of the REST API GET when virtual ports are defined. | ||
614 | + */ | ||
615 | + @Test | ||
616 | + public void testGetVirtualPortsArray() { | ||
617 | + NetworkId networkId = networkId3; | ||
618 | + DeviceId deviceId = dev22.id(); | ||
619 | + vportSet.add(vport23); | ||
620 | + vportSet.add(vport22); | ||
621 | + expect(mockVnetService.getVirtualPorts(networkId, deviceId)).andReturn(vportSet).anyTimes(); | ||
622 | + replay(mockVnetService); | ||
623 | + | ||
624 | + WebTarget wt = target(); | ||
625 | + String location = "vnets/" + networkId.toString() | ||
626 | + + "/devices/" + deviceId.toString() + "/ports"; | ||
627 | + String response = wt.path(location).request().get(String.class); | ||
628 | + assertThat(response, containsString("{\"ports\":[")); | ||
629 | + | ||
630 | + final JsonObject result = Json.parse(response).asObject(); | ||
631 | + assertThat(result, notNullValue()); | ||
632 | + | ||
633 | + assertThat(result.names(), hasSize(1)); | ||
634 | + assertThat(result.names().get(0), is("ports")); | ||
635 | + | ||
636 | + final JsonArray vnetJsonArray = result.get("ports").asArray(); | ||
637 | + assertThat(vnetJsonArray, notNullValue()); | ||
638 | + assertEquals("Virtual ports array is not the correct size.", | ||
639 | + vportSet.size(), vnetJsonArray.size()); | ||
640 | + | ||
641 | + vportSet.forEach(vport -> assertThat(vnetJsonArray, hasVport(vport))); | ||
642 | + | ||
643 | + verify(mockVnetService); | ||
644 | + } | ||
645 | + | ||
646 | + /** | ||
647 | + * Array matcher for VirtualPort. | ||
648 | + */ | ||
649 | + public static class VportJsonArrayMatcher extends JsonArrayMatcher<VirtualPort> { | ||
650 | + | ||
651 | + public VportJsonArrayMatcher(VirtualPort vportIn) { | ||
652 | + super(vportIn, | ||
653 | + vport -> "Virtual port " + vport.networkId().toString() + " " | ||
654 | + + vport.element().id().toString() + " " + vport.number().toString(), | ||
655 | + (vport, jsonObject) -> { | ||
656 | + return jsonObject.get(ID).asString().equals(vport.networkId().toString()) | ||
657 | + && jsonObject.get(PORT_NUM).asString().equals(vport.number().toString()) | ||
658 | + && jsonObject.get(DEVICE_ID).asString().equals(vport.element().id().toString()); }, | ||
659 | + ImmutableList.of(ID, DEVICE_ID, PORT_NUM, PHYS_DEVICE_ID, PHYS_PORT_NUM), | ||
660 | + (vport, s) -> { | ||
661 | + return s.equals(ID) ? vport.networkId().toString() | ||
662 | + : s.equals(DEVICE_ID) ? vport.element().id().toString() | ||
663 | + : s.equals(PORT_NUM) ? vport.number().toString() | ||
664 | + : s.equals(PHYS_DEVICE_ID) ? vport.realizedBy().element().id().toString() | ||
665 | + : s.equals(PHYS_PORT_NUM) ? vport.realizedBy().number().toString() | ||
666 | + : null; | ||
667 | + } | ||
668 | + ); | ||
669 | + } | ||
670 | + } | ||
671 | + | ||
672 | + /** | ||
673 | + * Factory to allocate a virtual port array matcher. | ||
674 | + * | ||
675 | + * @param vport virtual port object we are looking for | ||
676 | + * @return matcher | ||
677 | + */ | ||
678 | + private VportJsonArrayMatcher hasVport(VirtualPort vport) { | ||
679 | + return new VportJsonArrayMatcher(vport); | ||
680 | + } | ||
681 | + | ||
682 | + /** | ||
683 | + * Tests adding of new virtual port using POST via JSON stream. | ||
684 | + */ | ||
685 | + @Test | ||
686 | + public void testPostVirtualPort() { | ||
687 | + NetworkId networkId = networkId3; | ||
688 | + DeviceId deviceId = devId22; | ||
689 | + DefaultAnnotations annotations = DefaultAnnotations.builder().build(); | ||
690 | + Device physDevice = new DefaultDevice(null, DeviceId.deviceId("dev1"), | ||
691 | + null, null, null, null, null, null, annotations); | ||
692 | + Port port1 = new DefaultPort(physDevice, portNumber(1), true); | ||
693 | + expect(mockVnetAdminService.createVirtualPort(networkId, deviceId, portNumber(22), port1)) | ||
694 | + .andReturn(vport22); | ||
695 | + | ||
696 | + replay(mockVnetAdminService); | ||
697 | + | ||
698 | + WebTarget wt = target(); | ||
699 | + InputStream jsonStream = VirtualNetworkWebResourceTest.class | ||
700 | + .getResourceAsStream("post-virtual-port.json"); | ||
701 | + String reqLocation = "vnets/" + networkId.toString() | ||
702 | + + "/devices/" + deviceId.toString() + "/ports"; | ||
703 | + Response response = wt.path(reqLocation).request(MediaType.APPLICATION_JSON_TYPE) | ||
704 | + .post(Entity.json(jsonStream)); | ||
705 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED)); | ||
706 | + | ||
707 | + verify(mockVnetAdminService); | ||
708 | + } | ||
709 | + | ||
710 | + /** | ||
711 | + * Tests adding of a null virtual port using POST via JSON stream. | ||
712 | + */ | ||
713 | + @Test | ||
714 | + public void testPostVirtualPortNullJsonStream() { | ||
715 | + NetworkId networkId = networkId3; | ||
716 | + DeviceId deviceId = devId2; | ||
717 | + replay(mockVnetAdminService); | ||
718 | + | ||
719 | + WebTarget wt = target(); | ||
720 | + try { | ||
721 | + String reqLocation = "vnets/" + networkId.toString() | ||
722 | + + "/devices/" + deviceId.toString() + "/ports"; | ||
723 | + String response = wt.path(reqLocation) | ||
724 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
725 | + .post(Entity.json(null), String.class); | ||
726 | + fail("POST of null virtual port did not throw an exception"); | ||
727 | + } catch (BadRequestException ex) { | ||
728 | + assertThat(ex.getMessage(), containsString("HTTP 400 Bad Request")); | ||
729 | + } | ||
730 | + | ||
731 | + verify(mockVnetAdminService); | ||
732 | + } | ||
733 | + | ||
734 | + /** | ||
735 | + * Tests removing a virtual port with DELETE request. | ||
736 | + */ | ||
737 | + @Test | ||
738 | + public void testDeleteVirtualPort() { | ||
739 | + NetworkId networkId = networkId3; | ||
740 | + DeviceId deviceId = devId2; | ||
741 | + PortNumber portNum = portNumber(2); | ||
742 | + mockVnetAdminService.removeVirtualPort(networkId, deviceId, portNum); | ||
743 | + expectLastCall(); | ||
744 | + replay(mockVnetAdminService); | ||
745 | + | ||
746 | + WebTarget wt = target() | ||
747 | + .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true); | ||
748 | + String reqLocation = "vnets/" + networkId.toString() | ||
749 | + + "/devices/" + deviceId.toString() + "/ports/" + portNum.toLong(); | ||
750 | + Response response = wt.path(reqLocation) | ||
751 | + .request(MediaType.APPLICATION_JSON_TYPE) | ||
752 | + .delete(); | ||
753 | + | ||
754 | + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK)); | ||
755 | + | ||
756 | + verify(mockVnetAdminService); | ||
757 | + } | ||
758 | + | ||
759 | + // TODO Tests for Virtual Links | ||
760 | +} |
-
Please register or login to post a comment