diff options
Diffstat (limited to 'aai-resources/src/main')
47 files changed, 4612 insertions, 95 deletions
diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java new file mode 100644 index 0000000..15c9b1e --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/AddResourceVersionProp.java @@ -0,0 +1,126 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + + +import java.util.Iterator; +import java.util.Properties; + +import org.openecomp.aai.dbmap.AAIGraph; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.Configuration; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; +import org.apache.tinkerpop.gremlin.structure.Vertex; + + +public class AddResourceVersionProp { + + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + + // NOTE -- This is a one-time migration for adding the new property "resource-version" to ALL of our nodes. + // Also -- since it's a one-time thing, we just re-use AAI_SCHEMA_MOD_LOG4J_PROPS + + TitanGraph graph = null; + + System.out.println(">>> WARNING: this script affects all nodes in the database. <<<< " ); + System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<"); + try { + // Give them a chance to back out of this + Thread.sleep(5000); + } catch ( java.lang.InterruptedException ie) { + System.out.println( " AddResourceVersionProp script has been aborted. "); + System.exit(1); + } + + try { + AAIConfig.init(); + ErrorLogHelper.loadProperties(); + + System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n"); + + graph = AAIGraph.getInstance().getGraph(); + if( graph == null ){ + String emsg = "Not able to get a graph object in AddResourceVersionProp.java\n"; + System.out.println( emsg ); + System.exit(1); + } + + + // For each node in the db -- update the "resource-version" and the last mod timestamp. + Iterable<TitanVertex> verts = null; + verts= graph.query().vertices(); + Iterator<TitanVertex> it = verts.iterator(); + int vtxCount = 0; + long unixTimeNow = System.currentTimeMillis() / 1000L; + String timeNowInSec = "" + unixTimeNow; + + while( it.hasNext() ){ + vtxCount++; + TitanVertex tmpVtx = (TitanVertex)it.next(); + tmpVtx.property( "aai-last-mod-ts", timeNowInSec ); + tmpVtx.property( "resource-version", timeNowInSec ); + } + + System.out.println("Updated data for " + vtxCount + " vertexes. Now call graph.tx().commit(). "); + graph.tx().commit(); + + } + catch (AAIException e) { + System.out.print("Threw a AAIException: \n"); + System.out.println(e.getErrorObject().toString()); + } + catch (Exception ex) { + System.out.print("Threw a regular Exception:\n"); + System.out.println(ex.getMessage()); + } + finally { + if( graph != null ){ + // Any changes that worked correctly should have already done their commits. + graph.tx().rollback(); + graph.close(); + } + + } + + + System.exit(0); + + }// End of main() + + +} + + diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java new file mode 100644 index 0000000..f92cfbc --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/ChangePropertyCardinality.java @@ -0,0 +1,307 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.Properties; +import java.util.TimeZone; + +import org.openecomp.aai.dbmap.AAIGraph; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.ingestModel.DbMaps; +import org.openecomp.aai.ingestModel.IngestModelMoxyOxm; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.Configuration; +import com.thinkaurelius.titan.core.Cardinality; +import com.thinkaurelius.titan.core.PropertyKey; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; +import com.thinkaurelius.titan.core.schema.TitanManagement; +import org.apache.tinkerpop.gremlin.structure.Vertex; + + +public class ChangePropertyCardinality { + + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + //public static void ChangePropertyCardinality( String[] args ) { + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + + // NOTE -- We're just working with properties that are used for NODES + String propName = ""; + String targetDataType = "String"; + String targetCardinality = "SET"; + String preserveDataFlag = "false"; + boolean preserveData = false; + + + String usageString = "Usage: ChangePropertyCardinality propertyName targetDataType targetCardinality preserveDataFlag \n"; + if( args.length != 4 ){ + String emsg = "Four Parameters are required. \n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else { + propName = args[0]; + targetDataType = args[1]; + targetCardinality = args[2]; + preserveDataFlag = args[3]; + } + + if( propName.equals("") ){ + String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else if( !targetDataType.equals("String") ){ + // && !targetDataType.equals("Integer") + // && !targetDataType.equals("Long") + // && !targetDataType.equals("Boolean") ){ + // String emsg = "Unsupported targetDataType. We only support String, Integer, Long or Boolean for now.\n" + usageString; + String emsg = "Unsupported targetDataType. We only support String for now.\n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else if( !targetCardinality.equals("SET") ){ + // && !targetCardinality.equals("LIST") + // && !targetCardinality.equals("SINGLE") ){ + String emsg = "Unsupported targetCardinality. We only support SET for now.\n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else { + if( preserveDataFlag.equals("true") ){ + preserveData = true; + String emsg = "Unsupported preserveDataFlag. For now, we only support: 'false'.\n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else if (preserveDataFlag.equals("false") ){ + preserveData = false; + } + else { + String emsg = "Unsupported preserveDataFlag. We only support: 'true' or 'false'.\n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + } + + String targetDataTypeStr = ""; + if( targetCardinality.equals("SINGLE") ){ + targetDataTypeStr = targetDataType; + } + else if( targetCardinality.equals("SET") ){ + targetDataTypeStr = "Set<" + targetDataType + ">"; + } + else if( targetCardinality.equals("LIST") ){ + targetDataTypeStr = "List<" + targetDataType + ">"; + } + + Class dType = null; + if(targetDataType.equals("String")){ dType = String.class; } + else if(targetDataType.equals("Integer")){ dType = Integer.class; } + else if(targetDataType.equals("Boolean")){ dType = Boolean.class; } + else if(targetDataType.equals("Character")){ dType = Character.class; } + else if(targetDataType.equals("Long")){ dType = Long.class; } + else if(targetDataType.equals("Float")){ dType = Float.class; } + else if(targetDataType.equals("Double")){ dType = Double.class; } + + System.out.println("\n>> WARNING/NOTE - If the passed cardinality is not in synch with what is in the ex5.json file, "); + System.out.println("\n>> then this will cause problems when new environments are created."); + + // Give a big warning if the DbMaps.PropertyDataTypeMap value does not agree with what we're doing + DbMaps dbMaps = null; + try { + dbMaps = IngestModelMoxyOxm.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + } + catch( AAIException ae ){ + String emsg = "Could not instantiate a copy of dbMaps. "; + System.out.println( emsg ); + System.exit(1); + } + + String warningMsg = ""; + if( !dbMaps.PropertyDataTypeMap.containsKey(propName) ){ + String emsg = "Property Name = [" + propName + "] not found in PropertyDataTypeMap. "; + System.out.println( emsg ); + System.exit(1); + } + else { + String currentDataType = dbMaps.PropertyDataTypeMap.get(propName); + if( !currentDataType.equals(targetDataTypeStr) ){ + warningMsg = "TargetDataType [" + targetDataTypeStr + "] does not match what is in DbMaps (" + currentDataType + ")."; + } + } + + if( !warningMsg.equals("") ){ + System.out.println("\n>>> WARNING <<<< " ); + System.out.println(">>> " + warningMsg + " <<<"); + System.out.println(">>> !!! WARNING -- this change may be overwritten in some environments if <<<"); + System.out.println(">>> !!! entries are out of synch with what is done with this script. <<<"); + System.out.println(">>> WARNING <<<< " ); + } + + System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<"); + try { + // Give them a chance to back out of this + Thread.sleep(5000); + } catch ( java.lang.InterruptedException ie) { + System.out.println( " DB Schema Update has been aborted. "); + System.exit(1); + } + + TitanManagement graphMgt = null; + TitanGraph graph = null; + try { + AAIConfig.init(); + ErrorLogHelper.loadProperties(); + + System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n"); + + graph = AAIGraph.getInstance().getGraph(); + if( graph == null ){ + String emsg = "Not able to get a graph object in ChangePropertyCardinality.java\n"; + System.out.println( emsg ); + System.exit(1); + } + + // Make sure this property is in the DB. + graphMgt = graph.openManagement(); + if( graphMgt == null ){ + String emsg = "Not able to get a graph Management object in ChangePropertyCardinality.java\n"; + System.out.println( emsg ); + System.exit(1); + } + + PropertyKey origPropKey = graphMgt.getPropertyKey(propName); + if( origPropKey == null ){ + // The old one wasn't there, so there's nothing to do + String emsg = "The propName = [" + propName + "] is not defined in our graph. "; + System.out.println( emsg ); + System.exit(1); + } + + if( origPropKey.cardinality().equals(Cardinality.valueOf(targetCardinality)) ){ + // The existing one already has cardinality of what they're asking for. + String emsg = "The propName = [" + propName + "] already has Cardinality of [" + targetCardinality + "]. "; + System.out.println( emsg ); + System.exit(0); + } + + // Rename this property to a backup name (old name with "retired_" appended plus a dateStr) + SimpleDateFormat d = new SimpleDateFormat("MMddHHmm"); + d.setTimeZone(TimeZone.getTimeZone("GMT")); + String dteStr = d.format(new Date()).toString(); + String retiredName = propName + "-" + dteStr + "-RETIRED"; + graphMgt.changeName( origPropKey, retiredName ); + + // Create a new property using the original property name and the targetDataType + PropertyKey freshPropKey = graphMgt.makePropertyKey(propName).dataType(dType).cardinality(Cardinality.valueOf(targetCardinality)).make(); + + System.out.println("Committing schema changes with graphMgt.tx().commit()"); + graphMgt.commit(); + graph.tx().commit(); + graph.close(); + + + // Get A new graph object + System.out.println(" ---- NOTE --- about to open a second graph object (takes a little while)\n"); + + graph = AAIGraph.getInstance().getGraph(); + if( graph == null ){ + String emsg = "Not able to get a graph object in SchemaMod.java\n"; + System.out.println( emsg ); + System.exit(1); + } + + // For each node that has this property, update the new from the old and then remove the + // old property from that node + // ---- NOTE ---- We're not preserving data at this point + Iterable<TitanVertex> verts = null; + verts= graph.query().has(retiredName).vertices(); + Iterator<TitanVertex> it = verts.iterator(); + int vtxCount = 0; + while( it.hasNext() ){ + vtxCount++; + TitanVertex tmpVtx = (TitanVertex)it.next(); + String tmpVid = tmpVtx.id().toString(); + + Object origVal = tmpVtx.property(retiredName).orElse(null); + if( preserveData ){ + tmpVtx.property(propName,origVal); + System.out.println("INFO -- just did the add of the freshPropertyKey and updated it with the orig value (" + + origVal.toString() + ")"); + } + else { + // existing nodes just won't have this property anymore + // + } + tmpVtx.property(retiredName).remove(); + System.out.println("INFO -- just did the remove of the " + retiredName + " from this vertex. (vid=" + tmpVid + ")"); + } + + System.out.println("Updated data for " + vtxCount + " vertexes. Now call graph.tx().commit(). "); + graph.tx().commit(); + + } + catch (AAIException e) { + System.out.print("Threw a AAIException: \n"); + System.out.println(e.getErrorObject().toString()); + } + catch (Exception ex) { + System.out.print("Threw a regular Exception:\n"); + System.out.println(ex.getMessage()); + } + finally { + if( graphMgt != null && graphMgt.isOpen() ){ + // Any changes that worked correctly should have already done their commits. + graphMgt.rollback(); + } + if( graph != null ){ + // Any changes that worked correctly should have already done their commits. + graph.tx().rollback(); + graph.close(); + } + + } + + System.exit(0); + + }// End of main() + + +} + + diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java index 68bebc2..d03a5e3 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/DataSnapshot.java @@ -277,4 +277,4 @@ public class DataSnapshot { }// End of main() -} +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java new file mode 100644 index 0000000..20d5c9f --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/ForceDeleteTool.java @@ -0,0 +1,722 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Properties; +import java.util.Scanner; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.slf4j.MDC; + +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.Configuration; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanFactory; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanGraphQuery; +import com.thinkaurelius.titan.core.TitanVertex; + + + +public class ForceDeleteTool { + + + private static final int MAXDESCENDENTDEPTH = 15; + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + //SWGK 01/21/2016 - To suppress the warning message when the tool is run from the Terminal. + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, "forceDelete-logback.xml"); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + EELFLogger logger = EELFManager.getInstance().getLogger(ForceDeleteTool.class.getSimpleName()); + MDC.put("logFilenameAppender", ForceDeleteTool.class.getSimpleName()); + + String actionVal = ""; + String userIdVal = ""; + String dataString = ""; + Boolean displayAllVidsFlag = false; // Note - This should rarely be needed + Boolean overRideProtection = false; // This should rarely be used - it overrides all our new checking + long vertexIdLong = 0; + String edgeIdStr = ""; + String argStr4Msg = ""; + + if (args != null && args.length > 0) { + // They passed some arguments in that will affect processing + for (int i = 0; i < args.length; i++) { + String thisArg = args[i]; + argStr4Msg = argStr4Msg + " " + thisArg; + + if (thisArg.equals("-action")) { + i++; + if (i >= args.length) { + logger.error(" No value passed with -action option. "); + System.exit(0); + } + actionVal = args[i]; + argStr4Msg = argStr4Msg + " " + actionVal; + } + else if (thisArg.equals("-userId")) { + i++; + if (i >= args.length) { + logger.error(" No value passed with -userId option. "); + System.exit(0); + } + userIdVal = args[i]; + argStr4Msg = argStr4Msg + " " + userIdVal; + } + else if (thisArg.equals("-overRideProtection")) { + overRideProtection = true; + } + else if (thisArg.equals("-DISPLAY_ALL_VIDS")) { + displayAllVidsFlag = true; + } + else if (thisArg.equals("-vertexId")) { + i++; + if (i >= args.length) { + logger.error(" No value passed with -vertexId option. "); + System.exit(0); + } + String nextArg = args[i]; + argStr4Msg = argStr4Msg + " " + nextArg; + try { + vertexIdLong = Long.parseLong(nextArg); + } catch (Exception e) { + logger.error("Bad value passed with -vertexId option: [" + + nextArg + "]"); + System.exit(0); + } + } + else if (thisArg.equals("-params4Collect")) { + i++; + if (i >= args.length) { + logger.error(" No value passed with -params4Collect option. "); + System.exit(0); + } + dataString = args[i]; + argStr4Msg = argStr4Msg + " " + dataString; + } + else if (thisArg.equals("-edgeId")) { + i++; + if (i >= args.length) { + logger.error(" No value passed with -edgeId option. "); + System.exit(0); + } + String nextArg = args[i]; + argStr4Msg = argStr4Msg + " " + nextArg; + edgeIdStr = nextArg; + } + else { + logger.error(" Unrecognized argument passed to ForceDeleteTool: [" + + thisArg + "]. "); + logger.error(" Valid values are: -action -userId -vertexId -edgeId -overRideProtection -params4Collect -DISPLAY_ALL_VIDS"); + System.exit(0); + } + } + } + + if( !actionVal.equals("COLLECT_DATA") && !actionVal.equals("DELETE_NODE") && !actionVal.equals("DELETE_EDGE")){ + String emsg = "Bad action parameter [" + actionVal + "] passed to ForceDeleteTool(). Valid values = COLLECT_DATA or DELETE_NODE or DELETE_EDGE\n"; + System.out.println(emsg); + logger.error(emsg); + System.exit(0); + } + + if( actionVal.equals("DELETE_NODE") && vertexIdLong == 0 ){ + String emsg = "ERROR: No vertex ID passed on DELETE_NODE request. \n"; + System.out.println(emsg); + logger.error(emsg); + System.exit(0); + } + else if( actionVal.equals("DELETE_EDGE") && edgeIdStr.equals("")){ + String emsg = "ERROR: No edge ID passed on DELETE_EDGE request. \n"; + System.out.println(emsg); + logger.error(emsg); + System.exit(0); + } + + + userIdVal = userIdVal.trim(); + if( (userIdVal.length() < 6) || userIdVal.toUpperCase().equals("AAIADMIN") ){ + String emsg = "Bad userId parameter [" + userIdVal + "] passed to ForceDeleteTool(). must be not empty and not aaiadmin \n"; + System.out.println(emsg); + logger.error(emsg); + System.exit(0); + } + + String msg = ""; + TitanGraph graph = null; + try { + AAIConfig.init(); + System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n"); + graph = TitanFactory.open(AAIConstants.REALTIME_DB_CONFIG); + if( graph == null ){ + String emsg = "could not get graph object in ForceDeleteTool() \n"; + System.out.println(emsg); + logger.error(emsg); + System.exit(0); + } + } + catch (AAIException e1) { + msg = e1.getErrorObject().toString(); + System.out.println(msg); + logger.error(msg); + System.exit(0); + } + catch (Exception e2) { + msg = e2.toString(); + System.out.println(msg); + logger.error(msg); + System.exit(0); + } + + msg = "ForceDelete called by: userId [" + userIdVal + "] with these params: [" + argStr4Msg + "]"; + System.out.println(msg); + logger.info(msg); + + + if( actionVal.equals("COLLECT_DATA") ){ + // When doing COLLECT_DATA, we expect the dataString string to be comma separated + // name value pairs like this: + // "propName1|propVal1,propName2|propVal2" etc. We will look for a node or nodes + // that have properties that ALL match what was passed in. + + int resCount = 0; + int firstPipeLoc = dataString.indexOf("|"); + if( firstPipeLoc <= 0 ){ + msg = "Must use the -params4Collect option when collecting data with data string in a format like: 'propName1|propVal1,propName2|propVal2'"; + System.out.println(msg); + logger.error(msg); + System.exit(0); + } + TitanGraphQuery tgQ = graph.query(); + String qStringForMsg = " graph.query()"; + // Note - if they're only passing on parameter, there won't be any commas + String [] paramArr = dataString.split(","); + for( int i = 0; i < paramArr.length; i++ ){ + int pipeLoc = paramArr[i].indexOf("|"); + if( pipeLoc <= 0 ){ + msg = "Must use the -params4Collect option when collecting data with data string in a format like: 'propName1|propVal1,propName2|propVal2'"; + System.out.println(msg); + logger.error(msg); + System.exit(0); + } + else { + String propName = paramArr[i].substring(0,pipeLoc); + String propVal = paramArr[i].substring(pipeLoc + 1); + tgQ = tgQ.has(propName,propVal); + qStringForMsg = qStringForMsg + ".has(" + propName + "," + propVal + ")"; + } + } + if( (tgQ != null) && (tgQ instanceof TitanGraphQuery) ){ + Iterable <TitanVertex> verts = (Iterable<TitanVertex>) tgQ.vertices(); + Iterator <TitanVertex> vertItor = verts.iterator(); + while( vertItor.hasNext() ){ + resCount++; + TitanVertex v = (TitanVertex)vertItor.next(); + showNodeInfo( logger, v, displayAllVidsFlag ); + int descendantCount = countDescendants( logger, v, 0 ); + String infMsg = " Found " + descendantCount + " descendant nodes \n"; + System.out.println( infMsg ); + logger.info( infMsg ); + } + } + else { + msg = "Bad TitanGraphQuery object. "; + System.out.println(msg); + logger.error(msg); + System.exit(0); + } + + String infMsg = "\n\n Found: " + resCount + " nodes for this query: [" + qStringForMsg + "]\n"; + System.out.println( infMsg ); + logger.info( infMsg ); + } + else if( actionVal.equals("DELETE_NODE") ){ + Iterator <Vertex> vtxItr = graph.vertices( vertexIdLong ); + if( vtxItr != null && vtxItr.hasNext() ) { + Vertex vtx = vtxItr.next(); + showNodeInfo( logger, vtx, displayAllVidsFlag ); + int descendantCount = countDescendants( logger, (TitanVertex)vtx, 0 ); + String infMsg = " Found " + descendantCount + " descendant nodes. Note - forceDelete does not cascade to " + + " child nodes, but they may become unreachable after the delete. \n"; + System.out.println( infMsg ); + logger.info( infMsg ); + + int edgeCount = countEdges( logger, vtx ); + + infMsg = " Found total of " + edgeCount + " edges incident on this node. \n"; + System.out.println( infMsg ); + logger.info( infMsg ); + + if( getNodeDelConfirmation(logger, userIdVal, vtx, descendantCount, edgeCount, overRideProtection) ){ + vtx.remove(); + graph.tx().commit(); + infMsg = ">>>>>>>>>> Removed node with vertexId = " + vertexIdLong; + logger.info( infMsg ); + System.out.println(infMsg); + } + else { + infMsg = " Delete Cancelled. "; + System.out.println(infMsg); + logger.info( infMsg ); + } + } + else { + String infMsg = ">>>>>>>>>> Vertex with vertexId = " + vertexIdLong + " not found."; + System.out.println( infMsg ); + logger.info( infMsg ); + } + } + else if( actionVal.equals("DELETE_EDGE") ){ + TitanEdge thisEdge = null; + Iterator <Edge> edItr = graph.edges( edgeIdStr ); + if( edItr != null && edItr.hasNext() ) { + thisEdge = (TitanEdge)edItr.next(); + } + + if( thisEdge == null ){ + String infMsg = ">>>>>>>>>> Edge with edgeId = " + edgeIdStr + " not found."; + logger.info( infMsg ); + System.out.println(infMsg); + System.exit(0); + } + + if( getEdgeDelConfirmation(logger, userIdVal, thisEdge, overRideProtection) ){ + thisEdge.remove(); + graph.tx().commit(); + String infMsg = ">>>>>>>>>> Removed edge with edgeId = " + edgeIdStr; + logger.info( infMsg ); + System.out.println(infMsg); + } + else { + String infMsg = " Delete Cancelled. "; + System.out.println(infMsg); + logger.info( infMsg ); + } + System.exit(0); + } + else { + String emsg = "Unknown action parameter [" + actionVal + "] passed to ForceDeleteTool(). Valid values = COLLECT_DATA, DELETE_NODE or DELETE_EDGE \n"; + System.out.println(emsg); + logger.info( emsg ); + System.exit(0); + } + + System.exit(0); + + }// end of main() + + + public static void showNodeInfo(EELFLogger logger, Vertex tVert, Boolean displayAllVidsFlag ){ + + try { + Iterator<VertexProperty<Object>> pI = tVert.properties(); + String infStr = ">>> Found Vertex with VertexId = " + tVert.id() + ", properties: "; + System.out.println( infStr ); + logger.info(infStr); + while( pI.hasNext() ){ + VertexProperty<Object> tp = pI.next(); + infStr = " [" + tp.key() + "|" + tp.value() + "] "; + System.out.println( infStr ); + logger.info(infStr); + } + + ArrayList <String> retArr = collectEdgeInfoForNode( logger, tVert, displayAllVidsFlag ); + for( String infoStr : retArr ){ + System.out.println( infoStr ); + logger.info(infoStr); + } + } + catch (Exception e){ + String warnMsg = " -- Error -- trying to display edge info. [" + e.getMessage() + "]"; + System.out.println( warnMsg ); + logger.warn(warnMsg); + } + + }// End of showNodeInfo() + + + public static void showPropertiesForEdge( EELFLogger logger, TitanEdge tEd ){ + String infMsg = ""; + if( tEd == null ){ + infMsg = "null Edge object passed to showPropertiesForEdge()"; + System.out.print(infMsg); + logger.info(infMsg); + return; + } + + // Try to show the edge properties + try { + infMsg =" Label for this Edge = [" + tEd.label() + "] "; + System.out.print(infMsg); + logger.info(infMsg); + + infMsg =" EDGE Properties for edgeId = " + tEd.id() + ": "; + System.out.print(infMsg); + logger.info(infMsg); + Iterator <String> pI = tEd.keys().iterator(); + while( pI.hasNext() ){ + String propKey = pI.next(); + infMsg = "Prop: [" + propKey + "], val = [" + + tEd.property(propKey) + "] "; + System.out.print(infMsg); + logger.info(infMsg); + } + } + catch( Exception ex ){ + infMsg = " Could not retrieve properties for this edge. exMsg = [" + + ex.getMessage() + "] "; + System.out.println( infMsg ); + logger.info(infMsg); + } + + // Try to show what's connected to the IN side of this Edge + try { + infMsg = " Looking for the Vertex on the IN side of the edge: "; + System.out.print(infMsg); + logger.info(infMsg); + TitanVertex inVtx = tEd.inVertex(); + Iterator<VertexProperty<Object>> pI = inVtx.properties(); + String infStr = ">>> Found Vertex with VertexId = " + inVtx.id() + + ", properties: "; + System.out.println( infStr ); + logger.info(infStr); + while( pI.hasNext() ){ + VertexProperty<Object> tp = pI.next(); + infStr = " [" + tp.key() + "|" + tp.value() + "] "; + System.out.println( infStr ); + logger.info(infStr); + } + } + catch( Exception ex ){ + infMsg = " Could not retrieve vertex data for the IN side of " + + "the edge. exMsg = [" + ex.getMessage() + "] "; + System.out.println( infMsg ); + logger.info(infMsg); + } + + // Try to show what's connected to the OUT side of this Edge + try { + infMsg = " Looking for the Vertex on the OUT side of the edge: "; + System.out.print(infMsg); + logger.info(infMsg); + TitanVertex outVtx = tEd.outVertex(); + Iterator<VertexProperty<Object>> pI = outVtx.properties(); + String infStr = ">>> Found Vertex with VertexId = " + outVtx.id() + + ", properties: "; + System.out.println( infStr ); + logger.info(infStr); + while( pI.hasNext() ){ + VertexProperty<Object> tp = pI.next(); + infStr = " [" + tp.key() + "|" + tp.value() + "] "; + System.out.println( infStr ); + logger.info(infStr); + } + } + catch( Exception ex ){ + infMsg = " Could not retrieve vertex data for the OUT side of " + + "the edge. exMsg = [" + ex.getMessage() + "] "; + System.out.println( infMsg ); + logger.info(infMsg); + } + + }// end showPropertiesForEdge() + + + + public static ArrayList <String> collectEdgeInfoForNode( EELFLogger logger, Vertex tVert, boolean displayAllVidsFlag ){ + ArrayList <String> retArr = new ArrayList <String> (); + Direction dir = Direction.OUT; + for ( int i = 0; i <= 1; i++ ){ + if( i == 1 ){ + // Second time through we'll look at the IN edges. + dir = Direction.IN; + } + Iterator <Edge> eI = tVert.edges(dir); + if( ! eI.hasNext() ){ + retArr.add("No " + dir + " edges were found for this vertex. "); + } + while( eI.hasNext() ){ + Edge ed = eI.next(); + String lab = ed.label(); + Vertex vtx = null; + if( dir == Direction.OUT ){ + // get the vtx on the "other" side + vtx = ed.inVertex(); + } + else { + // get the vtx on the "other" side + vtx = ed.outVertex(); + } + if( vtx == null ){ + retArr.add(" >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< "); + } + else { + String nType = vtx.<String>property("aai-node-type").orElse(null); + if( displayAllVidsFlag ){ + // This should rarely be needed + String vid = vtx.id().toString(); + retArr.add("Found an " + dir + " edge (" + lab + ") between this vertex and a [" + nType + "] node with VtxId = " + vid ); + } + else { + // This is the normal case + retArr.add("Found an " + dir + " edge (" + lab + ") between this vertex and a [" + nType + "] node. "); + } + } + } + } + return retArr; + + }// end of collectEdgeInfoForNode() + + + public static int countEdges( EELFLogger logger, Vertex vtx ){ + int edgeCount = 0; + try { + Iterator<Edge> edgesItr = vtx.edges(Direction.BOTH); + while( edgesItr.hasNext() ){ + edgesItr.next(); + edgeCount++; + } + } + catch (Exception e) { + String wMsg = "-- ERROR -- Stopping the counting of edges because of Exception [" + e.getMessage() + "]"; + System.out.println( wMsg ); + logger.warn( wMsg ); + } + return edgeCount; + + }// end of countEdges() + + + public static int countDescendants(EELFLogger logger, TitanVertex vtx, int levelVal ){ + int totalCount = 0; + int thisLevel = levelVal + 1; + + if( thisLevel > MAXDESCENDENTDEPTH ){ + String wMsg = "Warning -- Stopping the counting of descendents because we reached the max depth of " + MAXDESCENDENTDEPTH; + System.out.println( wMsg ); + logger.warn( wMsg ); + return totalCount; + } + + try { + Iterable <?> verts = vtx.query().direction(Direction.OUT).has("isParent",true).vertices(); + Iterator <?> vertI = verts.iterator(); + while( vertI != null && vertI.hasNext() ){ + totalCount++; + TitanVertex childVtx = (TitanVertex) vertI.next(); + totalCount = totalCount + countDescendants( logger, childVtx, thisLevel ); + } + } + catch (Exception e) { + String wMsg = "Error -- Stopping the counting of descendents because of Exception [" + e.getMessage() + "]"; + System.out.println( wMsg ); + logger.warn( wMsg ); + } + + return totalCount; + }// end of countDescendants() + + + public static boolean getEdgeDelConfirmation( EELFLogger logger, String uid, TitanEdge ed, + Boolean overRideProtection ) { + + showPropertiesForEdge( logger, ed ); + System.out.print("\n Are you sure you want to delete this EDGE? (y/n): "); + Scanner s = new Scanner(System.in); + s.useDelimiter(""); + String confirm = s.next(); + s.close(); + + if (!confirm.equalsIgnoreCase("y")) { + String infMsg = " User [" + uid + "] has chosen to abandon this delete request. "; + System.out.println("\n" + infMsg); + logger.info(infMsg); + return false; + } + else { + String infMsg = " User [" + uid + "] has confirmed this delete request. "; + System.out.println("\n" + infMsg); + logger.info(infMsg); + return true; + } + + } // End of getEdgeDelConfirmation() + + + public static boolean getNodeDelConfirmation( EELFLogger logger, String uid, Vertex vtx, int edgeCount, + int descendantCount, Boolean overRideProtection ) { + String thisNodeType = ""; + try { + thisNodeType = vtx.<String>property("aai-node-type").orElse(null); + } + catch ( Exception nfe ){ + // Let the user know something is going on - but they can confirm the delete if they want to. + String infMsg = " -- WARNING -- could not get an aai-node-type for this vertex. -- WARNING -- "; + System.out.println( infMsg ); + logger.warn( infMsg ); + } + + String ntListString = ""; + String maxDescString = ""; + String maxEdgeString = ""; + + int maxDescCount = 10; // default value + int maxEdgeCount = 10; // default value + ArrayList <String> protectedNTypes = new ArrayList <String> (); + protectedNTypes.add("cloud-region"); // default value + + try { + ntListString = AAIConfig.get("aai.forceDel.protected.nt.list"); + maxDescString = AAIConfig.get("aai.forceDel.protected.descendant.count"); + maxEdgeString = AAIConfig.get("aai.forceDel.protected.edge.count"); + } + catch ( Exception nfe ){ + // Don't worry, we will use default values + String infMsg = "-- WARNING -- could not get aai.forceDel.protected values from aaiconfig.properties -- will use default values. "; + System.out.println( infMsg ); + logger.warn( infMsg ); + } + + if( maxDescString != null && !maxDescString.equals("") ){ + try { + maxDescCount = Integer.parseInt(maxDescString); + } + catch ( Exception nfe ){ + // Don't worry, we will leave "maxDescCount" set to the default value + } + } + + if( maxEdgeString != null && !maxEdgeString.equals("") ){ + try { + maxEdgeCount = Integer.parseInt(maxEdgeString); + } + catch ( Exception nfe ){ + // Don't worry, we will leave "maxEdgeCount" set to the default value + } + } + + if( ntListString != null && !ntListString.trim().equals("") ){ + String [] nodeTypes = ntListString.split("\\|"); + for( int i = 0; i < nodeTypes.length; i++ ){ + protectedNTypes.add(nodeTypes[i]); + } + } + + boolean giveProtOverRideMsg = false; + boolean giveProtErrorMsg = false; + if( descendantCount > maxDescCount ){ + // They are trying to delete a node with a lots of descendants + String infMsg = " >> WARNING >> This node has more descendant edges than the max ProtectedDescendantCount: " + edgeCount + ". Max = " + + maxEdgeCount + ". It can be DANGEROUS to delete one of these. << WARNING << "; + System.out.println(infMsg); + logger.info(infMsg); + if( ! overRideProtection ){ + // They cannot delete this kind of node without using the override option + giveProtErrorMsg = true; + } + else { + giveProtOverRideMsg = true; + } + } + + if( edgeCount > maxEdgeCount ){ + // They are trying to delete a node with a lot of edges + String infMsg = " >> WARNING >> This node has more edges than the max ProtectedEdgeCount: " + edgeCount + ". Max = " + + maxEdgeCount + ". It can be DANGEROUS to delete one of these. << WARNING << "; + System.out.println(infMsg); + logger.info(infMsg); + if( ! overRideProtection ){ + // They cannot delete this kind of node without using the override option + giveProtErrorMsg = true; + } + else { + giveProtOverRideMsg = true; + } + } + + if( thisNodeType != null && !thisNodeType.equals("") && protectedNTypes.contains(thisNodeType) ){ + // They are trying to delete a protected Node Type + String infMsg = " >> WARNING >> This node is a PROTECTED NODE-TYPE (" + thisNodeType + "). " + + " It can be DANGEROUS to delete one of these. << WARNING << "; + System.out.println(infMsg); + logger.info(infMsg); + if( ! overRideProtection ){ + // They cannot delete this kind of node without using the override option + giveProtErrorMsg = true; + } + else { + giveProtOverRideMsg = true; + } + } + + if( giveProtOverRideMsg ){ + String infMsg = " !!>> WARNING >>!! you are using the overRideProtection parameter which will let you do this potentially dangerous delete."; + System.out.println("\n" + infMsg); + logger.info(infMsg); + } + else if( giveProtErrorMsg ) { + String errMsg = " ERROR >> this kind of node can only be deleted if you pass the overRideProtection parameter."; + System.out.println("\n" + errMsg); + logger.error(errMsg); + return false; + } + + System.out.print("\n Are you sure you want to do this delete? (y/n): "); + Scanner s = new Scanner(System.in); + s.useDelimiter(""); + String confirm = s.next(); + s.close(); + + if (!confirm.equalsIgnoreCase("y")) { + String infMsg = " User [" + uid + "] has chosen to abandon this delete request. "; + System.out.println("\n" + infMsg); + logger.info(infMsg); + return false; + } + else { + String infMsg = " User [" + uid + "] has confirmed this delete request. "; + System.out.println("\n" + infMsg); + logger.info(infMsg); + return true; + } + + } // End of getNodeDelConfirmation() + +} + + diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLReaderNew.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLReaderNew.java new file mode 100644 index 0000000..4f3fee0 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLReaderNew.java @@ -0,0 +1,353 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.reflect.Array; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.events.XMLEvent; + +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Vertex; + +//import com.infrasight.model.UnicodeUtil; +import com.thinkaurelius.titan.core.TitanGraph; + +/** + * GraphMLReader writes the data from a GraphML stream to a graph. + */ +public class GraphMLReaderNew { + public static final Charset charset = Charset.forName("UTF8"); + + /** + * Input the GraphML stream data into the graph. + * In practice, usually the provided graph is empty. + * + * @param graph the graph to populate with the GraphML data + * @param titanGraph the titan graph + * @param graphMLInputStream an InputStream of GraphML data + * @return the map + * @throws XMLStreamException thrown when the GraphML data is not correctly formatted + */ + public static Map<String, Object> inputGraph(final Graph graph, final TitanGraph titanGraph, final InputStream graphMLInputStream) throws XMLStreamException { + return inputGraph(graph, titanGraph, new InputStreamReader(graphMLInputStream, charset), 1000); + } + +/* public static void inputGraphFiltered(final Graph graph, final InputStream graphMLInputStream) throws XMLStreamException { + inputGraph(graph, UnicodeUtil.createFilteredReader(new InputStreamReader(graphMLInputStream, charset)), 1000); + }*/ + + private static class KeySpec { + String attrName; + String attrType; + + /** + * Instantiates a new key spec. + * + * @param name the name + * @param type the type + */ + public KeySpec(String name, String type) { + this.attrName = name; + this.attrType = type; + } + } + + /** + * Input the GraphML stream data into the graph. + * More control over how data is streamed is provided by this method. + * + * @param graph the graph to populate with the GraphML data + * @param titanGraph the titan graph + * @param inputReader an Reader of GraphML character data + * @param bufferSize the amount of elements to hold in memory before committing a transactions (only valid for TransactionalGraphs) + * @return the map + * @throws XMLStreamException thrown when the GraphML data is not correctly formatted + */ + public static Map<String, Object> inputGraph(final Graph graph, final TitanGraph titanGraph, final Reader inputReader, int bufferSize) throws XMLStreamException { + + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + XMLStreamReader reader = inputFactory.createXMLStreamReader(inputReader); + + //final BatchGraph<?> graph = BatchGraph.wrap(inputGraph, bufferSize); + + Map<String, KeySpec> keyMap = new HashMap<String, KeySpec>(); + + // Buffered Vertex Data + String vertexId = null; + Map<String, Object> vertexProps = null; + boolean inVertex = false; + + // Buffered Edge Data + String edgeId = null; + String edgeLabel = null; + Vertex edgeInVertex = null; + Vertex edgeOutVertex = null; + Map<String, Object> edgeProps = null; + boolean inEdge = false; + Map<String, Object> vertexIdSetMap = new HashMap<String, Object>(); + + while (reader.hasNext()) { + + Integer eventType = reader.next(); + if (eventType.equals(XMLEvent.START_ELEMENT)) { + String elementName = reader.getName().getLocalPart(); + + if (elementName.equals(GraphMLTokens.KEY)) { + String id = reader.getAttributeValue(null, GraphMLTokens.ID); + String attributeName = reader.getAttributeValue(null, GraphMLTokens.ATTR_NAME); + String attributeType = reader.getAttributeValue(null, GraphMLTokens.ATTR_TYPE); + keyMap.put(id, new KeySpec(attributeName, attributeType)); + + } else if (elementName.equals(GraphMLTokens.NODE)) { + vertexId = reader.getAttributeValue(null, GraphMLTokens.ID); + inVertex = true; + vertexProps = new HashMap<String, Object>(); + + } else if (elementName.equals(GraphMLTokens.EDGE)) { + + + edgeId = reader.getAttributeValue(null, GraphMLTokens.ID); + edgeLabel = reader.getAttributeValue(null, GraphMLTokens.LABEL); + edgeLabel = edgeLabel == null ? GraphMLTokens._DEFAULT : edgeLabel; + + String outVertexId = reader.getAttributeValue(null, GraphMLTokens.SOURCE); + String inVertexId = reader.getAttributeValue(null, GraphMLTokens.TARGET); + + edgeOutVertex = graph.vertices(outVertexId).next(); + edgeInVertex = graph.vertices(inVertexId).next(); + + if (null == edgeOutVertex) { + edgeOutVertex = graph.addVertex(outVertexId); + } + if (null == edgeInVertex) { + edgeInVertex = graph.addVertex(inVertexId); + } + + inEdge = true; + edgeProps = new HashMap<String, Object>(); + + } else if (elementName.equals(GraphMLTokens.DATA)) { + String key = reader.getAttributeValue(null, GraphMLTokens.KEY); + KeySpec keySpec = keyMap.get(key); + + if (keySpec != null) { + Object value = readData(reader, keySpec.attrType); + if(value == null) + throw new RuntimeException("Empty data"); + if (inVertex == true) { + vertexProps.put(keySpec.attrName, value); + } else if (inEdge == true) { + edgeProps.put(keySpec.attrName, value); + } + } + + } + } else if (eventType.equals(XMLEvent.END_ELEMENT)) { + String elementName = reader.getName().getLocalPart(); + + if (elementName.equals(GraphMLTokens.NODE)) { + + Vertex currentVertex = graph.vertices(vertexId).next(); + if (currentVertex != null) + throw new RuntimeException("Duplicate vertex ID: "+vertexId); + currentVertex = graph.addVertex(vertexId); + Boolean hasCollection = false; + for (Entry<String, Object> prop : vertexProps.entrySet()) { + // multi-properties need a addProperty and need to use a TitanVertex - BluePrint + // Vertex does not support this + Object value = prop.getValue(); + if (value instanceof Collection) { + hasCollection = true; + vertexIdSetMap.put(currentVertex.id().toString() + "." + prop.getKey(), vertexProps); + currentVertex.property("has-collection", "true"); + } else { + currentVertex.property(prop.getKey(), value); + } + } + if (hasCollection) + System.out.println("---Found node with SET property vertex id:" + vertexId + " properties:" + vertexProps.toString()); + vertexId = null; + vertexProps = null; + inVertex = false; + } else if (elementName.equals(GraphMLTokens.EDGE)) { + Edge currentEdge = edgeOutVertex.addEdge(edgeLabel, edgeInVertex); + //addEdge(edgeId, edgeOutVertex, edgeInVertex, edgeLabel); + + for (Entry<String, Object> prop : edgeProps.entrySet()) { + currentEdge.property(prop.getKey(), prop.getValue()); + } + + edgeId = null; + edgeLabel = null; + edgeInVertex = null; + edgeOutVertex = null; + edgeProps = null; + inEdge = false; + } + + } + + } + + reader.close(); + graph.tx().close(); + + return vertexIdSetMap; + + } + + /** + * Read data. + * + * @param reader the reader + * @param type the type + * @return the object + * @throws XMLStreamException the XML stream exception + */ + private static Object readData(XMLStreamReader reader, String type) throws XMLStreamException { + Collection<Object> col = new ArrayList<Object>(); + + int pos = type.indexOf('-'); + if(pos < 0) + return typeCastValue(reader.getElementText(), type); + String arrayType = type.substring(0, pos); + type = type.substring(pos+1); + + boolean done = false; + while(!done) { + Integer eventType = reader.next(); + if(eventType.equals(XMLEvent.START_ELEMENT)) { + String text = reader.getElementText(); + Object value = typeCastValue(text, type); + col.add(value); + } + if(eventType.equals(XMLEvent.END_ELEMENT)) { + String elementName = reader.getName().getLocalPart(); + if(elementName.equals(GraphMLTokens.DATA)) { + done = true; + continue; + } + } + } + + if(arrayType.equals(GraphMLTokens.ARRAY)) { + Object arr = Array.newInstance(typeToClass(type), col.size()); + int i = 0; + for(Object obj : col) { + Array.set(arr, i, obj); + i++; + } + return arr; + } + else if(arrayType.equals(GraphMLTokens.SET)) + return new HashSet<Object>(col); + else if(type.startsWith(GraphMLTokens.LIST)) + return new HashSet<Object>(col); + + return col; + } + + /** + * Type to class. + * + * @param type the type + * @return the class + */ + private static Class<?> typeToClass(String type) { + if (type.equals(GraphMLTokens.STRING)) + return String.class; + else if (type.equals(GraphMLTokens.FLOAT)) + return Float.TYPE; + else if (type.equals(GraphMLTokens.INT)) + return Integer.TYPE; + else if (type.equals(GraphMLTokens.DOUBLE)) + return Double.TYPE; + else if (type.equals(GraphMLTokens.BOOLEAN)) + return Boolean.TYPE; + else if (type.equals(GraphMLTokens.LONG)) + return Long.TYPE; + else + throw new RuntimeException("Unsupported type: "+type); + } + + /** + * Type cast value. + * + * @param value the value + * @param type the type + * @return the object + */ + private static Object typeCastValue(String value, String type) { + if (type.equals(GraphMLTokens.STRING)) + return value; + else if (type.equals(GraphMLTokens.FLOAT)) + return Float.valueOf(value); + else if (type.equals(GraphMLTokens.INT)) + return Integer.valueOf(value); + else if (type.equals(GraphMLTokens.DOUBLE)) + return Double.valueOf(value); + else if (type.equals(GraphMLTokens.BOOLEAN)) + return Boolean.valueOf(value); + else if (type.equals(GraphMLTokens.LONG)) + return Long.valueOf(value); + else + throw new RuntimeException("Unsupported type: "+type); + } + +/* TitanVertex titanVertex = (TitanVertex) titanGraph.getVertex(vertexId); + if (titanVertex != null) + throw new RuntimeException("Duplicate vertex ID: "+vertexId); + titanVertex = (TitanVertex) titanGraph.addVertex(vertexId); + for (Entry<String, Object> prop : vertexProps.entrySet()) { + // multi-properties need a addProperty and need to use a TitanVertex - BluePrint + // Vertex does not support this + Object value = prop.getValue(); + if (value instanceof Collection) { + try { + for(Object obj : ((Collection<?>)value)) { + System.out.println("vertex id:property name:property value="+ vertexId + ":" + prop.getKey() + ":" + obj.toString()); + titanVertex.addProperty(prop.getKey(), obj.toString()); + } + } + catch (Exception e) { + System.out.println("Can't set SET/LIST properties - skipping"); + } + + } else + titanVertex.setProperty(prop.getKey(), prop.getValue()); + }*/ +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLTokens.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLTokens.java new file mode 100644 index 0000000..f863a52 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLTokens.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +/** + * A collection of tokens used for GraphML related data. + */ +public class GraphMLTokens { + public static final String GRAPHML = "graphml"; + public static final String XMLNS = "xmlns"; + public static final String GRAPHML_XMLNS = "http://graphml.graphdrawing.org/xmlns"; + public static final String G = "G"; + public static final String EDGEDEFAULT = "edgedefault"; + public static final String DIRECTED = "directed"; + public static final String KEY = "key"; + public static final String FOR = "for"; + public static final String ID = "id"; + public static final String ATTR_NAME = "attr.name"; + public static final String ATTR_TYPE = "attr.type"; + public static final String GRAPH = "graph"; + public static final String NODE = "node"; + public static final String EDGE = "edge"; + public static final String SOURCE = "source"; + public static final String TARGET = "target"; + public static final String DATA = "data"; + public static final String LABEL = "label"; + public static final String STRING = "string"; + public static final String FLOAT = "float"; + public static final String DOUBLE = "double"; + public static final String LONG = "long"; + public static final String BOOLEAN = "boolean"; + public static final String INT = "int"; + public static final String ARRAY = "array"; + public static final String SET = "set"; + public static final String LIST = "list"; + public static final String ITEM = "item"; + public static final String _DEFAULT = "_default"; + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLWriterNew.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLWriterNew.java new file mode 100644 index 0000000..1704428 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/GraphMLWriterNew.java @@ -0,0 +1,358 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + + +import java.io.OutputStream; +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +/** + * GraphMLWriter writes a Graph to a GraphML OutputStream. + */ +public class GraphMLWriterNew { + + private static class KeySpec { + String attrName; + String attrType; + + /** + * Instantiates a new key spec. + * + * @param name the name + * @param type the type + */ + public KeySpec(String name, String type) { + this.attrName = name; + this.attrType = type; + } + } + + /** + * Write the data in a Graph to a GraphML OutputStream. + * + * @param graph the Graph to pull the data from + * @param graphMLOutputStream the GraphML OutputStream to write the Graph data to + * @throws XMLStreamException thrown if there is an error generating the GraphML data + */ + public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream) throws XMLStreamException { + Map<String, KeySpec> vertexKeyTypes = new HashMap<String, KeySpec>(); + Map<String, KeySpec> edgeKeyTypes = new HashMap<String, KeySpec>(); + + + Iterator<Vertex> vertices = graph.vertices(); + Vertex vertex = null; + Iterator<VertexProperty<Object>> propertyIterator = null; + VertexProperty<Object> property = null; + while (vertices.hasNext()) { + vertex = vertices.next(); + propertyIterator = vertex.properties(); + while (propertyIterator.hasNext()) { + property = propertyIterator.next(); + Object value = property.value(); + String key = property.key(); + if(value == null) + continue; + String type = getStringType(value); + if(type == null) + continue; + String id = key+"-"+type; + if (!vertexKeyTypes.containsKey(id)) { + vertexKeyTypes.put(id, new KeySpec(key, type)); + } + } + } + Iterator<Edge> edges = graph.edges(); + Edge edge = null; + Iterator<Property<Object>> edgePropertyIterator = null; + Property<Object> edgeProperty = null; + + while (edges.hasNext()) { + edge = edges.next(); + edgePropertyIterator = edge.properties(); + while (edgePropertyIterator.hasNext()) { + edgeProperty = edgePropertyIterator.next(); + Object value = edgeProperty.value(); + String key = edgeProperty.key(); + if(value == null) + continue; + String type = getStringType(value); + if(type == null) + continue; + String id = key+"-"+type; + if (!edgeKeyTypes.containsKey(id)) { + edgeKeyTypes.put(id, new KeySpec(key, type)); + } + } + } + outputGraph(graph, graphMLOutputStream, vertexKeyTypes, edgeKeyTypes); + } + + /** + * Write the data in a Graph to a GraphML OutputStream. + * + * @param graph the Graph to pull the data from + * @param graphMLOutputStream the GraphML OutputStream to write the Graph data to + * @param vertexKeyTypes a Map of the data types of the vertex keys + * @param edgeKeyTypes a Map of the data types of the edge keys + * @throws XMLStreamException thrown if there is an error generating the GraphML data + */ + public static void outputGraph(final Graph graph, final OutputStream graphMLOutputStream, final Map<String, KeySpec> vertexKeyTypes, final Map<String, KeySpec> edgeKeyTypes) throws XMLStreamException { + XMLOutputFactory inputFactory = XMLOutputFactory.newInstance(); + XMLStreamWriter writer = inputFactory.createXMLStreamWriter(graphMLOutputStream, "UTF8"); + + writer.writeStartDocument("UTF-8", "1.0"); + writer.writeStartElement(GraphMLTokens.GRAPHML); + writer.writeAttribute(GraphMLTokens.XMLNS, GraphMLTokens.GRAPHML_XMLNS); + //<key id="weight" for="edge" attr.name="weight" attr.type="float"/> + for (Map.Entry<String, KeySpec> entry : vertexKeyTypes.entrySet()) { + writer.writeStartElement(GraphMLTokens.KEY); + writer.writeAttribute(GraphMLTokens.ID, entry.getKey()); + writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.NODE); + writer.writeAttribute(GraphMLTokens.ATTR_NAME, entry.getValue().attrName); + writer.writeAttribute(GraphMLTokens.ATTR_TYPE, entry.getValue().attrType); + writer.writeEndElement(); + } + for (Map.Entry<String, KeySpec> entry : edgeKeyTypes.entrySet()) { + writer.writeStartElement(GraphMLTokens.KEY); + writer.writeAttribute(GraphMLTokens.ID, entry.getKey()); + writer.writeAttribute(GraphMLTokens.FOR, GraphMLTokens.EDGE); + writer.writeAttribute(GraphMLTokens.ATTR_NAME, entry.getValue().attrName); + writer.writeAttribute(GraphMLTokens.ATTR_TYPE, entry.getValue().attrType); + writer.writeEndElement(); + } + + writer.writeStartElement(GraphMLTokens.GRAPH); + writer.writeAttribute(GraphMLTokens.ID, GraphMLTokens.G); + writer.writeAttribute(GraphMLTokens.EDGEDEFAULT, GraphMLTokens.DIRECTED); + Iterator<Vertex> vertices = graph.vertices(); + Vertex vertex = null; + Iterator<VertexProperty<Object>> propertyIterator = null; + VertexProperty<Object> property = null; + while (vertices.hasNext()) { + vertex = vertices.next(); + writer.writeStartElement(GraphMLTokens.NODE); + writer.writeAttribute(GraphMLTokens.ID, vertex.id().toString()); + propertyIterator = vertex.properties(); + while (propertyIterator.hasNext()) { + property = propertyIterator.next(); + String key = property.key(); + writeData(writer, key, property.value()); + } + writer.writeEndElement(); + } + + Iterator<Edge> edges = graph.edges(); + Edge edge = null; + Iterator<Property<Object>> edgePropertyIterator = null; + Property<Object> edgeProperty = null; + + while (edges.hasNext()) { + edge = edges.next(); + edgePropertyIterator = edge.properties(); + writer.writeStartElement(GraphMLTokens.EDGE); + writer.writeAttribute(GraphMLTokens.ID, edge.id().toString()); + writer.writeAttribute(GraphMLTokens.SOURCE, edge.outVertex().id().toString()); + writer.writeAttribute(GraphMLTokens.TARGET, edge.inVertex().id().toString()); + writer.writeAttribute(GraphMLTokens.LABEL, edge.label()); + + while (edgePropertyIterator.hasNext()) { + edgeProperty = edgePropertyIterator.next(); + String key = edgeProperty.key(); + writeData(writer, key, edgeProperty.value()); + } + writer.writeEndElement(); + } + + writer.writeEndElement(); // graph + writer.writeEndElement(); // graphml + writer.writeEndDocument(); + + writer.flush(); + writer.close(); + + } + + /** + * Write data. + * + * @param writer the writer + * @param key the key + * @param value the value + * @throws XMLStreamException the XML stream exception + */ + private static void writeData(XMLStreamWriter writer, String key, Object value) throws XMLStreamException { + if(value == null) + return; + String type = getStringType(value); + if(type == null) + return; + String id = key+"-"+type; + + writer.writeStartElement(GraphMLTokens.DATA); + writer.writeAttribute(GraphMLTokens.KEY, id); + if(type.startsWith(GraphMLTokens.ARRAY) || + type.startsWith(GraphMLTokens.LIST) || + type.startsWith(GraphMLTokens.SET)) + writeDataArray(writer, value); + else + writer.writeCharacters(propertyValueToString(value)); + writer.writeEndElement(); + } + + /** + * Write data array. + * + * @param writer the writer + * @param value the value + * @throws XMLStreamException the XML stream exception + */ + private static void writeDataArray(XMLStreamWriter writer, Object value) throws XMLStreamException { + if(value.getClass().isArray()) { + for(int i = 0; i < Array.getLength(value); i++) { + writer.writeStartElement(GraphMLTokens.ITEM); + writer.writeCharacters(Array.get(value, i).toString()); + writer.writeEndElement(); + } + } + else if(value instanceof Collection) { + for(Object obj : ((Collection<?>)value)) { + writer.writeStartElement(GraphMLTokens.ITEM); + writer.writeCharacters(obj.toString()); + writer.writeEndElement(); + } + } + } + + /** + * Gets the string type. + * + * @param object the object + * @return the string type + */ + private static String getStringType(final Object object) { + if(object.getClass().isArray()) + return GraphMLTokens.ARRAY+"-"+getStringType(object.getClass().getComponentType()); + if(object instanceof Collection) { + String colType; + if(object instanceof Set) + colType = GraphMLTokens.SET; + else if(object instanceof List) + colType = GraphMLTokens.LIST; + else + throw new RuntimeException("Unhandled Collection type: "+object.getClass()); + + Collection<?> col = (Collection<?>)object; + if(col.size() == 0) + return null; + return colType+"-"+getStringType(col.iterator().next()); + } + if (object instanceof String) + return GraphMLTokens.STRING; + else if (object instanceof Integer) + return GraphMLTokens.INT; + else if (object instanceof Long) + return GraphMLTokens.LONG; + else if (object instanceof Float) + return GraphMLTokens.FLOAT; + else if (object instanceof Double) + return GraphMLTokens.DOUBLE; + else if (object instanceof Boolean) + return GraphMLTokens.BOOLEAN; + else + throw new RuntimeException("Unsupported type: "+object.getClass()); + } + + /** + * Gets the string type. + * + * @param clazz the clazz + * @return the string type + */ + private static String getStringType(final Class<?> clazz) { + if(clazz.equals(String.class)) + return GraphMLTokens.STRING; + else if(clazz.equals(Integer.TYPE) || clazz.equals(Integer.class)) + return GraphMLTokens.INT; + else if(clazz.equals(Long.TYPE) || clazz.equals(Long.class)) + return GraphMLTokens.LONG; + else if(clazz.equals(Float.TYPE) || clazz.equals(Float.class)) + return GraphMLTokens.FLOAT; + else if(clazz.equals(Double.TYPE) || clazz.equals(Double.class)) + return GraphMLTokens.DOUBLE; + else if(clazz.equals(Boolean.TYPE) || clazz.equals(Boolean.class)) + return GraphMLTokens.BOOLEAN; + else + throw new RuntimeException("Unsupported array item type: "+clazz); + } + + /** + * Property value to string. + * + * @param value the value + * @return the string + */ + private static String propertyValueToString(Object value) { + if(value == null) + return null; + + if(value.getClass().isArray()) { + String str = "["; + for(int i = 0; i < Array.getLength(value); i++) { + if(i > 0) + str += ", "; + str += Array.get(value, i); + } + str += "]"; + return str; + } + else if(value instanceof Collection) { + String str = "["; + int i = 0; + for(Object obj : ((Collection<?>)value)) { + if(i > 0) + str += ", "; + str += obj.toString(); + i++; + } + str += "]"; + return str; + } + return value.toString(); + } + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java new file mode 100644 index 0000000..3f7f351 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/PropertyNameChange.java @@ -0,0 +1,317 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +import java.util.Iterator; +import java.util.Properties; + +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; + +import org.openecomp.aai.dbmap.AAIGraph; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import com.att.eelf.configuration.Configuration; +import com.thinkaurelius.titan.core.PropertyKey; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanProperty; +import com.thinkaurelius.titan.core.TitanVertex; +import com.thinkaurelius.titan.core.schema.TitanManagement; + + +public class PropertyNameChange { + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + + // NOTE -- We're just working with properties that are used for NODES for now. + + TitanGraph graph = null; + TitanManagement graphMgt = null;; + Boolean preserveData = true; + String propName = ""; + String targetPropName = ""; + String targetNodeType = ""; + String skipCommit = ""; + boolean noCommit = false; + + + String usageString = "Usage: PropertyNameChange propertyName targetPropertyName nodeType(or NA) skipCommit(true|false) \n"; + if( args.length != 4 ){ + String emsg = "Four Parameters are required. \n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + else { + propName = args[0]; + targetPropName = args[1]; + targetNodeType = args[2]; + skipCommit = args[3]; + if ( skipCommit.toLowerCase().equals("true")) + noCommit = true; + } + + if( propName.equals("") ){ + String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString; + System.out.println( emsg ); + System.exit(1); + } + + + + try { + AAIConfig.init(); + ErrorLogHelper.loadProperties(); + } + catch( Exception ae ){ + String emsg = "Problem with either AAIConfig.init() or ErrorLogHelper.LoadProperties(). "; + System.out.println( emsg + "[" + ae.getMessage() + "]"); + System.exit(1); + } + + + System.out.println(">>> Processing will begin in 5 seconds (unless interrupted). <<<"); + try { + // Give them a chance to back out of this + Thread.sleep(5000); + } catch ( java.lang.InterruptedException ie) { + System.out.println( " DB Schema Update has been aborted. "); + System.exit(1); + } + + try { + System.out.println(" ---- NOTE --- about to open graph (takes a little while)\n"); + + graph = AAIGraph.getInstance().getGraph(); + if( graph == null ){ + String emsg = "Not able to get a graph object in SchemaMod.java\n"; + System.out.println( emsg ); + System.exit(1); + } + + // Make sure this property is in the DB. + graphMgt = graph.openManagement(); + if( graphMgt == null ){ + String emsg = "Not able to get a graph Management object in SchemaMod.java\n"; + System.out.println( emsg ); + System.exit(1); + } + PropertyKey origPropKey = graphMgt.getPropertyKey(propName); + if( origPropKey == null ){ + String emsg = "The propName = [" + propName + "] is not defined in our graph. "; + System.out.println( emsg ); + System.exit(1); + } + origPropKey = graphMgt.getPropertyKey(targetPropName); + if( origPropKey == null ){ + String emsg = "The targetPropName = [" + targetPropName + "] is not defined in our graph. "; + System.out.println( emsg ); + System.exit(1); + } + + if ( !targetNodeType.equals("NA")) { + if ( graphMgt.getVertexLabel(targetNodeType) == null ) { + String emsg = "The targetNodeType = [" + targetNodeType + "] is not defined in our graph. "; + System.out.println( emsg ); + System.exit(1); + } + } + + // For each node that has this property, update the new from the old and then remove the + // old property from that node + Iterable<TitanVertex> verts = null; + int vtxCount = 0; + String label; + long longId; + + int propertyCount; + + Iterator<VertexProperty<Object>> titanProperties = null; + + VertexProperty<Object> tmpProperty = null; + Object origVal; + Object targetVal; + + if ( targetNodeType.equals("NA")) { + verts= graph.query().has(propName).vertices(); + Iterator<TitanVertex> it = verts.iterator(); + + while( it.hasNext() ){ + + TitanVertex tmpVtx = (TitanVertex)it.next(); + String tmpVid = tmpVtx.id().toString(); + + origVal = tmpVtx.<Object>property(propName).orElse(null); + targetVal = tmpVtx.<Object>property(targetPropName).orElse(null); + + label = tmpVtx.label(); + longId = tmpVtx.longId(); + + if ( targetVal != null ) { + System.out.println( "vertex [" + label + "] id " + tmpVid + " has " + targetPropName + + " with value " + targetVal + ", skip adding with value " + origVal); + continue; + } + vtxCount++; + titanProperties = tmpVtx.properties(); // current properties + + propertyCount = 0; + + while( titanProperties.hasNext() ){ + + tmpProperty = titanProperties.next(); + + if ( propertyCount == 0 ) + System.out.print( "adding to [" + label + "] vertex id " + tmpVid + " with existing properties " + + tmpProperty.toString() ); + else + System.out.print(", " + tmpProperty.toString()); + ++propertyCount; + } + + if ( propertyCount > 0 ) { + System.out.println(""); + + tmpVtx.property(targetPropName,origVal); + System.out.println("INFO -- just did the add using " + longId + + " with label " + label + "] and updated it with the orig value (" + + origVal.toString() + ")"); + titanProperties = tmpVtx.properties(); // current properties + propertyCount = 0; + + + while( titanProperties.hasNext() ){ + tmpProperty = titanProperties.next(); + if ( propertyCount == 0 ) + System.out.print( "new property list for [" + label + "] vertex id " + tmpVid + " with existing properties " + + tmpProperty.toString() ); + else + System.out.print(", " + tmpProperty.toString()); + ++propertyCount; + } + + if ( propertyCount > 0 ) + System.out.println(""); + } + } + } else { + // targetNodeType is NA + + verts= graph.query().has("aai-node-type", targetNodeType).vertices(); + if( verts != null ){ + // We did find some matching vertices + Iterator <?> it = verts.iterator(); + Object propVal; + while( it.hasNext() ){ + TitanVertex v = (TitanVertex)it.next(); + label = v.label(); + longId = v.longId(); + targetVal = v.<Object>property(targetPropName).orElse(null); + origVal = v.<Object>property(propName).orElse(null); + + if ( origVal == null) + continue; + + if ( targetVal != null ) { + System.out.println( "vertex [" + label + "] id " + longId + " has " + targetPropName + + " with value " + targetVal + ", skip adding with value " + origVal); + continue; + } + titanProperties = v.properties(); // current properties + propertyCount = 0; + if ( v.<Object>property(propName).orElse(null) != null ) { + propVal = v.<Object>property(propName).orElse(null); + v.property(targetPropName, propVal); + ++vtxCount; + while( titanProperties.hasNext() ){ + + tmpProperty = titanProperties.next(); + if ( propertyCount == 0 ) + System.out.print( "adding to vertex id " + longId + " with existing properties " + + tmpProperty.toString() ); + else + System.out.print(", " + tmpProperty.toString()); + ++propertyCount; + } + + if ( propertyCount > 0 ) + System.out.println(""); + System.out.println("INFO -- just did the add target [" + targetNodeType + "] using " + longId + + " with label " + label + "] and updated it with the orig value (" + + propVal.toString() + ")"); + propertyCount = 0; + while( titanProperties.hasNext() ){ + + tmpProperty = titanProperties.next(); + if ( propertyCount == 0 ) + System.out.print( "new property list for vertex [" + label + "] id " + longId + " with existing properties " + + tmpProperty.toString() ); + else + System.out.print(", " + tmpProperty.toString()); + ++propertyCount; + } + + if ( propertyCount > 0 ) + System.out.println(""); + } + } + } + + } + + System.out.println("added properties data for " + vtxCount + " vertexes. noCommit " + noCommit); + if ( !noCommit ) + graph.tx().commit(); + } + catch (Exception ex) { + System.out.print("Threw a regular Exception:\n"); + System.out.println(ex.getMessage()); + } + finally { + if( graphMgt != null && graphMgt.isOpen() ){ + // Any changes that worked correctly should have already done their commits. + graphMgt.rollback(); + } + if( graph != null ){ + // Any changes that worked correctly should have already done their commits. + graph.tx().rollback(); + graph.close(); + } + } + + System.exit(0); + + }// End of main() + + +} + + diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java new file mode 100644 index 0000000..9cc6cf3 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/SchemaMod.java @@ -0,0 +1,441 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.Properties; +import java.util.TimeZone; +import java.util.UUID; + +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.slf4j.MDC; + +import org.openecomp.aai.dbmap.AAIGraph; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.ingestModel.DbMaps; +import org.openecomp.aai.ingestModel.IngestModelMoxyOxm; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.util.AAIConfig; +import org.openecomp.aai.util.AAIConstants; +import org.openecomp.aai.util.UniquePropertyCheck; +import com.att.eelf.configuration.Configuration; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.thinkaurelius.titan.core.Cardinality; +import com.thinkaurelius.titan.core.PropertyKey; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; +import com.thinkaurelius.titan.core.schema.TitanManagement; + +public class SchemaMod { + + private static final String FROMAPPID = "AAI-UTILS"; + private static final String TRANSID = UUID.randomUUID().toString(); + private static final String COMPONENT = "SchemaMod"; + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + SchemaMod.execute(args); + System.exit(0); + + }// End of main() + + /** + * Execute. + * + * @param args the args + */ + public static void execute(String[] args) { + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_SCHEMA_MOD_LOGBACK_PROPS); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + + EELFLogger logger = EELFManager.getInstance().getLogger(UniquePropertyCheck.class.getSimpleName()); + MDC.put("logFilenameAppender", SchemaMod.class.getSimpleName()); + + // NOTE -- We're just working with properties that are used for NODES + // for now. + + TitanGraph graph = null; + TitanManagement graphMgt = null; + + Boolean preserveData = true; + String propName = ""; + String targetDataType = ""; + String targetIndexInfo = ""; + String preserveDataFlag = ""; + + String usageString = "Usage: SchemaMod propertyName targetDataType targetIndexInfo preserveDataFlag \n"; + if (args.length != 4) { + String emsg = "Four Parameters are required. \n" + usageString; + logAndPrint(logger, emsg); + System.exit(1); + } else { + propName = args[0]; + targetDataType = args[1]; + targetIndexInfo = args[2]; + preserveDataFlag = args[3]; + } + + if (propName.equals("")) { + String emsg = "Bad parameter - propertyName cannot be empty. \n" + usageString; + logAndPrint(logger, emsg); + System.exit(1); + } else if (!targetDataType.equals("String") && !targetDataType.equals("Set<String>") + && !targetDataType.equals("Integer") && !targetDataType.equals("Long") + && !targetDataType.equals("Boolean")) { + String emsg = "Unsupported targetDataType. We only support String, Set<String>, Integer, Long or Boolean for now.\n" + + usageString; + logAndPrint(logger, emsg); + System.exit(1); + } else if (!targetIndexInfo.equals("uniqueIndex") && !targetIndexInfo.equals("index") + && !targetIndexInfo.equals("noIndex")) { + String emsg = "Unsupported IndexInfo. We only support: 'uniqueIndex', 'index' or 'noIndex'.\n" + + usageString; + logAndPrint(logger, emsg); + System.exit(1); + } else { + if (preserveDataFlag.equals("true")) { + preserveData = true; + } else if (preserveDataFlag.equals("false")) { + preserveData = false; + } else { + String emsg = "Unsupported preserveDataFlag. We only support: 'true' or 'false'.\n" + usageString; + logAndPrint(logger, emsg); + System.exit(1); + } + } + + try { + AAIConfig.init(); + ErrorLogHelper.loadProperties(); + } catch (Exception ae) { + String emsg = "Problem with either AAIConfig.init() or ErrorLogHelper.LoadProperties(). "; + logAndPrint(logger, emsg + "[" + ae.getMessage() + "]"); + System.exit(1); + } + + DbMaps dbMaps = null; + try { + ArrayList<String> apiVersions = new ArrayList<String>(); + apiVersions.add(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + final IngestModelMoxyOxm m = new IngestModelMoxyOxm(); + m.init(apiVersions, false); + dbMaps = m.dbMapsContainer.get(AAIConfig.get(AAIConstants.AAI_DEFAULT_API_VERSION_PROP)); + } catch (AAIException ae) { + String emsg = "Could not instantiate a copy of DbMaps. "; + logAndPrint(logger, emsg + "[" + ae.getMessage() + "]"); + System.exit(1); + } catch (Exception e) { + String emsg = "exception, Could not instantiate a copy of DbMaps. "; + logAndPrint(logger, emsg + "[" + e.getMessage() + "]"); + System.exit(1); + } + // Give a big warning if the DbMaps.PropertyDataTypeMap value does not + // agree with what we're doing + String warningMsg = ""; + /*if (!dbMaps.PropertyDataTypeMap.containsKey(propName)) { + String emsg = "Property Name = [" + propName + "] not found in PropertyDataTypeMap. "; + logAndPrint(logger, emsg); + System.exit(1); + } else { + String currentDataType = dbMaps.PropertyDataTypeMap.get(propName); + if (!currentDataType.equals(targetDataType)) { + warningMsg = "TargetDataType [" + targetDataType + "] does not match what is in DbRules.java (" + + currentDataType + ")."; + } + }*/ + + if (!warningMsg.equals("")) { + logAndPrint(logger, "\n>>> WARNING <<<< "); + logAndPrint(logger, ">>> " + warningMsg + " <<<"); + } + + logAndPrint(logger, ">>> Processing will begin in 5 seconds (unless interrupted). <<<"); + try { + // Give them a chance to back out of this + Thread.sleep(5000); + } catch (java.lang.InterruptedException ie) { + logAndPrint(logger, " DB Schema Update has been aborted. "); + System.exit(1); + } + + try { + Class dType = null; + if (targetDataType.equals("String")) { + dType = String.class; + } else if (targetDataType.equals("Set<String>")) { + dType = String.class; + } else if (targetDataType.equals("Integer")) { + dType = Integer.class; + } else if (targetDataType.equals("Boolean")) { + dType = Boolean.class; + } else if (targetDataType.equals("Character")) { + dType = Character.class; + } else if (targetDataType.equals("Long")) { + dType = Long.class; + } else if (targetDataType.equals("Float")) { + dType = Float.class; + } else if (targetDataType.equals("Double")) { + dType = Double.class; + } else { + String emsg = "Not able translate the targetDataType [" + targetDataType + "] to a Class variable.\n"; + logAndPrint(logger, emsg); + System.exit(1); + } + String cardinality = "SINGLE"; // Default cardinality to SINGLE + + if (targetDataType.equals("Set<String>")) { + cardinality = "SET"; + } + logAndPrint(logger, " ---- NOTE --- about to open graph (takes a little while)\n"); + + graph = AAIGraph.getInstance().getGraph(); + if (graph == null) { + String emsg = "Not able to get a graph object in SchemaMod.java\n"; + logAndPrint(logger, emsg); + System.exit(1); + } + + // Make sure this property is in the DB. + graphMgt = graph.openManagement(); + if (graphMgt == null) { + String emsg = "Not able to get a graph Management object in SchemaMod.java\n"; + logAndPrint(logger, emsg); + System.exit(1); + } + PropertyKey origPropKey = graphMgt.getPropertyKey(propName); + if (origPropKey == null) { + String emsg = "The propName = [" + propName + "] is not defined in our graph. "; + logAndPrint(logger, emsg); + System.exit(1); + } + + if (targetIndexInfo.equals("uniqueIndex")) { + // Make sure the data in the property being changed can have a + // unique-index put on it. + // Ie. if there are duplicate values, we will not be able to + // migrate the data back into the property. + Boolean foundDupesFlag = UniquePropertyCheck.runTheCheckForUniqueness(TRANSID, FROMAPPID, + graph.newTransaction(), propName, logger); + if (foundDupesFlag) { + logAndPrint(logger, + "\n\n!!!!!! >> Cannot add a uniqueIndex for the property: [" + propName + + "] because duplicate values were found. See the log for details on which" + + " nodes have this value. \nThey will need to be resolved (by updating those values to new" + + " values or deleting unneeded nodes) using the standard REST-API \n"); + System.exit(1); + } + } + + // -------------- If we made it to here - we must be OK with making + // this change ------------ + + // Rename this property to a backup name (old name with "retired_" + // appended plus a dateStr) + + SimpleDateFormat d = new SimpleDateFormat("MMddHHmm"); + d.setTimeZone(TimeZone.getTimeZone("GMT")); + String dteStr = d.format(new Date()).toString(); + String retiredName = propName + "-" + dteStr + "-RETIRED"; + graphMgt.changeName(origPropKey, retiredName); + + // Create a new property using the original property name and the + // targetDataType + PropertyKey freshPropKey = graphMgt.makePropertyKey(propName).dataType(dType) + .cardinality(Cardinality.valueOf(cardinality)).make(); + + // Create the appropriate index (if any) + if (targetIndexInfo.equals("uniqueIndex")) { + String freshIndexName = propName + dteStr; + graphMgt.buildIndex(freshIndexName, Vertex.class).addKey(freshPropKey).unique().buildCompositeIndex(); + } else if (targetIndexInfo.equals("index")) { + String freshIndexName = propName + dteStr; + graphMgt.buildIndex(freshIndexName, Vertex.class).addKey(freshPropKey).buildCompositeIndex(); + } + + logAndPrint(logger, "Committing schema changes with graphMgt.commit()"); + graphMgt.commit(); + graph.tx().commit(); + + // Get A new graph object + logAndPrint(logger, " ---- NOTE --- about to open a second graph object (takes a little while)\n"); + + // For each node that has this property, update the new from the old + // and then remove the + // old property from that node + Iterable<?> verts = null; + verts = graph.query().has(retiredName).vertices(); + Iterator<?> it = verts.iterator(); + int vtxCount = 0; + ArrayList<String> alreadySeenVals = new ArrayList<String>(); + while (it.hasNext()) { + vtxCount++; + TitanVertex tmpVtx = (TitanVertex) it.next(); + String tmpVid = tmpVtx.id().toString(); + + Object origVal = tmpVtx.<Object> property(retiredName).orElse(null); + if (preserveData) { + tmpVtx.property(propName, origVal); + if (targetIndexInfo.equals("uniqueIndex")) { + // We're working on a property that is being used as a + // unique index + String origValStr = ""; + if (origVal != null) { + origValStr = origVal.toString(); + } + if (alreadySeenVals.contains(origValStr)) { + // This property is supposed to be unique, but we've + // already seen this value in this loop + // This should have been caught up in the first part + // of SchemaMod, but since it wasn't, we + // will just log the problem. + logAndPrint(logger, + "\n\n ---------- ERROR - could not migrate the old data [" + origValStr + + "] for propertyName [" + propName + + "] because this property is having a unique index put on it."); + showPropertiesAndEdges(TRANSID, FROMAPPID, tmpVtx, logger); + logAndPrint(logger, "-----------------------------------\n"); + } else { + // Ok to add this prop in as a unique value + tmpVtx.property(propName, origVal); + logAndPrint(logger, + "INFO -- just did the add of the freshPropertyKey and updated it with the orig value (" + + origValStr + ")"); + } + alreadySeenVals.add(origValStr); + } else { + // We are not working with a unique index + tmpVtx.property(propName, origVal); + logAndPrint(logger, + "INFO -- just did the add of the freshPropertyKey and updated it with the orig value (" + + origVal.toString() + ")"); + } + } else { + // existing nodes just won't have that property anymore + // Not sure if we'd ever actually want to do this -- maybe + // we'd do this if the new + // data type was not compatible with the old? + } + tmpVtx.property(retiredName).remove(); + + logAndPrint(logger, "INFO -- just did the remove of the " + retiredName + " from this vertex. (vid=" + + tmpVid + ")"); + } + + logAndPrint(logger, "Updated data for " + vtxCount + " vertexes. Now call graph2.commit(). "); + graph.tx().commit(); + } catch (Exception ex) { + logAndPrint(logger, "Threw a regular Exception: "); + logAndPrint(logger, ex.getMessage()); + } finally { + if (graphMgt != null && graphMgt.isOpen()) { + // Any changes that worked correctly should have already done + // their commits. + graphMgt.rollback(); + } + if (graph != null) { + // Any changes that worked correctly should have already done + // their commits. + graph.tx().rollback(); + graph.close(); + } + } + + } + + /** + * Show properties and edges. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param tVert the t vert + * @param logger the logger + */ + private static void showPropertiesAndEdges(String transId, String fromAppId, TitanVertex tVert, EELFLogger logger) { + + if (tVert == null) { + logAndPrint(logger, "Null node passed to showPropertiesAndEdges."); + } else { + String nodeType = ""; + Object ob = tVert.<String> property("aai-node-type"); + if (ob == null) { + nodeType = "null"; + } else { + nodeType = ob.toString(); + } + + logAndPrint(logger, " AAINodeType/VtxID for this Node = [" + nodeType + "/" + tVert.id() + "]"); + logAndPrint(logger, " Property Detail: "); + Iterator<VertexProperty<Object>> pI = tVert.properties(); + while (pI.hasNext()) { + VertexProperty<Object> tp = pI.next(); + Object val = tp.value(); + logAndPrint(logger, "Prop: [" + tp.key() + "], val = [" + val + "] "); + } + + Iterator<Edge> eI = tVert.edges(Direction.BOTH); + if (!eI.hasNext()) { + logAndPrint(logger, "No edges were found for this vertex. "); + } + while (eI.hasNext()) { + TitanEdge ed = (TitanEdge) eI.next(); + String lab = ed.label(); + TitanVertex vtx = (TitanVertex) ed.otherVertex(tVert); + if (vtx == null) { + logAndPrint(logger, + " >>> COULD NOT FIND VERTEX on the other side of this edge edgeId = " + ed.id() + " <<< "); + } else { + String nType = vtx.<String> property("aai-node-type").orElse(null); + String vid = vtx.id().toString(); + logAndPrint(logger, "Found an edge (" + lab + ") from this vertex to a [" + nType + + "] node with VtxId = " + vid); + } + } + } + } // End of showPropertiesAndEdges() + + /** + * Log and print. + * + * @param logger the logger + * @param msg the msg + */ + protected static void logAndPrint(EELFLogger logger, String msg) { + System.out.println(msg); + logger.info(msg); + } + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java b/aai-resources/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java new file mode 100644 index 0000000..c2ebf6f --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/dbgen/UpdateEdgeTags.java @@ -0,0 +1,380 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.dbgen; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; + +import org.openecomp.aai.dbmap.AAIGraph; +import org.openecomp.aai.dbmodel.DbEdgeRules; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.logging.ErrorLogHelper; +import org.openecomp.aai.serialization.db.EdgeRule; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.util.AAIConfig; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanTransaction; +import com.thinkaurelius.titan.core.TitanVertex; + + + +public class UpdateEdgeTags { + + private static final String FROMAPPID = "AAI-DB"; + private static final String TRANSID = UUID.randomUUID().toString(); + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + if( args == null || args.length != 1 ){ + String msg = "usage: UpdateEdgeTags edgeRuleKey (edgeRuleKey can be either, all, or a rule key like 'nodeTypeA|nodeTypeB') \n"; + System.out.println(msg); + System.exit(1); + } + String edgeRuleKeyVal = args[0]; + + TitanGraph graph = null; + + HashMap <String,Object> edgeRuleHash = new HashMap <String,Object>(); + HashMap <String,Object> edgeRulesFullHash = new HashMap <String,Object>(); + HashMap <String,Object> edgeRuleLabelToKeyHash = new HashMap <String,Object>(); + ArrayList <String> labelMapsToMultipleKeys = new <String> ArrayList (); + + int tagCount = DbEdgeRules.EdgeInfoMap.size(); + // Loop through all the edge-rules make sure they look right and + // collect info about which labels support duplicate ruleKeys. + Iterator<String> edgeRulesIterator = DbEdgeRules.EdgeRules.keySet().iterator(); + while( edgeRulesIterator.hasNext() ){ + String ruleKey = edgeRulesIterator.next(); + Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(ruleKey); + Iterator <String> ruleItr = edRuleColl.iterator(); + if( ruleItr.hasNext() ){ + // For now, we only look for one type of edge between two nodes. + String fullRuleString = ruleItr.next(); + edgeRulesFullHash.put(ruleKey,fullRuleString); + // An EdgeRule is comma-separated and the first item is the edgeLabel + String [] rules = fullRuleString.split(","); + //System.out.println( "rules.length = " + rules.length + ", tagCount = " + tagCount ); + if( rules.length != tagCount ){ + String detail = "Bad EdgeRule data (itemCount=" + rules.length + ") for key = [" + ruleKey + "]."; + System.out.println(detail); + System.exit(0); + } + String edgeLabel = rules[0]; + if( edgeRuleLabelToKeyHash.containsKey(edgeLabel) ){ + // This label maps to more than one edge rule - we'll have to figure out + // which rule applies when we look at each edge that uses this label. + // So we take it out of mapping hash and add it to the list of ones that + // we'll need to look up later. + edgeRuleLabelToKeyHash.remove(edgeLabel); + labelMapsToMultipleKeys.add(edgeLabel); + } + else { + edgeRuleLabelToKeyHash.put(edgeLabel, ruleKey); + } + } + } + + if( ! edgeRuleKeyVal.equals( "all" ) ){ + // If they passed in a (non-"all") argument, that is the single edgeRule that they want to update. + // Note - the key looks like "nodeA|nodeB" as it appears in DbEdgeRules.EdgeRules + Collection <String> edRuleColl = DbEdgeRules.EdgeRules.get(edgeRuleKeyVal); + Iterator <String> ruleItr = edRuleColl.iterator(); + if( ruleItr.hasNext() ){ + // For now, we only look for one type of edge between two nodes (Ie. for one key). + String edRule = ruleItr.next(); + edgeRuleHash.put(edgeRuleKeyVal, edRule); + System.out.println("Adding this rule to list of rules to do: key = " + edgeRuleKeyVal + ", rule = [" + edRule + "]"); + } + else { + String msg = " Error - Unrecognized edgeRuleKey: [" + edgeRuleKeyVal + "]. "; + System.out.println(msg); + System.exit(0); + } + } + else { + // They didn't pass a target ruleKey in, so we'll work on all types of edges + edgeRuleHash.putAll(edgeRulesFullHash); + } + + try { + AAIConfig.init(); + System.out.println(" ---- NOTE --- about to open graph (takes a little while)--------\n"); + ErrorLogHelper.loadProperties(); + + graph = AAIGraph.getInstance().getGraph(); + + if( graph == null ){ + String emsg = "null graph object in updateEdgeTags() \n"; + System.out.println(emsg); + System.exit(0); + } + } + catch (AAIException e1) { + String msg = e1.getErrorObject().toString(); + System.out.println(msg); + System.exit(0); + } + catch (Exception e2) { + String msg = e2.toString(); + System.out.println(msg); + e2.printStackTrace(); + System.exit(0); + } + + TitanTransaction g = graph.newTransaction(); + try { + Iterable <?> edges = graph.query().edges(); + Iterator <?> edgeItr = edges.iterator(); + + // Loop through all edges and update their tags if they are a type we are interested in. + // Sorry about looping over everything, but for now, I can't find a way to just select one type of edge at a time...!? + StringBuffer sb; + boolean missingEdge = false; + while( edgeItr != null && edgeItr.hasNext() ){ + TitanEdge tmpEd = (TitanEdge) edgeItr.next(); + String edLab = tmpEd.label().toString(); + + // Since we have edgeLabels that can be used for different pairs of node-types, we have to + // look to see what nodeTypes this edge is connecting (if it is a label that could do this). + String derivedEdgeKey = ""; + if( labelMapsToMultipleKeys.contains(edLab) ){ + // need to figure out which key is right for this edge + derivedEdgeKey = deriveEdgeRuleKeyForThisEdge( TRANSID, FROMAPPID, g, tmpEd ); + } + else { + // This kind of label only maps to one key -- so we can just look it up. + if ( edgeRuleLabelToKeyHash.get(edLab) == null ) { + if ( !missingEdge ) { + System.out.print("DEBUG - missing edge(s) in edgeRuleLabelToKeyHash " + edgeRuleLabelToKeyHash.toString()); + missingEdge = true; + } + sb = new StringBuffer(); + Vertex vIn = null; + Vertex vOut = null; + Object obj = null; + vIn = tmpEd.vertex(Direction.IN); + if ( vIn != null ){ + obj = vIn.<String>property("aai-node-type").orElse(null); + if ( obj != null ) { + sb.append("from node-type " + obj.toString()); + + obj = vIn.id(); + sb.append(" id " + obj.toString()); + } else { + sb.append(" missing from node-type "); + } + } else { + sb.append(" missing inbound vertex "); + } + vOut = tmpEd.vertex(Direction.OUT); + if ( vOut != null ) { + obj = vOut.<String>property("aai-node-type").orElse(null); + if ( obj != null ) { + sb.append(" to node-type " + obj.toString()); + obj = vOut.id(); + sb.append(" id " + obj.toString()); + } else { + sb.append(" missing to node-type "); + } + } else { + sb.append(" missing to vertex "); + } + System.out.println("DEBUG - null entry for [" + edLab + "] between " + sb.toString()); + continue; + } + derivedEdgeKey = edgeRuleLabelToKeyHash.get(edLab).toString(); + } + + if( edgeRuleHash.containsKey(derivedEdgeKey) ){ + // this is an edge that we want to update + System.out.print("DEBUG - key = " + derivedEdgeKey + ", label = " + edLab + + ", for id = " + tmpEd.id().toString() + ", set: "); + Map<String,EdgeRule> edgeRules = getEdgeTagPropPutHash(TRANSID, FROMAPPID, derivedEdgeKey); + for (String key : edgeRules.keySet()) { + if (tmpEd.label().equals(key)) { + EdgeRules.getInstance().addProperties(tmpEd, edgeRules.get(key)); + } + } + System.out.print("\n"); + } + } // End of looping over all edges + graph.tx().commit(); + System.out.println("DEBUG - committed updates for listed edges " ); + } + catch (Exception e2) { + String msg = e2.toString(); + System.out.println(msg); + e2.printStackTrace(); + if( graph != null ){ + graph.tx().rollback(); + } + System.exit(0); + } + + System.exit(0); + + }// end of main() + + + /** + * Derive edge rule key for this edge. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param graph the graph + * @param tEdge the t edge + * @return String - key to look up edgeRule (fromNodeType|toNodeType) + * @throws AAIException the AAI exception + */ + public static String deriveEdgeRuleKeyForThisEdge( String transId, String fromAppId, TitanTransaction graph, + TitanEdge tEdge ) throws AAIException{ + + TitanVertex fromVtx = tEdge.outVertex(); + TitanVertex toVtx = tEdge.inVertex(); + String startNodeType = fromVtx.<String>property("aai-node-type").orElse(null); + String targetNodeType = toVtx.<String>property("aai-node-type").orElse(null); + String key = startNodeType + "|" + targetNodeType; + if( EdgeRules.getInstance().hasEdgeRule(startNodeType, targetNodeType) ){ + // We can use the node info in the order they were given + return( key ); + } + else { + key = targetNodeType + "|" + startNodeType; + if( EdgeRules.getInstance().hasEdgeRule(targetNodeType, startNodeType) ){ + return( key ); + } + else { + // Couldn't find a rule for this edge + throw new AAIException("AAI_6120", "No EdgeRule found for passed nodeTypes: " + startNodeType + ", " + + targetNodeType); + } + } + }// end of deriveEdgeRuleKeyForThisEdge() + + /** + * Gets the edge tag prop put hash 4 rule. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param edRule the ed rule + * @return the edge tag prop put hash 4 rule + * @throws AAIException the AAI exception + */ + public static HashMap <String,Object> getEdgeTagPropPutHash4Rule( String transId, String fromAppId, String edRule ) + throws AAIException{ + // For a given edgeRule - already pulled out of DbEdgeRules.EdgeRules -- parse out the "tags" that + // need to be set for this kind of edge. + // These are the Boolean properties like, "isParent", "usesResource" etc. + HashMap <String,Object> retEdgePropPutMap = new HashMap <String,Object>(); + + if( (edRule == null) || edRule.equals("") ){ + // No edge rule found for this + throw new AAIException("AAI_6120", "blank edRule passed to getEdgeTagPropPutHash4Rule()"); + } + + int tagCount = DbEdgeRules.EdgeInfoMap.size(); + String [] rules = edRule.split(","); + if( rules.length != tagCount ){ + throw new AAIException("AAI_6121", "Bad EdgeRule data (itemCount =" + rules.length + ") for rule = [" + edRule + "]."); + } + + // In DbEdgeRules.EdgeRules -- What we have as "edRule" is a comma-delimited set of strings. + // The first item is the edgeLabel. + // The second in the list is always "direction" which is always OUT for the way we've implemented it. + // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to + // tags as defined in EdgeInfoMap. + // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it + for( int i = DbEdgeRules.firstTagIndex; i < tagCount; i++ ){ + String booleanStr = rules[i]; + Integer mapKey = new Integer(i); + String propName = DbEdgeRules.EdgeInfoMap.get(mapKey); + String revPropName = propName + "-REV"; + + if( booleanStr.equals("true") ){ + retEdgePropPutMap.put(propName, true); + retEdgePropPutMap.put(revPropName,false); + } + else if( booleanStr.equals("false") ){ + retEdgePropPutMap.put(propName, false); + retEdgePropPutMap.put(revPropName,false); + } + else if( booleanStr.equals("reverse") ){ + retEdgePropPutMap.put(propName, false); + retEdgePropPutMap.put(revPropName,true); + } + else { + throw new AAIException("AAI_6121", "Bad EdgeRule data for rule = [" + edRule + "], val = [" + booleanStr + "]."); + } + + } + + return retEdgePropPutMap; + + } // End of getEdgeTagPropPutHash() + + + /** + * Gets the edge tag prop put hash. + * + * @param transId the trans id + * @param fromAppId the from app id + * @param edgeRuleKey the edge rule key + * @return the edge tag prop put hash + * @throws AAIException the AAI exception + */ + public static Map<String, EdgeRule> getEdgeTagPropPutHash( String transId, String fromAppId, String edgeRuleKey ) + throws AAIException{ + // For a given edgeRuleKey (nodeTypeA|nodeTypeB), look up the rule that goes with it in + // DbEdgeRules.EdgeRules and parse out the "tags" that need to be set on each edge. + // These are the Boolean properties like, "isParent", "usesResource" etc. + // Note - this code is also used by the updateEdgeTags.java code + + String[] edgeRuleKeys = edgeRuleKey.split("\\|"); + + if (edgeRuleKeys.length < 2 || ! EdgeRules.getInstance().hasEdgeRule(edgeRuleKeys[0], edgeRuleKeys[1])) { + throw new AAIException("AAI_6120", "Could not find an DbEdgeRule entry for passed edgeRuleKey (nodeTypeA|nodeTypeB): " + edgeRuleKey + "."); + } + + Map<String, EdgeRule> edgeRules = EdgeRules.getInstance().getEdgeRules(edgeRuleKeys[0], edgeRuleKeys[1]); + + return edgeRules; + + } // End of getEdgeTagPropPutHash() + + + +} + + + diff --git a/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java index fc11e5d..c016bb1 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java +++ b/aai-resources/src/main/java/org/openecomp/aai/dmaap/AAIDmaapEventJMSConsumer.java @@ -126,7 +126,7 @@ public class AAIDmaapEventJMSConsumer implements MessageListener { //String aaiEvent = ""; //String eventName = ""; - + //String environment = ""; //if (message instanceof TextMessage) { diff --git a/aai-resources/src/main/java/org/openecomp/aai/migration/EventAction.java b/aai-resources/src/main/java/org/openecomp/aai/migration/EventAction.java new file mode 100644 index 0000000..82b7cad --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/migration/EventAction.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.migration; + +public enum EventAction { + CREATE, + UPDATE, + DELETE +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/migration/NotificationHelper.java b/aai-resources/src/main/java/org/openecomp/aai/migration/NotificationHelper.java new file mode 100644 index 0000000..b956705 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/migration/NotificationHelper.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.migration; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.HashMap; +import java.util.List; + +import javax.ws.rs.core.Response.Status; + +import org.apache.tinkerpop.gremlin.structure.Vertex; + +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.rest.ueb.UEBNotification; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import org.openecomp.aai.serialization.engines.query.QueryEngine; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public class NotificationHelper { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(NotificationHelper.class); + protected final DBSerializer serializer; + protected final Loader loader; + protected final TransactionalGraphEngine engine; + protected final String transactionId; + protected final String sourceOfTruth; + protected final UEBNotification notification; + + public NotificationHelper(Loader loader, DBSerializer serializer, TransactionalGraphEngine engine, String transactionId, String sourceOfTruth) { + this.loader = loader; + this.serializer = serializer; + this.engine = engine; + this.transactionId = transactionId; + this.sourceOfTruth = sourceOfTruth; + this.notification = new UEBNotification(loader); + } + + public void addEvent(Vertex v, Introspector obj, EventAction action, URI uri) throws UnsupportedEncodingException, AAIException { + HashMap<String, Introspector> relatedObjects = new HashMap<>(); + Status status = mapAction(action); + if (!obj.isTopLevel()) { + relatedObjects = this.getRelatedObjects(serializer, engine.getQueryEngine(), v); + } + notification.createNotificationEvent(transactionId, sourceOfTruth, status, uri, obj, relatedObjects); + + } + + private HashMap<String, Introspector> getRelatedObjects(DBSerializer serializer, QueryEngine queryEngine, Vertex v) throws AAIException { + HashMap<String, Introspector> relatedVertices = new HashMap<>(); + List<Vertex> vertexChain = queryEngine.findParents(v); + for (Vertex vertex : vertexChain) { + try { + final Introspector vertexObj = serializer.getVertexProperties(vertex); + relatedVertices.put(vertexObj.getObjectId(), vertexObj); + } catch (AAIUnknownObjectException | UnsupportedEncodingException e) { + LOGGER.warn("Unable to get vertex properties, partial list of related vertices returned"); + } + + } + + return relatedVertices; + } + + private Status mapAction(EventAction action) { + if (EventAction.CREATE.equals(action)) { + return Status.CREATED; + } else if (EventAction.UPDATE.equals(action)) { + return Status.OK; + } else if (EventAction.DELETE.equals(action)) { + return Status.NO_CONTENT; + } else { + return Status.OK; + } + } + + public void triggerEvents() throws AAIException { + notification.triggerEvents(); + } +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/migration/VertexMerge.java b/aai-resources/src/main/java/org/openecomp/aai/migration/VertexMerge.java new file mode 100644 index 0000000..6bb17a9 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/migration/VertexMerge.java @@ -0,0 +1,245 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.migration; + +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Vertex; + +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.introspection.Introspector; +import org.openecomp.aai.introspection.Loader; +import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException; +import org.openecomp.aai.serialization.db.DBSerializer; +import org.openecomp.aai.serialization.db.EdgeRules; +import org.openecomp.aai.serialization.db.EdgeType; +import org.openecomp.aai.serialization.engines.TransactionalGraphEngine; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +/** + * This class recursively merges two vertices passed in. + * <br> + * You can start with any two vertices, but after the vertices are merged based off the equality of their keys + * + */ +public class VertexMerge { + + private final EELFLogger logger = EELFManager.getInstance().getLogger(this.getClass().getSimpleName()); + + private final GraphTraversalSource g; + private final TransactionalGraphEngine engine; + private final DBSerializer serializer; + private final EdgeRules rules; + private final Loader loader; + private final NotificationHelper notificationHelper; + private final boolean hasNotifications; + private VertexMerge(Builder builder) { + this.engine = builder.getEngine(); + this.serializer = builder.getSerializer(); + this.g = engine.asAdmin().getTraversalSource(); + this.rules = EdgeRules.getInstance(); + this.loader = builder.getLoader(); + this.notificationHelper = builder.getHelper(); + this.hasNotifications = builder.isHasNotifications(); + } + + /** + * Merges vertices. forceCopy is a map of the form [{aai-node-type}:{set of properties}] + * @param primary + * @param secondary + * @param forceCopy + * @throws AAIException + * @throws UnsupportedEncodingException + */ + public void performMerge(Vertex primary, Vertex secondary, Map<String, Set<String>> forceCopy) throws AAIException, UnsupportedEncodingException { + final Optional<Introspector> secondarySnapshot; + if (this.hasNotifications) { + secondarySnapshot = Optional.of(serializer.getLatestVersionView(secondary)); + } else { + secondarySnapshot = Optional.empty(); + } + mergeProperties(primary, secondary, forceCopy); + + Collection<Vertex> secondaryChildren = this.engine.getQueryEngine().findChildren(secondary); + Collection<Vertex> primaryChildren = this.engine.getQueryEngine().findChildren(primary); + + mergeChildren(primary, secondary, primaryChildren, secondaryChildren, forceCopy); + + Collection<Vertex> secondaryCousins = this.engine.getQueryEngine().findCousinVertices(secondary); + Collection<Vertex> primaryCousins = this.engine.getQueryEngine().findCousinVertices(primary); + + secondaryCousins.removeAll(primaryCousins); + logger.info("removing vertex after merge: " + secondary ); + if (this.hasNotifications && secondarySnapshot.isPresent()) { + this.notificationHelper.addEvent(secondary, secondarySnapshot.get(), EventAction.DELETE, this.serializer.getURIForVertex(secondary, false)); + } + secondary.remove(); + for (Vertex v : secondaryCousins) { + this.rules.addEdgeIfPossible(g, v, primary); + } + if (this.hasNotifications) { + final Introspector primarySnapshot = serializer.getLatestVersionView(primary); + this.notificationHelper.addEvent(primary, primarySnapshot, EventAction.UPDATE, this.serializer.getURIForVertex(primary, false)); + } + } + + /** + * This method may go away if we choose to event on each modification performed + * @param primary + * @param secondary + * @param forceCopy + * @throws AAIException + * @throws UnsupportedEncodingException + */ + protected void performMergeHelper(Vertex primary, Vertex secondary, Map<String, Set<String>> forceCopy) throws AAIException, UnsupportedEncodingException { + mergeProperties(primary, secondary, forceCopy); + + Collection<Vertex> secondaryChildren = this.engine.getQueryEngine().findChildren(secondary); + Collection<Vertex> primaryChildren = this.engine.getQueryEngine().findChildren(primary); + + mergeChildren(primary, secondary, primaryChildren, secondaryChildren, forceCopy); + + Collection<Vertex> secondaryCousins = this.engine.getQueryEngine().findCousinVertices(secondary); + Collection<Vertex> primaryCousins = this.engine.getQueryEngine().findCousinVertices(primary); + + secondaryCousins.removeAll(primaryCousins); + secondary.remove(); + for (Vertex v : secondaryCousins) { + this.rules.addEdgeIfPossible(g, v, primary); + } + } + + private String getURI(Vertex v) throws UnsupportedEncodingException, AAIException { + Introspector obj = loader.introspectorFromName(v.<String>property(AAIProperties.NODE_TYPE).orElse("")); + this.serializer.dbToObject(Collections.singletonList(v), obj, 0, true, "false"); + return obj.getURI(); + + } + private void mergeChildren(Vertex primary, Vertex secondary, Collection<Vertex> primaryChildren, Collection<Vertex> secondaryChildren, Map<String, Set<String>> forceCopy) throws UnsupportedEncodingException, AAIException { + Map<String, Vertex> primaryMap = uriMap(primaryChildren); + Map<String, Vertex> secondaryMap = uriMap(secondaryChildren); + Set<String> primaryKeys = new HashSet<>(primaryMap.keySet()); + Set<String> secondaryKeys = new HashSet<>(secondaryMap.keySet()); + primaryKeys.retainAll(secondaryKeys); + final Set<String> mergeItems = new HashSet<>(primaryKeys); + primaryKeys = new HashSet<>(primaryMap.keySet()); + secondaryKeys = new HashSet<>(secondaryMap.keySet()); + secondaryKeys.removeAll(primaryKeys); + final Set<String> copyItems = new HashSet<>(secondaryKeys); + + for (String key : mergeItems) { + this.performMergeHelper(primaryMap.get(key), secondaryMap.get(key), forceCopy); + } + + for (String key : copyItems) { + this.rules.addTreeEdgeIfPossible(g, secondaryMap.get(key), primary); + this.serializer.getEdgeBetween(EdgeType.TREE, secondary, secondaryMap.get(key)).remove(); + } + + } + + private Map<String, Vertex> uriMap(Collection<Vertex> vertices) throws UnsupportedEncodingException, AAIException { + final Map<String, Vertex> result = new HashMap<>(); + for (Vertex v : vertices) { + result.put(getURI(v), v); + } + return result; + } + + private void mergeProperties(Vertex primary, Vertex secondary, Map<String, Set<String>> forceCopy) throws AAIUnknownObjectException { + final String primaryType = primary.<String>property(AAIProperties.NODE_TYPE).orElse(""); + final String secondaryType = secondary.<String>property(AAIProperties.NODE_TYPE).orElse(""); + + final Introspector secondaryObj = loader.introspectorFromName(secondaryType); + secondary.properties().forEachRemaining(prop -> { + if (!primary.property(prop.key()).isPresent() || forceCopy.getOrDefault(primaryType, new HashSet<String>()).contains(prop.key())) { + primary.property(prop.key(), prop.value()); + } + if (primary.property(prop.key()).isPresent() && secondary.property(prop.key()).isPresent() && secondaryObj.isListType(prop.key())) { + mergeCollection(primary, prop.key(), secondary.values(prop.key())); + } + }); + } + private void mergeCollection(Vertex primary, String propName, Iterator<Object> secondaryValues) { + secondaryValues.forEachRemaining(item -> { + primary.property(propName, item); + }); + } + + + public static class Builder { + private final TransactionalGraphEngine engine; + + private final DBSerializer serializer; + private final Loader loader; + private NotificationHelper helper = null; + private boolean hasNotifications = false; + public Builder(Loader loader, TransactionalGraphEngine engine, DBSerializer serializer) { + this.loader = loader; + this.engine = engine; + this.serializer = serializer; + } + + public Builder addNotifications(NotificationHelper helper) { + this.helper = helper; + this.hasNotifications = true; + return this; + } + + + public VertexMerge build() { + return new VertexMerge(this); + } + + protected TransactionalGraphEngine getEngine() { + return engine; + } + + protected DBSerializer getSerializer() { + return serializer; + } + + protected Loader getLoader() { + return loader; + } + + protected NotificationHelper getHelper() { + return helper; + } + + protected boolean isHasNotifications() { + return hasNotifications; + } + + } + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java b/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java index 7af432d..ca5fc33 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/LegacyMoxyConsumer.java @@ -140,6 +140,7 @@ public class LegacyMoxyConsumer extends RESTAPI { dbEngine = httpEntry.getDbEngine(); URI uriObject = UriBuilder.fromPath(uri).build(); + this.validateURI(uriObject); QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); @@ -421,7 +422,8 @@ public class LegacyMoxyConsumer extends RESTAPI { throw new AAIException("AAI_3102", "You must supply a relationship"); } URI uriObject = UriBuilder.fromPath(uri).build(); - + this.validateURI(uriObject); + QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); Introspector wrappedEntity = loader.unmarshal("relationship", content, org.openecomp.aai.restcore.MediaType.getEnum(this.getInputMediaType(inputMediaType))); @@ -524,7 +526,6 @@ public class LegacyMoxyConsumer extends RESTAPI { Boolean success = true; try { - validateRequest(info); version = Version.valueOf(versionParam); @@ -533,7 +534,7 @@ public class LegacyMoxyConsumer extends RESTAPI { loader = httpEntry.getLoader(); dbEngine = httpEntry.getDbEngine(); URI uriObject = UriBuilder.fromPath(uri).build(); - + this.validateURI(uriObject); QueryParser uriQuery = dbEngine.getQueryBuilder().createQueryFromURI(uriObject); String objName = uriQuery.getResultType(); if (content.length() == 0) { @@ -580,4 +581,14 @@ public class LegacyMoxyConsumer extends RESTAPI { return response; } + private void validateURI(URI uri) throws AAIException { + if (hasRelatedTo(uri)) { + throw new AAIException("AAI_3010"); + } + } + private boolean hasRelatedTo(URI uri) { + + return uri.toString().contains("/" + RestTokens.COUSIN + "/"); + + } } diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/RestTokens.java b/aai-resources/src/main/java/org/openecomp/aai/rest/RestTokens.java new file mode 100644 index 0000000..13bfe65 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/RestTokens.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.rest; + +public enum RestTokens { + + COUSIN("related-to"); + private final String name; + + private RestTokens(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8Models.java b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8Models.java new file mode 100644 index 0000000..3eb53da --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8Models.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.rest.retired; + +import javax.ws.rs.Path; + +@Path("{version: v[78]}/service-design-and-creation/models") +public class V7V8Models extends RetiredConsumer { + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java new file mode 100644 index 0000000..3f022a2 --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/retired/V7V8NamedQueries.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.rest.retired; + +import javax.ws.rs.Path; + +@Path("{version: v[78]}/service-design-and-creation/named-queries") +public class V7V8NamedQueries extends RetiredConsumer { + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java index 389d296..e473e9d 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/NotificationEvent.java @@ -31,12 +31,13 @@ import org.openecomp.aai.util.StoreNotificationEvent; */ public class NotificationEvent { - private Loader loader = null; + private final Loader loader; - private Introspector eventHeader = null; - - private Introspector obj = null; + private final Introspector eventHeader; + private final Introspector obj; + private final String transactionId; + private final String sourceOfTruth; /** * Instantiates a new notification event. * @@ -44,10 +45,12 @@ public class NotificationEvent { * @param eventHeader the event header * @param obj the obj */ - public NotificationEvent (Loader loader, Introspector eventHeader, Introspector obj) { + public NotificationEvent (Loader loader, Introspector eventHeader, Introspector obj, String transactionId, String sourceOfTruth) { this.loader = loader; this.eventHeader = eventHeader; this.obj = obj; + this.transactionId = transactionId; + this.sourceOfTruth = sourceOfTruth; } /** @@ -57,7 +60,7 @@ public class NotificationEvent { */ public void trigger() throws AAIException { - StoreNotificationEvent sne = new StoreNotificationEvent(); + StoreNotificationEvent sne = new StoreNotificationEvent(transactionId, sourceOfTruth); sne.storeEvent(loader, eventHeader, obj); diff --git a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java index 397082f..8cb16e1 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java +++ b/aai-resources/src/main/java/org/openecomp/aai/rest/ueb/UEBNotification.java @@ -50,7 +50,6 @@ public class UEBNotification { private Loader currentVersionLoader = null; protected List<NotificationEvent> events = null; - private String urlBase = null; private Version notificationVersion = null; /** @@ -61,7 +60,6 @@ public class UEBNotification { public UEBNotification(Loader loader) { events = new ArrayList<>(); currentVersionLoader = LoaderFactory.createLoaderForVersion(loader.getModelType(), AAIProperties.LATEST); - urlBase = AAIConfig.get("aai.server.url.base",""); notificationVersion = Version.valueOf(AAIConfig.get("aai.notification.current.version","v10")); } @@ -78,7 +76,7 @@ public class UEBNotification { * @throws IllegalArgumentException the illegal argument exception * @throws UnsupportedEncodingException the unsupported encoding exception */ - public void createNotificationEvent(String transactionId, String sourceOfTruth, Status status, URI uri, Introspector obj, HashMap<String, Introspector> relatedObjects) throws AAIException, IllegalArgumentException, UnsupportedEncodingException { + public void createNotificationEvent(String transactionId, String sourceOfTruth, Status status, URI uri, Introspector obj, HashMap<String, Introspector> relatedObjects) throws AAIException, UnsupportedEncodingException { String action = "UPDATE"; @@ -96,9 +94,9 @@ public class UEBNotification { String entityLink = ""; if (uri.toString().startsWith("/")) { - entityLink = urlBase + notificationVersion + uri; + entityLink = "/aai/" + notificationVersion + uri; } else { - entityLink = urlBase + notificationVersion + "/" + uri; + entityLink = "/aai/" + notificationVersion + "/" + uri; } @@ -148,7 +146,7 @@ public class UEBNotification { } } - final NotificationEvent event = new NotificationEvent(currentVersionLoader, eventHeader, eventObject); + final NotificationEvent event = new NotificationEvent(currentVersionLoader, eventHeader, eventObject, transactionId, sourceOfTruth); events.add(event); } catch (AAIUnknownObjectException e) { throw new RuntimeException("Fatal error - notification-event-header object not found!"); diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/DataConversionHelper.java b/aai-resources/src/main/java/org/openecomp/aai/util/DataConversionHelper.java new file mode 100644 index 0000000..c1d601d --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/util/DataConversionHelper.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.util; + + +/** + * Utility to convert data from one form to another + * + */ +public class DataConversionHelper { + + public static final String IPVERSION_IPV4 = "ipv4"; + public static final String IPVERSION_IPV6 = "ipv6"; + public static final String IPVERSION_UNKNOWN = "unknown"; + + /** + * Instantiates a new data conversion helper. + */ + public DataConversionHelper() { } + + /** + * Convert from 4 or 6 to ipv4 or ipv6. Returns unknown if 4 or 6 not passed. + * @param numVal expects good input but won't error if that's not what's passed + * @return IPVERSION constant, . + * @see org.openecomp.aai.domain.yang.IpVersion + */ + public static String convertIPVersionNumToString(String numVal) { + if ("4".equals(numVal)) return IPVERSION_IPV4; + else if ("6".equals(numVal))return IPVERSION_IPV6; + else return IPVERSION_UNKNOWN; + } + + /** + * Convert from ipv4 or ipv6 to 4 or 6. Returns 0 on bad input. + * @param stringVal expects good input but won't error if that's not what's passed + * @return 4 or 6, or 0 if a bad string is sent. + * @see org.openecomp.aai.domain.yang.IpVersion + */ + public static String convertIPVersionStringToNum(String stringVal) { + if (IPVERSION_IPV4.equals(stringVal)) return "4"; + else if (IPVERSION_IPV6.equals(stringVal)) return "6"; + else return "0"; + } + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/DeleteResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/DeleteResource.java index 81ee621..5e60c5c 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/DeleteResource.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/DeleteResource.java @@ -41,7 +41,7 @@ import com.google.common.base.CaseFormat; public class DeleteResource { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(DeleteResource.class); + private static EELFLogger LOGGER; private static final String FROMAPPID = "AAI-TOOLS"; private static final String TRANSID = UUID.randomUUID().toString(); // the logic below to parse the url is dependent on the node types @@ -64,7 +64,7 @@ public class DeleteResource { Properties props = System.getProperties(); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_DELTOOL_LOGBACK_PROPS); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); - + LOGGER = EELFManager.getInstance().getLogger(DeleteResource.class); String url = null; try { if ((args.length < 1) || ((args.length > 1) )) { @@ -113,8 +113,12 @@ public class DeleteResource { String resourceClass = CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, resource); resourceClass = "org.openecomp.aai.domain.yang." + resourceClass; - LOGGER.debug("class=" + resourceClass); - LOGGER.debug("path=" + path); + String dMsg = "class=" + resourceClass; + System.out.println(dMsg); + LOGGER.debug(dMsg); + dMsg = "path=" + path; + System.out.println(dMsg); + LOGGER.debug(dMsg); if (bResVersionEnabled) { @@ -127,7 +131,9 @@ public class DeleteResource { { RestController.<T>Get(t, FROMAPPID, TRANSID, path, restObj, false); t = restObj.get(); - LOGGER.info(" GET resoruceversion succeeded\n"); + String infMsg = " GET resoruceversion succeeded\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); String resourceUpdateVersion = GetResourceVersion(t); path += "?resource-version=" + resourceUpdateVersion; } catch (AAIException e) { @@ -150,12 +156,14 @@ public class DeleteResource { String confirm = s.next(); if (!confirm.equalsIgnoreCase("y")) { - LOGGER.info("User chose to exit before deleting"); + String infMsg = "User chose to exit before deleting"; + System.out.println(infMsg); + LOGGER.info(infMsg); System.exit(1); } RestController.Delete(FROMAPPID, TRANSID, path); - + s.close(); System.exit(0); diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/GetResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/GetResource.java index f16efb3..a0a3297 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/GetResource.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/GetResource.java @@ -36,7 +36,7 @@ import com.sun.jersey.api.client.ClientResponse; public class GetResource { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(GetResource.class); + private static EELFLogger LOGGER; private static final String FROMAPPID = "AAI-TOOLS"; private static final String TRANSID = UUID.randomUUID().toString(); private static final String USAGE_STRING = "Usage: getTool.sh <resource-path> \n + " @@ -53,7 +53,7 @@ public class GetResource { Properties props = System.getProperties(); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_GETRES_LOGBACK_PROPS); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); - + LOGGER = EELFManager.getInstance().getLogger(GetResource.class); String url = null; try { if (args.length < 1) { @@ -66,16 +66,23 @@ public class GetResource { url = args[0].replaceFirst("^/", ""); url = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + url; - LOGGER.debug("url=" + url); + String dmsg = "url=" + url; + LOGGER.debug( dmsg ); + System.out.println( dmsg ); + getNode(url); System.exit(0); } } catch (AAIException e) { - LOGGER.error("GET failed: " + e.getMessage()); + String emsg = "GET failed: " + e.getMessage(); + System.out.println(emsg); + LOGGER.error(emsg); ErrorLogHelper.logException(e); System.exit(1); } catch (Exception e) { - LOGGER.error("GET failed: " + e.getMessage()); + String emsg = "GET failed: " + e.getMessage(); + System.out.println(emsg); + LOGGER.error(emsg); ErrorLogHelper.logError("AAI_7402", e.getMessage()); System.exit(1); } @@ -113,8 +120,10 @@ public class GetResource { .get(ClientResponse.class); if (cres.getStatus() == 404) { // resource not found - LOGGER.info("\nResource does not exist: " + cres.getStatus() - + ":" + cres.getEntity(String.class)); + String infmsg = "\nResource does not exist: " + cres.getStatus() + + ":" + cres.getEntity(String.class); + System.out.println(infmsg); + LOGGER.info(infmsg); throw new AAIException("AAI_7404", "Resource does not exist"); } else if (cres.getStatus() == 200){ String msg = cres.getEntity(String.class); @@ -122,10 +131,13 @@ public class GetResource { Object json = mapper.readValue(msg, Object.class); String indented = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(json); + System.out.println(indented); LOGGER.info(indented); } else { - LOGGER.error("Getting the Resource failed: " + cres.getStatus() - + ":\n" + cres.getEntity(String.class)); + String emsg = "Getting the Resource failed: " + cres.getStatus() + + ":\n" + cres.getEntity(String.class); + System.out.println(emsg); + LOGGER.error(emsg); throw new AAIException("AAI_7402", "Error during GET"); } } catch (AAIException e) { diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java b/aai-resources/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java index 89562f7..000ebd0 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/HttpsAuthClient.java @@ -176,4 +176,62 @@ public class HttpsAuthClient{ } + + public static Client getClient() throws KeyManagementException { + + ClientConfig config = new DefaultClientConfig(); + config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); + config.getClasses().add(org.openecomp.aai.restcore.CustomJacksonJaxBJsonProvider.class); + + SSLContext ctx = null; + try { + String truststore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_FILENAME); + String truststore_password = AAIConfig.get(AAIConstants.AAI_TRUSTSTORE_PASSWD); + String keystore_path = AAIConstants.AAI_HOME_ETC_AUTH + AAIConfig.get(AAIConstants.AAI_KEYSTORE_FILENAME); + String keystore_password = AAIConfig.get(AAIConstants.AAI_KEYSTORE_PASSWD); + + System.setProperty("javax.net.ssl.trustStore", truststore_path); + System.setProperty("javax.net.ssl.trustStorePassword", truststore_password); + HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){ + public boolean verify(String string,SSLSession ssls) { + return true; + } + }); + + ctx = SSLContext.getInstance("TLSv1.2"); + KeyManagerFactory kmf = null; + try { + kmf = KeyManagerFactory.getInstance("SunX509"); + FileInputStream fin = new FileInputStream(keystore_path); + KeyStore ks = KeyStore.getInstance("PKCS12"); + char[] pwd = keystore_password.toCharArray(); + ks.load(fin, pwd); + kmf.init(ks, pwd); + } catch (Exception e) { + System.out.println("Error setting up kmf: exiting"); + e.printStackTrace(); + System.exit(1); + } + + ctx.init(kmf.getKeyManagers(), null, null); + config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, + new HTTPSProperties( new HostnameVerifier() { + @Override + public boolean verify( String s, SSLSession sslSession ) { + return true; + } + }, ctx)); + } catch (Exception e) { + System.out.println("Error setting up config: exiting"); + e.printStackTrace(); + System.exit(1); + } + + Client client = Client.create(config); + // uncomment this line to get more logging for the request/response + // client.addFilter(new LoggingFilter(System.out)); + + return client; + } + } diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java b/aai-resources/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java new file mode 100644 index 0000000..befa59c --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/util/JettyObfuscationConversionCommandLineUtil.java @@ -0,0 +1,99 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.util; + +import org.apache.commons.cli.BasicParser; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.eclipse.jetty.util.security.Password; + +import org.openecomp.aai.exceptions.AAIException; + +/* + * The purpose of this class is to be a tool for + * manually applying jetty obfuscation/deobfuscation + * so that one can obfuscate the various passwords/secrets + * in aaiconfig.properties. + * + * Originally, they were being encrypted by a similar + * command line utility, however the encryption key + * was being hardcoded in the src package + * which is a security violation. + * Since this ultimately just moved the problem of how + * to hide secrets to a different secret in a different file, + * and since that encryption was really just being done to + * obfuscate those values in case someone needed to look at + * properties with others looking at their screen, + * we decided that jetty obfuscation would be adequate + * for that task as well as + * removing the "turtles all the way down" secret-to-hide- + * the-secret-to-hide-the-secret problem. + */ +public class JettyObfuscationConversionCommandLineUtil { + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args){ + Options options = new Options(); + options.addOption("e", true, "obfuscate the given string"); + options.addOption("d", true, "deobfuscate the given string"); + + CommandLineParser parser = new BasicParser(); + + try { + CommandLine cmd = parser.parse(options, args); + String toProcess = null; + + if (cmd.hasOption("e")){ + toProcess = cmd.getOptionValue("e"); + String encoded = Password.obfuscate(toProcess); + System.out.println(encoded); + } else if (cmd.hasOption("d")) { + toProcess = cmd.getOptionValue("d"); + String decoded_str = Password.deobfuscate(toProcess); + System.out.println(decoded_str); + } else { + usage(); + } + } catch (ParseException e) { + System.out.println("failed to parse input"); + System.out.println(e.toString()); + usage(); + } catch (Exception e) { + System.out.println("exception:" + e.toString()); + } + } + + /** + * Usage. + */ + private static void usage(){ + System.out.println("usage:");; + System.out.println("-e [string] to obfuscate"); + System.out.println("-d [string] to deobfuscate"); + System.out.println("-h help"); + } +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/PostResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/PostResource.java index 72fcd86..1caeb09 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/PostResource.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/PostResource.java @@ -41,7 +41,7 @@ import com.google.common.base.CaseFormat; */ public class PostResource { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PostResource.class); + private static EELFLogger LOGGER; private static final String FROMAPPID = "AAI-TOOLS"; private static final String TRANSID = UUID.randomUUID().toString(); private static final String USAGE_STRING = "Usage: postTool.sh <resource-path> <filename>\n" + @@ -61,7 +61,7 @@ public class PostResource { Properties props = System.getProperties(); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_POSTTOOL_LOGBACK_PROPS); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); - + LOGGER = EELFManager.getInstance().getLogger(PostResource.class); try { if (args.length < 2) { System.out.println("Insufficient arguments"); @@ -85,8 +85,13 @@ public class PostResource { System.exit(1); } - LOGGER.debug("class=" + resourceClass); - LOGGER.debug("path=" + path); + String dMsg = "class=" + resourceClass; + System.out.println(dMsg); + LOGGER.debug(dMsg); + + dMsg = "path=" + path; + System.out.println(dMsg); + LOGGER.debug(dMsg); @SuppressWarnings("unchecked") T resJson1 = (T)readJsonFile(Class.forName(resourceClass), args[1]); @@ -95,9 +100,17 @@ public class PostResource { ObjectMapper mapper = new ObjectMapper(); Object json = mapper.readValue(response, Object.class); - LOGGER.info(" POST succeeded\n"); - LOGGER.info("Response = " + mapper.writer().withDefaultPrettyPrinter().writeValueAsString(json)); - LOGGER.info("\nDone!!"); + String infMsg = " POST succeeded\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + + infMsg = "Response = " + mapper.writer().withDefaultPrettyPrinter().writeValueAsString(json); + System.out.println(infMsg); + LOGGER.info(infMsg); + + infMsg = "\nDone!!"; + System.out.println(infMsg); + LOGGER.info(infMsg); System.exit(0); diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/PutResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/PutResource.java index 70fccb1..b4275b7 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/PutResource.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/PutResource.java @@ -48,7 +48,7 @@ import com.sun.jersey.api.client.ClientResponse; */ public class PutResource { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(PutResource.class); + private static EELFLogger LOGGER; private static final String FROMAPPID = "AAI-TOOLS"; private static final String TRANSID = UUID.randomUUID().toString(); private static final String USAGE_STRING = "Usage: putTool.sh <resource-path> <filename> <UpdatingRelationshiplist> <UpdatingChild> <ChildNameList> <SkipIfExists>\n" + @@ -74,7 +74,7 @@ public class PutResource { Properties props = System.getProperties(); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_PUTTOOL_LOGBACK_PROPS); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); - + LOGGER = EELFManager.getInstance().getLogger(PutResource.class); Boolean bResVersionEnabled = false; try @@ -144,16 +144,21 @@ public class PutResource { LOGGER.debug("url=" + url); if ( nodeExists( url) ) { - LOGGER.info("PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n"); - System.exit(0); + String infMsg ="PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + System.exit(0); } - } RestController.<T>Get(t2, FROMAPPID, TRANSID, path, restObj, false); t2 = restObj.get(); - LOGGER.info(" GET succeeded\n"); + String infMsg = " GET succeeded\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + } catch (AAIException e) { - if ( !doPutIfExists ) { + if ( !doPutIfExists ) { + System.out.println("Warning - Caught exception while attempting to PUT resource"); LOGGER.warn("Caught exception while attempting to PUT resource", e); } bExist = false; @@ -161,6 +166,7 @@ public class PutResource { catch (Exception e1) { if ( !doPutIfExists ) { + System.out.println("Warning - GET exception ignored with skipExists parameter\n"); LOGGER.warn(" GET exception ignored with skipExists parameter\n", e1); } bExist = false; @@ -177,17 +183,24 @@ public class PutResource { String DBresourceVersion = GetResourceVersion(t2); if ( !doPutIfExists ) { - LOGGER.info("PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n"); - System.exit(0); + String infMsg = "PUT succeeded, the resource exists already in the DB. Skipping the put based on the skipIfExists command line parameter.\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + System.exit(0); } if (resourceUpdateVersion == null || resourceUpdateVersion.isEmpty()) { - if ( DBresourceVersion != null && !DBresourceVersion.isEmpty()) - LOGGER.error("The resource with version = " + DBresourceVersion + " exists already in the DB. Please supply the right resourceVersion in input data file.\n"); - else - LOGGER.error("The resource exists already in the DB. Please supply the right resourceVersion in input data file.\n"); - + if ( DBresourceVersion != null && !DBresourceVersion.isEmpty()){ + String eMsg = "The resource with version = " + DBresourceVersion + " exists already in the DB. Please supply the right resourceVersion in input data file.\n"; + System.out.println(eMsg); + LOGGER.error(eMsg); + } + else{ + String eMsg = "The resource exists already in the DB. Please supply the right resourceVersion in input data file.\n"; + System.out.println(eMsg); + LOGGER.error(eMsg); + } System.exit(1); } @@ -196,7 +209,9 @@ public class PutResource { if ( resourceUpdateVersion != null && !resourceUpdateVersion.isEmpty() ) if (!DBresourceVersion.equals(resourceUpdateVersion)) { - LOGGER.error("DB version doesn't match current version. Please get the latest version and modify.\n"); + String eMsg = "DB version doesn't match current version. Please get the latest version and modify.\n"; + System.out.println(eMsg); + LOGGER.error(eMsg); System.exit(1); } } @@ -205,8 +220,10 @@ public class PutResource { { if ( bResVersionEnabled && resourceUpdateVersion != null && !resourceUpdateVersion.isEmpty()) { - LOGGER.error("DB doesn't have this resource any more. Please create a new version by taking out the resourceVersion tag from your input resource data file.\n"); - System.exit(1); + String eMsg = "DB doesn't have this resource any more. Please create a new version by taking out the resourceVersion tag from your input resource data file.\n"; + System.out.println(eMsg); + LOGGER.error(eMsg); + System.exit(1); } } @@ -247,8 +264,12 @@ public class PutResource { RestController.<T>Put(resJson1, FROMAPPID, TRANSID, path, false); - LOGGER.info(" PUT succeeded"); - LOGGER.info("Done!!"); + String infMsg = " PUT succeeded"; + System.out.println(infMsg); + LOGGER.info(infMsg); + infMsg = "Done!!"; + System.out.println(infMsg); + LOGGER.info(infMsg); System.exit(0); @@ -256,8 +277,13 @@ public class PutResource { if ( !doPutIfExists ) { // ignore 412 failure if ( e.getMessage().equals("AAI_7116") ) { if ( e.getMessage().indexOf("status=412") > 0) { - LOGGER.info("PUT succeeded, return 412 ignored\n"); - LOGGER.info("\nDone!!"); + String infMsg = "PUT succeeded, return 412 ignored\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + + infMsg = "\nDone!!"; + System.out.println(infMsg); + LOGGER.info(infMsg); System.exit(0); } } @@ -383,12 +409,14 @@ public class PutResource { client = HttpsAuthClient.getTwoWaySSLClient(); } - LOGGER.info("Getting the resource...: " + url); - + String infMsg = "Getting the resource...: " + url; + System.out.println(infMsg); + LOGGER.info(infMsg); + ClientResponse cres = client.resource(url) .header("X-TransactionId", TRANSID) .header("X-FromAppId", FROMAPPID) - .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue()) + .header("Authorization", HttpsAuthClient.getBasicAuthHeaderValue()) .accept("application/json") .get(ClientResponse.class); @@ -398,9 +426,11 @@ public class PutResource { } else if (cres.getStatus() == 200){ return true; } else { - LOGGER.error("Getting the Resource failed: " + cres.getStatus() - + ": " + cres.getEntity(String.class)); - return false; + String eMsg = "Getting the Resource failed: " + cres.getStatus() + + ": " + cres.getEntity(String.class); + System.out.println(eMsg); + LOGGER.error(eMsg); + return false; } } catch (KeyManagementException e) { throw new AAIException("AAI_7401", e, "Error during GET"); diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java b/aai-resources/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java new file mode 100644 index 0000000..a6a21ca --- /dev/null +++ b/aai-resources/src/main/java/org/openecomp/aai/util/RelationshipPutDel.java @@ -0,0 +1,211 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * 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.aai.util; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.security.KeyManagementException; +import java.util.Properties; +import java.util.UUID; + +import org.openecomp.aai.domain.yang.Relationship; +import org.openecomp.aai.exceptions.AAIException; +import com.att.eelf.configuration.Configuration; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; + + +public class RelationshipPutDel { + + private static final String FROMAPPID = "AAI-TOOLS"; + private static final String TRANSID = UUID.randomUUID().toString(); + private static EELFLogger LOGGER; + private static final String USAGE_STRING = "Usage: rshipTool.sh <PUT|DELETE> <resource-path> <filename>\n" + + "resource-path for a particular resource starting after the aai/<version>, relationship-list/relationship gets added by script\n" + + "filename is the path to a file which contains the json input for the relationship payload" + + "for example: relTool.sh PUT cloud-infrastructure/oam-networks/oam-network/test-100-oam /tmp/putrship.json\n"; + + /** + * The main method. + * + * @param args the arguments + */ + public static void main(String[] args) { + + // Set the logging file properties to be used by EELFManager + Properties props = System.getProperties(); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_RSHIPTOOL_LOGBACK_PROPS); + props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); + LOGGER = EELFManager.getInstance().getLogger(RelationshipPutDel.class); + String dMsg = "Start processing..."; + System.out.println(dMsg); + LOGGER.debug(dMsg); + + String rshipURL, resURL = null; + Relationship rship = null; + + try { + if ((args.length < 3) || (!args[0].equalsIgnoreCase("PUT") && !args[0].equalsIgnoreCase("DELETE"))) { + System.out.println("Insufficient or Invalid arguments"); + System.out.println(USAGE_STRING); + System.exit(1); + } + + rship = readJsonFile(args[2]); + + // Assume the config AAI_SERVER_URL has a last slash so remove if + // resource-path has it as the first char + resURL = args[1].replaceFirst("^/", ""); + resURL = AAIConfig.get(AAIConstants.AAI_SERVER_URL) + resURL; + rshipURL = resURL.concat("/relationship-list/relationship"); + + dMsg = "Resource URL=" + rshipURL; + System.out.println(dMsg); + LOGGER.debug(dMsg); + + PutDelRelationship(rshipURL, rship, args[0]); + + String infMsg = args[0] + " Relationship succeeded to: " + rship.getRelatedTo() + "\n"; + System.out.println(infMsg); + LOGGER.info(infMsg); + + GetResource.getNode(resURL); + infMsg = "Done!!"; + System.out.println(infMsg); + LOGGER.info(infMsg); + + System.exit(0); + + } catch (AAIException e) { + LOGGER.error(args[0] + " Relationship PUT/DELETE failed", e); + System.out.println(args[0] + " Relationship PUT/DELETE failed"); + System.exit(1); + } catch (Exception e) { + LOGGER.error(args[0] + " Relationship PUT/DELETE failed", e); + System.out.println(args[0] + " Relationship PUT/DELETE failed"); + System.exit(1); + } + } + + /** + * Read json file. + * + * @param fName the f name + * @return the relationship + * @throws AAIException the AAI exception + */ + public static Relationship readJsonFile( String fName ) throws AAIException { + String jsonData = ""; + BufferedReader br = null; + Relationship rship = new Relationship(); + + try { + String line; + br = new BufferedReader(new FileReader(fName)); + while ((line = br.readLine()) != null) { + jsonData += line + "\n"; + } + } catch (IOException e) { + throw new AAIException("AAI_7403", e, "Error opening json file"); + } finally { + try { + if (br != null) + br.close(); + } catch (IOException ex) { + throw new AAIException("AAI_7403", ex, "Error closing json file"); + } + } + + try { + rship = MapperUtil.readWithDashesAsObjectOf(Relationship.class, jsonData); + } + catch (Exception je){ + throw new AAIException("AAI_7403", je, "Error parsing json file"); + } + + return rship; + + }//End readJsonFile() + + + /** + * Put del relationship. + * + * @param aaiLogger the aai logger + * @param logline the logline + * @param rshipURL the rship URL + * @param rship the rship + * @param action the action + * @throws AAIException the AAI exception + */ + public static void PutDelRelationship(String rshipURL, + Relationship rship, + String action) throws AAIException{ + try { + Client client = HttpsAuthClient.getClient(); + ClientResponse cres = null; + + if (action.equalsIgnoreCase("PUT")) + cres = client.resource(rshipURL) + .header("X-TransactionId", TRANSID) + .header("X-FromAppId", FROMAPPID) + .accept("application/json") + .entity(rship) + .put(ClientResponse.class); + else + cres = client.resource(rshipURL) + .header("X-TransactionId", TRANSID) + .header("X-FromAppId", FROMAPPID) + .accept("application/json") + .entity(rship) + .delete(ClientResponse.class); + + if (cres.getStatus() == 404) { // resource not found + String infMsg = "Resource does not exist...: " + cres.getStatus() + + ":\n" + cres.getEntity(String.class); + System.out.println(infMsg); + LOGGER.info(infMsg); + throw new AAIException("AAI_7404", "Resource does not exist"); + } else if ((action.equalsIgnoreCase("PUT") && cres.getStatus() == 200) || + (action.equalsIgnoreCase("DELETE") && cres.getStatus() == 204)) { + String infMsg = action + " Resource status: " + cres.getStatus(); + System.out.println(infMsg); + LOGGER.info(infMsg); + } else { + String eMsg = action + " Resource failed: " + cres.getStatus() + + ":\n" + cres.getEntity(String.class); + System.out.println(eMsg); + LOGGER.error(eMsg); + throw new AAIException("AAI_7402", "Error during PutDel"); + } + } catch (AAIException e) { + throw e; + } catch (KeyManagementException e) { + throw new AAIException("AAI_7401", "Error during PutDel"); + } catch (Exception e) { + throw new AAIException("AAI_7402", "Error during PutDel"); + } + } + +} diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java b/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java index ea674ed..181627b 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/StoreNotificationEvent.java @@ -25,20 +25,17 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; -import java.util.List; -import java.util.Map; import java.util.UUID; import javax.xml.bind.Marshaller; -import org.apache.cxf.helpers.CastUtils; -import org.apache.cxf.message.Message; -import org.apache.cxf.phase.PhaseInterceptorChain; import org.eclipse.persistence.dynamic.DynamicEntity; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; import org.json.JSONException; import org.json.JSONObject; + import org.openecomp.aai.dmaap.AAIDmaapEventJMSProducer; +import org.openecomp.aai.domain.notificationEvent.NotificationEvent; import org.openecomp.aai.exceptions.AAIException; import org.openecomp.aai.introspection.Introspector; import org.openecomp.aai.introspection.Loader; @@ -49,31 +46,90 @@ public class StoreNotificationEvent { private AAIDmaapEventJMSProducer messageProducer; private String fromAppId = ""; private String transId = ""; - + private final String transactionId; + private final String sourceOfTruth; /** * Instantiates a new store notification event. */ - public StoreNotificationEvent() { + public StoreNotificationEvent(String transactionId, String sourceOfTruth) { this.messageProducer = new AAIDmaapEventJMSProducer(); - Message inMessage = PhaseInterceptorChain.getCurrentMessage().getExchange().getInMessage(); - Map<String, List<String>> headersList = CastUtils.cast((Map<?, ?>) inMessage.get(Message.PROTOCOL_HEADERS)); - if (headersList != null) { - List<String> xt = headersList.get("X-TransactionId"); - if (xt != null) { - for (String transIdValue : xt) { - transId = transIdValue; - } - } - List<String> fa = headersList.get("X-FromAppId"); - if (fa != null) { - for (String fromAppIdValue : fa) { + this.transactionId = transactionId; + this.sourceOfTruth = sourceOfTruth; + } - fromAppId = fromAppIdValue; - } - } + /** + * Store event. + * + * @param eh + * the eh + * @param obj + * the obj + * @throws AAIException + * the AAI exception + */ + public void storeEvent(NotificationEvent.EventHeader eh, Object obj) throws AAIException { + + if (obj == null) { + throw new AAIException("AAI_7350"); } - } + org.openecomp.aai.domain.notificationEvent.ObjectFactory factory = new org.openecomp.aai.domain.notificationEvent.ObjectFactory(); + + org.openecomp.aai.domain.notificationEvent.NotificationEvent ne = factory.createNotificationEvent(); + + if (eh.getId() == null) { + eh.setId(genDate2() + "-" + UUID.randomUUID().toString()); + } + if (eh.getTimestamp() == null) { + eh.setTimestamp(genDate()); + } + + // there's no default, but i think we want to put this in hbase? + + if (eh.getEntityLink() == null) { + eh.setEntityLink("UNK"); + } + + if (eh.getAction() == null) { + eh.setAction("UNK"); + } + + if (eh.getEventType() == null) { + eh.setEventType(AAIConfig.get("aai.notificationEvent.default.eventType", "UNK")); + } + + if (eh.getDomain() == null) { + eh.setDomain(AAIConfig.get("aai.notificationEvent.default.domain", "UNK")); + } + + if (eh.getSourceName() == null) { + eh.setSourceName(AAIConfig.get("aai.notificationEvent.default.sourceName", "UNK")); + } + + if (eh.getSequenceNumber() == null) { + eh.setSequenceNumber(AAIConfig.get("aai.notificationEvent.default.sequenceNumber", "UNK")); + } + + if (eh.getSeverity() == null) { + eh.setSeverity(AAIConfig.get("aai.notificationEvent.default.severity", "UNK")); + } + + if (eh.getVersion() == null) { + eh.setVersion(AAIConfig.get("aai.notificationEvent.default.version", "UNK")); + } + + ne.setCambriaPartition(AAIConstants.UEB_PUB_PARTITION_AAI); + ne.setEventHeader(eh); + ne.setEntity(obj); + + try { + PojoUtils pu = new PojoUtils(); + String entityJson = pu.getJsonFromObject(ne); + sendToDmaapJmsQueue(entityJson); + } catch (Exception e) { + throw new AAIException("AAI_7350", e); + } + } /** * Store dynamic event. diff --git a/aai-resources/src/main/java/org/openecomp/aai/util/UpdateResource.java b/aai-resources/src/main/java/org/openecomp/aai/util/UpdateResource.java index adecfb1..1597a7b 100644 --- a/aai-resources/src/main/java/org/openecomp/aai/util/UpdateResource.java +++ b/aai-resources/src/main/java/org/openecomp/aai/util/UpdateResource.java @@ -35,7 +35,7 @@ import com.att.eelf.configuration.EELFManager; public class UpdateResource { - private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(UpdateResource.class.getName()); + private static EELFLogger LOGGER; private static final String FROMAPPID = "AAIUPDT"; private static final String TRANSID = UUID.randomUUID().toString(); private static final String UPDATE_URL = "actions/update"; @@ -59,7 +59,7 @@ public class UpdateResource { Properties props = System.getProperties(); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_NAME, AAIConstants.AAI_UPDTOOL_LOGBACK_PROPS); props.setProperty(Configuration.PROPERTY_LOGGING_FILE_PATH, AAIConstants.AAI_HOME_ETC_APP_PROPERTIES); - + LOGGER = EELFManager.getInstance().getLogger(UpdateResource.class.getName()); try { if (args.length < 3) { System.out.println("Nothing to update or Insufficient arguments"); @@ -76,9 +76,11 @@ public class UpdateResource { System.exit(0); } catch (AAIException e) { + System.out.println("Error - Update Failed."); ErrorLogHelper.logException(e); System.exit(1); } catch (Exception e) { + System.out.println("Error - Update Failed." + e.getMessage()); ErrorLogHelper.logError("AAI_7402", "Update failed: " + e.getMessage()); System.exit(1); } @@ -113,10 +115,16 @@ public class UpdateResource { update.getAction().add(action); - LOGGER.info("updating the resource... "); - + String infMsg = "updating the resource... "; + System.out.println(infMsg); + LOGGER.info(infMsg); + RestController.<Update>Put(update, FROMAPPID, TRANSID, UPDATE_URL); - LOGGER.info("Update Successful"); + + infMsg = "Update Successful"; + System.out.println(infMsg); + LOGGER.info(infMsg); + } catch (AAIException e) { throw e; } catch (Exception e) { diff --git a/aai-resources/src/main/scripts/PropertyChangeName.sh b/aai-resources/src/main/scripts/PropertyChangeName.sh new file mode 100644 index 0000000..af61403 --- /dev/null +++ b/aai-resources/src/main/scripts/PropertyChangeName.sh @@ -0,0 +1,83 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# This script is used to add a target property name with the same value in the database schema +# to a vertex which has an existing property. The existing property is not removed. +# +# Note also - This script just makes changes to the schema that is currently live. +# If you were to create a new schema in a brandy-new environment, it would look like +# whatever the oxm (as of July 2016) told it to look like. So, part of making a +# change to the db schema should Always first be to make the change in the oxm so that +# future environments will have the change. This script is just to change existing +# instances of the schema since schemaGenerator (as of July 2015) does not update things - it +# just does the initial creation. +# +# To use this script, you need to pass four parameters: +# propertyName -- the name of the property that has the value to be used in the targetProperty +# targetPropertyName -- the name of the targetProperty +# targetNodeType -- NA if all propertyName instances in the DB are impacted, otherwise limit the change to this nodeType +# skipCommit -- true or false. For testing, skips the commit when set to true. +# +# Ie. propertyNameChange service-id persona-model-id service-instance true +# + +echo +echo `date` " Starting $0" + + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + + +if [ "$#" -ne 4 ]; then + echo "Illegal number of parameters" + echo "usage: $0 propertyName targetPropertyName targetNodeType skipCommit" + exit 1 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +for JAR in `ls $PROJECT_HOME/extJars/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \ + org.openecomp.aai.dbgen.PropertyNameChange $1 $2 $3 $4 +if [ "$?" -ne "0" ]; then + echo "Problem executing propertyNameChange " + exit 1 +fi + + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/addResourceVersionProperty.sh b/aai-resources/src/main/scripts/addResourceVersionProperty.sh new file mode 100644 index 0000000..821275a --- /dev/null +++ b/aai-resources/src/main/scripts/addResourceVersionProperty.sh @@ -0,0 +1,55 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# The script invokes the AddResourceVersionProp java class as a one-time (per database instance) migration tool +# which adds the new property "resource-version" to every node in the db. +# + +echo +echo `date` " Starting $0" + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +for JAR in `ls $PROJECT_HOME/extJars/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + + +$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \ + org.openecomp.aai.dbgen.AddResourceVersionProp + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/changePropertyCardinality.sh b/aai-resources/src/main/scripts/changePropertyCardinality.sh new file mode 100644 index 0000000..0eeac6d --- /dev/null +++ b/aai-resources/src/main/scripts/changePropertyCardinality.sh @@ -0,0 +1,88 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# This script is used to change the cardinality of an existing database property. +# It currently just allows you to change TO a SET cardinality with dataType = String. +# It does not currently let you preserve the data (since we're just doing this for one +# field which nobody uses yet). +# +# Note also - This script just makes changes to the schema that is currently live. +# If you were to create a new schema in a brandy-new environment, it would look like +# whatever ex5.json (as of Jan 2016) told it to look like. So, part of making a +# change to the db schema should Always first be to make the change in ex5.json so that +# future environments will have the change. This script is just to change existing +# instances of the schema since schemaGenerator (as of Jan 2016) does not update things - it +# just does the initial creation. +# +# Boy, this is getting to be a big comment section... +# +# To use this script, you need to pass four parameters: +# propertyName -- the name of the property that you need to change Cardinality on. +# targetDataType -- whether it's changing or not, you need to give it: For now -- we only allow "String" +# targetCardinality -- For now -- only accepts "SET". In the future we should support ("SET", "LIST" or "SINGLE") +# preserveDataFlag -- true or false. For now -- only supports "false" +# +# Ie. changePropertyCardinality.sh supplier-release-list String SET false +# + +echo +echo `date` " Starting $0" + + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + + +if [ "$#" -ne 4 ]; then + echo "Illegal number of parameters" + echo "usage: $0 propertyName targetDataType targetCardinality preserveDataFlag" + exit 1 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +for JAR in `ls $PROJECT_HOME/extJars/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + + +$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME \ + org.openecomp.aai.dbgen.ChangePropertyCardinality $1 $2 $3 $4 +if [ "$?" -ne "0" ]; then + echo "Problem executing ChangePropertyCardinality " + exit 1 +fi + + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/createDBSchema.sh b/aai-resources/src/main/scripts/createDBSchema.sh index 51668de..3cdbcd3 100644 --- a/aai-resources/src/main/scripts/createDBSchema.sh +++ b/aai-resources/src/main/scripts/createDBSchema.sh @@ -33,6 +33,7 @@ echo echo `date` " Starting $0" . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` diff --git a/aai-resources/src/main/scripts/deleteTool.sh b/aai-resources/src/main/scripts/deleteTool.sh index 585f333..c91f564 100644 --- a/aai-resources/src/main/scripts/deleteTool.sh +++ b/aai-resources/src/main/scripts/deleteTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/deobfuscatePW.sh b/aai-resources/src/main/scripts/deobfuscatePW.sh index 965525d..0a1f09a 100644 --- a/aai-resources/src/main/scripts/deobfuscatePW.sh +++ b/aai-resources/src/main/scripts/deobfuscatePW.sh @@ -39,6 +39,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/edgeTagger.sh b/aai-resources/src/main/scripts/edgeTagger.sh index 5a120a2..35c214c 100644 --- a/aai-resources/src/main/scripts/edgeTagger.sh +++ b/aai-resources/src/main/scripts/edgeTagger.sh @@ -72,6 +72,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/getTool.sh b/aai-resources/src/main/scripts/getTool.sh index 2da20eb..6f54299 100644 --- a/aai-resources/src/main/scripts/getTool.sh +++ b/aai-resources/src/main/scripts/getTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/notifyTool.sh b/aai-resources/src/main/scripts/notifyTool.sh index 2ecf1f4..9a0eede 100644 --- a/aai-resources/src/main/scripts/notifyTool.sh +++ b/aai-resources/src/main/scripts/notifyTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/postTool.sh b/aai-resources/src/main/scripts/postTool.sh index a773915..9a059e2 100644 --- a/aai-resources/src/main/scripts/postTool.sh +++ b/aai-resources/src/main/scripts/postTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/putTool.sh b/aai-resources/src/main/scripts/putTool.sh index 9d3f1dd..db581f8 100644 --- a/aai-resources/src/main/scripts/putTool.sh +++ b/aai-resources/src/main/scripts/putTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/rshipTool.sh b/aai-resources/src/main/scripts/rshipTool.sh index 316d0f5..5c71f51 100644 --- a/aai-resources/src/main/scripts/rshipTool.sh +++ b/aai-resources/src/main/scripts/rshipTool.sh @@ -43,6 +43,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/run_DbTestProcessBuilder.sh b/aai-resources/src/main/scripts/run_DbTestProcessBuilder.sh new file mode 100644 index 0000000..7cf1c5f --- /dev/null +++ b/aai-resources/src/main/scripts/run_DbTestProcessBuilder.sh @@ -0,0 +1,54 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# This script invokes the dataSnapshot java class passing an option to tell it to take +# a snapshot of the database and store it as a single-line XML file. +# + +echo +echo `date` " Starting $0" + + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +for JAR in `ls $PROJECT_HOME/extJars/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.DbTestProcessBuilder "$@" + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/run_FixXSD.sh b/aai-resources/src/main/scripts/run_FixXSD.sh new file mode 100644 index 0000000..9293ded --- /dev/null +++ b/aai-resources/src/main/scripts/run_FixXSD.sh @@ -0,0 +1,68 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# The script invokes GetResource java class to get all nodes +# + +echo +echo `date` " Starting $0" + +REV=$1 +AAIHOME=$2 +echo "AAIHOME: $AAIHOME" + +if test "$REV" = "" +then + REV=v6 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +if test "$AAIHOME" = "" +then + AAIHOME=$PROJECT_HOME +fi + + +for JAR in `ls $AAIHOME/target/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +export REV=$REV +echo "FixXSD $REV $AAIHOME" +$JAVA_HOME/bin/java -classpath $CLASSPATH -DAJSC_HOME=$AAIHOME org.openecomp.aai.util.FixXSDNew $REV +ret_code=$? +if [ $ret_code != 0 ]; then + echo `date` " Done $0" + exit $ret_code +fi + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/schemaMod.sh b/aai-resources/src/main/scripts/schemaMod.sh index f4fd4d5..3204900 100644 --- a/aai-resources/src/main/scripts/schemaMod.sh +++ b/aai-resources/src/main/scripts/schemaMod.sh @@ -66,6 +66,7 @@ if [ "$#" -ne 4 ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do diff --git a/aai-resources/src/main/scripts/uniquePropertyCheck.sh b/aai-resources/src/main/scripts/uniquePropertyCheck.sh new file mode 100644 index 0000000..cee03b9 --- /dev/null +++ b/aai-resources/src/main/scripts/uniquePropertyCheck.sh @@ -0,0 +1,60 @@ +#!/bin/ksh + +### +# ============LICENSE_START======================================================= +# org.openecomp.aai +# ================================================================================ +# 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========================================================= +### + +# +# The script invokes UniqueProperty java class to see if the passed property is unique in the db and if +# not, to display where duplicate values are found. +# +# For example: uniquePropertyCheck.sh subscriber-name +# + +echo +echo `date` " Starting $0" + +userid=$( id | cut -f2 -d"(" | cut -f1 -d")" ) +if [ "${userid}" != "aaiadmin" ]; then + echo "You must be aaiadmin to run $0. The id used $userid." + exit 1 +fi + +. /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources + +for JAR in `ls $PROJECT_HOME/extJars/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +for JAR in `ls $PROJECT_HOME/lib/*.jar` +do + CLASSPATH=$CLASSPATH:$JAR +done + +$JAVA_HOME/bin/java -classpath $CLASSPATH -Dhttps.protocols=TLSv1.1,TLSv1.2 -DAJSC_HOME=$PROJECT_HOME -Daai.home=$PROJECT_HOME org.openecomp.aai.util.UniquePropertyCheck "$@" +ret_code=$? +if [ $ret_code != 0 ]; then + echo `date` " Done $0" + exit $ret_code +fi + +echo `date` " Done $0" +exit 0 diff --git a/aai-resources/src/main/scripts/updateTool.sh b/aai-resources/src/main/scripts/updateTool.sh index 25670f6..bdb47e2 100644 --- a/aai-resources/src/main/scripts/updateTool.sh +++ b/aai-resources/src/main/scripts/updateTool.sh @@ -34,6 +34,7 @@ if [ "${userid}" != "aaiadmin" ]; then fi . /etc/profile.d/aai.sh +PROJECT_HOME=/opt/app/aai-resources for JAR in `ls $PROJECT_HOME/extJars/*.jar` do |