ONAP server pool code update 91/103691/5
authorJoseph Chou <jc2555@att.com>
Fri, 13 Mar 2020 18:15:35 +0000 (14:15 -0400)
committerJoseph Chou <jc2555@att.com>
Tue, 17 Mar 2020 21:25:02 +0000 (17:25 -0400)
Fix server-pool junit hang due to hardcoded IP

Issue-ID: POLICY-2425
Change-Id: Icaf54c0bbd81fa755a031df91ee6cf5cdee98f27
Signed-off-by: Joseph Chou <jc2555@att.com>
feature-server-pool/src/main/feature/config/feature-server-pool.properties
feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/AdapterImpl.java
feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Adapter.java
feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/SimDmaap.java
feature-server-pool/src/test/resources/TestController-controller.properties
feature-server-pool/src/test/resources/feature-server-pool-test.properties [new file with mode: 0644]

index 7be2167..0038029 100644 (file)
@@ -22,8 +22,8 @@
 # server binds to. The default will bind to all interfaces on the host,
 # and choose a port number at random.
 
-server.pool.server.ipAddress=0.0.0.0
-server.pool.server.port=${envd:SERVER_POOL_PORT}
+server.pool.server.ipAddress=${envd:SERVER_POOL_SERVER_IP}
+server.pool.server.port=${envd:SERVER_POOL_PORT:20000}
 
 # The following properties determine whether HTTPS is used -- note that HTTPS
 # also requires that the 'java.net.ssl.*' parameters in 'system.properties' be
@@ -76,7 +76,8 @@ server.pool.server.threads.keepAliveTime=5000
 # keeps this channel open long-term.
 
 server.pool.discovery.servers=${envd:SERVER_POOL_DISCOVERY_SERVERS}
-server.pool.discovery.topic=${envd:SERVER_POOL_DISCOVERY_TOPIC}
+server.pool.discovery.port=${envd:SERVER_POOL_DISCOVERY_PORT:3904}
+server.pool.discovery.topic=${envd:SERVER_POOL_DISCOVERY_TOPIC:DISCOVERY-TOPIC}
 server.pool.discovery.username=${envd:SERVER_POOL_DISCOVERY_USERNAME}
 server.pool.discovery.password=${envd:SERVER_POOL_DISCOVERY_PASSWORD}
 server.pool.discovery.https=${envd:DMAAP_USE_HTTPS}
@@ -116,11 +117,14 @@ keyword.path=requestID,CommonHeader.RequestID,body.output.common-header.request-
 # by '.' that are used to locate the keyword
 # (e.g. 'method1().field2.method3()')
 
+keyword.java.lang.String.lookup=toString()
 keyword.org.onap.policy.m2.base.Transaction.lookup=getRequestID()
 keyword.org.onap.policy.controlloop.ControlLoopEvent.lookup=requestID
 keyword.org.onap.policy.appclcm.LcmRequestWrapper.lookup=getBody().getCommonHeader().getRequestId()
 keyword.org.onap.policy.appclcm.LcmResponseWrapper.lookup=getBody().getCommonHeader().getRequestId()
 keyword.org.onap.policy.drools.serverpool.TargetLock.lookup=getOwnerKey()
+keyword.org.onap.policy.drools.serverpooltest.TestDroolsObject.lookup=getKey()
+keyword.org.onap.policy.drools.serverpooltest.Test1$KeywordWrapper.lookup=key
 
 # The following properties affect distributed 'TargetLock' behavior.
 #
index bac13f1..70dc211 100644 (file)
@@ -27,27 +27,21 @@ import java.nio.file.Paths;
 import java.util.Properties;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
-
 import org.kie.api.runtime.KieSession;
-
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.endpoints.event.comm.TopicListener;
-
 import org.onap.policy.drools.core.PolicyContainer;
 import org.onap.policy.drools.core.PolicySession;
 import org.onap.policy.drools.core.PolicySessionFeatureApiConstants;
-
 import org.onap.policy.drools.serverpooltest.Adapter;
 import org.onap.policy.drools.serverpooltest.BucketWrapper;
 import org.onap.policy.drools.serverpooltest.ServerWrapper;
 import org.onap.policy.drools.serverpooltest.TargetLockWrapper;
-
 import org.onap.policy.drools.system.PolicyController;
 import org.onap.policy.drools.system.PolicyEngineConstants;
 import org.onap.policy.drools.util.KieUtils;
 import org.onap.policy.drools.utils.PropertyUtil;
 import org.powermock.reflect.Whitebox;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -57,10 +51,11 @@ import org.slf4j.LoggerFactory;
  */
 public class AdapterImpl extends Adapter {
     private static Logger logger = LoggerFactory.getLogger(AdapterImpl.class);
-
-    // Each 'AdapterImpl' instance has it's own class object, making it a
-    // singleton. There is only a single 'Adapter' class object, and all
-    // 'AdapterImpl' classes are derived from it.
+    /*
+     * Each 'AdapterImpl' instance has it's own class object, making it a
+     * singleton. There is only a single 'Adapter' class object, and all
+     * 'AdapterImpl' classes are derived from it.
+     */
     private static AdapterImpl adapter = null;
 
     // this is the adapter index
@@ -94,29 +89,30 @@ public class AdapterImpl extends Adapter {
 
         PolicyEngineConstants.getManager().configure(new Properties());
         PolicyEngineConstants.getManager().start();
-
-        // Note that this method does basically what
-        // 'FeatureServerPool.afterStart(PolicyEngine)' does, but allows us to
-        // specify different properties for each of the 6 simulated hosts
+        /*
+         * Note that this method does basically what
+         * 'FeatureServerPool.afterStart(PolicyEngine)' does, but allows us to
+         * specify different properties for each of the 6 simulated hosts
+         */
         logger.info("{}: Running: AdapterImpl.init({}), class hash code = {}",
                     this, index, AdapterImpl.class.hashCode());
-
-        Properties prop = new Properties();
-        prop.setProperty("server.pool.discovery.servers", "127.0.63.250");
-        prop.setProperty("server.pool.discovery.topic", "DISCOVERY-TOPIC");
-        prop.setProperty("server.pool.server.ipAddress", "127.0.63." + index);
-        prop.setProperty("server.pool.server.port", "20000");
-
-        prop.setProperty("keyword.path", "requestID,CommonHeader.RequestID,key");
-
-        prop.setProperty("keyword.org.onap.policy.m2.base.Transaction.lookup",
-                      "getRequestID()");
-        prop.setProperty("keyword.org.onap.policy.controlloop.ControlLoopEvent.lookup", "requestID");
-        prop.setProperty("keyword.org.onap.policy.drools.serverpool.TargetLock.lookup", "getOwnerKey()");
-        prop.setProperty("keyword.java.lang.String.lookup", "toString()");
-        prop.setProperty("keyword.org.onap.policy.drools.serverpooltest.TestDroolsObject.lookup",
-                      "getKey()");
-        prop.setProperty("keyword.org.onap.policy.drools.serverpooltest.Test1$KeywordWrapper.lookup", "key");
+        final String propertyFile = "src/test/resources/feature-server-pool-test.properties";
+        Properties prop = PropertyUtil.getProperties(propertyFile);
+        if (System.getProperty("os.name").toLowerCase().indexOf("mac") < 0) {
+            // Window, Unix
+            String[] ipComponent = prop.getProperty("server.pool.server.ipAddress").split("[.]");
+            String serverIP = ipComponent[0] + "." + ipComponent[1] + "." + ipComponent[2] + "."
+                + (Integer.parseInt(ipComponent[3]) + index);
+            prop.setProperty("server.pool.server.ipAddress", serverIP);
+        } else {
+            // Mac, use localhost and different ports
+            String port = Integer.toString(Integer.parseInt(
+                prop.getProperty("server.pool.server.port")) + index);
+            prop.setProperty("server.pool.server.port", port);
+        }
+        logger.info("server={}, serverIP={}, port={}", index,
+            prop.getProperty("server.pool.server.ipAddress"),
+            prop.getProperty("server.pool.server.port"));
 
         TargetLock.startup();
         Server.startup(prop);
@@ -181,8 +177,6 @@ public class AdapterImpl extends Adapter {
                 while (bucket.getOwner() == null) {
                     Thread.sleep(Math.min(endTime - System.currentTimeMillis(), 100L));
                 }
-                //await().atMost(endTime - System.currentTimeMillis(),
-                //TimeUnit.MILLISECONDS).until(() -> bucket.getOwner() != null);
             }
         } catch (IllegalArgumentException e) {
             // 'Thread.sleep()' was passed a negative time-out value --
@@ -253,10 +247,11 @@ public class AdapterImpl extends Adapter {
     @Override
     public String createController() {
         Properties properties;
-
-        // set the thread class loader to be the same as the one associated
-        // with the 'AdapterImpl' instance, so it will be inherited by any
-        // new threads created (the Drools session thread, in particular)
+        /*
+         * set the thread class loader to be the same as the one associated
+         * with the 'AdapterImpl' instance, so it will be inherited by any
+         * new threads created (the Drools session thread, in particular)
+         */
         ClassLoader saveClassLoader =
             Thread.currentThread().getContextClassLoader();
         Thread.currentThread().setContextClassLoader(AdapterImpl.class.getClassLoader());
index 03b970b..d5d836b 100644 (file)
@@ -23,21 +23,16 @@ package org.onap.policy.drools.serverpooltest;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
 import java.io.PrintStream;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Properties;
 import java.util.concurrent.LinkedBlockingQueue;
-
 import org.kie.api.runtime.KieSession;
 import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.drools.serverpool.Util;
+import org.onap.policy.drools.utils.PropertyUtil;
 
 /**
  * This is a common base class for 6 'AdapterImpl' instances, all running
@@ -53,11 +48,12 @@ import org.onap.policy.drools.serverpool.Util;
 public abstract class Adapter {
     // 'true' indicates that initialization is still needed
     private static boolean initNeeded = true;
-
-    // Each 'Adapter' instance is implemented by 'AdapterImpl', but loaded
-    // with a different class loader that provides each with a different copy
-    // of the set of classes with packages in the list below (see references to
-    // 'BlockingClassLoader').
+    /*
+     * Each 'Adapter' instance is implemented by 'AdapterImpl', but loaded
+     * with a different class loader that provides each with a different copy
+     * of the set of classes with packages in the list below (see references to
+     * 'BlockingClassLoader').
+     */
     public static Adapter[] adapters = new Adapter[6];
 
     /**
@@ -76,8 +72,11 @@ public abstract class Adapter {
                     }
                 }, "DMAAP Simulator").start();
 
-                // wait 1 second to allow time for the port 3904 listener
-                assertTrue(NetworkUtil.isTcpPortOpen(SimDmaap.HOSTNAME, 3904, 50, 1000));
+                // wait 200 millisecond to allow time for the port 3904 listener
+                final String propertyFile = "src/test/resources/feature-server-pool-test.properties";
+                Properties prop = PropertyUtil.getProperties(propertyFile);
+                assertTrue(NetworkUtil.isTcpPortOpen(prop.getProperty("server.pool.discovery.servers"),
+                    Integer.parseInt(prop.getProperty("server.pool.discovery.port")), 250, 200));
 
                 // build 'BlockingClassLoader'
                 BlockingClassLoader bcl = new BlockingClassLoader(
@@ -113,18 +112,21 @@ public abstract class Adapter {
                 }
                 try {
                     for (int i = 0 ; i < adapters.length ; i += 1) {
-                        // Build a new 'ClassLoader' for this adapter. The
-                        // 'ClassLoader' hierarchy is:
-                        //
-                        // AdapterClassLoader(one copy per Adapter) ->
-                        // BlockingClassLoader ->
-                        // base ClassLoader (with the complete URL list)
+                        /*
+                         * Build a new 'ClassLoader' for this adapter. The
+                         * 'ClassLoader' hierarchy is:
+                         *
+                         * AdapterClassLoader(one copy per Adapter) ->
+                         * BlockingClassLoader ->
+                         * base ClassLoader (with the complete URL list)
+                         */
                         ClassLoader classLoader =
                             new AdapterClassLoader(i, urls, bcl);
-
-                        // set the current thread class loader, which should be
-                        // inherited by any child threads created during
-                        // the initialization of the adapter
+                        /*
+                         * set the current thread class loader, which should be
+                         * inherited by any child threads created during
+                         * the initialization of the adapter
+                         */
                         Thread.currentThread().setContextClassLoader(classLoader);
 
                         // now, build the adapter -- it is not just a new instance,
index 74fef07..8513c1f 100644 (file)
@@ -21,6 +21,7 @@
 package org.onap.policy.drools.serverpooltest;
 
 import java.util.Map;
+import java.util.Properties;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -39,7 +40,7 @@ import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
-
+import org.onap.policy.drools.utils.PropertyUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,7 +51,6 @@ import org.slf4j.LoggerFactory;
 @Path("/")
 public class SimDmaap {
     private static Logger logger = LoggerFactory.getLogger(SimDmaap.class);
-    public static final String HOSTNAME = "127.0.63.250";
 
     // miscellaneous Jetty/Servlet parameters
     private static ServletContextHandler context;
@@ -73,8 +73,10 @@ public class SimDmaap {
             connector = new ServerConnector(jettyServer);
             connector.setName("simdmaap");
             connector.setReuseAddress(true);
-            connector.setPort(3904);
-            connector.setHost("127.0.63.250");
+            final String propertyFile = "src/test/resources/feature-server-pool-test.properties";
+            Properties prop = PropertyUtil.getProperties(propertyFile);
+            connector.setPort(Integer.parseInt(prop.getProperty("server.pool.discovery.port")));
+            connector.setHost(prop.getProperty("server.pool.discovery.servers"));
 
             jettyServer.addConnector(connector);
             jettyServer.setHandler(context);
@@ -166,11 +168,12 @@ public class SimDmaap {
             int messageCount = 0;
 
             while (cur < end) {
-                // The body of the message may consist of multiple JSON messages,
-                // each preceded by 3 integers separated by '.'. The second one
-                // is the length, in bytes (the third seems to be some kind of
-                // channel identifier).
-
+                /*
+                 * The body of the message may consist of multiple JSON messages,
+                 * each preceded by 3 integers separated by '.'. The second one
+                 * is the length, in bytes (the third seems to be some kind of
+                 * channel identifier).
+                 */
                 int leftBrace = data.indexOf('{', cur);
                 if (leftBrace < 0) {
                     // no more messages
@@ -182,11 +185,12 @@ public class SimDmaap {
                         // determine length of message, and advance current position
                         int length = Integer.valueOf(prefix[1]);
                         cur = leftBrace + length;
-
-                        // extract message, and update count -- each double quote
-                        // has a '\' character placed before it, so the overall
-                        // message can be placed in double quotes, and parsed as
-                        // a literal string
+                        /*
+                         * extract message, and update count -- each double quote
+                         * has a '\' character placed before it, so the overall
+                         * message can be placed in double quotes, and parsed as
+                         * a literal string
+                         */
                         String message = data.substring(leftBrace, cur)
                                          .replace("\\", "\\\\").replace("\"", "\\\"")
                                          .replace("\n", "\\n");
index 89414b5..7d64558 100644 (file)
@@ -7,7 +7,7 @@ rules.groupId=org.onap.policy.drools-pdp
 rules.version=1.0.0
 
 ueb.source.topics=JUNIT-TEST-TOPIC
-ueb.source.topics.JUNIT-TEST-TOPIC.servers=127.0.63.250
+ueb.source.topics.JUNIT-TEST-TOPIC.servers=127.0.0.1
 ueb.source.topics.JUNIT-TEST-TOPIC.events=org.onap.policy.drools.serverpooltest.TestDroolsObject
 ueb.source.topics.JUNIT-TEST-TOPIC.events.org.onap.policy.drools.serverpooltest.TestDroolsObject.filter=
 [?($.key =~ /.*/)]
\ No newline at end of file
diff --git a/feature-server-pool/src/test/resources/feature-server-pool-test.properties b/feature-server-pool/src/test/resources/feature-server-pool-test.properties
new file mode 100644 (file)
index 0000000..70fed3f
--- /dev/null
@@ -0,0 +1,142 @@
+###
+# ============LICENSE_START=======================================================
+# feature-server-pool
+# ================================================================================
+# Copyright (C) 2020 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 following properties control the IP address and port that a given
+# server binds to. The default will bind to all interfaces on the host,
+# and choose a port number at random.
+
+server.pool.server.ipAddress=127.0.0.1
+server.pool.server.port=20000
+
+# The following properties determine whether HTTPS is used -- note that HTTPS
+# also requires that the 'java.net.ssl.*' parameters in 'system.properties' be
+# specified, and the key store and trust store be configured, as appropriate.
+server.pool.server.https=
+server.pool.server.selfSignedCerts=false
+
+# The IP address and port that servers on the geo-redundant site
+# should use to connect to servers on this site.
+server.pool.server.site.ip=
+server.pool.server.site.port=
+
+# A comma-separated list of host names -- if an entry is found that refers
+# to an HTTP/HTTPS destination IP address, the host name will used as the
+# destination, instead of the IP address
+server.pool.server.hostlist=
+
+# The servers send 'pings' to each other once per main loop cycle. They
+# also measure the gap between 'pings' from each server, and calculate
+# an allowed time gap based upon this. 'server.pool.server.allowedGap' is the initial
+# allowed gap prior to receiving any pings (default=30 seconds), and
+# 'server.pool.server.adaptiveGapAdjust' is a value that is added to the calculated
+# gap "just in case" (default=5 seconds)
+
+server.pool.server.allowedGap=30000
+server.pool.server.adaptiveGapAdjust=5000
+
+# 'connectTimeout' and 'readTimeout' affect the client end of a REST
+# connection (default=10 seconds each)
+
+server.pool.server.connectTimeout=10000
+server.pool.server.readTimeout=10000
+
+# Each server has a thread pool per remote server, which is used when
+# sending HTTP REST messages -- the following parameters determine the
+# configuration.
+
+server.pool.server.threads.corePoolSize=5
+server.pool.server.threads.maximumPoolSize=10
+server.pool.server.threads.keepAliveTime=5000
+
+# The server pool members use a UEB/DMAAP topic to connect with other
+# servers in the pool. The following set of parameters are passed to
+# the CambriaClient library, and are used in setting up the consumer and
+# publisher ends of the connection. 'discovery.servers' and 'discovery.topic'
+# are the minimum values that need to be specified. The last parameter in
+# this set, 'discovery.publisherLoopCycleTime' isn't passed to the
+# CambriaClient library; instead, it controls how frequently the 'ping'
+# messages are sent out on this channel. Note that only the lead server
+# keeps this channel open long-term.
+
+server.pool.discovery.servers=127.0.0.1
+server.pool.discovery.port=3904
+server.pool.discovery.topic=DISCOVERY-TOPIC
+server.pool.discovery.username=
+server.pool.discovery.password=
+server.pool.discovery.https=
+server.pool.discovery.apiKey=
+server.pool.discovery.apiSecret=
+#server.pool.discovery.publisherSocketTimeout=5000
+#server.pool.discovery.consumerSocketTimeout=70000
+server.pool.discovery.fetchTimeout=60000
+server.pool.discovery.fetchLimit=100
+server.pool.discovery.selfSignedCertificates=false
+server.pool.discovery.publisherLoopCycleTime=5000
+
+# The 'leader.*' parameters affect behavior during an election. The value of
+# 'mainLoop.cycle' determines the actual time delay. 'leader.stableIdCycles'
+# is the required minimum number of "stable" cycles before voting can start
+# (in this case, "stable" means no servers added or failing). Once voting has
+# started, "leader.stableVotingCycles' is the minimum number of "stable"
+# cycles needed before declaring a winner (in this case, "stable" means no
+# votes changing).
+
+server.pool.leader.stableIdleCycles=5
+server.pool.leader.stableVotingCycles=5
+
+# The value of 'mainLoop.cycle' (default = 1 second) determines how frequently
+# various events occur, such as the sending of 'ping' messages, and the
+# duration of a "cycle" while voting for a lead server.
+
+server.pool.mainLoop.cycle=1000
+
+# 'keyword.path' is used when looking for "keywords" within JSON messages.
+# The first keyword located is hashed to determine which bucket to route
+# through.
+
+keyword.path=requestID,CommonHeader.RequestID,body.output.common-header.request-id,result-info.request-id:uuid
+# 'keyword.<CLASS-NAME>.lookup' is used to locate "keywords" within objects.
+# The 'value' field contains a list of method calls or field names separated
+# by '.' that are used to locate the keyword
+# (e.g. 'method1().field2.method3()')
+
+keyword.java.lang.String.lookup=toString()
+keyword.org.onap.policy.m2.base.Transaction.lookup=getRequestID()
+keyword.org.onap.policy.controlloop.ControlLoopEvent.lookup=requestID
+keyword.org.onap.policy.appclcm.LcmRequestWrapper.lookup=getBody().getCommonHeader().getRequestId()
+keyword.org.onap.policy.appclcm.LcmResponseWrapper.lookup=getBody().getCommonHeader().getRequestId()
+keyword.org.onap.policy.drools.serverpool.TargetLock.lookup=getOwnerKey()
+keyword.org.onap.policy.drools.serverpooltest.TestDroolsObject.lookup=getKey()
+keyword.org.onap.policy.drools.serverpooltest.Test1$KeywordWrapper.lookup=key
+
+# The following properties affect distributed 'TargetLock' behavior.
+#
+#   server.pool.lock.ttl - controls how many hops a 'TargetLock' message can take
+#   server.pool.lock.audit.period - how frequently should the audit run?
+#   server.pool.lock.audit.gracePeriod - how long to wait after bucket reassignments
+#       before running the audit again
+#   server.pool.lock.audit.retryDelay - mismatches can occur due to the transient nature
+#       of the lock state: this property controls how long to wait before
+#       trying again
+
+server.pool.lock.ttl=3
+server.pool.lock.audit.period=300000
+server.pool.lock.audit.gracePeriod=60000
+server.pool.lock.audit.retryDelay=5000
\ No newline at end of file