2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
24 import org.json.JSONArray;
25 import org.json.JSONException;
26 import org.json.JSONObject;
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;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.List;
40 import java.util.Properties;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
45 * Used to perform operations on the data shard information returned as JSON
48 * @author Anthony Haddox
49 * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
52 public class ShardResolver {
53 private final Logger log = LoggerFactory.getLogger(ShardResolver.class);
54 private static ShardResolver _shardResolver;
56 private String jolokiaClusterPath;
57 private String shardManagerPath;
58 private String shardPathTemplate;
59 private String credentials;
60 private String httpProtocol;
62 private static final String VALUE = "value";
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();
73 public static ShardResolver getInstance(Properties properties) {
74 if (_shardResolver == null) {
75 _shardResolver = new ShardResolver(properties);
77 return _shardResolver;
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);
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);
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);
99 JSONObject responseValue = new JSONObject(response.content).getJSONObject(VALUE);
100 JSONArray shardList = responseValue.getJSONArray("LocalShards");
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));
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");
114 extractShardInfo(clusterActor, shard, shardConfigPath);
115 extractShardInfo(clusterActor, operationalShardName, shardOperationalPath);
116 } catch(IOException e) {
117 log.error("getShardStatus(): Error extracting shard info for {}", shard);
120 } catch(JSONException e) {
121 log.error("getShardStatus(): Error parsing response from " + clusterActor.getNode(), e);
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);
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, ""));
142 clusterActor.getNonReplicaShards().add(shardName.replace(shardPrefix, ""));
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);
153 } catch(JSONException e) {
154 log.error("extractShardInfo(): Error parsing response from " + clusterActor.getNode(), e);
158 public void getControllerHealth(Map<String, ClusterActor> memberMap) {
159 memberMap.values().parallelStream().forEach(this::getControllerHealth);
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());
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);
175 log.info("getControllerHealth(): MemberInfo:\n{}", clusterActor);