Hyunsun Moon
Committed by Gerrit Code Review

CORD-433 Implemented XOS REST client and cordvtn service API

Change-Id: I4324240e1cdc9c0b059757565e20fdab995b9e5d
......@@ -72,7 +72,8 @@
<module>influxdbmetrics</module>
<module>gangliametrics</module>
<module>graphitemetrics</module>
</modules>
<module>xosclient</module>
</modules>
<properties>
<web.context>default</web.context>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>onos-apps</artifactId>
<groupId>org.onosproject</groupId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-xos-client</artifactId>
<packaging>bundle</packaging>
<description>XOS client service</description>
<properties>
<onos.app.name>org.onosproject.xosclient</onos.app.name>
<onos.app.title>XOS Client App</onos.app.title>
<onos.app.category>Utility</onos.app.category>
<onos.app.url>http://onosproject.org</onos.app.url>
<onos.app.readme>XOS Client Application.</onos.app.readme>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
</dependencies>
</project>
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.api;
import java.util.Set;
/**
* Service for interacting with XOS VTN service and service dependency.
*/
public interface VtnServiceApi {
/**
* Returns all services list.
*
* @return service list
*/
Set<String> services();
/**
* Returns dependent tenant services of a given provider service.
*
* @param pServiceId service id
* @return service list
*/
Set<String> getTenantServices(String pServiceId);
/**
* Returns dependent provider services of a given tenant service.
*
* @param tServiceId service id
* @return set of services
*/
Set<String> getProviderServices(String tServiceId);
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.api;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Objects holding XOS API access information.
*/
public class XosAccess {
private final String endpoint;
private final String username;
private final String password;
/**
* Default constructor.
*
* @param endpoint XOS service endpoint
* @param adminUser admin user name
* @param adminPassword admin password
*/
public XosAccess(String endpoint, String adminUser, String adminPassword) {
this.endpoint = checkNotNull(endpoint);
this.username = checkNotNull(adminUser);
this.password = checkNotNull(adminPassword);
}
/**
* Returns XOS service endpoint.
*
* @return endpoint
*/
public String endpoint() {
return this.endpoint;
}
/**
* Returns admin user name.
*
* @return user name
*/
public String username() {
return this.username;
}
/**
* Returns admin password.
*
* @return password
*/
public String password() {
return this.password;
}
@Override
public int hashCode() {
return Objects.hash(endpoint, username, password);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if ((obj instanceof XosAccess)) {
XosAccess that = (XosAccess) obj;
if (Objects.equals(endpoint, that.endpoint) &&
Objects.equals(username, that.username) &&
Objects.equals(password, that.password)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("endpoint", endpoint)
.add("username", username)
.add("password", password)
.toString();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.api;
import com.fasterxml.jackson.databind.JsonNode;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
/**
* XOS API access information.
*/
public class XosAccessConfig extends Config<ApplicationId> {
protected final Logger log = getLogger(getClass());
private static final String XOS_SERVICE_ENDPOINT = "serviceEndpoint";
private static final String XOS_ADMIN_USER = "adminUser";
private static final String XOS_ADMIN_PASSWORD = "adminPassword";
/**
* Returns XOS access information.
*
* @return XOS access, or null
*/
public XosAccess xosAccess() {
try {
return new XosAccess(getConfig(object, XOS_SERVICE_ENDPOINT),
getConfig(object, XOS_ADMIN_USER),
getConfig(object, XOS_ADMIN_PASSWORD));
} catch (NullPointerException e) {
log.error("Failed to get XOS access");
return null;
}
}
/**
* Returns value of a given path. If the path is missing, show log and return
* null.
*
* @param path path
* @return value or null
*/
private String getConfig(JsonNode jsonNode, String path) {
jsonNode = jsonNode.path(path);
if (jsonNode.isMissingNode()) {
log.error("{} is not configured", path);
return null;
} else {
return jsonNode.asText();
}
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.api;
/**
* Provides interactions with XOS.
*/
public interface XosClientService {
/**
* Returns XOS API access information of the client.
*
* @return xos access
*/
XosAccess access();
/**
* Sets the XOS API access information to the client service.
*
* @return true if it is set and authenticated, otherwise false
*/
boolean setAccess(XosAccess xosAccess);
/**
* Returns CORD VTN service API.
*
* @return cord vtn service api
*/
VtnServiceApi vtnServiceApi();
/*
* adds more XOS service APIs below.
*/
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* XOS client application API.
*/
package org.onosproject.xosclient.api;
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import org.onosproject.xosclient.api.VtnServiceApi;
import org.onosproject.xosclient.api.XosAccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Provides CORD VTN service and service dependency APIs.
*/
public final class DefaultVtnServiceApi extends XosApi implements VtnServiceApi {
private final Logger log = LoggerFactory.getLogger(getClass());
private static DefaultVtnServiceApi instance = null;
/**
* Default constructor.
*/
private DefaultVtnServiceApi(String baseUrl, XosAccess access) {
super(baseUrl, access);
}
/**
* Returns VTN service API instance. Creates a new instance only if base url or
* access has been changed.
*
* @param baseUrl base url
* @param access access
* @return vtn service api
*/
public static synchronized DefaultVtnServiceApi getInstance(String baseUrl, XosAccess access) {
checkNotNull(access, "XOS access information is null");
checkArgument(!Strings.isNullOrEmpty(baseUrl), "VTN service API base url is null or empty");
if (instance == null ||
!instance.baseUrl.equals(baseUrl) ||
!instance.access.equals(access)) {
instance = new DefaultVtnServiceApi(baseUrl, access);
}
return instance;
}
@Override
public Set<String> services() {
String response = restGet(EMPTY_STRING);
log.trace("Get services {}", response);
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode nodes = mapper.readTree(response);
return Sets.newHashSet(nodes.fieldNames());
} catch (IOException e) {
log.warn("Failed to get service list");
return Sets.newHashSet();
}
}
@Override
public Set<String> getProviderServices(String tServiceId) {
checkNotNull(tServiceId);
String response = restGet(tServiceId);
log.trace("Get provider services {}", response);
ObjectMapper mapper = new ObjectMapper();
Set<String> pServices = Sets.newHashSet();
try {
JsonNode nodes = mapper.readTree(response);
nodes.forEach(node -> pServices.add(node.asText()));
} catch (IOException e) {
log.warn("Failed to get service dependency");
}
return pServices;
}
@Override
public Set<String> getTenantServices(String tServiceId) {
checkNotNull(tServiceId);
String response = restGet(EMPTY_STRING);
log.trace("Get tenant services {}", response);
ObjectMapper mapper = new ObjectMapper();
Set<String> tServices = Sets.newHashSet();
try {
JsonNode nodes = mapper.readTree(response);
Iterator<Map.Entry<String, JsonNode>> iterator = nodes.fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
entry.getValue().forEach(pService -> {
if (pService.asText().equals(tServiceId)) {
tServices.add(entry.getKey());
}
});
}
} catch (IOException e) {
log.warn("Failed to get service list");
}
return tServices;
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.impl;
import org.onosproject.xosclient.api.XosAccess;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import static com.google.common.net.MediaType.JSON_UTF_8;
/**
* XOS common REST API implementation.
*/
public class XosApi {
protected static final String EMPTY_STRING = "";
protected final String baseUrl;
protected final XosAccess access;
protected final Client client;
/**
* Default constructor.
*
* @param baseUrl base url of this api
* @param xosAccess xos access
*/
public XosApi(String baseUrl, XosAccess xosAccess) {
this.baseUrl = baseUrl;
this.access = xosAccess;
this.client = ClientBuilder.newClient();
}
/**
* Returns the access of this api.
*
* @return xos access
*/
public XosAccess access() {
return this.access;
}
/**
* Returns the base url of this api.
*
* @return base url
*/
public String baseUrl() {
return this.baseUrl;
}
/**
* Returns response of the REST get operation with a given additional path.
*
* @param path path or null
* @return response json string
*/
public String restGet(String path) {
WebTarget wt = client.target(access.endpoint() + baseUrl).path(path);
Invocation.Builder builder = wt.request(JSON_UTF_8.toString());
return builder.get(String.class);
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.xosclient.impl;
import com.google.common.base.Strings;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.xosclient.api.VtnServiceApi;
import org.onosproject.xosclient.api.XosAccess;
import org.onosproject.xosclient.api.XosAccessConfig;
import org.onosproject.xosclient.api.XosClientService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Dictionary;
import static org.slf4j.LoggerFactory.getLogger;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Provides interactions with XOS.
*/
@Component(immediate = true)
@Service
public class XosClient implements XosClientService {
protected final Logger log = getLogger(getClass());
private static final String VTN_BASE_URL = "vtnBaseUrl";
private static final String DEFAULT_VTN_BASE_URL = "/xoslib/rs/vtn/services/";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService componentConfigService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigRegistry configRegistry;
@Property(name = VTN_BASE_URL, value = DEFAULT_VTN_BASE_URL,
label = "XOS VTN service API base url")
private String vtnBaseUrl = DEFAULT_VTN_BASE_URL;
private final ConfigFactory configFactory =
new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, XosAccessConfig.class, "xosclient") {
@Override
public XosAccessConfig createConfig() {
return new XosAccessConfig();
}
};
private final NetworkConfigListener configListener = new InternalConfigListener();
private ApplicationId appId;
private XosAccess access = null;
@Activate
protected void activate(ComponentContext context) {
appId = coreService.registerApplication("org.onosproject.xosclient");
componentConfigService.registerProperties(getClass());
modified(context);
configRegistry.registerConfigFactory(configFactory);
configRegistry.addListener(configListener);
log.info("Started");
}
@Deactivate
protected void deactivate() {
log.info("Stopped");
}
@Modified
protected void modified(ComponentContext context) {
Dictionary<?, ?> properties = context.getProperties();
String updatedUrl = Tools.get(properties, VTN_BASE_URL);
if (!Strings.isNullOrEmpty(updatedUrl)) {
vtnBaseUrl = updatedUrl;
}
log.info("Modified");
}
@Override
public XosAccess access() {
return access;
}
@Override
public synchronized boolean setAccess(XosAccess xosAccess) {
checkNotNull(xosAccess);
// TODO authentication later before using the access
access = xosAccess;
return true;
}
@Override
public VtnServiceApi vtnServiceApi() {
checkNotNull(access, "XOS API access is not set");
return DefaultVtnServiceApi.getInstance(vtnBaseUrl, access);
}
/*
* adds more XOS service APIs below.
*/
private void readConfiguration() {
XosAccessConfig config = configRegistry.getConfig(appId, XosAccessConfig.class);
if (config == null) {
log.debug("No configuration found");
return;
}
setAccess(config.xosAccess());
}
private class InternalConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
if (!event.configClass().equals(XosAccessConfig.class)) {
return;
}
switch (event.type()) {
case CONFIG_ADDED:
case CONFIG_UPDATED:
log.info("Network configuration changed");
readConfiguration();
break;
default:
break;
}
}
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* XOS client application.
*/
package org.onosproject.xosclient.impl;
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* XOS API client application.
*/
package org.onosproject.xosclient;
\ No newline at end of file