diff options
Diffstat (limited to 'sdnr/wt/websocketmanager')
36 files changed, 3121 insertions, 0 deletions
diff --git a/sdnr/wt/websocketmanager/feature/pom.xml b/sdnr/wt/websocketmanager/feature/pom.xml new file mode 100644 index 000000000..5e27e7724 --- /dev/null +++ b/sdnr/wt/websocketmanager/feature/pom.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<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> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>single-feature-parent</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-websocketmanager-feature</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>feature</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-websocketmanager-model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-websocketmanager-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> diff --git a/sdnr/wt/websocketmanager/installer/pom.xml b/sdnr/wt/websocketmanager/installer/pom.xml new file mode 100755 index 000000000..a13f064e3 --- /dev/null +++ b/sdnr/wt/websocketmanager/installer/pom.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<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> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>odlparent-lite</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-websocketmanager-installer</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + + <properties> + <application.name>sdnr-wt-websocketmanager</application.name> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencies> + <dependency> + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>${application.name}-feature</artifactId> + <version>${project.version}</version> + <type>xml</type> + <classifier>features</classifier> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>${application.name}-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>maven-repo-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <attach>true</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>true</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-nested-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>true</transitive> + <outputDirectory>${project.build.directory}/assembly/system</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>true</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wt/websocketmanager/installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt/websocketmanager/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 000000000..dfe5060bf --- /dev/null +++ b/sdnr/wt/websocketmanager/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,47 @@ +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2017-2020 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======================================================= + ~ + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>repo</id> + <formats> + <format>zip</format> + </formats> + + <!-- we want "system" and related files right at the root level + as this file is suppose to be unzip on top of a karaf + distro. --> + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>target/assembly/</directory> + <outputDirectory>.</outputDirectory> + <excludes> + </excludes> + </fileSet> + </fileSets> + +</assembly> diff --git a/sdnr/wt/websocketmanager/model/pom.xml b/sdnr/wt/websocketmanager/model/pom.xml new file mode 100644 index 000000000..7026b3329 --- /dev/null +++ b/sdnr/wt/websocketmanager/model/pom.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<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> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-websocketmanager-model</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + </properties> + + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>mdsal-dom-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId> + <artifactId>rfc6991-ietf-yang-types</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> + </dependencies> +</project> diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/WebsocketManagerService.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/WebsocketManagerService.java new file mode 100644 index 000000000..bfceb373e --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/WebsocketManagerService.java @@ -0,0 +1,88 @@ +package org.onap.ccsdk.features.sdnr.wt.websocketmanager.model; + +import org.opendaylight.mdsal.dom.api.DOMNotification; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.yang.binding.Notification; +import org.opendaylight.yangtools.yang.common.QName; + +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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========================================================= + * + */ +/** + * + * outgoing message will be wrapped into container: + * <pre> + * {@code + * <notification> + * <eventTime>2017-07-12T12:00:00.0Z</eventTime> + * <problem-notification xmlns="urn:onf:params:xml:ns:yang:microwave-model"> + * <problem>signalIsLostMinor</problem> + * <object-id-ref>LP-MWPS-RADIO</object-id-ref> + * <severity>non-alarmed</severity> + * <counter>$COUNTER</counter> + * <time-stamp>$TIME</time-stamp> + * </problem-notification> + * <node-id>ROADM-A</node-id> + * <eventType></eventType> + * </notification> + * } + * </pre> + * @author jack + * + */ +public interface WebsocketManagerService { + + /** + * Send notification via Websocket to the connected clients. + * eventTime is extracted out of notification if {@link #EventInstantAware } is implemented + * @param notification + * @param nodeId + * @param eventType + */ + void sendNotification(Notification notification, String nodeId, QName eventType); + /** + * Send notification via Websocket to the connected clients. + * @param notification + * @param nodeId + * @param eventType + * @param eventTime + */ + void sendNotification(Notification notification, String nodeId, QName eventType, DateAndTime eventTime); + + /** + * Send notification via Websocket to the connected clients. + * @param notification + * @param nodeId + * @param eventType + */ + void sendNotification(DOMNotification notification, String nodeId, QName eventType); + /** + * Send notification via Websocket to the connected clients. + * @param notification + * @param nodeId + * @param eventType + * @param eventTime + */ + void sendNotification(DOMNotification notification, String nodeId, QName eventType, DateAndTime eventTime); + + + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/NotificationOutput.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/NotificationOutput.java new file mode 100644 index 000000000..5b966ef1e --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/NotificationOutput.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.yang.binding.Notification; +import org.opendaylight.yangtools.yang.common.QName; + +public class NotificationOutput { + + private DateAndTime eventTime; + private Notification data; + private String nodeId; + private ReducedSchemaInfo type; + + + public NotificationOutput() { + + } + + public DateAndTime getEventTime() { + return eventTime; + } + + public void setEventTime(DateAndTime eventTime) { + this.eventTime = eventTime; + } + + public Notification getData() { + return data; + } + + public String getNodeId() { + return this.nodeId; + } + + public ReducedSchemaInfo getType() { + return this.type; + } + + public void setData(Notification data) { + this.data = data; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public void setType(ReducedSchemaInfo type) { + this.type = type; + } + + public NotificationOutput(Notification notification, String nodeId, QName type, DateAndTime eventTime) { + this.data = notification; + this.nodeId = nodeId; + this.eventTime = eventTime; + this.type = new ReducedSchemaInfo(type); + } + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ReducedSchemaInfo.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ReducedSchemaInfo.java new file mode 100644 index 000000000..f6e6c5d0d --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ReducedSchemaInfo.java @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import org.opendaylight.yangtools.yang.common.QName; + +public class ReducedSchemaInfo { + private String namespace; + private String revision; + private String type; + + public ReducedSchemaInfo() {} + + + + public ReducedSchemaInfo(QName qname) { + this.namespace = qname.getNamespace().toString(); + this.revision = qname.getRevision().isPresent() ? qname.getRevision().get().toString() : null; + this.type = qname.getLocalName(); + } + + public boolean equals(QName obj) { + return this.namespace.equals(obj.getNamespace().toString()) && this.type.equals(obj.getLocalName()) + && ((this.revision == null && obj.getRevision().isEmpty()) + || (this.revision.equals(obj.getRevision().get().toString()))); + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/SchemaInfo.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/SchemaInfo.java new file mode 100644 index 000000000..c587a7997 --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/SchemaInfo.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.ArrayList; +import java.util.List; +import org.opendaylight.yangtools.yang.common.QName; + +public class SchemaInfo { + private String namespace; + private String revision; + private List<String> notification; + + public SchemaInfo() {} + + + + public SchemaInfo(QName qname) { + this.namespace = qname.getNamespace().toString(); + this.revision = qname.getRevision().isPresent() ? qname.getRevision().get().toString() : null; + this.notification = new ArrayList<>(); + this.notification.add(qname.getLocalName()); + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + + public List<String> getNotification() { + return notification; + } + + public void setNotification(List<String> notification) { + this.notification = notification; + } + + @JsonIgnore + public boolean isValid() { + return this.namespace != null + && (this.notification == null || (this.notification != null && this.notification.size() > 0)); + } + + /** + * Check if schema(qname based info of notification) matches into this scope + * @param schema + * @return + */ + @JsonIgnore + public boolean matches(ReducedSchemaInfo schema) { + //if namespace is * placeholder => true + if (this.namespace.equals("*")) { + return true; + } + //if namespace does not match => false + if (!this.namespace.equals(schema.getNamespace().toString())) { + return false; + } + //if revision of scope is set and it does not match => false + if (this.revision != null && !this.revision.equals(schema.getRevision())){ + return false; + } + //if notification of scope is set and is current notification is not in the list + if (this.notification != null && !this.notification.contains(schema.getType())) { + return false; + } + return true; + } + + @JsonIgnore + public boolean equalsNamespaceAndRevision(QName qname) { + if (this.namespace == null) { + return false; + } + if (!this.namespace.equals(qname.getNamespace().toString())) { + return false; + } + if (this.revision == null && qname.getRevision().isEmpty()) { + return true; + } + if (this.revision != null) { + return this.revision.equals(qname.getRevision().isEmpty() ? null : qname.getRevision().get().toString()); + } + return false; + } + + @JsonIgnore + public void addNotification(String notification) { + if(this.notification ==null) { + this.notification = new ArrayList<>(); + } + this.notification.add(notification); + } + + @Override + public String toString() { + return "SchemaInfo [namespace=" + namespace + ", revision=" + revision + ", notification=" + notification + "]"; + } + + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/Scope.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/Scope.java new file mode 100644 index 000000000..b30aed1a6 --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/Scope.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.opendaylight.yangtools.yang.common.QName; + +public class Scope { + + private String nodeId; + private SchemaInfo schema; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public SchemaInfo getSchema() { + return schema; + } + + public void setSchema(SchemaInfo schema) { + this.schema = schema; + } + + @JsonIgnore + public boolean isValid() { + if (this.nodeId == null && this.schema == null) { + return false; + } + if (this.nodeId == null && !this.schema.isValid()) { + return false; + } + return true; + } + + @JsonIgnore + public boolean matches(String nodeId, ReducedSchemaInfo reducedSchemaInfo) { + if (this.nodeId == null) { + return this.schema.matches(reducedSchemaInfo); + } else if (this.schema == null) { + return this.nodeId.equals(nodeId); + } + return this.nodeId.equals(nodeId) && this.schema.matches(reducedSchemaInfo); + + } + + public boolean addQname(QName qname) { + if(this.schema==null) { + this.schema = new SchemaInfo(qname); + return true; + } + if(!this.schema.equalsNamespaceAndRevision(qname)) { + return false; + } + this.schema.addNotification(qname.getLocalName()); + return true; + } + + @Override + public String toString() { + return "Scope [nodeId=" + nodeId + ", schema=" + schema + "]"; + } + + public static Scope create(QName qname) { + return create(null, qname); + } + + public static Scope create(String nodeId, QName qname) { + return create(nodeId, qname == null ? null : new SchemaInfo(qname)); + } + + public static Scope create(String nodeId, SchemaInfo schemaInfo) { + Scope scope = new Scope(); + scope.setNodeId(nodeId); + scope.setSchema(schemaInfo); + return scope; + } + + public static Scope create(String nodeId) { + return create(nodeId, (SchemaInfo) null); + } + + public static List<Scope> createList(List<QName> qnames) { + return createList(null, qnames); + } + + public static List<Scope> createList(String nodeId, List<QName> qnames) { + List<Scope> scopes = new ArrayList<>(); + Optional<Scope> listElem = null; + for (QName qname : qnames) { + listElem = scopes.stream().filter(e -> e.schema != null && e.schema.equalsNamespaceAndRevision(qname)) + .findFirst(); + if (listElem.isPresent()) { + if (!listElem.get().addQname(qname)) { + scopes.add(Scope.create(nodeId, qname)); + } + } else { + scopes.add(Scope.create(nodeId, qname)); + } + } + return scopes; + } + + + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistration.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistration.java new file mode 100644 index 000000000..b7295f870 --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistration.java @@ -0,0 +1,131 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Message object for registering for notifications + * + * @author jack + * + */ +public class ScopeRegistration { + + private static final String REGEX_RATIO = "^([\\d]+)\\/(min)$"; + private static final Pattern PATTERN_RATIO = Pattern.compile(REGEX_RATIO); + + @Override + public String toString() { + return "ScopeRegistration [data=" + data + ", scopes=" + scopes + ", ratio=" + ratio + ", isvalid=" + + this.validate() + "]"; + } + + private DataType data; + + public DataType getData() { + return data; + } + + public void setData(DataType data) { + this.data = data; + } + + private void setScopes(List<Scope> scopes) { + this.scopes = scopes; + } + + private List<Scope> scopes; + private String ratio; + + @JsonIgnore + private long rationLong; + + public boolean validate() { + return this.data != null && this.validateScopes(); + } + + private boolean validateScopes() { + if (this.scopes == null) { + return false; + } + for (Scope scope : this.scopes) { + if (!scope.isValid()) { + return false; + } + } + return true; + } + + public boolean isType(DataType type) { + return this.data == type; + } + + public List<Scope> getScopes() { + return this.scopes; + } + + public String getRatio() { + return this.ratio; + } + + @JsonIgnore + public boolean hasRatioLimit() { + return this.ratio != null; + } + + @JsonIgnore + public long getRatioPerMinute() { + return this.rationLong; + } + + public void setRatio(String ratio) { + assertRatioExpression(ratio); + this.ratio = ratio; + } + + private void assertRatioExpression(String ratio) { + final Matcher matcher = PATTERN_RATIO.matcher(ratio); + if (!matcher.find()) { + throw new IllegalArgumentException(ratio + " is not a valid ratio expression"); + } else { + this.rationLong = Long.parseLong(matcher.group(1)); + } + } + + public enum DataType { + scopes; + + + } + + public static ScopeRegistration forNotifications(List<Scope> scopes) { + ScopeRegistration reg = new ScopeRegistration(); + reg.setData(DataType.scopes); + reg.setScopes(scopes); + return reg; + } + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistrationResponse.java b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistrationResponse.java new file mode 100644 index 000000000..88cec46f0 --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/model/data/ScopeRegistrationResponse.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.model.data; + +import java.util.List; + +public class ScopeRegistrationResponse { + + private Status status; + private String message; + private List<Scope> scopes; + + public ScopeRegistrationResponse() { + + } + + private ScopeRegistrationResponse(Status status, List<Scope> scopes, String message) { + this.status = status; + this.scopes = scopes; + this.message = message; + } + + public Status getStatus() { + return status; + } + + public String getMessage() { + return message; + } + + public Object getScopes() { + return scopes; + } + + public void setStatus(Status status) { + this.status = status; + } + + public void setMessage(String message) { + this.message = message; + } + + public void setScopes(List<Scope> scopes) { + this.scopes = scopes; + } + + + public static ScopeRegistrationResponse error(String message) { + return new ScopeRegistrationResponse(Status.error, null, message); + } + + public static ScopeRegistrationResponse success(List<Scope> scopes) { + return new ScopeRegistrationResponse(Status.success, scopes, null); + } + + public enum Status { + success, error + } + +} diff --git a/sdnr/wt/websocketmanager/model/src/main/yang/websocketmanager.yang b/sdnr/wt/websocketmanager/model/src/main/yang/websocketmanager.yang new file mode 100644 index 000000000..18d7bd27a --- /dev/null +++ b/sdnr/wt/websocketmanager/model/src/main/yang/websocketmanager.yang @@ -0,0 +1,51 @@ +module websocketmanager { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:websocketmanager"; + prefix websocketmanager; + + import ietf-yang-types { + prefix yang; + } + organization + "highstreet technologies GmbH"; + contact + "Web: <https://highstreet-technologies.com> + ONAP: <https://wiki.onap.org/display/DW/SDN-R+Websocketmanager+Upgrade>"; + + description + "Websocketmanager Api Module + + Copyright 2021 highstreet technologies GmbH 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."; + + revision 2021-03-22 { + description + "Initial revision"; + } + + notification items-dropped-notification { + uses items-dropped-notification-g; + description "none"; + } + grouping items-dropped-notification-g { + leaf amount { + type uint32; + default 0; + description "Counts of notifications that were dropped."; + } + description "To be sent when notifications were dropped in fact of a set ratio limit."; + } +} diff --git a/sdnr/wt/websocketmanager/pom.xml b/sdnr/wt/websocketmanager/pom.xml new file mode 100755 index 000000000..5408f71d2 --- /dev/null +++ b/sdnr/wt/websocketmanager/pom.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2018 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<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> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>odlparent-lite</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-websocketmanager-top</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + + <modules> + <module>model</module> + <module>provider</module> + <module>feature</module> + <module>installer</module> + </modules> + + <properties> + <feature-name>sdnr-wt-websocketmanager</feature-name> + </properties> +</project> diff --git a/sdnr/wt/websocketmanager/provider/pom.xml b/sdnr/wt/websocketmanager/provider/pom.xml new file mode 100644 index 000000000..f1a7d2e52 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/pom.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<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> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>2.2.0-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-websocketmanager-provider</artifactId> + <version>1.2.0-SNAPSHOT</version> + <packaging>bundle</packaging> + + <name>ccsdk-features :: ${project.artifactId}</name> + <licenses> + <license> + <name>Apache License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + </license> + </licenses> + + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + </properties> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-websocketmanager-model</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-yang-utils</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.jetty.websocket</groupId> + <artifactId>websocket-api</artifactId> + </dependency> + <dependency> + <groupId>org.eclipse.jetty.websocket</groupId> + <artifactId>websocket-servlet</artifactId> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-transport</artifactId> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + <!-- <version>${netty.version}</version> --> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + </dependency> + <dependency> + <groupId>com.typesafe.akka</groupId> + <artifactId>akka-actor_2.13</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.typesafe.akka</groupId> + <artifactId>akka-cluster_2.13</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.java-websocket</groupId> + <artifactId>Java-WebSocket</artifactId> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>mdsal-binding-api</artifactId> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>mdsal-dom-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId> + <artifactId>rfc6991-ietf-yang-types</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.core</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.osgi</groupId> + <artifactId>org.osgi.compendium</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-devicemanager-provider</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-data-provider-model</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + + </dependencies> +</project> diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManager.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManager.java new file mode 100644 index 000000000..7b4916d5a --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManager.java @@ -0,0 +1,130 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.websocket.servlet.WebSocketServlet; +import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.WebSocketManagerSocket.EventInputCallback; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.AkkaConfig; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.AkkaConfig.ClusterConfig; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.AkkaConfig.ClusterNodeInfo; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.websocket.SyncWebSocketClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketManager extends WebSocketServlet { + + private static final long serialVersionUID = -681665669062744439L; + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketManager.class.getName()); + private static final String APPLICATION_NAME = WebSocketManager.class.getName(); + private static final int PORT = 8181; + private final EventInputCallback rpcEventInputCallback; + private final AkkaConfig akkaConfig; + /** + * timeout for websocket with no messages in ms + */ + //private static final long IDLE_TIMEOUT = 5 * 60 * 1000L; + private static final long IDLE_TIMEOUT = 0L; + + private final ArrayList<URI> clusterNodeClients = new ArrayList<>(); + + public WebSocketManager() { + this(null, null); + } + + public WebSocketManager(AkkaConfig akkaconfig, EventInputCallback cb) { + super(); + this.akkaConfig = akkaconfig; + if (cb != null) { + this.rpcEventInputCallback = cb; + } else { + this.rpcEventInputCallback = message -> { + LOG.debug("onMessagePushed: " + message); + SyncWebSocketClient client; + for (URI clientURI : WebSocketManager.this.clusterNodeClients) { + client = new SyncWebSocketClient(clientURI); + LOG.debug("try to push message to " + client.getURI()); + client.openAndSendAndCloseSync(message); + } + }; + } + LOG.info("Create servlet for {}", APPLICATION_NAME); + } + + @Override + public void configure(WebSocketServletFactory factory) { + LOG.info("Configure provider for {}", APPLICATION_NAME); + // set a second timeout + factory.getPolicy().setIdleTimeout(IDLE_TIMEOUT); + factory.getPolicy().setMaxBinaryMessageSize(1); + factory.getPolicy().setMaxTextMessageSize(64 * 1024); + + // register Socket as the WebSocket to create on Upgrade + factory.register(WebSocketManagerSocket.class); + + AkkaConfig cfg = this.akkaConfig; + if (cfg == null) { + try { + cfg = AkkaConfig.load(); + } catch (Exception e) { + LOG.warn("problem loading akka config: " + e.getMessage()); + } + } + if (cfg != null && cfg.isCluster()) { + this.initWSClients(cfg.getClusterConfig()); + } + } + + /********************************************************** + * Private functions + */ + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + if (req.getHeader("Upgrade") != null) { + /* Accept upgrade request */ + resp.setStatus(101); + resp.setHeader("Upgrade", "XYZP"); + resp.setHeader("Connection", "Upgrade"); + resp.setHeader("OtherHeaderB", "Value"); + } + } + + private void initWSClients(ClusterConfig clusterConfig) { + for (ClusterNodeInfo nodeConfig : clusterConfig.getSeedNodes()) { + if (clusterConfig.isMe(nodeConfig)) { + continue; + } + String url = String.format("ws://%s:%d/websocket", nodeConfig.getRemoteAddress(), PORT); + try { + LOG.debug("registering ws client for " + url); + clusterNodeClients.add(new URI(url)); + } catch (URISyntaxException e) { + LOG.warn("problem instantiating wsclient for url: " + url); + } + } + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerProvider.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerProvider.java new file mode 100644 index 000000000..0b6e9b453 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerProvider.java @@ -0,0 +1,109 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager; + +import java.time.Instant; +import javax.servlet.ServletException; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.WebsocketManagerService; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.NotificationOutput; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapperHelper; +import org.opendaylight.mdsal.dom.api.DOMNotification; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yangtools.yang.binding.Notification; +import org.opendaylight.yangtools.yang.common.QName; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketManagerProvider implements WebsocketManagerService, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketManagerProvider.class); + private static final String APPLICATION_NAME = WebSocketManagerProvider.class.getName(); + private static final String ALIAS = "/websocket"; + + private WebSocketManager wsServlet = null; + + public WebSocketManagerProvider() { + LOG.info("Creating provider for {}", APPLICATION_NAME); + } + + + public void init() { + LOG.info("Init provider for {}", APPLICATION_NAME); + } + + @Override + public void close() throws Exception { + LOG.info("Close provider for {}", APPLICATION_NAME); + } + + public void onUnbindService(HttpService httpService) { + httpService.unregister(ALIAS); + wsServlet = null; + } + + public void onBindService(HttpService httpService) throws ServletException, NamespaceException { + if (httpService == null) { + LOG.warn("Unable to inject HttpService into DluxLoader. dlux modules won't work without httpService"); + } else { + + if (wsServlet == null) { + wsServlet = new WebSocketManager(); + httpService.registerServlet(ALIAS, wsServlet, null, null); + LOG.info("websocket servlet registered."); + } else { + LOG.warn("Servelt "); + } + } + + } + + public WebSocketManager getWsServlet() { + return wsServlet; + } + + public void setWsServlet(WebSocketManager wsServlet) { + this.wsServlet = wsServlet; + } + + + @Override + public void sendNotification(Notification notification, String nodeId, QName eventType) { + this.sendNotification(notification, nodeId, eventType, YangToolsMapperHelper.getTime(notification,Instant.now())); + } + + @Override + public void sendNotification(Notification notification, String nodeId, QName eventType, DateAndTime eventTime) { + WebSocketManagerSocket.broadCast(new NotificationOutput(notification, nodeId, eventType, eventTime)); + + } + + @Override + public void sendNotification(DOMNotification notification, String nodeId, QName eventType) { + LOG.warn("not yet implemented"); + + } + + @Override + public void sendNotification(DOMNotification notification, String nodeId, QName eventType, DateAndTime eventTime) { + LOG.warn("not yet implemented"); + + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerSocket.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerSocket.java new file mode 100644 index 000000000..945de3c1f --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/WebSocketManagerSocket.java @@ -0,0 +1,245 @@ +/* +* ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager; + +import com.fasterxml.jackson.core.JsonProcessingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.WebSocketAdapter; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.NotificationOutput; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ReducedSchemaInfo; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ScopeRegistration; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ScopeRegistration.DataType; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ScopeRegistrationResponse; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.UserScopes; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebSocketManagerSocket extends WebSocketAdapter { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketManagerSocket.class.getName()); + public static final String MSG_KEY_DATA = "data"; + public static final DataType MSG_KEY_SCOPES = DataType.scopes; + public static final String MSG_KEY_PARAM = "param"; + public static final String MSG_KEY_VALUE = "value"; + public static final String MSG_KEY_SCOPE = "scope"; + + public static final String KEY_NODEID = "nodeId"; + public static final String KEY_EVENTTYPE = "eventType"; + private static final String REGEX_SCOPEREGISTRATION = "\"data\"[\\s]*:[\\s]*\"scopes\""; + private static final Pattern PATTERN_SCOPEREGISTRATION = + Pattern.compile(REGEX_SCOPEREGISTRATION, Pattern.MULTILINE); + private static final Random RND = new Random(); + + + /** + * list of all sessionids + */ + private static final List<String> sessionIds = new ArrayList<>(); + /** + * map of sessionid <=> UserScopes + */ + private static final HashMap<String, UserScopes> userScopesList = new HashMap<>(); + /** + * map of class.hashCode <=> class + */ + private static final HashMap<String, WebSocketManagerSocket> clientList = new HashMap<>(); + + private static final YangToolsMapper mapper = new YangToolsMapper(); + private final String myUniqueSessionId; + + private Session session = null; + + public interface EventInputCallback { + void onMessagePushed(final String message) throws Exception; + } + + public WebSocketManagerSocket() { + this.myUniqueSessionId = _genSessionId(); + } + + @Override + protected void finalize() throws Throwable { + sessionIds.remove(this.myUniqueSessionId); + } + + private static String _genSessionId() { + String sid = String.valueOf(RND.nextLong()); + while (sessionIds.contains(sid)) { + sid = String.valueOf(RND.nextLong()); + } + sessionIds.add(sid); + return sid; + } + + @Override + public void onWebSocketText(String message) { + LOG.info("{} has sent {}", this.getRemoteAdr(), message); + if (!this.manageClientRequest(message)) { + this.manageClientRequest2(message); + } + } + + @Override + public void onWebSocketBinary(byte[] payload, int offset, int len) { + LOG.debug("Binary not supported"); + } + + @Override + public void onWebSocketConnect(Session sess) { + this.session = sess; + clientList.put(String.valueOf(this.hashCode()), this); + LOG.debug("client connected from " + this.getRemoteAdr()); + } + + @Override + public void onWebSocketClose(int statusCode, String reason) { + clientList.remove(String.valueOf(this.hashCode())); + LOG.debug("client disconnected from " + this.getRemoteAdr()); + } + + @Override + public void onWebSocketError(Throwable cause) { + LOG.debug("error caused on " + this.getRemoteAdr() + " :" + cause.getMessage()); + // super.onWebSocketError(cause); + } + + private String getRemoteAdr() { + String adr = "unknown"; + try { + adr = this.session.getRemoteAddress().toString(); + } catch (Exception e) { + LOG.debug("error resolving adr: {}", e.getMessage()); + } + return adr; + } + + /** + * + * @param request is a json object {"data":"scopes","scopes":["scope1","scope2",...]} + * @return if handled + */ + private boolean manageClientRequest(String request) { + boolean ret = false; + final Matcher matcher = PATTERN_SCOPEREGISTRATION.matcher(request); + if(!matcher.find()) { + return false; + } + try { + ScopeRegistration registration = mapper.readValue(request, ScopeRegistration.class); + if (registration!=null && registration.validate() && registration.isType(MSG_KEY_SCOPES)) { + ret = true; + String sessionId = this.getSessionId(); + UserScopes clientDto = new UserScopes(); + clientDto.setScopes(registration.getScopes()); + userScopesList.put(sessionId, clientDto); + this.send(mapper.writeValueAsString(ScopeRegistrationResponse.success(registration.getScopes()))); + } + + } catch (JsonProcessingException e) { + LOG.warn("problem set scope: " + e.getMessage()); + try { + this.send(mapper.writeValueAsString(ScopeRegistrationResponse.error(e.getMessage()))); + } catch (JsonProcessingException e1) { + LOG.warn("problem sending error response via ws: " + e1); + } + } + return ret; + } + + /* + * broadcast message to all your clients + */ + private void manageClientRequest2(String request) { + try { + NotificationOutput notification = mapper.readValue(request, NotificationOutput.class); + if (notification.getNodeId() != null && notification.getType() != null) { + this.sendToAll(notification.getNodeId(), notification.getType(), request); + } + } catch (Exception e) { + LOG.warn("handle ws request failed:" + e.getMessage()); + } + } + + public void send(String msg) { + try { + LOG.trace("sending {}", msg); + this.session.getRemote().sendString(msg); + } catch (Exception e) { + LOG.warn("problem sending message: " + e.getMessage()); + } + } + + public String getSessionId() { + return this.myUniqueSessionId; + } + + private void sendToAll(NotificationOutput output) { + try { + this.sendToAll(output.getNodeId(), output.getType(), mapper.writeValueAsString(output)); + } catch (JsonProcessingException e) { + LOG.warn("problem serializing noitifcation: ", e); + } + } + + private void sendToAll(String nodeId, ReducedSchemaInfo reducedSchemaInfo, String notification) { + if (clientList.size() > 0) { + for (Map.Entry<String, WebSocketManagerSocket> entry : clientList.entrySet()) { + WebSocketManagerSocket socket = entry.getValue(); + if (socket != null) { + try { + UserScopes clientScopes = userScopesList.get(socket.getSessionId()); + if (clientScopes != null) { + if (clientScopes.hasScope(nodeId, reducedSchemaInfo)) { + socket.send(notification); + } else { + LOG.debug("client has not scope {}", reducedSchemaInfo); + } + } else { + LOG.debug("no scopes for notifications registered"); + } + } catch (Exception ioe) { + LOG.warn(ioe.getMessage()); + } + } else { + LOG.debug("cannot broadcast. socket is null"); + } + } + } + } + + public static void broadCast(NotificationOutput output) { + if (clientList.size() > 0) { + Set<Entry<String, WebSocketManagerSocket>> e = clientList.entrySet(); + WebSocketManagerSocket s = e.iterator().next().getValue(); + if (s != null) { + s.sendToAll(output); + } + } + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/data/TimeRateLimitingQueue.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/data/TimeRateLimitingQueue.java new file mode 100644 index 000000000..6627eeadf --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/data/TimeRateLimitingQueue.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.data; + +import java.util.concurrent.ArrayBlockingQueue; + +public class TimeRateLimitingQueue<T> extends ArrayBlockingQueue<T>{ + + public TimeRateLimitingQueue(int capacity) { + super(capacity); + // TODO Auto-generated constructor stub + } + + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/AkkaConfig.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/AkkaConfig.java new file mode 100644 index 000000000..794515bb2 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/AkkaConfig.java @@ -0,0 +1,207 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.utils; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.WebSocketManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AkkaConfig { + + private static final Logger LOG = LoggerFactory.getLogger(WebSocketManager.class.getName()); + + public static class ClusterNodeInfo { + @Override + public String toString() { + return "ClusterNodeInfo [protocol=" + protocol + ", clusterName=" + clusterName + ", remoteAdr=" + remoteAdr + + ", port=" + port + "]"; + } + + private final String protocol; + private final String clusterName; + private final String remoteAdr; + private final int port; + + public String getRemoteAddress() { + return this.remoteAdr; + } + + public ClusterNodeInfo(String s) throws Exception { + final String regex = "([a-z.]*):\\/\\/([a-zA-Z0-9-]*)@([a-zA-Z0-9.-]*):([0-9]*)"; + final Pattern pattern = Pattern.compile(regex); + final Matcher matcher = pattern.matcher(s); + if (!matcher.find()) { + throw new Exception("invalid seedNode format"); + } + this.protocol = matcher.group(1); + this.clusterName = matcher.group(2); + this.remoteAdr = matcher.group(3); + this.port = Integer.parseInt(matcher.group(4)); + } + } + public static class ClusterRoleInfo { + @Override + public String toString() { + return "ClusterRoleInfo [Role=" + Role + ", Index=" + Index + "]"; + } + + private final String Role; + private final int Index; + + public ClusterRoleInfo(String s) throws Exception { + final String regex = "([a-z]*)-([0-9]*)"; + final Pattern pattern = Pattern.compile(regex); + final Matcher matcher = pattern.matcher(s); + if (!matcher.find()) { + throw new Exception("invalid role format"); + } + this.Role = matcher.group(1); + this.Index = Integer.parseInt(matcher.group(2)); + } + + } + public static class ClusterConfig { + @Override + public String toString() { + return "ClusterConfig [seedNodes=" + seedNodes + ", roles=" + roles + "]"; + } + + private final List<ClusterNodeInfo> seedNodes; + private final List<ClusterRoleInfo> roles; + private final ClusterNodeInfo ismeInfo; + + public ClusterConfig(Config o) throws Exception { + { + this.seedNodes = new ArrayList<>(); + List<String> a = o.getStringList("seed-nodes"); + for (int i = 0; i < a.size(); i++) { + ClusterNodeInfo info = new ClusterNodeInfo(a.get(i)); + this.seedNodes.add(info); + } + this.roles = new ArrayList<>(); + a = o.getStringList("roles"); + for (int i = 0; i < a.size(); i++) { + ClusterRoleInfo s = new ClusterRoleInfo(a.get(i)); + this.roles.add(s); + } + int idx = this.roles.get(0).Index - 1; + if (idx >= 0 && idx < this.seedNodes.size()) { + this.ismeInfo = this.seedNodes.get(idx); + } else { + this.ismeInfo = null; + } + } + + } + + public boolean isCluster() { + return this.seedNodes != null ? this.seedNodes.size() > 1 : false; + } + + public boolean isMe(ClusterNodeInfo i) { + return this.ismeInfo != null ? this.ismeInfo.equals(i) : false; + } + + public List<ClusterNodeInfo> getSeedNodes() { + return this.seedNodes; + } + } + + private static final String DEFAULT_FILENAME = "configuration/initial/akka.conf"; + private final File file; + private final String resourceFilename; + private final String fileContent; + private ClusterConfig cluserConfig; + + public ClusterConfig getClusterConfig() { + return this.cluserConfig; + } + + private AkkaConfig(File file, boolean isResource) { + this.file = isResource ? null : file; + this.fileContent = null; + this.resourceFilename = isResource ? file.getName() : null; + } + + private AkkaConfig(String fileContent) { + this.file = null; + this.fileContent = fileContent; + this.resourceFilename = null; + } + + + @Override + public String toString() { + return "AkkaConfig [filename=" + file + ", cluserConfig=" + cluserConfig + "]"; + } + + private void loadFromFile() throws Exception { + Config cfg = null; + if (this.file != null) { + cfg = ConfigFactory.parseFile(this.file); + } else if (this.fileContent != null) { + cfg = ConfigFactory.parseString(this.fileContent); + } else if (this.resourceFilename != null) { + cfg = ConfigFactory.parseResources(this.getClass(), this.resourceFilename); + } + + if (cfg != null) { + this.cluserConfig = + new ClusterConfig(cfg.getConfig("odl-cluster-data").getConfig("akka").getConfig("cluster")); + } else { + LOG.warn("unable to parse config file"); + this.cluserConfig = null; + } + } + + public boolean isCluster() { + return this.cluserConfig != null ? this.cluserConfig.isCluster() : false; + } + + public static AkkaConfig load() throws Exception { + return load(DEFAULT_FILENAME); + } + + public static AkkaConfig load(String filename) throws Exception { + return load(filename, false); + } + + public static AkkaConfig load(String filename, boolean isResource) throws Exception { + AkkaConfig cfg = new AkkaConfig(new File(filename), isResource); + cfg.loadFromFile(); + + return cfg; + } + + public static AkkaConfig loadContent(String content) throws Exception { + AkkaConfig cfg = new AkkaConfig(content); + cfg.loadFromFile(); + + return cfg; + } + + + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/RateFilter.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/RateFilter.java new file mode 100644 index 000000000..5f3a5af2c --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/RateFilter.java @@ -0,0 +1,138 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.utils; + +import java.time.Duration; +import java.time.Instant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Problems of to many notifications during mount of thousand of devices: + * <ul> + * <li>Overload ODLUX with notification flood -> ODLUX App can not control notifications rate + * <li>Notification processing blocks user -> App design with notifications popups + * </ul> + * Rate filter + * <ul> + * <li>Do not use a thread -> Do nothing if there are no notifications + * <li>Parameter1 integrationTime : Measurement or integration time for period + * <li>Parameter2 readMaxCount : Specifies event number per interval indicating overload + * <li>Start measurement on event received that comes later then + * </ul> + * + * <pre> + * Example (e: Event received, rateMaxCount=3) + * eee e e e e e e e e e e e e e e + * ---//--|--------------|-----//-------|--------------|--------------|--------------|---//----|--------------| + * P1 P2 P1 P2 P3 P7 P1 + *Overload no no yes yes no no + * + * + *Intention to use: + * 1. Construct with parameters for WS stream to handle + * 2. + * </pre> + */ + +public class RateFilter { + + private static final Logger LOG = LoggerFactory.getLogger(RateFilter.class.getName()); + + private final Duration integrationTime; // Integration time to measure event rate + private final long rateMaxCount; //Rate for dropping packets + private Instant timeStampPeriodStart; //Time stamp period beginn + private Instant timeStampLastEvent; //Measurement interval + private long rateCount; // >0: integration running 0: no integration running + private boolean overload; //true means in overload status. Change at end of period only. + private GetNow get; + + /** + * Allow testing with own timestamp provider + */ + public interface GetNow { + Instant now(); + } + + public RateFilter(Duration integrationTime, long rateMaxCount, GetNow getNowMethod) { + this.integrationTime = integrationTime; + this.rateMaxCount = rateMaxCount; + this.get = getNowMethod; + this.timeStampLastEvent = Instant.MIN; + } + + public RateFilter(Duration integrationTime, long rateMaxCount) { + this(integrationTime, rateMaxCount, () -> Instant.now()); + } + + public synchronized boolean getOverloadStatus() { + return overload; + } + + /** + * Handle filter on event received + */ + public synchronized void filterEvent() { + final Instant now = get.now(); + final Duration durationSinceLastEvent = Duration.between(timeStampLastEvent, now); + this.timeStampLastEvent = now; + + if (durationSinceLastEvent.compareTo(integrationTime) >= 0) { + //No measurement. Sync and start with period + LOG.debug("Sync"); + timeStampPeriodStart = now; + rateCount = 1; //Reset event count .. is part of the + } else { + //Within period + Duration durationPeriod = Duration.between(timeStampPeriodStart, now); + rateCount++; + boolean endOfPeriod = durationPeriod.compareTo(integrationTime) >= 0; + LOG.debug("Period start{}: now:{} end:{} dur:{} int:{}", timeStampPeriodStart, now, endOfPeriod, durationPeriod, integrationTime); + if (endOfPeriod) { + //Only if end of Period + overload = rateCount > rateMaxCount; + LOG.debug("Reset overload {}", overload); + timeStampPeriodStart = timeStampPeriodStart.plus(integrationTime); + rateCount = 0; + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("RateFilter [integrationTime="); + builder.append(integrationTime); + builder.append(", rateMaxCount="); + builder.append(rateMaxCount); + builder.append(", timeStampPeriodStart="); + builder.append(timeStampPeriodStart); + builder.append(", timeStampLastEvent="); + builder.append(timeStampLastEvent); + builder.append(", rateCount="); + builder.append(rateCount); + builder.append(", overload="); + builder.append(overload); + builder.append("]"); + return builder.toString(); + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/UserScopes.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/UserScopes.java new file mode 100644 index 000000000..3969bcb15 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/utils/UserScopes.java @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.utils; + +import java.util.List; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.NotificationOutput; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ReducedSchemaInfo; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.Scope; + +public class UserScopes { + + private List<Scope> scopes; + + /** + * + * @param list array of Strings + */ + public void setScopes(List<Scope> list) { + this.scopes = list; + } + + public boolean hasScope(NotificationOutput output) { + return this.hasScope(output.getNodeId(), output.getType()); + } + + public boolean hasScope(ReducedSchemaInfo schema) { + return this.hasScope(null, schema); + } + + public boolean hasScope(String nodeId, ReducedSchemaInfo reducedSchemaInfo) { + if (this.scopes == null) + return false; + for (Scope scope : this.scopes) { + if (scope.matches(nodeId, reducedSchemaInfo)) { + return true; + } + } + return false; + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/websocket/SyncWebSocketClient.java b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/websocket/SyncWebSocketClient.java new file mode 100644 index 000000000..c9177205b --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager/websocket/SyncWebSocketClient.java @@ -0,0 +1,120 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager.websocket; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import org.java_websocket.client.WebSocketClient; +import org.java_websocket.handshake.ServerHandshake; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SyncWebSocketClient extends WebSocketClient { + + public interface WebsocketEventHandler { + void onMessageReceived(String message); + + void onOpen(ServerHandshake arg0); + + void onClose(int arg0, String arg1, boolean arg2); + + void onError(Exception e); + } + + private static final Logger LOG = LoggerFactory.getLogger(SyncWebSocketClient.class.getName()); + private String messageToSend; + private final List<WebsocketEventHandler> handlers; + + public SyncWebSocketClient(URI serverUri) { + super(serverUri); + this.handlers = new ArrayList<WebsocketEventHandler>(); + } + + public SyncWebSocketClient(String uri) throws URISyntaxException { + this(new URI(uri)); + } + + public void addEventHandler(WebsocketEventHandler h) { + this.handlers.add(h); + } + + public void removeEventHandler(WebsocketEventHandler h) { + this.handlers.remove(h); + } + + @Override + public void onClose(int arg0, String arg1, boolean arg2) { + LOG.debug("socket closed: {} {} {}", arg0, arg1, arg2); + for (WebsocketEventHandler h : this.handlers) { + h.onClose(arg0, arg1, arg2); + } + } + + @Override + public void onError(Exception arg0) { + LOG.warn("error on socket: {}", arg0.getMessage()); + for (WebsocketEventHandler h : this.handlers) { + h.onError(arg0); + } + } + + @Override + public void onMessage(String arg0) { + LOG.debug("received message: {}", arg0); + for (WebsocketEventHandler h : this.handlers) { + h.onMessageReceived(arg0); + } + } + + @Override + public void onOpen(ServerHandshake arg0) { + LOG.debug("socket opened"); + if (this.messageToSend != null) { + LOG.debug("try to send: " + this.messageToSend); + this.send(this.messageToSend); + this.messageToSend = null; + } + for (WebsocketEventHandler h : this.handlers) { + h.onOpen(arg0); + } + } + + public void openAndSendAsync(String message) { + this.messageToSend = message; + this.connect(); + } + + public void openAndSendAndCloseSync(String message) { + try { + this.connectBlocking(); + } catch (InterruptedException e) { + LOG.warn("problem connecting:" + e.getMessage()); + Thread.currentThread().interrupt(); + } + this.send(message); + try { + this.closeBlocking(); + } catch (InterruptedException e) { + LOG.warn("problem disconnecting:" + e.getMessage()); + Thread.currentThread().interrupt(); + } + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/websocketmanager/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml new file mode 100644 index 000000000..e3b36e3fe --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ ============LICENSE_START======================================================= + ~ ONAP : ccsdk features + ~ ================================================================================ + ~ Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. + ~ All rights reserved. + ~ ================================================================================ + ~ Update Copyright (C) 2020 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======================================================= + ~ + --> + +<blueprint xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> + + <bean id="provider" class="org.onap.ccsdk.features.sdnr.wt.websocketmanager.WebSocketManagerProvider" init-method="init" destroy-method="close"> + </bean> + + <reference id="onBindService" availability="mandatory" activation="eager" interface="org.osgi.service.http.HttpService"> + <reference-listener ref="provider" bind-method="onBindService" unbind-method="onUnbindService"/> + </reference> + + <service id="registerWebsocketmanagerService" + interface="org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.WebsocketManagerService" + ref="provider"/> + +</blueprint> diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/AkkaConfigTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/AkkaConfigTest.java new file mode 100644 index 000000000..f3cf09545 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/AkkaConfigTest.java @@ -0,0 +1,76 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.AkkaConfig; + +public class AkkaConfigTest { + + @Test + public void test() throws URISyntaxException, IOException { + + AkkaConfig config = null; + try { + //config = AkkaConfig.load("akka-singlenode.cfg", true); + config = AkkaConfig.loadContent(loadResourceContentAsString("akka-singlenode.cfg")); + } catch (Exception e) { + e.printStackTrace(); + fail("error loading singlenode config"); + } + assertEquals("no singlenode config detected", false, config.isCluster()); + assertEquals("more than one node detected", 1, config.getClusterConfig().getSeedNodes().size()); + + try { + config = AkkaConfig.loadContent(loadResourceContentAsString("akka-cluster.cfg")); + } catch (Exception e) { + fail("error loading cluster config"); + } + assertEquals("no cluster config detected", true, config.isCluster()); + assertTrue("only one node detected", config.getClusterConfig().getSeedNodes().size() > 1); + } + + public static String loadResourceContentAsString(String resourceName) + throws URISyntaxException, FileNotFoundException, IOException { + + StringBuilder sb = new StringBuilder(); + + ClassLoader classLoader = AkkaConfigTest.class.getClassLoader(); + File file = Paths.get(classLoader.getResource(resourceName).toURI()).toFile(); + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + } + return sb.toString(); + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/RateFilterTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/RateFilterTest.java new file mode 100644 index 000000000..f4fab6810 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/RateFilterTest.java @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import java.time.Duration; +import java.time.Instant; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.RateFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link #RateFilter} Problems of to many notifications during mount of thousand of devices. + * + * <pre> + * Testcase (e: 17 Event received, rateMaxCount=3) + * eee e e e e e e e e e e e e e e + * ---//--|--------------|-----//-------|--------------|--------------|--------------|---//----|--------------| + * P1:1 P2:1 P1:2 P2:2 P3:2 P4:2 P1:3 + * 1000-1002 2000 3500 10 millis + *Overload no no yes yes no no + * </pre> + * + */ +public class RateFilterTest { + + private static final Logger LOG = LoggerFactory.getLogger(RateFilterTest.class.getName()); + + private static int MILLIS = 1000; + private static long[] now = { 1000, 1001, 1002, //P1:1 0-2 + 3500, 3550, 3560, 3570, 3580, 3590, 3800, //P1:2 3500 3-9 + 4510, 4520, 4530, 4540, 4900, //P2:2 4500 10-14 + 5700, //P3:2 5500 15 + 7000, 8000};//P1:3 16-17 + private static int idx; + + @Test + public void test() { + RateFilter rateFilter = new RateFilter(Duration.ofMillis(MILLIS), 4, () -> getNow()); + LOG.info("Init done"); + + for (int t=0; t < 20; t++) { + LOG.info("{}", t); + rateFilter.filterEvent(); + LOG.info("{}", rateFilter.getOverloadStatus()); + } + + } + + Instant getNow() { + long res; + if (idx < now.length) { + res = now[idx]; + } else { + int lastIdx = now.length - 1; + res = now[lastIdx] + (idx - lastIdx) * MILLIS; + } + idx++; + return Instant.ofEpochMilli(res); + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestDeserialize.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestDeserialize.java new file mode 100644 index 000000000..8c7b451fe --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestDeserialize.java @@ -0,0 +1,85 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2020 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.fail; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ScopeRegistration; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapper; + +public class TestDeserialize { + + private static final String SCOPE_REGISTRATION_JSON = "{\n" + " \"data\":\"scopes\",\n" + " \"scopes\":[\n" + + " {\n" + " \"node-id\":\"ROADM-A\",\n" + " \"schema\":{\n" + + " \"namespace\":\"onf:params:xml:ns:yang:microwave-model\",\n" + + " \"revision\":\"2018-10-10\",\n" + " \"notification\":[\"problem-notification\"]\n" + + " }\n" + " }\n" + " ]\n" + "}"; + private static final String SCOPE_REGISTRATION2_JSON = "{\n" + " \"data\":\"scopes\",\n" + " \"scopes\":[\n" + + " {\n" + " \"node-id\":\"ROADM-A\",\n" + " \"schema\":{\n" + + " \"namespace\":\"onf:params:xml:ns:yang:microwave-model\",\n" + + " \"revision\":\"2018-10-10\",\n" + " \"notification\":[\"problem-notification\"]\n" + + " }\n" + " }\n" + " ],\n" + " \"ratio\":\"120/min\"\n" + "}"; + private static final String SCOPE_REGISTRATION3_INVALID_JSON = "{\n" + " \"data\":\"scopes\",\n" + + " \"scopes\":[\n" + " {\n" + " \"node-id\":\"ROADM-A\",\n" + " \"schema\":{\n" + + " \"namespace\":\"onf:params:xml:ns:yang:microwave-model\",\n" + + " \"revision\":\"2018-10-10\",\n" + " \"notification\":[\"problem-notification\"]\n" + + " }\n" + " }\n" + " ],\n" + " \"ratio\":\"120/sec\"\n" + "}"; + + @Test + public void testScopeRegistration() { + YangToolsMapper mapper = new YangToolsMapper(); + ScopeRegistration obj = null; + try { + obj = mapper.readValue(SCOPE_REGISTRATION_JSON, ScopeRegistration.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + System.out.println(obj); + } + + @Test + public void testScopeRegistration2() { + YangToolsMapper mapper = new YangToolsMapper(); + ScopeRegistration obj = null; + try { + obj = mapper.readValue(SCOPE_REGISTRATION2_JSON, ScopeRegistration.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + System.out.println(obj); + } + + @Test + public void testScopeRegistration3() { + YangToolsMapper mapper = new YangToolsMapper(); + try { + mapper.readValue(SCOPE_REGISTRATION3_INVALID_JSON, ScopeRegistration.class); + } catch (JsonProcessingException | IllegalArgumentException e) { + // e.printStackTrace(); + return; + } + fail("json should not contain a valid ratio"); + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestSerializer.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestSerializer.java new file mode 100644 index 000000000..962838489 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/TestSerializer.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : ccsdk features + * ================================================================================ + * Copyright (C) 2021 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.NotificationOutput; +import org.onap.ccsdk.features.sdnr.wt.yang.mapper.YangToolsMapper; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectCreationNotification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectCreationNotificationBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestSerializer { + + private static final Logger LOG = LoggerFactory.getLogger(TestSerializer.class); + private static final YangToolsMapper mapper = new YangToolsMapper(); + private static final String TIMESTAMP = "2020-04-01T10:20:40.0Z"; + private static final String NODEID = "node1"; + + @Test + public void test1() { + ObjectCreationNotification notification = new ObjectCreationNotificationBuilder().setCounter(Integer.valueOf(5)).build(); + NotificationOutput output = new NotificationOutput(notification, NODEID, ObjectCreationNotification.QNAME,DateAndTime.getDefaultInstance(TIMESTAMP)); + String sOutput=null; + try { + sOutput = mapper.writeValueAsString(output); + LOG.debug(sOutput); + } catch (JsonProcessingException e) { + e.printStackTrace(); + fail(e.getMessage()); + } + assertNotNull(sOutput); + assertTrue(sOutput.contains("\"type\"")); + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/UserScopeTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/UserScopeTest.java new file mode 100644 index 000000000..d21bb529c --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/UserScopeTest.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.ReducedSchemaInfo; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.SchemaInfo; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.model.data.Scope; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.UserScopes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ObjectCreationNotification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.devicemanager.rev190109.ProblemNotification; +import org.opendaylight.yangtools.yang.common.QName; + +public class UserScopeTest { + + private static final String SCOPE1 = "problem-notification"; + private static final String SCOPE2 = "scope2"; + private static final String SCOPE3 = "scope3"; + private static final String SCOPE4 = "scope4"; + + @Test + public void test() { + UserScopes scopes1 = new UserScopes(); + List<String> json1 = Arrays.asList(SCOPE1, SCOPE2, SCOPE3); + scopes1.setScopes(Arrays.asList(buildScope(null, ProblemNotification.QNAME))); + + assertTrue(scopes1.hasScope(new ReducedSchemaInfo(ProblemNotification.QNAME))); + assertFalse(scopes1.hasScope("RoadmA", new ReducedSchemaInfo(ObjectCreationNotification.QNAME))); + + assertTrue(scopes1.hasScope("RoadmA", new ReducedSchemaInfo(ProblemNotification.QNAME))); + + } + + + private static final Scope buildScope(String nodeId, QName qname) { + Scope scope = new Scope(); + scope.setNodeId(nodeId); + scope.setSchema(new SchemaInfo(qname)); + return scope; + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsockerProviderTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsockerProviderTest.java new file mode 100644 index 000000000..bc3cd10f8 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsockerProviderTest.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.fail; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.WebSocketManagerProvider; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.osgi.service.http.HttpService; + +public class WebsockerProviderTest extends Mockito { + + @Test + public void test() { + RpcProviderService rpcProviderServiceMock = mock(RpcProviderService.class); + HttpService httpService = mock(HttpService.class); + + try (WebSocketManagerProvider provider = new WebSocketManagerProvider();) { + provider.init(); + provider.onBindService(httpService); + provider.close(); + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketClientTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketClientTest.java new file mode 100644 index 000000000..0ef1bff63 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketClientTest.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.fail; +import org.java_websocket.handshake.ServerHandshake; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.websocket.SyncWebSocketClient; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.websocket.SyncWebSocketClient.WebsocketEventHandler; + +public class WebsocketClientTest extends Mockito { + + @Test + public void test() { + + WebsocketEventHandler clientHandlerMock = mock(WebsocketEventHandler.class); + ServerHandshake serverHandshakeMock = mock(ServerHandshake.class); + + try { + SyncWebSocketClient client = new SyncWebSocketClient("url"); + + client.addEventHandler(clientHandlerMock); + client.onMessage("TestMessage"); + client.onOpen(serverHandshakeMock); + client.close(); + } catch (Exception e) { + e.printStackTrace(); + fail("Exception " + e.getMessage()); + } + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketMessageTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketMessageTest.java new file mode 100644 index 000000000..e029150fa --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketMessageTest.java @@ -0,0 +1,83 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import java.net.InetSocketAddress; +import org.eclipse.jetty.websocket.api.Session; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.WebSocketManagerSocket; + +public class WebsocketMessageTest { + + private static final String MSG1 = "{\"data\":\"scopes\",\"scopes\":[{\"node-id\":\"scope1\"}]}"; + private static final String MSG1_RESPONSE = "{\"status\":\"success\",\"scopes\":[{\"node-id\":\"scope1\"}]}"; + private static final String MSG2 = "{}"; + private static final String MSG3 = "{\n" + + " \"event-time\": \"2021-03-12T05:08:55.3Z\",\n" + + " \"type\": \"urn:opendaylight:params:xml:ns:yang:devicemanager@2019-01-09:object-creation-notification\",\n" + + " \"node-id\": \"SDN-Controller-0\",\n" + + " \"data\": {\n" + + " \"object-id-ref\": \"sim1\",\n" + + " \"counter\": 7,\n" + + " \"time-stamp\": \"2021-03-12T05:08:55.2Z\"\n" + + " }\n" + + "}"; + private static final String MSG4 = "{ Not correct messga}"; + + @Test + public void test() { + MyWebSocketManagerSocket socketToTest = new MyWebSocketManagerSocket(); + Session sess = mock(Session.class); + InetSocketAddress remoteAdr = new InetSocketAddress("127.0.0.1", 4444); + when(sess.getRemoteAddress()).thenReturn(remoteAdr); + socketToTest.onWebSocketConnect(sess); + // message from client + socketToTest.setExpected(MSG1_RESPONSE); + socketToTest.onWebSocketText(MSG1); + socketToTest.setExpected(MSG2); + socketToTest.onWebSocketText(MSG2); + socketToTest.setExpected(MSG3); + socketToTest.onWebSocketText(MSG3); + socketToTest.setExpected(MSG4); + socketToTest.onWebSocketText(MSG4); + socketToTest.onWebSocketClose(0, "by default"); + sess.close(); + + } + + private static class MyWebSocketManagerSocket extends WebSocketManagerSocket { + + private String expected; + + public MyWebSocketManagerSocket() {} + + void setExpected(String expected) { + this.expected = expected; + } + + @Override + public void send(String msg) { + System.out.println(msg); + assertTrue("Expected '" + expected + "' answer '" + msg + "'", msg.contains(expected)); + } + + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketServerConnectTest.java b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketServerConnectTest.java new file mode 100644 index 000000000..b9869419e --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/websocketmanager2/test/WebsocketServerConnectTest.java @@ -0,0 +1,45 @@ +/* + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH 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.features.sdnr.wt.websocketmanager2.test; + +import static org.junit.Assert.fail; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils.AkkaConfig; + +public class WebsocketServerConnectTest { + + private static final String XML1 = "<notification></notification>"; + private static final String NODENAME = "abc"; + private static final String EVENTTYPE = "test"; + protected boolean responseReceived; + + @Test + public void test() { + responseReceived = false; + AkkaConfig config = null; + try { + // config = AkkaConfig.load("akka-singlenode.cfg", true); + config = AkkaConfig.loadContent(AkkaConfigTest.loadResourceContentAsString("akka-cluster-local.cfg")); + } catch (Exception e) { + e.printStackTrace(); + fail("error loading singlenode config"); + } + + } + +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster-local.cfg b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster-local.cfg new file mode 100644 index 000000000..465dcad83 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster-local.cfg @@ -0,0 +1,49 @@ +odl-cluster-data { + akka { + remote { + artery { + enabled = off + canonical.hostname = "192.168.178.143" + canonical.port = 2550 + } + netty.tcp { + hostname = "192.168.178.143" + port = 2550 + } + # when under load we might trip a false positive on the failure detector + # transport-failure-detector { + # heartbeat-interval = 4 s + # acceptable-heartbeat-pause = 16s + # } + } + + cluster { + # Remove ".tcp" when using artery. + seed-nodes = ["akka.tcp://opendaylight-cluster-data@192.168.178.142:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.143:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.144:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.145:2550"] + + roles = ["member-2"] + + } + + persistence { + # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by + # modifying the following two properties. The directory location specified may be a relative or absolute path. + # The relative path is always relative to KARAF_HOME. + + # snapshot-store.local.dir = "target/snapshots" + # journal.leveldb.dir = "target/journal" + + journal { + leveldb { + # Set native = off to use a Java-only implementation of leveldb. + # Note that the Java-only version is not currently considered by Akka to be production quality. + + # native = off + } + } + } + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster.cfg b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster.cfg new file mode 100644 index 000000000..465dcad83 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-cluster.cfg @@ -0,0 +1,49 @@ +odl-cluster-data { + akka { + remote { + artery { + enabled = off + canonical.hostname = "192.168.178.143" + canonical.port = 2550 + } + netty.tcp { + hostname = "192.168.178.143" + port = 2550 + } + # when under load we might trip a false positive on the failure detector + # transport-failure-detector { + # heartbeat-interval = 4 s + # acceptable-heartbeat-pause = 16s + # } + } + + cluster { + # Remove ".tcp" when using artery. + seed-nodes = ["akka.tcp://opendaylight-cluster-data@192.168.178.142:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.143:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.144:2550", + "akka.tcp://opendaylight-cluster-data@192.168.178.145:2550"] + + roles = ["member-2"] + + } + + persistence { + # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by + # modifying the following two properties. The directory location specified may be a relative or absolute path. + # The relative path is always relative to KARAF_HOME. + + # snapshot-store.local.dir = "target/snapshots" + # journal.leveldb.dir = "target/journal" + + journal { + leveldb { + # Set native = off to use a Java-only implementation of leveldb. + # Note that the Java-only version is not currently considered by Akka to be production quality. + + # native = off + } + } + } + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/resources/akka-singlenode.cfg b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-singlenode.cfg new file mode 100644 index 000000000..19e723319 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/resources/akka-singlenode.cfg @@ -0,0 +1,48 @@ +odl-cluster-data { + akka { + remote { + artery { + enabled = off + canonical.hostname = "127.0.0.1" + canonical.port = 2550 + } + netty.tcp { + hostname = "127.0.0.1" + port = 2550 + } + # when under load we might trip a false positive on the failure detector + # transport-failure-detector { + # heartbeat-interval = 4 s + # acceptable-heartbeat-pause = 16s + # } + } + + cluster { + # Remove ".tcp" when using artery. + seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550"] + + roles = [ + "member-1" + ] + + } + + persistence { + # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by + # modifying the following two properties. The directory location specified may be a relative or absolute path. + # The relative path is always relative to KARAF_HOME. + + # snapshot-store.local.dir = "target/snapshots" + # journal.leveldb.dir = "target/journal" + + journal { + leveldb { + # Set native = off to use a Java-only implementation of leveldb. + # Note that the Java-only version is not currently considered by Akka to be production quality. + + # native = off + } + } + } + } +} diff --git a/sdnr/wt/websocketmanager/provider/src/test/resources/simplelogger.properties b/sdnr/wt/websocketmanager/provider/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..1aa3824a1 --- /dev/null +++ b/sdnr/wt/websocketmanager/provider/src/test/resources/simplelogger.properties @@ -0,0 +1,58 @@ +# +# ============LICENSE_START======================================================= +# ONAP : ccsdk features +# ================================================================================ +# Copyright (C) 2020 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======================================================= +# +# + +# SLF4J's SimpleLogger configuration file +# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + +# Default logging detail level for all instances of SimpleLogger. +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=trace + +# Logging detail level for a SimpleLogger instance named "xxx.yyy.zzz". +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, the default logging detail level is used. +# org.slf4j.simpleLogger.log.xxx.yyy=debug +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager=debug +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.internalTypes.Resources=info +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.base.netconf.container=trace + +# Set to true if you want the current date and time to be included in output messages. +# Default is false, and will output the number of milliseconds elapsed since startup. +#org.slf4j.simpleLogger.showDateTime=false + +# The date and time format to be used in the output messages. +# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. +# If the format is not specified or is invalid, the default format is used. +# The default format is yyyy-MM-dd HH:mm:ss:SSS Z. +#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z + +# Set to true if you want to output the current thread name. +# Defaults to true. +#org.slf4j.simpleLogger.showThreadName=true + +# Set to true if you want the Logger instance name to be included in output messages. +# Defaults to true. +#org.slf4j.simpleLogger.showLogName=true + +# Set to true if you want the last component of the name to be included in output messages. +# Defaults to false. +#org.slf4j.simpleLogger.showShortLogName=false |