Java tutorial
/* * 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.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Properties; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dasein.cloud.CloudException; import org.dasein.cloud.InternalException; import org.dasein.cloud.compute.Architecture; import org.dasein.cloud.compute.ComputeServices; import org.dasein.cloud.compute.MachineImage; import org.dasein.cloud.compute.Platform; import org.dasein.cloud.compute.VirtualMachine; import org.dasein.cloud.compute.VirtualMachineProduct; import org.dasein.cloud.compute.VirtualMachineSupport; import org.dasein.cloud.identity.ShellKeySupport; import org.dasein.cloud.network.Firewall; import org.dasein.cloud.network.FirewallRule; import org.dasein.cloud.network.FirewallSupport; import org.dasein.cloud.network.NetworkServices; import org.dasein.cloud.network.Protocol; import be.ac.ua.comp.scarletnebula.misc.Utils; /** * Class representing a cloud provider in Scarlet Nebula. This will contain a * Dasein cloudprovider object but also implement other stuff like making a * cloudprovider specific configuration. * * @author ives */ public class CloudProvider { private static Log log = LogFactory.getLog(CloudProvider.class); private org.dasein.cloud.CloudProvider providerImpl; private ComputeServices computeServices = null; private VirtualMachineSupport virtualMachineServices = null; private FirewallSupport firewallSupport = null; private String name; private String providerClassName; private String apiSecret; private String apiKey; private String endpoint; private String defaultKeypair; private final Collection<Server> servers = new ArrayList<Server>(); private Collection<MachineImage> favoriteImages = new LinkedList<MachineImage>(); private final Collection<ServerLinkUnlinkObserver> linkUnlinkObservers = new ArrayList<ServerLinkUnlinkObserver>(); /** * Constructor for constructing a cloudprovider from file. * * Don't forget to update the other ctor. * * @param name * Name of the provider. Used to search for a savefile. */ public CloudProvider(final String name) { load(name); connect(); } /** * Sets up the provider implementation. */ private void connect() { try { providerImpl = (org.dasein.cloud.CloudProvider) Class.forName(providerClassName).newInstance(); } catch (final Exception e) { log.error("Underlying cloud provider class " + providerClassName + " failed creation.", e); } providerImpl.connect(getCurrentContext()); computeServices = providerImpl.getComputeServices(); if (computeServices == null) { log.error(providerImpl.getCloudName() + " does not support compute instances."); return; } virtualMachineServices = computeServices.getVirtualMachineSupport(); if (computeServices == null) { log.error(providerImpl.getCloudName() + " does not support Virtual Machines."); return; } final NetworkServices networkServices = providerImpl.getNetworkServices(); if (networkServices == null) { log.warn(providerImpl.getCloudName() + " does not support network services."); } else { firewallSupport = networkServices.getFirewallSupport(); if (firewallSupport == null) { log.warn(providerImpl.getCloudName() + " does not support firewalls."); return; } } } /** * Call when a new server is linked and observers need to be notified. * * @param srv * The server that's linked. */ private void notifyObserversBecauseServerLinked(final Server srv) { for (final ServerLinkUnlinkObserver obs : linkUnlinkObservers) { obs.serverLinked(this, srv); log.info("Cloudprovider is updating his observers"); } } /** * Call when a new server is unlinked and observers need to be notified. * * @param srv * The server that is unlinked. */ private void notifyObserversBecauseServerUnlinked(final Server srv) { for (final ServerLinkUnlinkObserver obs : linkUnlinkObservers) { obs.serverUnlinked(this, srv); } } /** * Loads a CloudProvider from file based on his name. * * @param name * Name of the provider to load. */ private void load(final String name) { Properties properties = null; try { properties = new Properties(); properties.load(new FileInputStream(getConfigfileName(name))); } catch (final IOException e) { log.error("IOException while loading provider from file.", e); } this.name = name; this.providerClassName = properties.getProperty("class"); this.apiKey = properties.getProperty("apikey"); this.apiSecret = properties.getProperty("apisecret"); this.endpoint = properties.getProperty("endpoint"); this.defaultKeypair = properties.getProperty("defaultKeypair", ""); this.favoriteImages = deserialiseFavoriteImages(properties.getProperty("favoriteImages", null)); } /** * Basic constructor for use when *not* loading from file. A provider made * in this fashion will probably not be linked with the cloudManager. * * Don't forget to update the other constructor! * * @param name * CloudProvider's name * @param classname * Name of the dasein class this provider is based on * @param endpoint * Endpoint to use * @param apikey * ID or username to login * @param apisecret * Key or password to login * @param defaultKeypair * Default keypair to use */ public CloudProvider(final String name, final String classname, final String endpoint, final String apikey, final String apisecret, final String defaultKeypair) { this.name = name; this.providerClassName = classname; this.apiKey = apikey; this.apiSecret = apisecret; this.endpoint = endpoint; this.defaultKeypair = defaultKeypair; connect(); } /** * Loads a server (from file!) and returns it. * * @param unfriendlyName * Provider implementation's name for the server to load. * @return The server that was just started. * @throws InternalException * @throws CloudException * @throws IOException */ public Server loadServer(final String unfriendlyName) throws InternalException, CloudException, IOException { log.warn("Getting for name " + unfriendlyName); final VirtualMachine server = getServerImpl(unfriendlyName); if (server == null) { return null; } final Server rv = Server.load(server, this); return rv; } /** * Loads all servers that have a saved representation. * * @return Collection of all the servers that were loaded. * @throws InternalException * @throws CloudException * @throws IOException */ public Collection<Server> loadLinkedServers() throws InternalException, CloudException, IOException { final File dir = new File(getSaveFileDir()); final String[] files = dir.list(); if (files == null) { return servers; } for (final String file : files) { final Server server = loadServer(file); // If the server cannot be made it was deleted and the file // referencing it // should also be removed. if (server == null) { log.warn("Server from file " + file + " cannot be loaded. Discarting save file."); deleteServerSaveFile(file); } else { linkServer(server); } } return servers; } /** * Links a server to this cloudprovider. * * @param server * The server to link. */ public void linkServer(final Server server) { notifyObserversBecauseServerLinked(server); servers.add(server); } /** * Delete's the server whose CloudProvider specific name is * "unfriendlyName". * * @param unfriendlyName * Unfriendly name of the server whose savefile to remove. */ private void deleteServerSaveFile(final String unfriendlyName) { final File toBeRemoved = new File(getSaveFileDir() + unfriendlyName); final boolean result = toBeRemoved.delete(); if (!result) { log.error("Could not remove savefile for server " + unfriendlyName); } } /** * Creates a new key with name "keyname", changes the default key if it has * to and stores the server to file. * * @param keyname * Name of the key to create * @throws InternalException * @throws CloudException */ public void createKey(final String keyname, final boolean makeDefault) throws InternalException, CloudException { final ShellKeySupport shellKeySupport = providerImpl.getIdentityServices().getShellKeySupport(); KeyManager.addKey(getName(), keyname, shellKeySupport.createKeypair(keyname)); if (makeDefault) { setDefaultKeypair(keyname); store(); } } /** * Adds a new firewall rule to an already existing firewall on this * provider. * * @param firewall * The firewall to add the rule to * @param beginPort * The lower edge of the port range that should be allowed * @param endPort * The upper edge of the port range that should be allowed * @param protocol * The protocol, UDP or TCP which should be allowed * @param cidr * The IP CIDR that should be allowed. * @throws CloudException * @throws InternalException */ public void addFirewallRule(final Firewall firewall, final int beginPort, final int endPort, final Protocol protocol, final String cidr) throws CloudException, InternalException { firewallSupport.authorize(firewall.getProviderFirewallId(), cidr, protocol, beginPort, endPort); } /** * Deletes a firewall rule on the cloudprovider's side. * * @param firewall * The firewall whose rule to revoke. * @param beginPort * The lower end of the port range. * @param endPort * The higher end of the port range. * @param protocol * The protocol. * @param cidr * Ip address descriptor * @throws CloudException * @throws InternalException */ public void deleteFirewallRule(final Firewall firewall, final int beginPort, final int endPort, final Protocol protocol, final String cidr) throws CloudException, InternalException { firewallSupport.revoke(firewall.getProviderFirewallId(), cidr, protocol, beginPort, endPort); } /** * @return All firewalls for this CloudProvider. * @throws InternalException * @throws CloudException */ public Collection<Firewall> getFirewalls() throws InternalException, CloudException { final FirewallSupport fws = providerImpl.getNetworkServices().getFirewallSupport(); if (fws == null) { return new ArrayList<Firewall>(); } return fws.list(); } /** * Returns a collection of all rules for a certain firewall. * * @param firewall * The firewall whose rules to return. * @return A collection of all rules for a certain firewall. * @throws InternalException * @throws CloudException */ public Collection<FirewallRule> getFirewallRules(final String firewall) throws InternalException, CloudException { return firewallSupport.getRules(firewall); } /** * Lists all servers the underlying Cloud Provider manages, but that are * *not* by listLinkedServers() i.e. the ones that aren't managed by Scarlet * Nebula at this moment. * * @return The servers that exist in the cloud but are not linked with this * provider. * @throws CloudException * @throws InternalException */ public ArrayList<Server> listUnlinkedServers() throws InternalException, CloudException { final ArrayList<Server> rv = new ArrayList<Server>(); // List all servers for (final VirtualMachine testServer : virtualMachineServices.listVirtualMachines()) { // For each server, check if this server is already linked. Do // this based on his unfriendly id boolean found = false; for (final Iterator<Server> linkedServerIterator = servers.iterator(); linkedServerIterator.hasNext() && !found;) { if (linkedServerIterator.next().getUnfriendlyName().equals(testServer.getName())) { found = true; } } if (!found) { final List<String> daseinTags = new ArrayList<String>(); for (final String key : testServer.getTags().keySet()) { daseinTags.add(key + ":" + testServer.getTags().get(key)); } rv.add(new Server(testServer, // dasein server this, // cloud provider "", // keypair testServer.getName() + " (" + getName() + ")", // friendly // name daseinTags, // tags true, // use password nullToEmpty(testServer.getRootUser()), // root user nullToEmpty(testServer.getRootPassword()), // root // password nullToEmpty(testServer.getRootPassword()), // VNC passwd getDefaultStatisticsCommand(), // statistics command "CPU")); } } return rv; } /** * Utility method that returns the string if it is not null, or the empty * string if the string is null. * * @param input * The input string. * @return the input string if it is not null, or the empty string if the * string is null. */ private String nullToEmpty(final String input) { return (input == null) ? "" : input; } /** * Returns all servers that are currently being managed by this * CloudProvider. * * @return A collection of all servers that are linked with this * cloudprovider. */ public Collection<Server> listLinkedServers() { return servers; } /** * Terminates the server with unfriendlyName "unfriendlyName". This method * will and should only be called by Server.terminate(). * * @param unfriendlyName * Unfriendly name of the server to terminate. * @throws InternalException * @throws CloudException */ public void terminateServer(final String unfriendlyName) throws InternalException, CloudException { virtualMachineServices.terminate(unfriendlyName); } /** * Starts a new server. * * @param serverName * Friendly name of the server to start * @param product * Product (size ed) for the new server * @param image * Image to use for the new server * @param tags * Tags this server will have * @param keypairOrPassword * Keypair or password to use for the server * @param firewalls * The firewalls that will protect this server * @return The server that's either started or starting. * @throws InternalException * @throws CloudException */ public Server startServer(final String serverName, final VirtualMachineProduct product, final MachineImage image, final Collection<String> tags, final String keypairOrPassword, final Collection<String> firewalls) throws InternalException, CloudException { final String dataCenterId = "eu-west-1b"; final String vlan = null; final Collection<org.dasein.cloud.Tag> daseinTags = new ArrayList<org.dasein.cloud.Tag>(); int i = 0; for (final String tag : tags) { daseinTags.add(new org.dasein.cloud.Tag("tag" + (++i), tag)); } final VirtualMachine daseinServer = virtualMachineServices.launch(image.getProviderMachineImageId(), // image id product, // vm product (size) dataCenterId, // data center id serverName, // friendly server name "", // server description keypairOrPassword, // keypair vlan, // vlan false, false, (firewalls != null ? firewalls.toArray(new String[0]) : null), // firewalls daseinTags.toArray(new org.dasein.cloud.Tag[0])); // tags String rootUser = daseinServer.getRootUser(); if (rootUser == null || rootUser.isEmpty()) { if (image.getName().toLowerCase().contains("ubuntu") || image.getDescription().toLowerCase().contains("ubuntu")) { rootUser = "ubuntu"; } else if (image.getPlatform() != Platform.WINDOWS) { rootUser = "root"; } else { rootUser = ""; } } final Server server = new Server(daseinServer, // Dasein server // implementation this, // Cloud provider keypairOrPassword, // Keypair used serverName, // Server's friendly name tags, // Tags this server was given !supportsSSHKeys(), // server uses password to SSH rootUser, // SSH login daseinServer.getRootPassword(), // SSH Password keypairOrPassword, // VNC password getDefaultStatisticsCommand(), // Statistics // command "CPU"); // preferred datastream server.store(); linkServer(server); return server; } /** * @return The name of the default keypair for this provider. If no default * keypair is set (or the default keypair is invalid) but there are * keys available, one of these will be chosen. */ public String getDefaultKeypair() { // If no default keypair is entered in the cloudprovider, but there is a // key for this provider, make that the default. // Also do something similar when the default key is not in the set of // keys. final Collection<String> keys = KeyManager.getKeyNames(getName()); if (defaultKeypair.isEmpty() || !keys.contains(defaultKeypair)) { if (!keys.isEmpty()) { final String newDefaultKey = keys.iterator().next(); setDefaultKeypair(newDefaultKey); store(); } } return defaultKeypair; } /** * Sets the default keypair (without saving) on the condition that a keypair * by this name exists. * * @param newDefaultKeypair * The name of the new keypair that will become default. */ public void setDefaultKeypair(final String newDefaultKeypair) { if (KeyManager.getKeyNames(getName()).contains(newDefaultKeypair)) { defaultKeypair = newDefaultKeypair; } } /** * @return The default statistics command for this cloudprovider. */ public String getDefaultStatisticsCommand() { final StringBuffer sb = new StringBuffer(); try { BufferedReader br; br = new BufferedReader(new FileReader(Utils.internalFile("statistics.sh"))); String nextLine = ""; while ((nextLine = br.readLine()) != null) { sb.append(nextLine); sb.append("\n"); } } catch (final Exception e) { log.error("Could not read default statistics command, continuing with empty string", e); } return sb.toString(); } /** * Returns a VirtualMachineProduct representation of a certain unfriendly * name for that product. * * @param name * Unfriendly name for the vm product. * @return The product with name name or null if no such product exists. */ public VirtualMachineProduct getVMProductWithName(final String name) { try { final Iterable<VirtualMachineProduct> products = virtualMachineServices.listProducts(Architecture.I32); for (final VirtualMachineProduct product : products) { if (name == product.getName()) { return product; } } return null; } catch (final Exception e) { log.error("Error while getting VM Product with name", e); } return null; } /** * Returns the endpoint this CloudProvider uses. * * @return The endpoint this CloudProvider uses. */ private String getEndpoint() { return endpoint; } /** * Closes this CloudProvider (call it before the program ends). */ void close() { providerImpl.close(); } /** * @return A dasein provider context for this cloudprovider. */ private org.dasein.cloud.ProviderContext getCurrentContext() { final org.dasein.cloud.ProviderContext context = new org.dasein.cloud.ProviderContext(); context.setAccountNumber("000000000000"); context.setAccessPublic(apiKey.getBytes()); context.setAccessPrivate(apiSecret.getBytes()); context.setEndpoint(getEndpoint()); return context; } /** * Returns a collection of instance sizes that are possible. * * @param architecture * The architecture for which all instance sizes should be * listed. * @return An iterator over all possible instance sizes for that * architecture. */ public Iterable<VirtualMachineProduct> getPossibleInstanceSizes(final Architecture architecture) { Iterable<VirtualMachineProduct> products = null; try { products = virtualMachineServices.listProducts(architecture); } catch (final Exception e) { log.error("Error while querying the list of VM products for architecture " + architecture, e); } return products; } /** * Returns the underlying class' name... * * @return The name of the underlying dasein class. */ public String getUnderlyingClassname() { return providerClassName; } /** * * @param unfriendlyName * The unfriendly name for which a dasein server is needed. * @return The dasein server implementation from an unfriendly name. * @throws InternalException * @throws CloudException */ public VirtualMachine getServerImpl(final String unfriendlyName) throws InternalException, CloudException { return virtualMachineServices.getVirtualMachine(unfriendlyName); } /** * * @param platform * Platform to filter on * @param architecture * Architecture to filter on. * @return An iterator over all possible machine images for a certain * architecture & platform. */ public Iterable<MachineImage> getAvailableMachineImages(final Platform platform, final Architecture architecture) { Iterable<MachineImage> images = null; try { images = computeServices.getImageSupport().searchMachineImages("", platform, architecture); } catch (final Exception e) { log.error("Error while searching for a machine image with platform " + platform + " and architecture " + architecture); } return images; } /** * Pauses the server in parameter. This method is only supposed to be called * by Server.pause() * * @param server * The server to pause. * @throws InternalException * @throws CloudException */ public void pause(final Server server) throws InternalException, CloudException { virtualMachineServices.pause(server.getUnfriendlyName()); } /** * Resumes a previously paused server. * * @param server * The server to resume. * @throws InternalException * @throws CloudException */ public void resume(final Server server) throws InternalException, CloudException { log.info("Resuming " + server); virtualMachineServices.boot(server.getUnfriendlyName()); } /** * Reboots the server in parameter. This method is only supposed to be * called by Server.reboot() * * @param server * The server to reboot. * @throws CloudException * @throws InternalException */ public void reboot(final Server server) throws CloudException, InternalException { virtualMachineServices.reboot(server.getUnfriendlyName()); } /** * Unlinks the instance in parameter. After this call, this instance will no * longer be linked to this CloudProvider * * @param selectedServer * The server to unlink. */ public void unlink(final Server selectedServer) { servers.remove(selectedServer); deleteServerSaveFile(selectedServer.getUnfriendlyName()); notifyObserversBecauseServerUnlinked(selectedServer); } /** * Returns true if this cloudprovider owns an instance named "friendlyName" * * @param friendlyName * The name of the instance * @return True if a linked server with name "friendlyName" exists, * otherwise false */ public boolean hasServer(final String friendlyName) { for (final Server s : servers) { if (s.getFriendlyName().equals(friendlyName)) { return true; } } return false; } /** * Returns the identifier that uniquely identifies this CloudProvider * instance. * * @return Friendly name for this cloudprovider. */ public String getName() { return name; } /** * @return The directory (ending in "/") all servers with this CloudProvider * should be saved in. */ String getSaveFileDir() { return "servers/" + getName() + "/"; } /** * Saves the file describing this CloudProvider. If a cloudprovider by the * name "providername" already exists, the savefile will be overwritten. * */ public void store() { // First assure the providers/ directory exists final File dir = new File("providers"); if (!dir.exists() || !dir.isDirectory()) { if (!dir.mkdir()) { log.error("Could not create providers/ directory."); } } // Now write to the file properties file final Properties prop = new Properties(); prop.setProperty("class", providerClassName); prop.setProperty("apikey", apiKey); prop.setProperty("apisecret", apiSecret); prop.setProperty("endpoint", endpoint); prop.setProperty("defaultKeypair", defaultKeypair); prop.setProperty("favoriteImages", getSerialisedFavoriteImages()); try { prop.store(new FileOutputStream(getConfigfileName(name)), null); } catch (final Exception e) { log.error("Properties file describing cloud provider could not be created."); } } /** * @return A serialised base64-drepresentation of the favorite images. Ready * to be debase64d and deserialised. */ private String getSerialisedFavoriteImages() { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ObjectOutputStream oout = null; String rv = ""; try { oout = new ObjectOutputStream(outputStream); log.info("size of serialised images collection = " + favoriteImages.size()); oout.writeObject(favoriteImages); final byte[] bytes = outputStream.toByteArray(); final byte[] encodedBytes = Base64.encodeBase64(bytes, false); rv = new String(encodedBytes); } catch (final IOException e) { log.error("Exception while serialising favorite images.", e); } finally { try { oout.close(); outputStream.close(); } catch (final IOException ignore) { } } return rv; } /** * Converts a string containing base64 encoded favorite image data back to a * collection of machine images. The suppress warnings needs to be here * because of type erasure -- the runtime has no clue what's inside the * collection... * * @param input * String to be deserialised * @return The collection of machine images contained in the input string. */ @SuppressWarnings("unchecked") private Collection<MachineImage> deserialiseFavoriteImages(final String input) { if (input == null || input.isEmpty()) { return new ArrayList<MachineImage>(); } final byte[] decodedBytes = Base64.decodeBase64(input.getBytes()); if (decodedBytes != null) { try { final ObjectInputStream objectIn = new ObjectInputStream(new ByteArrayInputStream(decodedBytes)); final Object readObject = objectIn.readObject(); return (Collection<MachineImage>) readObject; } catch (final Exception e) { log.error("Exception while deserialising favorite images.", e); } } return new ArrayList<MachineImage>(); } /** * @param providername * The friendly name for the provider whose file we're asking * for. * @return The filename of this provider's savefile (or at least where it * would be if one existed). */ public static String getConfigfileName(final String providername) { return "providers/" + providername + ".properties"; } /** * @return Returns a collection of all providernames that exist on disk. */ static Collection<String> getProviderNames() { final File dir = new File("providers"); if (!dir.exists() || !dir.isDirectory()) { return new ArrayList<String>(); } final Collection<String> files = Arrays.asList(dir.list()); final Collection<String> rv = new ArrayList<String>(files.size()); for (final String file : files) { rv.add(file.replaceFirst(".properties$", "")); } return rv; } /** * @param server * The server to check. * @return True if this server is linked, false otherwise. */ public boolean isLinked(final Server server) { // Not using servers.contains because this seems to use Server.equals // which isn't implemented... for (final Server linkedServer : servers) { if (server == linkedServer) { return true; } } return false; } /** * Adds an observer that will be notified when a new server is linked or * unlinked. * * @param obs * The observer that will be notified. */ public void addServerLinkUnlinkObserver(final ServerLinkUnlinkObserver obs) { linkUnlinkObservers.add(obs); } /** * Tests the current CloudProvider for connectivity. * * @return True if a connection can be made, false otherwise. */ public boolean test() { return providerImpl.testContext() != null; } /** * @return A collection of all keys that exist on the provider side but not * locally for this provider. * @throws InternalException * @throws CloudException */ public Collection<String> getUnknownKeys() throws InternalException, CloudException { final ShellKeySupport shellKeySupport = providerImpl.getIdentityServices().getShellKeySupport(); final Collection<String> keys = shellKeySupport.list(); final Collection<String> knownKeys = KeyManager.getKeyNames(getName()); keys.removeAll(knownKeys); return keys; } /** * @return True if this provider supports SSH keys, false otherwise. */ public boolean supportsSSHKeys() { return providerImpl.getIdentityServices() != null && providerImpl.getIdentityServices().getShellKeySupport() != null; } /** * * @param checkKeyname * The name of the key to check. * @return Returns true if a key by the name given exists on the * cloudprovider's side. */ public boolean linkedUnlinkedKeyExists(final String checkKeyname) { final ShellKeySupport shellKeySupport = providerImpl.getIdentityServices().getShellKeySupport(); boolean exists = false; try { exists = shellKeySupport.list().contains(checkKeyname); } catch (final Exception e) { log.error("Could not list keys.", e); } return exists; } /** * Imports a key to the Scarlet Nebula system, and optionally makes it * default and saves the server. * * @param keyname * The key's name * @param keyFile * The file to copy from * @param makeDefault * True if it should become default, false otherwise. */ public void importKey(final String keyname, final File keyFile, final boolean makeDefault) { KeyManager.addKey(getName(), keyname, keyFile); if (makeDefault) { setDefaultKeypair(keyname); store(); } } /** * Deletes and SSH key, both locally and, if it exists, remotely. * * @param key * The key to delete remotely & locally. * @throws CloudException * @throws InternalException */ public void deleteKey(final String key) throws InternalException, CloudException { KeyManager.deleteKey(getName(), key); final ShellKeySupport shellKeySupport = providerImpl.getIdentityServices().getShellKeySupport(); shellKeySupport.deleteKeypair(key); } /** * Creates a firewall in the cloudprovider and returns a pseudo-firewall * object. This object only contains a user friendly name and a provider id. * * @param firewallName * User friendly name of the firewall * @return A pseudo-firewall object. This object only contains a user * friendly name and a provider id. * @throws InternalException * @throws CloudException */ public Firewall createFirewall(final String firewallName) throws InternalException, CloudException { final String id = firewallSupport.create(firewallName, firewallName); final Firewall firewall = new Firewall(); firewall.setName(firewallName); firewall.setProviderFirewallId(id); return firewall; } /** * Deletes a firewall remotely. * * @param firewall * The firewall to delete (if possible) * @throws InternalException * @throws CloudException */ public void deleteFirewall(final Firewall firewall) throws InternalException, CloudException { firewallSupport.delete(firewall.getProviderFirewallId()); } /** * @return True if this cloudprivder supports firewalls, false otherwise. */ public boolean supportsFirewalls() { return firewallSupport != null; } /** * Adds an image to the list of images that are favorite for this provider * (without saving). * * @param image * The image to add. */ public void addToFavorites(final MachineImage image) { if (!imageInFavorites(image)) { favoriteImages.add(image); } } /** * @return A copy of all favorite images for this cloudprovider. */ public Collection<MachineImage> getFavoriteImages() { return new ArrayList<MachineImage>(favoriteImages); } /** * Removes a MachineImage from the list of favorites (without storing). * * @param image * The image to remove from favorites. */ public void removeFromFavorites(final MachineImage image) { favoriteImages.remove(image); } /** * Method that works around a nullexception when comparing MachineImages. * * @param testImage * Image that is or is not in the favoriteImages * @return True if testImage is a favorite image for this cloudprovider, * false otherwise. */ public boolean imageInFavorites(final MachineImage testImage) { boolean found = false; for (final MachineImage image : favoriteImages) { if (image.getProviderMachineImageId() == testImage.getProviderMachineImageId()) { found = true; break; } } return found; } }