blob: e23cb0b66929accf00f501e2475a623de6428aaf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
package com.cloud.network.resource;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.naming.ConfigurationException;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.BasicClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.gson.Gson;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer;
import com.cloud.agent.api.ExternalNetworkResourceUsageCommand;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.NetScalerImplementNetworkCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
import com.cloud.agent.api.UnsupportedAnswer;
import com.cloud.agent.api.routing.DestroyLoadBalancerApplianceCommand;
import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand;
import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer;
import com.cloud.agent.api.routing.HealthCheckLBConfigCommand;
import com.cloud.agent.api.routing.IpAssocAnswer;
import com.cloud.agent.api.routing.IpAssocCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.LoadBalancerTO;
import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO;
import com.cloud.agent.api.to.LoadBalancerTO.StickinessPolicyTO;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType;
import com.cloud.resource.ServerResource;
import com.cloud.serializer.GsonHelper;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.StringUtils;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.NetUtils;
class NccHttpCode {
static final String INTERNAL_ERROR = "INTERNAL ERROR";
static final String NOT_FOUND = "NOT FOUND";
static final String JOB_ID = "Job_id";
static final String UNAUTHORIZED = "UNAUTHORIZED";
}
public class NetScalerControlCenterResource implements ServerResource {
// deployment configuration
private String _name;
private String _zoneId;
private String _ip;
private String _username;
private String _password;
private String _publicInterface;
private String _privateInterface;
private Integer _numRetries;
private Long _nccCmdTimeout;
private String _guid;
private boolean _inline;
private String _deviceName;
private String _sessionid;
public static final int DEFAULT_PORT = 443;
private static final Gson s_gson = GsonHelper.getGson();
private static final Logger s_logger = Logger.getLogger(NetScalerControlCenterResource.class);
protected Gson _gson;
private final String _objectNamePathSep = "-";
final String protocol="https";
private static String nccsession;
private int pingCount = 0;
public NetScalerControlCenterResource() {
_gson = GsonHelper.getGsonLogger();
}
public static String get_nccsession() {
return nccsession;
}
public static void set_nccsession(String nccsession) {
NetScalerControlCenterResource.nccsession = nccsession;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
JSONObject jsonResponse = null;
try {
_name = (String)params.get("name");
if (_name == null) {
throw new ConfigurationException("Unable to find name in the configuration parameters");
}
_zoneId = (String)params.get("zoneId");
if (_zoneId == null) {
throw new ConfigurationException("Unable to find zone Id in the configuration parameters");
}
_ip = (String)params.get("ip");
if (_ip == null) {
throw new ConfigurationException("Unable to find IP address in the configuration parameters");
}
_username = (String)params.get("username");
if (_username == null) {
throw new ConfigurationException("Unable to find username in the configuration parameters");
}
_password = (String)params.get("password");
if (_password == null) {
throw new ConfigurationException("Unable to find password in the configuration parameters");
}
_numRetries = NumbersUtil.parseInt((String)params.get("numretries"), 2);
_guid = (String)params.get("guid");
if (_guid == null) {
throw new ConfigurationException("Unable to find the guid in the configuration parameters");
}
_deviceName = (String)params.get("deviceName");
if (_deviceName == null) {
throw new ConfigurationException("Unable to find the device name in the configuration parameters");
}
_nccCmdTimeout = NumbersUtil.parseLong((String)params.get("numretries"), 600000);
// validate device configuration parameters
login();
return true;
} catch (ConfigurationException e) {
throw new ConfigurationException(e.getMessage());
} catch (ExecutionException e) {
s_logger.debug("Execution Exception :" + e.getMessage());
throw new ConfigurationException("Failed to add the device. Please check the device is NCC and It is reachable from Management Server.");
}
}
public void getServicePackages() throws ExecutionException {
String result = null;
try {
URI agentUri = null;
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/admin/v1/servicepackages", null, null);
org.json.JSONObject jsonBody = new JSONObject();
org.json.JSONObject jsonCredentials = new JSONObject();
result = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
s_logger.debug("List of Service Packages in NCC:: " + result);
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
} catch (Exception e) {
throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
}
}
private synchronized String login() throws ExecutionException{
String result = null;
JSONObject jsonResponse = null;
try {
URI agentUri = null;
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/nitro/v2/config/" + "login", null, null);
org.json.JSONObject jsonBody = new JSONObject();
org.json.JSONObject jsonCredentials = new JSONObject();
jsonCredentials.put("username", _username);
jsonCredentials.put("password", _password);
jsonBody.put("login", jsonCredentials);
result = postHttpRequest(jsonBody.toString(), agentUri, _sessionid);
if (result == null) {
throw new ConfigurationException("No Response Received from the NetScalerControlCenter Device");
} else {
jsonResponse = new JSONObject(result);
org.json.JSONArray loginResponse = jsonResponse.getJSONArray("login");
_sessionid = jsonResponse.getJSONArray("login").getJSONObject(0).getString("sessionid");
s_logger.debug("New Session id from NCC :" + _sessionid);
set_nccsession(_sessionid);
s_logger.debug("session on Static Session variable" + get_nccsession());
}
s_logger.debug("Login to NCC Device response :: " + result);
return result;
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
} catch (JSONException e) {
s_logger.debug("JSON Exception :" + e.getMessage());
throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
} catch (Exception e) {
throw new ExecutionException("Failed to log in to NCC device at " + _ip + " due to " + e.getMessage());
}
return result;
}
@Override
public StartupCommand[] initialize() {
StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand(Host.Type.NetScalerControlCenter);
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod("");
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion(NetScalerControlCenterResource.class.getPackage().getImplementationVersion());
cmd.setGuid(_guid);
return new StartupCommand[] {cmd};
}
@Override
public Answer executeRequest(Command cmd) {
return executeRequest(cmd, _numRetries);
}
private Answer executeRequest(Command cmd, int numRetries) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand)cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand)cmd);
} else if (cmd instanceof IpAssocCommand) {
return execute((IpAssocCommand)cmd, numRetries);
} else if (cmd instanceof LoadBalancerConfigCommand) {
return execute((LoadBalancerConfigCommand)cmd, numRetries);
} else if (cmd instanceof ExternalNetworkResourceUsageCommand) {
return execute((ExternalNetworkResourceUsageCommand)cmd, numRetries);
} else if (cmd instanceof DestroyLoadBalancerApplianceCommand) {
return Answer.createUnsupportedCommandAnswer(cmd);
} else if (cmd instanceof SetStaticNatRulesCommand) {
return execute((SetStaticNatRulesCommand)cmd, numRetries);
} else if (cmd instanceof GlobalLoadBalancerConfigCommand) {
return Answer.createUnsupportedCommandAnswer(cmd);
} else if (cmd instanceof HealthCheckLBConfigCommand) {
return execute((HealthCheckLBConfigCommand)cmd, numRetries);
} else if (cmd instanceof NetScalerImplementNetworkCommand ) {
return execute((NetScalerImplementNetworkCommand)cmd, numRetries);
}
else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
private Answer execute(ReadyCommand cmd) {
return new ReadyAnswer(cmd);
}
protected Answer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd);
}
private void keepSessionAlive() throws ExecutionException {
URI agentUri = null;
try {
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/cs/cca/v1/cloudstacks", null, null);
org.json.JSONObject jsonBody = new JSONObject();
getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
s_logger.debug("Keeping Session Alive");
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
private String queryAsyncJob(String jobId) throws ExecutionException {
String result = null;
try {
URI agentUri = null;
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/admin/v1/journalcontexts/" + jobId, null, null);
org.json.JSONObject jsonBody = new JSONObject();
long startTick = System.currentTimeMillis();
while (System.currentTimeMillis() - startTick < _nccCmdTimeout) {
result = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
JSONObject response = new JSONObject(result);
if(response != null ) {
s_logger.debug("Job Status result for ["+jobId + "]:: " + result + " Tick and currentTime :" + System.currentTimeMillis() +" -" + startTick + "job cmd timeout :" +_nccCmdTimeout);
String status = response.getJSONObject("journalcontext").getString("status").toUpperCase();
String message = response.getJSONObject("journalcontext").getString("message");
s_logger.debug("Job Status Progress Status ["+ jobId + "]:: " + status);
switch(status) {
case "FINISHED":
return status;
case "IN PROGRESS":
break;
case "ERROR, ROLLBACK IN PROGRESS":
break;
case "ERROR, ROLLBACK COMPLETED":
throw new ExecutionException("ERROR, ROLLBACK COMPLETED " + message);
case "ERROR, ROLLBACK FAILED":
throw new ExecutionException("ERROR, ROLLBACK FAILED " + message);
}
}
}
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for NetScaler ControlCenter";
s_logger.error(errMsg, e);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
private synchronized Answer execute(NetScalerImplementNetworkCommand cmd, int numRetries) {
String result = null;
try {
URI agentUri = null;
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/cs/adcaas/v1/networks", null, null);
org.json.JSONObject jsonBody = new JSONObject(cmd.getDetails());
s_logger.debug("Sending Network Implement to NCC:: " + jsonBody);
result = postHttpRequest(jsonBody.toString(), agentUri, _sessionid);
s_logger.debug("Result of Network Implement to NCC:: " + result);
result = queryAsyncJob(result);
s_logger.debug("Done query async of network implement request :: " + result);
return new Answer(cmd, true, "Successfully allocated device");
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for NetScaler ControlCenter ";
s_logger.error(errMsg, e);
} catch (ExecutionException e) {
if(e.getMessage().equalsIgnoreCase(NccHttpCode.NOT_FOUND)) {
return new Answer(cmd, true, "Successfully unallocated the device");
}else if(e.getMessage().startsWith("ERROR, ROLLBACK") ) {
s_logger.error(e.getMessage());
return new Answer(cmd, false, e.getMessage());
}
else {
if (shouldRetry(numRetries)) {
s_logger.debug("Retrying the command NetScalerImplementNetworkCommand retry count: " + numRetries, e);
return retry(cmd, numRetries);
} else {
return new Answer(cmd, false, e.getMessage());
}
}
} catch (Exception e) {
if (shouldRetry(numRetries)) {
s_logger.debug("Retrying the command NetScalerImplementNetworkCommand retry count: " + numRetries, e);
return retry(cmd, numRetries);
} else {
return new Answer(cmd, false, e.getMessage());
}
}
return Answer.createUnsupportedCommandAnswer(cmd);
}
private synchronized Answer execute(IpAssocCommand cmd, int numRetries) {
String[] results = new String[cmd.getIpAddresses().length];
int i = 0;
IpAddressTO[] ips = cmd.getIpAddresses();
for (IpAddressTO ip : ips) {
results[i++] = ip.getPublicIp() + " - success";
}
return new IpAssocAnswer(cmd, results);
}
private Answer execute(HealthCheckLBConfigCommand cmd, int numRetries) {
List<LoadBalancerTO> hcLB = new ArrayList<LoadBalancerTO>();
try {
LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
if (loadBalancers == null) {
return new HealthCheckLBConfigAnswer(hcLB);
}
String result = getLBHealthChecks(cmd.getNetworkId());
JSONObject res = new JSONObject(result);
JSONArray lbstatus = res.getJSONArray("lbhealthstatus");
for(int i=0; i<lbstatus.length(); i++) {
JSONObject lbstat = lbstatus.getJSONObject(i);
LoadBalancerTO loadBalancer = null;
JSONArray dest = lbstat.getJSONArray("destinations");
List<DestinationTO> listDestTo = new ArrayList<DestinationTO>();
for(int d=0; d<dest.length(); d++ ) {
JSONObject dt = dest.getJSONObject(d);
if( dt!=null ) {
DestinationTO destTO = new DestinationTO(dt.getString("destIp"), dt.getInt("destPort"), dt.getString("monitorState"));
listDestTo.add(destTO);
}
}
loadBalancer = new LoadBalancerTO(lbstat.getString("lb_uuid"),listDestTo);
hcLB.add(loadBalancer);
}
} catch (ExecutionException e) {
s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e);
if (shouldRetry(numRetries)) {
return retry(cmd, numRetries);
} else {
return new HealthCheckLBConfigAnswer(hcLB);
}
} catch (Exception e) {
s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e);
if (shouldRetry(numRetries)) {
return retry(cmd, numRetries);
} else {
return new HealthCheckLBConfigAnswer(hcLB);
}
}
return new HealthCheckLBConfigAnswer(hcLB);
}
private String getLBHealthChecks(long networkid) throws ExecutionException {
URI agentUri = null;
String response = null;
try {
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/cs/adcaas/v1/networks/"+ networkid +"/lbhealthstatus", null, null);
org.json.JSONObject jsonBody = new JSONObject();
response = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
s_logger.debug("LBHealthcheck Response :" + response);
} catch (URISyntaxException e) {
e.printStackTrace();
}
return response;
}
private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) {
try {
LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers();
if (loadBalancers == null) {
return new Answer(cmd);
}
JSONObject lbConfigPaylod = new JSONObject(cmd);
String gsonLBConfig = _gson.toJson(cmd);
URI agentUri = null;
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/cs/adcaas/v1/loadbalancerCmds", null, null);
JSONObject lbConfigCmd = new JSONObject();
JSONObject lbcmd = new JSONObject(gsonLBConfig);
s_logger.debug("LB config from gsonstring to JSONObject : " + lbcmd.toString() + "\n" + "gson cmd is :: \t" + gsonLBConfig);
lbConfigCmd.put("LoadBalancerConfigCommand", lbcmd.getJSONArray("loadBalancers"));
s_logger.debug("LB config paylod : " + lbConfigCmd.toString());
String result = postHttpRequest(lbConfigCmd.toString(), agentUri, _sessionid);
s_logger.debug("Result of lbconfigcmg is "+ result);
result = queryAsyncJob(result);
s_logger.debug("Done query async of LB ConfigCmd implement request and result:: " + result);
return new Answer(cmd);
} catch (ExecutionException e) {
s_logger.error("Failed to execute LoadBalancerConfigCommand due to ", e);
if(e.getMessage().equalsIgnoreCase(NccHttpCode.NOT_FOUND)) {
return new Answer(cmd, true, "LB Rule is not present in NS device. So returning as removed the LB Rule");
} else if(e.getMessage().startsWith("ERROR, ROLLBACK COMPLETED") || e.getMessage().startsWith("ERROR, ROLLBACK FAILED")) {
s_logger.error("Failed to execute LoadBalancerConfigCommand due to : " + e.getMessage());
return new Answer(cmd, false, e.getMessage());
} else if (e.getMessage().startsWith(NccHttpCode.INTERNAL_ERROR)) {
s_logger.error("Failed to execute LoadBalancerConfigCommand as Internal Error returning Internal error ::" + e.getMessage() );
return new Answer(cmd, false, e.getMessage());
}
if (shouldRetry(numRetries)) {
return retry(cmd, numRetries);
} else {
return new Answer(cmd, false, e.getMessage());
}
} catch (Exception e) {
s_logger.error("Failed to execute LoadBalancerConfigCommand due to ", e);
if (shouldRetry(numRetries)) {
return retry(cmd, numRetries);
} else {
return new Answer(cmd, false, e.getMessage());
}
}
}
private synchronized Answer execute(SetStaticNatRulesCommand cmd, int numRetries) {
return Answer.createUnsupportedCommandAnswer(cmd);
}
private synchronized Answer execute(ExternalNetworkResourceUsageCommand cmd, int numRetries) {
try {
return getPublicIpBytesSentAndReceived(cmd);
} catch (ExecutionException e) {
if (shouldRetry(numRetries)) {
return retry(cmd, numRetries);
} else {
return new ExternalNetworkResourceUsageAnswer(cmd, e);
}
}
}
private String getNetScalerProtocol(LoadBalancerTO loadBalancer) throws ExecutionException {
String port = Integer.toString(loadBalancer.getSrcPort());
String lbProtocol = loadBalancer.getLbProtocol();
StickinessPolicyTO[] stickyPolicies = loadBalancer.getStickinessPolicies();
String nsProtocol = "TCP";
if (lbProtocol == null)
lbProtocol = loadBalancer.getProtocol();
if ((stickyPolicies != null) && (stickyPolicies.length > 0) && (stickyPolicies[0] != null)) {
StickinessPolicyTO stickinessPolicy = stickyPolicies[0];
if (StickinessMethodType.LBCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()) ||
(StickinessMethodType.AppCookieBased.getName().equalsIgnoreCase(stickinessPolicy.getMethodName()))) {
nsProtocol = "HTTP";
return nsProtocol;
}
}
if (lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO) || lbProtocol.equalsIgnoreCase(NetUtils.HTTP_PROTO))
return lbProtocol.toUpperCase();
if (port.equals(NetUtils.HTTP_PORT)) {
nsProtocol = "HTTP";
} else if (NetUtils.TCP_PROTO.equalsIgnoreCase(lbProtocol)) {
nsProtocol = "TCP";
} else if (NetUtils.UDP_PROTO.equalsIgnoreCase(lbProtocol)) {
nsProtocol = "UDP";
}
return nsProtocol;
}
private ExternalNetworkResourceUsageAnswer getPublicIpBytesSentAndReceived(ExternalNetworkResourceUsageCommand cmd) throws ExecutionException {
ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd);
long networkid = cmd.getNetworkid();
try {
//TODO send GET cmd to get the network stats
URI agentUri = null;
String response = null;
try {
agentUri =
new URI("https", null, _ip, DEFAULT_PORT,
"/cs/adcaas/v1/networks/"+ networkid +"/ipStats", null, null);
org.json.JSONObject jsonBody = new JSONObject();
response = getHttpRequest(jsonBody.toString(), agentUri, _sessionid);
JSONArray statsIPList = null;
if(response !=null ) {
statsIPList = new JSONObject(response).getJSONObject("stats") .getJSONArray("ipBytes");
}
if(statsIPList != null) {
for(int i=0; i<statsIPList.length(); i++) {
JSONObject ipstat = statsIPList.getJSONObject(i);
JSONObject ipvalues = ipstat.getJSONObject("ipstats");
if(ipstat != null) {
long[] bytesSentAndReceived = new long[] {0, 0};
bytesSentAndReceived[0] = ipvalues.getLong("received");
bytesSentAndReceived[1] = ipvalues.getLong("sent");
if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) {
answer.ipBytes.put(ipstat.getString("ip"), bytesSentAndReceived);
}
}
}
}
s_logger.debug("IPStats Response :" + response);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ExecutionException e) {
s_logger.debug("Seesion Alive" + e.getMessage());
e.printStackTrace();
}
} catch (Exception e) {
s_logger.error("Failed to get bytes sent and recived statistics due to " + e);
throw new ExecutionException(e.getMessage());
}
return answer;
}
private Answer retry(Command cmd, int numRetries) {
int numRetriesRemaining = numRetries - 1;
s_logger.warn("Retrying " + cmd.getClass().getSimpleName() + ". Number of retries remaining: " + numRetriesRemaining);
return executeRequest(cmd, numRetriesRemaining);
}
private boolean shouldRetry(int numRetries) {
try {
if (numRetries > 0) {
login();
return true;
}
} catch (Exception e) {
s_logger.error("Failed to log in to Netscaler ControlCenter device at " + _ip + " due to " + e.getMessage());
return false;
}
return false;
}
@Override
public IAgentControl getAgentControl() {
return null;
}
private boolean refreshNCCConnection() {
boolean ret = false;
try {
keepSessionAlive();
return true;
} catch (ExecutionException ex) {
s_logger.debug("Failed to keep up the session alive ", ex);
}
return ret;
}
@Override
public PingCommand getCurrentStatus(long id) {
pingCount++;
if (pingCount > 10 && refreshNCCConnection()) {
pingCount = 0;
}
return new PingCommand(Host.Type.NetScalerControlCenter, id);
}
@Override
public Type getType() {
return Host.Type.NetScalerControlCenter ;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
return;
}
@Override
public String getName() {
return _name;
}
@Override
public void setName(String name) {
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public void disconnected() {
return;
}
@Override
public void setConfigParams(Map<String, Object> params) {
}
@Override
public Map<String, Object> getConfigParams() {
return null;
}
@Override
public int getRunLevel() {
return 0;
}
@Override
public void setRunLevel(int level) {
}
public String getSessionID() {
return _sessionid;
}
public static String cleanPassword(String logString) {
String cleanLogString = null;
if (logString != null) {
cleanLogString = logString;
String[] temp = logString.split(",");
int i = 0;
if (temp != null) {
while (i < temp.length) {
temp[i] = StringUtils.cleanString(temp[i]);
i++;
}
List<String> stringList = new ArrayList<String>();
Collections.addAll(stringList, temp);
cleanLogString = StringUtils.join(stringList, ",");
}
}
return cleanLogString;
}
public static HttpClient getHttpClient() {
HttpClient httpClient = null;
TrustStrategy easyStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
};
try {
SSLSocketFactory sf = new SSLSocketFactory(easyStrategy, new AllowAllHostnameVerifier());
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", DEFAULT_PORT, sf));
ClientConnectionManager ccm = new BasicClientConnectionManager(registry);
httpClient = new DefaultHttpClient(ccm);
} catch (KeyManagementException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (UnrecoverableKeyException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (KeyStoreException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
}
return httpClient;
}
public static String getHttpRequest(final String jsonCmd, final URI agentUri, String sessionID) throws ExecutionException {
// Using Apache's HttpClient for HTTP POST
// Java-only approach discussed at on StackOverflow concludes with
// comment to use Apache HttpClient
// http://stackoverflow.com/a/2793153/939250, but final comment is to
// use Apache.
String logMessage = StringEscapeUtils.unescapeJava(jsonCmd);
logMessage = cleanPassword(logMessage);
s_logger.debug("GET request to " + agentUri.toString()
+ " with contents " + logMessage);
// Create request
HttpClient httpClient = getHttpClient();
String result = null;
// TODO: are there timeout settings and worker thread settings to tweak?
try {
HttpGet request = new HttpGet(agentUri);
// JSON encode command
// Assumes command sits comfortably in a string, i.e. not used for
// large data transfers
StringEntity cmdJson = new StringEntity(jsonCmd);
request.addHeader("content-type", "application/json");
request.addHeader("Cookie", "SessId=" + sessionID);
s_logger.debug("Sending cmd to " + agentUri.toString()
+ " cmd data:" + logMessage);
HttpResponse response = httpClient.execute(request);
// Unsupported commands will not route.
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
String errMsg = "Failed to send : HTTP error code : " + response.getStatusLine().getStatusCode();
s_logger.error(errMsg);
String unsupportMsg = "Unsupported command " + agentUri.getPath() + ". Are you sure you got the right f of" + " server?";
Answer ans = new UnsupportedAnswer(null, unsupportMsg);
s_logger.error(ans);
result = s_gson.toJson(new Answer[] {ans});
} else if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
String errMsg = "Failed send to " + agentUri.toString() + " : HTTP error code : " + response.getStatusLine().getStatusCode();
s_logger.error(errMsg);
throw new ExecutionException("UNAUTHORIZED");
} else {
result = EntityUtils.toString(response.getEntity());
String logResult = cleanPassword(StringEscapeUtils.unescapeJava(result));
s_logger.debug("Get response is " + logResult);
}
} catch (ClientProtocolException protocolEx) {
// Problem with HTTP message exchange
s_logger.error(protocolEx);
} catch (IOException connEx) {
// Problem with underlying communications
s_logger.error(connEx);
} finally {
httpClient.getConnectionManager().shutdown();
}
return result;
}
public static String postHttpRequest(final String jsonCmd, final URI agentUri, String sessionID) throws ExecutionException {
// Using Apache's HttpClient for HTTP POST
// Java-only approach discussed at on StackOverflow concludes with
// comment to use Apache HttpClient
// http://stackoverflow.com/a/2793153/939250, but final comment is to
// use Apache.
String logMessage = StringEscapeUtils.unescapeJava(jsonCmd);
logMessage = cleanPassword(logMessage);
s_logger.debug("POST request to " + agentUri.toString()
+ " with contents " + logMessage);
// Create request
HttpClient httpClient = getHttpClient();
TrustStrategy easyStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
};
try {
SSLSocketFactory sf = new SSLSocketFactory(easyStrategy, new AllowAllHostnameVerifier());
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("https", DEFAULT_PORT, sf));
ClientConnectionManager ccm = new BasicClientConnectionManager(registry);
httpClient = new DefaultHttpClient(ccm);
} catch (KeyManagementException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (UnrecoverableKeyException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
} catch (KeyStoreException e) {
s_logger.error("failed to initialize http client " + e.getMessage());
}
String result = null;
// TODO: are there timeout settings and worker thread settings to tweak?
try {
HttpPost request = new HttpPost(agentUri);
// JSON encode command
// Assumes command sits comfortably in a string, i.e. not used for
// large data transfers
StringEntity cmdJson = new StringEntity(jsonCmd);
request.addHeader("content-type", "application/json");
request.addHeader("Cookie", "SessId=" + sessionID);
request.setEntity(cmdJson);
s_logger.debug("Sending cmd to " + agentUri.toString()
+ " cmd data:" + logMessage + "SEssion id: " + sessionID);
HttpResponse response = httpClient.execute(request);
// Unsupported commands will not route.
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND) {
String errMsg = "Failed : HTTP error code : " + response.getStatusLine().getStatusCode();
throw new ExecutionException(NccHttpCode.NOT_FOUND);
} else if ((response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) && (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED )) {
String errMsg = "Command Not Success " + agentUri.toString() + " : HTTP error code : " + response.getStatusLine().getStatusCode();
s_logger.error(errMsg);
throw new ExecutionException(NccHttpCode.INTERNAL_ERROR + " " + errMsg);
} else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
//Successfully created the resource in the NCC, Now get the Job ID and send to the response
// make login request and store new session id
throw new ExecutionException(NccHttpCode.UNAUTHORIZED);
} else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CREATED) {
//Successfully created the resource in the NCC, Now get the Job ID and send to the response
result = response.getFirstHeader(NccHttpCode.JOB_ID).getValue();
} else {
result = EntityUtils.toString(response.getEntity());
String logResult = cleanPassword(StringEscapeUtils.unescapeJava(result));
s_logger.debug("POST response is " + logResult);
}
} catch (ClientProtocolException protocolEx) {
// Problem with HTTP message exchange
s_logger.error(protocolEx);
} catch (IOException connEx) {
// Problem with underlying communications
s_logger.error(connEx);
} finally {
httpClient.getConnectionManager().shutdown();
}
return result;
}
}