/* * Copyright (C) 2011 Ives van der Flaas * * 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 3 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 be.ac.ua.comp.scarletnebula.core; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import org.dasein.cloud.CloudException; import org.dasein.cloud.InternalException; import be.ac.ua.comp.scarletnebula.core.CloudProviderTemplate.AccessMethod; /** * Singleton class that can be accessed through CloudManager.get(). E.g. * CloudManager.get().load() to load. * * This class manages all clouds. * * @author ives * */ public final class CloudManager { private final HashMap<String, CloudProvider> providers = new HashMap<String, CloudProvider>(); private final Collection<CloudProviderTemplate> providerTemplates = new ArrayList<CloudProviderTemplate>(); private final Collection<ServerLinkUnlinkObserver> linkUnlinkObservers = new ArrayList<ServerLinkUnlinkObserver>(); /** * Private constructor. */ private CloudManager() { populateCloudProviderTemplates(); // Load all providers and put them in the list for (final String provname : CloudProvider.getProviderNames()) { final CloudProvider cloudProvider = new CloudProvider(provname); for (final ServerLinkUnlinkObserver obs : linkUnlinkObservers) { cloudProvider.addServerLinkUnlinkObserver(obs); } providers.put(provname, cloudProvider); } } /** * Adds an observer that will be notified when a server is linked & * unlinked. * * @param obs * The observer to add */ public void addServerLinkUnlinkObserver(final ServerLinkUnlinkObserver obs) { linkUnlinkObservers.add(obs); // Also add this observer to the cloudproviders that are already in the // system. for (final CloudProvider prov : providers.values()) { prov.addServerLinkUnlinkObserver(obs); } } /** * Fills the available cloud provider templates. */ private void populateCloudProviderTemplates() { // AWS final CloudProviderTemplate aws = new CloudProviderTemplate( "Amazon Elastic Compute Cloud", "Amazon EC2", "org.dasein.cloud.aws.AWSCloud", AccessMethod.KEY); aws.addEndPoint("EU (Ireland)", "EU", "http://ec2.eu-west-1.amazonaws.com"); aws.addEndPoint("Asia Pacific (Singapore)", "Asia", "http://ec2.ap-southeast-1.amazonaws.com"); aws.addEndPoint("US-West (Northern California)", "US-West", "http://ec2.us-west-1.amazonaws.com"); aws.addEndPoint("US-East (Northern Virginia)", "US-East", "http://ec2.us-east-1.amazonaws.com"); providerTemplates.add(aws); // Rackspace // final CloudProviderTemplate rackspace = new CloudProviderTemplate( // "Rackspace (not implemented)", "Rackspace", // "org.dasein.cloud.aws.AWSCloud", AccessMethod.KEY); // providerTemplates.add(rackspace); final CloudProviderTemplate mock = new CloudProviderTemplate( "Mock Cloud Provider", "Mock", "be.ac.ua.comp.scarletnebula.misc.MockCloudProvider", AccessMethod.EMAILPASSWD); providerTemplates.add(mock); final CloudProviderTemplate cloudSigma = new CloudProviderTemplate( "CloudSigma", "CloudSigma", "org.dasein.cloud.jclouds.cloudsigma.CloudSigma", AccessMethod.EMAILPASSWD); providerTemplates.add(cloudSigma); } /** * Bill Pugh's singleton implementation for Java. Because the class is not * referenced before the first call to get, the instance will be lazily * created. This is also perfectly threadsafe. */ private static class CloudManagerHolder { public static final CloudManager INSTANCE = new CloudManager(); } /** * Returns the singleton instance. * * @return The instance. */ public static CloudManager get() { return CloudManagerHolder.INSTANCE; } /** * Returns the names of all linked CloudProviders. * * @return Collection of all the names of linked cloud providers. */ public Collection<String> getLinkedCloudProviderNames() { return providers.keySet(); } /** * Returns all linked CloudProviders. * * @return The actual linked cloudproviders. */ public Collection<CloudProvider> getLinkedCloudProviders() { return providers.values(); } /** * Returns the CloudProvider with name "name". * * @param name * The name of the cloud provider to get. * @return The cloudprovider with name "name" */ public CloudProvider getCloudProviderByName(final String name) { return providers.get(name); } /** * Returns true if the server with "name" exists in one of the * CloudProviders, false otherwise. * * @param name * The friendly name of the server if it exists * @return True if a server by that name exists, false otherwise. */ public boolean serverExists(final String name) { for (final CloudProvider prov : providers.values()) { if (prov.hasServer(name)) { return true; } } return false; } /** * @return A Collection of all available CloudProviderTemplates */ public Collection<CloudProviderTemplate> getTemplates() { return providerTemplates; } /** * Registers a new Cloudprovider. * * @param name * Friendly name of the new cloudprovider * @param classname * The dasein classname for this cloudprovider * @param endpoint * Endpoint to connect to. * @param apiKey * Access id or login * @param apiSecret * Key or password */ public void registerNewCloudProvider(final String name, final String classname, final String endpoint, final String apiKey, final String apiSecret) { final CloudProvider prov = new CloudProvider(name, classname, endpoint, apiKey, apiSecret, ""); prov.store(); for (final ServerLinkUnlinkObserver obs : linkUnlinkObservers) { prov.addServerLinkUnlinkObserver(obs); } providers.put(name, prov); } /** * Removes a cloudprovider, all of his servers and their respective * savefiles. * * @param provname * The provider's name that should be removed. */ public void deleteCloudProvider(final String provname) { final CloudProvider provider = providers.get(provname); providers.remove(provname); // Remove all of his servers final Collection<Server> linkedServers = provider.listLinkedServers(); for (final Server server : linkedServers) { server.unlink(); } // Remove his server directory final File serverdir = removeFilesInDir("servers/" + provname); // Should the provider's keyfiles be removed?? // Now delete the dir itself serverdir.delete(); // And delete his configfile final File config = new File(CloudProvider.getConfigfileName(provname)); config.delete(); } /** * Removes all files in a certain directory. * * @param dirname * The directory whose contents to remove * @return A File describing the hopefully empty directory. */ private File removeFilesInDir(final String dirname) { final File dir = new File(dirname); if (dir.list() != null) { // If there are still files in the directory, delete them for (final String file : dir.list()) { final File f = new File(file); f.delete(); } } return dir; } /** * Sends a request to each CloudProvider to load all of its servers. * * @throws InternalException * @throws CloudException * @throws IOException */ public void loadAllLinkedServers() throws InternalException, CloudException, IOException { for (final CloudProvider prov : providers.values()) { prov.loadLinkedServers(); } } }