blob: fed5e91b6e6029d0ea5a584dc0a0ee19ff97b33d [file] [log] [blame]
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -07001/*
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 */
Hyunsun Moon187bf532017-01-19 10:57:40 +090016package org.opencord.cordvtn.rest;
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070017
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.SerializationFeature;
20import com.fasterxml.jackson.databind.node.ObjectNode;
21import com.google.common.base.Strings;
22import com.google.common.collect.ImmutableSet;
23import org.glassfish.jersey.client.ClientProperties;
24import org.onlab.util.Tools;
25import org.onosproject.rest.AbstractWebResource;
26import org.opencord.cordvtn.api.net.NetworkId;
27import org.opencord.cordvtn.api.net.PortId;
28import org.opencord.cordvtn.api.net.ServiceNetwork;
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070029import org.opencord.cordvtn.api.net.ServicePort;
30import org.slf4j.Logger;
31
32import javax.ws.rs.client.Client;
33import javax.ws.rs.client.ClientBuilder;
34import javax.ws.rs.client.Invocation;
35import javax.ws.rs.client.WebTarget;
36import javax.ws.rs.core.Response;
37import java.io.IOException;
38import java.util.Set;
39import java.util.stream.Collectors;
40
41import static com.google.common.base.Preconditions.checkArgument;
42import static com.google.common.net.MediaType.JSON_UTF_8;
43import static java.net.HttpURLConnection.HTTP_OK;
44import static org.slf4j.LoggerFactory.getLogger;
45
46/**
Hyunsun Moon187bf532017-01-19 10:57:40 +090047 * Implementation of REST client for XOS VTN networking service.
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070048 */
Hyunsun Moon187bf532017-01-19 10:57:40 +090049public final class XosVtnNetworkingClient extends AbstractWebResource {
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070050
51 protected final Logger log = getLogger(getClass());
52
53 private static final String URL_BASE = "/api/service/vtn/";
54 private static final String URL_SERVICE_NETWORKS = "serviceNetworks/";
55 private static final String URL_SERVICE_PORTS = "servicePorts/";
56
57 private static final String SERVICE_PORTS = "servicePorts";
58 private static final String SERVICE_PORT = "servicePort";
59 private static final String SERVICE_NETWORKS = "serviceNetworks";
60 private static final String SERVICE_NETWORK = "serviceNetwork";
61 private static final String EMPTY_JSON_STRING = "{}";
62
63 private static final String MSG_RECEIVED = "Received ";
64 private static final String ERR_LOG = "Received %s result with wrong format: %s";
65
66 private static final int DEFAULT_TIMEOUT_MS = 2000;
67
68 private final String endpoint;
69 private final String user;
70 private final String password;
71 private final Client client = ClientBuilder.newClient();
72
Hyunsun Moon187bf532017-01-19 10:57:40 +090073 private XosVtnNetworkingClient(String endpoint, String user, String password) {
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070074 this.endpoint = endpoint;
75 this.user = user;
76 this.password = password;
77
78 client.property(ClientProperties.CONNECT_TIMEOUT, DEFAULT_TIMEOUT_MS);
79 client.property(ClientProperties.READ_TIMEOUT, DEFAULT_TIMEOUT_MS);
80 mapper().enable(SerializationFeature.INDENT_OUTPUT);
81 }
82
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -070083 public Set<ServiceNetwork> serviceNetworks() {
84 String response = restGet(URL_SERVICE_NETWORKS);
85 final String error = String.format(ERR_LOG, SERVICE_NETWORKS, response);
86 try {
87 JsonNode jsonTree = mapper().readTree(response).get(SERVICE_NETWORKS);
88 if (jsonTree == null) {
89 return ImmutableSet.of();
90 }
91 log.trace(MSG_RECEIVED + SERVICE_NETWORKS);
92 log.trace(mapper().writeValueAsString(jsonTree));
93 return Tools.stream(jsonTree).map(snet -> codec(ServiceNetwork.class)
94 .decode((ObjectNode) snet, this))
95 .collect(Collectors.toSet());
96 } catch (IOException e) {
97 throw new IllegalArgumentException(error);
98 }
99 }
100
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -0700101 public ServiceNetwork serviceNetwork(NetworkId netId) {
102 String response = restGet(URL_SERVICE_NETWORKS + netId.id());
103 final String error = String.format(ERR_LOG, SERVICE_NETWORK, response);
104 try {
105 JsonNode jsonTree = mapper().readTree(response).get(SERVICE_NETWORK);
106 if (jsonTree == null) {
107 throw new IllegalArgumentException(error);
108 }
109 log.trace(MSG_RECEIVED + SERVICE_NETWORK);
110 log.trace(mapper().writeValueAsString(jsonTree));
111 return codec(ServiceNetwork.class).decode((ObjectNode) jsonTree, this);
112 } catch (IOException e) {
113 throw new IllegalArgumentException(error);
114 }
115 }
116
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -0700117 public Set<ServicePort> servicePorts() {
118 String response = restGet(URL_SERVICE_PORTS);
119 final String error = String.format(ERR_LOG, SERVICE_PORTS, response);
120 try {
121 JsonNode jsonTree = mapper().readTree(response).get(SERVICE_PORTS);
122 if (jsonTree == null) {
123 ImmutableSet.of();
124 }
125 log.trace(MSG_RECEIVED + SERVICE_PORTS);
126 log.trace(mapper().writeValueAsString(jsonTree));
127 return Tools.stream(jsonTree).map(sport -> codec(ServicePort.class)
128 .decode((ObjectNode) sport, this))
129 .collect(Collectors.toSet());
130 } catch (IOException e) {
131 throw new IllegalArgumentException(error);
132 }
133 }
134
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -0700135 public ServicePort servicePort(PortId portId) {
136 String response = restGet(URL_SERVICE_PORTS + portId.id());
137 final String error = String.format(ERR_LOG, SERVICE_PORT, response);
138 try {
139 JsonNode jsonTree = mapper().readTree(response).get(SERVICE_PORT);
140 if (jsonTree == null) {
141 throw new IllegalArgumentException(error);
142 }
143 log.trace(MSG_RECEIVED + SERVICE_PORT);
144 log.trace(mapper().writeValueAsString(jsonTree));
145 return codec(ServicePort.class).decode((ObjectNode) jsonTree, this);
146 } catch (IOException e) {
147 throw new IllegalArgumentException(error);
148 }
149 }
150
151 private String restGet(String path) {
152 WebTarget wt = client.target(endpoint + URL_BASE).path(path);
153 Invocation.Builder builder = wt.request(JSON_UTF_8.toString());
154 try {
155 Response response = builder.get();
156 if (response.getStatus() != HTTP_OK) {
157 log.warn("Failed to get resource {}", endpoint + path);
158 return EMPTY_JSON_STRING;
159 }
160 } catch (javax.ws.rs.ProcessingException e) {
161 return EMPTY_JSON_STRING;
162 }
163 return builder.get(String.class);
164 }
165
166 /**
167 * Returns endpoint url for the XOS service API access.
168 *
169 * @return endpoint url as a string
170 */
171 public String endpoint() {
172 return endpoint;
173 }
174
175 /**
176 * Returns user name for the XOS service API access.
177 *
178 * @return user name as a string
179 */
180 public String user() {
181 return user;
182 }
183
184 /**
185 * Returns password for the XOS service API access.
186 *
187 * @return password as a string
188 */
189 public String password() {
190 return password;
191 }
192
193 /**
194 * Returns new XOS service networking builder instance.
195 *
196 * @return xos service networking builder
197 */
198 public static Builder builder() {
199 return new Builder();
200 }
201
202 /**
203 * Builder of the XOS service networking entities.
204 */
205 public static final class Builder {
206
207 private String endpoint;
208 private String user;
209 private String password;
210
211 private Builder() {
212 }
213
214 /**
215 * Builds immutable XOS service networking instance.
216 *
217 * @return xos service networking instance
218 */
Hyunsun Moon187bf532017-01-19 10:57:40 +0900219 public XosVtnNetworkingClient build() {
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -0700220 checkArgument(!Strings.isNullOrEmpty(endpoint));
221 checkArgument(!Strings.isNullOrEmpty(user));
222 checkArgument(!Strings.isNullOrEmpty(password));
223
224 // TODO perform authentication when XOS provides it
Hyunsun Moon187bf532017-01-19 10:57:40 +0900225 return new XosVtnNetworkingClient(endpoint, user, password);
Hyunsun Moon4a94c2e2016-10-21 17:37:05 -0700226 }
227
228 /**
229 * Returns XOS service networking builder with the supplied endpoint.
230 *
231 * @param endpoint endpoint url
232 * @return xos service networking builder
233 */
234 public Builder endpoint(String endpoint) {
235 this.endpoint = endpoint;
236 return this;
237 }
238
239 /**
240 * Returns XOS service networking builder with the supplied user
241 * credential.
242 *
243 * @param user user
244 * @return xos service networking builder
245 */
246 public Builder user(String user) {
247 this.user = user;
248 return this;
249 }
250
251 /**
252 * Returns XOS service networking builder with the supplied password
253 * credential.
254 *
255 * @param password password
256 * @return xos service networking builder
257 */
258 public Builder password(String password) {
259 this.password = password;
260 return this;
261 }
262 }
263}