Update project structure to org.onap
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / Poker.java
1 /*******************************************************************************\r
2  * ============LICENSE_START==================================================\r
3  * * org.onap.dmaap\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 \r
24 package org.onap.dmaap.datarouter.provisioning;\r
25 \r
26 import java.io.FileInputStream;\r
27 import java.io.IOException;\r
28 import java.io.InputStream;\r
29 import java.net.HttpURLConnection;\r
30 import java.net.InetAddress;\r
31 import java.net.MalformedURLException;\r
32 import java.net.URL;\r
33 import java.net.UnknownHostException;\r
34 import java.util.Arrays;\r
35 import java.util.HashSet;\r
36 import java.util.Map;\r
37 import java.util.Properties;\r
38 import java.util.Set;\r
39 import java.util.Timer;\r
40 import java.util.TimerTask;\r
41 import java.util.TreeSet;\r
42 \r
43 import javax.servlet.ServletException;\r
44 \r
45 import org.apache.log4j.Logger;\r
46 import org.json.JSONException;\r
47 import org.json.JSONObject;\r
48 import org.json.JSONTokener;\r
49 import org.onap.dmaap.datarouter.provisioning.beans.EgressRoute;\r
50 import org.onap.dmaap.datarouter.provisioning.beans.Feed;\r
51 import org.onap.dmaap.datarouter.provisioning.beans.Group;\r
52 import org.onap.dmaap.datarouter.provisioning.beans.IngressRoute;\r
53 import org.onap.dmaap.datarouter.provisioning.beans.NetworkRoute;\r
54 import org.onap.dmaap.datarouter.provisioning.beans.Parameters;\r
55 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;\r
56 import org.onap.dmaap.datarouter.provisioning.utils.*;\r
57 \r
58 /**\r
59  * This class handles the two timers (described in R1 Design Notes), and takes care of issuing\r
60  * the GET to each node of the URL to "poke".\r
61  *\r
62  * @author Robert Eby\r
63  * @version $Id: Poker.java,v 1.11 2014/01/08 16:13:47 eby Exp $\r
64  */\r
65 public class Poker extends TimerTask {\r
66         /** Template used to generate the URL to issue the GET against */\r
67         public static final String POKE_URL_TEMPLATE = "http://%s/internal/fetchProv";\r
68         \r
69         \r
70         \r
71 \r
72         /** This is a singleton -- there is only one Poker object in the server */\r
73         private static Poker p;\r
74 \r
75         /**\r
76          * Get the singleton Poker object.\r
77          * @return the Poker\r
78          */\r
79         public static synchronized Poker getPoker() {\r
80                 if (p == null)\r
81                         p = new Poker();\r
82                 return p;\r
83         }\r
84 \r
85         private long timer1;\r
86         private long timer2;\r
87         private Timer rolex;\r
88         private String this_pod;                // DNS name of this machine\r
89         private Logger logger;\r
90         private String provstring;\r
91 \r
92         private Poker() {\r
93                 timer1 = timer2 = 0;\r
94                 rolex = new Timer();\r
95                 logger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");\r
96                 try {\r
97                         this_pod = InetAddress.getLocalHost().getHostName();\r
98                 } catch (UnknownHostException e) {\r
99                         this_pod = "*UNKNOWN*"; // not a major problem\r
100                 }\r
101                 provstring = buildProvisioningString();\r
102 \r
103                 rolex.scheduleAtFixedRate(this, 0L, 1000L);     // Run once a second to check the timers\r
104         }\r
105 \r
106         /**\r
107          * This method sets the two timers described in the design notes.\r
108          * @param t1 the first timer controls how long to wait after a provisioning request before poking each node\r
109          *   This timer can be reset if it has not "gone off".\r
110          * @param t2 the second timer set the outer bound on how long to wait.  It cannot be reset.\r
111          */\r
112         public void setTimers(long t1, long t2) {\r
113                 synchronized (this_pod) {\r
114                         if (timer1 == 0 || t1 > timer1)\r
115                                 timer1 = t1;\r
116                         if (timer2 == 0)\r
117                                 timer2 = t2;\r
118                 }\r
119                 if (logger.isDebugEnabled())\r
120                         logger.debug("Poker timers set to " + timer1 + " and " + timer2);\r
121         \r
122                 \r
123         }\r
124 \r
125         /**\r
126          * Return the last provisioning string built.\r
127          * @return the last provisioning string built.\r
128          */\r
129         public String getProvisioningString() {\r
130                 return provstring;\r
131         }\r
132 \r
133         /**\r
134          * The method to run at the predefined interval (once per second).  This method checks\r
135          * to see if either of the two timers has expired, and if so, will rebuild the provisioning\r
136          * string, and poke all the nodes and other PODs.  The timers are then reset to 0.\r
137          */\r
138         @Override\r
139         public void run() {\r
140                 try {\r
141                         if (timer1 > 0) {\r
142                                 long now = System.currentTimeMillis();\r
143                                 boolean fire = false;\r
144                                 synchronized (this_pod) {\r
145                                         if (now > timer1 || now > timer2) {\r
146                                                 timer1 = timer2 = 0;\r
147                                                 fire = true;\r
148                                         }\r
149                                 }\r
150                                 if (fire) {\r
151                                         // Rebuild the prov string\r
152                                         provstring = buildProvisioningString();\r
153 \r
154                                         // Only the active POD should poke nodes, etc.\r
155                                         boolean active = SynchronizerTask.getSynchronizer().isActive();\r
156                                         if (active) {\r
157                                                 // Poke all the DR nodes\r
158                                                 for (String n : BaseServlet.getNodes()) {\r
159                                                         pokeNode(n);\r
160                                                 }\r
161                                                 // Poke the pod that is not us\r
162                                                 for (String n : BaseServlet.getPods()) {\r
163                                                         if (n.length() > 0 && !n.equals(this_pod))\r
164                                                                 pokeNode(n);\r
165                                                 }\r
166                                         }\r
167                                 }\r
168                         }\r
169                 } catch (Exception e) {\r
170                         logger.warn("PROV0020: Caught exception in Poker: "+e);\r
171                         e.printStackTrace();\r
172                 }\r
173         }\r
174         private void pokeNode(final String nodename) {\r
175                 logger.debug("PROV0012 Poking node " + nodename + " ...");\r
176                 Runnable r = new Runnable() {\r
177                         @Override\r
178                         public void run() {\r
179                         \r
180                                 try {\r
181                                         String u = String.format(POKE_URL_TEMPLATE, nodename+":"+DB.HTTP_PORT);\r
182                                         URL url = new URL(u);\r
183                                         HttpURLConnection conn = (HttpURLConnection) url.openConnection();\r
184                                         conn.setConnectTimeout(60000);  //Fixes for Itrack DATARTR-3, poke timeout\r
185                                         conn.connect();\r
186                                         conn.getContentLength();        // Force the GET through\r
187                                         conn.disconnect();\r
188                                 } catch (MalformedURLException e) {\r
189                                         logger.warn("PROV0013 MalformedURLException Error poking node "+nodename+": " + e.getMessage());\r
190                                 } catch (IOException e) {\r
191                                         logger.warn("PROV0013 IOException Error poking node "+nodename+": " + e.getMessage());\r
192                                 }\r
193                         }\r
194                 };\r
195 //              Thread t = new Thread(r);\r
196 //              t.start();\r
197                 r.run();\r
198         }\r
199         @SuppressWarnings("unused")\r
200         private String buildProvisioningString() {\r
201                 StringBuilder sb = new StringBuilder("{\n");\r
202 \r
203                 // Append Feeds to the string\r
204                 String pfx = "\n";\r
205                 sb.append("\"feeds\": [");\r
206                 for (Feed f : Feed.getAllFeeds()) {\r
207                         sb.append(pfx);\r
208                         sb.append(f.asJSONObject().toString());\r
209                         pfx = ",\n";\r
210                 }\r
211                 sb.append("\n],\n");\r
212                 \r
213                 //Append groups to the string - Rally:US708115  - 1610          \r
214                 pfx = "\n";             \r
215                 sb.append("\"groups\": [");             \r
216                 for (Group s : Group.getAllgroups()) {          \r
217                         sb.append(pfx);         \r
218                         sb.append(s.asJSONObject().toString());         \r
219                         pfx = ",\n";            \r
220                 }               \r
221                 sb.append("\n],\n");            \r
222                                 \r
223 \r
224                 // Append Subscriptions to the string\r
225                 pfx = "\n";\r
226                 sb.append("\"subscriptions\": [");\r
227                 for (Subscription s : Subscription.getAllSubscriptions()) {\r
228                         sb.append(pfx);\r
229                         if(s!=null)\r
230                         sb.append(s.asJSONObject().toString());\r
231                         pfx = ",\n";\r
232                 }\r
233                 sb.append("\n],\n");\r
234 \r
235                 // Append Parameters to the string\r
236                 pfx = "\n";\r
237                 sb.append("\"parameters\": {");\r
238                 Map<String,String> props = Parameters.getParameters();\r
239                 Set<String> ivals = new HashSet<String>();\r
240                 String intv = props.get("_INT_VALUES");\r
241                 if (intv != null)\r
242                         ivals.addAll(Arrays.asList(intv.split("\\|")));\r
243                 for (String key : new TreeSet<String>(props.keySet())) {\r
244                         String v = props.get(key);\r
245                         sb.append(pfx);\r
246                         sb.append("  \"").append(key).append("\": ");\r
247                         if (ivals.contains(key)) {\r
248                                 // integer value\r
249                                 sb.append(v);\r
250                         } else if (key.endsWith("S")) {\r
251                                 // Split and append array of strings\r
252                                 String[] pp = v.split("\\|");\r
253                                 String p2 = "";\r
254                                 sb.append("[");\r
255                                 for (String t : pp) {\r
256                                         sb.append(p2).append("\"").append(quote(t)).append("\"");\r
257                                         p2 = ",";\r
258                                 }\r
259                                 sb.append("]");\r
260                         } else {\r
261                                 sb.append("\"").append(quote(v)).append("\"");\r
262                         }\r
263                         pfx = ",\n";\r
264                 }\r
265                 sb.append("\n},\n");\r
266 \r
267                 // Append Routes to the string\r
268                 pfx = "\n";\r
269                 sb.append("\"ingress\": [");\r
270                 for (IngressRoute in : IngressRoute.getAllIngressRoutes()) {\r
271                         sb.append(pfx);\r
272                         sb.append(in.asJSONObject().toString());\r
273                         pfx = ",\n";\r
274                 }\r
275                 sb.append("\n],\n");\r
276 \r
277                 pfx = "\n";\r
278                 sb.append("\"egress\": {");\r
279                 for (EgressRoute eg : EgressRoute.getAllEgressRoutes()) {\r
280                         sb.append(pfx);\r
281                         String t = eg.asJSONObject().toString();\r
282                         t = t.substring(1, t.length()-1);\r
283                         sb.append(t);\r
284                         pfx = ",\n";\r
285                 }\r
286                 sb.append("\n},\n");\r
287 \r
288                 pfx = "\n";\r
289                 sb.append("\"routing\": [");\r
290                 for (NetworkRoute ne : NetworkRoute.getAllNetworkRoutes()) {\r
291                         sb.append(pfx);\r
292                         sb.append(ne.asJSONObject().toString());\r
293                         pfx = ",\n";\r
294                 }\r
295                 sb.append("\n]");\r
296                 sb.append("\n}");\r
297 \r
298                 // Convert to string and verify it is valid JSON\r
299                 String provstring = sb.toString();\r
300                 try {\r
301                         new JSONObject(new JSONTokener(provstring));\r
302                 } catch (JSONException e) {\r
303                         logger.warn("PROV0016: Possible invalid prov string: "+e);\r
304                 }\r
305                 return provstring;\r
306         }\r
307         private String quote(String s) {\r
308                 StringBuilder sb = new StringBuilder();\r
309                 for (char ch : s.toCharArray()) {\r
310                         if (ch == '\\' || ch == '"') {\r
311                                 sb.append('\\');\r
312                         }\r
313                         sb.append(ch);\r
314                 }\r
315                 return sb.toString();\r
316         }\r
317 }\r