From a7058c0af341d852a667b1a5adac895e4652f01f Mon Sep 17 00:00:00 2001 From: "Benjamin, Max (mb388a)" Date: Mon, 4 Feb 2019 20:02:38 -0500 Subject: cloud config migration from openstack to catdb remove the wait and sleep code in migration move cloud config migration from openstack to catdb Change-Id: Id887a37ce12665e5d8a604308ea251744529491c Issue-ID: SO-1461 Signed-off-by: Benjamin, Max (mb388a) --- .../src/main/java/db/migration/CloudConfig.java | 87 ++++++++ .../java/db/migration/R__CloudConfigMigration.java | 236 +++++++++++++++++++++ .../src/test/resources/application-test.yaml | 41 +++- 3 files changed, 358 insertions(+), 6 deletions(-) create mode 100644 adapters/mso-catalog-db-adapter/src/main/java/db/migration/CloudConfig.java create mode 100644 adapters/mso-catalog-db-adapter/src/main/java/db/migration/R__CloudConfigMigration.java (limited to 'adapters/mso-catalog-db-adapter') diff --git a/adapters/mso-catalog-db-adapter/src/main/java/db/migration/CloudConfig.java b/adapters/mso-catalog-db-adapter/src/main/java/db/migration/CloudConfig.java new file mode 100644 index 0000000000..82139f21af --- /dev/null +++ b/adapters/mso-catalog-db-adapter/src/main/java/db/migration/CloudConfig.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 - 2018 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 db.migration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.onap.so.db.catalog.beans.CloudIdentity; +import org.onap.so.db.catalog.beans.CloudSite; +import org.onap.so.db.catalog.beans.CloudifyManager; + +import java.util.HashMap; +import java.util.Map; + +/** + * @deprecated + * This class is introduced as deprecated as its only purpose is for migration of cloud config data. It shouldnt be used elsewhere. + */ + +@Deprecated +@JsonIgnoreProperties(ignoreUnknown = true) +public class CloudConfig { + @JsonProperty("identity_services") + private Map identityServices = new HashMap<>(); + + @JsonProperty("cloud_sites") + private Map cloudSites = new HashMap<>(); + + @JsonProperty("cloudify_managers") + private Map cloudifyManagers = new HashMap<>(); + + + public Map getIdentityServices() { + return identityServices; + } + + public void setIdentityServices(Map identityServices) { + this.identityServices = identityServices; + } + + public Map getCloudSites() { + return cloudSites; + } + + public void setCloudSites(Map cloudSites) { + this.cloudSites = cloudSites; + } + + public Map getCloudifyManagers() { + return cloudifyManagers; + } + + public void setCloudifyManagers(Map cloudifyManagers) { + this.cloudifyManagers = cloudifyManagers; + } + + public void populateId(){ + for (Map.Entry entry : identityServices.entrySet()) { + entry.getValue().setId(entry.getKey()); + } + + for (Map.Entry entry : cloudSites.entrySet()) { + entry.getValue().setId(entry.getKey()); + } + + for (Map.Entry entry : cloudifyManagers.entrySet()) { + entry.getValue().setId(entry.getKey()); + } + } +} diff --git a/adapters/mso-catalog-db-adapter/src/main/java/db/migration/R__CloudConfigMigration.java b/adapters/mso-catalog-db-adapter/src/main/java/db/migration/R__CloudConfigMigration.java new file mode 100644 index 0000000000..5acd8359ec --- /dev/null +++ b/adapters/mso-catalog-db-adapter/src/main/java/db/migration/R__CloudConfigMigration.java @@ -0,0 +1,236 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP - SO + * ================================================================================ + * Copyright (C) 2017 - 2018 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 db.migration; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.flywaydb.core.api.MigrationVersion; +import org.flywaydb.core.api.migration.MigrationChecksumProvider; +import org.flywaydb.core.api.migration.MigrationInfoProvider; +import org.flywaydb.core.api.migration.jdbc.JdbcMigration; +import org.onap.so.db.catalog.beans.CloudIdentity; +import org.onap.so.db.catalog.beans.CloudSite; +import org.onap.so.db.catalog.beans.CloudifyManager; +import org.onap.so.logger.MsoLogger; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collection; + +/** + * Performs migration using JDBC Connection from the cloud config provided in the environment (application-{profile}.yaml) and persist data (when not already present) to the catalod database. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class R__CloudConfigMigration implements JdbcMigration , MigrationInfoProvider, MigrationChecksumProvider { + public static final String FLYWAY = "FLYWAY"; + + private static final MsoLogger LOGGER = MsoLogger.getMsoLogger(MsoLogger.Catalog.RA, R__CloudConfigMigration.class); + @JsonProperty("cloud_config") + private CloudConfig cloudConfig; + + @Override + public boolean isUndo(){ + return false; + } + + @Override + public void migrate(Connection connection) throws Exception { + LOGGER.debug("Starting migration for CloudConfig"); + + CloudConfig cloudConfig = null; + + String tableQuery = "SELECT * FROM identity_services"; + int totalRetries = 20; + boolean tableExists = false; + int count = 1; + while(!tableExists && count != totalRetries) { + try(Statement stmt = connection.createStatement();) { + stmt.executeQuery(tableQuery); + tableExists = true; + } catch (SQLException e) { + count++; + // Wait 5 mintues + Thread.sleep(300000); + } + } + + // Try the override file + String configLocation = System.getProperty("spring.config.additional-location"); + if (configLocation != null) { + try (InputStream stream = new FileInputStream(Paths.get(configLocation).normalize().toString())) { + cloudConfig = loadCloudConfig(stream); + }catch(Exception e){ + LOGGER.warnSimple("Error Loading override.yaml",e); + } + } + + if (cloudConfig == null) { + LOGGER.debug("No CloudConfig defined in " + configLocation); + + // Try the application.yaml file + try (InputStream stream = R__CloudConfigMigration.class.getResourceAsStream(getApplicationYamlName())) { + cloudConfig = loadCloudConfig(stream); + } + + if (cloudConfig == null) { + LOGGER.debug("No CloudConfig defined in " + getApplicationYamlName()); + } + } + + if(cloudConfig != null){ + migrateCloudIdentity(cloudConfig.getIdentityServices().values(), connection); + migrateCloudSite(cloudConfig.getCloudSites().values(), connection); + migrateCloudifyManagers(cloudConfig.getCloudifyManagers().values(), connection); + } + } + + public CloudConfig getCloudConfig() { + return cloudConfig; + } + + public void setCloudConfig(CloudConfig cloudConfig) { + this.cloudConfig = cloudConfig; + } + + private CloudConfig loadCloudConfig(InputStream stream) throws IOException { + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + R__CloudConfigMigration cloudConfigMigration = + mapper.readValue(stream, R__CloudConfigMigration.class); + CloudConfig cloudConfig = cloudConfigMigration.getCloudConfig(); + + if(cloudConfig != null){ + cloudConfig.populateId(); + } + + return cloudConfig; + } + + private String getApplicationYamlName() { + String profile = System.getProperty("spring.profiles.active") == null ? "" : "-" + System.getProperty("spring.profiles.active"); + return "/application" + profile + ".yaml"; + } + + private void migrateCloudIdentity(Collection entities, Connection connection) throws SQLException { + LOGGER.debug("Starting migration for CloudConfig-->IdentityService"); + String insert = "INSERT INTO `identity_services` (`ID`, `IDENTITY_URL`, `MSO_ID`, `MSO_PASS`, `ADMIN_TENANT`, `MEMBER_ROLE`, `TENANT_METADATA`, `IDENTITY_SERVER_TYPE`, `IDENTITY_AUTHENTICATION_TYPE`, `LAST_UPDATED_BY`) " + + "VALUES (?,?,?,?,?,?,?,?,?,?);"; + + try (Statement stmt = connection.createStatement();PreparedStatement ps = connection.prepareStatement(insert)) { + for (CloudIdentity cloudIdentity : entities) { + try (ResultSet rows = stmt.executeQuery("Select count(1) from identity_services where id='" + cloudIdentity.getId() + "'")) { + int count = 0; + while (rows.next()) { + count = rows.getInt(1); + } + if (count == 0) { + ps.setString(1, cloudIdentity.getId()); + ps.setString(2, cloudIdentity.getIdentityUrl()); + ps.setString(3, cloudIdentity.getMsoId()); + ps.setString(4, cloudIdentity.getMsoPass()); + ps.setString(5, cloudIdentity.getAdminTenant()); + ps.setString(6, cloudIdentity.getMemberRole()); + ps.setBoolean(7, cloudIdentity.getTenantMetadata()); + ps.setString(8, cloudIdentity.getIdentityServerType() != null ? cloudIdentity.getIdentityServerType().name() : null); + ps.setString(9, cloudIdentity.getIdentityAuthenticationType() != null ? cloudIdentity.getIdentityAuthenticationType().name() : null); + ps.setString(10, FLYWAY); + ps.executeUpdate(); + } + } + } + } + } + + private void migrateCloudSite(Collection entities, Connection connection) throws SQLException { + LOGGER.debug("Starting migration for CloudConfig-->CloudSite"); + String insert = "INSERT INTO `cloud_sites` (`ID`, `REGION_ID`, `IDENTITY_SERVICE_ID`, `CLOUD_VERSION`, `CLLI`, `CLOUDIFY_ID`, `PLATFORM`, `ORCHESTRATOR`, `LAST_UPDATED_BY`) " + + "VALUES (?,?,?,?,?,?,?,?,?);"; + + try (Statement stmt = connection.createStatement();PreparedStatement ps = connection.prepareStatement(insert)) { + for (CloudSite cloudSite : entities) { + try (ResultSet rows = stmt.executeQuery("Select count(1) from cloud_sites where id='" + cloudSite.getId() + "'")) { + int count = 0; + while (rows.next()) { + count = rows.getInt(1); + } + if (count == 0) { + ps.setString(1, cloudSite.getId()); + ps.setString(2, cloudSite.getRegionId()); + ps.setString(3, cloudSite.getIdentityServiceId()); + ps.setString(4, cloudSite.getCloudVersion()); + ps.setString(5, cloudSite.getClli()); + ps.setString(6, cloudSite.getCloudifyId()); + ps.setString(7, cloudSite.getPlatform()); + ps.setString(8, cloudSite.getOrchestrator()); + ps.setString(9, FLYWAY); + ps.executeUpdate(); + } + } + } + } + } + + private void migrateCloudifyManagers(Collection entities, Connection connection) throws SQLException { + String insert = "INSERT INTO `cloudify_managers` (`ID`, `CLOUDIFY_URL`, `USERNAME`, `PASSWORD`, `VERSION`, `LAST_UPDATED_BY`)" + + " VALUES (?,?,?,?,?,?);"; + + try (Statement stmt = connection.createStatement();PreparedStatement ps = connection.prepareStatement(insert)) { + for (CloudifyManager cloudifyManager : entities) { + try (ResultSet rows = stmt.executeQuery("Select count(1) from cloudify_managers where id='" + cloudifyManager.getId() + "'")) { + int count = 0; + while (rows.next()) { + count = rows.getInt(1); + } + if (count == 0) { + ps.setString(1, cloudifyManager.getId()); + ps.setString(2, cloudifyManager.getCloudifyUrl()); + ps.setString(3, cloudifyManager.getUsername()); + ps.setString(4, cloudifyManager.getPassword()); + ps.setString(5, cloudifyManager.getVersion()); + ps.setString(6, FLYWAY); + ps.executeUpdate(); + } + } + } + } + } + + public MigrationVersion getVersion() { + return null; + } + + public String getDescription() { + return "R_CloudConfigMigration"; + } + + public Integer getChecksum() { + return Math.toIntExact(System.currentTimeMillis() / 1000); + } +} + diff --git a/adapters/mso-catalog-db-adapter/src/test/resources/application-test.yaml b/adapters/mso-catalog-db-adapter/src/test/resources/application-test.yaml index f84e194962..954e41aa68 100644 --- a/adapters/mso-catalog-db-adapter/src/test/resources/application-test.yaml +++ b/adapters/mso-catalog-db-adapter/src/test/resources/application-test.yaml @@ -20,6 +20,11 @@ spring: driver-class-name: org.mariadb.jdbc.Driver initialization-mode: always data: classpath*:data.sql + flyway: + baseline-on-migrate: false + url: jdbc:mariadb://localhost:3307/catalogdb + user: root + password: password jpa: generate-ddl: false show-sql: false @@ -69,9 +74,33 @@ management: enabled: true # Whether exporting of metrics to Prometheus is enabled. step: 1m # Step size (i.e. reporting frequency) to use. - -flyway: - baseline-on-migrate: false - jdbc-url: jdbc:mariadb://localhost:3307/catalogdb - user: root - password: password +cloud_config: + identity_services: + MTKEYSTONE: + identity_url: "http://localhost:5000/v2.0" + mso_id: "john" + mso_pass: "313DECE408AF7759D442D7B06DD9A6AA" + admin_tenant: "admin" + member_role: "_member_" + tenant_metadata: false + identity_server_type: "KEYSTONE" + identity_authentication_type: "USERNAME_PASSWORD" + cloud_sites: + mtn13: + region_id: "mtn13" + clli: "MDT13" + aic_version: "3.0" + identity_service_id: "MTN13" + orchestrator: "orchestrator" + cloudify_id: "mtn13" + regionOne: + region_id: "regionOne" + clli: "MT2" + aic_version: "2.5" + identity_service_id: "MTKEYSTONE" + cloudify_managers: + manager: + cloudify_url: "http://localhost:8080" + username: "user" + password: "password" + version: "2.0" -- cgit 1.2.3-korg