1 /*******************************************************************************
2 * ============LICENSE_START==================================================
4 * * ===========================================================================
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * * ===========================================================================
7 * * Licensed under the Apache License, Version 2.0 (the "License");
8 * * you may not use this file except in compliance with the License.
9 * * You may obtain a copy of the License at
11 * * http://www.apache.org/licenses/LICENSE-2.0
13 * * Unless required by applicable law or agreed to in writing, software
14 * * distributed under the License is distributed on an "AS IS" BASIS,
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * * See the License for the specific language governing permissions and
17 * * limitations under the License.
18 * * ============LICENSE_END====================================================
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 ******************************************************************************/
24 package org.onap.dmaap.datarouter.provisioning;
26 import java.io.IOException;
27 import java.net.HttpURLConnection;
28 import java.net.InetAddress;
29 import java.net.MalformedURLException;
31 import java.net.UnknownHostException;
32 import java.util.Arrays;
33 import java.util.HashSet;
36 import java.util.Timer;
37 import java.util.TimerTask;
38 import java.util.TreeSet;
40 import org.apache.log4j.Logger;
41 import org.json.JSONException;
42 import org.json.JSONObject;
43 import org.json.JSONTokener;
44 import org.onap.dmaap.datarouter.provisioning.beans.EgressRoute;
45 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
46 import org.onap.dmaap.datarouter.provisioning.beans.Group;
47 import org.onap.dmaap.datarouter.provisioning.beans.IngressRoute;
48 import org.onap.dmaap.datarouter.provisioning.beans.NetworkRoute;
49 import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
50 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
51 import org.onap.dmaap.datarouter.provisioning.utils.*;
54 * This class handles the two timers (described in R1 Design Notes), and takes care of issuing the GET to each node of
58 * @version $Id: Poker.java,v 1.11 2014/01/08 16:13:47 eby Exp $
60 public class Poker extends TimerTask {
63 * Template used to generate the URL to issue the GET against
65 private static final String POKE_URL_TEMPLATE = "http://%s/internal/fetchProv";
67 private static final Object lock = new Object();
70 * This is a singleton -- there is only one Poker object in the server
72 private static Poker poker;
75 * Get the singleton Poker object.
79 public static synchronized Poker getPoker() {
88 private String thisPod; // DNS name of this machine
89 private Logger logger;
90 private String provString;
94 Timer rolex = new Timer();
95 logger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
97 thisPod = InetAddress.getLocalHost().getHostName();
98 } catch (UnknownHostException e) {
99 thisPod = "*UNKNOWN*"; // not a major problem
101 provString = buildProvisioningString();
103 rolex.scheduleAtFixedRate(this, 0L, 1000L); // Run once a second to check the timers
107 * This method sets the two timers described in the design notes.
109 * @param t1 the first timer controls how long to wait after a provisioning request before poking each node This
110 * timer can be reset if it has not "gone off".
111 * @param t2 the second timer set the outer bound on how long to wait. It cannot be reset.
113 public void setTimers(long t1, long t2) {
114 synchronized (lock) {
115 if (timer1 == 0 || t1 > timer1) {
122 if (logger.isDebugEnabled()) {
123 logger.debug("Poker timers set to " + timer1 + " and " + timer2);
130 * Return the last provisioning string built.
132 * @return the last provisioning string built.
134 public String getProvisioningString() {
139 * The method to run at the predefined interval (once per second). This method checks to see if either of the two
140 * timers has expired, and if so, will rebuild the provisioning string, and poke all the nodes and other PODs. The
141 * timers are then reset to 0.
147 long now = System.currentTimeMillis();
148 boolean fire = false;
149 synchronized (lock) {
150 if (now > timer1 || now > timer2) {
159 } catch (Exception e) {
160 logger.warn("PROV0020: Caught exception in Poker: " + e);
165 private void pokeNodes() {
166 // Rebuild the prov string
167 provString = buildProvisioningString();
168 // Only the active POD should poke nodes, etc.
169 boolean active = SynchronizerTask.getSynchronizer().isActive();
171 // Poke all the DR nodes
172 for (String n : BaseServlet.getNodes()) {
175 // Poke the pod that is not us
176 for (String n : BaseServlet.getPods()) {
177 if (n.length() > 0 && !n.equals(thisPod)) {
184 private void pokeNode(final String nodename) {
185 logger.debug("PROV0012 Poking node " + nodename + " ...");
186 String nodeUrl = String.format(POKE_URL_TEMPLATE, nodename + ":" + DB.HTTP_PORT);
189 URL url = new URL(nodeUrl);
190 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
191 conn.setConnectTimeout(60000); //Fixes for Itrack DATARTR-3, poke timeout
193 conn.getContentLength(); // Force the GET through
195 } catch (MalformedURLException e) {
196 logger.warn("PROV0013 MalformedURLException Error poking node at " + nodeUrl + " : " + e.getMessage());
197 } catch (IOException e) {
198 logger.warn("PROV0013 IOException Error poking node at " + nodeUrl + " : " + e.getMessage());
204 private String buildProvisioningString() {
205 StringBuilder sb = new StringBuilder("{\n");
207 // Append Feeds to the string
209 sb.append("\"feeds\": [");
210 for (Feed f : Feed.getAllFeeds()) {
212 sb.append(f.asJSONObject().toString());
217 //Append groups to the string - Rally:US708115 - 1610
219 sb.append("\"groups\": [");
220 for (Group s : Group.getAllgroups()) {
222 sb.append(s.asJSONObject().toString());
227 // Append Subscriptions to the string
229 sb.append("\"subscriptions\": [");
230 for (Subscription s : Subscription.getAllSubscriptions()) {
233 sb.append(s.asJSONObject().toString());
239 // Append Parameters to the string
241 sb.append("\"parameters\": {");
242 Map<String, String> props = Parameters.getParameters();
243 Set<String> ivals = new HashSet<String>();
244 String intv = props.get("_INT_VALUES");
246 ivals.addAll(Arrays.asList(intv.split("\\|")));
248 for (String key : new TreeSet<String>(props.keySet())) {
249 String v = props.get(key);
251 sb.append(" \"").append(key).append("\": ");
252 if (ivals.contains(key)) {
255 } else if (key.endsWith("S")) {
256 // Split and append array of strings
257 String[] pp = v.split("\\|");
260 for (String t : pp) {
261 sb.append(p2).append("\"").append(quote(t)).append("\"");
266 sb.append("\"").append(quote(v)).append("\"");
272 // Append Routes to the string
274 sb.append("\"ingress\": [");
275 for (IngressRoute in : IngressRoute.getAllIngressRoutes()) {
277 sb.append(in.asJSONObject().toString());
283 sb.append("\"egress\": {");
284 for (EgressRoute eg : EgressRoute.getAllEgressRoutes()) {
286 String t = eg.asJSONObject().toString();
287 t = t.substring(1, t.length() - 1);
294 sb.append("\"routing\": [");
295 for (NetworkRoute ne : NetworkRoute.getAllNetworkRoutes()) {
297 sb.append(ne.asJSONObject().toString());
303 // Convert to string and verify it is valid JSON
304 String tempProvString = sb.toString();
306 new JSONObject(new JSONTokener(tempProvString));
307 } catch (JSONException e) {
308 logger.warn("PROV0016: Possible invalid prov string: " + e);
310 return tempProvString;
313 private String quote(String s) {
314 StringBuilder sb = new StringBuilder();
315 for (char ch : s.toCharArray()) {
316 if (ch == '\\' || ch == '"') {
321 return sb.toString();