/** * 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.bootstrap; import java.util.ArrayList; 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.groupmanager.repository.GroupLeaderRepositoryInformation; import org.inria.myriads.snoozecommon.communication.localcontroller.LocalControllerDescription; import org.inria.myriads.snoozecommon.communication.localcontroller.LocalControllerList; import org.inria.myriads.snoozecommon.communication.rest.CommunicatorFactory; import org.inria.myriads.snoozecommon.communication.rest.api.BootstrapAPI; import org.inria.myriads.snoozecommon.communication.rest.api.GroupManagerAPI; import org.inria.myriads.snoozecommon.communication.virtualcluster.VirtualMachineMetaData; import org.inria.myriads.snoozecommon.communication.virtualcluster.migration.ClientMigrationRequestSimple; import org.inria.myriads.snoozecommon.communication.virtualcluster.migration.MigrationRequest; import org.inria.myriads.snoozecommon.communication.virtualcluster.submission.VirtualClusterSubmissionRequest; import org.inria.myriads.snoozecommon.communication.virtualcluster.submission.VirtualClusterSubmissionResponse; import org.inria.myriads.snoozecommon.communication.virtualcluster.submission.VirtualMachineLocation; import org.inria.myriads.snoozecommon.communication.virtualmachine.VirtualMachinesList; import org.inria.myriads.snoozecommon.guard.Guard; import org.inria.myriads.snoozecommon.request.HostListRequest; import org.inria.myriads.snoozenode.groupmanager.statemachine.VirtualMachineCommand; import org.restlet.resource.ServerResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Bootstrap resource. * * @author Eugen Feller */ public final class BootstrapResource extends ServerResource implements BootstrapAPI { /** Define the logger. */ private static final Logger log_ = LoggerFactory.getLogger(BootstrapResource.class); /** Backend backend reference. */ private BootstrapBackend backend_; /** * Constructor. */ public BootstrapResource() { log_.debug("Starting bootstrap resource"); backend_ = (BootstrapBackend) getApplication().getContext().getAttributes().get("backend"); } /** * Gets the current Group Leader Description. * * * @return The group leader description */ public GroupManagerDescription getGroupLeaderDescription() { log_.debug("Received group leader information request"); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } GroupManagerDescription groupLeaderDescription = backend_.getGroupLeaderDescription(); if (groupLeaderDescription != null) { log_.debug(String.format("Returning group leader %s:%d", groupLeaderDescription.getListenSettings().getControlDataAddress().getAddress(), groupLeaderDescription.getListenSettings().getControlDataAddress().getPort())); } return groupLeaderDescription; } /** * * Gets the complete hierarchy. * * @return The complete hierarchy of the system. * */ public synchronized GroupLeaderRepositoryInformation getCompleteHierarchy() { log_.debug("Received complete hierarchy request"); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } GroupLeaderRepositoryInformation hierarchy = backend_.getCompleteHierarchy(); return hierarchy; } @Override public boolean destroyVirtualMachine(String virtualMachineId) { log_.debug("Processing destroy for virtual machine " + virtualMachineId); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } return backend_.commandVirtualMachine(VirtualMachineCommand.DESTROY, virtualMachineId); } @Override public boolean suspendVirtualMachine(String virtualMachineId) { log_.debug("Processing suspend for virtual machine " + virtualMachineId); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } return backend_.commandVirtualMachine(VirtualMachineCommand.SUSPEND, virtualMachineId); } @Override public boolean rebootVirtualMachine(String virtualMachineId) { log_.debug("Processing reboot for virtual machine " + virtualMachineId); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } return backend_.commandVirtualMachine(VirtualMachineCommand.REBOOT, virtualMachineId); } @Override public boolean shutdownVirtualMachine(String virtualMachineId) { log_.debug("Processing reboot for virtual machine " + virtualMachineId); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } return backend_.commandVirtualMachine(VirtualMachineCommand.SHUTDOWN, virtualMachineId); } @Override public boolean resumeVirtualMachine(String virtualMachineId) { log_.debug("Processing reboot for virtual machine " + virtualMachineId); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } return backend_.commandVirtualMachine(VirtualMachineCommand.RESUME, virtualMachineId); } @Override public boolean migrateVirtualMachine(ClientMigrationRequestSimple migrationRequest) { MigrationRequest internalMigrationRequest = backend_.getRepository().createMigrationRequest(migrationRequest); if (internalMigrationRequest == null) { return false; } VirtualMachineLocation oldLocation = internalMigrationRequest.getSourceVirtualMachineLocation(); NetworkAddress groupManagerSource = oldLocation.getGroupManagerControlDataAddress(); GroupManagerAPI communicator = CommunicatorFactory.newGroupManagerCommunicator(groupManagerSource); boolean isMigrating = communicator.migrateVirtualMachine(internalMigrationRequest); return isMigrating; } /** * Dispatches the virtual cluster submission request. * (called by the client) * * @param virtualClusterDescription The virtual cluster description * @return The assigned task identifier */ @Override public String startVirtualCluster(VirtualClusterSubmissionRequest virtualClusterDescription) { Guard.check(virtualClusterDescription); log_.debug("Received virtual cluster start request"); GroupManagerDescription groupLeader = getGroupLeaderDescription(); NetworkAddress groupLeaderAddress = groupLeader.getListenSettings().getControlDataAddress(); GroupManagerAPI groupLeaderCommunicator = CommunicatorFactory.newGroupManagerCommunicator(groupLeaderAddress); String taskIdentifier = groupLeaderCommunicator.startVirtualCluster(virtualClusterDescription); log_.debug(String.format("Returning task identifier: %s", taskIdentifier)); return taskIdentifier; } @Override public LocalControllerList geLocalControllerList() { if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } LocalControllerList localControllerList = backend_.getRepository().getLocalControllerList(); return localControllerList; } // admin zone @Override public List<GroupManagerDescription> getGroupManagerDescriptions(HostListRequest hostListRequest) { if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } String firstGroupManagerId = hostListRequest.getStart(); int numberOfMonitoringEntries = hostListRequest.getNumberOfMonitoringEntries(); int limit = hostListRequest.getLimit(); List<GroupManagerDescription> groupManagerDescriptions = new ArrayList<GroupManagerDescription>(); groupManagerDescriptions = backend_.getRepository().getGroupManagerDescriptions( firstGroupManagerId, limit, numberOfMonitoringEntries, backend_.getGroupLeaderDescription() ); return groupManagerDescriptions; } @Override public List<LocalControllerDescription> getLocalControllerDescriptions(HostListRequest hostListRequest) { if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } String groupManagerId = hostListRequest.getGroupManagerId(); String startLocalController = hostListRequest.getStart(); int numberOfMonitoringEntries = hostListRequest.getNumberOfMonitoringEntries(); int limit = hostListRequest.getLimit(); List<LocalControllerDescription> localControllers = backend_.getRepository().getLocalControllerDescriptions( groupManagerId, startLocalController, limit, numberOfMonitoringEntries, backend_.getGroupLeaderDescription() ); return localControllers; } @Override public VirtualMachinesList getVirtualMachineDescriptions(HostListRequest hostListRequest) { Guard.check(hostListRequest); if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return null; } String groupManagerId = hostListRequest.getGroupManagerId(); String localControllerId = hostListRequest.getLocalControllerId(); String startVirtualMachine = hostListRequest.getStart(); int numberOfMonitoringEntries = hostListRequest.getNumberOfMonitoringEntries(); int limit = hostListRequest.getLimit(); List<VirtualMachineMetaData> virtualMachines = backend_.getRepository().getVirtualMachineDescriptions( groupManagerId, localControllerId, startVirtualMachine, limit, numberOfMonitoringEntries, backend_.getGroupLeaderDescription() ); VirtualMachinesList virtualMachinesList = new VirtualMachinesList(); virtualMachinesList.setVirtualMachines(virtualMachines); return virtualMachinesList; } /** * Starts a reconfiguration on the given groupManager. * * @param groupManagerId The group manager id. * * @return True if everything is fine (see startReconfiguration in GM) */ public boolean startReconfiguration(String groupManagerId) { if (!isBackendActive()) { log_.debug("Backend is not initialized yet!"); return false; } GroupManagerDescription groupLeader = backend_.getGroupLeaderDescription(); GroupManagerDescription groupManager = backend_.getRepository().getGroupManagerDescription(groupManagerId, groupLeader); NetworkAddress groupManagerAddress = groupManager.getListenSettings().getControlDataAddress(); GroupManagerAPI groupManagerCommunicator = CommunicatorFactory.newGroupManagerCommunicator(groupManagerAddress); boolean isStarted = groupManagerCommunicator.startReconfiguration(); return isStarted; } @Override public VirtualClusterSubmissionResponse getVirtualClusterResponse(String taskIdentifier) { if (!isBackendActive()) { log_.debug("Backend is not initialized yet"); return null; } GroupManagerDescription groupLeader = backend_.getGroupLeaderDescription(); NetworkAddress groupLeaderAddress = groupLeader.getListenSettings().getControlDataAddress(); GroupManagerAPI groupLeaderCommunicator = CommunicatorFactory.newGroupManagerCommunicator(groupLeaderAddress); VirtualClusterSubmissionResponse response = groupLeaderCommunicator.getVirtualClusterResponse(taskIdentifier); return response; } /** * Check backend activity. * * @return true if active, false otherwise */ private boolean isBackendActive() { if (backend_ == null && backend_.isActive()) { return false; } return true; } }