/*******************************************************************************
* Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
*
* Licensed 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 org.cloudifysource.shell.validators;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.StringUtils;
import org.cloudifysource.dsl.internal.CloudifyConstants;
import org.cloudifysource.dsl.internal.CloudifyErrorMessages;
import org.cloudifysource.dsl.utils.IOUtils;
import org.cloudifysource.dsl.utils.IPUtils;
import org.cloudifysource.shell.exceptions.CLIValidationException;
/**
* This class validates a connection to the lookup service can be established on the specified port.
* @author noak
* @since 2.7.0
*/
public class LusConnectionValidator implements CloudifyAgentValidator {
private static final long TEN_SECONDS_MILLI = 10000;
private final Logger logger = Logger.getLogger(this.getClass().getName());
private static final int MAX_NUM_RETRIES = 3;
private String lusIpAddresses;
// TODO noa run only on agent
// use lookup locators
/**
* Setter for lusIpAddress.
* @param lusIpAddress The LUS IP address to validate, or null to use the env var setting.
*/
public void setLusIpAddress(final String lusIpAddresses) {
this.lusIpAddresses = lusIpAddresses;
}
/**
* Validates a connection can be established to the lookup service on the specified port.
* @throws CLIValidationException Indicates a failure to establish a connection.
*/
@Override
public void validate() throws CLIValidationException {
// get lus IP address from the environment variable if not already set
if (StringUtils.isBlank(lusIpAddresses)) {
lusIpAddresses = System.getenv(CloudifyConstants.LUS_IP_ADDRESS_ENV);
}
String[] lusAddresses = lusIpAddresses.split(",");
Exception ex = new Exception();
for (String address : lusAddresses) {
try {
validateManagementAddress(address);
return;
} catch (final CLIValidationException e) {
ex = e;
}
}
throw (CLIValidationException) ex;
}
void validateManagementAddress(final String address)
throws CLIValidationException {
// TODO noak : throw CLIValidationException with custom exit code (130) instead?
if (StringUtils.isBlank(address)) {
throw new IllegalArgumentException("LUS IP address not configred. The environment variable \""
+ CloudifyConstants.LUS_IP_ADDRESS_ENV + "\" is not set.");
}
//parse the ip address and port
final String hostAddress = IPUtils.getHostFromFullAddress(address);
final int port = IPUtils.getPortFromFullAddress(address);
for (int i = 0; i < MAX_NUM_RETRIES; i++) {
try {
validateConnection(hostAddress, port);
return;
} catch (CLIValidationException e) {
if (i == 2) {
throw e;
}
logger.log(Level.WARNING, "Failed validating connection to lus. "
+ "Error was: " + e.getMessage()
+ "Attempting to reconnect.", e);
}
IOUtils.threadSleep(TEN_SECONDS_MILLI);
}
}
void validateConnection(final String hostAddress, final int port)
throws CLIValidationException {
try {
IPUtils.validateConnection(hostAddress, port);
return;
} catch (UnknownHostException uhe) {
// thrown if the IP address of the host could not be determined.
throw new CLIValidationException(uhe, 127,
CloudifyErrorMessages.LUS_CONNECTION_VALIDATION_ABORTED_UNKNOWN_HOST.getName(), hostAddress);
} catch (IOException ioe) {
// thrown if an I/O error occurs when creating the socket or connecting.
throw new CLIValidationException(ioe, 128,
CloudifyErrorMessages.LUS_CONNECTION_VALIDATION_ABORTED_IO_ERROR.getName(), hostAddress, port,
ioe.getMessage());
} catch (SecurityException se) {
// thrown if a security manager exists and permission to resolve the host name is denied.
throw new CLIValidationException(se, 129,
CloudifyErrorMessages.LUS_CONNECTION_VALIDATION_ABORTED_NO_PERMISSION.getName(), hostAddress,
port, se.getMessage());
}
}
}