[CCSDK-1985]GR Toolkit Refactor
[ccsdk/sli/plugins.git] / grToolkit / provider / src / main / java / org / onap / ccsdk / sli / plugins / grtoolkit / resolver / ShardResolver.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights
6  *                      reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
23
24 import org.json.JSONArray;
25 import org.json.JSONException;
26 import org.json.JSONObject;
27
28 import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionManager;
29 import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionResponse;
30 import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
31 import org.onap.ccsdk.sli.plugins.grtoolkit.data.PropertyKeys;
32
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Properties;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
43
44 /**
45  * Used to perform operations on the data shard information returned as JSON
46  * from Jolokia.
47  *
48  * @author Anthony Haddox
49  * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
50  * @see HealthResolver
51  */
52 public class ShardResolver {
53     private final Logger log = LoggerFactory.getLogger(ShardResolver.class);
54     private static ShardResolver _shardResolver;
55
56     private String jolokiaClusterPath;
57     private String shardManagerPath;
58     private String shardPathTemplate;
59     private String credentials;
60     private String httpProtocol;
61
62     private static final String VALUE = "value";
63
64     private ShardResolver(Properties properties) {
65         String port = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? properties.getProperty(PropertyKeys.CONTROLLER_PORT_SSL).trim() : properties.getProperty(PropertyKeys.CONTROLLER_PORT_HTTP).trim();
66         httpProtocol = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? "https://" : "http://";
67         jolokiaClusterPath = ":" + port + properties.getProperty(PropertyKeys.MBEAN_CLUSTER).trim();
68         shardManagerPath = ":" + port + properties.getProperty(PropertyKeys.MBEAN_SHARD_MANAGER).trim();
69         shardPathTemplate = ":" + port + properties.getProperty(PropertyKeys.MBEAN_SHARD_CONFIG).trim();
70         credentials = properties.getProperty(PropertyKeys.CONTROLLER_CREDENTIALS).trim();
71     }
72
73     public static ShardResolver getInstance(Properties properties) {
74         if (_shardResolver == null) {
75             _shardResolver = new ShardResolver(properties);
76         }
77         return _shardResolver;
78     }
79
80     private void getMemberStatus(ClusterActor clusterActor) throws IOException {
81         log.info("getMemberStatus(): Getting member status for {}", clusterActor.getNode());
82         ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + jolokiaClusterPath, ConnectionManager.HttpMethod.GET, null, credentials);
83         try {
84             JSONObject responseJson = new JSONObject(response.content);
85             JSONObject responseValue = responseJson.getJSONObject(VALUE);
86             clusterActor.setUp("Up".equals(responseValue.getString("MemberStatus")));
87             clusterActor.setUnreachable(false);
88         } catch(JSONException e) {
89             log.error("getMemberStatus(): Error parsing response from {}", clusterActor.getNode(), e);
90             clusterActor.setUp(false);
91             clusterActor.setUnreachable(true);
92         }
93     }
94
95     private void getShardStatus(ClusterActor clusterActor) throws IOException {
96         log.info("getShardStatus(): Getting shard status for {}", clusterActor.getNode());
97         ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + shardManagerPath, ConnectionManager.HttpMethod.GET, null, credentials);
98         try {
99             JSONObject responseValue = new JSONObject(response.content).getJSONObject(VALUE);
100             JSONArray shardList = responseValue.getJSONArray("LocalShards");
101
102             String pattern = "-config$";
103             Pattern r = Pattern.compile(pattern);
104             List<String> shards = new ArrayList<>();
105             for(int ndx = 0; ndx < shardList.length(); ndx++) {
106                 shards.add(shardList.getString(ndx));
107             }
108             shards.parallelStream().forEach(shard -> {
109                 Matcher m = r.matcher(shard);
110                 String operationalShardName = m.replaceFirst("-operational");
111                 String shardConfigPath = String.format(shardPathTemplate, shard);
112                 String shardOperationalPath = String.format(shardPathTemplate, operationalShardName).replace("Config", "Operational");
113                 try {
114                     extractShardInfo(clusterActor, shard, shardConfigPath);
115                     extractShardInfo(clusterActor, operationalShardName, shardOperationalPath);
116                 } catch(IOException e) {
117                     log.error("getShardStatus(): Error extracting shard info for {}", shard);
118                 }
119             });
120         } catch(JSONException e) {
121             log.error("getShardStatus(): Error parsing response from " + clusterActor.getNode(), e);
122         }
123     }
124
125     private void extractShardInfo(ClusterActor clusterActor, String shardName, String shardPath) throws IOException {
126         log.info("extractShardInfo(): Extracting shard info for {}", shardName);
127         String shardPrefix = "";
128 //        String shardPrefix = clusterActor.getMember() + "-shard-";
129         log.debug("extractShardInfo(): Pulling config info for {} from: {}", shardName, shardPath);
130         ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + shardPath, ConnectionManager.HttpMethod.GET, null, credentials);
131         log.debug("extractShardInfo(): Response: {}", response.content);
132
133         try {
134             JSONObject shardValue = new JSONObject(response.content).getJSONObject(VALUE);
135             clusterActor.setVoting(shardValue.getBoolean("Voting"));
136             if(shardValue.getString("PeerAddresses").length() > 0) {
137                 clusterActor.getReplicaShards().add(shardName.replace(shardPrefix, ""));
138                 if(shardValue.getString("Leader").startsWith(clusterActor.getMember())) {
139                     clusterActor.getShardLeader().add(shardName.replace(shardPrefix, ""));
140                 }
141             } else {
142                 clusterActor.getNonReplicaShards().add(shardName.replace(shardPrefix, ""));
143             }
144             JSONArray followerInfo = shardValue.getJSONArray("FollowerInfo");
145             for(int followerNdx = 0; followerNdx < followerInfo.length(); followerNdx++) {
146                 int commitIndex = shardValue.getInt("CommitIndex");
147                 int matchIndex = followerInfo.getJSONObject(followerNdx).getInt("matchIndex");
148                 if(commitIndex != -1 && matchIndex != -1) {
149                     int commitsBehind = commitIndex - matchIndex;
150                     clusterActor.getCommits().put(followerInfo.getJSONObject(followerNdx).getString("id"), commitsBehind);
151                 }
152             }
153         } catch(JSONException e) {
154             log.error("extractShardInfo(): Error parsing response from " + clusterActor.getNode(), e);
155         }
156     }
157
158     public void getControllerHealth(Map<String, ClusterActor> memberMap) {
159         memberMap.values().parallelStream().forEach(this::getControllerHealth);
160     }
161
162     // Seen ConcurrentAccess issues, probably related to getting the controller health
163     private synchronized void getControllerHealth(ClusterActor clusterActor) {
164         clusterActor.flush();
165         log.info("getControllerHealth(): Gathering info for {}", clusterActor.getNode());
166         try {
167             // First flush out the old values
168             getMemberStatus(clusterActor);
169             getShardStatus(clusterActor);
170         } catch(IOException e) {
171             log.error("getControllerHealth(): Connection Error", e);
172             clusterActor.setUnreachable(true);
173             clusterActor.setUp(false);
174         }
175         log.info("getControllerHealth(): MemberInfo:\n{}", clusterActor);
176     }
177 }