/** * 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 java.util.List; import org.inria.myriads.snoozecommon.communication.NetworkAddress; import org.inria.myriads.snoozecommon.communication.groupmanager.GroupManagerDescription; import org.inria.myriads.snoozecommon.communication.localcontroller.AssignedGroupManager; import org.inria.myriads.snoozecommon.communication.localcontroller.LocalControllerDescription; 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.database.DatabaseFactory; import org.inria.myriads.snoozenode.database.api.GroupLeaderRepository; import org.inria.myriads.snoozenode.exception.GroupLeaderInitException; import org.inria.myriads.snoozenode.groupmanager.estimator.ResourceDemandEstimator; import org.inria.myriads.snoozenode.groupmanager.leaderpolicies.GroupLeaderPolicyFactory; import org.inria.myriads.snoozenode.groupmanager.leaderpolicies.assignment.AssignmentPolicy; import org.inria.myriads.snoozenode.groupmanager.leaderpolicies.enums.Assignment; import org.inria.myriads.snoozenode.groupmanager.monitoring.MonitoringFactory; import org.inria.myriads.snoozenode.groupmanager.virtualclustermanager.VirtualClusterManager; import org.inria.myriads.snoozenode.groupmanager.virtualmachinediscovery.VirtualMachineDiscovery; import org.inria.myriads.snoozenode.heartbeat.HeartbeatFactory; import org.inria.myriads.snoozenode.heartbeat.message.HeartbeatMessage; import org.inria.myriads.snoozenode.util.ManagementUtils; import org.inria.snoozenode.external.notifier.ExternalNotifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Group leader initialization. * * @author Eugen Feller */ public final class GroupLeaderInit { /** Logging instance. */ private static final Logger log_ = LoggerFactory.getLogger(GroupLeaderInit.class); /** Node configuration parameters.. */ private NodeConfiguration nodeConfiguration_; /** Group leader repository. */ private GroupLeaderRepository groupLeaderRepository_; /** Virtual cluster manager. */ private VirtualClusterManager virtualClusterManager_; /** Virtual machine discovery. */ private VirtualMachineDiscovery virtualMachineDiscovery_; /** Local controller assignment policy. */ private AssignmentPolicy assignmentPolicy_; /** Resource demand estimator. */ private ResourceDemandEstimator estimator_; /** External notifier.*/ private ExternalNotifier externalNotifier_; /** * Constructor. * * @param nodeConfiguration The node configuration * @param groupLeaderDescription The group leader description * @param externalNotifier external notifier. * @throws Exception Exception */ public GroupLeaderInit(NodeConfiguration nodeConfiguration, GroupManagerDescription groupLeaderDescription, ExternalNotifier externalNotifier ) throws Exception { Guard.check(nodeConfiguration); log_.debug("Initializing the group leader logic"); nodeConfiguration_ = nodeConfiguration; externalNotifier_ = externalNotifier; startInitialization(groupLeaderDescription); } /** * Starts the initialization. * * @param groupLeaderDescription The group leader description * @throws Exception */ private void startInitialization(GroupManagerDescription groupLeaderDescription) throws Exception { Guard.check(groupLeaderDescription); log_.debug("Starting the group leader components initialization!"); initializeLocalControllerAssignmentPolicy(); initializeRepository(groupLeaderDescription); initializeResourceDemandEstimator(); initializeVirtualClusterManager(); initializeVirtualMachineDiscovery(); startGroupManagerMonitoringDataReceiver(); //everyting is setup we can send heartbeat. startHeartbeatSender(groupLeaderDescription); } /** * Returns the node configuration. * * @return The node configuration */ public NodeConfiguration getNodeConfiguration() { return nodeConfiguration_; } /** * Initializes the resource demand estimator. */ private void initializeResourceDemandEstimator() { estimator_ = new ResourceDemandEstimator(nodeConfiguration_.getEstimator(), nodeConfiguration_.getMonitoring().getThresholds(), nodeConfiguration_.getSubmission().getPackingDensity()); } /** * Initializes the repository. * * @param groupLeaderDescription The group leader description */ private void initializeRepository(GroupManagerDescription groupLeaderDescription) { String[] virtualMachineSubnets = nodeConfiguration_.getNetworking().getVirtualMachineSubnets(); DatabaseSettings settings = nodeConfiguration_.getDatabase(); groupLeaderRepository_ = DatabaseFactory.newGroupLeaderRepository( groupLeaderDescription, virtualMachineSubnets, settings, externalNotifier_); } /** * Starts the virtual machine discovery. */ private void initializeVirtualMachineDiscovery() { virtualMachineDiscovery_ = new VirtualMachineDiscovery(groupLeaderRepository_); } /** * Starts the virtual cluster manager. */ private void initializeVirtualClusterManager() { virtualClusterManager_ = new VirtualClusterManager(nodeConfiguration_, groupLeaderRepository_, estimator_); } /** * Return the group manager repository. * * @return The group leader repository */ public GroupLeaderRepository getRepository() { return groupLeaderRepository_; } /** * Starts the group manager monitoring data receiver. * * @throws Exception */ private void startGroupManagerMonitoringDataReceiver() throws Exception { log_.debug("Starting the group manager monitoring data receiver"); NetworkAddress monitoringAddress = nodeConfiguration_.getNetworking().getListen().getMonitoringDataAddress(); int monitoringTimeout = nodeConfiguration_.getMonitoring().getTimeout(); MonitoringFactory.newGroupManagerSummaryReceiver(monitoringAddress, monitoringTimeout, groupLeaderRepository_); } /** * Initializes the local controller assignment policy. * * @throws GroupLeaderInitException */ private void initializeLocalControllerAssignmentPolicy() throws GroupLeaderInitException { Assignment policy = nodeConfiguration_.getGroupLeaderScheduler().getAssignmentPolicy(); assignmentPolicy_ = GroupLeaderPolicyFactory.newLocalControllerAssignment(policy); if (assignmentPolicy_ == null) { throw new GroupLeaderInitException("Local controller assignment policy is NULL"); } } /** * Assigns local controller to group manager. * * @param localController The local controller description * @return The group manager description */ public AssignedGroupManager assignLocalController(LocalControllerDescription localController) { Guard.check(localController); log_.debug(String.format("Assigning local controller: %s, %s: %d", localController.getId(), localController.getControlDataAddress().getAddress(), localController.getControlDataAddress().getPort())); int numberOfMonitoringEntries = nodeConfiguration_.getEstimator().getNumberOfMonitoringEntries(); List<GroupManagerDescription> descriptions = groupLeaderRepository_.getGroupManagerDescriptions(numberOfMonitoringEntries); if (descriptions.size() == 0) { log_.debug("No group manager descriptions available!"); return null; } AssignedGroupManager lookUp = lookupLocalControllerLocation(localController, descriptions); if (lookUp == null) { GroupManagerDescription groupManager = assignmentPolicy_.assign(localController, descriptions); log_.debug(String.format("Unable to find previous group manager! Assigned to new group manager: %s", groupManager.getId())); lookUp = new AssignedGroupManager(); lookUp.setGroupManager(groupManager); return lookUp; } log_.debug(String.format("Previous identifier: %s and group manager found: %s", lookUp.getLocalControllerId(), lookUp.getGroupManager().getId())); return lookUp; } /** * Performs local controller lookup. * * @param localController The local controller description * @param groupManagers The group manager descriptions * @return The lookup reply, null otherwise */ private AssignedGroupManager lookupLocalControllerLocation(LocalControllerDescription localController, List<GroupManagerDescription> groupManagers) { log_.debug("Performing local controller lookup on group managers"); NetworkAddress contactInformation = localController.getControlDataAddress(); AssignedGroupManager lookup = groupLeaderRepository_.getAssignedGroupManager(contactInformation); return lookup; // We don't need this anymore since we got the LCs in the GL repo // for (GroupManagerDescription groupManager : groupManagers) // { // NetworkAddress groupManagerAddress = groupManager.getListenSettings().getControlDataAddress(); // GroupManagerAPI groupManagerCommunicator = // CommunicatorFactory.newGroupManagerCommunicator(groupManagerAddress); // String localControllerId = groupManagerCommunicator.hasLocalController(contactInformation); // if (localControllerId != null) // { // AssignedGroupManager lookup = new AssignedGroupManager(); // lookup.setLocalControllerId(localControllerId); // lookup.setGroupManager(groupManager); // return lookup; // } // } // return null; } /** * Multicast the group leader presence. * * @param groupLeader The group leader description * @throws IOException */ private void startHeartbeatSender(GroupManagerDescription groupLeader) throws IOException { Guard.check(groupLeader); log_.debug("Starting the group leader heartbeat sender"); NetworkAddress heartbeatAddress = nodeConfiguration_.getNetworking() .getMulticast() .getGroupLeaderHeartbeatAddress(); int heartbeatInterval = nodeConfiguration_.getFaultTolerance().getHeartbeat().getInterval(); HeartbeatMessage heartbeatMessage = ManagementUtils.createHeartbeatMessage(groupLeader.getListenSettings(), groupLeader.getId()); new Thread(HeartbeatFactory.newHeartbeatMulticastSender(heartbeatAddress, heartbeatInterval, heartbeatMessage), "HeartbeatSender" ).start(); } /** * Returns the virtual cluster manager. * * @return The virtual cluster manager */ public VirtualClusterManager getVirtualClusterManager() { return virtualClusterManager_; } /** * Returns the virtual machine discovery. * * @return The virtual machine discovery service */ public VirtualMachineDiscovery getVirtualMachineDiscovery() { return virtualMachineDiscovery_; } /** * Returns the resource demand estimator. * * @return The resource demand estimator */ public ResourceDemandEstimator getResourceDemandEstimator() { return estimator_; } }