diff options
author | Skip Wonnell <kw5258@att.com> | 2017-08-15 20:42:44 -0500 |
---|---|---|
committer | Patrick Brady <pb071s@att.com> | 2017-08-17 22:21:40 -0700 |
commit | 1ec4bf9a21ebdc17c1aa99985afb12d5b6ea4651 (patch) | |
tree | e882152d89b70120214fc33e60ce9fe9374b2ee7 | |
parent | dbf27a48318ba76644d6e2b095358db60bf5c9b6 (diff) |
Initial commit for appc-config-adaptor
This bundle contains utilities used by config-generator.
Change-Id: I04877ebe90536fd57368d00c033189c280e77c90
Signed-off-by: Skip Wonnell <kw5258@att.com>
Issue-ID: APPC-67
26 files changed, 3809 insertions, 0 deletions
diff --git a/appc-config/appc-config-adaptor/.gitignore b/appc-config/appc-config-adaptor/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/appc-config/appc-config-adaptor/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/appc-config/appc-config-adaptor/features/.gitignore b/appc-config/appc-config-adaptor/features/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/appc-config/appc-config-adaptor/features/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/appc-config/appc-config-adaptor/features/pom.xml b/appc-config/appc-config-adaptor/features/pom.xml new file mode 100644 index 000000000..d8b954f28 --- /dev/null +++ b/appc-config/appc-config-adaptor/features/pom.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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"> + + + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>appc-config-adaptor-features</artifactId> + <name>Config Component Adaptor - Features</name> + + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor-provider</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <!-- <groupId>org.opendaylight.controller</groupId> --> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>features-mdsal</artifactId> + <version>${odl.mdsal.version}</version> + <classifier>features</classifier> + <type>xml</type> + + <scope>runtime</scope> + </dependency> + + <!-- dependency for opendaylight-karaf-empty for use by testing --> + <dependency> + <groupId>org.opendaylight.controller</groupId> + <artifactId>opendaylight-karaf-empty</artifactId> + <version>${odl.karaf.empty.distro.version}</version> + <type>zip</type> + </dependency> + + <dependency> + <!-- Required for launching the feature tests --> + <!-- <groupId>org.opendaylight.yangtools</groupId> --> + <groupId>org.opendaylight.odlparent</groupId> + <artifactId>features-test</artifactId> + <!-- <version>${odl.yangtools.version}</version> --> + <version>${odl.commons.opendaylight.version}</version> + <scope>test</scope> + </dependency> + + </dependencies> + + <build> + <resources> + <resource> + <filtering>true</filtering> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>filter</id> + <goals> + <goal>resources</goal> + </goals> + <phase>generate-resources</phase> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>attach-artifacts</id> + <goals> + <goal>attach-artifact</goal> + </goals> + <phase>package</phase> + <configuration> + <artifacts> + <artifact> + <file>${project.build.directory}/classes/${features.file}</file> + <type>xml</type> + <classifier>features</classifier> + </artifact> + </artifacts> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-config/appc-config-adaptor/features/src/main/resources/features.xml b/appc-config/appc-config-adaptor/features/src/main/resources/features.xml new file mode 100644 index 000000000..910ab40df --- /dev/null +++ b/appc-config/appc-config-adaptor/features/src/main/resources/features.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + + +<features name="appc-config-adaptor-${project.version}" + xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0"> + + <repository>mvn:org.opendaylight.mdsal/features-mdsal/${odl.mdsal.version}/xml/features</repository> + + <feature name='appc-config-adaptor' description="Application Controller Config Adaptor" + version='${project.version}'> + <feature version= '${sdnc.sli.version}'>sdnc-sli</feature> + <bundle>wrap:mvn:com.jcraft/jsch/0.1.52</bundle> + <bundle>wrap:mvn:org.jasypt/jasypt/1.9.2</bundle> + <bundle>wrap:mvn:com.att.eelf/eelf-core/${eelf.version}</bundle> + <bundle>mvn:ch.qos.logback/logback-core/${logback.version}</bundle> + <bundle>mvn:ch.qos.logback/logback-classic/${logback.version}</bundle> + <bundle>mvn:org.openecomp.appc/appc-config-adaptor-provider/${project.version}</bundle> + </feature> + +</features> diff --git a/appc-config/appc-config-adaptor/installer/pom.xml b/appc-config/appc-config-adaptor/installer/pom.xml new file mode 100644 index 000000000..404c7d2c0 --- /dev/null +++ b/appc-config/appc-config-adaptor/installer/pom.xml @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============LICENSE_START======================================================= + APPC + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + Copyright (C) 2017 Amdocs + ================================================================================ + 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========================================================= + ECOMP is a trademark and service mark of AT&T Intellectual Property. + --> +<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.openecomp.appc</groupId> + <artifactId>appc-config-adaptor</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-config-adaptor-installer</artifactId> + <name>Config Component Adaptor - Installer</name> + <packaging>pom</packaging> + <properties> + <application.name>appc-config-adaptor</application.name> + <features.boot>appc-config-adaptor</features.boot> + <features.repositories>mvn:org.openecomp.appc/appc-config-adaptor-features/${project.version}/xml/features</features.repositories> + <include.transitive.dependencies>false</include.transitive.dependencies> + </properties> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor-provider</artifactId> + <version>1.1.0-SNAPSHOT</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> + <appendAssemblyId>false</appendAssemblyId> + <attach>false</attach> + <finalName>stage/${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor> + </descriptors> + </configuration> + </execution> + <execution> + <id>installer-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <appendAssemblyId>false</appendAssemblyId> + <attach>true</attach> + <finalName>${application.name}-${project.version}</finalName> + <descriptors> + <descriptor>src/assembly/assemble_installer_zip.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</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> + <excludeGroupIds>org.opendaylight</excludeGroupIds> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>copy-version</id> + <goals> + <goal>copy-resources</goal> + </goals> + <!-- here the phase you need --> + <phase>validate</phase> + <configuration> + <outputDirectory>${basedir}/target/stage</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/scripts</directory> + <includes> + <include>install-feature.sh</include> + </includes> + <filtering>true</filtering> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/appc-config/appc-config-adaptor/installer/src/assembly/assemble_installer_zip.xml b/appc-config/appc-config-adaptor/installer/src/assembly/assemble_installer_zip.xml new file mode 100644 index 000000000..31a71f7e2 --- /dev/null +++ b/appc-config/appc-config-adaptor/installer/src/assembly/assemble_installer_zip.xml @@ -0,0 +1,59 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + ECOMP is a trademark and service mark of AT&T Intellectual Property. + --> + +<!-- 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>adapter</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/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>755</fileMode> + <includes> + <include>*.sh</include> + </includes> + </fileSet> + <fileSet> + <directory>target/stage/</directory> + <outputDirectory>${application.name}</outputDirectory> + <fileMode>644</fileMode> + <excludes> + <exclude>*.sh</exclude> + </excludes> + </fileSet> + </fileSets> + + + +</assembly> diff --git a/appc-config/appc-config-adaptor/installer/src/assembly/assemble_mvnrepo_zip.xml b/appc-config/appc-config-adaptor/installer/src/assembly/assemble_mvnrepo_zip.xml new file mode 100644 index 000000000..c7fd287e1 --- /dev/null +++ b/appc-config/appc-config-adaptor/installer/src/assembly/assemble_mvnrepo_zip.xml @@ -0,0 +1,47 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + ECOMP is a trademark and service mark of AT&T Intellectual Property. + --> + +<!-- 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>adapter</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/appc-config/appc-config-adaptor/installer/src/main/resources/scripts/install-feature.sh b/appc-config/appc-config-adaptor/installer/src/main/resources/scripts/install-feature.sh new file mode 100644 index 000000000..d3d2ea6e7 --- /dev/null +++ b/appc-config/appc-config-adaptor/installer/src/main/resources/scripts/install-feature.sh @@ -0,0 +1,40 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +### + +#!/bin/bash + +ODL_HOME=${ODL_HOME:-/opt/opendaylight/current} +ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client} +ODL_KARAF_CLIENT_OPTS=${ODL_KARAF_CLIENT_OPTS:-"-u karaf"} +INSTALLERDIR=$(dirname $0) + +REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip + +if [ -f ${REPOZIP} ] +then + unzip -n -d ${ODL_HOME} ${REPOZIP} +else + echo "ERROR : repo zip ($REPOZIP) not found" + exit 1 +fi + +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:repo-add ${features.repositories} +${ODL_KARAF_CLIENT} ${ODL_KARAF_CLIENT_OPTS} feature:install ${features.boot} diff --git a/appc-config/appc-config-adaptor/pom.xml b/appc-config/appc-config-adaptor/pom.xml new file mode 100644 index 000000000..d6bccd81d --- /dev/null +++ b/appc-config/appc-config-adaptor/pom.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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/maven-v4_0_0.xsd"> + + <parent> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <artifactId>appc-config-adaptor</artifactId> + <packaging>pom</packaging> + + <name>Config Component Adaptor</name> + <description>This adaptor implements Configure DG node that calls the Configuration Component</description> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor-features</artifactId> + <classifier>features</classifier> + <type>xml</type> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.openecomp.appc</groupId> + <artifactId>appc-config-adaptor-provider</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + </dependencyManagement> + + <modules> + <module>provider</module> + <module>features</module> + <module>installer</module> + </modules> + +</project> diff --git a/appc-config/appc-config-adaptor/provider/.gitignore b/appc-config/appc-config-adaptor/provider/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/appc-config/appc-config-adaptor/provider/pom.xml b/appc-config/appc-config-adaptor/provider/pom.xml new file mode 100644 index 000000000..48acd8d92 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/pom.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8"?> +<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.openecomp.appc</groupId> + <artifactId>appc-config-adaptor</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + + <artifactId>appc-config-adaptor-provider</artifactId> + <packaging>bundle</packaging> + <name>Config Component Adaptor - Provider</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-common</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.openecomp.sdnc.core</groupId> + <artifactId>sli-provider</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + </dependency> + + <dependency> + <groupId>com.jcraft</groupId> + <artifactId>jsch</artifactId> + <version>0.1.52</version> + </dependency> + + <dependency> + <groupId>jdom</groupId> + <artifactId>jdom</artifactId> + <version>1.1</version> + </dependency> + + <dependency> + <groupId>xerces</groupId> + <artifactId>xerces</artifactId> + <version>2.4.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-client</artifactId> + <version>1.17</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.jasypt</groupId> + <artifactId>jasypt</artifactId> + <version>1.9.2</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <build> + + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Bundle-SymbolicName>appc.config.adaptor</Bundle-SymbolicName> + <Bundle-Activator>org.openecomp.appc.config.adaptor.CCAActivator</Bundle-Activator> + <Export-Package>org.openecomp.appc.config.adaptor</Export-Package> + <Import-Package>*</Import-Package> + <DynamicImport-Package>*</DynamicImport-Package> + </instructions> + <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation> + </configuration> + </plugin> + </plugins> + + </build> +</project> diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/CCAActivator.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/CCAActivator.java new file mode 100644 index 000000000..32119f00c --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/CCAActivator.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Properties; + +import org.openecomp.sdnc.sli.ConfigurationException; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class CCAActivator implements BundleActivator +{ + + private static final String CCA_PROP_FILE_VAR = "SDNC_CCA_PROPERTIES"; + private static final String SDNC_CONFIG_DIR_VAR = "SDNC_CONFIG_DIR"; + + @SuppressWarnings("rawtypes") + private ServiceRegistration registration = null; + + //private static final Logger log = LoggerFactory.getLogger(CCAActivator.class); + private static final EELFLogger log = EELFManager.getInstance().getLogger(CCAActivator.class); + + @Override + public void start(BundleContext ctx) throws Exception + { + // Read properties + Properties props = new Properties(); + + // Read properties from appc-config-adaptor.properties + String propFileName = System.getenv(CCA_PROP_FILE_VAR); + if (propFileName == null) + { + String propDir = System.getenv(SDNC_CONFIG_DIR_VAR); + if (propDir == null) + throw new ConfigurationException( + "Cannot find config file - " + CCA_PROP_FILE_VAR + " and " + SDNC_CONFIG_DIR_VAR + " unset"); + + propFileName = propDir + "/appc-config-adaptor.properties"; + log.warn("Environment variable " + CCA_PROP_FILE_VAR + " unset - defaulting to " + propFileName); + } + + File propFile = new File(propFileName); + if (!propFile.exists()) + throw new ConfigurationException("Missing configuration properties file: " + propFile); + + InputStream in = new FileInputStream(propFile); + try + { + props.load(in); + } + catch (Exception e) + { + throw new ConfigurationException("Could not load properties file " + propFileName, e); + } + finally + { + try + { + in.close(); + } + catch (Exception e) + { + log.warn("Could not close FileInputStream", e); + } + } + + log.info("Loaded properties: "); + + // Advertise adaptor + ConfigComponentAdaptor adaptor = new ConfigComponentAdaptor(props); + if (registration == null) + { + log.info("Registering service " + ConfigComponentAdaptor.class.getName()); + registration = ctx.registerService(ConfigComponentAdaptor.class.getName(), adaptor, null); + } + + } + + @Override + public void stop(BundleContext ctx) throws Exception + { + if (registration != null) + { + registration.unregister(); + registration = null; + } + } +} diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/ConfigComponentAdaptor.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/ConfigComponentAdaptor.java new file mode 100644 index 000000000..3158bd6fc --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/ConfigComponentAdaptor.java @@ -0,0 +1,1062 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property.All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.StringTokenizer; +import java.util.NoSuchElementException; +import java.io.StringReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.openecomp.sdnc.sli.SvcLogicAdaptor; +import org.openecomp.sdnc.sli.SvcLogicContext; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.core.util.Base64; +import org.jdom.input.SAXBuilder; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class ConfigComponentAdaptor implements SvcLogicAdaptor +{ + + private static final EELFLogger log = EELFManager.getInstance().getLogger(ConfigComponentAdaptor.class); + + private String configUrl = null; + private String configUser = null; + private String configPassword = null; + private String auditUrl = null; + private String auditUser = null; + private String auditPassword = null; + private String configCallbackUrl = null; + private String auditCallbackUrl = null; + DebugLog debugLog = new DebugLog(); + + public ConfigComponentAdaptor(Properties props) + { + if (props != null) + { + configUrl = props.getProperty("configComponent.url", ""); + configUser = props.getProperty("configComponent.user", ""); + configPassword = props.getProperty("configComponent.passwd", ""); + auditUrl = props.getProperty("auditComponent.url", ""); + auditUser = props.getProperty("auditComponent.user", ""); + auditPassword = props.getProperty("auditComponent.passwd", ""); + configCallbackUrl = props.getProperty("service-configuration-notification-url", ""); + auditCallbackUrl = props.getProperty("audit-configuration-notification-url", ""); + } + else + { + configUrl = ""; + configUser = ""; + configPassword = ""; + auditUrl = ""; + auditUser = ""; + auditPassword = ""; + configCallbackUrl = ""; + auditCallbackUrl = ""; + } + } + + @Override + public ConfigStatus configure(String key, Map<String, String> parameters, SvcLogicContext ctx) + { + String fnName = "ConfigComponentAdaptor.configure"; + HttpResponse r = new HttpResponse(); + r.code = 200; + log.debug("ConfigComponentAdaptor.configure - key = " + key); + debugLog.printRTAriDebug(fnName, "key = " + key); + log.debug("Parameters:"); + debugLog.printRTAriDebug(fnName, "Parameters:"); + for (String parmName : parameters.keySet()) + { + log.debug(" " + parmName + " = " + parameters.get(parmName)); + debugLog.printRTAriDebug(fnName, " " + parmName + " = " + parameters.get(parmName)); + } + + String parmval = parameters.get("config-component-configUrl"); + if ((parmval != null) && (parmval.length() > 0)) + { + log.debug("Overwriting URL with " + parmval); + configUrl = parmval; + } + + parmval = parameters.get("config-component-configPassword"); + if ((parmval != null) && (parmval.length() > 0)) + { + log.debug("Overwriting configPassword with " + parmval); + configPassword = parmval; + } + + parmval = parameters.get("config-component-configUser"); + if ((parmval != null) && (parmval.length() > 0)) + { + log.debug("Overwriting configUser id with " + parmval); + configUser = parmval; + } + + String action = parameters.get("action"); + + String chg = ctx.getAttribute( + "service-data.vnf-config-parameters-list.vnf-config-parameters[0].update-configuration[0].block-key-name"); + if (chg != null && "prepare".equalsIgnoreCase(action)) + return prepare(ctx, "CHANGE", "change"); + if (chg != null && "activate".equalsIgnoreCase(action)) + return activate(ctx, true); + + String scale = ctx.getAttribute( + "service-data.vnf-config-parameters-list.vnf-config-parameters[0].scale-configuration[0].network-type"); + if (scale != null && "prepare".equalsIgnoreCase(action)) + return prepare(ctx, "CHANGE", "scale"); + if (scale != null && "activate".equalsIgnoreCase(action)) + return activate(ctx, true); + + if ("prepare".equalsIgnoreCase(action)) + return prepare(ctx, "BASE", "create"); + if ("activate".equalsIgnoreCase(action)) + return activate(ctx, false); + + if ("backup".equalsIgnoreCase(action)) + return prepare(ctx, "BACKUP", "backup"); + if ("restorebackup".equalsIgnoreCase(action)) + return prepare(ctx, "RESTOREBACKUP", "restorebackup"); + if ("deletebackup".equalsIgnoreCase(action)) + return prepare(ctx, "DELETEBACKUP", "deletebackup"); + if ("audit".equalsIgnoreCase(action)) + return audit(ctx, "FULL"); + if ("getrunningconfig".equalsIgnoreCase(action)) + return audit(ctx, "RUNNING"); + + if ((key.equals("put")) || (key.equals("get"))) + { + String loginId = parameters.get("loginId"); + String host = parameters.get("host"); + String password = parameters.get("password"); + password = EncryptionTool.getInstance().decrypt(password); + String fullPathFileName = parameters.get("fullPathFileName"); + String data = null; + if (key.equals("put")) + data = parameters.get("data"); + + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + log.debug("SCP: SshJcraftWrapper has been instantiated"); + debugLog.printRTAriDebug(fnName, "SCP: SshJcraftWrapper has been instantiated"); + try + { + if (key.equals("put")) + { + debugLog.printRTAriDebug(fnName, "Command is for put: Length of data is: " + data.length()); + InputStream is = new ByteArrayInputStream(data.getBytes()); + log.debug("SCP: Doing a put: fullPathFileName=" + fullPathFileName); + debugLog.printRTAriDebug(fnName, "SCP: Doing a put: fullPathFileName=" + fullPathFileName); + sshJcraftWrapper.put(is, fullPathFileName, host, loginId, password); + try + { + debugLog.printRTAriDebug(fnName, "Sleeping for 180 seconds...."); + Thread.sleep(1000 * 180); + debugLog.printRTAriDebug(fnName, "Woke up...."); + } + catch (java.lang.InterruptedException ee) + { + boolean ignore = true; + } + } + else // Must be a get + { + log.debug("SCP: Doing a get: fullPathFileName=" + fullPathFileName); + debugLog.printRTAriDebug(fnName, "SCP: Doing a get: fullPathFileName=" + fullPathFileName); + String response = sshJcraftWrapper.get(fullPathFileName, host, loginId, password); + debugLog.printRTAriDebug(fnName, "Got the response and putting into the ctx object"); + ctx.setAttribute("fileContents", response); + log.debug("SCP: Closing the SFTP connection"); + } + sshJcraftWrapper = null; + return (setResponseStatus(ctx, r)); + } + catch (IOException e) + { + DebugLog.printAriDebug(fnName, "Caught a IOException e=" + e); + log.debug(fnName + " : Caught a IOException e=" + e); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + return (setResponseStatus(ctx, r)); + } + } + if (key.equals("cli")) + { + String loginId = parameters.get("loginId"); + String host = parameters.get("host"); + String password = parameters.get("password"); + password = EncryptionTool.getInstance().decrypt(password); + String cliCommand = parameters.get("cli"); + String portNumber = parameters.get("portNumber"); + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + try + { + log.debug("CLI: Attempting to login: host=" + host + " loginId=" + loginId + " password=" + password + + " portNumber=" + portNumber); + debugLog.printRTAriDebug(fnName, "CLI: Attempting to login: host=" + host + " loginId=" + loginId + + " password=" + password + " portNumber=" + portNumber); + sshJcraftWrapper.connect(host, loginId, password, Integer.parseInt(portNumber)); + + DebugLog.printAriDebug(fnName, "Sending 'sdc'"); + String response = sshJcraftWrapper.send("sdc", ":"); + DebugLog.printAriDebug(fnName, "Sending 1"); + response = sshJcraftWrapper.send("1", ":"); + DebugLog.printAriDebug(fnName, "Sending 1, the second time"); + response = sshJcraftWrapper.send("1", "#"); + DebugLog.printAriDebug(fnName, "Sending paging-options disable"); + response = sshJcraftWrapper.send("paging-options disable", "#"); + DebugLog.printAriDebug(fnName, "Sending show config"); + response = sshJcraftWrapper.send("show config", "#"); + + DebugLog.printAriDebug(fnName, "response is now:'" + response + "'"); + DebugLog.printAriDebug(fnName, "Populating the ctx object with the response"); + ctx.setAttribute("cliOutput", response); + sshJcraftWrapper.closeConnection(); + r.code = 200; + sshJcraftWrapper = null; + return (setResponseStatus(ctx, r)); + } + catch (IOException e) + { + DebugLog.printAriDebug(fnName, "Caught a IOException e=" + e); + log.debug(fnName + " : Caught a IOException e=" + e); + sshJcraftWrapper.closeConnection(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + DebugLog.printAriDebug(fnName, "Returning error message"); + return (setResponseStatus(ctx, r)); + } + } + if (key.equals("escapeSql")) + { + String data = parameters.get("artifactContents"); + log.debug("ConfigComponentAdaptor.configure - escapeSql"); + data = escapeMySql(data); + ctx.setAttribute("escapedData", data); + return (setResponseStatus(ctx, r)); + } + if(key.equals("GetCliRunningConfig")) + { + debugLog.printRTAriDebug (fnName, "key was: GetCliRunningConfig: "); + log.debug("key was: GetCliRunningConfig: "); + String User_name = parameters.get("User_name"); + String Host_ip_address = parameters.get("Host_ip_address"); + String Password = parameters.get("Password"); + Password = EncryptionTool.getInstance().decrypt(Password); + String Port_number = parameters.get("Port_number"); + String Get_config_template = parameters.get("Get_config_template"); + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + log.debug("GetCliRunningConfig: sshJcraftWrapper was instantiated"); + debugLog.printRTAriDebug (fnName, "GetCliRunningConfig: sshJcraftWrapper was instantiated"); + try + { + DebugLog.printAriDebug(fnName, "GetCliRunningConfig: User_name="+User_name + + " Host_ip_address="+Host_ip_address +" Password="+Password +" Port_number="+Port_number); + log.debug("GetCliRunningConfig: Attempting to login: Host_ip_address="+Host_ip_address + + " User_name="+User_name+" Password="+Password+" Port_number="+Port_number); + StringBuffer sb = new StringBuffer(); + String response = ""; + String CliResponse = ""; + boolean showConfigFlag = false; + sshJcraftWrapper.connect (Host_ip_address, User_name, Password, "", 30000, Integer.parseInt(Port_number)); + DebugLog.printAriDebug(fnName, "GetCliRunningConfig: On the VNF device"); + StringTokenizer st = new StringTokenizer(Get_config_template, "\n"); + String command = null; + try + { + while (st.hasMoreTokens()) + { + String line = st.nextToken(); + DebugLog.printAriDebug(fnName, "line="+line); + if (line.indexOf("Request:") != -1) + { + DebugLog.printAriDebug(fnName, "Found a Request line: line="+line); + command = getStringBetweenQuotes(line); + DebugLog.printAriDebug(fnName, "Sending command="+command); + sshJcraftWrapper.send(command); + DebugLog.printAriDebug(fnName, "command has been sent"); + if (line.indexOf("show config") != -1) + { + showConfigFlag = true; + DebugLog.printAriDebug(fnName, "GetCliRunningConfig: setting 'showConfigFlag' to true"); + log.debug("GetCliRunningConfig: GetCliRunningConfig: setting 'showConfigFlag' to true"); + } + } + if (line.indexOf("Response: Ends_With") != -1) + { + DebugLog.printAriDebug(fnName, "Found a Response line: line="+line); + String delemeter = getStringBetweenQuotes(line); + DebugLog.printAriDebug(fnName, "The delemeter="+delemeter); + String tmpResponse = sshJcraftWrapper.receiveUntil(delemeter, 30*1000, command); + response += tmpResponse; + if (showConfigFlag) + { + showConfigFlag = false; + StringTokenizer st2 = new StringTokenizer(tmpResponse, "\n"); + // Strip off the last line which is the command prompt from the VNF device. + while (st2.hasMoreTokens()) + { + String line2 = st2.nextToken(); + if (line2.indexOf("#") == -1) + CliResponse += line2 +"\n"; + } + } + } + } + } + catch (NoSuchElementException e) + { + DebugLog.printAriDebug(fnName, "Caught a NoSuchElementException: e="+e); + } + DebugLog.printAriDebug(fnName, "CliResponse=\n"+CliResponse); + ctx.setAttribute("cliOutput", CliResponse); + sshJcraftWrapper.closeConnection(); + r.code = 200; + sshJcraftWrapper = null; + return(setResponseStatus(ctx, r)); + } + catch(IOException e) + { + DebugLog.printAriDebug(fnName, "GetCliRunningConfig: Caught a IOException e="+e); + log.debug(fnName +" : GetCliRunningConfig: Caught a IOException e="+e); + sshJcraftWrapper.closeConnection(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + DebugLog.printAriDebug(fnName, "GetCliRunningConfig: Returning error message"); + return(setResponseStatus(ctx, r)); + } + } + if(key.equals("xml-download")) + { + log(fnName, "key was: xml-download"); + String User_name = parameters.get("User_name"); + String Host_ip_address = parameters.get("Host_ip_address"); + String Password = parameters.get("Password"); + Password = EncryptionTool.getInstance().decrypt(Password); + String Port_number = parameters.get("Port_number"); + String Contents = parameters.get("Contents"); + String netconfHelloCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n <capabilities>\n <capability>urn:ietf:params:netconf:base:1.0</capability>\n <capability>urn:com:ericsson:ebase:1.1.0</capability> </capabilities>\n </hello>"; + String terminateConnectionCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <rpc message-id=\"terminateConnection\" xmlns:netconf=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n <close-session/> \n </rpc>\n ]]>]]>"; + String commitCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <rpc> <commit/> </rpc>\n ]]>]]>"; + + log(fnName, "xml-download: User_name="+User_name +" Host_ip_address="+Host_ip_address +" Password="+Password +" Port_number="+Port_number); + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + try + { + sshJcraftWrapper.connect (Host_ip_address, User_name, Password, "]]>]]>", 30000, Integer.parseInt(Port_number), "netconf"); + String NetconfHelloCmd = netconfHelloCmd; + NetconfHelloCmd = NetconfHelloCmd +"]]>]]>"; + log(fnName, "Sending the hello command"); + sshJcraftWrapper.send(NetconfHelloCmd); + String response = sshJcraftWrapper.receiveUntil("]]>]]>", 10000, ""); + log(fnName, "Sending xmlCmd cmd"); + String xmlCmd = Contents; + String messageId = "1"; + messageId= "\"" +messageId+"\""; + String loadConfigurationString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id="+messageId+"> <edit-config> <target> <candidate /> </target> <default-operation>merge</default-operation> <config xmlns:xc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"+xmlCmd+"</config> </edit-config> </rpc>"; + loadConfigurationString = loadConfigurationString +"]]>]]>"; + sshJcraftWrapper.send(loadConfigurationString); + DebugLog.printAriDebug(fnName,":After sending loadConfigurationString"); + response = sshJcraftWrapper.receiveUntil("</rpc-reply>", 600000, ""); + if (response.indexOf("rpc-error") != -1) + { + DebugLog.printAriDebug(fnName,"Error from device: Response from device had 'rpc-error'"); + DebugLog.printAriDebug(fnName,"response=\n"+response +"\n"); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = response; + } + else + { + DebugLog.printAriDebug(fnName,":LoadConfiguration was a success, sending commit cmd"); + sshJcraftWrapper.send(commitCmd); + DebugLog.printAriDebug(fnName,":After sending commitCmd"); + response = sshJcraftWrapper.receiveUntil("</rpc-reply>", 180000, ""); + if (response.indexOf("rpc-error") != -1) + { + DebugLog.printAriDebug(fnName,"Error from device: Response from device had 'rpc-error'"); + DebugLog.printAriDebug(fnName,"response=\n"+response +"\n"); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = response; + } + else + { + DebugLog.printAriDebug(fnName,":Looks like a success"); + DebugLog.printAriDebug(fnName,"response=\n"+response +"\n"); + r.code = 200; + } + } + sshJcraftWrapper.send(terminateConnectionCmd); + sshJcraftWrapper.closeConnection(); + sshJcraftWrapper = null; + return(setResponseStatus(ctx, r)); + } + catch (Exception e) + { + log(fnName, "Caught an Exception, e="+e); + log(fnName, "StackTrace="+DebugLog.getStackTraceString(e)); + sshJcraftWrapper.closeConnection(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + log(fnName, "Returning error message"); + return (setResponseStatus(ctx, r)); + } + } + if(key.equals("xml-getrunningconfig")) + { + log(fnName, "key was: : xml-getrunningconfig"); + String xmlGetRunningConfigCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\"> <get-config> <source> <running /> </source> </get-config> </rpc>\n"; + String Host_ip_address = parameters.get("Host_ip_address"); + String User_name = parameters.get("User_name"); + String Password = parameters.get("Password"); + Password = EncryptionTool.getInstance().decrypt(Password); + String Port_number = parameters.get("Port_number"); + String Protocol = parameters.get("Protocol"); + String netconfHelloCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n <capabilities>\n <capability>urn:ietf:params:netconf:base:1.0</capability>\n <capability>urn:com:ericsson:ebase:1.1.0</capability> </capabilities>\n </hello>"; + String terminateConnectionCmd = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n <rpc message-id=\"terminateConnection\" xmlns:netconf=\"urn:ietf:params:xml:ns:netconf:base:1.0\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n <close-session/> \n </rpc>\n ]]>]]>"; + log(fnName, "xml-getrunningconfig: User_name="+User_name +" Host_ip_address="+Host_ip_address +" Password="+Password +" Port_number="+Port_number); + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + try + { + String NetconfHelloCmd = netconfHelloCmd; + sshJcraftWrapper.connect (Host_ip_address, User_name, Password, "]]>]]>", 30000, Integer.parseInt(Port_number), "netconf"); + NetconfHelloCmd = NetconfHelloCmd +"]]>]]>"; + log(fnName, ":Sending the hello command"); + sshJcraftWrapper.send(NetconfHelloCmd); + String response = sshJcraftWrapper.receiveUntil("]]>]]>", 10000, ""); + log(fnName, "Sending get running config command"); + sshJcraftWrapper.send(xmlGetRunningConfigCmd +"]]>]]>\n"); + response = sshJcraftWrapper.receiveUntil("</rpc-reply>", 180000, ""); + DebugLog.printAriDebug(fnName,"Response from getRunningconfigCmd="+response); + response = trimResponse(response); + ctx.setAttribute("xmlRunningConfigOutput", response); + sshJcraftWrapper.send(terminateConnectionCmd); + sshJcraftWrapper.closeConnection(); + r.code = 200; + sshJcraftWrapper = null; + return(setResponseStatus(ctx, r)); + } + catch (Exception e) + { + log(fnName, "Caught an Exception, e="+e); + log(fnName, "StackTrace="+DebugLog.getStackTraceString(e)); + sshJcraftWrapper.closeConnection(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + log(fnName, "Returning error message"); + return (setResponseStatus(ctx, r)); + } + } + if(key.equals("DownloadCliConfig")) + { + debugLog.printRTAriDebug (fnName, "key was: DownloadCliConfig: "); + log.debug("key was: DownloadCliConfig: "); + String User_name = parameters.get("User_name"); + String Host_ip_address = parameters.get("Host_ip_address"); + String Password = parameters.get("Password"); + Password = EncryptionTool.getInstance().decrypt(Password); + String Port_number = parameters.get("Port_number"); + String Download_config_template = parameters.get("Download_config_template"); + String Config_contents = parameters.get("Config_contents"); + DebugLog.printAriDebug(fnName, "Contents of the 'Config_contents' are: "+Config_contents); + SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper(); + log.debug("DownloadCliConfig: sshJcraftWrapper was instantiated"); + debugLog.printRTAriDebug (fnName, "DownloadCliConfig: sshJcraftWrapper was instantiated"); + int timeout = 4*60*1000; + try + { + DebugLog.printAriDebug(fnName, "DownloadCliConfig: User_name="+User_name + + " Host_ip_address="+Host_ip_address +" Password="+Password +" Port_number="+Port_number); + log.debug("DownloadCliConfig: Attempting to login: Host_ip_address="+Host_ip_address + + " User_name="+User_name+" Password="+Password+" Port_number="+Port_number); + StringBuffer sb = new StringBuffer(); + String response = ""; + String CliResponse = ""; + sshJcraftWrapper.connect (Host_ip_address, User_name, Password, "", 30000, Integer.parseInt(Port_number)); + DebugLog.printAriDebug(fnName, "DownloadCliConfig: On the VNF device"); + StringTokenizer st = new StringTokenizer(Download_config_template, "\n"); + String command = null; + String executeConfigContentsDelemeter = null; + try + { + while (st.hasMoreTokens()) + { + String line = st.nextToken(); + DebugLog.printAriDebug(fnName, "line="+line); + if (line.indexOf("Request:") != -1) + { + DebugLog.printAriDebug(fnName, "Found a Request line: line="+line); + command = getStringBetweenQuotes(line); + DebugLog.printAriDebug(fnName, "Sending command="+command); + sshJcraftWrapper.send(command); + DebugLog.printAriDebug(fnName, "command has been sent"); + } + else if ((line.indexOf("Response: Ends_With") != -1) && (line.indexOf("Execute_config_contents Response: Ends_With") == -1)) + { + DebugLog.printAriDebug(fnName, "Found a Response line: line="+line); + String delemeter = getStringBetweenQuotes(line); + DebugLog.printAriDebug(fnName, "The delemeter="+delemeter); + String tmpResponse = sshJcraftWrapper.receiveUntil(delemeter, timeout, command); + response += tmpResponse; + CliResponse += tmpResponse; + } + else if (line.indexOf("Execute_config_contents Response: Ends_With") != -1) + { + DebugLog.printAriDebug(fnName, "Found a 'Execute_config_contents Response:' line="+line); + executeConfigContentsDelemeter = getStringBetweenQuotes(line); + DebugLog.printAriDebug(fnName, "executeConfigContentsDelemeter="+executeConfigContentsDelemeter); + StringTokenizer st2 = new StringTokenizer(Config_contents, "\n"); + while (st2.hasMoreTokens()) + { + String cmd = st2.nextToken(); + DebugLog.printAriDebug(fnName, "Config_contents: cmd="+cmd); + sshJcraftWrapper.send(cmd); + String tmpResponse = sshJcraftWrapper.receiveUntil(executeConfigContentsDelemeter, timeout, command); + CliResponse += tmpResponse; + } + } + } + } + catch (NoSuchElementException e) + { + DebugLog.printAriDebug(fnName, "Caught a NoSuchElementException: e="+e); + } + sshJcraftWrapper.closeConnection(); + sshJcraftWrapper = null; + DebugLog.printAriDebug(fnName, ":Escaping all the single and double quotes in the response"); + CliResponse = CliResponse.replaceAll("\"", "\\\\\""); + CliResponse = CliResponse.replaceAll("\'", "\\\\'"); + DebugLog.printAriDebug(fnName, "CliResponse=\n"+CliResponse); + ctx.setAttribute("cliOutput", CliResponse); + r.code = 200; + return(setResponseStatus(ctx, r)); + } + catch(IOException e) + { + DebugLog.printAriDebug(fnName, "DownloadCliConfig: Caught a IOException e="+e); + log.debug(fnName +" : DownloadCliConfig: Caught a IOException e="+e); + sshJcraftWrapper.closeConnection(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + sshJcraftWrapper = null; + DebugLog.printAriDebug(fnName, "DownloadCliConfig: Returning error message"); + return(setResponseStatus(ctx, r)); + } + } + + debugLog.printRTAriDebug (fnName, "Unsupported action - " + action); + log.error("Unsupported action - " + action); + return ConfigStatus.FAILURE; + } + + private void log (String fileName, String messg) + { + debugLog.printRTAriDebug (fileName, messg); + log.debug(fileName +": "+messg); + } + + private ConfigStatus prepare(SvcLogicContext ctx, String requestType, String operation) + { + String templateName = requestType.equals("BASE") ? "/config-base.xml" : "/config-data.xml"; + String ndTemplate = readFile(templateName); + String nd = buildNetworkData2(ctx, ndTemplate, operation); + + String reqTemplate = readFile("/config-request.xml"); + Map<String, String> param = new HashMap<String, String>(); + param.put("request-id", ctx.getAttribute("service-data.appc-request-header.svc-request-id")); + param.put("request-type", requestType); + param.put("callback-url", configCallbackUrl); + if (operation.equals("create") || operation.equals("change") || operation.equals("scale")) + param.put("action", "GenerateOnly"); + param.put("equipment-name", ctx.getAttribute("service-data.service-information.service-instance-id")); + param.put("equipment-ip-address", ctx.getAttribute("service-data.vnf-config-information.vnf-host-ip-address")); + param.put("vendor", ctx.getAttribute("service-data.vnf-config-information.vendor")); + param.put("network-data", nd); + + String req = null; + try + { + req = buildXmlRequest(param, reqTemplate); + } + catch (Exception e) + { + log.error("Error building the XML request: ", e); + + HttpResponse r = new HttpResponse(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + return setResponseStatus(ctx, r); + } + + HttpResponse r = sendXmlRequest(req, configUrl, configUser, configPassword); + return setResponseStatus(ctx, r); + } + + private ConfigStatus activate(SvcLogicContext ctx, boolean change) + { + String reqTemplate = readFile("/config-request.xml"); + Map<String, String> param = new HashMap<String, String>(); + param.put("request-id", ctx.getAttribute("service-data.appc-request-header.svc-request-id")); + param.put("callback-url", configCallbackUrl); + param.put("action", change ? "DownloadChange" : "DownloadBase"); + param.put("equipment-name", ctx.getAttribute("service-data.service-information.service-instance-id")); + + String req = null; + try + { + req = buildXmlRequest(param, reqTemplate); + } + catch (Exception e) + { + log.error("Error building the XML request: ", e); + + HttpResponse r = new HttpResponse(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + return setResponseStatus(ctx, r); + } + + HttpResponse r = sendXmlRequest(req, configUrl, configUser, configPassword); + return setResponseStatus(ctx, r); + } + + private ConfigStatus audit(SvcLogicContext ctx, String auditLevel) + { + String reqTemplate = readFile("/audit-request.xml"); + Map<String, String> param = new HashMap<String, String>(); + param.put("request-id", ctx.getAttribute("service-data.appc-request-header.svc-request-id")); + param.put("callback-url", auditCallbackUrl); + param.put("equipment-name", ctx.getAttribute("service-data.service-information.service-instance-id")); + param.put("audit-level", auditLevel); + + String req = null; + try + { + req = buildXmlRequest(param, reqTemplate); + } + catch (Exception e) + { + log.error("Error building the XML request: ", e); + + HttpResponse r = new HttpResponse(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + return setResponseStatus(ctx, r); + } + + HttpResponse r = sendXmlRequest(req, auditUrl, auditUser, auditPassword); + return setResponseStatus(ctx, r); + } + + @Override + public ConfigStatus activate(String key, SvcLogicContext ctx) + { + return ConfigStatus.SUCCESS; + } + + @Override + public ConfigStatus deactivate(String key, SvcLogicContext ctx) + { + return ConfigStatus.SUCCESS; + } + + private String escapeMySql(String input) + { + if (input == null) + return null; + + input = input.replace("\\", "\\\\"); + input = input.replace("\'", "\\'"); + + return input; + } + + private String readFile(String fileName) + { + InputStream is = getClass().getResourceAsStream(fileName); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader in = new BufferedReader(isr); + StringBuilder ss = new StringBuilder(); + try + { + String s = in.readLine(); + while (s != null) + { + ss.append(s).append('\n'); + s = in.readLine(); + } + } + catch (IOException e) + { + System.out.println("Error reading " + fileName + ": " + e.getMessage()); + throw new RuntimeException("Error reading " + fileName + ": " + e.getMessage(), e); + } + finally + { + try + { + in.close(); + } + catch (Exception e) + { + log.warn("Could not close BufferedReader", e); + } + try + { + isr.close(); + } + catch (Exception e) + { + log.warn("Could not close InputStreamReader", e); + } + try + { + is.close(); + } + catch (Exception e) + { + log.warn("Could not close InputStream", e); + } + } + return ss.toString(); + } + + private String buildXmlRequest(Map<String, String> param, String template) + { + StringBuilder ss = new StringBuilder(); + int i = 0; + while (i < template.length()) + { + int i1 = template.indexOf("${", i); + if (i1 < 0) + { + ss.append(template.substring(i)); + break; + } + + int i2 = template.indexOf('}', i1 + 2); + if (i2 < 0) + throw new RuntimeException("Template error: Matching } not found"); + + String var1 = template.substring(i1 + 2, i2); + String value1 = param.get(var1); + if (value1 == null || value1.trim().length() == 0) + { + // delete the whole element (line) + int i3 = template.lastIndexOf('\n', i1); + if (i3 < 0) + i3 = 0; + int i4 = template.indexOf('\n', i1); + if (i4 < 0) + i4 = template.length(); + + if (i < i3) + ss.append(template.substring(i, i3)); + i = i4; + } + else + { + ss.append(template.substring(i, i1)).append(value1); + i = i2 + 1; + } + } + + return ss.toString(); + } + + private String buildNetworkData2(SvcLogicContext ctx, String template, String operation) + { + log.info("Building XML started"); + long t1 = System.currentTimeMillis(); + + template = expandRepeats(ctx, template, 1); + + Map<String, String> mm = new HashMap<>(); + for (String s : ctx.getAttributeKeySet()) + mm.put(s, ctx.getAttribute(s)); + mm.put("operation", operation); + + StringBuilder ss = new StringBuilder(); + int i = 0; + while (i < template.length()) + { + int i1 = template.indexOf("${", i); + if (i1 < 0) + { + ss.append(template.substring(i)); + break; + } + + int i2 = template.indexOf('}', i1 + 2); + if (i2 < 0) + throw new RuntimeException("Template error: Matching } not found"); + + String var1 = template.substring(i1 + 2, i2); + String value1 = XmlUtil.getXml(mm, var1); + if (value1 == null || value1.trim().length() == 0) + { + // delete the whole element (line) + int i3 = template.lastIndexOf('\n', i1); + if (i3 < 0) + i3 = 0; + int i4 = template.indexOf('\n', i1); + if (i4 < 0) + i4 = template.length(); + + if (i < i3) + ss.append(template.substring(i, i3)); + i = i4; + } + else + { + ss.append(template.substring(i, i1)).append(value1); + i = i2 + 1; + } + } + + long t2 = System.currentTimeMillis(); + log.info("Building XML completed. Time: " + (t2 - t1)); + + return ss.toString(); + } + + private String expandRepeats(SvcLogicContext ctx, String template, int level) + { + StringBuilder newTemplate = new StringBuilder(); + int k = 0; + while (k < template.length()) + { + int i1 = template.indexOf("${repeat:", k); + if (i1 < 0) + { + newTemplate.append(template.substring(k)); + break; + } + + int i2 = template.indexOf(':', i1 + 9); + if (i2 < 0) + throw new RuntimeException( + "Template error: Context variable name followed by : is required after repeat"); + + // Find the closing }, store in i3 + int nn = 1; + int i3 = -1; + int i = i2; + while (nn > 0 && i < template.length()) + { + i3 = template.indexOf('}', i); + if (i3 < 0) + throw new RuntimeException("Template error: Matching } not found"); + int i32 = template.indexOf('{', i); + if (i32 >= 0 && i32 < i3) + { + nn++; + i = i32 + 1; + } + else + { + nn--; + i = i3 + 1; + } + } + + String var1 = template.substring(i1 + 9, i2); + String value1 = ctx.getAttribute(var1); + log.info(" " + var1 + ": " + value1); + int n = 0; + try + { + n = Integer.parseInt(value1); + } + catch (Exception e) + { + n = 0; + } + + newTemplate.append(template.substring(k, i1)); + + String rpt = template.substring(i2 + 1, i3); + + for (int ii = 0; ii < n; ii++) + { + String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]"); + newTemplate.append(ss); + } + + k = i3 + 1; + } + + if (k == 0) + return newTemplate.toString(); + + return expandRepeats(ctx, newTemplate.toString(), level + 1); + } + + private HttpResponse sendXmlRequest(String xmlRequest, String url, String user, String password) + { + try + { + Client client = Client.create(); + client.setConnectTimeout(5000); + WebResource webResource = client.resource(url); + + log.info("SENDING..............."); + log.info(xmlRequest); + + String authString = user + ":" + password; + byte[] authEncBytes = Base64.encode(authString); + String authStringEnc = new String(authEncBytes); + authString = "Basic " + authStringEnc; + + ClientResponse response = + webResource.header("Authorization", authString).accept("UTF-8").type("application/xml").post( + ClientResponse.class, xmlRequest); + + int code = response.getStatus(); + String message = null; + + log.info("RESPONSE..............."); + log.info("HTTP response code: " + code); + log.info("HTTP response message: " + message); + log.info(""); + + HttpResponse r = new HttpResponse(); + r.code = code; + r.message = message; + return r; + + } + catch (Exception e) + { + log.error("Error sending the request: ", e); + + HttpResponse r = new HttpResponse(); + r.code = HttpURLConnection.HTTP_INTERNAL_ERROR; + r.message = e.getMessage(); + return r; + } + } + + private static class HttpResponse + { + + public int code; + public String message; + } + + private ConfigStatus setResponseStatus(SvcLogicContext ctx, HttpResponse r) + { + ctx.setAttribute("error-code", String.valueOf(r.code)); + ctx.setAttribute("error-message", r.message); + + return r.code > 299 ? ConfigStatus.FAILURE : ConfigStatus.SUCCESS; + } + + private String getStringBetweenQuotes(String string) + { + String fnName = "ConfigComponentAdaptor.getStringBetweenQuotes"; + DebugLog.printAriDebug(fnName, "string="+string); + String retString = null; + int start = string.indexOf("\""); + int end = string.lastIndexOf("\""); + retString = string.substring(start+1, end); + DebugLog.printAriDebug(fnName, "retString="+retString); + return(retString); + } + + public static String _readFile(String fileName) + { + StringBuffer strBuff = new StringBuffer(); + String line; + try + { + BufferedReader in = new BufferedReader(new FileReader(fileName)); + while ((line = in.readLine()) != null) + { + strBuff.append(line+"\n"); + } + in.close(); + } + catch (IOException e) + { + System.out.println("Caught an IOException in method readFile(): e="+e.toString()); + } + return (strBuff.toString()); + } + + private String trimResponse(String response) + { + StringTokenizer line = new StringTokenizer(response, "\n"); + StringBuffer sb = new StringBuffer(); + boolean captureText = false; + while (line.hasMoreTokens()) + { + String token = line.nextToken(); + if (token.indexOf("<configuration xmlns=") != -1) + captureText = true; + if (captureText) + sb.append(token +"\n"); + if (token.indexOf("</configuration>") != -1) + captureText = false; + } + return(sb.toString()); + } + + public static void main (String args[]) throws Exception + { + Properties props = null; + System.out.println("*************************Hello*****************************"); + ConfigComponentAdaptor cca = new ConfigComponentAdaptor(props); + String Get_config_template = _readFile ("/home/userID/data/Get_config_template"); + String Download_config_template = _readFile ("/home/userID/data/Download_config_template_2"); + String key = "GetCliRunningConfig"; + Map<String, String> parameters = new HashMap(); + parameters.put("Host_ip_address", "000.00.000.00"); + parameters.put("User_name", "root"); + parameters.put("Password", "!bootstrap"); + parameters.put("Port_number", "22"); + parameters.put("Get_config_template", Get_config_template); + + SvcLogicContext ctx = null; + System.out.println("*************************TRACE 1*****************************"); + cca.configure(key, parameters, ctx); + } + +} + diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/DebugLog.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/DebugLog.java new file mode 100644 index 000000000..307db639a --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/DebugLog.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.io.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + + +public class DebugLog +{ + private static String fileName = "/tmp/rt.log"; + + public static void main (String args[]) + { + DebugLog debugLog = new DebugLog(); + debugLog.printAriDebug("DebugLog", "The Message"); + } + + public static void printAriDebug(String fn, String messg) + { + String logMessg = getDateTime() +" " +fn +" " + messg; + appendToFile(logMessg +"\n"); + + } + + public static void printRTAriDebug(String fn, String messg) + { + // System.out.println (getDateTime() +" " +fn +" " + messg); + String logMessg = getDateTime() +" " +fn +" " + messg; + appendToFile(logMessg +"\n"); + } + public static String getDateTime() + { + DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + // DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + Date date = new Date(); + return dateFormat.format(date); + } + + public static void appendToFile (String dataToWrite) + { + String fn = "DebugLog.appendToFile"; + try + { + // First check to see if a file 'fileName' exist, if it does + // write to it. If it does not exist, don't write to it. + File tmpFile = new File(fileName); + if (tmpFile.exists()) + { + BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); + out.write(dataToWrite); + out.close(); + } + } + catch (IOException e) + { + DebugLog.printRTAriDebug (fn, "writeToFile() exception: " + e); + //System.err.println("writeToFile() exception: " + e); + e.printStackTrace(); + } + } + + public void outputStackTrace(Exception e) + { + String fn = "DebugLog.outputStackTrace"; + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + DebugLog.printRTAriDebug(fn, "Stack trace::: "+stackTrace); + } + + public static String getStackTraceString(Exception e) + { + String fn = "DebugLog.outputStackTrace"; + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + String stackTrace = sw.toString(); + return(stackTrace); + } + +} + diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/EncryptionTool.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/EncryptionTool.java new file mode 100644 index 000000000..8555c29fe --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/EncryptionTool.java @@ -0,0 +1,214 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.security.Provider; +import java.security.Provider.Service; +import java.security.Security; + +import javax.crypto.Cipher; + +import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64; +import org.jasypt.util.text.BasicTextEncryptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class is used to encapsulate the encryption and decryption support in one place and to provide a utility to + * encrypt and decrypt data. + */ +public class EncryptionTool { + + /** + * This lock object is used ONLY if the singleton has not been set up. + */ + private static final Object lock = new Object(); + + /** + * The salt is used to initialize the PBE (password Based Encrpytion) algorithm. + */ + private static final byte[] DEFAULT_SALT = { + (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 + }; + + /** + * The prefix we insert onto any data we encrypt so that we can tell if it is encrpyted later and therefore decrypt + * it + */ + @SuppressWarnings("nls") + public static final String ENCRYPTED_VALUE_PREFIX = "enc:"; + + /** + * The instance of the encryption utility object + */ + private static EncryptionTool instance = null; + + /** + * The iteration count used to initialize the PBE algorithm and to generate the key spec + */ + private static final int ITERATION_COUNT = 20; + + /** + * The logger for this class. + */ + private static final Logger LOG = LoggerFactory.getLogger(EncryptionTool.class); + + /** + * The secret passphrase (PBE) that we use to perform encryption and decryption. The algorithm we are using is a + * symmetrical cipher. + */ + private static char[] secret = { + 'C', '_', 'z', 'l', '!', 'K', '!', '4', '?', 'O', 'z', 'E', 'K', 'E', '>', 'U', 'R', '/', '%', 'Y', '\\', 'f', + 'b', '"', 'e', 'n', '{', '"', 'l', 'U', 'F', '+', 'E', '\'', 'R', 'T', 'p', '1', 'V', '4', 'l', 'a', '9', 'w', + 'v', '5', 'Z', '#', 'i', 'V', '"', 'd', 'l', '!', 'L', 'M', 'g', 'L', 'Q', '{', 'v', 'v', 'K', 'V' + }; + + /** + * The algorithm to encrypt and decrpyt data is "Password (or passphrase) Based Encryption with Message Digest #5 + * and the Data Encryption Standard", i.e., PBEWithMD5AndDES. + */ + @SuppressWarnings("nls") + private static final String SECURITY_ALGORITHM = "PBEWITHMD5AND256BITAES";// "PBEWithMD5AndDES"; + + /** + * The decryption cipher object + */ + private Cipher decryptCipher = null; + + /** + * The encryption cipher object + */ + private Cipher encryptCipher = null; + + private BasicTextEncryptor encryptor; + + /** + * Get an instance of the EncryptionTool + * + * @return The encryption tool to be used + */ + public static final EncryptionTool getInstance() { + if (instance == null) { + synchronized (lock) { + if (instance == null) { + instance = new EncryptionTool(); + } + } + } + return instance; + } + + /** + * Create the EncryptionTool instance + */ + @SuppressWarnings("nls") + private EncryptionTool() { + // encryptor = new BasicTextEncryptor(); + // encryptor.setPassword(secret.toString()); + String out = "Found the following security algorithms:"; + for (Provider p : Security.getProviders()) { + for (Service s : p.getServices()) { + String algo = s.getAlgorithm(); + out += + String.format("\n -Algorithm [ %s ] in provider [ %s ] and service [ %s ]", algo, p.getName(), + s.getClassName()); + } + } + LOG.debug(out); + } + + /** + * Decrypt the provided encrypted text + * + * @param cipherText + * THe cipher text to be decrypted. If the ciphertext is not encrypted, then it is returned as is. + * @return the clear test of the (possibly) encrypted value. The original value if the string is not encrypted. + */ + @SuppressWarnings("nls") + public synchronized String decrypt(String cipherText) { + if (isEncrypted(cipherText)) { + String encValue = cipherText.substring(ENCRYPTED_VALUE_PREFIX.length()); + // return encryptor.decrypt(encValue); + byte[] plainByte = Base64.decodeBase64(encValue.getBytes()); + byte[] decryptByte = xorWithSecret(plainByte); + return new String(decryptByte); + } else { + return cipherText; + } + + } + + /** + * Encrypt the provided clear text + * + * @param clearText + * The clear text to be encrypted + * @return the encrypted text. If the clear text is empty (null or zero length), then an empty string is returned. + * If the clear text is already encrypted, it is not encrypted again and is returned as is. Otherwise, the + * clear text is encrypted and returned. + */ + @SuppressWarnings("nls") + public synchronized String encrypt(String clearText) { + if (clearText != null) { + byte[] encByte = xorWithSecret(clearText.getBytes()); + String encryptedValue = new String(Base64.encodeBase64(encByte)); + return ENCRYPTED_VALUE_PREFIX + encryptedValue; + } else { + return null; + } + } + + /** + * Is a value encrypted? A value is considered to be encrypted if it begins with the + * {@linkplain #ENCRYPTED_VALUE_PREFIX encrypted value prefix}. + * + * @param value + * the value to check. + * @return true/false; + */ + private static boolean isEncrypted(final String value) { + return value != null && value.startsWith(ENCRYPTED_VALUE_PREFIX); + } + + /** + * XORs the input byte array with the secret key, padding 0x0 to the end of the secret key if the input is longer + * and returns a byte array the same size as input + * + * @param inp + * The byte array to be XORed with secret + * @return A byte array the same size as inp or null if input is null. + */ + private byte[] xorWithSecret(byte[] inp) { + if (inp == null) { + return null; + } + + byte[] secretBytes = new String(secret).getBytes(); + int size = inp.length; + + byte[] out = new byte[size]; + for (int i = 0; i < size; i++) { + out[i] = (byte) ((inp[i]) ^ (secretBytes[i % secretBytes.length])); + } + return out; + } + +} diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/SshJcraftWrapper.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/SshJcraftWrapper.java new file mode 100644 index 000000000..ea98baed8 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/SshJcraftWrapper.java @@ -0,0 +1,1243 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.*; +import java.util.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import com.jcraft.jsch.*; + +public class SshJcraftWrapper +{ + private String debugLogFileName = "/tmp/sshJcraftWrapperDebug"; + InputStream inputStream = null; + OutputStream outputStream = null; + private TelnetListener listener = null; + private String routerLogFileName = null; + DebugLog debugLog = new DebugLog(); + private String host = null; + private String RouterName = null; + private int BUFFER_SIZE = 512000; + // private int BUFFER_SIZE = 4000000; + private DataInputStream dis = null; + private BufferedReader reader = null; + char[] charBuffer = new char[BUFFER_SIZE]; + private BufferedWriter out = null; + private File _tmpFile = null; + private JSch jsch = null; + private Session session = null; + private Channel channel = null; + private String tId = ""; + private String aggregatedReceivedString = ""; + private File extraDebugFile = new File("/tmp/sshJcraftWrapperDEBUG"); + private String routerCmdType = "XML"; + private String routerFileName = null; + private File jcraftReadSwConfigFileFromDisk = new File("/tmp/jcraftReadSwConfigFileFromDisk"); + private String equipNameCode = null; + private String hostName = null; + private String userName = null; + private String passWord = null; + private StringBuffer charactersFromBufferFlush = new StringBuffer(); + private Runtime runtime = Runtime.getRuntime(); + private DebugLog dbLog = new DebugLog(); + + public void SshJcraftWrapper() + { + String fn = "SshJcraftWrapper.SshJcraftWrapper"; + debugLog.printRTAriDebug (fn, "SshJcraftWrapper has been instantated"); + routerLogFileName = "/tmp/" +host; + this.host = host; + } + + public void connect (String hostname, String username, String password, String prompt, int timeOut) throws IOException + { + String fn = "SshJcraftWrapper.connect"; + jsch = new JSch(); + debugLog.printRTAriDebug (fn, "Attempting to connect to "+hostname +" username="+username + + " password="+password + " prompt='"+prompt +"' timeOut="+timeOut); + debugLog.printRTAriDebug (fn, "Trace A"); + RouterName = hostname; + hostName = hostname; + userName = username; + passWord = password; + try + { + session = jsch.getSession(username, hostname, 22); + UserInfo ui = new MyUserInfo(); + session.setPassword(password); + session.setUserInfo(ui); + session.connect(timeOut); + channel = session.openChannel("shell"); + session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!! + ((ChannelShell)channel).setPtyType("vt102"); + inputStream = channel.getInputStream(); + dis = new DataInputStream(inputStream); + reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE); + channel.connect(); + debugLog.printRTAriDebug (fn, "Successfully connected."); + debugLog.printRTAriDebug (fn, "Flushing input buffer"); + try + { + receiveUntil(prompt, 3000, "No cmd was sent, just waiting"); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception: Nothing to flush out."); + } + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception. e="+e); + throw new IOException(e.toString()); + } + } + + // User specifies the port number. + public void connect (String hostname, String username, String password, String prompt, int timeOut, int portNum) throws IOException + { + String fn = "SshJcraftWrapper.connect"; + debugLog.printRTAriDebug (fn, ":Attempting to connect to "+hostname +" username="+username + + " password="+password + " prompt='"+prompt +"' timeOut="+timeOut +" portNum="+portNum); + RouterName = hostname; + hostName = hostname; + userName = username; + passWord = password; + RouterName = hostname; + jsch = new JSch(); + try + { + session = jsch.getSession(username, hostname, portNum); + UserInfo ui = new MyUserInfo(); + session.setPassword(password); + session.setUserInfo(ui); + session.setConfig("StrictHostKeyChecking", "no"); + debugLog.printRTAriDebug (fn, ":StrictHostKeyChecking set to 'no'"); + + session.connect(timeOut); + session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!! + channel = session.openChannel("shell"); + ((ChannelShell)channel).setPtyType("vt102"); + inputStream = channel.getInputStream(); + dis = new DataInputStream(inputStream); + reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE); + channel.connect(); + debugLog.printRTAriDebug (fn, ":Successfully connected."); + debugLog.printRTAriDebug (fn, ":Flushing input buffer"); + try + { + if (prompt.equals("]]>]]>")) + receiveUntil("]]>]]>", 10000, "No cmd was sent, just waiting"); + else + receiveUntil(":~#", 5000, "No cmd was sent, just waiting"); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception::: Nothing to flush out."); + } + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, ":Caught an Exception. e="+e); + dbLog.outputStackTrace(e); + + throw new IOException(e.toString()); + } + } + + + public String receiveUntil (String delimeters, int timeout, String cmdThatWasSent) throws TimedOutException, IOException + { + String fn = "SshJcraftWrapper.receiveUntil"; + boolean match = false; + boolean cliPromptCmd = false; + StringBuffer sb2 = new StringBuffer(); + StringBuffer sbReceive = new StringBuffer(); + debugLog.printRTAriDebug (fn, "delimeters='"+delimeters +"' timeout="+timeout +" cmdThatWasSent='"+cmdThatWasSent +"'"); + appendToFile(debugLogFileName, fn +" delimeters='"+delimeters +"' timeout="+timeout +" cmdThatWasSent='"+cmdThatWasSent +"'\n"); + String CmdThatWasSent = removeWhiteSpaceAndNewLineCharactersAroundString(cmdThatWasSent); + int readCounts = 0; + aggregatedReceivedString = ""; + + long deadline = new Date().getTime() + timeout; + try + { + session.setTimeout(timeout); // This is the socket timeout value. + while (!match) + { + if(new Date().getTime() > deadline) + { + debugLog.printRTAriDebug (fn, "Throwing a TimedOutException: time in routine has exceed our deadline: RouterName:"+ + RouterName +" CmdThatWasSent="+ CmdThatWasSent); + throw new TimedOutException("Timeout: time in routine has exceed our deadline"); + } + try + { + Thread.sleep(500); + } + catch (java.lang.InterruptedException ee) + { + boolean ignore = true; + } + int len = reader.read(charBuffer, 0, BUFFER_SIZE); + appendToFile(debugLogFileName, fn +" After reader.read cmd: len="+len +"\n"); + if (len <= 0) + { + debugLog.printRTAriDebug (fn, "Reader read "+len +" bytes. Looks like we timed out, router="+RouterName); + throw new TimedOutException ("Received a SocketTimeoutException router="+RouterName); + } + if (!cliPromptCmd) + { + if (cmdThatWasSent.indexOf("IOS_XR_uploadedSwConfigCmd") != -1) + { + if (out == null) + { + // This is a IOS XR sw config file. We will write it to the disk. + timeout = timeout * 2; + deadline = new Date().getTime() + timeout; + debugLog.printRTAriDebug (fn, "IOS XR upload for software config: timeout="+timeout); + StringTokenizer st = new StringTokenizer(cmdThatWasSent); + st.nextToken(); + routerFileName = st.nextToken(); + out = new BufferedWriter(new FileWriter(routerFileName)); + routerLogFileName = "/tmp/"+RouterName; + _tmpFile = new File(routerLogFileName); + debugLog.printRTAriDebug (fn, "Will write the swConfigFile to disk, routerFileName="+routerFileName); + } + int c; + out.write(charBuffer, 0, len); + out.flush(); + appendToFile(debugLogFileName, fn +" Wrote "+len +" bytes to the disk\n"); + if (_tmpFile.exists()) + appendToRouterFile(routerLogFileName, len); + match = checkIfReceivedStringMatchesDelimeter(len, "\nXML>"); + if (match == true) + { + out.flush(); + out.close(); + out = null; + return null; + } + } + else + { + readCounts ++; + appendToFile(debugLogFileName, fn +" readCounts="+readCounts +" Reader read "+len +" of data\n"); + int c; + sb2.setLength(0); + for(int i=0; i<len; i++ ) + { + c = charBuffer[i]; + if ((c != 7) && (c != 13) && (c != 0) && (c != 27)) + { + sbReceive.append((char)charBuffer[i]); + sb2.append((char)charBuffer[i]); + } + } + appendToRouterFile("/tmp/"+RouterName, len); + if (listener != null) + listener.receivedString(sb2.toString()); + + appendToFile(debugLogFileName, fn +" Trace 1\n"); + match = checkIfReceivedStringMatchesDelimeter(delimeters, sb2.toString(), cmdThatWasSent); + appendToFile(debugLogFileName, fn +" Trace 2\n"); + if (match == true) + { + appendToFile(debugLogFileName, fn +" Match was true, breaking...\n"); + break; + } + } + } + else + { + debugLog.printRTAriDebug (fn, "cliPromptCmd, Trace 2"); + sb2.setLength(0); + for(int i=0; i<len; i++ ) + { + sbReceive.append( (char)charBuffer[i] ); + sb2.append( (char)charBuffer[i] ); + } + appendToRouterFile("/tmp/"+RouterName, sb2); + if (listener != null) + listener.receivedString(sb2.toString()); + debugLog.printRTAriDebug (fn, "sb2='"+sb2.toString() +"' delimeters='" +delimeters +"'"); + if (sb2.toString().indexOf("\nariPrompt>") != -1) + { + debugLog.printRTAriDebug (fn, "Found our prompt"); + match = true; + break; + } + } + } + } + catch (JSchException e) + { + debugLog.printRTAriDebug (fn, "Caught an JSchException e="+e.toString()); + dbLog.outputStackTrace(e); + throw new TimedOutException (e.toString()); + } + catch (IOException ee) + { + debugLog.printRTAriDebug (fn, "Caught an IOException: ee="+ee.toString()); + dbLog.outputStackTrace(ee); + throw new TimedOutException (ee.toString()); + } + String result = stripOffCmdFromRouterResponse(sbReceive.toString()); + debugLog.printRTAriDebug (fn, "Leaving method successfully"); + return (result); + } + + public boolean checkIfReceivedStringMatchesDelimeter(String delimeters, String receivedString, String cmdThatWasSent) + { + // The delimeters are in a '|' seperated string. Return true on the first match. + String fn = "SshJcraftWrapper.checkIfReceivedStringMatchesDelimeter"; + appendToFile(debugLogFileName, fn +" Entered: delimeters='"+delimeters +" cmdThatWasSent='"+cmdThatWasSent +"' receivedString='"+receivedString +"'\n"); + StringTokenizer st = new StringTokenizer(delimeters, "|"); + + if ((delimeters.indexOf("#$") != -1) || (routerCmdType.equals("CLI"))) // This would be an IOS XR, CLI command. + { + int x = receivedString.lastIndexOf("#"); + int y = receivedString.length() - 1; + appendToFile(debugLogFileName, fn +" IOS XR, CLI command\n"); + if (extraDebugFile.exists()) + appendToFile(debugLogFileName, fn +" :::cmdThatWasSent='"+cmdThatWasSent +"' x="+x +" y="+y +"\n"); + if ((x != -1) && (y == x)) + return(true); + else + return(false); + } + if (cmdThatWasSent.indexOf("show config") != -1) + { + appendToFile(debugLogFileName, fn +"In the block for 'show config'\n"); + while (st.hasMoreTokens()) + { + String delimeter = st.nextToken(); + // Make sure we don't get faked out by a response of " #". + // Proc #0 + // # signaling-local-address ipv6 FD00:F4D5:EA06:1::110:136:254 + // LAAR2# + int x = receivedString.lastIndexOf(delimeter); + if ((receivedString.lastIndexOf(delimeter) != -1) && (receivedString.lastIndexOf(" #") != x-1)) + { + appendToFile(debugLogFileName, fn +"receivedString=\n'" +receivedString +"'\n"); + appendToFile(debugLogFileName, fn +"Returning true for the 'show config' command. We found our real delmeter. \n\n"); + return (true); + } + } + } + else + { + aggregatedReceivedString = aggregatedReceivedString + receivedString; + _appendToFile ("/tmp/aggregatedReceivedString.debug", aggregatedReceivedString); + + while (st.hasMoreTokens()) + { + String delimeter = st.nextToken(); + appendToFile(debugLogFileName, fn +" Looking for an delimeter of:'"+delimeter+"'\n"); + appendToFile(debugLogFileName, fn +" receivedString='"+receivedString); + if (aggregatedReceivedString.indexOf(delimeter) != -1) + { + debugLog.printRTAriDebug (fn, "Found our delimeter, which was: '"+delimeter +"'"); + aggregatedReceivedString = ""; + return (true); + } + } + } + return (false); + } + + public boolean checkIfReceivedStringMatchesDelimeter(int len, String delimeter) + { + String fnName = "SshJcraftWrapper.checkIfReceivedStringMatchesDelimeter:::"; + int x; + int c; + String str = null; + + if (jcraftReadSwConfigFileFromDisk()) + { + DebugLog.printAriDebug(fnName, "jcraftReadSwConfigFileFromDisk block"); + File fileName = new File(routerFileName); + appendToFile(debugLogFileName, fnName +" jcraftReadSwConfigFileFromDisk::: Will read the tail end of the file from the disk"); + try + { + str = getLastFewLinesOfFile(fileName, 3); + } + catch (IOException e) + { + DebugLog.printAriDebug(fnName, "Caught an Exception, e="+e); + dbLog.outputStackTrace(e); + e.printStackTrace(); + } + } + else + { + // DebugLog.printAriDebug(fnName, "TRACE 1: ******************************"); + // When looking at the end of the charBuffer, don't include any linefeeds or spaces. We only want to make the smallest string possible. + for(x=len-1; x>=0; x--) + { + c = charBuffer[x]; + if (extraDebugFile.exists()) + appendToFile(debugLogFileName, fnName +" x="+x +" c="+c +"\n"); + if ((c != 10) && (c != 32)) // Not a line feed nor a space. + break; + } + if ((x+1 - 13) >= 0) + { + str = new String (charBuffer, (x+1-13), 13); + appendToFile(debugLogFileName, fnName +" str:'"+str +"'\n"); + } + else + { + File fileName = new File(routerFileName); + appendToFile(debugLogFileName, fnName +" Will read the tail end of the file from the disk, x="+x + + " len="+len +" str::'"+str +"' routerFileName='" +routerFileName +"'\n"); + DebugLog.printAriDebug(fnName, "Will read the tail end of the file from the disk, x="+x +" len=" + +len +" str::'"+str +"' routerFileName='" +routerFileName +"'"); + try + { + str = getLastFewLinesOfFile(fileName, 3); + } + catch (IOException e) + { + DebugLog.printAriDebug(fnName, "Caught an Exception, e="+e); + dbLog.outputStackTrace(e); + e.printStackTrace(); + } + } + } + + if (str.indexOf(delimeter) != -1) + { + DebugLog.printAriDebug(fnName, "str in break is:'"+str +"'" +" delimeter='" +delimeter +"'"); + appendToFile(debugLogFileName, fnName +" str in break is:'"+str +" delimeter='" +delimeter +"'" +"'\n"); + return(true); + } + else + { + appendToFile(debugLogFileName, fnName +" Returning false"); + return(false); + } + + } + + public void closeConnection() + { + String fn = "SshJcraftWrapper.closeConnection"; + debugLog.printRTAriDebug (fn, "Executing the closeConnection...."); + inputStream = null; + outputStream = null; + dis = null; + charBuffer = null; + session.disconnect(); + session = null; + } + + public void send (String cmd) throws IOException + { + String fn = "SshJcraftWrapper.send"; + OutputStream out = channel.getOutputStream(); + DataOutputStream dos = new DataOutputStream(out); + + if ((cmd.charAt(cmd.length() - 1) != '\n') && (cmd.charAt(cmd.length() - 1) != '\r')) + cmd += "\n"; + int length = cmd.length(); + int i = -1; + int nchars = 300000; + int ncharsTotalSent = 0; + int ncharsSent = 0; + + appendToFile(debugLogFileName, fn+": Sending: '"+cmd ); + debugLog.printRTAriDebug (fn, "Length of cmd is:" +length); // 2,937,706 + try + { + if (length > 600000) + { + int timeout = 9000; + for (i=0; i<length; i+=nchars) + { + String Cmd = cmd.substring(i, Math.min(length, i + nchars)); + ncharsSent = Cmd.length(); + ncharsTotalSent = ncharsTotalSent + Cmd.length(); + debugLog.printRTAriDebug (fn, "i="+i +" Sending Cmd: ncharsSent="+ncharsSent); + dos.writeBytes(Cmd); + dos.flush(); + try + { + debugLog.printRTAriDebug (fn, ":::i="+i +" length="+length); + if (ncharsSent < length) + receiveUntilBufferFlush (ncharsSent, timeout, "buffer flush i="+i); + else + { + debugLog.printRTAriDebug (fn, "i="+i +" No Waiting this time...."); + dos.flush(); + } + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception: Nothing to flush out."); + } + } + } + else + { + debugLog.printRTAriDebug (fn, "Before executing the dos.writeBytes"); + dos.writeBytes(cmd); + } + dos.flush(); + debugLog.printRTAriDebug (fn, "Leaving method"); + appendToFile(debugLogFileName, fn+": Leaving method\n"); + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException. e="+e); + dbLog.outputStackTrace(e); + throw new IOException(e.toString()); + } + } + + + public void sendChar (int v) throws IOException + { + String fn = "SshJcraftWrapper.sendChar"; + OutputStream out = channel.getOutputStream(); + DataOutputStream dos = new DataOutputStream(out); + try + { + debugLog.printRTAriDebug (fn, "Sending: '" +v +"'"); + dos.writeChar (v); + dos.flush(); + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException. e="+e); + throw new IOException(e.toString()); + } + } + + public void send (byte[] b, int off, int len) throws IOException + { + String fn = "SshJcraftWrapper.send:byte[]"; + OutputStream out = channel.getOutputStream(); + DataOutputStream dos = new DataOutputStream(out); + try + { + dos.write (b, off, len); + dos.flush(); + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException. e="+e); + throw new IOException(e.toString()); + } + } + + public static class MyUserInfo implements UserInfo, UIKeyboardInteractive + { + public String getPassword() + { + return null; + } + public boolean promptYesNo(String str) + { + return false; + } + public String getPassphrase() + { + return null; + } + public boolean promptPassphrase(String message) + { + return false; + } + public boolean promptPassword(String message) + { + return false; + } + public void showMessage(String message) + { } + public String[] promptKeyboardInteractive(String destination, + String name, + String instruction, + String[] prompt, + boolean[] echo) + { + return null; + } + } + + public void addListener(TelnetListener listener) + { + this.listener = listener; + } + + public void appendToFile (String fileName, String dataToWrite) + { + String fn = "SshJcraftWrapper.appendToFile"; + + try + { + // First check to see if a file 'fileName' exist, if it does + // write to it. If it does not exist, don't write to it. + File tmpFile = new File(fileName); + if (tmpFile.exists()) + { + BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); + out.write(getTheDate() +": " +tId +": "+dataToWrite); + out.close(); + } + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException: e="+e); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception: e="+e); + } + } + + public void _appendToFile (String fileName, String dataToWrite) + { + String fn = "SshJcraftWrapper.appendToFile"; + + try + { + // First check to see if a file 'fileName' exist, if it does + // write to it. If it does not exist, don't write to it. + File tmpFile = new File(fileName); + if (tmpFile.exists()) + { + BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); + out.write(dataToWrite); + out.close(); + } + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException: e="+e); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception: e="+e); + } + } + + + public String getTheDate() + { + Calendar cal = Calendar.getInstance(); + java.util.Date today = cal.getTime(); + DateFormat df1 = DateFormat.getDateInstance(); + DateFormat df3 = new SimpleDateFormat("MM/dd/yyyy H:mm:ss "); + return (df3.format(today)); + } + + + public void appendToRouterFile (String fileName, StringBuffer dataToWrite) + { + String fnName = "SshJcraftWrapper.appendToRouterFile"; + debugLog.printRTAriDebug (fnName, "Entered.... "); + try + { + // First check to see if a file 'fileName' exist, if it does + // write to it. If it does not exist, don't write to it. + File tmpFile = new File(fileName); + { + // if ((tmpFile.exists()) && (tmpFile.setWritable(true, true))) + if (tmpFile.exists()) + { + BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); + out.write(dataToWrite.toString()); + out.close(); + } + } + } + catch (IOException e) + { + System.err.println("writeToFile() exception: " + e); + e.printStackTrace(); + } + } + + public void appendToRouterFile (String fileName, int len) + { + String fnName = "SshJcraftWrapper.appendToFile"; + try + { + // First check to see if a file 'fileName' exist, if it does + // write to it. If it does not exist, don't write to it. + File tmpFile = new File(fileName); + // if ((tmpFile.exists()) && (tmpFile.setWritable(true, true))) + if (tmpFile.exists()) + { + BufferedWriter out = new BufferedWriter(new FileWriter(fileName, true)); + out.write(charBuffer, 0, len); + out.close(); + } + } + catch (IOException e) + { + System.err.println("writeToFile() exception: " + e); + e.printStackTrace(); + } + } + + public String removeWhiteSpaceAndNewLineCharactersAroundString(String str) + { + if (str != null) + { + StringTokenizer strTok = new StringTokenizer(str, "\n"); + StringBuffer sb = new StringBuffer(); + + while (strTok.hasMoreTokens()) + { + String line = strTok.nextToken(); + sb.append(line); + } + return (sb.toString().trim()); + } + else + return(str); + } + + public String stripOffCmdFromRouterResponse(String routerResponse) + { + String fn = "SshJcraftWrapper.stripOffCmdFromRouterResponse"; + // appendToFile(debugLogFileName, fn+": routerResponse='"+routerResponse +"'\n"); + + // The session of SSH will echo the command sent to the router, in the router's response. + // Since all our commands are terminated by a '\n', strip off the first line + // of the response from the router. This first line contains the orginal command. + + StringTokenizer rr = new StringTokenizer(routerResponse, "\n"); + StringBuffer sb = new StringBuffer(); + + int numTokens = rr.countTokens(); + if (numTokens > 1) + { + rr.nextToken(); //Skip the first line. + while (rr.hasMoreTokens()) + { + sb.append(rr.nextToken()+'\n'); + } + } + return (sb.toString()); + } + + public void setRouterCommandType(String type) + { + String fn = "SshJcraftWrapper.setRouterCommandType"; + this.routerCmdType = type; + debugLog.printRTAriDebug (fn, "Setting routerCmdType to a value of '"+type +"'"); + } + + public String getLastFewLinesOfFile(File file, int linesToRead) throws FileNotFoundException, IOException + { + String fn = "SshJcraftWrapper.getLastFewLinesOfFile"; + RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); + int lines = 0; + StringBuilder builder = new StringBuilder(); + String tail = ""; + long length = file.length(); + length--; + randomAccessFile.seek(length); + for(long seek = length; seek >= 0; --seek) + { + randomAccessFile.seek(seek); + char c = (char)randomAccessFile.read(); + builder.append(c); + if(c == '\n') + { + builder = builder.reverse(); + tail = builder.toString() + tail; + lines++; + builder.setLength(0); + if (lines == linesToRead) + { + break; + } + } + } + randomAccessFile.close(); + if(!jcraftReadSwConfigFileFromDisk()) + debugLog.printRTAriDebug (fn, "tail='"+tail +"'"); + appendToFile(debugLogFileName, "tail='"+tail +"'\n"); + return tail; + } + + public boolean jcraftReadSwConfigFileFromDisk() + { + if (jcraftReadSwConfigFileFromDisk.exists()) + return(true); + else + return(false); + } + + public String getEquipNameCode() + { + return (equipNameCode); + } + + public void setEquipNameCode(String equipNameCode) + { + this.equipNameCode = equipNameCode; + } + + public String getRouterName() + { + return(RouterName); + } + + // Routine does reads until it has read 'nchars' or times out. + public void receiveUntilBufferFlush (int ncharsSent, int timeout, String message) throws TimedOutException, IOException + { + String fn = "SshJcraftWrapper.receiveUntilBufferFlush"; + StringBuffer sb2 = new StringBuffer(); + StringBuffer sbReceive = new StringBuffer(); + debugLog.printRTAriDebug (fn, "ncharsSent="+ncharsSent+" timeout="+timeout +" "+message); + int ncharsTotalReceived = 0; + int ncharsRead = 0; + boolean flag = false; + charactersFromBufferFlush.setLength(0); + + long deadline = new Date().getTime() + timeout; + logMemoryUsage(); + try + { + session.setTimeout(timeout); // This is the socket timeout value. + while (true) + { + if(new Date().getTime() > deadline) + { + debugLog.printRTAriDebug (fn, "Throwing a TimedOutException: time in routine has exceed our deadline: ncharsSent=" + +ncharsSent+" ncharsTotalReceived="+ncharsTotalReceived); + flag = true; + throw new TimedOutException("Timeout: time in routine has exceed our deadline"); + } + ncharsRead = reader.read(charBuffer, 0, BUFFER_SIZE); + if (listener != null) + listener.receivedString(String.copyValueOf(charBuffer,0,ncharsRead)); + appendToRouterFile("/tmp/"+RouterName, ncharsRead); + ncharsTotalReceived = ncharsTotalReceived + ncharsRead; + if (ncharsTotalReceived >= ncharsSent) + { + debugLog.printRTAriDebug (fn, "Received the correct number of characters, ncharsSent=" + +ncharsSent +" ncharsTotalReceived="+ncharsTotalReceived); + logMemoryUsage(); + return; + } + } + } + catch (JSchException e) + { + debugLog.printRTAriDebug (fn, "Caught an JSchException e="+e.toString()); + debugLog.printRTAriDebug (fn, "ncharsSent="+ncharsSent+" ncharsTotalReceived="+ncharsTotalReceived +" ncharsRead="+ncharsRead); + throw new TimedOutException (e.toString()); + } + } + + public String getHostName() + { + return(hostName); + } + + public String getUserName() + { + return(userName); + } + + public String getPassWord() + { + return(passWord); + } + + public void sftpPut(String sourcePath, String destDirectory) throws IOException + { + String fn = "SshJcraftWrapper.sftp"; + try + { + Session sftpSession = jsch.getSession(userName, hostName, 22); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + debugLog.printRTAriDebug (fn, "Sending "+sourcePath +" --> "+destDirectory); + sftp.put(sourcePath, destDirectory, ChannelSftp.OVERWRITE); + debugLog.printRTAriDebug (fn, "Sent successfully"); + sftpSession.disconnect(); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + throw new IOException(e.toString()); + } + } + + + + public void SftpPut(String stringOfData, String fullPathDest) throws IOException + { + String fn = "SshJcraftWrapper.Sftp"; + try + { + Session sftpSession = jsch.getSession(userName, hostName, 22); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + InputStream is = new ByteArrayInputStream(stringOfData.getBytes()); + debugLog.printRTAriDebug (fn, "Sending stringOfData --> "+fullPathDest); + sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE); + debugLog.printRTAriDebug (fn, "Sent successfully"); + sftpSession.disconnect(); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + throw new IOException(e.toString()); + } + } + + public String sftpGet(String fullFilePathName) throws IOException + { + String fn = "SshJcraftWrapper.Sftp"; + try + { + Session sftpSession = jsch.getSession(userName, hostName, 22); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + InputStream in = null; + in = sftp.get(fullFilePathName); + String sftpFileString = readInputStreamAsString(in); + debugLog.printRTAriDebug (fn, "Retreived successfully"); + // debugLog.printRTAriDebug (fn, "sftpFileString="+sftpFileString); + sftpSession.disconnect(); + return(sftpFileString); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + // dbLog.storeData("ErrorMsg= sftp threw an Exception. error is:"+e); + throw new IOException(e.toString()); + } + } + + public static String readInputStreamAsString(InputStream in) throws IOException + { + BufferedInputStream bis = new BufferedInputStream(in); + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + int result = bis.read(); + while(result != -1) + { + byte b = (byte)result; + buf.write(b); + result = bis.read(); + } + return buf.toString(); + } + + + public void logMemoryUsage() + { + String fn = "SshJcraftWrapper.logMemoryUsage"; + int mb = 1024*1024; + long usedMemory; + long maxMemoryAdvailable; + long memoryLetfOnHeap; + maxMemoryAdvailable = (runtime.maxMemory() / mb); + usedMemory = ((runtime.totalMemory()/mb) - (runtime.freeMemory()/mb)); + memoryLetfOnHeap = maxMemoryAdvailable - usedMemory; + DebugLog.printAriDebug(fn, "maxMemoryAdvailable="+maxMemoryAdvailable +" usedMemory="+usedMemory +" memoryLetfOnHeap="+memoryLetfOnHeap); + } + + + // User specifies the port number, and the subsystem + public void connect (String hostname, String username, String password, String prompt, int timeOut, int portNum, String subsystem) throws IOException + { + String fn = "SshJcraftWrapper.connect"; + + debugLog.printRTAriDebug (fn, ":::Attempting to connect to "+hostname +" username="+username +" password="+password + " prompt='"+prompt +"' timeOut="+timeOut +" portNum="+portNum +" subsystem="+subsystem); + RouterName = hostname; + jsch = new JSch(); + try + { + session = jsch.getSession(username, hostname, portNum); + UserInfo ui = new MyUserInfo(); + session.setPassword(password); + session.setUserInfo(ui); + session.setConfig("StrictHostKeyChecking", "no"); + session.connect(timeOut); + session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!! + channel = session.openChannel("subsystem"); + ((ChannelSubsystem)channel).setSubsystem(subsystem); + ((ChannelSubsystem)channel).setPty(true); + + inputStream = channel.getInputStream(); + dis = new DataInputStream(inputStream); + reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE); + channel.connect(); + debugLog.printRTAriDebug (fn, "Successfully connected."); + debugLog.printRTAriDebug (fn, "Five second sleep...."); + try { Thread.sleep(5000); } catch (java.lang.InterruptedException ee) { boolean ignore = true; } + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception. e="+e); + throw new IOException(e.toString()); + } + } + + public void connect (String hostName, String username, String password, int portNumber) throws IOException + { + String fn = "SshJcraftWrapper.connect"; + jsch = new JSch(); + debugLog.printRTAriDebug (fn, "::Attempting to connect to "+hostName +" username="+username +" password="+password +" portNumber="+portNumber); + debugLog.printRTAriDebug (fn, "Trace C"); + RouterName = hostName; + this.hostName = hostName; + userName = username; + passWord = password; + try + { + java.util.Properties config = new java.util.Properties(); + config.put("StrictHostKeyChecking", "no"); + session = jsch.getSession(username, hostName, 22); + UserInfo ui = new MyUserInfo(); + session.setConfig(config); + session.setPassword(password); + session.setUserInfo(ui); + session.connect(30000); + channel = session.openChannel("shell"); + session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!! + ((ChannelShell)channel).setPtyType("vt102"); + inputStream = channel.getInputStream(); + dis = new DataInputStream(inputStream); + reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE); + channel.connect(); + debugLog.printRTAriDebug (fn, "::Successfully connected."); + debugLog.printRTAriDebug (fn, "::Flushing input buffer"); + try + { + receiveUntil(":~#", 9000, "No cmd was sent, just waiting, but we can stop on a '~#'"); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception::: Nothing to flush out."); + } + + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception. e="+e); + throw new IOException(e.toString()); + } + } + + + public void put(String sourcePath, String destDirectory) throws IOException + { + String fn = "SshJcraftWrapper.sftp"; + try + { + Session sftpSession = jsch.getSession(userName, hostName, 22); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + debugLog.printRTAriDebug (fn, "Sending "+sourcePath +" --> "+destDirectory); + sftp.put(sourcePath, destDirectory, ChannelSftp.OVERWRITE); + debugLog.printRTAriDebug (fn, "Sent successfully"); + sftpSession.disconnect(); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + throw new IOException(e.toString()); + } + } + + public void put(InputStream is, String fullPathDest, String hostName, String userName, String passWord) throws IOException + { + String fn = "SshJcraftWrapper.put"; + Session sftpSession = null; + try + { + debugLog.printRTAriDebug (fn, "userName="+userName +" hostName="+hostName +" passWord="+passWord); + jsch = new JSch(); + java.util.Properties config = new java.util.Properties(); + config.put("StrictHostKeyChecking", "no"); + sftpSession = jsch.getSession(userName, hostName, 22); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.setConfig(config); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + String oldFiles = fullPathDest +"*"; + debugLog.printRTAriDebug (fn, "Deleting old files --> "+oldFiles); + sftp.rm(oldFiles); + debugLog.printRTAriDebug (fn, "Sending stringOfData --> "+fullPathDest); + sftp.put(is, fullPathDest, ChannelSftp.OVERWRITE); + debugLog.printRTAriDebug (fn, "Sent successfully"); + sftpSession.disconnect(); + sftpSession = null; + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + sftpSession.disconnect(); + sftpSession = null; + // dbLog.storeData("ErrorMsg= sftp threw an Exception. error is:"+e); + throw new IOException(e.toString()); + } + } + + + public String get(String fullFilePathName, String hostName, String userName, String passWord) throws IOException + { + String fn = "SshJcraftWrapper.get"; + Session sftpSession = null; + try + { + debugLog.printRTAriDebug (fn, "userName="+userName +" hostName="+hostName +" passWord="+passWord); + jsch = new JSch(); + sftpSession = jsch.getSession(userName, hostName, 22); + java.util.Properties config = new java.util.Properties(); + config.put("StrictHostKeyChecking", "no"); + UserInfo ui = new MyUserInfo(); + sftpSession.setPassword(passWord); + sftpSession.setUserInfo(ui); + sftpSession.setConfig(config); + sftpSession.connect(30*1000); + debugLog.printRTAriDebug (fn, "Opening up an sftp channel...."); + ChannelSftp sftp=(ChannelSftp)sftpSession.openChannel("sftp"); + debugLog.printRTAriDebug (fn, "Connecting...."); + sftp.connect(); + InputStream in = null; + in = sftp.get(fullFilePathName); + String sftpFileString = readInputStreamAsString(in); + debugLog.printRTAriDebug (fn, "Retreived successfully"); + // debugLog.printRTAriDebug (fn, "sftpFileString="+sftpFileString); + sftpSession.disconnect(); + sftpSession = null; + return(sftpFileString); + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception, e="+e); + sftpSession.disconnect(); + sftpSession = null; + // dbLog.storeData("ErrorMsg= sftp threw an Exception. error is:"+e); + throw new IOException(e.toString()); + } + } + + public String send(String cmd, String delimiter) throws IOException + { + String fn = "SshJcraftWrapper.send"; + OutputStream out = channel.getOutputStream(); + DataOutputStream dos = new DataOutputStream(out); + + if ((cmd.charAt(cmd.length() - 1) != '\n') && (cmd.charAt(cmd.length() - 1) != '\r')) + cmd += "\n"; + int length = cmd.length(); + int i = -1; + int nchars = 300000; + int ncharsTotalSent = 0; + int ncharsSent = 0; + + debugLog.printRTAriDebug (fn, "Length of cmd is:" +length); // 2,937,706 + debugLog.printRTAriDebug (fn, "Length of cmd is:" +length); // 2,937,706 + try + { + if (length > 600000) + { + int timeout = 9000; + for (i=0; i<length; i+=nchars) + { + String Cmd = cmd.substring(i, Math.min(length, i + nchars)); + ncharsSent = Cmd.length(); + ncharsTotalSent = ncharsTotalSent + Cmd.length(); + debugLog.printRTAriDebug (fn, "i="+i +" Sending Cmd: ncharsSent="+ncharsSent); + dos.writeBytes(Cmd); + dos.flush(); + try + { + debugLog.printRTAriDebug (fn, ":::i="+i +" length="+length); + if (ncharsSent < length) + receiveUntilBufferFlush (ncharsSent, timeout, "buffer flush i="+i); + else + { + debugLog.printRTAriDebug (fn, "i="+i +" No Waiting this time...."); + dos.flush(); + } + } + catch (Exception e) + { + debugLog.printRTAriDebug (fn, "Caught an Exception: Nothing to flush out."); + } + } + } + else + { + debugLog.printRTAriDebug (fn, "Before executing the dos.writeBytes"); + dos.writeBytes(cmd); + } + dos.flush(); + // Now lets get the response. + String response = receiveUntil (delimiter, 300000, cmd); + debugLog.printRTAriDebug (fn, "Leaving method"); + return(response); + } + catch (IOException e) + { + debugLog.printRTAriDebug (fn, "Caught an IOException. e="+e); + throw new IOException(e.toString()); + } + } + +} diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TelnetListener.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TelnetListener.java new file mode 100644 index 000000000..e3f7138b0 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TelnetListener.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +public interface TelnetListener +{ + public void receivedString(String s); + public void filterStrings(String s1, String s2); +} + diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TimedOutException.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TimedOutException.java new file mode 100644 index 000000000..c0480f4fd --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/TimedOutException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.io.*; + +public class TimedOutException extends IOException +{ + public TimedOutException() + { + } + + public TimedOutException(String message) + { + super(message); + } +} + + diff --git a/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/XmlUtil.java b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/XmlUtil.java new file mode 100644 index 000000000..7cc1b57d7 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/java/org/openecomp/appc/ccadaptor/XmlUtil.java @@ -0,0 +1,163 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.ccadaptor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class XmlUtil +{ + + private static final Logger log = LoggerFactory.getLogger(XmlUtil.class); + + public static String getXml(Map<String, String> varmap, String var) + { + Object o = createStructure(varmap, var); + return generateXml(o, 0); + } + + private static Object createStructure(Map<String, String> flatmap, String var) + { + if (flatmap.containsKey(var)) + return flatmap.get(var); + + Map<String, Object> mm = new HashMap<>(); + for (String k : flatmap.keySet()) + if (k.startsWith(var + ".")) + { + int i1 = k.indexOf('.', var.length() + 1); + int i2 = k.indexOf('[', var.length() + 1); + int i3 = k.length(); + if (i1 > 0 && i1 < i3) + i3 = i1; + if (i2 > 0 && i2 < i3) + i3 = i2; + String k1 = k.substring(var.length() + 1, i3); + String var1 = k.substring(0, i3); + if (!mm.containsKey(k1)) + { + Object str = createStructure(flatmap, var1); + if (str != null && (!(str instanceof String) || ((String) str).trim().length() > 0)) + mm.put(k1, str); + } + } + if (!mm.isEmpty()) + return mm; + + boolean arrayFound = false; + for (String k : flatmap.keySet()) + if (k.startsWith(var + "[")) + { + arrayFound = true; + break; + } + + if (arrayFound) + { + List<Object> ll = new ArrayList<>(); + + int length = Integer.MAX_VALUE; + String lengthStr = flatmap.get(var + "_length"); + if (lengthStr != null) + { + try + { + length = Integer.parseInt(lengthStr); + } + catch (Exception e) + { + log.warn("Invalid number for " + var + "_length:" + lengthStr); + } + } + + for (int i = 0; i < length; i++) + { + Object v = createStructure(flatmap, var + '[' + i + ']'); + if (v == null) + break; + ll.add(v); + } + + if (!ll.isEmpty()) + return ll; + } + + return null; + } + + @SuppressWarnings("unchecked") + private static String generateXml(Object o, int indent) + { + if (o == null) + return null; + + if (o instanceof String) + return (String) o; + + if (o instanceof Map) + { + StringBuilder ss = new StringBuilder(); + Map<String, Object> mm = (Map<String, Object>) o; + for (String k : mm.keySet()) + { + Object v = mm.get(k); + if (v instanceof String) + { + ss.append(pad(indent)).append('<').append(k).append('>'); + ss.append(v); + ss.append("</").append(k).append('>').append('\n'); + } + else if (v instanceof Map) + { + ss.append(pad(indent)).append('<').append(k).append('>').append('\n'); + ss.append(generateXml(v, indent + 1)); + ss.append(pad(indent)).append("</").append(k).append('>').append('\n'); + } + else if (v instanceof List) + { + List<Object> ll = (List<Object>) v; + for (Object o1 : ll) + { + ss.append(pad(indent)).append('<').append(k).append('>').append('\n'); + ss.append(generateXml(o1, indent + 1)); + ss.append(pad(indent)).append("</").append(k).append('>').append('\n'); + } + } + } + return ss.toString(); + } + + return null; + } + + private static String pad(int n) + { + String s = ""; + for (int i = 0; i < n; i++) + s += '\t'; + return s; + } +} diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/adaptor.properties b/appc-config/appc-config-adaptor/provider/src/main/resources/adaptor.properties new file mode 100644 index 000000000..33fedfaed --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/adaptor.properties @@ -0,0 +1,23 @@ +### +# ============LICENSE_START======================================================= +# ONAP : APP-C +# ================================================================================ +# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +configComponent.url= +configComponent.user= +configComponent.passwd= diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/audit-request.xml b/appc-config/appc-config-adaptor/provider/src/main/resources/audit-request.xml new file mode 100644 index 000000000..a5d0237ae --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/audit-request.xml @@ -0,0 +1,33 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<NetworkAudit xmlns="http://lpp.att.com/configuration/configure/schema/v1" + xmlns:q2="http://lpp.att.com/configuration/configure/schema/v1"> + <q2:Requester>APP-C</q2:Requester> + <q2:RequesterPrefix>APP</q2:RequesterPrefix> + <q2:RequestId>${request-id}</q2:RequestId> + <q2:CallbackUrl>${callback-url}</q2:CallbackUrl> + <q2:EquipmentAudit> + <q2:EquipmentName>${equipment-name}</q2:EquipmentName> + <q2:Vendor>Netconf</q2:Vendor> + <q2:AuditType>N-SBG</q2:AuditType> + <q2:AuditLevel>${audit-level}</q2:AuditLevel> + </q2:EquipmentAudit> +</NetworkAudit> diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/config-base.xml b/appc-config/appc-config-adaptor/provider/src/main/resources/config-base.xml new file mode 100644 index 000000000..05827937a --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/config-base.xml @@ -0,0 +1,26 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<configure> + <operation>${operation}</operation> + <base> + ${service-data} + </base> +</configure> diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/config-data.xml b/appc-config/appc-config-adaptor/provider/src/main/resources/config-data.xml new file mode 100644 index 000000000..b24869936 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/config-data.xml @@ -0,0 +1,26 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<configure> + <operation>${operation}</operation> + <data> + ${service-data} + </data> +</configure> diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/config-request.xml b/appc-config/appc-config-adaptor/provider/src/main/resources/config-request.xml new file mode 100644 index 000000000..d77d039b5 --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/config-request.xml @@ -0,0 +1,39 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<NetworkConfiguration + xmlns="http://lpp.att.com/configuration/configure/schema/v1" xmlns:q2="http://lpp.att.com/configuration/configure/schema/v1"> + <q2:Requester>APP-C</q2:Requester> + <q2:RequesterPrefix>APP</q2:RequesterPrefix> + <q2:RequestId>${request-id}</q2:RequestId> + <q2:RequestType>${request-type}</q2:RequestType> + <q2:CallbackUrl>${callback-url}</q2:CallbackUrl> + <q2:Action>${action}</q2:Action> + <q2:EquipmentConfiguration> + <q2:EquipmentName>${equipment-name}</q2:EquipmentName> + <q2:EquipmentIpAddress>${equipment-ip-address}</q2:EquipmentIpAddress> + <q2:Vendor>${vendor}</q2:Vendor> + <q2:NetworkData> +<![CDATA[ +${network-data} +]]> + </q2:NetworkData> + </q2:EquipmentConfiguration> +</NetworkConfiguration> diff --git a/appc-config/appc-config-adaptor/provider/src/main/resources/prepare.xml b/appc-config/appc-config-adaptor/provider/src/main/resources/prepare.xml new file mode 100644 index 000000000..b59c2e7de --- /dev/null +++ b/appc-config/appc-config-adaptor/provider/src/main/resources/prepare.xml @@ -0,0 +1,122 @@ +<!-- + ============LICENSE_START======================================================= + ONAP : APP-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<configure> + <operation>create</operation> + <base> + <vnf-type>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].vnf-type}</vnf-type> + <vnf-host-ip-address>${service-data.vnf-config-information.vnf-host-ip-address}</vnf-host-ip-address> + <service-instance-id>${service-data.service-information.service-instance-id}</service-instance-id> + <ldap-ip-address>${service-data.vnf-config-information.ldap-ip-address}</ldap-ip-address> + <tls-ca-certificate>${service-data.vnf-config-information.tls-ca-certificate}</tls-ca-certificate> + <tls-client-certificate>${service-data.vnf-config-information.tls-client-certificate}</tls-client-certificate> + <tls-client-key>${service-data.vnf-config-information.tls-client-key}</tls-client-key> + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].snmp-target-v3_length: + <SnmpTargetV3> + <snmp-target-v3-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].snmp-target-v3[${1}].snmp-target-v3-id}</snmp-target-v3-id> + <snmp-target-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].snmp-target-v3[${1}].snmp-target-ip-address}</snmp-target-ip-address> + <snmp-security-level>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].snmp-target-v3[${1}].snmp-security-level}</snmp-security-level> + </SnmpTargetV3>} + + <escf-domain-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].escf-domain-name}</escf-domain-name> + <dns-ip-address-1>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dns-ip-address1}</dns-ip-address-1> + <dns-ip-address-2>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dns-ip-address2}</dns-ip-address-2> + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].dia-realm-rf_length: + <DiaRealmRf> + <realm>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dia-realm-rf[${1}].realm}</realm> + <peer-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dia-realm-rf[${1}].peer-ip-address}</peer-ip-address> + <peer-port>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dia-realm-rf[${1}].peer-port}</peer-port> + <local-port>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].dia-realm-rf[${1}].local-port}</local-port> + </DiaRealmRf>} + + <ext-bgf-controller-interface-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].ext-bgf-controller-interface-ip-address}</ext-bgf-controller-interface-ip-address> + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].ext-bgf-control-link_length: + <ExtBgfControlLink> + <bgf-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].ext-bgf-control-link[${1}].bgf-name}</bgf-name> + </ExtBgfControlLink>} + + <proxy-failover-delay>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].proxy-failover-delay}</proxy-failover-delay> + <proxy-fallback-delay>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].proxy-fallback-delay}</proxy-fallback-delay> + <proxy-polling-interval>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].proxy-polling-interval}</proxy-polling-interval> + <fallback-mode>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].fallback-mode}</fallback-mode> + <rf-interface-vlan-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].rf-interface-vlan-id}</rf-interface-vlan-id> + <rf-interface-nexthop-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].rf-interface-nexthop-ip-address}</rf-interface-nexthop-ip-address> + <rf-interface-subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].rf-interface-subnet-mask-length}</rf-interface-subnet-mask-length> + <rf-local-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].rf-local-ip-address}</rf-local-ip-address> + <sctpmh-configuration-subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].sctpmh-configuration-subnet-mask-length}</sctpmh-configuration-subnet-mask-length> + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf_length: + <AccessNetPcscf> + <network-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].network-name}</network-name> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].id}</id> + <network-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].network-id}</network-id> + <proactive-transcoding-profile>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].proactive-transcoding-profile}</proactive-transcoding-profile> + <next-hop-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].next-hop-ip-address}</next-hop-ip-address> + <subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].subnet-mask-length}</subnet-mask-length> + <vlan-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].vlan-id}</vlan-id> + <sip-pa-termination-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf[${1}].sip-pa-termination-ip-address}</sip-pa-termination-ip-address> + </AccessNetPcscf>} + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf_length: + <CoreNetPcscf> + <network-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].network-name}</network-name> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].id}</id> + <network-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].network-id}</network-id> + <next-hop-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].next-hop-ip-address}</next-hop-ip-address> + <subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].subnet-mask-length}</subnet-mask-length> + <vlan-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].vlan-id}</vlan-id> + <sip-pa-termination-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-pcscf[${1}].sip-pa-termination-ip-address}</sip-pa-termination-ip-address> + </CoreNetPcscf>} + + <proc-mgmt-signal-param-host-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].proc-mgmt-signal-param-host-name}</proc-mgmt-signal-param-host-name> + <mated-pair-fully-qualified-domain-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].mated-pair-fully-qualified-domain-name}</mated-pair-fully-qualified-domain-name> + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].outgoing-proxy_length: + <OutgoingProxy> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].outgoing-proxy[${1}].id}</id> + <domain-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].outgoing-proxy[${1}].domain-name}</domain-name> + <ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].outgoing-proxy[${1}].ip-address}</ip-address> + </OutgoingProxy>} + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net_length: + <ForeignNet> + <network-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].network-name}</network-name> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].id}</id> + <network-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].network-id}</network-id> + <next-hop-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].next-hop-ip-address}</next-hop-ip-address> + <subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].subnet-mask-length}</subnet-mask-length> + <vlan-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].vlan-id}</vlan-id> + <sip-ic-termination-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].foreign-net[${1}].sip-ic-termination-ip-address}</sip-ic-termination-ip-address> + </ForeignNet>} + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].address-to-network_length: + <AddressToNetwork> + <foreign-network-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].address-to-network[${1}].foreign-network-id}</foreign-network-id> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].address-to-network[${1}].id}</id> + <ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].address-to-network[${1}].ip-address}</ip-address> + <subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].address-to-network[${1}].subnet-mask-length}</subnet-mask-length> + </AddressToNetwork>} + ${repeat:service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf_length: + <CoreNetIbcf> + <network-name>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].network-name}</network-name> + <id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].id}</id> + <network-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].network-id}</network-id> + <next-hop-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].next-hop-ip-address}</next-hop-ip-address> + <subnet-mask-length>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].subnet-mask-length}</subnet-mask-length> + <vlan-id>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].vlan-id}</vlan-id> + <sip-ic-termination-ip-address>${service-data.vnf-config-parameters-list.vnf-config-parameters[0].core-net-ibcf[${1}].sip-ic-termination-ip-address}</sip-ic-termination-ip-address> + </CoreNetIbcf>} + </base> +</configure> diff --git a/appc-config/pom.xml b/appc-config/pom.xml index 17a90f715..24060ce15 100644 --- a/appc-config/pom.xml +++ b/appc-config/pom.xml @@ -93,6 +93,7 @@ <module>appc-data-services</module> <module>appc-flow-controller</module> <module>appc-config-generator</module> + <module>appc-config-adaptor</module> </modules> </project> |