/*************************************************************************
* Copyright 2009-2016 Eucalyptus Systems, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
* Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta
* CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need
* additional information or have any questions.
************************************************************************/
package com.eucalyptus.loadbalancing.workflow;
import java.util.List;
import org.apache.log4j.Logger;
import com.google.common.base.Supplier;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
/**
* @author Sang-Min Park (sangmin.park@hpe.com)
*
*/
public class LoadBalancingVmActivitiesImpl
implements LoadBalancingVmActivities {
private static Logger LOG =
Logger.getLogger( LoadBalancingVmActivitiesImpl.class );
static class NoSubscriberException extends Exception { }
private static RedisPubSubClient setPolicyClient =
new RedisPubSubClient("localhost", "set-policy");
private static RedisPubSubClient setLoadBalancerClient =
new RedisPubSubClient("localhost", "set-loadbalancer");
private static RedisPubSubClient getInstanceStatusClient =
new RedisPubSubClient("localhost", "get-instance-status");
private static RedisBlockingListClient getInstanceStatusReplyClient =
new RedisBlockingListClient("localhost", "get-instance-status-reply");
private static RedisPubSubClient getCloudwatchMetricsClient =
new RedisPubSubClient("localhost", "get-cloudwatch-metrics");
private static RedisBlockingListClient getCloudwatchMetricsReplyClient =
new RedisBlockingListClient("localhost", "get-cloudwatch-metrics-reply");
static class RedisClient {
private String server = null;
private Jedis jedis = null;
public RedisClient(final String server) {
this.server = server;
}
protected Jedis connect() {
if (jedis == null) {
jedis = new Jedis(this.server);
}
return jedis;
}
protected void close() {
if (jedis != null) {
jedis.quit();
jedis = null;
}
}
}
static class RedisPubSubClient extends RedisClient {
public RedisPubSubClient(String server) {
super(server);
}
public RedisPubSubClient(String server, String channel) {
super(server);
this.channel = channel;
}
private String channel = "euca-vmservice";
public void publish(Supplier<String> message) throws NoSubscriberException {
try {
final Jedis server = this.connect();
if( server.publish(channel, message.get()) <= 0 )
throw new NoSubscriberException();
}finally{
this.close();
}
}
public void subscribe(JedisPubSub callback) {
final Jedis server = this.connect();
server.subscribe(callback, this.channel);
this.close();
}
}
static class RedisBlockingListClient extends RedisClient {
public RedisBlockingListClient(String server) {
super(server);
}
private String defaultKey = null;
public RedisBlockingListClient(String server, String key) {
super(server);
this.defaultKey = key;
}
public String pop() {
return this.pop(defaultKey);
}
public String pop(final String key) {
return this.pop(key, 0);
}
public String pop(final String key, final int timeout) {
try{
final Jedis server = this.connect();
final List<String> results = server.blpop(timeout, key);
String result = null;
if (results != null && !results.isEmpty())
result = results.get(1);
return result;
}finally {
this.close();
}
}
}
@Override
public void setPolicy(final String policy) throws LoadBalancingActivityException {
try {
setPolicyClient.publish(new Supplier<String>() {
@Override
public String get() {
return policy;
}
});
} catch(final NoSubscriberException ex) {
throw new LoadBalancingActivityException("No subscriber is found to receive the policy");
}
}
@Override
public void setLoadBalancer(final String loadbalancer) throws LoadBalancingActivityException{
// serialize loadbalancer
try{
setLoadBalancerClient.publish(new Supplier<String>() {
@Override
public String get() {
return loadbalancer;
}
});
LOG.debug(String.format("New loadbalancer: %n%s", loadbalancer));
}catch(final NoSubscriberException ex) {
throw new LoadBalancingActivityException("No subscriber is found to receive the loadbalanacer");
}
}
@Override
public String getCloudWatchMetrics() throws LoadBalancingActivityException {
try{
getCloudwatchMetricsClient.publish(new Supplier<String> () {
@Override
public String get() {
return "GetCloudWatchMetrics";
}
});
}catch(final NoSubscriberException ex) {
throw new LoadBalancingActivityException("No subscriber is found to send the cloudwatch metrics");
}
String output = null;
try{
output = getCloudwatchMetricsReplyClient.pop();
}catch(final Exception ex) {
throw new LoadBalancingActivityException("Failed to receive cloudwatch metrics");
}
LOG.debug(String.format("get-cloudwatch-metric result: %n%s", output));
return output;
}
@Override
public String getInstanceStatus() throws LoadBalancingActivityException {
try{
getInstanceStatusClient.publish(new Supplier<String>() {
@Override
public String get() {
return "GetInstanceStatus";
}
});
}catch(final NoSubscriberException ex) {
throw new LoadBalancingActivityException("No subscriber is found to send the instance status");
}
String output = null;
try{
output = getInstanceStatusReplyClient.pop();
}catch(final Exception ex) {
throw new LoadBalancingActivityException("Failed to receive instance status");
}
LOG.debug(String.format("get-instance-status result: %n%s", output));
return output;
}
}