From 4318ad160fa6ee1d75c395f4409e209f5da36f53 Mon Sep 17 00:00:00 2001 From: "Arun S. Yerra" Date: Mon, 11 Sep 2017 18:57:40 -0700 Subject: Implement framework to process REST notifications Global SDNC controller needs information about network Devices (mostly PNFs) so as to instantiate/configure service. Domain Controllers control/manage the network devices within the fabric. This task is to implement RESTCONF notification processing framework, so that Global SDNC controller can process notifications from Domain controllers. Change-Id: Ia5edb5006ac3fd4ec71e55f92a05e79e40ce76d2 Issue-Id: CCSDK-88 Signed-off-by: Arun S. Yerra --- fabric-discovery-plugin/.gitignore | 19 +++ fabric-discovery-plugin/features/pom.xml | 135 ++++++++++++++++++++ .../features/src/main/resources/features.xml | 40 ++++++ fabric-discovery-plugin/installer/pom.xml | 139 +++++++++++++++++++++ .../src/assembly/assemble_installer_zip.xml | 59 +++++++++ .../src/assembly/assemble_mvnrepo_zip.xml | 49 ++++++++ .../src/main/resources/scripts/install-feature.sh | 40 ++++++ fabric-discovery-plugin/pom.xml | 42 +++++++ fabric-discovery-plugin/provider/pom.xml | 126 +++++++++++++++++++ .../fabricdiscovery/ClientMessageCallback.java | 20 +++ .../fabricdiscovery/FabricDiscoveryPlugin.java | 129 +++++++++++++++++++ .../fabricdiscovery/IClientMessageCallback.java | 16 +++ .../fabricdiscovery/IFabricDiscoveryService.java | 17 +++ .../plugins/fabricdiscovery/WebSocketClient.java | 96 ++++++++++++++ .../fabricdiscovery/WebSocketClientHandler.java | 92 ++++++++++++++ .../blueprint/fabricdiscoveryplugin-blueprint.xml | 10 ++ pom.xml | 6 +- 17 files changed, 1032 insertions(+), 3 deletions(-) create mode 100644 fabric-discovery-plugin/.gitignore create mode 100755 fabric-discovery-plugin/features/pom.xml create mode 100644 fabric-discovery-plugin/features/src/main/resources/features.xml create mode 100755 fabric-discovery-plugin/installer/pom.xml create mode 100644 fabric-discovery-plugin/installer/src/assembly/assemble_installer_zip.xml create mode 100644 fabric-discovery-plugin/installer/src/assembly/assemble_mvnrepo_zip.xml create mode 100644 fabric-discovery-plugin/installer/src/main/resources/scripts/install-feature.sh create mode 100755 fabric-discovery-plugin/pom.xml create mode 100755 fabric-discovery-plugin/provider/pom.xml create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/ClientMessageCallback.java create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/FabricDiscoveryPlugin.java create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IClientMessageCallback.java create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IFabricDiscoveryService.java create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClient.java create mode 100644 fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClientHandler.java create mode 100644 fabric-discovery-plugin/provider/src/main/resources/org/opendaylight/blueprint/fabricdiscoveryplugin-blueprint.xml diff --git a/fabric-discovery-plugin/.gitignore b/fabric-discovery-plugin/.gitignore new file mode 100644 index 00000000..4213c216 --- /dev/null +++ b/fabric-discovery-plugin/.gitignore @@ -0,0 +1,19 @@ +*.class +**/target +bin/ +dist +**/logs +*~ +target +target-ide +.classpath +.project +.settings +.idea +xtend-gen +yang-gen-config +yang-gen-sal +classes +.DS_STORE +.metadata +.gitreview diff --git a/fabric-discovery-plugin/features/pom.xml b/fabric-discovery-plugin/features/pom.xml new file mode 100755 index 00000000..2e0b0d94 --- /dev/null +++ b/fabric-discovery-plugin/features/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + + fabric-discovery-plugin + org.onap.ccsdk.sli.plugins + 0.1.0-SNAPSHOT + + org.onap.ccsdk.sli.plugins + 0.1.0-SNAPSHOT + fabric-discovery-plugin-features + Fabric Discovery Plugin - Features + + jar + + + + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-provider + ${project.version} + + + + commons-lang + commons-lang + 2.6 + compile + + + + org.opendaylight.mdsal + features-mdsal + ${odl.mdsal.features.version} + features + xml + + runtime + + + + + + org.opendaylight.controller + opendaylight-karaf-empty + ${odl.karaf.empty.distro.version} + zip + + + + + + org.opendaylight.odlparent + features-test + ${odl.commons.opendaylight.version} + test + + + + org.opendaylight.yangtools + features-yangtools + ${odl.yangtools.version} + features + xml + runtime + + + + + + + true + src/main/resources + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + + resources + + generate-resources + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/${features.file} + xml + features + + + + + + + + + diff --git a/fabric-discovery-plugin/features/src/main/resources/features.xml b/fabric-discovery-plugin/features/src/main/resources/features.xml new file mode 100644 index 00000000..0750c438 --- /dev/null +++ b/fabric-discovery-plugin/features/src/main/resources/features.xml @@ -0,0 +1,40 @@ + + + + + + + mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.features.version}/xml/features + + + sdnc-sli + spring + spring-dm + mvn:com.sun.jersey/jersey-client/${jersey.version} + mvn:org.codehaus.jettison/jettison/${jettison.version} + mvn:org.onap.ccsdk.sli.plugins/fabric-discovery-plugin-provider/${project.version} + + + diff --git a/fabric-discovery-plugin/installer/pom.xml b/fabric-discovery-plugin/installer/pom.xml new file mode 100755 index 00000000..1f429901 --- /dev/null +++ b/fabric-discovery-plugin/installer/pom.xml @@ -0,0 +1,139 @@ + + + 4.0.0 + + fabric-discovery-plugin + org.onap.ccsdk.sli.plugins + 0.1.0-SNAPSHOT + + fabric-discovery-plugin-installer + Properties node - Karaf Installer + pom + + + sdnc-fabric-discovery-plugin + sdnc-fabric-discovery-plugin + mvn:org.onap.ccsdk.sli.plugins/fabric-discovery-plugin-features/${project.version}/xml/features + false + + + + + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-features + ${project.version} + features + xml + + + * + * + + + + + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-provider + ${project.version} + + + + + + + + maven-assembly-plugin + 2.6 + + + maven-repo-zip + + single + + package + + false + stage/${application.name}-${project.version} + + src/assembly/assemble_mvnrepo_zip.xml + + false + + + + installer-zip + + single + + package + + true + ${application.name}-${project.version}-installer + + src/assembly/assemble_installer_zip.xml + + false + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + + copy-dependencies + + prepare-package + + false + ${project.build.directory}/assembly/system + false + true + true + true + false + false + org.onap.ccsdk.sli + sli-common,sli-provider,dblib-provider + provided + + + + + + maven-resources-plugin + 2.6 + + + copy-version + + copy-resources + + validate + + ${basedir}/target/stage + + + src/main/resources/scripts + + install-feature.sh + + true + + + + + + + + + + + + diff --git a/fabric-discovery-plugin/installer/src/assembly/assemble_installer_zip.xml b/fabric-discovery-plugin/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 00000000..3bed4b5e --- /dev/null +++ b/fabric-discovery-plugin/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ + + + + + + installer_zip + + zip + + + + false + + + + target/stage/ + ${application.name} + 755 + + *.sh + + + + target/stage/ + ${application.name} + 644 + + *.sh + + + + + + + diff --git a/fabric-discovery-plugin/installer/src/assembly/assemble_mvnrepo_zip.xml b/fabric-discovery-plugin/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 00000000..cb56f2cd --- /dev/null +++ b/fabric-discovery-plugin/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,49 @@ + + + + + + mvnrepo_zip + + zip + + + + false + + + + target/assembly/ + . + + + + + + + + diff --git a/fabric-discovery-plugin/installer/src/main/resources/scripts/install-feature.sh b/fabric-discovery-plugin/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 00000000..e986764b --- /dev/null +++ b/fabric-discovery-plugin/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights +# reserved. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= +### + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/fabric-discovery-plugin/pom.xml b/fabric-discovery-plugin/pom.xml new file mode 100755 index 00000000..f22fb695 --- /dev/null +++ b/fabric-discovery-plugin/pom.xml @@ -0,0 +1,42 @@ + + + + org.onap.ccsdk.sli.plugins + ccsdk-sli-plugins + 0.1.0-SNAPSHOT + + + 4.0.0 + pom + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin + 0.1.0-SNAPSHOT + + Fabric Discovery Plugin + This plugin will populate information about the devices within network fabric into SDNC database + + + + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-features + features + xml + ${project.version} + + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-provider + ${project.version} + + + + + + provider + features + installer + + + diff --git a/fabric-discovery-plugin/provider/pom.xml b/fabric-discovery-plugin/provider/pom.xml new file mode 100755 index 00000000..c38acb1b --- /dev/null +++ b/fabric-discovery-plugin/provider/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin + 0.1.0-SNAPSHOT + + org.onap.ccsdk.sli.plugins + fabric-discovery-plugin-provider + 0.1.0-SNAPSHOT + bundle + Fabric Discovery Plugin - Provider + http://maven.apache.org + + UTF-8 + + + + + io.netty + netty + 3.10.6.Final + + + + io.netty + netty-buffer + 4.0.26.Final + + + + io.netty + netty-transport + 4.0.4.Final + + + + io.netty + netty-codec-http + 4.0.15.Final + + + junit + junit + test + + + org.springframework + spring-test + ${spring.version} + test + + + org.onap.ccsdk.sli.core + sli-common + ${sdnctl.sli.version} + compile + + + org.onap.ccsdk.sli.core + sli-provider + ${sdnctl.sli.version} + compile + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + com.sun.jersey + jersey-client + ${jersey.version} + provided + + + org.codehaus.jettison + jettison + ${jettison.version} + provided + + + org.onap.ccsdk.sli.core + sli-common + ${sdnctl.sli.version} + + + org.onap.ccsdk.sli.core + sli-provider + ${sdnctl.sli.version} + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + org.onap.ccsdk.sli.plugins.fabricdiscovery + org.onap.ccsdk.sli.plugins.fabricdiscovery + * + + + + + + diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/ClientMessageCallback.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/ClientMessageCallback.java new file mode 100644 index 00000000..0a8ba9e7 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/ClientMessageCallback.java @@ -0,0 +1,20 @@ +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; + +/** + * Created by arun on 9/9/17. + */ +public class ClientMessageCallback implements IClientMessageCallback { + private static final Logger LOG = LoggerFactory.getLogger(ClientMessageCallback.class); + + @Override + public void onMessageReceived(final Object message) { + if (message instanceof TextWebSocketFrame) { + LOG.info("received message {}" + ((TextWebSocketFrame) message).text()); + } + } + +} diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/FabricDiscoveryPlugin.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/FabricDiscoveryPlugin.java new file mode 100644 index 00000000..7a0c68f4 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/FabricDiscoveryPlugin.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : SDN-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; +import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class FabricDiscoveryPlugin implements SvcLogicJavaPlugin, IFabricDiscoveryService { + + private ExecutorService service; + private Map streamMap; + private static final Logger LOG = LoggerFactory.getLogger(FabricDiscoveryPlugin.class); + + public FabricDiscoveryPlugin() { + service = Executors.newFixedThreadPool(10); + streamMap = new ConcurrentHashMap (); + } + + @Override + public void processDcNotificationStream (Map paramMap, SvcLogicContext ctx) throws SvcLogicException { + boolean enable = Boolean.parseBoolean(parseParam(paramMap, "enable", true, null)); + String stream = parseParam(paramMap, "stream", true, null); + + LOG.info("{} monitoring notification stream: {}", (enable) ? "START" : "STOP", stream); + try { + service.execute(new Runnable () { + public void run () { + try { + URI uri = new URI(stream); + if (enable) { + if (streamMap.get(stream) != null) { + LOG.info("Notification Stream: {} is already being monitoried", stream); + return; + } + IClientMessageCallback messageCallback = new ClientMessageCallback(); + WebSocketClient wcClient = new WebSocketClient(uri, messageCallback); + streamMap.put(stream, wcClient); + wcClient.initialize(); + try { + wcClient.connect(); + } catch (InterruptedException e) { + LOG.info("Web Socket Client throws Exception: ", e.getMessage()); + } + } else { + WebSocketClient wc = streamMap.get(stream); + if (wc != null) { + try { + wc.close("Closing"); + } catch (InterruptedException e) { + LOG.info("Web Socket Client throws Exception: ", e.getMessage()); + } + } + } + } catch (URISyntaxException e) { + LOG.info("Exception converting stream to URI with: ", e.getMessage()); + } + } + }); + } catch (Exception e) { + LOG.info("Web Socket client connection throws an exception: ", e.getMessage()); + } + } + + private String parseParam(Map paramMap, String name, boolean required, String def) + throws SvcLogicException { + String s = paramMap.get(name); + + if (s == null || s.trim().length() == 0) { + if (!required) + return def; + throw new SvcLogicException("Parameter " + name + " is required in PropertiesNode"); + } + + s = s.trim(); + String value = ""; + int i = 0; + int i1 = s.indexOf('%'); + while (i1 >= 0) { + int i2 = s.indexOf('%', i1 + 1); + if (i2 < 0) + throw new SvcLogicException("Cannot parse parameter " + name + ": " + s + ": no matching %"); + + String varName = s.substring(i1 + 1, i2); + String varValue = System.getenv(varName); + if (varValue == null) + varValue = ""; + + value = (new StringBuilder()).append(value) + .append(s.substring(i, i1)) + .append(varValue).toString(); + i = i2 + 1; + i1 = s.indexOf('%', i); + } + value = (new StringBuilder()).append(value) + .append(s.substring(i)).toString(); + + LOG.info("Parameter {}: {}", name, value); + return value; + } +} diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IClientMessageCallback.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IClientMessageCallback.java new file mode 100644 index 00000000..e555d338 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IClientMessageCallback.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +/** + * Created by mbobak on 1/22/14. + */ +public interface IClientMessageCallback { + + void onMessageReceived(Object message); +} diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IFabricDiscoveryService.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IFabricDiscoveryService.java new file mode 100644 index 00000000..857d75a9 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/IFabricDiscoveryService.java @@ -0,0 +1,17 @@ +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +import java.util.Map; +import org.onap.ccsdk.sli.core.sli.SvcLogicContext; +import org.onap.ccsdk.sli.core.sli.SvcLogicException; + +/** + * Created by arun on 9/10/17. + */ +public interface IFabricDiscoveryService { + + /* (non-Javadoc) + * @see void#processDcNotificationStream(java.lang.String, java.lang.Integer, java.lang.String, java.lang.Boolean) + */ + void processDcNotificationStream (Map paramMap, SvcLogicContext ctx) throws SvcLogicException; + +} diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClient.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClient.java new file mode 100644 index 00000000..bdecdc74 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClient.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.HttpClientCodec; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; +import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory; +import io.netty.handler.codec.http.websocketx.WebSocketVersion; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketClient { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketClient.class); + + private final URI uri; + private final Bootstrap bootstrap = new Bootstrap(); + private final WebSocketClientHandler clientHandler; + private Channel clientChannel; + private final EventLoopGroup group = new NioEventLoopGroup(); + + public WebSocketClient(final URI uri, final IClientMessageCallback clientMessageCallback) { + this.uri = uri; + clientHandler = new WebSocketClientHandler(WebSocketClientHandshakerFactory.newHandshaker(uri, + WebSocketVersion.V13, null, false, null), clientMessageCallback); + // last null could be replaced with DefaultHttpHeaders + initialize(); + } + + public void initialize() { + + String protocol = uri.getScheme(); + if (!"ws".equals(protocol)) { + throw new IllegalArgumentException("Unsupported protocol: " + protocol); + } + + bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer() { + @Override + public void initChannel(final SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("http-codec", new HttpClientCodec()); + pipeline.addLast("aggregator", new HttpObjectAggregator(8192)); + pipeline.addLast("ws-handler", clientHandler); + } + }); + } + + public void connect() throws InterruptedException { + LOG.info("WebSocket Client connecting"); + clientChannel = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel(); + clientHandler.handshakeFuture().sync(); + } + + public void writeAndFlush(final String message) { + clientChannel.writeAndFlush(new TextWebSocketFrame(message)); + } + + public void writeAndFlush(final Object message) { + clientChannel.writeAndFlush(message); + } + + public void ping() { + clientChannel.writeAndFlush(new PingWebSocketFrame(Unpooled.copiedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 }))); + } + + public void close(final String reasonText) throws InterruptedException { + CloseWebSocketFrame closeWebSocketFrame = new CloseWebSocketFrame(1000, reasonText); + clientChannel.writeAndFlush(closeWebSocketFrame); + + // WebSocketClientHandler will close the connection when the server + // responds to the CloseWebSocketFrame. + clientChannel.closeFuture().sync(); + group.shutdownGracefully(); + } +} diff --git a/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClientHandler.java b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClientHandler.java new file mode 100644 index 00000000..c1c5dc30 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/java/org/onap/ccsdk/sli/plugins/fabricdiscovery/WebSocketClientHandler.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.onap.ccsdk.sli.plugins.fabricdiscovery; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; +import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.util.CharsetUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketClientHandler extends SimpleChannelInboundHandler { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketClientHandler.class.toString()); + private final WebSocketClientHandshaker handshaker; + private ChannelPromise handshakeFuture; + private final IClientMessageCallback messageListener; + + public WebSocketClientHandler(WebSocketClientHandshaker handshaker, IClientMessageCallback listener) { + this.handshaker = handshaker; + this.messageListener = listener; + } + + public ChannelFuture handshakeFuture() { + return handshakeFuture; + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + handshakeFuture = ctx.newPromise(); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + handshaker.handshake(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + LOG.info("WebSocket Client disconnected!"); + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { + Channel ch = ctx.channel(); + if (!handshaker.isHandshakeComplete()) { + handshaker.finishHandshake(ch, (FullHttpResponse) msg); + LOG.info("WebSocket Client connected!"); + handshakeFuture.setSuccess(); + return; + } + + if (msg instanceof FullHttpResponse) { + FullHttpResponse response = (FullHttpResponse) msg; + throw new Exception("Unexpected FullHttpResponse (getStatus=" + response.getStatus() + ", content=" + + response.content().toString(CharsetUtil.UTF_8) + ')'); + } + + messageListener.onMessageReceived(msg); + WebSocketFrame frame = (WebSocketFrame) msg; + + if (frame instanceof PongWebSocketFrame) { + LOG.info("WebSocket Client received pong"); + } else if (frame instanceof CloseWebSocketFrame) { + LOG.info("WebSocket Client received closing"); + ch.close(); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + LOG.info("Cause: {} .", cause.toString()); + + if (!handshakeFuture.isDone()) { + handshakeFuture.setFailure(cause); + } + + ctx.close(); + } +} diff --git a/fabric-discovery-plugin/provider/src/main/resources/org/opendaylight/blueprint/fabricdiscoveryplugin-blueprint.xml b/fabric-discovery-plugin/provider/src/main/resources/org/opendaylight/blueprint/fabricdiscoveryplugin-blueprint.xml new file mode 100644 index 00000000..43137bb8 --- /dev/null +++ b/fabric-discovery-plugin/provider/src/main/resources/org/opendaylight/blueprint/fabricdiscoveryplugin-blueprint.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/pom.xml b/pom.xml index d2a761b1..4f1ac54e 100755 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - + org.onap.ccsdk.parent @@ -108,7 +107,8 @@ properties-node restapi-call-node - + fabric-discovery-plugin + AT&T -- cgit 1.2.3-korg