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