From 56da09aae132118a55af3cad601fff7b1cc70390 Mon Sep 17 00:00:00 2001 From: Fiete Ostkamp Date: Tue, 19 Nov 2024 14:20:15 +0100 Subject: Move GraphChecker to aai-common - define GraphCheck class that tests connection to storage backend - disable caching for the db transaction to make sure that the real connection is tested - define GraphConfig class that defines a Graph bean. This is an alternative to the AAIGraph class Issue-ID: AAI-4060 Change-Id: Id6d20adc8a8bab8bc914fb47353c37fd80905896 Signed-off-by: Fiete Ostkamp --- .../main/java/org/onap/aai/config/GraphConfig.java | 106 +++++++++++++++++++++ .../main/java/org/onap/aai/util/GraphChecker.java | 93 ++++++++++++++++++ aai-core/src/main/resources/application.properties | 2 + .../java/org/onap/aai/util/GraphCheckerTest.java | 71 ++++++++++++++ aai-core/src/test/resources/application.properties | 1 + .../etc/appprops/janusgraph-cached.properties | 37 ------- 6 files changed, 273 insertions(+), 37 deletions(-) create mode 100644 aai-core/src/main/java/org/onap/aai/config/GraphConfig.java create mode 100644 aai-core/src/main/java/org/onap/aai/util/GraphChecker.java create mode 100644 aai-core/src/main/resources/application.properties create mode 100644 aai-core/src/test/java/org/onap/aai/util/GraphCheckerTest.java create mode 100644 aai-core/src/test/resources/application.properties delete mode 100644 aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties diff --git a/aai-core/src/main/java/org/onap/aai/config/GraphConfig.java b/aai-core/src/main/java/org/onap/aai/config/GraphConfig.java new file mode 100644 index 00000000..352821f5 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/config/GraphConfig.java @@ -0,0 +1,106 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2024 Deutsche Telekom. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.aai.config; + +import java.io.FileNotFoundException; + +import javax.annotation.PreDestroy; + +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphFactory; +import org.janusgraph.core.schema.JanusGraphManagement; +import org.onap.aai.dbgen.SchemaGenerator; +import org.onap.aai.dbgen.SchemaGenerator4Hist; +import org.onap.aai.dbmap.AAIGraphConfig; +import org.onap.aai.exceptions.AAIException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Configuration +public class GraphConfig { + + private static final String IN_MEMORY = "inmemory"; + + @Value("${spring.application.name}") + private String serviceName; + + @Value("${aai.graph.properties.path}") + private String configPath; + + @Bean + public org.apache.commons.configuration2.Configuration getGraphProperties() + throws FileNotFoundException, ConfigurationException { + + return new AAIGraphConfig.Builder(configPath) + .forService(serviceName) + .withGraphType("realtime") + .buildConfiguration(); + } + + @Bean + public JanusGraph janusGraph(org.apache.commons.configuration2.Configuration graphConfiguration) throws AAIException { + JanusGraph graph = JanusGraphFactory.open(graphConfiguration); + + boolean loadSchema = false; + if (loadSchema) { + if (IN_MEMORY.equals(graphConfiguration.getProperty("storage.backend"))) { + // Load the propertyKeys, indexes and edge-Labels into the DB + loadSchema(graph); + } + } + + if (graph == null) { + throw new AAIException("AAI_5102"); + } + + return graph; + } + + @Bean + public Graph graph(JanusGraph janusGraph) { + return janusGraph; + } + + @Bean + public GraphTraversalSource graphTraversalSource(Graph graph) { + return graph.traversal(); + } + + private void loadSchema(JanusGraph graph) { + // Load the propertyKeys, indexes and edge-Labels into the DB + boolean dbNotEmpty = graph.traversal().V().limit(1).hasNext(); + log.info("-- loading schema into JanusGraph"); + if ("true".equals( + SpringContextAware.getApplicationContext().getEnvironment().getProperty("history.enabled", "false"))) { + JanusGraphManagement graphMgt = graph.openManagement(); + SchemaGenerator4Hist.loadSchemaIntoJanusGraph(graphMgt, IN_MEMORY); + } else { + SchemaGenerator.loadSchemaIntoJanusGraph(graph, IN_MEMORY, dbNotEmpty); + } + } +} diff --git a/aai-core/src/main/java/org/onap/aai/util/GraphChecker.java b/aai-core/src/main/java/org/onap/aai/util/GraphChecker.java new file mode 100644 index 00000000..43caebc5 --- /dev/null +++ b/aai-core/src/main/java/org/onap/aai/util/GraphChecker.java @@ -0,0 +1,93 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Bell Canada + * Modification Copyright (C) 2024 Deutsche Telekom SA + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.aai.util; + +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphException; +import org.janusgraph.core.JanusGraphTransaction; +import org.onap.aai.logging.ErrorLogHelper; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +@RequiredArgsConstructor +public class GraphChecker { + + private final JanusGraph graph; + + /** + * Checks whether a connection to the graph database can be made. + * + * @return + *
  • true, if database is available
  • + *
  • false, if database is NOT available
  • + */ + public boolean isAaiGraphDbAvailable() { + boolean dbAvailable; + JanusGraphTransaction transaction = null; + try { + // disable caching and other features that are not needed for this check + transaction = graph + .buildTransaction() + .readOnly() + .consistencyChecks(false) + .vertexCacheSize(0) + .skipDBCacheRead() + .start(); + dbAvailable = transaction.traversal().V().limit(1).hasNext(); + } catch (JanusGraphException e) { + String message = "Database is not available (after JanusGraph exception)"; + ErrorLogHelper.logError("500", message + ": " + e.getMessage()); + log.error(message, e); + dbAvailable = false; + } catch (Error e) { + // Following error occurs when aai resources is starting: + // - UnsatisfiedLinkError (for org.onap.aai.dbmap.AAIGraph$Helper instantiation) + // Following errors are raised when aai resources is starting and cassandra is not + // running: + // - ExceptionInInitializerError + // - NoClassDefFoundError (definition for org.onap.aai.dbmap.AAIGraph$Helper is not + // found) + String message = "Database is not available (after error)"; + ErrorLogHelper.logError("500", message + ": " + e.getMessage()); + log.error(message, e); + dbAvailable = false; + } catch (Exception e) { + String message = "Database availability can not be determined"; + ErrorLogHelper.logError("500", message + ": " + e.getMessage()); + log.error(message, e); + dbAvailable = false; + } finally { + if (transaction != null && !transaction.isClosed()) { + // check if transaction is open then closed instead of flag + try { + transaction.rollback(); + } catch (Exception e) { + String message = "Exception occurred while closing transaction"; + log.error(message, e); + ErrorLogHelper.logError("500", message + ": " + e.getMessage()); + } + } + } + return dbAvailable; + } +} diff --git a/aai-core/src/main/resources/application.properties b/aai-core/src/main/resources/application.properties new file mode 100644 index 00000000..ec085cc5 --- /dev/null +++ b/aai-core/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=aai-core +aai.graph.properties.path=src/main/resources/janusgraph-realtime.properties diff --git a/aai-core/src/test/java/org/onap/aai/util/GraphCheckerTest.java b/aai-core/src/test/java/org/onap/aai/util/GraphCheckerTest.java new file mode 100644 index 00000000..03634c8c --- /dev/null +++ b/aai-core/src/test/java/org/onap/aai/util/GraphCheckerTest.java @@ -0,0 +1,71 @@ +package org.onap.aai.util; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.JanusGraph; +import org.janusgraph.core.JanusGraphTransaction; +import org.janusgraph.core.TransactionBuilder; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.onap.aai.AAISetup; +import org.onap.aai.config.GraphConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + + +@RunWith(MockitoJUnitRunner.class) +@ContextConfiguration(classes = {GraphConfig.class, GraphChecker.class}) +@TestPropertySource(value = "classpath:/application.properties") +public class GraphCheckerTest extends AAISetup { + + @Mock TransactionBuilder transactionBuilder; + @Mock JanusGraphTransaction transaction; + @Mock GraphTraversalSource traversalSource; + @Mock GraphTraversal traversal; + @MockBean JanusGraph graph; + @Autowired GraphChecker graphChecker; + + @Before + public void setup() { + mockGraphTransaction(); + mockTraversal(); + } + + @Test + public void thatAvailabilityCanBeTrue() { + when(traversal.hasNext()).thenReturn(true); + boolean available = graphChecker.isAaiGraphDbAvailable(); + assertTrue(available); + } + @Test + public void thatAvailabilityCanBeFalse() { + when(traversal.hasNext()).thenReturn(false); + boolean available = graphChecker.isAaiGraphDbAvailable(); + assertFalse(available); + } + + private void mockTraversal() { + when(transaction.traversal()).thenReturn(traversalSource); + when(traversalSource.V()).thenReturn(traversal); + when(traversal.limit(1)).thenReturn(traversal); + } + + private void mockGraphTransaction() { + when(graph.buildTransaction()).thenReturn(transactionBuilder); + when(transactionBuilder.readOnly()).thenReturn(transactionBuilder); + when(transactionBuilder.consistencyChecks(false)).thenReturn(transactionBuilder); + when(transactionBuilder.vertexCacheSize(0)).thenReturn(transactionBuilder); + when(transactionBuilder.skipDBCacheRead()).thenReturn(transactionBuilder); + when(transactionBuilder.start()).thenReturn(transaction); + } +} diff --git a/aai-core/src/test/resources/application.properties b/aai-core/src/test/resources/application.properties new file mode 100644 index 00000000..a763b733 --- /dev/null +++ b/aai-core/src/test/resources/application.properties @@ -0,0 +1 @@ +aai.graph.properties.path=src/test/resources/bundleconfig-local/etc/appprops/janusgraph-realtime.properties diff --git a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties b/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties deleted file mode 100644 index a0926e7c..00000000 --- a/aai-core/src/test/resources/bundleconfig-local/etc/appprops/janusgraph-cached.properties +++ /dev/null @@ -1,37 +0,0 @@ -# -# ============LICENSE_START======================================================= -# org.onap.aai -# ================================================================================ -# Copyright © 2017-18 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========================================================= - -query.fast-property=true -query.smart-limit=false -# the following parameters are not reloaded automatically and require a manual bounce -storage.backend=inmemory -storage.hostname=localhost - -#schema.default=none -storage.lock.wait-time=300 -storage.hbase.table=aaigraph-dev1.dev -storage.hbase.ext.zookeeper.znode.parent=/hbase-unsecure -#caching on -cache.db-cache = true -cache.db-cache-clean-wait = 20 -cache.db-cache-time = 180000 -cache.db-cache-size = 0.3 - -#load graphson file on startup -load.snapshot.file=false -- cgit 1.2.3-korg