From 75a5dadbe6b4eb6e6838341dffdd2c272b65b35c Mon Sep 17 00:00:00 2001 From: ankitbhatt Date: Tue, 5 Mar 2019 16:34:18 +0530 Subject: Added SDNC MDSAL Data Migrator Functionality. Change-Id: I63ec1a4674d3a3cc6b39708ddee18ae7f9040b1c Issue-ID: SDNC-223 Signed-off-by: ankitbhatt Former-commit-id: c4c27b78ff6b4a8f22553ef3d19aec67edd17482 --- data-migrator/pom.xml | 139 +++++++++++++++++++ data-migrator/src/assembly/assemble_zip.xml | 59 ++++++++ .../onap/sdnc/oam/datamigrator/DataMigration.java | 39 ++++++ .../oam/datamigrator/DataMigrationInternal.java | 148 +++++++++++++++++++++ .../sdnc/oam/datamigrator/common/Description.java | 31 +++++ .../datamigrator/common/MigratorConfiguration.java | 118 ++++++++++++++++ .../sdnc/oam/datamigrator/common/Operation.java | 24 ++++ .../oam/datamigrator/common/RestconfClient.java | 144 ++++++++++++++++++++ .../datamigrator/exceptions/RestconfException.java | 46 +++++++ .../sdnc/oam/datamigrator/migrators/Migrator.java | 136 +++++++++++++++++++ .../migrators/PreloadInformationMigrator.java | 61 +++++++++ .../migrators/RenameDeleteLeafMigrator.java | 62 +++++++++ .../src/main/resources/data-migrator.properties | 27 ++++ data-migrator/src/main/resources/log4j.properties | 37 ++++++ data-migrator/src/main/scripts/runMigration.sh | 48 +++++++ .../datamigrator/DataMigrationInternalTest.java | 92 +++++++++++++ .../datamigrator/common/RestconfClientTest.java | 107 +++++++++++++++ .../PreloadInformationMigratorTest.java | 80 +++++++++++ data-migrator/src/test/resources/log4j.properties | 29 ++++ .../migration/props/data-migrator.properties | 27 ++++ .../wiremock/preloadInformationRequest.json | 1 + .../resources/wiremock/preloadVnfResponse.json | 132 ++++++++++++++++++ installation/sdnc/pom.xml | 20 ++- .../src/main/properties/data-migrator.properties | 26 ++++ pom.xml | 10 +- 25 files changed, 1640 insertions(+), 3 deletions(-) create mode 100644 data-migrator/pom.xml create mode 100644 data-migrator/src/assembly/assemble_zip.xml create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigration.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternal.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Description.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/MigratorConfiguration.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Operation.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/RestconfClient.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/exceptions/RestconfException.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/Migrator.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/PreloadInformationMigrator.java create mode 100644 data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/RenameDeleteLeafMigrator.java create mode 100644 data-migrator/src/main/resources/data-migrator.properties create mode 100644 data-migrator/src/main/resources/log4j.properties create mode 100644 data-migrator/src/main/scripts/runMigration.sh create mode 100644 data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternalTest.java create mode 100644 data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/common/RestconfClientTest.java create mode 100644 data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/datamigrator/PreloadInformationMigratorTest.java create mode 100644 data-migrator/src/test/resources/log4j.properties create mode 100644 data-migrator/src/test/resources/migration/props/data-migrator.properties create mode 100644 data-migrator/src/test/resources/wiremock/preloadInformationRequest.json create mode 100644 data-migrator/src/test/resources/wiremock/preloadVnfResponse.json create mode 100644 installation/src/main/properties/data-migrator.properties diff --git a/data-migrator/pom.xml b/data-migrator/pom.xml new file mode 100644 index 00000000..f05f3709 --- /dev/null +++ b/data-migrator/pom.xml @@ -0,0 +1,139 @@ + + + 4.0.0 + + + org.onap.sdnc.oam + sdnc-oam + 1.5.0-SNAPSHOT + + + org.onap.sdnc.oam + data-migrator + 1.5.0-SNAPSHOT + jar + + sdnc-oam :: data-migrator + MDSAL Data Migrator + + + 2.9.4 + 2.0 + true + yyyyMMdd'T'HHmmss'Z' + ${maven.build.timestamp} + ${project.version}-${build.number} + + + + + + + + + + org.slf4j + slf4j-api + 1.7.21 + + + org.slf4j + slf4j-log4j12 + 1.6.1 + compile + + + log4j + log4j + 1.2.17 + + + junit + junit + ${junit.version} + test + + + com.google.code.gson + gson + 2.8.5 + + + org.apache.commons + commons-lang3 + 3.5 + + + org.reflections + reflections + 0.9.9-RC1 + + + com.beust + jcommander + 1.48 + + + com.github.tomakehurst + wiremock-standalone + 2.18.0 + test + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + true + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + true + org.onap.sdnc.oam.datamigrator.DataMigration + + + + + + maven-assembly-plugin + 2.6 + + + create-zip + + single + + package + + true + ${project.artifactId}.${project.version} + true + + src/assembly/assemble_zip.xml + + false + + + + + + + + diff --git a/data-migrator/src/assembly/assemble_zip.xml b/data-migrator/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..604adf30 --- /dev/null +++ b/data-migrator/src/assembly/assemble_zip.xml @@ -0,0 +1,59 @@ + + + + + + assemble_zip + + zip + + + false + + + + src/main/scripts + bin + + + target + lib + + *.jar + + + + src/main/resources + properties + + *.properties + + + + + + lib + true + runtime + + + diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigration.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigration.java new file mode 100644 index 00000000..ac53f448 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigration.java @@ -0,0 +1,39 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataMigration { + + private static final Logger LOG = LoggerFactory.getLogger(DataMigration.class); + + public static void main(String[] args) { + try { + DataMigrationInternal dataMigrationInternal = new DataMigrationInternal(LOG); + dataMigrationInternal.run(args); + }catch (Exception e){ + e.printStackTrace(); + LOG.error("Error in DataMigration" + e.getMessage()); + } + return; + } +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternal.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternal.java new file mode 100644 index 00000000..ae497235 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternal.java @@ -0,0 +1,148 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator; + +import com.beust.jcommander.JCommander; +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Strings; +import org.onap.sdnc.oam.datamigrator.common.Description; +import org.onap.sdnc.oam.datamigrator.common.MigratorConfiguration; +import org.onap.sdnc.oam.datamigrator.common.Operation; +import org.onap.sdnc.oam.datamigrator.migrators.Migrator; +import org.reflections.Reflections; +import org.slf4j.Logger; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class DataMigrationInternal { + + private final Logger log; + + public DataMigrationInternal(Logger log) { + this.log = log; + } + + private void logAndPrint(String msg) { + System.out.println(msg); + log.info(msg); + } + + public void run(String[] args){ + CommandLineArgs cArgs = new CommandLineArgs(); + JCommander jCommander = new JCommander(cArgs, args); + jCommander.setProgramName(DataMigration.class.getSimpleName()); + + if (cArgs.help) { + jCommander.usage(); + return; + } + + Set> migratorList = getMigratorList(); + if(cArgs.scripts.size() > 0){ + migratorList = migratorList.stream().filter(aClass -> cArgs.scripts.contains(aClass.getSimpleName())).collect(Collectors.toSet()); + } + if(cArgs.excludeClasses.size() > 0){ + migratorList = migratorList.stream().filter(aClass -> !cArgs.excludeClasses.contains(aClass.getSimpleName())).collect(Collectors.toSet()); + } + + if(migratorList.size()>0) { + logAndPrint("Total number of available migrations: " + migratorList.size()); + if(cArgs.list) { + logAndPrint("List of available migrations:"); + for (Class migrator : migratorList) { + if(migrator.getAnnotation(Description.class) != null && !migrator.getAnnotation(Description.class).value().isEmpty()) { + logAndPrint(migrator.getSimpleName()+ ": " + migrator.getAnnotation(Description.class).value() ); + }else { + logAndPrint(migrator.getSimpleName()); + } + } + }else { + Operation operation; + try { + operation = Operation.valueOf(cArgs.operation.toUpperCase()); + logAndPrint("Starting operation: " + operation.name()); + }catch (IllegalArgumentException e) { + logAndPrint("Invalid operation: " + cArgs.operation +". Supported operations are: Migrate, Backup, Restore."); + return; + } + boolean success = true; + MigratorConfiguration config; + if(!Strings.isStringEmpty(cArgs.config)){ + config = new MigratorConfiguration(cArgs.config); + }else { + logAndPrint("No external configuration provided. Initializing Default configuration."); + config = new MigratorConfiguration(); + } + for (Class migratorClass : migratorList) { + logAndPrint("Started executing migrator: "+ migratorClass.getSimpleName()); + try { + Migrator migrator = migratorClass.newInstance(); + migrator.init(config); + migrator.run(operation); + success = success && migrator.isSuccess(); + } catch (InstantiationException | IllegalAccessException e) { + logAndPrint("Error instantiating migrator: " + migratorClass); + success=false; + } + logAndPrint("Completed execution for migrator "+ migratorClass.getSimpleName() +" with status: " + success); + } + if(success){ + logAndPrint(operation.name()+ " operation completed Successfully."); + }else{ + logAndPrint("Error during "+ operation.name() +" operation. Check logs for details."); + } + } + }else{ + logAndPrint("No migrations available."); + } + } + + private Set> getMigratorList() { + Reflections reflections = new Reflections("org.onap.sdnc.oam.datamigrator.migrators"); + return reflections.getSubTypesOf(Migrator.class).stream().filter(aClass -> !Modifier.isAbstract(aClass.getModifiers())).collect(Collectors.toSet()); + } + + class CommandLineArgs { + + @Parameter(names = "--h", help = true) + public boolean help; + + @Parameter(names = "-o", description = "Operation to be performed. Default is Migrate. Supported operations: Migrate , Backup , Restore.") + public String operation = "Migrate"; + + @Parameter(names = "-c", description = "Configuration File path / directory") + public String config; + + @Parameter(names = "-m", description = "Names of migration scripts to run") + public List scripts = new ArrayList<>(); + + @Parameter(names = "-l", description = "List the available of migrations") + public boolean list = false; + + @Parameter(names = "-e", description = "Exclude list of migrator classes") + public List excludeClasses = new ArrayList<>(); + } + + +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Description.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Description.java new file mode 100644 index 00000000..3eaf562d --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Description.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.common; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Description { + String value() default ""; +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/MigratorConfiguration.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/MigratorConfiguration.java new file mode 100644 index 00000000..40a1b920 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/MigratorConfiguration.java @@ -0,0 +1,118 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.common; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; + +public class MigratorConfiguration { + + private String sourceHost ; + private String sourceUser ; + private String sourcePassword ; + private String targetHost ; + private String targetUser ; + private String targetPassword ; + private String dataPath; + + private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR"; + private static final Logger LOG = LoggerFactory + .getLogger(MigratorConfiguration.class); + + public MigratorConfiguration (){ + String propDir = System.getenv(SDNC_CONFIG_DIR); + if (propDir == null) { + propDir = "/opt/sdnc/data/properties"; + } + try { + init(propDir); + } catch (Exception e) { + LOG.error("Cannot initialize MigratorConfiguration", e); + } + } + + public MigratorConfiguration (String propDir){ + try { + init(propDir); + } catch (Exception e) { + LOG.error("Cannot initialize MigratorConfiguration", e); + } + } + + public void init(String propDir) throws IOException { + String propPath = propDir + "/data-migrator.properties"; + URL propPathUrl= getClass().getClassLoader().getResource(propPath); + File propFile = (propPathUrl != null) ? new File(propPathUrl.getFile()) : new File(propPath); + if (!propFile.exists()) { + throw new FileNotFoundException( + "Missing configuration properties file : " + + propFile); + } + + Properties props = new Properties(); + props.load(new FileInputStream(propFile)); + this.sourceHost = props.getProperty("org.onap.sdnc.datamigrator.source.host"); + this.sourceUser = props.getProperty("org.onap.sdnc.datamigrator.source.user"); + this.sourcePassword = props.getProperty("org.onap.sdnc.datamigrator.source.password"); + this.targetHost = props.getProperty("org.onap.sdnc.datamigrator.target.host"); + this.targetUser = props.getProperty("org.onap.sdnc.datamigrator.target.user"); + this.targetPassword = props.getProperty("org.onap.sdnc.datamigrator.target.password"); + this.dataPath = props.getProperty("org.onap.sdnc.datamigrator.data.path"); + } + + public String getSourceHost() { + return sourceHost; + } + + public String getSourceUser() { + return sourceUser; + } + + public String getSourcePassword() { + return sourcePassword; + } + + public String getTargetHost() { + return targetHost; + } + + public String getTargetUser() { + return targetUser; + } + + public String getTargetPassword() { + return targetPassword; + } + + public String getDataPath() { + return dataPath; + } + + public void setDataPath(String dataPath) { + this.dataPath = dataPath; + } +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Operation.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Operation.java new file mode 100644 index 00000000..df6cd00a --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/Operation.java @@ -0,0 +1,24 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.common; + +public enum Operation { + RESTORE,MIGRATE,BACKUP +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/RestconfClient.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/RestconfClient.java new file mode 100644 index 00000000..b7722b6d --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/common/RestconfClient.java @@ -0,0 +1,144 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.common; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.onap.sdnc.oam.datamigrator.exceptions.RestconfException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.util.Base64; + +public class RestconfClient { + + private HttpURLConnection httpConn = null; + private final String host ; + private final String user ; + private final String password ; + private static final String CONFIG_PATH = "/restconf/config/"; + private static final String CONTENT_TYPE_JSON = "application/json"; + private final Logger log = LoggerFactory.getLogger(RestconfClient.class); + + public RestconfClient (String host , String user , String password){ + this.host = host; + this.user = user; + this.password = password; + } + + private class SdncAuthenticator extends Authenticator { + + private final String user; + private final String passwd; + + SdncAuthenticator(String user, String passwd) { + this.user = user; + this.passwd = passwd; + } + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, passwd.toCharArray()); + } + } + + public JsonObject get(String path) throws RestconfException { + String getResponse = send(path,"GET",CONTENT_TYPE_JSON,""); + JsonParser parser = new JsonParser(); + return parser.parse(getResponse).getAsJsonObject(); + } + + public void put(String path, String data) throws RestconfException { + send(path,"PUT",CONTENT_TYPE_JSON, data ); + } + + private String send(String path,String method, String contentType, String msg) throws RestconfException { + Authenticator.setDefault(new SdncAuthenticator(user, password)); + String url = host + CONFIG_PATH + path; + try { + URL sdncUrl = new URL(url); + log.info("SDNC url: " + url); + log.info("Method: " + method); + this.httpConn = (HttpURLConnection) sdncUrl.openConnection(); + String authStr = user + ":" + password; + String encodedAuthStr = new String(Base64.getEncoder().encode(authStr.getBytes())); + httpConn.addRequestProperty("Authentication", "Basic " + encodedAuthStr); + + httpConn.setRequestMethod(method); + httpConn.setRequestProperty("Content-Type", contentType); + httpConn.setRequestProperty("Accept", contentType); + + httpConn.setDoInput(true); + httpConn.setDoOutput(true); + httpConn.setUseCaches(false); + + if (httpConn instanceof HttpsURLConnection) { + HostnameVerifier hostnameVerifier = (hostname, session) -> true; + ((HttpsURLConnection) httpConn).setHostnameVerifier(hostnameVerifier); + } + if (!method.equals("GET")) { + log.info("Request payload: " + msg); + httpConn.setRequestProperty("Content-Length", "" + msg.length()); + DataOutputStream outStr = new DataOutputStream(httpConn.getOutputStream()); + outStr.write(msg.getBytes()); + outStr.close(); + } + + BufferedReader respRdr; + log.info("Response: " + httpConn.getResponseCode() + " " + httpConn.getResponseMessage()); + + if (httpConn.getResponseCode() < 300) { + respRdr = new BufferedReader(new InputStreamReader(httpConn.getInputStream())); + } else { + respRdr = new BufferedReader(new InputStreamReader(httpConn.getErrorStream())); + log.error("Error during restconf operation: "+ method + ". URL:" + sdncUrl.toString()+". Response:"+respRdr); + throw new RestconfException(httpConn.getResponseCode(),"Error during restconf operation: "+ method +". Response:"+respRdr); + } + + StringBuilder respBuff = new StringBuilder(); + String respLn; + while ((respLn = respRdr.readLine()) != null) { + respBuff.append(respLn).append("\n"); + } + respRdr.close(); + String respString = respBuff.toString(); + + log.info("Response body :\n" + respString); + return respString; + }catch (IOException e){ + throw new RestconfException(500,e.getMessage(),e); + }finally { + if (httpConn != null) { + httpConn.disconnect(); + } + } + } + + +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/exceptions/RestconfException.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/exceptions/RestconfException.java new file mode 100644 index 00000000..6b714c29 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/exceptions/RestconfException.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.exceptions; + +public class RestconfException extends Exception{ + + private final int errorCode; + private final String errorMessage; + + public RestconfException(int errorCode, String errorMessage) { + super(errorMessage); + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + public RestconfException(int errorCode, String errorMessage, Throwable e) { + super(errorMessage,e); + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + public int getErrorCode() { + return errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/Migrator.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/Migrator.java new file mode 100644 index 00000000..e44a2c73 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/Migrator.java @@ -0,0 +1,136 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.migrators; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import org.onap.sdnc.oam.datamigrator.common.MigratorConfiguration; +import org.onap.sdnc.oam.datamigrator.common.Operation; +import org.onap.sdnc.oam.datamigrator.common.RestconfClient; +import org.onap.sdnc.oam.datamigrator.exceptions.RestconfException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +public abstract class Migrator { + + protected RestconfClient sourceClient; + protected RestconfClient targetClient; + protected boolean success = true; + private MigratorConfiguration config; + private final Logger log = LoggerFactory.getLogger(PreloadInformationMigrator.class); + + + public void run(Operation operation){ + { + JsonObject sourceData; + if(operation != Operation.RESTORE) { + + try { + sourceData = sourceClient.get(getYangModuleName()+":"+ getSourcePath()); + if(operation == Operation.BACKUP){ + String fileName = getFileName(); + try { + BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); + writer.write(sourceData.toString()); + writer.close(); + } catch (IOException e) { + log.error("Error writing data to file : " + fileName, e); + success = false; + return; + } + return; + } + } catch (RestconfException e) { + if(e.getErrorCode() == 404){ + log.error("No data available for migration. Returning silent success.", e); + success = true; + }else { + log.error("Error retrieving data from MD-SAL store. Error code: " + e.getErrorCode() + ". Error message:" + e.getErrorMessage(), e); + success = false; + } + return; + } + }else { + String fileName = getFileName(); + try { + Gson gson = new Gson(); + sourceData = gson.fromJson(new BufferedReader(new FileReader(fileName)),JsonObject.class); + } catch (IOException e) { + log.error("Error Reading data from file : " + fileName, e); + success = false; + return; + } + } + try { + String targetData = convertData(sourceData); + targetClient.put(getYangModuleName()+":"+ getTargetPath(),targetData); + } catch (RestconfException e) { + log.error("Error loading data to MD-SAL store. Error code: "+e.getErrorCode()+". Error message:"+e.getErrorMessage(),e); + success=false; + } + } + } + + private String getFileName() { + return config.getDataPath()+ "/" + getYangModuleName()+ "_"+ getSourcePath()+"_"+ getTargetPath() + ".json"; + } + + protected abstract String convertData(JsonObject sourceData); + + public abstract String getYangModuleName(); + public abstract String getSourcePath(); + public abstract String getTargetPath(); + + public void init(MigratorConfiguration config){ + this.config = config; + sourceClient = new RestconfClient(config.getSourceHost(),config.getSourceUser(),config.getSourcePassword()); + targetClient = new RestconfClient(config.getTargetHost(),config.getTargetUser(),config.getTargetPassword()); + } + + public RestconfClient getSourceClient() { + return sourceClient; + } + + public void setSourceClient(RestconfClient sourceClient) { + this.sourceClient = sourceClient; + } + + public RestconfClient getTargetClient() { + return targetClient; + } + + public void setTargetClient(RestconfClient targetClient) { + this.targetClient = targetClient; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } +} + diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/PreloadInformationMigrator.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/PreloadInformationMigrator.java new file mode 100644 index 00000000..d259c216 --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/PreloadInformationMigrator.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.migrators; + +import org.onap.sdnc.oam.datamigrator.common.Description; + +import java.util.HashMap; +import java.util.HashSet; + +@Description("Migrator for container 'preload-vnf' in GENERIC-RESOURCE-API.yang") +public class PreloadInformationMigrator extends RenameDeleteLeafMigrator { + + private static final String YANG_MODULE = "GENERIC-RESOURCE-API"; + + static{ + deletedFields = new HashSet<>(); + deletedFields.add("preload-vnfs.vnf-preload-list.preload-data.vnf-topology-information"); + deletedFields.add("preload-vnfs.vnf-preload-list.preload-data.network-topology-information.network-topology-identifier.service-type"); + deletedFields.add("preload-vnfs.vnf-preload-list.preload-data.oper-status.last-action"); + renamedFields = new HashMap<>(); + renamedFields.put("preload-vnfs","preload-information"); + renamedFields.put("preload-vnfs.vnf-preload-list","preload-list"); + renamedFields.put("preload-vnfs.vnf-preload-list.vnf-type","preload-type"); + renamedFields.put("preload-vnfs.vnf-preload-list.vnf-name","preload-id"); + renamedFields.put("preload-vnfs.vnf-preload-list.preload-data.oper-status","preload-oper-status"); + renamedFields.put("preload-vnfs.vnf-preload-list.preload-data.network-topology-information","preload-network-topology-information"); + renamedFields.put("preload-vnfs.vnf-preload-list.preload-data.network-topology-information.network-topology-identifier","network-topology-identifier-structure"); + } + + @Override + public String getYangModuleName() { + return YANG_MODULE; + } + + @Override + public String getSourcePath() { + return "preload-vnfs"; + } + + @Override + public String getTargetPath() { + return "preload-information"; + } +} diff --git a/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/RenameDeleteLeafMigrator.java b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/RenameDeleteLeafMigrator.java new file mode 100644 index 00000000..8c0adc0c --- /dev/null +++ b/data-migrator/src/main/java/org/onap/sdnc/oam/datamigrator/migrators/RenameDeleteLeafMigrator.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.migrators; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.apache.commons.lang3.StringUtils; +import java.util.Map; +import java.util.Set; + +public abstract class RenameDeleteLeafMigrator extends Migrator { + + protected static Map renamedFields ; + protected static Set deletedFields ; + + @Override + protected String convertData(JsonObject sourceData) { + JsonObject target = convert(sourceData,""); + return target.toString(); + } + + protected JsonObject convert(JsonObject source,String parent) { + JsonObject target = new JsonObject(); + for (String key : source.keySet()){ + String prefixKey = StringUtils.isNotEmpty(parent) ? parent + "."+key : key; + if(!deletedFields.contains(prefixKey)) { + JsonElement value = source.get(key); + if (value.isJsonPrimitive()) { + target.add(renamedFields.getOrDefault(prefixKey,key), value); + } else if(value.isJsonArray()){ + JsonArray targetList = new JsonArray(); + JsonArray sourceArray = value.getAsJsonArray(); + for(JsonElement e : sourceArray){ + targetList.add(convert(e.getAsJsonObject(),prefixKey)); + } + target.add(renamedFields.getOrDefault(prefixKey,key), targetList); + } else{ + target.add(renamedFields.getOrDefault(prefixKey,key), convert(value.getAsJsonObject(),prefixKey)); + } + } + } + return target; + } +} diff --git a/data-migrator/src/main/resources/data-migrator.properties b/data-migrator/src/main/resources/data-migrator.properties new file mode 100644 index 00000000..f5f55a5e --- /dev/null +++ b/data-migrator/src/main/resources/data-migrator.properties @@ -0,0 +1,27 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### + +org.onap.sdnc.datamigrator.source.host=http://localhost:8081 +org.onap.sdnc.datamigrator.source.user=admin +org.onap.sdnc.datamigrator.source.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.target.host=http://localhost:8082 +org.onap.sdnc.datamigrator.target.user=admin +org.onap.sdnc.datamigrator.target.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.data.path=C:/DATA \ No newline at end of file diff --git a/data-migrator/src/main/resources/log4j.properties b/data-migrator/src/main/resources/log4j.properties new file mode 100644 index 00000000..d53dc5a8 --- /dev/null +++ b/data-migrator/src/main/resources/log4j.properties @@ -0,0 +1,37 @@ +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### + +log4j.rootLogger=DEBUG,CONSOLE,LOGFILE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Threshold=DEBUG +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%p %d{yyyy-MM-dd HH:mm:ss.SSS Z} %c{1} - %m%n + + +# LOGFILE is set to be a File appender using a PatternLayout. +log4j.appender.LOGFILE=org.apache.log4j.RollingFileAppender +log4j.appender.LOGFILE.File=/opt/app/data-migrator/data-migrator.log +log4j.appender.LOGFILE.Append=true +log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=%p %d{yyyy-MM-dd HH:mm:ss.SSS Z} %c{1} - %m%n +log4j.appender.LOGFILE.MaxFileSize=10MB +log4j.appender.LOGFILE.MaxBackupIndex=10 diff --git a/data-migrator/src/main/scripts/runMigration.sh b/data-migrator/src/main/scripts/runMigration.sh new file mode 100644 index 00000000..e763acbe --- /dev/null +++ b/data-migrator/src/main/scripts/runMigration.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +### +# ============LICENSE_START======================================================= +# openECOMP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### + +PROPERTY_DIR=${PROPERTY_DIR:-/opt/onap/sdnc/data/properties} +MIGRATION=data-migrator +MIGRATION_ROOT=${MIGRATION_ROOT:-/opt/onap/sdnc/data-migrator} +JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-8-oracle} +JAVA_OPTS=${JAVA_OPTS:--Dhttps.protocols=TLSv1.1,TLSv1.2} +JAVA=${JAVA:-${JAVA_HOME}/bin/java} + +# Redirect output from script to MIGRATION.out +exec >> ${MIGRATION_ROOT}/logs/$MIGRATION.out +exec 2>&1 + +if [ ! -d ${MIGRATION_ROOT}/logs ] +then + mkdir ${MIGRATION_ROOT}/logs +fi + +for file in ${MIGRATION_ROOT}/lib/*.jar +do + CLASSPATH=$CLASSPATH:$file +done + +${JAVA} ${JAVA_OPTS} -Dlog4j.configuration=file:${MIGRATION_ROOT}/properties/log4j.properties -cp ${CLASSPATH} org.onap.sdnc.oam.datamigrator.DataMigration $@ + +echo $! + +exit 0 diff --git a/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternalTest.java b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternalTest.java new file mode 100644 index 00000000..18cd662f --- /dev/null +++ b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/DataMigrationInternalTest.java @@ -0,0 +1,92 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.junit.Rule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.hamcrest.MatcherAssert.assertThat; + +public class DataMigrationInternalTest { + + @Rule + public WireMockRule source = new WireMockRule(8081); + @Rule + public WireMockRule target = new WireMockRule(8082); + + private static final Logger LOG = LoggerFactory.getLogger(DataMigrationInternal.class); + DataMigrationInternal dataMigrationInternal = new DataMigrationInternal(LOG); + private ClassLoader classLoader = getClass().getClassLoader(); + private String preloadVnfResponseJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadVnfResponse.json").toURI()))); + private String preloadInformationRequestJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadInformationRequest.json").toURI()))); + + public DataMigrationInternalTest() throws IOException, URISyntaxException { + } + + @Test + public void runPositiveTest() { + String [] args = {"-c","migration/props"}; + PrintStream oldOutputStream = System.out; + final ByteArrayOutputStream myOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(myOut)); + source.stubFor(get(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")).willReturn( + aResponse() + .withStatus(200) + .withBody(preloadVnfResponseJson))); + target.stubFor(put(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")).withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn( + aResponse() + .withStatus(200))); + dataMigrationInternal.run(args); + String content = myOut.toString(); + assertThat("Migration failed", content.contains("MIGRATE operation completed Successfully.")); + System.setOut(oldOutputStream); + } + + @Test + public void runTestWithNoData() { + String [] args = {"-c","migration/props"}; + PrintStream oldOutputStream = System.out; + final ByteArrayOutputStream myOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(myOut)); + source.stubFor(get(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")) + .willReturn(aResponse().withStatus(404))); + target.stubFor(put(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")) + .withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn(aResponse().withStatus(200))); + dataMigrationInternal.run(args); + String content = myOut.toString(); + assertThat("Migration failed", content.contains("MIGRATE operation completed Successfully.")); + System.setOut(oldOutputStream); + } +} \ No newline at end of file diff --git a/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/common/RestconfClientTest.java b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/common/RestconfClientTest.java new file mode 100644 index 00000000..bbffd608 --- /dev/null +++ b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/common/RestconfClientTest.java @@ -0,0 +1,107 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.common; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.junit.Rule; +import org.junit.Test; +import org.onap.sdnc.oam.datamigrator.exceptions.RestconfException; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class RestconfClientTest { + + @Rule + public WireMockRule service = new WireMockRule(8081); + private RestconfClient restconfClient = new RestconfClient("http://localhost:8081","admin","Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"); + private ClassLoader classLoader = getClass().getClassLoader(); + private String preloadVnfResponseJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadVnfResponse.json").toURI()))); + private String preloadInformationRequestJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadInformationRequest.json").toURI()))); + + + JsonObject expectedJsonObject = new JsonParser().parse(preloadVnfResponseJson).getAsJsonObject(); + + public RestconfClientTest() throws IOException, URISyntaxException { + } + + @Test + public void getPositiveTest() { + service.stubFor(get(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")) + .willReturn(aResponse().withStatus(200).withBody(preloadVnfResponseJson))); + JsonObject actualResponse=null; + try { + actualResponse = restconfClient.get("GENERIC-RESOURCE-API:preload-vnfs"); + } catch (RestconfException e) { + e.printStackTrace(); + } + assertEquals(expectedJsonObject,actualResponse); + } + + @Test + public void getNegativeTest() { + service.stubFor(get(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")) + .willReturn(aResponse().withStatus(404))); + JsonObject actualResponse=null; + try { + actualResponse = restconfClient.get("GENERIC-RESOURCE-API:preload-vnfs"); + } catch (RestconfException e) { + e.printStackTrace(); + } + assertNull(actualResponse); + } + + @Test + public void putPositiveTest() { + service.stubFor(put(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")) + .withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn(aResponse().withStatus(200))); + Exception ex = null; + try { + restconfClient.put("GENERIC-RESOURCE-API:preload-information", preloadInformationRequestJson); + } catch (RestconfException e) { + ex =e; + } + assertNull(ex); + } + + @Test + public void putNegativeTest() { + service.stubFor(put(urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")) + .withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn(aResponse().withStatus(500))); + try { + restconfClient.put("GENERIC-RESOURCE-API:preload-information", preloadInformationRequestJson); + } catch (RestconfException e) { + assertTrue(e.getErrorMessage().contains("Error during restconf operation: PUT.")); + } + } +} \ No newline at end of file diff --git a/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/datamigrator/PreloadInformationMigratorTest.java b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/datamigrator/PreloadInformationMigratorTest.java new file mode 100644 index 00000000..7972b7ab --- /dev/null +++ b/data-migrator/src/test/java/org/onap/sdnc/oam/datamigrator/datamigrator/PreloadInformationMigratorTest.java @@ -0,0 +1,80 @@ +/* + * ============LICENSE_START======================================================= + * ONAP : SDNC + * ================================================================================ + * Copyright 2019 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========================================================= + */ +package org.onap.sdnc.oam.datamigrator.datamigrator; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.junit.Rule; +import org.junit.Test; +import org.onap.sdnc.oam.datamigrator.common.Operation; +import org.onap.sdnc.oam.datamigrator.common.RestconfClient; +import org.onap.sdnc.oam.datamigrator.migrators.PreloadInformationMigrator; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class PreloadInformationMigratorTest { + + @Rule + public WireMockRule service1 = new WireMockRule(8081); + + @Rule + public WireMockRule service2 = new WireMockRule(8082); + PreloadInformationMigrator migrator = new PreloadInformationMigrator(); + private ClassLoader classLoader = getClass().getClassLoader(); + private String preloadVnfResponseJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadVnfResponse.json").toURI()))); + private String preloadInformationRequestJson = new String(Files.readAllBytes(Paths.get(classLoader.getResource("wiremock/preloadInformationRequest.json").toURI()))); + + public PreloadInformationMigratorTest() throws IOException, URISyntaxException { + } + + @Test + public void testRun (){ + service1.stubFor(WireMock.get(WireMock.urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")).willReturn( + WireMock.aResponse() + .withStatus(200) + .withBody(preloadVnfResponseJson))); + service2.stubFor(WireMock.put(WireMock.urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")).withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn( + WireMock.aResponse() + .withStatus(200))); + RestconfClient sourceClient = new RestconfClient("http://localhost:8081","admin","Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"); + migrator.setSourceClient(sourceClient); + RestconfClient targetClient = new RestconfClient("http://localhost:8082","admin","Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"); + migrator.setTargetClient(targetClient); + migrator.run(Operation.MIGRATE); + } + + @Test + public void testRunNoData (){ + service1.stubFor(WireMock.get(WireMock.urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-vnfs")).willReturn( + WireMock.aResponse() + .withStatus(404))); + service2.stubFor(WireMock.put(WireMock.urlEqualTo("/restconf/config/GENERIC-RESOURCE-API:preload-information")).withRequestBody(WireMock.equalTo(preloadInformationRequestJson)).willReturn( + WireMock.aResponse() + .withStatus(200))); + RestconfClient sourceClient = new RestconfClient("http://localhost:8081","admin","Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"); + migrator.setSourceClient(sourceClient); + RestconfClient targetClient = new RestconfClient("http://localhost:8082","admin","Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"); + migrator.setTargetClient(targetClient); + migrator.run(Operation.MIGRATE); + } +} diff --git a/data-migrator/src/test/resources/log4j.properties b/data-migrator/src/test/resources/log4j.properties new file mode 100644 index 00000000..82f1f470 --- /dev/null +++ b/data-migrator/src/test/resources/log4j.properties @@ -0,0 +1,29 @@ +### +# ============LICENSE_START======================================================= +# ONAP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### + +log4j.rootLogger=DEBUG,CONSOLE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.Threshold=DEBUG +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%p %d{yyyy-MM-dd HH:mm:ss.SSS Z} %c{1} - %m%n + + diff --git a/data-migrator/src/test/resources/migration/props/data-migrator.properties b/data-migrator/src/test/resources/migration/props/data-migrator.properties new file mode 100644 index 00000000..d9ddadbb --- /dev/null +++ b/data-migrator/src/test/resources/migration/props/data-migrator.properties @@ -0,0 +1,27 @@ +### +# ============LICENSE_START======================================================= +# ONAP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### + +org.onap.sdnc.datamigrator.source.host=http://localhost:8081 +org.onap.sdnc.datamigrator.source.user=admin +org.onap.sdnc.datamigrator.source.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.target.host=http://localhost:8082 +org.onap.sdnc.datamigrator.target.user=admin +org.onap.sdnc.datamigrator.target.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.data.path=C:/DATA \ No newline at end of file diff --git a/data-migrator/src/test/resources/wiremock/preloadInformationRequest.json b/data-migrator/src/test/resources/wiremock/preloadInformationRequest.json new file mode 100644 index 00000000..82df627b --- /dev/null +++ b/data-migrator/src/test/resources/wiremock/preloadInformationRequest.json @@ -0,0 +1 @@ +{"preload-information":{"preload-list":[{"preload-type":"vnf-type","preload-id":"vnf-name","preload-data":{"preload-oper-status":{"modify-timestamp":"Some modify-timestamp","create-timestamp":"Some create-timestamp","last-order-status":"Active","order-status":"Active","maintenance-indicator":"Y","last-svc-request-id":"Some last-svc-request-id"},"preload-network-topology-information":{"is-provider-network":true,"network-topology-identifier-structure":{"network-role":"Some network-role","network-technology":"Some network-technology","network-type":"Some network-type","network-name":"Some network-name"},"route-table-reference":[{"route-table-reference-fqdn":"Some route-table-reference-fqdn","route-table-reference-id":"Some route-table-reference-id"}],"network-policy":[{"network-policy-fqdn":"Some network-policy-fqdn","network-policy-id":"Some network-policy-id"}],"subnets":[{"start-address":"1.1.11.2","gateway-address":"8.0.25.2","cidr-mask":"Some cidr-mask","dhcp-end-address":"Some dhcp-end-address","subnet-name":"Some subnet-name","dhcp-start-address":"Some dhcp-start-address","ip-version":"Some ip-version","dhcp-enabled":"Y"}],"vpn-bindings":[{"vpn-binding-id":"Some vpn-binding-id","global-route-target":"Some global-route-target"}],"is-external-network":true,"is-shared-network":true,"physical-network-name":"Some physical-network-name"}}}]}} \ No newline at end of file diff --git a/data-migrator/src/test/resources/wiremock/preloadVnfResponse.json b/data-migrator/src/test/resources/wiremock/preloadVnfResponse.json new file mode 100644 index 00000000..006d62f7 --- /dev/null +++ b/data-migrator/src/test/resources/wiremock/preloadVnfResponse.json @@ -0,0 +1,132 @@ +{ + "preload-vnfs": { + "vnf-preload-list": [ + { + "vnf-type": "vnf-type", + "vnf-name": "vnf-name", + "preload-data": { + "oper-status": { + "last-action": "VNFActivateRequest", + "modify-timestamp": "Some modify-timestamp", + "create-timestamp": "Some create-timestamp", + "last-order-status": "Active", + "order-status": "Active", + "maintenance-indicator": "Y", + "last-svc-request-id": "Some last-svc-request-id" + }, + "vnf-topology-information": { + "vnf-topology-identifier": { + "service-type": "Some service-type", + "service-id": "Some service-id", + "generic-vnf-name": "Some generic-vnf-name", + "generic-vnf-id": "Some generic-vnf-id", + "generic-vnf-type": "Some generic-vnf-type", + "vnf-type": "vnf-type", + "vnf-name": "vnf-name" + }, + "vnf-parameters": [ + { + "vnf-parameter-name": "Some vnf-parameter-name", + "vnf-parameter-value": "Some vnf-parameter-value" + } + ], + "vnf-assignments": { + "vnf-vms": [ + { + "vm-type": "Some vm-type", + "vm-count": 0, + "vm-names": [ + {"vm-name": "Some vm-name"} + ], + "vm-networks": [ + { + "network-role": "Some network-role", + "use-dhcp": "Y", + "floating-ip": "2.12.250.0", + "network-macs": [ + {"mac-address": "Some mac-address"} + ], + "network-ips": [ + {"ip-address": "13.2.219.8"} + ], + "interface-route-prefixes": [ + { + "interface-route-prefix-cidr": "Some interface-route-prefix-cidr", + "interface-route-prefix": "24.0.45.1" + } + ], + "ip-count": 0 + } + ] + } + ], + "vnf-status": "Some vnf-status", + "vnf-networks": [ + { + "network-role": "Some network-role", + "network-id": "Some network-id", + "ipv6-subnet-id": "Some ipv6-subnet-id", + "ipv6-subnet-name": "Some ipv6-subnet-name", + "subnet-name": "Some subnet-name", + "contrail-network-fqdn": "Some contrail-network-fqdn", + "subnet-id": "Some subnet-id", + "sriov-vlan-filter-list": [ + {"sriov-vlan-filter": "Some sriov-vlan-filter"} + ], + "network-name": "Some network-name", + "neutron-id": "Some neutron-id" + } + ], + "availability-zones": [ + {"availability-zone": "Some availability-zone"} + ] + } + }, + "network-topology-information": { + "is-provider-network": true, + "network-topology-identifier": { + "service-type": "Some service-type", + "network-role": "Some network-role", + "network-technology": "Some network-technology", + "network-type": "Some network-type", + "network-name": "Some network-name" + }, + "route-table-reference": [ + { + "route-table-reference-fqdn": "Some route-table-reference-fqdn", + "route-table-reference-id": "Some route-table-reference-id" + } + ], + "network-policy": [ + { + "network-policy-fqdn": "Some network-policy-fqdn", + "network-policy-id": "Some network-policy-id" + } + ], + "subnets": [ + { + "start-address": "1.1.11.2", + "gateway-address": "8.0.25.2", + "cidr-mask": "Some cidr-mask", + "dhcp-end-address": "Some dhcp-end-address", + "subnet-name": "Some subnet-name", + "dhcp-start-address": "Some dhcp-start-address", + "ip-version": "Some ip-version", + "dhcp-enabled": "Y" + } + ], + "vpn-bindings": [ + { + "vpn-binding-id": "Some vpn-binding-id", + "global-route-target": "Some global-route-target" + } + ], + "is-external-network": true, + "is-shared-network": true, + "physical-network-name": "Some physical-network-name" + } + } + } + ] + } +} \ No newline at end of file diff --git a/installation/sdnc/pom.xml b/installation/sdnc/pom.xml index c26b4361..4f59aaa9 100644 --- a/installation/sdnc/pom.xml +++ b/installation/sdnc/pom.xml @@ -280,6 +280,24 @@ + + unpack migration utility + generate-sources + + unpack + + + ${basedir}/target/docker-stage/opt/onap/sdnc/data-migrator + + + org.onap.sdnc.oam + data-migrator + 1.5.0-SNAPSHOT + zip + + + + @@ -310,8 +328,6 @@ - - diff --git a/installation/src/main/properties/data-migrator.properties b/installation/src/main/properties/data-migrator.properties new file mode 100644 index 00000000..9bec60dd --- /dev/null +++ b/installation/src/main/properties/data-migrator.properties @@ -0,0 +1,26 @@ +### +# ============LICENSE_START======================================================= +# ONAP : SDN-C +# ================================================================================ +# Copyright (C) 2019 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========================================================= +### +org.onap.sdnc.datamigrator.source.host=http://10.53.234.213:30202 +org.onap.sdnc.datamigrator.source.user=admin +org.onap.sdnc.datamigrator.source.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.target.host=http://10.53.234.215:30202 +org.onap.sdnc.datamigrator.target.user=admin +org.onap.sdnc.datamigrator.target.password=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U +org.onap.sdnc.datamigrator.data.path=/tmp \ No newline at end of file diff --git a/pom.xml b/pom.xml index d4da4829..a28819f0 100755 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,8 @@ admportal platform-logic configbackuprestore - SdncReports + SdncReports + data-migrator @@ -104,4 +105,11 @@ + + + org.slf4j + slf4j-api + 1.7.25 + + -- cgit 1.2.3-korg