diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java index b54e2031c8..c6852e53d2 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxComputeServiceContextModule.java @@ -19,7 +19,9 @@ package org.jclouds.virtualbox.config; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_ARCH; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_OS; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_VERSION; import java.io.File; import java.io.InputStream; @@ -29,7 +31,6 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import javax.inject.Named; import javax.inject.Singleton; import org.eclipse.jetty.server.Server; @@ -46,7 +47,6 @@ import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeState; -import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.domain.Location; @@ -56,7 +56,6 @@ import org.jclouds.predicates.RetryablePredicate; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.virtualbox.Host; -import org.jclouds.virtualbox.Preconfiguration; import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter; import org.jclouds.virtualbox.domain.CloneSpec; import org.jclouds.virtualbox.domain.ExecutionType; @@ -76,7 +75,7 @@ import org.jclouds.virtualbox.functions.NodeCreator; import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; import org.jclouds.virtualbox.functions.admin.FileDownloadFromURI; import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor; -import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning; +import org.jclouds.virtualbox.functions.admin.PreseedCfgServer; import org.jclouds.virtualbox.functions.admin.StartVBoxIfNotAlreadyRunning; import org.jclouds.virtualbox.predicates.SshResponds; import org.testng.internal.annotations.Sets; @@ -91,7 +90,6 @@ import com.google.common.base.Functions; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; -import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; @@ -128,10 +126,10 @@ public class VirtualBoxComputeServiceContextModule extends bind(new TypeLiteral>() { }).to(IMachineToImage.class); bind(new TypeLiteral>() { - }).to((Class) StartJettyIfNotAlreadyRunning.class); + }).to((Class) PreseedCfgServer.class); bind(new TypeLiteral>() { }).to((Class) FileDownloadFromURI.class); - + bind(new TypeLiteral>() { }).to((Class) StartVBoxIfNotAlreadyRunning.class); // the yaml config to image mapper @@ -139,9 +137,11 @@ public class VirtualBoxComputeServiceContextModule extends }).to((Class) ImagesToYamlImagesFromYamlDescriptor.class); // the yaml config provider bind(YamlImagesFromFileConfig.class); + // the master machines cache bind(new TypeLiteral>() { - }).to((Class) MastersLoadingCache.class); + }).to(MastersLoadingCache.class); + // the master creating function bind(new TypeLiteral>() { }).to((Class) CreateAndInstallVm.class); @@ -150,6 +150,9 @@ public class VirtualBoxComputeServiceContextModule extends }).to((Class) NodeCreator.class); bind(new TypeLiteral>() { }).to((Class) CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.class); + // the jetty server provider + bind(new TypeLiteral() { + }).to((Class) PreseedCfgServer.class).asEagerSingleton(); // for byon bind(new TypeLiteral>() { @@ -162,13 +165,6 @@ public class VirtualBoxComputeServiceContextModule extends bind(LockType.class).toInstance(LockType.Write); } - @Provides - @Singleton - @Preconfiguration - protected LoadingCache preconfiguration(CacheLoader cacheLoader) { - return CacheBuilder.newBuilder().build(cacheLoader); - } - @Provides @Host @Singleton @@ -180,12 +176,6 @@ public class VirtualBoxComputeServiceContextModule extends ImmutableSet. of(new SLF4JLoggingModule(), new SshjSshClientModule())); } - @Provides - @Singleton - protected Server providesJettyServer(@Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl) { - return new Server(URI.create(preconfigurationUrl).getPort()); - } - @Provides @Singleton protected Function, VirtualBoxManager> provideVBox() { @@ -230,7 +220,8 @@ public class VirtualBoxComputeServiceContextModule extends @Override protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { - return template.osFamily(OsFamily.UBUNTU).osVersionMatches("11.04"); + return template.osFamily(VIRTUALBOX_DEFAULT_IMAGE_OS).osVersionMatches(VIRTUALBOX_DEFAULT_IMAGE_VERSION) + .osArchMatches(VIRTUALBOX_DEFAULT_IMAGE_ARCH); } @Provides @@ -248,8 +239,7 @@ public class VirtualBoxComputeServiceContextModule extends @VisibleForTesting public static final Map machineToNodeState = ImmutableMap - . builder() - .put(MachineState.Running, NodeState.RUNNING) + . builder().put(MachineState.Running, NodeState.RUNNING) .put(MachineState.PoweredOff, NodeState.SUSPENDED) .put(MachineState.DeletingSnapshot, NodeState.PENDING) .put(MachineState.DeletingSnapshotOnline, NodeState.PENDING) @@ -261,15 +251,10 @@ public class VirtualBoxComputeServiceContextModule extends .put(MachineState.Stopping, NodeState.PENDING) .put(MachineState.Restoring, NodeState.PENDING) // TODO What to map these states to? - .put(MachineState.FirstOnline, NodeState.PENDING) - .put(MachineState.FirstTransient, NodeState.PENDING) - .put(MachineState.LastOnline, NodeState.PENDING) - .put(MachineState.LastTransient, NodeState.PENDING) - .put(MachineState.Teleported, NodeState.PENDING) - .put(MachineState.TeleportingIn, NodeState.PENDING) - .put(MachineState.TeleportingPausedVM, NodeState.PENDING) - .put(MachineState.Aborted, NodeState.ERROR) - .put(MachineState.Stuck, NodeState.ERROR) - .put(MachineState.Null, NodeState.UNRECOGNIZED).build(); + .put(MachineState.FirstOnline, NodeState.PENDING).put(MachineState.FirstTransient, NodeState.PENDING) + .put(MachineState.LastOnline, NodeState.PENDING).put(MachineState.LastTransient, NodeState.PENDING) + .put(MachineState.Teleported, NodeState.PENDING).put(MachineState.TeleportingIn, NodeState.PENDING) + .put(MachineState.TeleportingPausedVM, NodeState.PENDING).put(MachineState.Aborted, NodeState.ERROR) + .put(MachineState.Stuck, NodeState.ERROR).put(MachineState.Null, NodeState.UNRECOGNIZED).build(); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java index 909297682b..a96fff34c2 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java @@ -21,6 +21,8 @@ package org.jclouds.virtualbox.config; import java.io.File; +import org.jclouds.compute.domain.OsFamily; + /** * Configuration properties used for interacting with VirtualBox instances. * @@ -30,7 +32,7 @@ import java.io.File; public interface VirtualBoxConstants { public static final String VIRTUALBOX_NODE_NAME_SEPARATOR = "-0x0-"; - + public static final String VIRTUALBOX_IMAGE_PREFIX = "jclouds-image" + VIRTUALBOX_NODE_NAME_SEPARATOR; public static final String VIRTUALBOX_NODE_PREFIX = "jclouds-node" + VIRTUALBOX_NODE_NAME_SEPARATOR; @@ -60,6 +62,12 @@ public interface VirtualBoxConstants { public static final String VIRTUALBOX_DEFAULT_DIR = System.getProperty("user.home") + File.separator + ".jclouds-vbox"; + public static final OsFamily VIRTUALBOX_DEFAULT_IMAGE_OS = OsFamily.UBUNTU; + + public static final String VIRTUALBOX_DEFAULT_IMAGE_VERSION = "11.10"; + + public static final String VIRTUALBOX_DEFAULT_IMAGE_ARCH = "x86"; + public static final String VIRTUALBOX_PROVIDER = "virtualbox"; } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/YamlImage.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/YamlImage.java index af4aac4740..37dbb7fc89 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/YamlImage.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/domain/YamlImage.java @@ -139,7 +139,7 @@ public class YamlImage { OsFamily family = parseOsFamilyOrUnrecognized(arg0.os_family); OperatingSystem operatingSystem = OperatingSystem.builder().description(arg0.os_description).family(family) - .version(arg0.os_version).is64Bit(arg0.os_64bit).build(); + .version(arg0.os_version).is64Bit(arg0.os_64bit).arch(arg0.os_arch).build(); return new ImageBuilder().id(arg0.id).name(arg0.name).description(arg0.description) .operatingSystem(operatingSystem).build(); @@ -149,4 +149,15 @@ public class YamlImage { public Image toImage() { return toImage.apply(this); } + + @Override + public String toString() { + return "YamlImage [id=" + id + ", name=" + name + ", description=" + description + ", hostname=" + hostname + + ", location_id=" + location_id + ", os_arch=" + os_arch + ", os_family=" + os_family + + ", os_description=" + os_description + ", os_version=" + os_version + ", iso=" + iso + + ", keystroke_sequence=" + keystroke_sequence + ", preseed_cfg=" + preseed_cfg + ", login_port=" + + login_port + ", os_64bit=" + os_64bit + ", group=" + group + ", tags=" + tags + ", metadata=" + + metadata + ", username=" + username + ", credential=" + credential + ", credential_url=" + + credential_url + ", sudo_password=" + sudo_password + "]"; + } } \ No newline at end of file diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index ad3bc8983f..a848671835 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -21,8 +21,8 @@ package org.jclouds.virtualbox.functions; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.transform; import static org.jclouds.scriptbuilder.domain.Statements.call; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; -import java.net.URI; import java.util.List; import javax.annotation.Resource; @@ -36,7 +36,6 @@ import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import org.jclouds.ssh.SshClient; -import org.jclouds.virtualbox.Preconfiguration; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; import org.jclouds.virtualbox.domain.VmSpec; @@ -49,7 +48,6 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Throwables; -import com.google.common.cache.LoadingCache; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -64,28 +62,28 @@ public class CreateAndInstallVm implements Function { private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists; private final Predicate sshResponds; - private LoadingCache preConfiguration; private final Function sshClientForIMachine; private final MachineUtils machineUtils; private final IMachineToNodeMetadata imachineToNodeMetadata; private final MachineController machineController; private final String version; + private final String preconfigurationUrl; @Inject public CreateAndInstallVm( CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists, IMachineToNodeMetadata imachineToNodeMetadata, Predicate sshResponds, Function sshClientForIMachine, MachineUtils machineUtils, - @Preconfiguration LoadingCache preConfiguration, MachineController machineController, - @Named(Constants.PROPERTY_BUILD_VERSION) String version) { + MachineController machineController, @Named(Constants.PROPERTY_BUILD_VERSION) String version, + @Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl) { this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists; this.sshResponds = sshResponds; this.sshClientForIMachine = sshClientForIMachine; this.machineUtils = machineUtils; - this.preConfiguration = preConfiguration; this.imachineToNodeMetadata = imachineToNodeMetadata; this.machineController = machineController; this.version = Iterables.get(Splitter.on('r').split(version), 0); + this.preconfigurationUrl = preconfigurationUrl; } @Override @@ -100,9 +98,8 @@ public class CreateAndInstallVm implements Function { // Launch machine and wait for it to come online machineController.ensureMachineIsLaunched(vmName); - URI uri = preConfiguration.getUnchecked(isoSpec); String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL", - uri.toASCIIString()); + preconfigurationUrl); configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence); @@ -112,7 +109,7 @@ public class CreateAndInstallVm implements Function { } catch (InterruptedException e) { Throwables.propagate(e); } - + SshClient client = sshClientForIMachine.apply(vm); logger.debug(">> awaiting installation to finish node(%s)", vmName); @@ -127,7 +124,6 @@ public class CreateAndInstallVm implements Function { ExecResponse cleanupResponse = Futures.getUnchecked(execCleanup); checkState(cleanupResponse.getExitStatus() == 0); - logger.debug(">> awaiting installation of guest additions on vm: %s", vmName); ListenableFuture execInstallGA = machineUtils.runScriptOnNode(nodeMetadata, new InstallGuestAdditions(vmSpec, version), RunScriptOptions.NONE); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java index 2c75646c85..ecdc4b8bc3 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java @@ -21,7 +21,7 @@ package org.jclouds.virtualbox.functions; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.*; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR; @@ -54,6 +54,7 @@ import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.domain.YamlImage; +import org.jclouds.virtualbox.functions.admin.PreseedCfgServer; import org.virtualbox_4_1.CleanupMode; import org.virtualbox_4_1.IMachine; import org.virtualbox_4_1.NetworkAttachmentType; @@ -72,7 +73,8 @@ import com.google.common.collect.Maps; /** * A {@link LoadingCache} for masters. If the requested master has been previously created this * returns it, if not it coordinates its creation including downloading isos and creating - * cache/config directories. + * cache/config directories. This also implements {@link Supplier} in order to provide jetty with + * the current image (only one master can be created at a time). * * @author dralves * @@ -94,13 +96,15 @@ public class MastersLoadingCache extends AbstractLoadingCache { private final String workingDir; private final String installationKeySequence; private final String isosDir; - private Supplier manager; - private Function isoDownloader; - private String version; + private final Supplier manager; + private final Function isoDownloader; + private final String version; + private final String preconfigurationUrl; @Inject public MastersLoadingCache(@Named(Constants.PROPERTY_BUILD_VERSION) String version, @Named(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) String installationKeySequence, + @Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl, @Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function masterLoader, Supplier> yamlMapper, Supplier manager, Function isoDownloader) { @@ -118,6 +122,7 @@ public class MastersLoadingCache extends AbstractLoadingCache { } this.version = Iterables.get(Splitter.on('r').split(version), 0); this.isoDownloader = isoDownloader; + this.preconfigurationUrl = preconfigurationUrl; } @PostConstruct @@ -135,11 +140,11 @@ public class MastersLoadingCache extends AbstractLoadingCache { } // the yaml image - YamlImage yamlImage = imageMapping.get(key.getId()); + YamlImage currentImage = imageMapping.get(key.getId()); - checkNotNull(yamlImage, "could not find yaml image for image: " + key); + checkNotNull(currentImage, "could not find yaml image for image: " + key); - checkState(!yamlImage.id.contains(VIRTUALBOX_NODE_NAME_SEPARATOR), "master image names cannot contain \"" + checkState(!currentImage.id.contains(VIRTUALBOX_NODE_NAME_SEPARATOR), "master image names cannot contain \"" + VIRTUALBOX_NODE_NAME_SEPARATOR + "\""); String guestAdditionsFileName = String.format("VBoxGuestAdditions_%s.iso", version); @@ -151,9 +156,9 @@ public class MastersLoadingCache extends AbstractLoadingCache { checkState(new File(guestAdditionsIso).exists(), "guest additions iso does not exist at: " + guestAdditionsIso); // check if the iso is here, download if not - String localIsoUrl = getFilePathOrDownload(yamlImage.iso); + String localIsoUrl = getFilePathOrDownload(currentImage.iso); - String vmName = VIRTUALBOX_IMAGE_PREFIX + yamlImage.id; + String vmName = VIRTUALBOX_IMAGE_PREFIX + currentImage.id; String adminDisk = workingDir + File.separator + vmName + ".vdi"; @@ -163,7 +168,7 @@ public class MastersLoadingCache extends AbstractLoadingCache { StorageController ideController = StorageController.builder().name("IDE Controller").bus(StorageBus.IDE) .attachISO(0, 0, localIsoUrl).attachHardDisk(hardDisk).attachISO(1, 0, guestAdditionsIso).build(); - VmSpec vmSpecification = VmSpec.builder().id(yamlImage.id).name(vmName).memoryMB(512).osTypeId("") + VmSpec vmSpecification = VmSpec.builder().id(currentImage.id).name(vmName).memoryMB(512).osTypeId("") .controller(ideController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) @@ -183,17 +188,24 @@ public class MastersLoadingCache extends AbstractLoadingCache { IMachine masterMachine; - // try and find a master machine in vbox + + // ready the preseed file server + PreseedCfgServer server = new PreseedCfgServer(); try { + // try and find a master machine in vbox masterMachine = manager.get().getVBox().findMachine(vmName); } catch (VBoxException e) { if (machineNotFoundException(e)) { + server.start(preconfigurationUrl,currentImage.preseed_cfg); // create the master machine if it can't be found masterMachine = masterCreatorAndInstaller.apply(masterSpec); } else { throw e; } + } finally { + server.stop(); } + Master master = Master.builder().machine(masterMachine).spec(masterSpec).build(); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java index 5d0b373c80..6bb5b92baf 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/ImagesToYamlImagesFromYamlDescriptor.java @@ -48,7 +48,7 @@ public class ImagesToYamlImagesFromYamlDescriptor implements Supplier yamlDescriptorSupplier*/YamlImagesFromFileConfig yamlDescriptorSupplier) { + public ImagesToYamlImagesFromYamlDescriptor(YamlImagesFromFileConfig yamlDescriptorSupplier) { this.yamlDescriptor = yamlDescriptorSupplier.get(); checkNotNull(yamlDescriptor, "yaml descriptor"); checkState(!yamlDescriptor.equals(""), "yaml descriptor is empty"); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/PreseedCfgServer.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/PreseedCfgServer.java new file mode 100644 index 0000000000..d8ce88e988 --- /dev/null +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/PreseedCfgServer.java @@ -0,0 +1,74 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.jclouds.virtualbox.functions.admin; + +import java.io.IOException; +import java.net.URI; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; + +import com.google.common.base.Throwables; + +/** + * Sets up jetty so that it can serve the preseed.cfg file to automate master creation. + * + * @author Andrea Turli, David Alves + */ +public class PreseedCfgServer { + + private Server jetty; + + public void start(String preconfigurationUrl, final String preseedCfg) { + this.jetty = new Server(URI.create(preconfigurationUrl).getPort()); + try { + // since we're only serving the preseed.cfg file respond to all requests with it + jetty.setHandler(new AbstractHandler() { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, + HttpServletResponse response) throws IOException, ServletException { + response.setContentType("text/plain;charset=utf-8"); + response.setStatus(HttpServletResponse.SC_OK); + baseRequest.setHandled(true); + response.getWriter().println(preseedCfg); + } + }); + jetty.start(); + } catch (Exception e) { + throw Throwables.propagate(e); + } + } + + public void stop() { + try { + if (jetty != null) { + jetty.stop(); + } + } catch (Exception e) { + throw Throwables.propagate(e); + } + } + +} diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunning.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunning.java deleted file mode 100644 index f43f398f05..0000000000 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunning.java +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.jclouds.virtualbox.functions.admin; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.base.Throwables.propagate; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; - -import java.io.IOException; -import java.net.URI; - -import javax.annotation.PreDestroy; -import javax.inject.Inject; -import javax.inject.Named; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.IOUtils; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; -import org.eclipse.jetty.util.resource.Resource; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.logging.Logger; -import org.jclouds.virtualbox.domain.IsoSpec; - -import com.google.common.base.Throwables; -import com.google.common.cache.CacheLoader; -import com.google.inject.Singleton; - -/** - * Sets up jetty so that it can serve the preseed.cfg file to automate master creation. - * - * TODO - Probably we can make this only start jetty. This has not been used to serve isos. - * - * @author Andrea Turli, David Alves - */ -@Singleton -public class StartJettyIfNotAlreadyRunning extends CacheLoader { - - @javax.annotation.Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - private Server jetty; - private final String preconfigurationUrl; - - @Inject - public StartJettyIfNotAlreadyRunning(@Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl, Server jetty) { - this.preconfigurationUrl = preconfigurationUrl; - this.jetty = jetty; - } - - @Override - public URI load(IsoSpec isoSpec) throws Exception { - try { - start(); - } catch (Exception e) { - logger.error("Could not connect to host providing ISO " + isoSpec, e); - propagate(e); - } - return URI.create(preconfigurationUrl); - } - - private void start() { - if (jetty.getState().equals(Server.STARTED)) { - logger.debug("not starting jetty, as existing host is serving %s", preconfigurationUrl); - } else { - try { - - // find the the parent dir inside the jar to serve the file from - - final String preseedFile = IOUtils - .toString(Resource.newSystemResource("preseed.cfg").getURL().openStream()); - - checkState(preseedFile != null); - - // since we're only serving the preseed.cfg file respond to all requests with it - jetty.setHandler(new AbstractHandler() { - - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, - HttpServletResponse response) throws IOException, ServletException { - response.setContentType("text/plain;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - baseRequest.setHandled(true); - response.getWriter().println(preseedFile); - } - - }); - - jetty.start(); - - } catch (Exception e) { - logger.error(e, "Server jetty could not be started for %s", preconfigurationUrl); - throw Throwables.propagate(e); - } - } - } - - @PreDestroy() - public void stop() { - try { - jetty.stop(); - } catch (Exception e) { - logger.error("Could not stop jetty.", e); - } - } - -} diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/DefaultImagePredicate.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/DefaultImagePredicate.java new file mode 100644 index 0000000000..0221274ffc --- /dev/null +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/predicates/DefaultImagePredicate.java @@ -0,0 +1,37 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.virtualbox.predicates; + +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_ARCH; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_OS; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_IMAGE_VERSION; + +import org.jclouds.compute.domain.Image; + +import com.google.common.base.Predicate; + +public class DefaultImagePredicate implements Predicate { + + @Override + public boolean apply(Image input) { + return input.getOperatingSystem().getFamily() == VIRTUALBOX_DEFAULT_IMAGE_OS + && input.getOperatingSystem().getVersion().equals(VIRTUALBOX_DEFAULT_IMAGE_VERSION) + && input.getOperatingSystem().getArch().equals(VIRTUALBOX_DEFAULT_IMAGE_ARCH); + } +} diff --git a/labs/virtualbox/src/main/resources/default-images.yaml b/labs/virtualbox/src/main/resources/default-images.yaml index 7927b93aac..ab990730d9 100644 --- a/labs/virtualbox/src/main/resources/default-images.yaml +++ b/labs/virtualbox/src/main/resources/default-images.yaml @@ -1,5 +1,5 @@ images: - - id: default-ubuntu-11.04-i386 + - id: ubuntu-11.04-i386 name: ubuntu-11.04-server-i386 description: ubuntu 11.04 server (i386) os_arch: x86 @@ -66,3 +66,70 @@ images: # debconf-get-selections --install #Use mirror choose-mirror-bin mirror/http/proxy string + - id: ubuntu-11.10-i386 + name: ubuntu-11.10-server-i386 + description: ubuntu 11.10 server (i386) + os_arch: x86 + os_family: ubuntu + os_description: ubuntu + os_version: 11.10 + iso: http://releases.ubuntu.com/11.10/ubuntu-11.10-server-i386.iso + keystroke_sequence: | + + /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg + debian-installer=en_US auto locale=en_US kbd-chooser/method=us + hostname=vmName + fb=false debconf/frontend=noninteractive + keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false + initrd=/install/initrd.gz -- + preseed_cfg: | + ## Options to set on the command line + d-i debian-installer/locale string en_US.utf8 + d-i console-setup/ask_detect boolean false + d-i console-setup/layout string USA + d-i netcfg/get_hostname string unassigned-hostname + d-i netcfg/get_domain string unassigned-domain + # Continue without a default route + # Not working , specify a dummy in the DHCP + d-i time/zone string UTC + d-i clock-setup/utc-auto boolean true + d-i clock-setup/utc boolean true + d-i kbd-chooser/method select American English + d-i netcfg/wireless_wep string + d-i base-installer/kernel/override-image string linux-server + # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive + d-i debconf debconf/frontend select Noninteractive + d-i pkgsel/install-language-support boolean false + tasksel tasksel/first multiselect standard, ubuntu-server + d-i partman-auto/method string lvm + d-i partman-lvm/confirm boolean true + d-i partman-lvm/device_remove_lvm boolean true + d-i partman-auto/choose_recipe select atomic + d-i partman/confirm_write_new_label boolean true + d-i partman/confirm_nooverwrite boolean true + d-i partman/choose_partition select finish + d-i partman/confirm boolean true + # Write the changes to disks and configure LVM? + d-i partman-lvm/confirm boolean true + d-i partman-lvm/confirm_nooverwrite boolean true + d-i partman-auto-lvm/guided_size string max + ## Default user, we can get away with a recipe to change this + d-i passwd/user-fullname string toor + d-i passwd/username string toor + d-i passwd/user-password password password + d-i passwd/user-password-again password password + d-i user-setup/encrypt-home boolean false + d-i user-setup/allow-password-weak boolean true + # Individual additional packages to install + d-i pkgsel/include string openssh-server ntp + # Whether to upgrade packages after debootstrap. + # Allowed values: none, safe-upgrade, full-upgrade + d-i pkgsel/upgrade select full-upgrade + d-i grub-installer/only_debian boolean true + d-i grub-installer/with_other_os boolean true + d-i finish-install/reboot_in_progress note + #For the update + d-i pkgsel/update-policy select none + # debconf-get-selections --install + #Use mirror + choose-mirror-bin mirror/http/proxy string \ No newline at end of file diff --git a/labs/virtualbox/src/main/resources/preseed.cfg b/labs/virtualbox/src/main/resources/preseed.cfg deleted file mode 100644 index 5a972d1bf4..0000000000 --- a/labs/virtualbox/src/main/resources/preseed.cfg +++ /dev/null @@ -1,88 +0,0 @@ -## Options to set on the command line -d-i debian-installer/locale string en_US.utf8 -d-i console-setup/ask_detect boolean false -d-i console-setup/layout string USA - -#d-i netcfg/get_hostname string dummy -d-i netcfg/get_hostname string unassigned-hostname -d-i netcfg/get_domain string unassigned-domain - -# Continue without a default route -# Not working , specify a dummy in the DHCP -#d-i netcfg/no_default_route boolean - -d-i time/zone string UTC -d-i clock-setup/utc-auto boolean true -d-i clock-setup/utc boolean true - -d-i kbd-chooser/method select American English - -d-i netcfg/wireless_wep string - -d-i base-installer/kernel/override-image string linux-server -#d-i base-installer/kernel/override-image string linux-image-2.6.32-21-generic - -# Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive -d-i debconf debconf/frontend select Noninteractive - -d-i pkgsel/install-language-support boolean false -tasksel tasksel/first multiselect standard, ubuntu-server - -#d-i partman-auto/method string regular -d-i partman-auto/method string lvm -#d-i partman-auto/purge_lvm_from_device boolean true - -d-i partman-lvm/confirm boolean true -d-i partman-lvm/device_remove_lvm boolean true -d-i partman-auto/choose_recipe select atomic - -d-i partman/confirm_write_new_label boolean true -d-i partman/confirm_nooverwrite boolean true -d-i partman/choose_partition select finish -d-i partman/confirm boolean true - -#http://ubuntu-virginia.ubuntuforums.org/showthread.php?p=9626883 -#Message: "write the changes to disk and configure lvm preseed" -#http://serverfault.com/questions/189328/ubuntu-kickstart-installation-using-lvm-waits-for-input -#preseed partman-lvm/confirm_nooverwrite boolean true - -# Write the changes to disks and configure LVM? -d-i partman-lvm/confirm boolean true -d-i partman-lvm/confirm_nooverwrite boolean true -d-i partman-auto-lvm/guided_size string max - -## Default user, we can get away with a recipe to change this -d-i passwd/user-fullname string toor -d-i passwd/username string toor -d-i passwd/user-password password password -d-i passwd/user-password-again password password -d-i user-setup/encrypt-home boolean false -d-i user-setup/allow-password-weak boolean true - -## minimum is puppet and ssh and ntp -# Individual additional packages to install -d-i pkgsel/include string openssh-server ntp -# dkms build-essential module-assistant - -# Whether to upgrade packages after debootstrap. -# Allowed values: none, safe-upgrade, full-upgrade -d-i pkgsel/upgrade select full-upgrade - -d-i grub-installer/only_debian boolean true -d-i grub-installer/with_other_os boolean true -d-i finish-install/reboot_in_progress note - -#For the update -d-i pkgsel/update-policy select none - -# debconf-get-selections --install -#Use mirror -#d-i apt-setup/use_mirror boolean true -#d-i mirror/country string manual -#choose-mirror-bin mirror/protocol string http -#choose-mirror-bin mirror/http/hostname string 192.168.4.150 -#choose-mirror-bin mirror/http/directory string /ubuntu -#choose-mirror-bin mirror/suite select maverick -#d-i debian-installer/allow_unauthenticated string true - -choose-mirror-bin mirror/http/proxy string \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java index 75ab267429..fc6ecf1811 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java @@ -20,10 +20,11 @@ package org.jclouds.virtualbox; import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import java.io.File; -import java.net.URI; +import java.util.Map; import java.util.Properties; import java.util.concurrent.ExecutorService; @@ -52,11 +53,16 @@ import org.jclouds.virtualbox.domain.NetworkInterfaceCard; import org.jclouds.virtualbox.domain.NetworkSpec; import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; +import org.jclouds.virtualbox.domain.YamlImage; import org.jclouds.virtualbox.functions.IMachineToVmSpec; +import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; +import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor; import org.jclouds.virtualbox.functions.admin.UnregisterMachineIfExistsAndDeleteItsMedia; +import org.jclouds.virtualbox.predicates.DefaultImagePredicate; import org.jclouds.virtualbox.util.MachineController; import org.jclouds.virtualbox.util.MachineUtils; import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterSuite; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.virtualbox_4_1.CleanupMode; @@ -83,12 +89,15 @@ import com.google.inject.Module; */ @Test(groups = "live", singleThreaded = true, testName = "BaseVirtualBoxClientLiveTest") public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { + + public static final String DONT_DESTROY_MASTER = "jclouds.virtualbox.keep-test-master"; + public BaseVirtualBoxClientLiveTest() { provider = "virtualbox"; } - + protected ComputeServiceContext context; - + @Inject protected MachineController machineController; @@ -104,11 +113,6 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { @Inject protected MachineUtils machineUtils; - // this will eagerly startup Jetty, note the impl will shut itself down - @Inject - @Preconfiguration - protected LoadingCache preconfigurationUri; - protected String hostVersion; protected String operatingSystemIso; protected String guestAdditionsIso; @@ -122,8 +126,9 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { protected PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate; @Inject protected LoadingCache mastersCache; - - private final ExecutorService singleThreadExec = MoreExecutors.sameThreadExecutor(); + + private final ExecutorService singleThreadExec = MoreExecutors.sameThreadExecutor(); + private String masterVmName; @Override protected void setupCredentials() { @@ -147,16 +152,19 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { context = new ComputeServiceContextFactory().createContext(provider, identity, credential, ImmutableSet . of(new SLF4JLoggingModule(), new SshjSshClientModule(), new ExecutorServiceModule( singleThreadExec, singleThreadExec)), overrides); - + context.utils().injector().injectMembers(this); - imageId = "ubuntu-11.04-server-i386"; + YamlImage image = getDefaultImage(); + + imageId = image.id; + masterVmName = VIRTUALBOX_IMAGE_PREFIX + image.id; isosDir = workingDir + File.separator + "isos"; hostVersion = Iterables.get(Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0); - operatingSystemIso = String.format("%s/%s.iso", isosDir, imageId); + operatingSystemIso = String.format("%s/%s.iso", isosDir, image.name); guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso", isosDir, hostVersion); - + // try and get a master from the cache, this will initialize the config/download isos and // prepare everything IF a master is not available, subsequent calls should be pretty fast Template template = context.getComputeService().templateBuilder().build(); @@ -189,7 +197,8 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { } public MasterSpec getMasterSpecForTest() { - String masterName = "jclouds-image-0x0-default-ubuntu-11.04-i386"; + String masterName = "jclouds-image-0x0-" + imageId; + StorageController ideController = StorageController .builder() .name("IDE Controller") @@ -199,37 +208,45 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest { HardDisk.builder().diskpath(adminDisk(masterName)).controllerPort(0).deviceSlot(1) .autoDelete(true).build()).attachISO(1, 0, guestAdditionsIso).build(); - VmSpec sourceVmSpec = VmSpec.builder().id(masterName).name(masterName) - .osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full) - .controller(ideController).forceOverwrite(true).build(); + VmSpec sourceVmSpec = VmSpec.builder().id(masterName).name(masterName).osTypeId("").memoryMB(512) + .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Injector injector = context.utils().injector(); - Function configProperties = injector - .getInstance(ValueOfConfigurationKeyOrNull.class); - IsoSpec isoSpec = IsoSpec - .builder() - .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply( - VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace( - "HOSTNAME", sourceVmSpec.getVmName())).build(); - - NetworkAdapter networkAdapter = NetworkAdapter.builder() - .networkAttachmentType(NetworkAttachmentType.NAT) - .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard - .builder().addNetworkAdapter(networkAdapter).build(); + Injector injector = context.utils().injector(); + Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); + IsoSpec isoSpec = IsoSpec + .builder() + .sourcePath(operatingSystemIso) + .installationScript( + configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", + sourceVmSpec.getVmName())).build(); - NetworkSpec networkSpec = NetworkSpec.builder() - .addNIC(networkInterfaceCard).build(); - return MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec) - .network(networkSpec).build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) + .build(); + + NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); + return MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec).network(networkSpec).build(); } - + + public static YamlImage getDefaultImage() { + Map images = new ImagesToYamlImagesFromYamlDescriptor(new YamlImagesFromFileConfig( + "/default-images.yaml")).get(); + return images.get(Iterables.getOnlyElement(Iterables.filter(images.keySet(), new DefaultImagePredicate()))); + } + @AfterClass(groups = "live") protected void tearDown() throws Exception { if (context != null) context.close(); } + @AfterSuite + protected void destroyMaster() { + if (System.getProperty(DONT_DESTROY_MASTER) == null + || !Boolean.parseBoolean(System.getProperty(DONT_DESTROY_MASTER))) { + undoVm(masterVmName); + } + } + } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/StartJettyIfNotAlreadyRunningLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/PreseedCfgServerTest.java similarity index 72% rename from labs/virtualbox/src/test/java/org/jclouds/virtualbox/StartJettyIfNotAlreadyRunningLiveTest.java rename to labs/virtualbox/src/test/java/org/jclouds/virtualbox/PreseedCfgServerTest.java index 5a18cbe3eb..2dc1358f7d 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/StartJettyIfNotAlreadyRunningLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/PreseedCfgServerTest.java @@ -25,20 +25,19 @@ import java.net.URL; import java.util.Properties; import org.apache.commons.io.IOUtils; -import org.eclipse.jetty.server.Server; import org.jclouds.virtualbox.config.VirtualBoxConstants; -import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning; +import org.jclouds.virtualbox.functions.admin.PreseedCfgServer; import org.testng.annotations.Test; /** - * Tests that jetty is able to serve the preseed.cfg file. This test is here to have access to the - * defaultProperties() method in {@link VirtualBoxPropertiesBuilder}. + * Tests that jetty is able to serve the preseed.cfg from the provided yaml image. This test is here + * to have access to the defaultProperties() method in {@link VirtualBoxPropertiesBuilder}. * * @author dralves * */ @Test(groups = "live", singleThreaded = true, testName = "StartJettyIfNotAlreadyRunningLiveTest") -public class StartJettyIfNotAlreadyRunningLiveTest { +public class PreseedCfgServerTest { @Test public void testJettyServerServesPreseedFile() throws Exception { @@ -48,15 +47,14 @@ public class StartJettyIfNotAlreadyRunningLiveTest { int port = URI.create(preconfigurationUrl).getPort(); - Server server = new Server(port); + PreseedCfgServer starter = new PreseedCfgServer(); - StartJettyIfNotAlreadyRunning starter = new StartJettyIfNotAlreadyRunning(preconfigurationUrl, server); - - starter.load(null); + starter.start(preconfigurationUrl, BaseVirtualBoxClientLiveTest.getDefaultImage().preseed_cfg); String preseedFileFromJetty = IOUtils.toString(new URL("http://127.0.0.1:" + port + "/preseed.cfg").openStream()); - String preseedFileFromFile = IOUtils - .toString(this.getClass().getClassLoader().getResourceAsStream("preseed.cfg")) + "\n"; + String preseedFileFromFile = BaseVirtualBoxClientLiveTest.getDefaultImage().preseed_cfg + "\n"; assertEquals(preseedFileFromFile, preseedFileFromJetty); + + starter.stop(); } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java index a3d61ba27b..5535b11690 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java @@ -19,6 +19,7 @@ package org.jclouds.virtualbox.compute; +import static junit.framework.Assert.assertTrue; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; import static org.testng.Assert.assertEquals; @@ -42,7 +43,7 @@ import com.google.common.collect.Iterables; public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClientLiveTest { private NodeAndInitialCredentials machine; - + @Inject protected VirtualBoxComputeServiceAdapter adapter; @@ -50,14 +51,14 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien public void testCreatedNodeHasExpectedNameAndWeCanConnectViaSsh() { String group = "foo"; String name = "foo-ef4"; - String machineName = VIRTUALBOX_NODE_PREFIX + "default-ubuntu-11.04-i386-" + "0x0-" + group + "-0x0-" + name; Template template = context.getComputeService().templateBuilder().build(); machine = adapter.createNodeWithGroupEncodedIntoName(group, name, template); - - assertEquals(machine.getNode().getName(), machineName); + assertTrue(machine.getNode().getName().contains(group)); + assertTrue(machine.getNode().getName().contains(name)); + assertTrue(machine.getNode().getName().startsWith(VIRTUALBOX_NODE_PREFIX)); doConnectViaSsh(machine.getNode(), prioritizeCredentialsFromTemplate.apply(template, machine.getCredentials())); } - + protected void doConnectViaSsh(IMachine machine, LoginCredentials creds) { SshClient ssh = context.utils().injector().getInstance(IMachineToSshClient.class).apply(machine); try { @@ -77,14 +78,12 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien public void testListHardwareProfiles() { Iterable profiles = adapter.listHardwareProfiles(); assertEquals(1, Iterables.size(profiles)); - //TODO: check state; } @Test public void testListImages() { Iterable iMageIterable = adapter.listImages(); - assertEquals(1, Iterables.size(iMageIterable)); - //TODO: check state; + assertTrue(!Iterables.isEmpty(iMageIterable)); } @AfterClass diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java index 6415236e77..a13cf5655c 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java @@ -39,6 +39,7 @@ import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.scriptbuilder.statements.login.AdminAccess; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; +import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -51,7 +52,7 @@ import com.google.inject.Module; * @author Adrian Cole */ @Test(groups = "live", singleThreaded = true, testName = "VirtualBoxExperimentLiveTest") -public class VirtualBoxExperimentLiveTest { +public class VirtualBoxExperimentLiveTest extends BaseVirtualBoxClientLiveTest { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) @@ -69,7 +70,8 @@ public class VirtualBoxExperimentLiveTest { public void testLaunchCluster() throws RunNodesException { int numNodes = 2; final String clusterName = "test-launch-cluster"; - Set nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes, TemplateOptions.Builder.runScript(AdminAccess.standard())); + Set nodes = context.getComputeService().createNodesInGroup(clusterName, numNodes, + TemplateOptions.Builder.runScript(AdminAccess.standard())); assertEquals(numNodes, nodes.size(), "wrong number of nodes"); for (NodeMetadata node : nodes) { assertTrue(node.getGroup().equals("test-launch-cluster")); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java index 8998ceb560..42d62ab2c8 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java @@ -19,16 +19,19 @@ package org.jclouds.virtualbox.functions.admin; +import static junit.framework.Assert.assertTrue; import static org.testng.Assert.assertEquals; -import java.io.InputStreamReader; +import java.util.Map; -import org.apache.commons.io.IOUtils; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OsFamily; +import org.jclouds.virtualbox.domain.YamlImage; import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig; +import org.jclouds.virtualbox.predicates.DefaultImagePredicate; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.common.collect.Iterables; @@ -40,22 +43,31 @@ import com.google.common.collect.Iterables; public class ImageFromYamlStringTest { public static final Image TEST1 = new ImageBuilder() - .id("default-ubuntu-11.04-i386") + .id("ubuntu-11.04-i386") .name("ubuntu-11.04-server-i386") .description("ubuntu 11.04 server (i386)") .operatingSystem( - OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("11.04").build()) - .build(); + OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("11.04") + .arch("x86").build()).build(); + + Map images; + + @BeforeMethod + public void setUp() { + images = new ImagesToYamlImagesFromYamlDescriptor(new YamlImagesFromFileConfig("/default-images.yaml")).get(); + } @Test - public void testNodesParse() throws Exception { + public void testNodesParse() { + assertEquals(Iterables.getFirst(images.keySet(), null), TEST1); + } - final StringBuilder yamlFileLines = new StringBuilder(); - for (Object line : IOUtils - .readLines(new InputStreamReader(getClass().getResourceAsStream("/default-images.yaml")))) { - yamlFileLines.append(line).append("\n"); - } - ImagesToYamlImagesFromYamlDescriptor parser = new ImagesToYamlImagesFromYamlDescriptor(new YamlImagesFromFileConfig("/default-images.yaml")); - assertEquals(Iterables.getFirst(parser.get().keySet(), null), TEST1); + @Test + public void testDefaultImagePresent() { + + Iterable defaultImage = Iterables.filter(images.keySet(), new DefaultImagePredicate()); + + assertTrue(!Iterables.isEmpty(defaultImage)); + assertEquals(1, Iterables.size(defaultImage)); } } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunningTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunningTest.java deleted file mode 100644 index 18f798569a..0000000000 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartJettyIfNotAlreadyRunningTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.jclouds.virtualbox.functions.admin; - -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; -import static org.testng.Assert.assertEquals; - -import java.net.URI; - -import org.eclipse.jetty.server.Server; -import org.jclouds.virtualbox.domain.IsoSpec; -import org.testng.annotations.Test; - -/** - * @author Andrea Turli, Adrian Cole - */ -@Test(groups = "unit", singleThreaded = true, testName = "StartJettyIfNotAlreadyRunningTest") -public class StartJettyIfNotAlreadyRunningTest { - @Test - public void testLoadStartsJettyServer() throws Exception { - Server jetty = createMock(Server.class); - - String preconfigurationUrl = "http://foo:8080"; - - expect(jetty.getState()).andReturn(Server.STARTED); - - replay(jetty); - - StartJettyIfNotAlreadyRunning starter = new StartJettyIfNotAlreadyRunning(preconfigurationUrl, jetty); - - IsoSpec isoSpec = IsoSpec.builder() - .sourcePath("/tmp/myisos/ubuntu.iso") - .installationScript("install").build(); - assertEquals(starter.load(isoSpec), URI.create(preconfigurationUrl)); - verify(jetty); - } - - @Test - public void testLaunchJettyServerWhenNotRunningStartsJettyOnCorrectHostPortAndBasedir() { - // TODO: all yours! - } -} diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java index fba1fcd779..007b169ff9 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java @@ -25,7 +25,6 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTA import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest; import org.jclouds.virtualbox.domain.CloneSpec; -import org.jclouds.virtualbox.domain.ExecutionType; import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; import org.jclouds.virtualbox.domain.MasterSpec; @@ -36,7 +35,6 @@ import org.jclouds.virtualbox.domain.StorageController; import org.jclouds.virtualbox.domain.VmSpec; import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists; import org.jclouds.virtualbox.functions.CreateAndInstallVm; -import org.jclouds.virtualbox.functions.LaunchMachineIfNotAlreadyRunning; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; diff --git a/labs/virtualbox/src/test/resources/default-images.yaml b/labs/virtualbox/src/test/resources/default-images.yaml new file mode 100644 index 0000000000..ab2dbe6762 --- /dev/null +++ b/labs/virtualbox/src/test/resources/default-images.yaml @@ -0,0 +1,135 @@ +images: + - id: ubuntu-11.04-i386 + name: ubuntu-11.04-server-i386 + description: ubuntu 11.04 server (i386) + os_arch: x86 + os_family: ubuntu + os_description: ubuntu + os_version: 11.04 + iso: http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso + keystroke_sequence: | + + /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg + debian-installer=en_US auto locale=en_US kbd-chooser/method=us + hostname=vmName + fb=false debconf/frontend=noninteractive + keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false + initrd=/install/initrd.gz -- + preseed_cfg: | + ## Options to set on the command line + d-i debian-installer/locale string en_US.utf8 + d-i console-setup/ask_detect boolean false + d-i console-setup/layout string USA + d-i netcfg/get_hostname string unassigned-hostname + d-i netcfg/get_domain string unassigned-domain + # Continue without a default route + # Not working , specify a dummy in the DHCP + d-i time/zone string UTC + d-i clock-setup/utc-auto boolean true + d-i clock-setup/utc boolean true + d-i kbd-chooser/method select American English + d-i netcfg/wireless_wep string + d-i base-installer/kernel/override-image string linux-server + # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive + d-i debconf debconf/frontend select Noninteractive + d-i pkgsel/install-language-support boolean false + tasksel tasksel/first multiselect standard, ubuntu-server + d-i partman-auto/method string lvm + d-i partman-lvm/confirm boolean true + d-i partman-lvm/device_remove_lvm boolean true + d-i partman-auto/choose_recipe select atomic + d-i partman/confirm_write_new_label boolean true + d-i partman/confirm_nooverwrite boolean true + d-i partman/choose_partition select finish + d-i partman/confirm boolean true + # Write the changes to disks and configure LVM? + d-i partman-lvm/confirm boolean true + d-i partman-lvm/confirm_nooverwrite boolean true + d-i partman-auto-lvm/guided_size string max + ## Default user, we can get away with a recipe to change this + d-i passwd/user-fullname string toor + d-i passwd/username string toor + d-i passwd/user-password password password + d-i passwd/user-password-again password password + d-i user-setup/encrypt-home boolean false + d-i user-setup/allow-password-weak boolean true + # Individual additional packages to install + d-i pkgsel/include string openssh-server ntp + # Whether to upgrade packages after debootstrap. + # Allowed values: none, safe-upgrade, full-upgrade + d-i pkgsel/upgrade select full-upgrade + d-i grub-installer/only_debian boolean true + d-i grub-installer/with_other_os boolean true + d-i finish-install/reboot_in_progress note + #For the update + d-i pkgsel/update-policy select none + # debconf-get-selections --install + #Use mirror + choose-mirror-bin mirror/http/proxy string + - id: test-ubuntu-11.10-i386 + name: ubuntu-11.10-server-i386 + description: ubuntu 11.10 server (i386) + os_arch: x86 + os_family: ubuntu + os_description: ubuntu + os_version: 11.10 + iso: http://releases.ubuntu.com/11.10/ubuntu-11.10-server-i386.iso + keystroke_sequence: | + + /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg + debian-installer=en_US auto locale=en_US kbd-chooser/method=us + hostname=vmName + fb=false debconf/frontend=noninteractive + keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false + initrd=/install/initrd.gz -- + preseed_cfg: | + ## Options to set on the command line + d-i debian-installer/locale string en_US.utf8 + d-i console-setup/ask_detect boolean false + d-i console-setup/layout string USA + d-i netcfg/get_hostname string unassigned-hostname + d-i netcfg/get_domain string unassigned-domain + # Continue without a default route + # Not working , specify a dummy in the DHCP + d-i time/zone string UTC + d-i clock-setup/utc-auto boolean true + d-i clock-setup/utc boolean true + d-i kbd-chooser/method select American English + d-i netcfg/wireless_wep string + d-i base-installer/kernel/override-image string linux-server + # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive + d-i debconf debconf/frontend select Noninteractive + d-i pkgsel/install-language-support boolean false + tasksel tasksel/first multiselect standard, ubuntu-server + d-i partman-auto/method string lvm + d-i partman-lvm/confirm boolean true + d-i partman-lvm/device_remove_lvm boolean true + d-i partman-auto/choose_recipe select atomic + d-i partman/confirm_write_new_label boolean true + d-i partman/confirm_nooverwrite boolean true + d-i partman/choose_partition select finish + d-i partman/confirm boolean true + # Write the changes to disks and configure LVM? + d-i partman-lvm/confirm boolean true + d-i partman-lvm/confirm_nooverwrite boolean true + d-i partman-auto-lvm/guided_size string max + ## Default user, we can get away with a recipe to change this + d-i passwd/user-fullname string toor + d-i passwd/username string toor + d-i passwd/user-password password password + d-i passwd/user-password-again password password + d-i user-setup/encrypt-home boolean false + d-i user-setup/allow-password-weak boolean true + # Individual additional packages to install + d-i pkgsel/include string openssh-server ntp + # Whether to upgrade packages after debootstrap. + # Allowed values: none, safe-upgrade, full-upgrade + d-i pkgsel/upgrade select full-upgrade + d-i grub-installer/only_debian boolean true + d-i grub-installer/with_other_os boolean true + d-i finish-install/reboot_in_progress note + #For the update + d-i pkgsel/update-policy select none + # debconf-get-selections --install + #Use mirror + choose-mirror-bin mirror/http/proxy string \ No newline at end of file