diff options
author | herbert <herbert.eiselt@highstreet-technologies.com> | 2019-12-14 00:36:01 +0100 |
---|---|---|
committer | Herbert Eiselt <herbert.eiselt@highstreet-technologies.com> | 2019-12-16 11:22:50 +0000 |
commit | 2cf702de0b65fe132ec32b6abfffe4c2c976dca0 (patch) | |
tree | 43bdda96e1320969c08de301cd619ae29621386e | |
parent | 3309d25d5883ebaa9db9fa10a81ff0779dcfb2a3 (diff) |
Add netconfnode-state-service
v2 add new service to devicemanager
Issue-ID: SDNC-1006
Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com>
Change-Id: Iaba3d02e0ef6078cba57a33e03c2b2ad7aa0bacd
Signed-off-by: herbert <herbert.eiselt@highstreet-technologies.com>
42 files changed, 3760 insertions, 0 deletions
diff --git a/sdnr/wt/netconfnode-state-service/feature/pom.xml b/sdnr/wt/netconfnode-state-service/feature/pom.xml new file mode 100644 index 000000000..1e98505a8 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/feature/pom.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + * ============LICENSE_START======================================================= + * ONAP : CCSDK.sdnr.wt.netconfnode-state-service.feature + * ================================================================================ + * Copyright (C) 2018 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========================================================= + +--> +<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> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-feature</artifactId> + <version>0.7.0-SNAPSHOT</version> + <packaging>feature</packaging> + <name>ccsdk-features-sdnr-wt :: ${project.artifactId} :: feature</name> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>single-feature-parent</artifactId> + <version>1.5.1-SNAPSHOT</version> + <relativePath /> + </parent> + + <dependencies> +<!-- <dependency> --> +<!-- <groupId>org.yaml</groupId> --> +<!-- <artifactId>snakeyaml</artifactId> --> +<!-- </dependency> --> +<!-- <dependency> --> +<!-- <groupId>${project.groupId}</groupId> --> +<!-- <artifactId>sdnr-wt-netconfnode-state-service-model</artifactId> --> +<!-- <version>${project.version}</version> --> +<!-- </dependency> --> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> +</project> diff --git a/sdnr/wt/netconfnode-state-service/installer/pom.xml b/sdnr/wt/netconfnode-state-service/installer/pom.xml new file mode 100755 index 000000000..aedc4d2c6 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/installer/pom.xml @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + * ============LICENSE_START======================================================= + * ONAP : CCSDK.sdnr.wt.netconfnode-state-service.installer + * ================================================================================ + * Copyright (C) 2018 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========================================================= + +--> +<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>1.5.1-SNAPSHOT</version> + <relativePath/> + </parent> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-installer</artifactId> + <version>0.7.0-SNAPSHOT</version> + <packaging>pom</packaging> + <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name> + + <properties> + <application.name>sdnr-wt-netconfnode-state-service</application.name> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>mdsal-artifacts</artifactId> + <version>${odl.controller.mdsal.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + + <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/netconfnode-state-service/installer/src/assembly/assemble_mvnrepo_zip.xml b/sdnr/wt/netconfnode-state-service/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 000000000..c4eb9aa25 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,49 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : CCSDK + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + 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/netconfnode-state-service/model/pom.xml b/sdnr/wt/netconfnode-state-service/model/pom.xml new file mode 100644 index 000000000..b0c9840ac --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/pom.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + * ============LICENSE_START======================================================= + * ONAP : CCSDK.sdnr.wt.netconfnode-state-service.model + * ================================================================================ + * Copyright (C) 2018 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========================================================= + +--> +<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> + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-model</artifactId> + <version>0.7.0-SNAPSHOT</version> + <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name> + <packaging>bundle</packaging> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>1.5.1-SNAPSHOT</version> + <relativePath/> + </parent> + + <properties> + <maven.javadoc.skip>true</maven.javadoc.skip> + </properties> + + <licenses> + <license> + <name>Apache License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + </license> + </licenses> + + <dependencies> + <dependency> + <groupId>org.opendaylight.netconf</groupId> + <artifactId>sal-netconf-connector</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-data-provider-model</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <configuration> + <excludes> + <exclude>**/gen/**</exclude> + <exclude>**/generated-sources/**</exclude> + <exclude>**/yang-gen-sal/**</exclude> + <exclude>**/pax/**</exclude> + </excludes> + </configuration> + </plugin> + </plugins> + </build> +</project> diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/Capabilities.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/Capabilities.java new file mode 100644 index 000000000..ba80d305f --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/Capabilities.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * ============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========================================================================== + ******************************************************************************/ +/** + * Convert capabilities of netconfnode into internal format. Boron and Carbon are providing + * different versions + */ +package org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nullable; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities; +import org.opendaylight.yangtools.yang.common.QName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wrapper class for capabilites for Boron and later releases. Uses generics because yang model was + * changed from Boron to later version. Interface class: + * org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability + */ +public class Capabilities { + + private static final Logger LOG = LoggerFactory.getLogger(Capabilities.class); + + private static final String METHODNAME = "getCapability"; + private final List<String> capabilities = new ArrayList<>(); + private final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + + private Capabilities() {} + + @SuppressWarnings("null") + public static Capabilities getAvailableCapabilities(@Nullable NetconfNode nnode) { + LOG.info("GetAvailableCapabilities for node"); + Capabilities capabilities = new Capabilities(); + if (nnode != null) { + AvailableCapabilities availableCapabilites = nnode.getAvailableCapabilities(); + if (availableCapabilites != null) { + capabilities.constructor(availableCapabilites.getAvailableCapability()); + } else { + LOG.debug("empty capabilites"); + } + } else { + LOG.debug("No node provided"); + } + return capabilities; + } + + @SuppressWarnings("null") + public static Capabilities getUnavailableCapabilities(NetconfNode nnode) { + LOG.info("GetAvailableCapabilities for node"); + Capabilities capabilities = new Capabilities(); + if (nnode != null) { + UnavailableCapabilities availableCapabilites = nnode.getUnavailableCapabilities(); + if (availableCapabilites != null) { + capabilities.constructor(availableCapabilites.getUnavailableCapability()); + } else { + LOG.debug("empty capabilites"); + } + } else { + LOG.debug("No node provided"); + } + return capabilities; + } + + + /** + * Does all construction steps + * + * @param pcapabilities with a list of capabilities. <br> + * Type could be <br> + * - Boron: List<code><String></code> <br> + * - Carbon: List<AvailableCapability> + */ + private void constructor(List<@NonNull ?> pcapabilities) { + if (pcapabilities != null) { + Method methodGetCapability; + + for (Object capability : pcapabilities) { + if (capability instanceof String) { // ODL Boron specific + this.capabilities.add((String) capability); + } else { // Carbon specific part .. handled via generics + try { + methodGetCapability = capability.getClass().getDeclaredMethod(METHODNAME); + methodGetCapability.setAccessible(true); + this.capabilities.add(methodGetCapability.invoke(capability).toString()); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + LOG.warn("Capability class with missing interface method {}: {} {} {}", METHODNAME, + e.getMessage(), capability.getClass(), + Arrays.toString(capability.getClass().getInterfaces())); + } + } + } + } + } + + /** + * Get Capabilites + * @return List<String> with capabilites + */ + public List<String> getCapabilities() { + return capabilities; + } + + /** + * Verify if the namespace is supported + * @param qCapability from model + * @return true if namespace is supported + */ + public boolean isSupportingNamespace(QName qCapability) { + + String namespace = qCapability.getNamespace().toString(); + + return isSupportingNamespaceAndRevision(namespace, null); + + } + + /** + * check if the namespace and its revision are supported by the given capabilities + * + * @param qCapability capability from the model + * @return true if supporting the model AND revision<br> + * false if revision not available or both not found. + */ + public boolean isSupportingNamespaceAndRevision(QName qCapability) { + + String namespace = qCapability.getNamespace().toString(); + String revision = getRevisionString(qCapability); + return revision == null ? false : isSupportingNamespaceAndRevision(namespace, revision); + } + + /** + * + * @param namespace requested + * @param revision request or null for any revision + * @return true if existing + */ + private boolean isSupportingNamespaceAndRevision(String namespace, @Nullable String revision) { + LOG.trace("isSupportingNamespaceAndRevision: Model namespace {}?[revision {}]", namespace, revision); + for (String capability : capabilities) { + if (capability.contains(namespace) && (revision == null || capability.contains(revision))) { + LOG.trace("Verify true with: {}", capability); + return true; + } else { + LOG.trace("Verify false with: {}", capability); + } + } + return false; + } + + /** + * Provide revision as String from QName, considering older formats. + * @param qCapability that specifies the revision + * @return String with revisiondate or null + */ + private String getRevisionString(QName qCapability) { + Object revisionObject = qCapability.getRevision(); + String revision = null; + if (revisionObject instanceof Optional) { + if (((Optional<?>) revisionObject).isPresent()) { + revisionObject = ((Optional<?>) revisionObject).get(); + LOG.info("Unwrapp Optional: {}", revisionObject != null ? revisionObject.getClass() : null); + } + } + if (revisionObject == null) { + // Cover null case + } else if (revisionObject instanceof String) { + revision = (String) revisionObject; + } else if (revisionObject instanceof Date) { + revision = formatter.format((Date) revisionObject); + } else { + revision = revisionObject.toString(); + LOG.debug("Revision number type not supported. Use toString().String:{} Class:{} ", revisionObject, + revisionObject.getClass().getName()); + } + return revision; + } + + /** + * Get revision of first entry of related capability + * @param qCapability that specifies the namespace + * @return String with date or + */ + public String getRevisionForNamespace(QName qCapability) { + String namespace = qCapability.getNamespace().toString(); + for (String capability : capabilities) { + if (capability.contains(namespace)) { + return QName.create(capability).getRevision().get().toString(); + } + } + return "Unsupported"; + } + + + @Override + public String toString() { + return "Capabilities [capabilities=" + capabilities + "]"; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/INetconfAcessor.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/INetconfAcessor.java new file mode 100644 index 000000000..a186b3c6e --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/INetconfAcessor.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * ============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.netconfnodestateservice; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.NotificationListener; + +/** + * Interface handling netconf connection. + */ +public interface INetconfAcessor { + + /** + * @return the nodeId + */ + NodeId getNodeId(); + + /** + * @return NetconfNode of this connection + */ + NetconfNode getNetconfNode(); + + /** + * @return Capabilites + */ + Capabilities getCapabilites(); + + /** + * @return the dataBroker + */ + DataBroker getDataBroker(); + + /** + * @return the MDSAL Mountpoint service + **/ + MountPoint getMountpoint(); + + /** + * @Return TransAction + */ + TransactionUtils getTransactionUtils(); + + + /** + * Register netconf notification listener for related mountpoint + * + * @param <T> specific child class of NotificationListener + * @param listener listener to be called + * @return handler to manager registration + */ + <T extends NotificationListener> ListenerRegistration<NotificationListener> doRegisterNotificationListener( + @NonNull T listener); + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfAccessor.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfAccessor.java new file mode 100644 index 000000000..c80c7befc --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfAccessor.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.netconfnodestateservice; + +import java.util.Optional; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.NotificationService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.NotificationListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetconfAccessor implements INetconfAcessor { + + private static final Logger log = LoggerFactory.getLogger(NetconfAccessor.class); + + private final NodeId nodeId; + private final DataBroker dataBroker; + private final TransactionUtils transactionUtils; + private final MountPoint mountpoint; + private final NetconfNode netconfNode; + private final Capabilities capabilities; + + /** + * @param nodeId of managed netconf node + * @param dataBroker to access node + */ + public NetconfAccessor(NodeId nodeId, NetconfNode netconfNode, DataBroker dataBroker, MountPoint mountpoint, + TransactionUtils transactionUtils) { + super(); + this.nodeId = nodeId; + this.netconfNode = netconfNode; + this.dataBroker = dataBroker; + this.mountpoint = mountpoint; + this.transactionUtils = transactionUtils; + + ConnectionStatus csts = netconfNode != null ? netconfNode.getConnectionStatus() : null; + this.capabilities = Capabilities.getAvailableCapabilities(csts != null ? netconfNode : null); + } + + /** + * @param nodeId with uuid of managed netconf node + * @param dataBroker to access node + */ + public NetconfAccessor(String nodeId, NetconfNode netconfNode, DataBroker dataBroker, MountPoint mountpoint, + TransactionUtils transactionUtils) { + this(new NodeId(nodeId), netconfNode, dataBroker, mountpoint, transactionUtils); + } + + @Override + public NodeId getNodeId() { + return nodeId; + } + + @Override + public DataBroker getDataBroker() { + return dataBroker; + } + @Override + public MountPoint getMountpoint() { + return mountpoint; + } + @Override + public TransactionUtils getTransactionUtils() { + return transactionUtils; + } + @Override + public NetconfNode getNetconfNode() { + return netconfNode; + } + @Override + public Capabilities getCapabilites() { + return capabilities; + } + + @Override + public @NonNull <T extends NotificationListener> ListenerRegistration<NotificationListener> doRegisterNotificationListener(@NonNull T listener) { + log.info("Begin register listener for Mountpoint {}", mountpoint.getIdentifier().toString()); + final Optional<NotificationService> optionalNotificationService = mountpoint + .getService(NotificationService.class); + final NotificationService notificationService = optionalNotificationService.get(); + final ListenerRegistration<NotificationListener> ranListenerRegistration = notificationService + .registerNotificationListener(listener); + log.info("End registration listener for Mountpoint {} Listener: {} Result: {}", + mountpoint.getIdentifier().toString(), optionalNotificationService, ranListenerRegistration); + return ranListenerRegistration; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeConnectListener.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeConnectListener.java new file mode 100644 index 000000000..942e29f19 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeConnectListener.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * ============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.netconfnodestateservice; + +import java.util.EventListener; + +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; + +/** + * Indicate if device is connected or not. + * A NetconfNode (Mountpoint) is providing the status. + * If this is Master and connected, this function is calles. + */ + +public interface NetconfNodeConnectListener extends EventListener, AutoCloseable { + + /** + * Called if device state changes to "connected" for a netconf master node. + * @param nNodeId name of mount point + * @param netconfNode with related information + * @param netconfNodeDataBroker to access connected netconf device + */ + public void onEnterConnected(NodeId nNodeId, NetconfNode netconfNode, DataBroker netconfNodeDataBroker); + + /** + * Notify of device state change to "not connected" mount point supervision. + * HINT: This callback could be called multiple times also the onEnterConnected state was not called. + * @param nNodeId name of mount point + */ + public void onLeaveConnected(NodeId nNodeId); + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateListener.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateListener.java new file mode 100644 index 000000000..253af0598 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateListener.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * ============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.netconfnodestateservice; + +import java.util.EventListener; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; + +/** + * Indicate all state changes of NetconfNode (Mountpoint). Cleans up and + * summarizes the + */ +public interface NetconfNodeStateListener extends EventListener { + + /** + * New NetconfNode has been created + * @param nNodeId of Node + * @param netconfNode object + */ + + void onCreated(NodeId nNodeId, NetconfNode netconfNode); + + /** + * New NetconfNode has been created + * @param nNodeId of node + * @param netconfNode object after change + */ + void onStateChange(NodeId nNodeId, NetconfNode netconfNode); + + /** + * NetconfNode has been removed + * @param nNodeId of related node + */ + void onRemoved(NodeId nNodeId); + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateService.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateService.java new file mode 100644 index 000000000..0105c36e8 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/NetconfNodeStateService.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.netconfnodestateservice; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.Registration; + +public interface NetconfNodeStateService extends Registration { + + /** + * Register for indication that Master NetconNode is entering or leaving Connected state. + * @param netconfNodeConnectListener + * @return managing object for listener + */ + @NonNull <L extends NetconfNodeConnectListener> ListenerRegistration<L> registerNetconfNodeConnectListener(@NonNull L netconfNodeConnectListener); + + /** + * Register for all NetconfNode specific state changes + * @param netconfNodeStateListener + * @return managing object for listener + */ + @NonNull <L extends NetconfNodeStateListener> ListenerRegistration<L> registerNetconfNodeStateListener(@NonNull L netconfNodeStateListener); + + /** + * Register for Ves/DmaaP provided messages + * @param netconfNodeStateListener + * @return managing object for listener + */ + @NonNull <L extends VesNotificationListener> ListenerRegistration<L> registerVesNotifications(@NonNull L netconfNodeStateListener); + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/TransactionUtils.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/TransactionUtils.java new file mode 100644 index 000000000..da8da5c7f --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/TransactionUtils.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * ============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.netconfnodestateservice; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * @author herbert + * + */ +public interface TransactionUtils { + + /** + * Deliver the data back or null. Warning + * + * @param <T> SubType of the DataObject to be handled + * @param dataBroker for accessing data + * @param dataStoreType to address datastore + * @param iid id to access data + * @return null or object + */ + @Nullable + <T extends DataObject> T readData(DataBroker dataBroker, LogicalDatastoreType dataStoreType, + InstanceIdentifier<T> iid); + + /** + * Deliver the data back or null + * + * @param <T> SubType of the DataObject to be handled + * @param dataBroker for accessing data + * @param dataStoreType to address datastore + * @param iid id to access data + * @param noErrorIndication (Output) true if data could be read and are available and is not null + * @param statusIndicator (Output) String with status indications during the read. + * @return null or object + */ + @Nullable + <T extends DataObject> T readDataOptionalWithStatus(DataBroker dataBroker, LogicalDatastoreType dataStoreType, + InstanceIdentifier<T> iid, AtomicBoolean noErrorIndication, AtomicReference<String> statusIndicator); + +}
\ No newline at end of file diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/VesNotificationListener.java b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/VesNotificationListener.java new file mode 100644 index 000000000..e7d2481b8 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/VesNotificationListener.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.netconfnodestateservice; + +import java.util.EventListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotification; + +/** + * Indicate if device is connected or not. + * A NetconfNode (Mountpoint) is providing the status. + * If this is Master and connected, this function is calles. + */ + +public interface VesNotificationListener extends EventListener, AutoCloseable { + + /** + * Called in case of fault notification + * @param faultNotification to handle + */ + public void onNotification(FaultNotification faultNotification); + + /** + * Called in case of attributeChange notification + * @param attributeChangeNotification to handle + */ + public void onNotification(AttributeChangeNotification attributeChangeNotification); + +} diff --git a/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang b/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang new file mode 100644 index 000000000..737f858de --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/model/src/main/yang/netconfnodestateservice.yang @@ -0,0 +1,64 @@ +module netconfnode-state { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:netconfnode-state"; + prefix "netconfnode-state"; + + import data-provider { prefix "data-provider"; } + + description + "sdnr-wt-netconfnode-state-service Api Module"; + + revision "2019-10-11" { + description + "Initial revision"; + } + + container fault-notification { + description + "Handle fault problem notification of a network-element"; + uses data-provider:object-change-reference; + uses data-provider:fault; + } + container attribute-change-notification { + description + "Handle attribute change notification of a network-element"; + uses data-provider:object-change-reference; + uses data-provider:attribute-change; + } + rpc push-fault-notification { + description + "Forward fault problem notification of a network-element"; + input { + uses data-provider:object-change-reference; + uses data-provider:fault; + } + } + rpc push-attribute-change-notification { + description + "Forward attribute change notification of a network-element"; + input { + uses data-provider:object-change-reference; + uses data-provider:attribute-change; + } + } + + rpc get-status { + description + "Returns status information"; + + output { + list status { + description "Provides a key value list with status information"; + key key; + leaf key { + type string; + } + leaf value { + type string; + } + } + } + } +} + diff --git a/sdnr/wt/netconfnode-state-service/pom.xml b/sdnr/wt/netconfnode-state-service/pom.xml new file mode 100755 index 000000000..07dfcc7bf --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/pom.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + * ============LICENSE_START======================================================= + * ONAP : CCSDK.sdnr.wt.netconfnode-state-service + * ================================================================================ + * Copyright (C) 2018 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========================================================= + +--> +<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> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-top</artifactId> + <version>0.7.0-SNAPSHOT</version> + <packaging>pom</packaging> + <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>odlparent-lite</artifactId> + <version>1.5.1-SNAPSHOT</version> + <relativePath/> + </parent> + + <properties> + <feature-name>sdnr-wt-netconfnode-state-service</feature-name> + </properties> + + <modules> + <module>model</module> + <module>provider</module> + <module>feature</module> + <module>installer</module> + </modules> + +</project> diff --git a/sdnr/wt/netconfnode-state-service/provider/copyright b/sdnr/wt/netconfnode-state-service/provider/copyright new file mode 100644 index 000000000..754b6218f --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/copyright @@ -0,0 +1,17 @@ +/** + * ============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========================================================================== + */ diff --git a/sdnr/wt/netconfnode-state-service/provider/pom.xml b/sdnr/wt/netconfnode-state-service/provider/pom.xml new file mode 100644 index 000000000..ed0dad795 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/pom.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : CCSDK / SDNR / WT / netconfnode-state-service + ================================================================================ + 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========================================================= +--> +<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> + + <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-provider</artifactId> + <version>0.7.0-SNAPSHOT</version> + <name>ccsdk-features-sdnr-wt :: ${project.artifactId}</name> + <packaging>bundle</packaging> + + <parent> + <groupId>org.onap.ccsdk.parent</groupId> + <artifactId>binding-parent</artifactId> + <version>1.5.1-SNAPSHOT</version> + <relativePath/> + </parent> + + <properties> + <checkstyle.skip>true</checkstyle.skip> <!-- POM configuration --> + <maven.javadoc.skip>true</maven.javadoc.skip> + <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format> + <buildtime>${maven.build.timestamp} UTC</buildtime> + </properties> + + <licenses> + <license> + <name>Apache License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + </license> + </licenses> + + <dependencies> + <dependency> + <groupId>org.opendaylight.netconf</groupId> + <artifactId>sal-netconf-connector</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>mdsal-singleton-common-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.typesafe.akka</groupId> + <artifactId>akka-actor_2.12</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.typesafe.akka</groupId> + <artifactId>akka-cluster_2.12</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-common</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>sdnr-wt-netconfnode-state-service-model</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + </resource> + </resources> + </build> +</project> + diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java new file mode 100644 index 000000000..0af35e569 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/NetconfNodeStateServiceImpl.java @@ -0,0 +1,586 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl; + +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.annotation.Nullable; + +import org.eclipse.jdt.annotation.NonNull; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeConnectListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateService; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.AkkaConfig; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.GeoConfig; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.NetconfnodeStateServiceRpcApiImpl; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.RpcApigetStateCallback; +import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataObjectModification; +import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType; +import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.MountPointService; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.ClusteredConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetconfNodeStateServiceImpl implements NetconfNodeStateService, RpcApigetStateCallback, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(NetconfNodeStateServiceImpl.class); + private static final String APPLICATION_NAME = "NetconfNodeStateService"; + @SuppressWarnings("unused") + private static final String CONFIGURATIONFILE = "etc/netconfnode-status-service.properties"; + + + private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, + new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + + private static final InstanceIdentifier<Node> NETCONF_NODE_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))) + .child(Node.class); + + private static final DataTreeIdentifier<Node> NETCONF_NODE_TOPO_TREE_ID = + DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID); + + // Name of ODL controller NETCONF instance + private static final NodeId CONTROLLER = new NodeId("controller-config"); + + // -- OSGi services, provided + private DataBroker dataBroker; + private MountPointService mountPointService; + private RpcProviderService rpcProviderRegistry; + @SuppressWarnings("unused") + private NotificationPublishService notificationPublishService; + @SuppressWarnings("unused") + private ClusterSingletonServiceProvider clusterSingletonServiceProvider; + + // -- Parameter + private ListenerRegistration<L1> listenerL1; + private ListenerRegistration<L2> listenerL2; + @SuppressWarnings("unused") + private ClusterSingletonServiceRegistration cssRegistration; + + private NetconfnodeStateServiceRpcApiImpl rpcApiService; + + /** Indication if init() function called and fully executed **/ + private Boolean initializationSuccessful; + + /** List of all registered listeners **/ + private final List<NetconfNodeConnectListener> netconfNodeConnectListenerList; + + /** List of all registered listeners **/ + private final List<NetconfNodeStateListener> netconfNodeStateListenerList; + + /** List of all registered listeners **/ + private final List<VesNotificationListener> vesNotificationListenerList; + + /** Indicates if running in cluster configuration **/ + private boolean isCluster; + + /** Indicates the name of the cluster **/ + private String clusterName; + + /** Blueprint **/ + public NetconfNodeStateServiceImpl() { + LOG.info("Creating provider for {}", APPLICATION_NAME); + + this.dataBroker = null; + this.mountPointService = null; + this.rpcProviderRegistry = null; + this.notificationPublishService = null; + this.clusterSingletonServiceProvider = null; + + this.listenerL1 = null; + this.listenerL2 = null; + this.initializationSuccessful= false; + this.netconfNodeConnectListenerList = new CopyOnWriteArrayList<>(); + this.netconfNodeStateListenerList = new CopyOnWriteArrayList<>(); + this.vesNotificationListenerList = new CopyOnWriteArrayList<>(); + } + + public void setDataBroker(DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + public void setRpcProviderRegistry(RpcProviderService rpcProviderRegistry) { + this.rpcProviderRegistry = rpcProviderRegistry; + } + + public void setNotificationPublishService(NotificationPublishService notificationPublishService) { + this.notificationPublishService = notificationPublishService; + } + + public void setMountPointService(MountPointService mountPointService) { + this.mountPointService = mountPointService; + } + public void setClusterSingletonService(ClusterSingletonServiceProvider clusterSingletonService) { + this.clusterSingletonServiceProvider = clusterSingletonService; + } + + /** Blueprint initialization **/ + public void init() { + + LOG.info("Session Initiated start {}", APPLICATION_NAME); + + // Start RPC Service + this.rpcApiService = new NetconfnodeStateServiceRpcApiImpl(rpcProviderRegistry, vesNotificationListenerList); + + // Get configuration + // ConfigurationFileRepresentation config = new ConfigurationFileRepresentation(CONFIGURATIONFILE); + // Akka setup + AkkaConfig akkaConfig = getAkkaConfig(); + this.isCluster = akkaConfig == null ? false : akkaConfig.isCluster(); + this.clusterName = akkaConfig == null ? "" : akkaConfig.getClusterConfig().getClusterSeedNodeName("abc"); + + // RPC Service for specific services + this.rpcApiService.setStatusCallback(this); + + LOG.debug("start NetconfSubscriptionManager Service"); + //this.netconfChangeListener = new NetconfChangeListener(this, dataBroker); + //this.netconfChangeListener.register(); + //DataTreeIdentifier<Node> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, NETCONF_NODE_TOPO_IID); + + listenerL1 = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new L1()); + listenerL2 = dataBroker.registerDataTreeChangeListener(NETCONF_NODE_TOPO_TREE_ID, new L2()); + + this.initializationSuccessful = true; + + LOG.info("Session Initiated end. Initialization done {}", initializationSuccessful); + + } + /** Blueprint destroy-method method */ + public void destroy() { + close(); + } + + /** + * Getter + * @return NetconfnodeStateServiceRpcApiImpl + */ + public NetconfnodeStateServiceRpcApiImpl getNetconfnodeStateServiceRpcApiImpl() { + return rpcApiService; + } + + @Override + public GetStatusOutputBuilder getStatus(GetStatusInput input) { + return new GetStatusOutputBuilder(); + } + + @Override + public <L extends NetconfNodeConnectListener> @NonNull ListenerRegistration<L> registerNetconfNodeConnectListener( + final @NonNull L netconfNodeConnectListener) { + LOG.info("Register connect listener {}",netconfNodeConnectListener.getClass().getName()); + netconfNodeConnectListenerList.add(netconfNodeConnectListener); + + return new ListenerRegistration<L>() { + @Override + public @NonNull L getInstance() { + return netconfNodeConnectListener; + } + + @Override + public void close() { + LOG.info("Remove connect listener {}",netconfNodeConnectListener); + netconfNodeConnectListenerList.remove(netconfNodeConnectListener); + } + }; + } + + @Override + public <L extends NetconfNodeStateListener> @NonNull ListenerRegistration<L> registerNetconfNodeStateListener( + @NonNull L netconfNodeStateListener) { + LOG.info("Register state listener {}",netconfNodeStateListener.getClass().getName()); + netconfNodeStateListenerList.add(netconfNodeStateListener); + + return new ListenerRegistration<L>() { + @Override + public @NonNull L getInstance() { + return netconfNodeStateListener; + } + + @Override + public void close() { + LOG.info("Remove state listener {}",netconfNodeStateListener); + netconfNodeStateListenerList.remove(netconfNodeStateListener); + } + }; + } + + @Override + public <L extends VesNotificationListener> @NonNull ListenerRegistration<L> registerVesNotifications( + @NonNull L vesNotificationListener) { + LOG.info("Register Ves notification listener {}",vesNotificationListener.getClass().getName()); + vesNotificationListenerList.add(vesNotificationListener); + + return new ListenerRegistration<L>() { + @Override + public @NonNull L getInstance() { + return vesNotificationListener; + } + + @Override + public void close() { + LOG.info("Remove Ves notification listener {}",vesNotificationListener); + vesNotificationListenerList.remove(vesNotificationListener); + } + }; + } + + @Override + public void close() { + LOG.info("Closing start ..."); + try { + close(rpcApiService, listenerL1, listenerL2); + } catch (Exception e) { + LOG.debug("Closing", e); + } + LOG.info("Closing done"); + } + + /** + * Used to close all Services, that should support AutoCloseable Pattern + * + * @param toClose + * @throws Exception + */ + private void close(AutoCloseable... toCloseList) throws Exception { + for (AutoCloseable element : toCloseList) { + if (element != null) { + element.close(); + } + } + } + + /** + * Indication if init() of this bundle successfully done. + * @return true if init() was successful. False if not done or not successful. + */ + public boolean isInitializationSuccessful() { + return this.initializationSuccessful; + } + + /*------------------------------------------------------------------------------------------- + * Functions for interface DeviceManagerService + */ + + /** + * For each mounted device a mountpoint is created and this listener is called. + * Mountpoint was created or existing. Managed device is now fully connected to node/mountpoint. + * @param nNodeId id of the mountpoint + * @param netconfNode mountpoint contents + */ + private void enterConnectedState(NodeId nNodeId, NetconfNode netconfNode) { + + String mountPointNodeName = nNodeId.getValue(); + LOG.info("Starting Event listener on Netconf for mountpoint {}", mountPointNodeName); + + boolean preConditionMissing = false; + if (mountPointService == null) { + preConditionMissing = true; + LOG.warn("No mountservice available."); + } + if (!initializationSuccessful) { + preConditionMissing = true; + LOG.warn("Devicemanager initialization still pending."); + } + if (preConditionMissing) { + return; + } + + if (isNetconfNodeMaster(netconfNode)) { + + InstanceIdentifier<Node> instanceIdentifier = NETCONF_TOPO_IID.child(Node.class, + new NodeKey(new NodeId(mountPointNodeName))); + + Optional<MountPoint> optionalMountPoint = null; + int timeout = 10000; + while (!(optionalMountPoint = mountPointService.getMountPoint(instanceIdentifier)).isPresent() + && timeout > 0) { + LOG.info("Event listener waiting for mount point for Netconf device :: Name : {}", mountPointNodeName); + sleepMs(1000); + timeout -= 1000; + } + + if (!optionalMountPoint.isPresent()) { + LOG.warn("Event listener timeout while waiting for mount point for Netconf device :: Name : {} ", + mountPointNodeName); + } else { + // Mountpoint is present for sure + MountPoint mountPoint = optionalMountPoint.get(); + // BindingDOMDataBrokerAdapter.BUILDER_FACTORY; + LOG.info("Mountpoint with id: {}", mountPoint.getIdentifier()); + + Optional<DataBroker> optionalNetconfNodeDatabroker = mountPoint.getService(DataBroker.class); + + if (!optionalNetconfNodeDatabroker.isPresent()) { + LOG.info("Slave mountpoint {} without databroker", mountPointNodeName); + } else { + LOG.info("Master mountpoint {}", mountPointNodeName); + DataBroker netconfNodeDataBroker = optionalNetconfNodeDatabroker.get(); + + /* + * --> Call Listers for onConnect() Indication + for (all) + */ + netconfNodeConnectListenerList.forEach(item -> { + try { + item.onEnterConnected(nNodeId, netconfNode, netconfNodeDataBroker); + } catch (Exception e) { + LOG.info("Exception during onEnterConnected listener call", e); + } + }); + + LOG.info("Connect indication forwarded for {}", mountPointNodeName); + } + } + } + } + + /** + * Leave the connected status to a non connected or removed status + * @param action that occurred + * @param nNodeId id of the mountpoint + * @param nNode mountpoint contents + */ + private void leaveConnectedState(NodeId nNodeId) { + LOG.info("netconfNode id {}", nNodeId); + netconfNodeConnectListenerList.forEach(item -> { + try { + if (item != null) { + item.onLeaveConnected(nNodeId); + } else { + LOG.warn("Unexpeced null item during onleave"); + } + } catch (Exception e) { + LOG.info("Exception during onLeaveConnected listener call", e); + } + }); + } + + // ---- subclasses for listeners + + /** + * Clustered listener function to select the right node from + * DataObjectModification + */ + private class L1 implements ClusteredDataTreeChangeListener<Node> { + @Override + public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) { + LOG.info("L1 TreeChange, changes:{}", changes.size()); + + for (final DataTreeModification<Node> change : changes) { + + final DataObjectModification<Node> root = change.getRootNode(); + if (LOG.isTraceEnabled()) { + LOG.trace("Handle this modificationType:{} path:{} root:{}", root.getModificationType(), + change.getRootPath(), root); + } + + // Catch potential nullpointer exceptions .. + try { + ModificationType modificationTyp = root.getModificationType(); + Node node = modificationTyp == ModificationType.DELETE ? root.getDataBefore() + : root.getDataAfter(); + NodeId nodeId = node != null ? node.getNodeId() : null; + if (nodeId != null) { + if (nodeId.equals(CONTROLLER)) { + // Do not forward any controller related events to devicemanager + LOG.debug("Stop processing for [{}]", nodeId); + } else { + if (modificationTyp != null) { + switch (modificationTyp) { + case SUBTREE_MODIFIED: // Create or modify sub level node + case WRITE: // Create or modify top level node + // Treat an overwrite as an update + // leaveconnected state.before = connected; state.after != connected + // enterConnected state.after == connected + // => Here create or update by checking root.getDataBefore() != null + + boolean connectedBefore, connectedAfter; + NetconfNode nNodeAfter = getNetconfNode(root.getDataAfter()); + connectedAfter = isConnected(nNodeAfter); + if (root.getDataBefore() != null) { + // It is an update + NetconfNode nodeBefore = getNetconfNode(root.getDataBefore()); + connectedBefore = isConnected(nodeBefore); + } else { + // It is a create + connectedBefore = false; + } + + LOG.info( + "L1 NETCONF Node change with id {} ConnectedBefore {} connectedAfter {} cluster status {} akkaIsCluster", + nodeId, connectedBefore, connectedAfter, + getClusteredConnectionStatus(nNodeAfter), isCluster); + + if (!connectedBefore && connectedAfter) { + netconfNodeStateListenerList.forEach(item -> { + try { + item.onCreated(nodeId, nNodeAfter); + } catch (Exception e) { + LOG.info("Exception during onCreated listener call", e); + } + }); + enterConnectedState(nodeId, nNodeAfter); + } else { + LOG.debug("State change {} {}", connectedBefore, connectedAfter); + if (connectedBefore && !connectedAfter) { + leaveConnectedState(nodeId); + } + netconfNodeStateListenerList.forEach(item -> { + try { + item.onStateChange(nodeId, nNodeAfter); + } catch (Exception e) { + LOG.info("Exception during onStateChange listener call", e); + } + }); + } + // doProcessing(update ? Action.UPDATE : Action.CREATE, nodeId, root); + break; + case DELETE: + // Node removed + // leaveconnected state.before = connected; + leaveConnectedState(nodeId); + netconfNodeStateListenerList.forEach(item -> { + try { + item.onRemoved(nodeId); + } catch (Exception e) { + LOG.info("Exception during onRemoved listener call", e); + } + }); + // doProcessing(Action.REMOVE, nodeId, root); + break; + } + } + } + } + } catch (NullPointerException e) { + LOG.info("Data not available at ", e); + } + } + } + } + + private static @Nullable NetconfNode getNetconfNode(Node node) { + return node != null ? node.augmentation(NetconfNode.class) : null; + } + + private static boolean isConnected(NetconfNode nNode) { + return nNode != null ? ConnectionStatus.Connected.equals(nNode.getConnectionStatus()) : false; + } + + private static @Nullable ClusteredConnectionStatus getClusteredConnectionStatus(NetconfNode node) { + return node != null ? node.getClusteredConnectionStatus() : null; + } + /** + * Normal listener function to select the right node from DataObjectModification + */ + private class L2 implements DataTreeChangeListener<Node> { + + @Override + public void onDataTreeChanged(@NonNull Collection<DataTreeModification<Node>> changes) { + LOG.info("L2 TreeChange, changes:{}", changes.size()); + } + } + + /* -- LOG related functions -- */ + + /** Analyze configuration **/ + private static @Nullable AkkaConfig getAkkaConfig() { + AkkaConfig akkaConfig; + try { + akkaConfig = AkkaConfig.load(); + LOG.debug("akka.conf loaded: " + akkaConfig.toString()); + } catch (Exception e1) { + akkaConfig = null; + LOG.warn("problem loading akka.conf: " + e1.getMessage()); + } + if (akkaConfig != null && akkaConfig.isCluster()) { + LOG.info("cluster mode detected"); + if (GeoConfig.fileExists()) { + try { + LOG.debug("try to load geoconfig"); + GeoConfig.load(); + } catch (Exception err) { + LOG.warn("problem loading geoconfig: " + err.getMessage()); + } + } else { + LOG.debug("no geoconfig file found"); + } + } else { + LOG.info("single node mode detected"); + } + return akkaConfig; + } + + private boolean isNetconfNodeMaster(NetconfNode nNode) { + if (this.isCluster) { + LOG.debug("check if me is responsible for node"); + ClusteredConnectionStatus ccs = nNode.getClusteredConnectionStatus(); + @SuppressWarnings("null") + @NonNull String masterNodeName = ccs == null || ccs.getNetconfMasterNode() == null ? "null" : ccs.getNetconfMasterNode(); + LOG.debug("sdnMasterNode=" + masterNodeName + " and sdnMyNode=" + this.clusterName); + if (!masterNodeName.equals(this.clusterName)) { + LOG.debug("netconf change but me is not master for this node"); + return false; + } + } + return true; + } + + + private void sleepMs(int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) { + LOG.debug("Interrupted sleep"); + // Restore interrupted state... + Thread.currentThread().interrupt(); + } + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java new file mode 100644 index 000000000..d0ea0eb69 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/AkkaConfig.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.conf.odlAkka; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; + +public class AkkaConfig { + + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(AkkaConfig.class); + + private static final String DEFAULT_FILENAME = "configuration/initial/akka.conf"; + private final String filename; + private ClusterConfig cluserConfig; + + public ClusterConfig getClusterConfig() { + return this.cluserConfig; + } + + private AkkaConfig(String filename) { + this.filename = filename; + } + + public AkkaConfig() { + this(null); + } + + @Override + public String toString() { + return "AkkaConfig [filename=" + filename + ", cluserConfig=" + cluserConfig + "]"; + } + + private void loadFromFile() throws Exception { + Config cfg = ConfigFactory.parseFile(new File(this.filename)); + this.cluserConfig = new ClusterConfig(cfg.getConfig("odl-cluster-data").getConfig("akka").getConfig("cluster")); + } + + public boolean isCluster() { + return this.cluserConfig != null ? this.cluserConfig.isCluster() : false; + } + + public boolean isClusterAndFirstNode() { + return isSingleNode() || isCluster() && getClusterConfig().getRoleMemberIndex() == 1; + } + + public static AkkaConfig load() throws Exception { + return load(DEFAULT_FILENAME); + } + + public static AkkaConfig load(String filename) throws Exception { + AkkaConfig cfg = new AkkaConfig(filename); + cfg.loadFromFile(); + return cfg; + } + + public boolean isSingleNode() { + return !this.isCluster(); + } + public static AkkaConfig parse(String content) throws Exception { + Config cfg = ConfigFactory.parseString(content); + AkkaConfig c = new AkkaConfig(); + c.cluserConfig=new ClusterConfig(cfg.getConfig("odl-cluster-data").getConfig("akka").getConfig("cluster")); + return c; + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java new file mode 100644 index 000000000..bdde30828 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterConfig.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.conf.odlAkka; + +import java.util.ArrayList; +import java.util.List; + +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.ClusterRoleInfo; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.ClusterRoleInfoCollection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.typesafe.config.Config; + +public class ClusterConfig { + + private static final Logger LOG = LoggerFactory.getLogger(ClusterConfig.class); + + private final List<ClusterNodeInfo> seedNodes; + private final ClusterRoleInfoCollection roles; + private ClusterNodeInfo ismeInfo; + + public static ClusterConfig defaultSingleNodeConfig() + { + ClusterConfig cfg=new ClusterConfig(); + cfg.ismeInfo=ClusterNodeInfo.defaultSingleNodeInfo(); + cfg.seedNodes.add(cfg.ismeInfo); + cfg.roles.add(ClusterRoleInfo.defaultSingleNodeRole()); + return cfg; + } + public ClusterConfig() + { + this.seedNodes = new ArrayList<>(); + this.roles = new ClusterRoleInfoCollection(); + + } + public ClusterConfig(Config o) throws Exception { + { + this.seedNodes = new ArrayList<>(); + this.roles = new ClusterRoleInfoCollection(); + 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); + } + 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).getIndex() - 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; + } + + public String getHostName(String defaultValue) { + if (getRoleMemberIndex() > 0 && getRoleMemberIndex() <= seedNodes.size()) { + return this.seedNodes.get(getRoleMemberIndex()-1).getRemoteAddress(); + } else { + LOG.warn("Seednode not available for roleMemberIndex {}. Using default {}",getRoleMember(), defaultValue); + return defaultValue; + } + } + + public String getDBClusterName(String defaultValue) { + String r = null; + if (this.seedNodes != null && this.seedNodes.size() > 0) { + r = String.format("cluster-%s.%d", this.seedNodes.get(0).getRemoteAddress(), this.seedNodes.get(0).getPort()); + } + if (r == null || r.isEmpty()) { + r = defaultValue; + } + return r; + } + public String getClusterSeedNodeName() { + return this.getClusterSeedNodeName(""); + } + public String getClusterSeedNodeName(String defaultValue) { + int idx=this.getRoleMemberIndex()-1; + String r=null; + if(this.seedNodes!=null && idx>=0 && this.seedNodes.size()>0 && this.seedNodes.size()>idx) + { + r=this.seedNodes.get(idx).getSeedNodeName(); + } + if (r == null || r.isEmpty()) { + r = defaultValue; + } + return r; + } + public int getRoleMemberIndex() { + + ClusterRoleInfo role=this.roles.get("member"); + return role!=null?role.getIndex():0; + } + public ClusterRoleInfo getRoleMember() { + return this.roles.get("member"); + } + + @Override + public String toString() { + return "ClusterConfig [seedNodes=" + seedNodes + ", roles=" + roles + ", ismeInfo=" + ismeInfo + "]"; + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java new file mode 100644 index 000000000..ef161ad12 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlAkka/ClusterNodeInfo.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.conf.odlAkka; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClusterNodeInfo { + private final String protocol; + private final String clusterName; + private final String remoteAdr; + private final int port; + private final String seedNodeName; + + public static ClusterNodeInfo defaultSingleNodeInfo() { + return new ClusterNodeInfo("akka.tcp","opendaylight-cluster-data","127.0.0.1",2550); + } + + 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.seedNodeName = matcher.group(); + this.protocol = matcher.group(1); + this.clusterName = matcher.group(2); + this.remoteAdr = matcher.group(3); + this.port = Integer.parseInt(matcher.group(4)); + } + + public ClusterNodeInfo(String protocol, String clustername, String remoteadr, int port) { + this.protocol=protocol; + this.clusterName=clustername; + this.remoteAdr=remoteadr; + this.port=port; + this.seedNodeName=this.protocol+"://"+this.clusterName+"@"+this.remoteAdr+":"+this.port; + } + + public String getProtocol() { + return protocol; + } + + public String getClusterName() { + return clusterName; + } + + public String getRemoteAddress() { + return remoteAdr; + } + public String getSeedNodeName() { + return seedNodeName; + } + + public int getPort() { + return port; + } + + @Override + public String toString() { + return "ClusterNodeInfo [protocol=" + protocol + ", clusterName=" + clusterName + ", remoteAdr=" + remoteAdr + + ", port=" + port + ", seedNodeName=" + seedNodeName + "]"; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java new file mode 100644 index 000000000..994ef548b --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfo.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.conf.odlGeo; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClusterRoleInfo { + private final String Role; + private final int Index; + + public ClusterRoleInfo(String s) throws Exception { + final String regex = "([a-zA-Z]*)-([0-9]*)"; + final Pattern pattern = Pattern.compile(regex); + final Matcher matcher = pattern.matcher(s); + if (!matcher.find()) { + throw new Exception("unexpected role format:"+s); + } + this.Role = matcher.group(1); + this.Index = Integer.parseInt(matcher.group(2)); + } + + private ClusterRoleInfo(String role, int idx) { + this.Role=role; + this.Index=idx; + } + + public static ClusterRoleInfo defaultSingleNodeRole() { + return new ClusterRoleInfo("member",1); + } + + public String getRole() { + return Role; + } + public int getIndex() { + return Index; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Index; + result = prime * result + (Role == null ? 0 : Role.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ClusterRoleInfo other = (ClusterRoleInfo) obj; + if (Index != other.Index) { + return false; + } + if (Role == null) { + if (other.Role != null) { + return false; + } + } else if (!Role.equals(other.Role)) { + return false; + } + return true; + } + @Override + public String toString() { + return "ClusterRoleInfo [Role=" + Role + ", Index=" + Index + "]"; + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.java new file mode 100644 index 000000000..478ed8394 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/ClusterRoleInfoCollection.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.netconfnodestateservice.impl.conf.odlGeo; + +import java.util.ArrayList; + +public class ClusterRoleInfoCollection extends ArrayList<ClusterRoleInfo> { + private static final long serialVersionUID = 1L; + + public ClusterRoleInfo get(String role) { + for (ClusterRoleInfo info : this) { + if (info.getRole().equals(role)) { + return info; + } + } + return null; + } + + public boolean contains(ClusterRoleInfo info) { + if (info == null) { + return false; + } + for (ClusterRoleInfo i : this) { + if (i.equals(info)) { + return true; + } + } + return false; + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java new file mode 100644 index 000000000..c25f3264b --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/conf/odlGeo/GeoConfig.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.conf.odlGeo; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; + +public class GeoConfig { + + private static final String DEFAULT_FILENAME = "configuration/initial/geo.conf"; + private static final String LUMINA_ROOTNODENAME = "lumina-geo-cluster"; + private final String filename; + private final String rootNodename; + private ClusterRoleInfoCollection primaryRoles; + private ClusterRoleInfoCollection secondayRoles; + private RolesTable rolesTable; + + private GeoConfig() { + this(null); + } + + private GeoConfig(String filename) { + this(filename, LUMINA_ROOTNODENAME); + } + + private GeoConfig(String filename, String rootNodeName) { + this.filename = filename; + this.rootNodename = rootNodeName; + } + + public static boolean fileExists() { + File f = new File(DEFAULT_FILENAME); + return f.exists(); + } + + public static GeoConfig load() throws Exception { + return load(DEFAULT_FILENAME); + } + + public static GeoConfig load(String filename) throws Exception { + GeoConfig cfg = new GeoConfig(filename); + cfg._load(); + return cfg; + } + + private void _load() throws Exception { + this._load(ConfigFactory.parseFile(new File(this.filename))); + } + + private void _load(Config cfg) throws Exception { + this.primaryRoles = new ClusterRoleInfoCollection(); + List<String> a = cfg.getConfig(this.rootNodename).getStringList("primary_roles"); + + for (int i = 0; i < a.size(); i++) { + ClusterRoleInfo s = new ClusterRoleInfo(a.get(i)); + this.primaryRoles.add(s); + } + this.secondayRoles = new ClusterRoleInfoCollection(); + a = cfg.getConfig(this.rootNodename).getStringList("secondary_roles"); + for (int i = 0; i < a.size(); i++) { + ClusterRoleInfo s = new ClusterRoleInfo(a.get(i)); + this.secondayRoles.add(s); + } + this.checkDuplicateRoleEntries(); + this.rolesTable = new RolesTable(cfg.getConfig(this.rootNodename).getConfigList("ip_roles_table")); + } + + private void checkDuplicateRoleEntries() throws Exception { + ClusterRoleInfoCollection duplicateEntries = new ClusterRoleInfoCollection(); + for (ClusterRoleInfo primaryRole : this.primaryRoles) { + if (this.secondayRoles.contains(primaryRole)) { + duplicateEntries.add(primaryRole); + } + } + if (duplicateEntries.size() > 0) { + throw new Exception("duplicate entries found: " + duplicateEntries.toString()); + } + + } + + public static GeoConfig parse(String content) throws Exception { + GeoConfig cfg = new GeoConfig(); + cfg._load(ConfigFactory.parseString(content)); + return cfg; + } + + public ClusterRoleInfoCollection getPrimaryRoles() { + return this.primaryRoles; + } + + public ClusterRoleInfoCollection getSecondaryRoles() { + return this.secondayRoles; + } + + public boolean isPrimary(ClusterRoleInfo roleMember) { + return !this.isSecondary(roleMember); + } + + private boolean isSecondary(ClusterRoleInfo roleMember) { + if (roleMember == null) { + return false; + } + for (ClusterRoleInfo info : this.secondayRoles) { + if (info.equals(roleMember)) { + return true; + } + } + return false; + } + + @Override + public String toString() { + return "GeoConfig [filename=" + filename + ", rootNodename=" + rootNodename + ", primaryRoles=" + primaryRoles + + ", secondayRoles=" + secondayRoles + ", rolesTable=" + rolesTable + "]"; + } + + public static class RolesTableEntry { + private final ClusterRoleInfo role; + private final String ip; + + public RolesTableEntry(Config c) throws Exception { + this.role = new ClusterRoleInfo(c.getString("role")); + this.ip = c.getString("ip"); + } + + @Override + public String toString() { + return "RolesTableEntry [role=" + role + ", ip=" + ip + "]"; + } + } + public static class RolesTable extends ArrayList<RolesTableEntry> { + private static final long serialVersionUID = -9146218864237487506L; + + public RolesTable(List<? extends Config> configList) throws Exception { + for (Config c : configList) { + this.add(new RolesTableEntry(c)); + } + } + + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java new file mode 100644 index 000000000..9215887ff --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/NetconfnodeStateServiceRpcApiImpl.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.rpc; + +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotificationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotificationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.NetconfnodeStateService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.List; + +public class NetconfnodeStateServiceRpcApiImpl implements NetconfnodeStateService, AutoCloseable { + + private static final Logger LOG = LoggerFactory.getLogger(NetconfnodeStateServiceRpcApiImpl.class); + + private final ObjectRegistration<NetconfnodeStateServiceRpcApiImpl> rpcReg; + private RpcApigetStateCallback getStatusCallback; + private final List<VesNotificationListener> vesNotificationListenerList; + + public NetconfnodeStateServiceRpcApiImpl(final RpcProviderService rpcProviderRegistry, + List<VesNotificationListener> vesNotificationListenerList) { + + this.vesNotificationListenerList = vesNotificationListenerList; + + // Register ourselves as the REST API RPC implementation + LOG.info("Register RPC Service " + NetconfnodeStateService.class.getSimpleName()); + rpcReg = rpcProviderRegistry.registerRpcImplementation(NetconfnodeStateService.class, this); + this.getStatusCallback = null; + } + + public NetconfnodeStateServiceRpcApiImpl setStatusCallback(RpcApigetStateCallback getStatusCallback) { + this.getStatusCallback = getStatusCallback; + return this; + } + + @Override + public void close() throws Exception { + LOG.info("Close RPC Service"); + if (rpcReg != null) { + rpcReg.close(); + } + } + + /*------------------------------- + * Interfaces for getting information + */ + @Override + public ListenableFuture<RpcResult<GetStatusOutput>> getStatus(GetStatusInput input) { + + LOG.info("RPC Request: getStatus input: {}", input); + RpcResultBuilder<GetStatusOutput> result; + + try { + GetStatusOutputBuilder outputBuilder = new GetStatusOutputBuilder(); + getStatusCallback.getStatus(input); + result = RpcResultBuilder.success(outputBuilder); + } catch (Exception e) { + result = RpcResultBuilder.failed(); + result.withError(ErrorType.APPLICATION, "Exception", e); + } + return result.buildFuture(); + } + + @Override + public ListenableFuture<RpcResult<PushFaultNotificationOutput>> pushFaultNotification( + PushFaultNotificationInput input) { + + RpcResultBuilder<PushFaultNotificationOutput> result; + try { + FaultNotificationBuilder faultNotificationBuilder = new FaultNotificationBuilder(); + faultNotificationBuilder.fieldsFrom(input); + vesNotificationListenerList.forEach(item -> item.onNotification(faultNotificationBuilder.build())); + result = RpcResultBuilder.success(); + } catch (Exception e) { + result = RpcResultBuilder.failed(); + result.withError(ErrorType.APPLICATION, "Exception", e); + } + return result.buildFuture(); + } + + @Override + public ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> pushAttributeChangeNotification( + PushAttributeChangeNotificationInput input) { + RpcResultBuilder<PushAttributeChangeNotificationOutput> result; + try { + AttributeChangeNotificationBuilder attributeChangeNotificationBuilder = new AttributeChangeNotificationBuilder(); + attributeChangeNotificationBuilder.fieldsFrom(input); + vesNotificationListenerList.forEach(item -> item.onNotification(attributeChangeNotificationBuilder.build())); + result = RpcResultBuilder.success(); + } catch (Exception e) { + result = RpcResultBuilder.failed(); + result.withError(ErrorType.APPLICATION, "Exception", e); + } + return result.buildFuture(); + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java new file mode 100644 index 000000000..1434cf41a --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/impl/rpc/RpcApigetStateCallback.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.impl.rpc; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder; + +public interface RpcApigetStateCallback { + + GetStatusOutputBuilder getStatus(GetStatusInput input); +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml new file mode 100644 index 000000000..46930ac9e --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/org/opendaylight/blueprint/impl-blueprint.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +============LICENSE_START======================================================= +ONAP : ccsdk feature sdnr wt netconfnode-service-provider + ================================================================================ +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========================================================= + --> + +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" odl:use-default-for-reference-types="true"> + + <reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker" + odl:type="default" /> + + <reference id="notificationPublishService" + interface="org.opendaylight.mdsal.binding.api.NotificationPublishService" + odl:type="default" /> + + <reference id="mountPointService" + interface="org.opendaylight.mdsal.binding.api.MountPointService" + odl:type="default" /> + + <reference id="rpcProviderRegistry" + interface="org.opendaylight.mdsal.binding.api.RpcProviderService" + odl:type="default" /> + + <reference id="clusterSingletonService" + interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/> + + <bean id="netconfNodeStateService" class="org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.NetconfNodeStateServiceImpl" init-method="init" destroy-method="destroy" scope="singleton"> + <property name="dataBroker" ref="dataBroker"/> + <property name="rpcProviderRegistry" ref="rpcProviderRegistry" /> + <property name="notificationPublishService" ref="notificationPublishService" /> + <property name="mountPointService" ref="mountPointService" /> + <property name="clusterSingletonService" ref="clusterSingletonService" /> + </bean> + + <service id="registerNetconfNodeStateService" + interface="org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateService" + ref="netconfNodeStateService" /> + +</blueprint> diff --git a/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties new file mode 100644 index 000000000..80373399e --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/main/resources/version.properties @@ -0,0 +1,3 @@ +# Proberties filled in by maven during build process +version = ${project.version} +build = ${buildtime} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java new file mode 100644 index 000000000..dd317c781 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestAkkaConfig.java @@ -0,0 +1,147 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test; + +import static org.junit.Assert.fail; + +import java.io.File; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.AkkaConfig; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.ClusterConfig; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlAkka.ClusterNodeInfo; + +public class TestAkkaConfig { + + private static String getAkkaConfigSingleNodeText() { + return "\n" + "odl-cluster-data {\n" + " akka {\n" + " remote {\n" + " artery {\n" + + " enabled = off\n" + " canonical.hostname = \"127.0.0.1\"\n" + + " canonical.port = 2550\n" + " }\n" + " netty.tcp {\n" + + " hostname = \"127.0.0.1\"\n" + " port = 2550\n" + " }\n" + + " # when under load we might trip a false positive on the failure detector\n" + + " # transport-failure-detector {\n" + " # heartbeat-interval = 4 s\n" + + " # acceptable-heartbeat-pause = 16s\n" + " # }\n" + " }\n" + "\n" + " cluster {\n" + + " # Remove \".tcp\" when using artery.\n" + + " seed-nodes = [\"akka.tcp://opendaylight-cluster-data@127.0.0.1:2550\"]\n" + "\n" + + " roles = [\n" + " \"member-1\"\n" + " ]\n" + "\n" + " }\n" + "\n" + + " persistence {\n" + + " # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by\n" + + " # modifying the following two properties. The directory location specified may be a relative or absolute path. \n" + + " # The relative path is always relative to KARAF_HOME.\n" + "\n" + + " # snapshot-store.local.dir = \"target/snapshots\"\n" + + " # journal.leveldb.dir = \"target/journal\"\n" + "\n" + " journal {\n" + + " leveldb {\n" + " # Set native = off to use a Java-only implementation of leveldb.\n" + + " # Note that the Java-only version is not currently considered by Akka to be production quality.\n" + + "\n" + " # native = off\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; + } + + private static String getAkkaConfigClusterNodeText() { + return "\n" + "odl-cluster-data {\n" + "\n" + " akka {\n" + " loglevel = \"\"\n" + " remote {\n" + + " netty.tcp {\n" + " hostname = \"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + + " port = 2550\n" + " }\n" + " }\n" + " actor {\n" + " debug{\n" + + " autoreceive = on\n" + " lifecycle = on\n" + " unhandled = on\n" + + " fsm = on\n" + " event-stream = on\n" + " }\n" + " }\n" + " cluster {\n" + + " seed-nodes = [\"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc01.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc02.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23arbc03.2f0377.mtn23a.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com:2550\", \"akka.tcp://opendaylight-cluster-data@zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com:2550\"]\n" + + " seed-node-timeout = 15s\n" + " roles = [\"member-1\"]\n" + "\n" + " }\n" + + " persistence {\n" + " journal-plugin-fallback {\n" + " circuit-breaker {\n" + + " max-failures = 10\n" + " call-timeout = 60s\n" + + " reset-timeout = 30s\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}\n" + "\n" + + "odl-cluster-rpc {\n" + "\n" + " akka {\n" + " loglevel = \"\"\n" + " remote {\n" + + " netty.tcp {\n" + " hostname = \"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + + " port = 2551\n" + " }\n" + " }\n" + " actor {\n" + " debug{\n" + + " autoreceive = on\n" + " lifecycle = on\n" + " unhandled = on\n" + + " fsm = on\n" + " event-stream = on\n" + " }\n" + " }\n" + " cluster {\n" + + " seed-nodes = [\"akka.tcp://odl-cluster-rpc@zltcmtn23arbc01.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23arbc02.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23arbc03.2f0377.mtn23a.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com:2551\", \"akka.tcp://odl-cluster-rpc@zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com:2551\"]\n" + + " seed-node-timeout = 15s\n" + " }\n" + " persistence {\n" + + " journal-plugin-fallback {\n" + " circuit-breaker {\n" + " max-failures = 10\n" + + " call-timeout = 60s\n" + " reset-timeout = 30s\n" + " }\n" + " }\n" + + " }\n" + " }\n" + "}\n" + "\n" + ""; + } + + @Test + public void test1() { + AkkaConfig cfg; + try { + System.out.println("testing clusternode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.parse(getAkkaConfigClusterNodeText()); + System.out.println("succeeded: "); + System.out.println(cfg.toString()); + System.out.println(String.format("found %d cluster nodes", cfg.getClusterConfig().getSeedNodes().size())); + for (ClusterNodeInfo n : cfg.getClusterConfig().getSeedNodes()) { + System.out.println(n.toString()); + } + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test2() { + AkkaConfig cfg; + try { + System.out.println("testing singlenode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.parse(getAkkaConfigSingleNodeText()); + System.out.println("succeeded: "); + System.out.println(cfg.toString()); + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test3() { + AkkaConfig cfg; + + ClassLoader classLoader = getClass().getClassLoader(); + File file = new File(classLoader.getResource("captured-akka.conf").getFile()); + System.out.println(file.getAbsolutePath()); + + try { + System.out.println("testing clusternode config1"); + System.out.println("==========================="); + cfg = AkkaConfig.load(file.getAbsolutePath()); + System.out.println("succeeded: "+cfg.hashCode()); + System.out.println(cfg.toString()); + System.out.println(String.format("found %d cluster nodes", cfg.getClusterConfig().getSeedNodes().size())); + for (ClusterNodeInfo n : cfg.getClusterConfig().getSeedNodes()) { + System.out.println(n.toString()); + } + } catch (Exception e) { + String failMessage = "failed: " + e.getMessage(); + System.out.println(failMessage); + fail(failMessage); + } + } + + @Test + public void test4() { + ClusterConfig cc = ClusterConfig.defaultSingleNodeConfig(); + cc.getClusterSeedNodeName(); + cc.getRoleMemberIndex(); + cc.isCluster(); + cc.isMe(null); + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java new file mode 100644 index 000000000..915c88d50 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestGeoConfig.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test; + +import static org.junit.Assert.*; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.conf.odlGeo.GeoConfig; + +public class TestGeoConfig { + + @Test + public void test() { + GeoConfig config; + try { + System.out.println("testing clusternode geo config1"); + System.out.println("==========================="); + config = GeoConfig.parse(getClusterGeoConfigContent()); + System.out.println("succeeded: "); + System.out.println(config.toString()); + System.out.println("primary roles:"); + System.out.println(config.getPrimaryRoles().toString()); + System.out.println("secondary roles:"); + System.out.println(config.getSecondaryRoles().toString()); + + } catch (Exception e) { + fail("failed: " + e.getMessage()); + } + } + + + + private static String getClusterGeoConfigContent() { + return "\n" + "lumina-geo-cluster {\n" + " primary_roles = [\n" + + " \"member-1\",\"member-2\",\"member-3\"\n" + " ]\n" + " secondary_roles = [\n" + + " \"member-4\",\"member-5\",\"member-6\"\n" + " ]\n" + " ip_roles_table = [\n" + "\n" + + " {\n" + "role=\"member-1\"\n" + "ip=\"zltcmtn23arbc01.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + + "{\n" + "role=\"member-2\"\n" + "ip=\"zltcmtn23arbc02.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-3\"\n" + "ip=\"zltcmtn23arbc03.2f0377.mtn23a.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-4\"\n" + "ip=\"zltcmtn23brbc01.f84e7a.mtn23b.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-5\"\n" + "ip=\"zltcmtn23brbc02.f84e7a.mtn23b.tci.att.com\"\n" + "},\n" + "{\n" + + "role=\"member-6\"\n" + "ip=\"zltcmtn23brbc03.f84e7a.mtn23b.tci.att.com\"\n" + "}\n" + " \n" + + " ]\n" + "}\n" + "\n" + "\n" + "\n" + "\n" + ""; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java new file mode 100644 index 000000000..ff659ca3d --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/TestNetconfNodeStateService.java @@ -0,0 +1,316 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.common.util.concurrent.ListenableFuture; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.times; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.ExecutionException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeConnectListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.NetconfNodeStateListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.VesNotificationListener; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.NetconfNodeStateServiceImpl; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.impl.rpc.NetconfnodeStateServiceRpcApiImpl; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.ClusterSingletonServiceProviderMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.DataBrokerNetconfMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.MountPointServiceMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.NotificationPublishServiceMock; +import org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice.test.mock.RpcProviderRegistryMock; +import org.opendaylight.mdsal.binding.api.DataObjectModification; +import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType; +import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.MountPointService; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.AttributeChangeNotificationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.FaultNotificationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.GetStatusOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushAttributeChangeNotificationOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netconfnode.state.rev191011.PushFaultNotificationOutput; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class TestNetconfNodeStateService { + + private static Path KARAF_ETC = Paths.get("etc"); + private static NetconfNodeStateServiceImpl netconfStateService; + private static MountPointMock mountPoint; + private static DataBrokerNetconfMock dataBrokerNetconf; + + private static final Logger LOG = LoggerFactory.getLogger(TestNetconfNodeStateService.class); + + @BeforeClass + public static void before() throws InterruptedException, IOException { + + System.out.println("Logger: " + LOG.getClass().getName() + " " + LOG.getName()); + // Call System property to get the classpath value + Path etc = KARAF_ETC; + delete(etc); + + System.out.println("Create empty:" + etc.toString()); + Files.createDirectories(etc); + + // Create mocks + dataBrokerNetconf = new DataBrokerNetconfMock(); + dataBrokerNetconf.newReadWriteTransaction(); + mountPoint = new MountPointMock(); + ClusterSingletonServiceProvider clusterSingletonService = new ClusterSingletonServiceProviderMock(); + MountPointService mountPointService = new MountPointServiceMock(mountPoint); + NotificationPublishService notificationPublishService = new NotificationPublishServiceMock(); + RpcProviderService rpcProviderRegistry = new RpcProviderRegistryMock(); + + // start using blueprint interface + netconfStateService = new NetconfNodeStateServiceImpl(); + + netconfStateService.setDataBroker(dataBrokerNetconf); + netconfStateService.setMountPointService(mountPointService); + netconfStateService.setNotificationPublishService(notificationPublishService); + netconfStateService.setRpcProviderRegistry(rpcProviderRegistry); + netconfStateService.setClusterSingletonService(clusterSingletonService); + netconfStateService.init(); + System.out.println("Initialization done"); + } + + @AfterClass + public static void after() throws InterruptedException, IOException { + System.out.println("Start shutdown"); + // close using blueprint interface + netconfStateService.close(); + delete(KARAF_ETC); + + } + + @Test + public void test1() { + + System.out.println("Test1: Verify init state"); + assertTrue("Devicemanager not initialized", netconfStateService.isInitializationSuccessful()); + } + + + @Test + public void test2() { + + System.out.println("Test2: Register state listener"); + + NetconfNodeStateListener nSL = mock(NetconfNodeStateListener.class); + ListenerRegistration<NetconfNodeStateListener> res = + netconfStateService.registerNetconfNodeStateListener(nSL); + assertNotNull("Result should be null", res); + res.getInstance(); + res.close(); + } + + @Test + public void test3() { + + System.out.println("Test3: Register connect listener"); + + NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class); + ListenerRegistration<NetconfNodeConnectListener> res = + netconfStateService.registerNetconfNodeConnectListener(nCL); + assertNotNull("Result should be null", res); + res.getInstance(); + res.close(); + } + + @Test + public void test4() { + System.out.println("Test4: Get status listener"); + GetStatusInputBuilder inputBuilder = new GetStatusInputBuilder(); + GetStatusOutputBuilder res = netconfStateService.getStatus(inputBuilder.build()); + assertNotNull("Result should be null", res); + } + + @SuppressWarnings("unchecked") + @Test + public void test5OnConnect() { + System.out.println("Test5: On Connect"); + NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder(); + netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected); + NetconfNode rootNodeNetconf = netconfNodeBuilder.build(); + + NodeId nodeId = new NodeId("Test"); + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.addAugmentation(NetconfNode.class, rootNodeNetconf); + nodeBuilder.setNodeId(nodeId); + Node rootNode = nodeBuilder.build(); + + DataObjectModification<Node> dom = mock(DataObjectModification.class); + when(dom.getDataAfter()).thenReturn(rootNode); + when(dom.getModificationType()).thenReturn(ModificationType.WRITE); + + DataTreeModification<Node> ntn = mock(DataTreeModification.class); + when(ntn.getRootNode()).thenReturn(dom); + + NetconfNodeConnectListener nCL = mock(NetconfNodeConnectListener.class); + netconfStateService.registerNetconfNodeConnectListener(nCL); + mountPoint.setDatabrokerAbsent(false); + + Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn); + dataBrokerNetconf.sendClusteredChanges(changes); + dataBrokerNetconf.sendChanges(changes); + + //verify that it was called one time + verify(nCL,times(1)).onEnterConnected(nodeId, rootNodeNetconf, mountPoint.getDataBroker()); + + } + + @SuppressWarnings("unchecked") + @Test + public void test6Update() { + System.out.println("Test6: OnChange"); + NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder(); + netconfNodeBuilder.setConnectionStatus(ConnectionStatus.Connected); + NetconfNode rootNodeNetconf = netconfNodeBuilder.build(); + + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.addAugmentation(NetconfNode.class, rootNodeNetconf); + nodeBuilder.setNodeId(new NodeId("Test")); + Node rootNodeAfter = nodeBuilder.build(); + + DataObjectModification<Node> dom = mock(DataObjectModification.class); + when(dom.getDataBefore()).thenReturn(rootNodeAfter); + when(dom.getDataAfter()).thenReturn(rootNodeAfter); + when(dom.getModificationType()).thenReturn(ModificationType.WRITE); + + DataTreeModification<Node> ntn = mock(DataTreeModification.class); + when(ntn.getRootNode()).thenReturn(dom); + + Collection<DataTreeModification<Node>> changes = Arrays.asList(ntn); + dataBrokerNetconf.sendClusteredChanges(changes); + dataBrokerNetconf.sendChanges(changes); + } + + @Test + public void test7ApiStatus() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + GetStatusInputBuilder statusInput = new GetStatusInputBuilder(); + ListenableFuture<RpcResult<GetStatusOutput>> statusOutput = api.getStatus(statusInput.build()); + RpcResult<GetStatusOutput> res = statusOutput.get(); + GetStatusOutput output = res.getResult(); + System.out.println("Output "+output); + } + + + @Test + public void test8ApiPushFault() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + VesNotificationListener vNL = mock(VesNotificationListener.class); + ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL); + + FaultNotificationBuilder faultBuilder = new FaultNotificationBuilder(); + faultBuilder.setProblem("problem1"); + FaultNotification fault = faultBuilder.build(); + PushFaultNotificationInputBuilder statusInput = new PushFaultNotificationInputBuilder(); + statusInput.fieldsFrom(fault); + ListenableFuture<RpcResult<PushFaultNotificationOutput>> rpcOutput = api.pushFaultNotification(statusInput.build()); + RpcResult<PushFaultNotificationOutput> res = rpcOutput.get(); + PushFaultNotificationOutput output = res.getResult(); + + //verify that it was called one time + verify(vNL,times(1)).onNotification(fault); + + registration.close(); + System.out.println("Output "+output); + } + + @Test + public void test9ApiPushNotifiction() throws InterruptedException, ExecutionException { + + NetconfnodeStateServiceRpcApiImpl api = netconfStateService.getNetconfnodeStateServiceRpcApiImpl(); + + VesNotificationListener vNL = mock(VesNotificationListener.class); + ListenerRegistration<VesNotificationListener> registration = netconfStateService.registerVesNotifications(vNL); + + AttributeChangeNotificationBuilder changeBuilder = new AttributeChangeNotificationBuilder(); + changeBuilder.setAttributeName("attribute1"); + AttributeChangeNotification change = changeBuilder.build(); + PushAttributeChangeNotificationInputBuilder statusInput = new PushAttributeChangeNotificationInputBuilder(); + statusInput.fieldsFrom(change); + ListenableFuture<RpcResult<PushAttributeChangeNotificationOutput>> rpcOutput = api.pushAttributeChangeNotification(statusInput.build()); + RpcResult<PushAttributeChangeNotificationOutput> res = rpcOutput.get(); + PushAttributeChangeNotificationOutput output = res.getResult(); + + //verify that it was called one time + verify(vNL,times(1)).onNotification(change); + + registration.close(); + System.out.println("Output "+output); + } + + + // ------- private section + + private static void delete(Path etc) throws IOException { + if (Files.exists(etc)) { + System.out.println("Found and remove:" + etc.toString()); + delete(etc.toFile()); + } + } + + private static void delete(File f) throws IOException { + if (f.isDirectory()) { + for (File c : f.listFiles()) { + delete(c); + } + } + if (!f.delete()) { + throw new FileNotFoundException("Failed to delete file: " + f); + } + } + + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java new file mode 100644 index 000000000..86340c052 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/ClusterSingletonServiceProviderMock.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test.mock; + +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider; +import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration; + +public class ClusterSingletonServiceProviderMock implements ClusterSingletonServiceProvider { + + @Override + public void close() throws Exception { + + } + + @Override + public ClusterSingletonServiceRegistration registerClusterSingletonService(ClusterSingletonService service) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java new file mode 100644 index 000000000..48401c881 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerMountpointMock.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test.mock; + +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.api.BindingService; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.binding.api.ReadWriteTransaction; +import org.opendaylight.mdsal.binding.api.TransactionChain; +import org.opendaylight.mdsal.binding.api.TransactionChainListener; +import org.opendaylight.mdsal.binding.api.WriteTransaction; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; + +public class DataBrokerMountpointMock implements DataBroker, BindingService { + + ReadTransaction readTransaction; + + public void setReadOnlyTransaction(ReadTransaction readTransaction) { + this.readTransaction = readTransaction; + } + + @Override + public @NonNull ReadTransaction newReadOnlyTransaction() { + return null; + } + + @Override + public @NonNull ReadWriteTransaction newReadWriteTransaction() { + return null; + } + + @Override + public @NonNull WriteTransaction newWriteOnlyTransaction() { + return null; + } + + @Override + public <T extends DataObject, L extends DataTreeChangeListener<T>> @NonNull ListenerRegistration<L> registerDataTreeChangeListener( + @NonNull DataTreeIdentifier<T> treeId, @NonNull L listener) { + return null; + } + + @Override + public @NonNull TransactionChain createTransactionChain(@NonNull TransactionChainListener listener) { + return null; + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java new file mode 100644 index 000000000..90ab8608c --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/DataBrokerNetconfMock.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test.mock; + +import java.util.Collection; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataTreeChangeListener; +import org.opendaylight.mdsal.binding.api.DataTreeIdentifier; +import org.opendaylight.mdsal.binding.api.DataTreeModification; +import org.opendaylight.mdsal.binding.api.ReadTransaction; +import org.opendaylight.mdsal.binding.api.TransactionChain; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; + +public class DataBrokerNetconfMock implements DataBroker { + + private @NonNull DataTreeChangeListener<Node> listener; + private @NonNull ClusteredDataTreeChangeListener<Node> listenerClustered; + + @Override + public @NonNull ReadTransaction newReadOnlyTransaction() { + return null; + } + + @Override + public org.opendaylight.mdsal.binding.api.@NonNull ReadWriteTransaction newReadWriteTransaction() { + return null; + } + + @Override + public org.opendaylight.mdsal.binding.api.@NonNull WriteTransaction newWriteOnlyTransaction() { + return null; + } + + + @Override + public @NonNull TransactionChain createTransactionChain( + org.opendaylight.mdsal.binding.api.@NonNull TransactionChainListener listener) { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public <T extends DataObject, L extends DataTreeChangeListener<T>> @NonNull ListenerRegistration<L> registerDataTreeChangeListener( + @NonNull DataTreeIdentifier<T> treeId, @NonNull L pListener) { + System.out.println("Register "+pListener.getClass().getName()); + if (pListener instanceof ClusteredDataTreeChangeListener) { + System.out.println("Clustered listener"); + this.listenerClustered = (ClusteredDataTreeChangeListener<Node>) pListener; + } else if (pListener instanceof DataTreeChangeListener) { + System.out.println("Listener"); + this.listener = (DataTreeChangeListener<Node>) pListener; + } + return new ListenerRegistration<L>() { + + @Override + public @NonNull L getInstance() { + return pListener; + } + + @Override + public void close() { + } + + }; + } + + public void sendChanges(Collection<DataTreeModification<Node>> changes) { + this.listener.onDataTreeChanged(changes); + } + + public void sendClusteredChanges(Collection<DataTreeModification<Node>> changes) { + this.listenerClustered.onDataTreeChanged(changes); + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java new file mode 100644 index 000000000..e5bff451d --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointMock.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * ONAP : ccsdk feature sdnr wt sdnr-wt-devicemanager-provider + * ================================================================================ + * 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.netconfnodestateservice.test.mock; + +import java.util.Optional; +import org.opendaylight.mdsal.binding.api.BindingService; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.NotificationService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * @author herbert + * + */ +public class MountPointMock implements MountPoint { + + private boolean databrokerAbsent = true; + private final DataBrokerMountpointMock dataBroker = new DataBrokerMountpointMock(); + private final RpcConsumerRegistryMock rpcConsumerRegistry = new RpcConsumerRegistryMock(); + private NotificationService setReadTransaction; + + private static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = + InstanceIdentifier.create(NetworkTopology.class).child(Topology.class, + new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + + @Override + public InstanceIdentifier<?> getIdentifier() { + return NETCONF_TOPO_IID; + } + + @SuppressWarnings("unchecked") + @Override + public <T extends BindingService> Optional<T> getService(Class<T> service) { + + System.out.println("Requested mountpoint service: "+service.getSimpleName()+" databrokerAbsent state: "+databrokerAbsent); + + Optional<? extends BindingService> res; + if (service.isInstance(dataBroker)) { + System.out.println("Delivering databroker"); + res = databrokerAbsent ? Optional.empty() : Optional.of(dataBroker); + } else if (service.isInstance(rpcConsumerRegistry)) { + System.out.println("Delivering RpcConsumerRegistryMock"); + res = Optional.of(rpcConsumerRegistry); + } else if (service.isInstance(setReadTransaction)) { + System.out.println("Delivering notificationService"); + res = Optional.of(setReadTransaction); + } else { + System.out.println("Delivering no service"); + res = Optional.empty(); + } + return (Optional<T>) res; + } + + public void setDatabrokerAbsent( boolean state) { + this.databrokerAbsent = state; + } + + public DataBroker getDataBroker() { + return dataBroker; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java new file mode 100644 index 000000000..127019633 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/MountPointServiceMock.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test.mock; + +import java.util.Optional; +import org.opendaylight.mdsal.binding.api.MountPoint; +import org.opendaylight.mdsal.binding.api.MountPointService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * @author herbert + * + */ +public class MountPointServiceMock implements MountPointService { + + private final MountPointMock mountpoint; + + public MountPointServiceMock(MountPointMock mountpoint) { + this.mountpoint = mountpoint; + } + + @Override + public Optional<MountPoint> getMountPoint(InstanceIdentifier<?> mountPoint) { + + Optional<MountPoint> optional = Optional.of(mountpoint); + return optional; + } + + @Override + public <T extends MountPointListener> ListenerRegistration<T> registerListener(InstanceIdentifier<?> path, + T listener) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.java new file mode 100644 index 000000000..0564c56a3 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/NotificationPublishServiceMock.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.netconfnodestateservice.test.mock; + +import com.google.common.util.concurrent.ListenableFuture; +import java.util.concurrent.TimeUnit; +import org.opendaylight.mdsal.binding.api.NotificationPublishService; +import org.opendaylight.yangtools.yang.binding.Notification; + +public class NotificationPublishServiceMock implements NotificationPublishService { + + @Override + public ListenableFuture<?> offerNotification(Notification notification) { + return null; + } + + @Override + public ListenableFuture<?> offerNotification(Notification notification, int timeout, TimeUnit unit) + throws InterruptedException { + return null; + } + + @Override + public void putNotification(Notification notification) throws InterruptedException { + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java new file mode 100644 index 000000000..7e48ff2e5 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcConsumerRegistryMock.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * ============LICENSE_START======================================================= + * ONAP : ccsdk feature sdnr wt sdnr-wt-devicemanager-provider + * ================================================================================ + * 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.netconfnodestateservice.test.mock; + +import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class RpcConsumerRegistryMock implements RpcConsumerRegistry { + + @Override + public <T extends RpcService> T getRpcService(Class<T> serviceInterface) { + return null; + } + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java new file mode 100644 index 000000000..fbcb21db9 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/java/org/onap/ccsdk/features/sdnr/wt/netconfnodestateservice/test/mock/RpcProviderRegistryMock.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * ============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.netconfnodestateservice.test.mock; + +import java.util.Set; +import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.yangtools.concepts.ObjectRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.RpcService; + +public class RpcProviderRegistryMock implements RpcProviderService { + + @Override + public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type, + T implementation) { + return null; + } + + @Override + public <S extends RpcService, T extends S> ObjectRegistration<T> registerRpcImplementation(Class<S> type, + T implementation, Set<InstanceIdentifier<?>> paths) { + return null; + } + + +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf new file mode 100644 index 000000000..8489f0905 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/captured-akka.conf @@ -0,0 +1,72 @@ + +odl-cluster-data { + + akka { + loglevel = "" + remote { + netty.tcp { + hostname = "zltcdyh1arbc02.2f0377.dyh1a.tci.att.com" + port = 2550 + } + } + actor { + debug{ + autoreceive = on + lifecycle = on + unhandled = on + fsm = on + event-stream = on + } + } + cluster { + seed-nodes = ["akka.tcp://opendaylight-cluster-data@zltcdyh1arbc01.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1arbc02.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1arbc03.2f0377.dyh1a.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc01.f84e7a.dyh1b.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc02.f84e7a.dyh1b.tci.att.com:2550", "akka.tcp://opendaylight-cluster-data@zltcdyh1brbc03.f84e7a.dyh1b.tci.att.com:2550"] + seed-node-timeout = 15s + roles = ["member-2"] + + } + persistence { + journal-plugin-fallback { + circuit-breaker { + max-failures = 10 + call-timeout = 60s + reset-timeout = 30s + } + } + } + } +} + +odl-cluster-rpc { + + akka { + loglevel = "" + remote { + netty.tcp { + hostname = "zltcdyh1arbc02.2f0377.dyh1a.tci.att.com" + port = 2551 + } + } + actor { + debug{ + autoreceive = on + lifecycle = on + unhandled = on + fsm = on + event-stream = on + } + } + cluster { + seed-nodes = ["akka.tcp://odl-cluster-rpc@zltcdyh1arbc01.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1arbc02.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1arbc03.2f0377.dyh1a.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc01.f84e7a.dyh1b.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc02.f84e7a.dyh1b.tci.att.com:2551", "akka.tcp://odl-cluster-rpc@zltcdyh1brbc03.f84e7a.dyh1b.tci.att.com:2551"] + seed-node-timeout = 15s + } + persistence { + journal-plugin-fallback { + circuit-breaker { + max-failures = 10 + call-timeout = 60s + reset-timeout = 30s + } + } + } + } +} diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..2eb3eb7b3 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/simplelogger.properties @@ -0,0 +1,38 @@ +# 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=info + +# 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=info +org.slf4j.simpleLogger.log.org.onap.ccsdk.features.sdnr.wt.devicemanager.archiveservice=info +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=info + +# 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 diff --git a/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties new file mode 100644 index 000000000..de49c5893 --- /dev/null +++ b/sdnr/wt/netconfnode-state-service/provider/src/test/resources/test.properties @@ -0,0 +1,55 @@ +[dcae] +dcaeUserCredentials=admin:admin +dcaeUrl=off +dcaeHeartbeatPeriodSeconds=120 +dcaeTestCollector=no + +[aots] +userPassword=passwd +soapurladd=off +soapaddtimeout=10 +soapinqtimeout=20 +userName=user +inqtemplate=inqreq.tmpl.xml +assignedto=userid +addtemplate=addreq.tmpl.xml +severitypassthrough=critical,major,minor,warning +systemuser=user +prt-offset=1200 +soapurlinq=off +#smtpHost= +#smtpPort= +#smtpUsername= +#smtpPassword= +#smtpSender= +#smtpReceivers= + +[es] +esCluster=sendateodl5 +#time limit to keep increasing data in database [in seconds] +#60*60*24*30 (30days) +esArchiveLimit=2592000 +#folder where removed data will be stored +esArchiveFolder=./backup +#interval to archive database [in seconds] +#60*60*24 (1day) +esArchiveInterval=86400 + +[aai] +#keep comment +aaiHeaders=["X-TransactionId: 9999"] +aaiUrl=http://localhost:81 +aaiUserCredentials=AAI:AAI +aaiDeleteOnMountpointRemove=false +aaiTrustAllCerts=false +aaiApiVersion=aai/v13 +aaiPropertiesFile=aaiclient.properties +aaiApplicationId=SDNR +aaiPcks12ClientCertFile=/opt/logs/externals/data/stores/keystore.client.p12 +aaiPcks12ClientCertPassphrase=adminadmin +aaiClientConnectionTimeout=30000 + +[pm] +pmCluster=sendateodl5 +pmEnabled=true + diff --git a/sdnr/wt/pom.xml b/sdnr/wt/pom.xml index d8c3f41d4..317bf99a3 100644 --- a/sdnr/wt/pom.xml +++ b/sdnr/wt/pom.xml @@ -42,5 +42,6 @@ <module>websocketmanager2</module> <module>helpserver</module> <module>data-provider</module> + <module>netconfnode-state-service</module> </modules> </project> |