/**
* Abiquo community edition
* cloud management application for hybrid clouds
* Copyright (C) 2008-2010 - Abiquo Holdings S.L.
*
* This application is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC
* LICENSE as published by the Free Software Foundation under
* version 3 of the License
*
* This software 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
* LESSER GENERAL PUBLIC LICENSE v.3 for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package com.abiquo.vsm;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.abiquo.commons.amqp.util.RabbitMQUtils;
import com.abiquo.vsm.model.PhysicalMachine;
import com.abiquo.vsm.redis.dao.RedisDao;
import com.abiquo.vsm.redis.dao.RedisDaoFactory;
import com.abiquo.vsm.redis.pubsub.RedisSubscriber;
import com.abiquo.vsm.redis.util.RedisUtils;
/**
* Handles the VSM initialization and destruction.
*
* @author eruiz@abiquo.com
*/
public class VSMManager
{
private final static Logger logger = LoggerFactory.getLogger(VSMManager.class);
private enum InitializationSteps
{
Uninitialized, CheckRabbitMQRunning, StartSubscriber, ReloadMonitors, Initialized;
public InitializationSteps next()
{
return ordinal() < (values().length - 1) ? values()[ordinal() + 1] : this;
}
public boolean isInitialized()
{
return this.equals(Initialized);
}
}
private final String redisHost;
private final int redisPort;
private InitializationSteps current;
private RedisSubscriber subscriber;
private static VSMManager instance = null;
private ExecutorService subscriberExecutor;
private VSMManager()
{
current = InitializationSteps.Uninitialized;
redisHost = getProperty("abiquo.redis.host", "localhost");
redisPort = Integer.valueOf(getProperty("abiquo.redis.port", "6379"));
subscriberExecutor = Executors.newSingleThreadExecutor();
}
public static VSMManager getInstance()
{
if (instance == null)
{
instance = new VSMManager();
}
return instance;
}
private String getProperty(String name, String defaultValue)
{
String value = System.getProperty(name);
return value == null ? defaultValue : value;
}
/**
* Initializes all the modules. If one is not well initialized, VSM will not handle requests.
*/
public void initialize()
{
InitializationSteps nextStep = current.next();
boolean success = true;
while (!current.isInitialized() && success)
{
switch (nextStep)
{
case CheckRabbitMQRunning:
success = isRabbitMQRunning();
break;
case StartSubscriber:
success = startSubscriber();
break;
case ReloadMonitors:
reloadMonitors();
success = true;
break;
default:
success = true;
break;
}
if (success)
{
current = nextStep;
nextStep = current.next();
}
}
}
public boolean isRabbitMQRunning()
{
try
{
return RabbitMQUtils.pingRabbitMQ();
}
catch (Exception e)
{
return false;
}
}
public boolean isRedisRunning()
{
return RedisUtils.ping(redisHost, redisPort);
}
private boolean startSubscriber()
{
logger.info("Starting redis subscriber.");
boolean ping = isRedisRunning();
if (ping)
{
subscriber = new RedisSubscriber(redisHost, redisPort);
subscriberExecutor.execute(subscriber);
}
else
{
logger.error("Redis is not listening at {}:{}. VSM is not properly initialized.",
redisHost, redisPort);
}
return ping;
}
/**
* Checks if all the modules are correctly initialized and working.
*
* @return True if all is OK. Otherwise false.
*/
public boolean checkSystem()
{
boolean initialized = true;
if (!current.isInitialized())
{
// Continue initialization from last step
initialize();
initialized = current.isInitialized();
}
if (current == InitializationSteps.Initialized)
{
// RabbitMQ could be down
if (!isRabbitMQRunning())
{
logger.error("VSM can not ping RabbitMQ check if RabbitMQ is up and restart VSM.");
initialized = false;
}
// Redis could be down
if (!isRedisRunning())
{
logger.error("Redis is not listening at {}:{}. VSM is not properly initialized.",
redisHost, redisPort);
initialized = false;
}
// Redis subscriber could be down
if (!subscriber.isRunning() && initialized)
{
// Try to re-start
logger.error("The subscriber is not running. Trying to restart.");
initialized = startSubscriber();
}
}
if (!initialized)
{
logger.error("VSM is NOT running properly. Check redis and rabbitmq status.");
}
return initialized;
}
/**
* Stops the subscriber thread and waits for the correct thread unload.
*/
public void destroy()
{
subscriberExecutor.shutdown();
VSMService.getInstance().stopAllMonitors();
}
/**
* Starts the monitoring of all redis stored physical machines.
*/
protected void reloadMonitors()
{
RedisDao dao = RedisDaoFactory.getInstance();
VSMService.getInstance().stopAllMonitors();
for (PhysicalMachine machine : dao.findAllPhysicalMachines())
{
String address = machine.getAddress();
String type = machine.getType();
String username = machine.getUsername();
String password = machine.getPassword();
try
{
VSMService.getInstance().createAndStartMonitor(address, type, username, password);
}
catch (Exception e)
{
logger.error("Could not start monitoring the machine at address" + address);
}
}
}
public String getRedisHost()
{
return redisHost;
}
public int getRedisPort()
{
return redisPort;
}
}