/**
* Copyright (C) 2010-2013 Eugen Feller, INRIA <eugen.feller@inria.fr>
*
* This file is part of Snooze, a scalable, autonomic, and
* energy-aware virtual machine (VM) management framework.
*
* 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, either version 2
* of the License, or (at your option) any later version.
*
* 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>.
*/
package org.inria.myriads.snoozenode.groupmanager.init;
import java.io.IOException;
import org.inria.myriads.snoozecommon.communication.NetworkAddress;
import org.inria.myriads.snoozecommon.communication.groupmanager.GroupManagerDescription;
import org.inria.myriads.snoozecommon.communication.groupmanager.ListenSettings;
import org.inria.myriads.snoozecommon.communication.rest.CommunicatorFactory;
import org.inria.myriads.snoozecommon.communication.rest.api.GroupManagerAPI;
import org.inria.myriads.snoozecommon.guard.Guard;
import org.inria.myriads.snoozenode.configurator.api.NodeConfiguration;
import org.inria.myriads.snoozenode.configurator.database.DatabaseSettings;
import org.inria.myriads.snoozenode.configurator.scheduler.ReconfigurationSettings;
import org.inria.myriads.snoozenode.database.DatabaseFactory;
import org.inria.myriads.snoozenode.database.api.GroupManagerRepository;
import org.inria.myriads.snoozenode.groupmanager.energysaver.EnergySaverFactory;
import org.inria.myriads.snoozenode.groupmanager.energysaver.saver.EnergySaver;
import org.inria.myriads.snoozenode.groupmanager.estimator.ResourceDemandEstimator;
import org.inria.myriads.snoozenode.groupmanager.monitoring.MonitoringFactory;
import org.inria.myriads.snoozenode.groupmanager.monitoring.service.GroupManagerMonitoringService;
import org.inria.myriads.snoozenode.groupmanager.monitoring.service.LocalControllerMonitoringService;
import org.inria.myriads.snoozenode.groupmanager.reconfiguration.ReconfigurationScheduler;
import org.inria.myriads.snoozenode.groupmanager.statemachine.api.StateMachine;
import org.inria.myriads.snoozenode.groupmanager.statemachine.api.impl.GroupManagerStateMachine;
import org.inria.myriads.snoozenode.heartbeat.HeartbeatFactory;
import org.inria.myriads.snoozenode.heartbeat.message.HeartbeatMessage;
import org.inria.myriads.snoozenode.heartbeat.sender.HeartbeatMulticastSender;
import org.inria.myriads.snoozenode.util.ManagementUtils;
import org.inria.snoozenode.external.notifier.ExternalNotifier;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Group manager initialization.
*
* @author Eugen Feller
*/
public final class GroupManagerInit
{
/** Define the logger. */
private static final Logger log_ = LoggerFactory.getLogger(GroupManagerInit.class);
/** Holds the node params reference. */
private NodeConfiguration nodeConfiguration_;
/** Group mananager repository. */
private GroupManagerRepository repository_;
/** Energy saver. */
private EnergySaver energySaver_;
/** Heartbeat multicast sender. */
private HeartbeatMulticastSender heartbeatSender_;
/** Local controller monitoring service. */
private LocalControllerMonitoringService localControllerMonitoring_;
/** Monitoring service. */
private GroupManagerMonitoringService monitoringService_;
/** Control loop scheduler. */
private ReconfigurationScheduler reconfigurationScheduler_;
/** Group manager description. */
private GroupManagerDescription description_;
/** Resource demand measure. */
private ResourceDemandEstimator estimator_;
/** State machine. */
private StateMachine stateMachine_;
/** External Notifier. */
private ExternalNotifier externalNotifier_;
/**
* Group manager logic constructor.
*
* @param nodeConfiguration The node configuration
* @param groupManagerDescription The group manager description
* @param externalNotifier The external notifier
* @throws Exception The exception
*/
public GroupManagerInit(NodeConfiguration nodeConfiguration,
GroupManagerDescription groupManagerDescription,
ExternalNotifier externalNotifier
)
throws Exception
{
Guard.check(nodeConfiguration, groupManagerDescription);
log_.debug("Initializing the group manager logic");
nodeConfiguration_ = nodeConfiguration;
description_ = groupManagerDescription;
externalNotifier_ = externalNotifier;
initializeRepository();
initializeResourceDemandEstimator();
initializeStateMachine();
checkAndEnableFeatures();
startLocalControllerMonitoringService();
startHeartbeatSender();
}
/**
* Stops the group manager services.
*
* @throws IOException Exception
* @throws SchedulerException Exception
*/
public void stopServices()
throws SchedulerException, IOException
{
log_.debug("Stopping the group manager logic");
if (repository_ != null)
{
repository_.clean();
}
if (energySaver_ != null)
{
energySaver_.terminate();
}
if (heartbeatSender_ != null)
{
heartbeatSender_.terminate();
}
if (localControllerMonitoring_ != null)
{
localControllerMonitoring_.terminate();
}
if (monitoringService_ != null)
{
monitoringService_.terminate();
}
if (reconfigurationScheduler_ != null)
{
reconfigurationScheduler_.shutdown();
}
}
/**
* Initializes the repository.
*/
private void initializeRepository()
{
int maxCapacity = nodeConfiguration_.getDatabase().getNumberOfEntriesPerVirtualMachine();
DatabaseSettings settings = nodeConfiguration_.getDatabase();
int interval = nodeConfiguration_.getMonitoring().getInterval();
repository_ = DatabaseFactory.newGroupManagerRepository(
new GroupManagerDescription(description_, 0),
maxCapacity,
interval,
settings,
nodeConfiguration_.getExternalNotifier(),
externalNotifier_
);
}
/**
* Initializes the resource demand estimator.
*/
private void initializeResourceDemandEstimator()
{
estimator_ = new ResourceDemandEstimator(nodeConfiguration_.getEstimator(),
nodeConfiguration_.getMonitoring().getThresholds(),
nodeConfiguration_.getSubmission().getPackingDensity());
}
/**
* Initializes the state machine.
*/
private void initializeStateMachine()
{
stateMachine_ = new GroupManagerStateMachine(nodeConfiguration_, estimator_, repository_, externalNotifier_);
}
/**
* Starts the local controller monitoring service.
*
* @throws Exception
*/
private void startLocalControllerMonitoringService()
throws Exception
{
localControllerMonitoring_ = new LocalControllerMonitoringService(nodeConfiguration_,
stateMachine_,
repository_);
localControllerMonitoring_.startMonitoring();
}
/**
* Enable possible features.
*
* @throws Exception The exception
*/
private void checkAndEnableFeatures()
throws Exception
{
ReconfigurationSettings reconfigurationSettings =
nodeConfiguration_.getGroupManagerScheduler().getReconfigurationSettings();
if (reconfigurationSettings.isEnabled())
{
log_.debug("Starting the reconfiguration loop");
String interval = reconfigurationSettings.getInterval();
reconfigurationScheduler_ = new ReconfigurationScheduler(stateMachine_, interval);
reconfigurationScheduler_.run();
}
if (nodeConfiguration_.getEnergyManagement().isEnabled())
{
log_.debug("Starting the energy saver");
energySaver_ = EnergySaverFactory.newEnergySaver(nodeConfiguration_.getEnergyManagement(),
repository_,
stateMachine_);
new Thread(energySaver_, "EnergySaver").start();
}
}
/**
* Multicast group manager presence.
* @throws IOException
*/
private void startHeartbeatSender()
throws IOException
{
log_.debug("Starting the group manager heartbeat sender");
NetworkAddress heartbeatAddress = nodeConfiguration_.getNetworking()
.getMulticast()
.getGroupManagerHeartbeatAddress();
int heartbeatInterval = nodeConfiguration_.getFaultTolerance().getHeartbeat().getInterval();
ListenSettings listenSettings = nodeConfiguration_.getNetworking().getListen();
HeartbeatMessage heartbeatMessage = ManagementUtils.createHeartbeatMessage(listenSettings,
description_.getId());
heartbeatSender_ = HeartbeatFactory.newHeartbeatMulticastSender(heartbeatAddress,
heartbeatInterval,
heartbeatMessage);
new Thread(heartbeatSender_, "HeartBeatSender").start();
}
/**
* Starts the data sender.
*
* @param groupLeader The group leader description
* @throws Exception The exception
*/
private void startGroupManagerMonitoringService(GroupManagerDescription groupLeader)
throws Exception
{
Guard.check(groupLeader);
if (monitoringService_ == null)
{
monitoringService_ = MonitoringFactory.newGroupManagerMonitoringService(
description_.getId(),
repository_,
estimator_,
nodeConfiguration_.getDatabase(),
nodeConfiguration_.getMonitoring(),
nodeConfiguration_.getExternalNotifier()
);
}
monitoringService_.startServices(groupLeader.getListenSettings().getMonitoringDataAddress());
}
/**
* Returns the energy saver reference.
*
* @return The energy saver
*/
public EnergySaver getEnergySaver()
{
return energySaver_;
}
/**
* Routine to join the group leader.
*
* @param groupLeader The group leader description
* @return true if everything ok, false otherwise
* @throws Exception The exception
*/
public boolean onGroupLeaderJoin(GroupManagerDescription groupLeader)
throws Exception
{
Guard.check(groupLeader);
NetworkAddress address = groupLeader.getListenSettings().getControlDataAddress();
log_.debug(String.format("Joining group leader %s with control data port: %s",
address.getAddress(), address.getPort()));
repository_.fillGroupManagerDescription(description_);
GroupManagerAPI communicator = CommunicatorFactory.newGroupManagerCommunicator(address);
boolean hasJoined = communicator.joinGroupLeader(description_);
if (hasJoined)
{
startGroupManagerMonitoringService(groupLeader);
}
return hasJoined;
}
/**.
* Returns the state machine.
*
* @return The state machine
*/
public StateMachine getStateMachine()
{
return stateMachine_;
}
/**
* Returns the group manager repository.
*
* @return The group manager repository
*/
public GroupManagerRepository getRepository()
{
return repository_;
}
/**
*
* Gets the external notifier.
*
* @return ExternalNotifier
*/
public ExternalNotifier getExternalNotifier()
{
return externalNotifier_;
}
}