/*******************************************************************************
* Copyright (c) 2011 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.usm.liveness;
import java.util.List;
import java.util.Map;
import org.cloudifysource.domain.context.ServiceContext;
import org.cloudifysource.dsl.utils.ServiceUtils;
import org.cloudifysource.usm.Plugin;
import org.cloudifysource.usm.UniversalServiceManagerBean;
import org.cloudifysource.usm.events.AbstractUSMEventListener;
import org.cloudifysource.usm.events.EventResult;
import org.cloudifysource.usm.events.PreStartListener;
import org.cloudifysource.usm.events.StartReason;
/**
* PortLivenessDetector class is responsible for verifying that the process has finished loading by checking whether the
* ports opened by the process are indeed open. the application ports to check are defined in the configuration file.
*
* There are 2 ways of using the PortLiveness. 1. The first is by adding a plugin to the DSL in the following manner:
* plugins ([ plugin { name "portLiveness" className "org.cloudifysource.usm.liveness.PortLivenessDetector" config ([
* "Port" : [39000,38999,38998], "TimeoutInSeconds" : 30, "Host" : "127.0.0.1" ]) },
*
* plugin{...
*
* 2. By adding the following closures to the Service Groovy file in the following manner:
*
* * Add the following command to the preStart Closure(Not a mandatory check):
* ServiceUtils.arePortsFree([23894,34,3243], "127.0.0.1") //to see that the ports are available before process starts.
*
* * Add the following closure to the lifecycle closure: startDetection
* {ServiceUtils.waitForPortToOpen([23894,34,3243],"127.0.0.1", 60)} //to see that the process has started and is using
* these ports.
*
* @author adaml
*
*/
public class PortLivenessDetector extends AbstractUSMEventListener implements LivenessDetector, Plugin,
PreStartListener {
private static final java.util.logging.Logger logger = java.util.logging.Logger
.getLogger(PortLivenessDetector.class.getName());
private static final String PORT_KEY = "Port";
// Injected values
private List<Integer> portList;
@SuppressWarnings("unchecked")
@Override
public void setConfig(final Map<String, Object> config) {
this.portList = (List<Integer>) config.get(PORT_KEY);
if (this.portList == null) {
throw new IllegalArgumentException("Parameter portList of Plugin " + this.getClass().getName()
+ " is mandatory");
}
}
/**
* Checks if a set of ports is open (i.e. you can connect to them).
*
* @return true if all ports in the list are open, false if any one of them is not.
*/
@Override
public boolean isProcessAlive() {
logger.info("Testing if the following ports are open: " + this.portList.toString());
return ServiceUtils.arePortsOccupied(this.portList);
}
@Override
public void init(final UniversalServiceManagerBean usm) {
}
@Override
public int getOrder() {
return 5;
}
/**
* Verifies that the ports are not in use before the service starts.
*
* @param reason
* the start reason.
* @return the event result.
*/
@Override
public EventResult onPreStart(final StartReason reason) {
for (final Integer port : this.portList) {
if (ServiceUtils.isPortOccupied(port)) {
throw new IllegalStateException("The Port Liveness Detector found that port " + port
+ " is IN USE before the process was launched!");
}
}
return EventResult.SUCCESS;
}
@Override
public void setServiceContext(final ServiceContext context) {
// ignore
}
}