* 'jclouds-vbox' of https://github.com/dralves/jclouds: (24 commits)
  updated readme
  corrected IMachinePredicatesLiveTests that were failing and added workaround for transient function execution failure
  minor error wrt to test group
  got the clone to get networking
  solved a problem running most live tests where the admin disk was the same
  corrected formatting and small bug in CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest
  formatted most changed classes to comply with jclouds formatting guildelines
  removed dangling file
  clones are now booting, but without networking
  clone is created and boots sucessfully. still no network on the clone though
  stuck on adapter problems
  added the possiblity for master machines to survive the jvm. first run creates and installs the master vm subsequent calls fetch the already created master from vm
  adapter creates the master image. cloning next
  sshclien to the master is now workign
  added dependencies
  added a computeservicecontext provider for the vbox host (byon)
  circular dependencies problem with CreateAndInstallVm
  still failing matching the default image to the yaml images
  refactored image from yaml creation
  refactored image from yaml creation
  ...
This commit is contained in:
Adrian Cole 2012-03-06 16:48:35 -08:00
commit d069b0b745
59 changed files with 1808 additions and 1019 deletions

View File

@ -1,3 +1,86 @@
#Enviroment setup
Note: These steps will be automated in the future:
- create a ~/.jclouds-vbox/ directory
- create a ~/.jclouds-vbox/isos directory
- download an ubuntu 11.04 server i386 ISO into "~/.jclouds-vbox/isos" from http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso
- download VirtualBox Guest Additions ISO into "~/.jclouds-vbox/isos" from http://download.virtualbox.org/virtualbox/4.1.8/VBoxGuestAdditions_4.1.8.iso
- copy the following into an images.yaml file to place in"~/.jclouds-vbox/" :
"images:
- id: myTestId
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: |
<Esc><Esc><Enter>
/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 -- <Enter>
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"
** NOTE! **
Make sure you change your VirtualBox preferences to not auto-capture keyboard, and also set host key to none. Otherwise you may accidentally screw-up automated installs.
- Old Notes -
# Administation viewpoint
These steps are usually in charge of cloud provider, in this case it's up to you
@ -37,7 +120,3 @@ and choose the numberOfVirtualMachine you need using -Dtest.virtualbox.numberOfV
These VMs will be cloned starting from the golden template VM created before
It will create a "numberOfVirtualMachine" in a vbox default machine folder with 'VMName_i' name, by cloning the golden template in linked mode with a bridged NIC.
** NOTE! **
Make sure you change your VirtualBox preferences to not auto-capture keyboard, and also set host key to none. Otherwise you may accidentally screw-up automated installs.

View File

@ -19,7 +19,8 @@
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
@ -42,6 +43,8 @@
<test.virtualbox.image-id>ubuntu-11.04-server-i386</test.virtualbox.image-id>
<test.virtualbox.image.login-user>toor:password</test.virtualbox.image.login-user>
<test.virtualbox.image.authenticate-sudo>true</test.virtualbox.image.authenticate-sudo>
<test.virtualbox.image.authenticate-sudo>true</test.virtualbox.image.authenticate-sudo>
<test.virtualbox.image.descriptor.yaml>target/test-classes/testImages.yaml</test.virtualbox.image.descriptor.yaml>
</properties>
<dependencies>
@ -70,6 +73,21 @@
<artifactId>jetty-server</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
@ -84,26 +102,25 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.3.1</version>
<exclusions>
<exclusion>
<artifactId>snakeyaml</artifactId>
<groupId>org.yaml</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
@ -130,6 +147,7 @@
<test.virtualbox.image-id>${test.virtualbox.image-id}</test.virtualbox.image-id>
<test.virtualbox.image.login-user>${test.virtualbox.image.login-user}</test.virtualbox.image.login-user>
<test.virtualbox.image.authenticate-sudo>${test.virtualbox.image.authenticate-sudo}</test.virtualbox.image.authenticate-sudo>
<test.virtualbox.image.descriptor.yaml>${test.virtualbox.image.descriptor.yaml}</test.virtualbox.image.descriptor.yaml>
</systemPropertyVariables>
</configuration>
</execution>
@ -142,7 +160,7 @@
<build>
<plugins>
<plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>

View File

@ -0,0 +1,40 @@
/**
* 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;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Signals the annotated target pertains to the vbox host and not to one of the nodes.
*
* @author dralves
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Host {
}

View File

@ -19,18 +19,23 @@
package org.jclouds.virtualbox;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.*;
import static org.jclouds.Constants.PROPERTY_BUILD_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.jclouds.Constants.PROPERTY_IDENTITY;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_AUTHENTICATE_SUDO;
import static org.jclouds.compute.reference.ComputeServiceConstants.PROPERTY_IMAGE_LOGIN_USER;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.*;
import java.io.File;
import java.util.Properties;
import org.jclouds.PropertiesBuilder;
import static org.jclouds.compute.reference.ComputeServiceConstants.*;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.*;
/**
* Builds properties for VirtualBox integration.
@ -53,32 +58,36 @@ public class VirtualBoxPropertiesBuilder extends PropertiesBuilder {
properties.put(PROPERTY_ENDPOINT, "http://localhost:18083/");
// later version not in maven, yet
properties.put(PROPERTY_API_VERSION, "4.1.4");
properties.put(PROPERTY_BUILD_VERSION, "4.1.8r75467");
properties.put(PROPERTY_IDENTITY, "administrator");
properties.put(PROPERTY_CREDENTIAL, "12345");
properties.put(PROPERTY_IMAGE_ID, "ubuntu-11.04-server-i386");
properties.put(PROPERTY_IMAGE_LOGIN_USER, "toor:password");
properties.put(PROPERTY_IMAGE_AUTHENTICATE_SUDO, "true");
properties.put(VIRTUALBOX_ISO_URL, "http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso");
properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, "<Esc><Esc><Enter> "
+ "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL "
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us "
+ "hostname=" + "HOSTNAME "
+ "debian-installer=en_US auto locale=en_US kbd-chooser/method=us " + "hostname=" + "HOSTNAME "
+ "fb=false debconf/frontend=noninteractive "
+ "keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false "
+ "initrd=/install/initrd.gz -- <Enter>");
properties.put(VIRTUALBOX_WORKINGDIR, System.getProperty("user.home") + File.separator
+ System.getProperty("test.virtualbox.workingDir", "jclouds-virtualbox-test"));
properties.put(
VIRTUALBOX_WORKINGDIR,
System.getProperty("user.home") + File.separator
+ System.getProperty("test.virtualbox.workingDir", ".jclouds-vbox"));
// allow to set the descriptor as a sysprop but default to just setting a default file path.
// The configured supplier
// must be able to handle the chosen option.
properties.put(
VIRTUALBOX_IMAGES_DESCRIPTOR,
System.getProperty("test.virtualbox.image.descriptor.yaml", VIRTUALBOX_DEFAULT_DIR + File.separator
+ "images.yaml"));
properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:8080/src/test/resources/preseed.cfg");
return properties;
}
}

View File

@ -21,8 +21,10 @@ package org.jclouds.virtualbox.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
import java.util.Map;
import javax.inject.Inject;
@ -31,6 +33,9 @@ import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.YamlImage;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
@ -42,14 +47,14 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Singleton;
/**
* Defines the connection between the
* {@link org.virtualbox_4_1.VirtualBoxManager} implementation and the jclouds
* {@link org.jclouds.compute.ComputeService}
* Defines the connection between the {@link org.virtualbox_4_1.VirtualBoxManager} implementation
* and the jclouds {@link org.jclouds.compute.ComputeService}
*
* @author Mattias Holmqvist, Andrea Turli
*/
@ -57,30 +62,39 @@ import com.google.inject.Singleton;
public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IMachine, IMachine, Image, Location> {
private final Supplier<VirtualBoxManager> manager;
private final Function<IMachine, Image> iMachineToImage;
private final Map<Image, YamlImage> images;
private final LoadingCache<Image, Master> mastersLoader;
private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator;
@Inject
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
Function<IMachine, Image> iMachineToImage) {
this.iMachineToImage = iMachineToImage;
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader,
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator) {
this.manager = checkNotNull(manager, "manager");
this.images = imagesMapper.get();
this.mastersLoader = mastersLoader;
this.cloneCreator = cloneCreator;
}
@Override
public NodeAndInitialCredentials<IMachine> createNodeWithGroupEncodedIntoName(String tag, String name,
Template template) {
return null;
Template template) {
try {
Master master = mastersLoader.get(template.getImage());
NodeSpec nodeSpec = NodeSpec.builder().master(master).name(name).tag(tag).template(template).build();
return cloneCreator.apply(nodeSpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Iterable<IMachine> listNodes() {
return Iterables.filter(manager.get().getVBox().getMachines(), new Predicate<IMachine>() {
@Override
public boolean apply(IMachine arg0) {
return !arg0.getName().startsWith(VIRTUALBOX_IMAGE_PREFIX);
return !arg0.getName().startsWith(VIRTUALBOX_NODE_PREFIX);
}
});
}
@ -91,7 +105,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
@Override
public Iterable<Image> listImages() {
return transform(imageMachines(), iMachineToImage);
return images.keySet();
}
private Iterable<IMachine> imageMachines() {
@ -108,7 +122,7 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
@Override
public Iterable<Location> listLocations() {
// Not using the adapter to determine locations
return ImmutableSet.<Location>of();
return ImmutableSet.<Location> of();
}
@Override
@ -181,4 +195,5 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
throw Throwables.propagate(e);
}
}
}

View File

@ -23,6 +23,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECO
import java.io.InputStream;
import java.net.URI;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -31,11 +32,16 @@ import javax.inject.Singleton;
import org.eclipse.jetty.server.Server;
import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule;
import org.jclouds.byon.functions.NodeToNodeMetadata;
import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty;
import org.jclouds.compute.ComputeServiceAdapter;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.HardwareBuilder;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
@ -44,16 +50,30 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.domain.Location;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
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;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.YamlImage;
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
import org.jclouds.virtualbox.functions.IMachineToHardware;
import org.jclouds.virtualbox.functions.IMachineToImage;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
import org.jclouds.virtualbox.functions.IMachineToSshClient;
import org.jclouds.virtualbox.functions.MastersCache;
import org.jclouds.virtualbox.functions.NodeCreator;
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor;
import org.jclouds.virtualbox.functions.admin.StartJettyIfNotAlreadyRunning;
import org.jclouds.virtualbox.functions.admin.StartVBoxIfNotAlreadyRunning;
import org.jclouds.virtualbox.predicates.SshResponds;
@ -72,7 +92,9 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -81,7 +103,7 @@ import com.google.inject.TypeLiteral;
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class VirtualBoxComputeServiceContextModule extends
ComputeServiceAdapterContextModule<Supplier, Supplier, IMachine, IMachine, Image, Location> {
ComputeServiceAdapterContextModule<Supplier, Supplier, IMachine, IMachine, Image, Location> {
public VirtualBoxComputeServiceContextModule() {
super(Supplier.class, Supplier.class);
@ -106,6 +128,24 @@ public class VirtualBoxComputeServiceContextModule extends
}).to((Class) StartJettyIfNotAlreadyRunning.class);
bind(new TypeLiteral<Supplier<VirtualBoxManager>>() {
}).to((Class) StartVBoxIfNotAlreadyRunning.class);
// the yaml config to image mapper
bind(new TypeLiteral<Supplier<Map<Image, YamlImage>>>() {
}).to((Class) ImagesToYamlImagesFromYamlDescriptor.class);
// the yaml config provider
bind(new TypeLiteral<Supplier<String>>() {
}).to((Class) YamlImagesFromFileConfig.class);
// the master machines cache
bind(new TypeLiteral<LoadingCache<Image, Master>>() {
}).to((Class) MastersCache.class);
// the master creating function
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
}).to((Class) CreateAndInstallVm.class);
// the machine cloning function
bind(new TypeLiteral<Function<NodeSpec, NodeAndInitialCredentials<IMachine>>>() {
}).to((Class) NodeCreator.class);
bind(new TypeLiteral<Function<CloneSpec, IMachine>>() {
}).to((Class) CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.class);
// for byon
bind(new TypeLiteral<Function<URI, InputStream>>() {
}).to(SupplyFromProviderURIOrNodesProperty.class);
@ -115,9 +155,8 @@ public class VirtualBoxComputeServiceContextModule extends
bind(ExecutionType.class).toInstance(ExecutionType.GUI);
bind(LockType.class).toInstance(LockType.Write);
}
@Provides
@Singleton
@Preconfiguration
@ -125,6 +164,25 @@ public class VirtualBoxComputeServiceContextModule extends
return CacheBuilder.newBuilder().build(cacheLoader);
}
@Provides
@Host
@Singleton
protected ComputeServiceContext provideHostController() {
String provider = "byon";
String identity = "";
String credential = "";
CacheNodeStoreModule hostModule = new CacheNodeStoreModule(ImmutableMap.of(
"host",
Node.builder().id("host").name("host installing virtualbox").hostname("localhost")
.osFamily(OsFamily.LINUX.toString()).osDescription(System.getProperty("os.name"))
.osVersion(System.getProperty("os.version")).group("ssh")
.username(System.getProperty("user.name"))
.credentialUrl(URI.create("file://" + System.getProperty("user.home") + "/.ssh/id_rsa"))
.build()));
return new ComputeServiceContextFactory().createContext(provider, identity, credential,
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule(), hostModule));
}
@Provides
@Singleton
protected Server providesJettyServer(@Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl) {
@ -141,7 +199,6 @@ public class VirtualBoxComputeServiceContextModule extends
return VirtualBoxManager.createInstance(nodeSupplier.get().getId());
}
@Override
public String toString() {
return "createInstanceByNodeId()";
@ -162,6 +219,12 @@ public class VirtualBoxComputeServiceContextModule extends
return new RetryablePredicate<SshClient>(sshResponds, timeouts.nodeRunning);
}
@Override
protected Supplier provideHardware(ComputeServiceAdapter<IMachine, IMachine, Image, Location> adapter,
Function<IMachine, Hardware> transformer) {
return Suppliers.ofInstance(Collections.singleton(new HardwareBuilder().id("").build()));
}
@Override
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
return template.osFamily(OsFamily.UBUNTU).osVersionMatches("11.04");
@ -170,7 +233,7 @@ public class VirtualBoxComputeServiceContextModule extends
@Provides
@Singleton
protected Supplier<NodeMetadata> host(Supplier<LoadingCache<String, Node>> nodes, NodeToNodeMetadata converter)
throws ExecutionException {
throws ExecutionException {
return Suppliers.compose(Functions.compose(converter, new Function<LoadingCache<String, Node>, Node>() {
@Override
@ -182,22 +245,24 @@ public class VirtualBoxComputeServiceContextModule extends
@VisibleForTesting
public static final Map<MachineState, NodeState> machineToNodeState = ImmutableMap
.<MachineState, NodeState>builder().put(MachineState.Running, NodeState.RUNNING).put(
MachineState.PoweredOff, NodeState.SUSPENDED)
.put(MachineState.DeletingSnapshot, NodeState.PENDING).put(MachineState.DeletingSnapshotOnline,
NodeState.PENDING).put(MachineState.DeletingSnapshotPaused, NodeState.PENDING).put(
MachineState.FaultTolerantSyncing, NodeState.PENDING).put(MachineState.LiveSnapshotting,
NodeState.PENDING).put(MachineState.SettingUp, NodeState.PENDING).put(MachineState.Starting,
NodeState.PENDING).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)
.<MachineState, NodeState> builder().put(MachineState.Running, NodeState.RUNNING)
.put(MachineState.PoweredOff, NodeState.SUSPENDED)
.put(MachineState.DeletingSnapshot, NodeState.PENDING)
.put(MachineState.DeletingSnapshotOnline, NodeState.PENDING)
.put(MachineState.DeletingSnapshotPaused, NodeState.PENDING)
.put(MachineState.FaultTolerantSyncing, NodeState.PENDING)
.put(MachineState.LiveSnapshotting, NodeState.PENDING)
.put(MachineState.SettingUp, NodeState.PENDING)
.put(MachineState.Starting, NodeState.PENDING)
.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.Aborted, NodeState.ERROR).put(MachineState.Stuck, NodeState.ERROR)
.put(MachineState.Null, NodeState.UNRECOGNIZED).build();
.put(MachineState.Null, NodeState.UNRECOGNIZED).build();
}

View File

@ -19,6 +19,8 @@
package org.jclouds.virtualbox.config;
import java.io.File;
/**
* Configuration properties used for interacting with VirtualBox instances.
*
@ -29,13 +31,15 @@ public interface VirtualBoxConstants {
public static final String VIRTUALBOX_IMAGE_PREFIX = "jclouds-image-";
public static final String VIRTUALBOX_NODE_PREFIX = "jclouds-node-";
public static final String VIRTUALBOX_PRECONFIGURATION_URL = "jclouds.virtualbox.preconfigurationurl";
public static final String VIRTUALBOX_INSTALLATION_KEY_SEQUENCE = "jclouds.virtualbox.installationkeysequence";
public static final String VIRTUALBOX_WORKINGDIR = "jclouds.virtualbox.workingdir";
public static final String VIRTUALBOX_ISO_URL = "jclouds.virtualbox.isourl";
public static final String VIRTUALBOX_IMAGES_DESCRIPTOR = "jclouds.virtualbox.image.descriptor.yaml";
public static final String VIRTUALBOX_MACHINE_GROUP = "jclouds.virtualbox.machinegroup";
@ -51,4 +55,9 @@ public interface VirtualBoxConstants {
public static final String VIRTUALBOX_WEBSERVER_CREDENTIAL = "jclouds.virtualbox.webserver.credential";
public static final String VIRTUALBOX_DEFAULT_DIR = System.getProperty("user.home") + File.separator
+ ".jclouds-vbox";
public static final String VIRTUALBOX_PROVIDER = "virtualbox";
}

View File

@ -19,18 +19,22 @@
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import org.virtualbox_4_1.IMachine;
import com.google.common.base.Objects;
/**
* A complete specification of a "clone" node with networking setup
* and the physical machine specification.
* A complete specification of a "clone" node with networking setup and the physical machine
* specification.
*/
public class CloneSpec {
private final VmSpec vmSpec;
private final NetworkSpec networkSpec;
private final IMachine master;
private final boolean isLinked;
public static Builder builder() {
return new Builder();
@ -40,6 +44,8 @@ public class CloneSpec {
private VmSpec vmSpec;
private NetworkSpec networkSpec;
private IMachine master;
private boolean isLinked;
public Builder vm(VmSpec vmSpec) {
this.vmSpec = vmSpec;
@ -51,17 +57,30 @@ public class CloneSpec {
return this;
}
public Builder master(IMachine master) {
this.master = master;
return this;
}
public Builder linked(boolean isLinked) {
this.isLinked = isLinked;
return this;
}
public CloneSpec build() {
return new CloneSpec(vmSpec, networkSpec);
return new CloneSpec(vmSpec, networkSpec, master, isLinked);
}
}
public CloneSpec(VmSpec vmSpec, NetworkSpec networkSpec) {
public CloneSpec(VmSpec vmSpec, NetworkSpec networkSpec, IMachine master, boolean isLinked) {
checkNotNull(vmSpec, "vmSpec");
checkNotNull(networkSpec, "networkSpec");
checkNotNull(master, "master");
this.vmSpec = vmSpec;
this.networkSpec = networkSpec;
this.master = master;
this.isLinked = isLinked;
}
public VmSpec getVmSpec() {
@ -72,27 +91,32 @@ public class CloneSpec {
return networkSpec;
}
public IMachine getMaster() {
return master;
}
public boolean isLinked() {
return isLinked;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (this == o)
return true;
if (o instanceof VmSpec) {
CloneSpec other = (CloneSpec) o;
return Objects.equal(vmSpec, other.vmSpec) &&
Objects.equal(networkSpec, other.networkSpec);
return Objects.equal(vmSpec, other.vmSpec) && Objects.equal(networkSpec, other.networkSpec);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(vmSpec,networkSpec);
return Objects.hashCode(vmSpec, networkSpec);
}
@Override
public String toString() {
return "IMachineSpec{" +
"vmSpec= " + vmSpec +
", networkSpec= " + networkSpec +
'}';
return "IMachineSpec{" + "vmSpec= " + vmSpec + ", networkSpec= " + networkSpec + '}';
}
}

View File

@ -19,10 +19,11 @@
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import org.virtualbox_4_1.DeviceType;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
/**
* Represents a specification for a device attachment.

View File

@ -18,10 +18,10 @@
*/
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
/**
* Represents an optical medium (DVD) in a VirtualBox VM.
* <p/>

View File

@ -0,0 +1,67 @@
/**
* 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.domain;
import org.virtualbox_4_1.IMachine;
public class Master {
private final IMachine machine;
private final MasterSpec spec;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private IMachine machine;
private MasterSpec spec;
public Builder machine(IMachine machine) {
this.machine = machine;
return this;
}
public Builder spec(MasterSpec spec) {
this.spec = spec;
return this;
}
public Master build() {
return new Master(machine, spec);
}
}
private Master(IMachine machine, MasterSpec spec) {
super();
this.machine = machine;
this.spec = spec;
}
public IMachine getMachine() {
return machine;
}
public MasterSpec getSpec() {
return spec;
}
}

View File

@ -19,13 +19,13 @@
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
/**
* A complete specification of a "master" node, including the ISO, networking setup
* and the physical machine specification.
* A complete specification of a "master" node, including the ISO, networking setup and the physical
* machine specification.
*/
public class MasterSpec {
@ -64,7 +64,7 @@ public class MasterSpec {
}
public MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec) {
private MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec) {
checkNotNull(vmSpec, "vmSpec");
checkNotNull(isoSpec, "isoSpec");
checkNotNull(networkSpec, "networkSpec");
@ -87,27 +87,23 @@ public class MasterSpec {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (this == o)
return true;
if (o instanceof VmSpec) {
MasterSpec other = (MasterSpec) o;
return Objects.equal(vmSpec, other.vmSpec) &&
Objects.equal(isoSpec, other.isoSpec) &&
Objects.equal(networkSpec, other.networkSpec);
return Objects.equal(vmSpec, other.vmSpec) && Objects.equal(isoSpec, other.isoSpec)
&& Objects.equal(networkSpec, other.networkSpec);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(vmSpec,isoSpec,networkSpec);
return Objects.hashCode(vmSpec, isoSpec, networkSpec);
}
@Override
public String toString() {
return "IMachineSpec{" +
"vmSpec=" + vmSpec +
", isoSpec=" + isoSpec +
", networkSpec=" + networkSpec +
'}';
return "IMachineSpec{" + "vmSpec=" + vmSpec + ", isoSpec=" + isoSpec + ", networkSpec=" + networkSpec + '}';
}
}

View File

@ -19,14 +19,15 @@
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import com.google.common.collect.Sets;
import org.virtualbox_4_1.NATProtocol;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import org.virtualbox_4_1.NATProtocol;
import com.google.common.base.Objects;
import com.google.common.collect.Sets;
/**
* Represents a NAT network adapter in VirtualBox.

View File

@ -27,6 +27,7 @@ import java.util.List;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
/**
* Describes the network configuration for a VirtualBox machine.
*/

View File

@ -0,0 +1,92 @@
/**
* 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.domain;
import org.jclouds.compute.domain.Template;
public class NodeSpec {
private final Master master;
private final String name;
private final String tag;
private final Template template;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private Master master;
private String name;
private String tag;
private Template template;
public Builder master(Master master) {
this.master = master;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder tag(String tag) {
this.tag = tag;
return this;
}
public Builder template(Template template) {
this.template = template;
return this;
}
public NodeSpec build() {
return new NodeSpec(master, name, tag, template);
}
}
private NodeSpec(Master master, String name, String tag, Template template) {
super();
this.master = master;
this.name = name;
this.tag = tag;
this.template = template;
}
public Master getMaster() {
return master;
}
public String getName() {
return name;
}
public String getTag() {
return tag;
}
public Template getTemplate() {
return template;
}
}

View File

@ -18,10 +18,11 @@
*/
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
import org.virtualbox_4_1.NATProtocol;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
/**
* @author Mattias Holmqvist

View File

@ -18,14 +18,17 @@
*/
package org.jclouds.virtualbox.domain;
import com.google.common.base.Objects;
import org.virtualbox_4_1.CleanupMode;
import java.util.*;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.virtualbox_4_1.CleanupMode;
import com.google.common.base.Objects;
/**
* A description of a Virtual Machine in VirtualBox.
*/
@ -39,7 +42,8 @@ public class VmSpec {
private final Set<StorageController> controllers;
private final CleanupMode cleanupMode;
public VmSpec(String vmId, String vmName, String osTypeId, long memory, boolean forceOverwrite, Set<StorageController> controllers, CleanupMode cleanupMode) {
public VmSpec(String vmId, String vmName, String osTypeId, long memory, boolean forceOverwrite,
Set<StorageController> controllers, CleanupMode cleanupMode) {
this.vmId = checkNotNull(vmId, "vmId");
this.vmName = checkNotNull(vmName, "vmName");
this.osTypeId = checkNotNull(osTypeId, "osTypeId");
@ -61,7 +65,7 @@ public class VmSpec {
private String name;
private String id;
private String osTypeId = "";
private boolean forceOverwrite;
private boolean forceOverwrite = true;
private long memory;
private CleanupMode cleanUpMode;
@ -138,16 +142,14 @@ public class VmSpec {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (this == o)
return true;
if (o instanceof VmSpec) {
VmSpec other = (VmSpec) o;
return Objects.equal(vmId, other.vmId) &&
Objects.equal(vmName, other.vmName) &&
Objects.equal(osTypeId, other.osTypeId) &&
Objects.equal(memory, other.memory) &&
Objects.equal(forceOverwrite, other.forceOverwrite) &&
Objects.equal(controllers, other.controllers) &&
Objects.equal(cleanupMode, other.cleanupMode);
return Objects.equal(vmId, other.vmId) && Objects.equal(vmName, other.vmName)
&& Objects.equal(osTypeId, other.osTypeId) && Objects.equal(memory, other.memory)
&& Objects.equal(forceOverwrite, other.forceOverwrite)
&& Objects.equal(controllers, other.controllers) && Objects.equal(cleanupMode, other.cleanupMode);
}
return false;
}
@ -159,14 +161,8 @@ public class VmSpec {
@Override
public String toString() {
return "VmSpecification{" +
"vmName='" + vmName + '\'' +
", osTypeId='" + osTypeId + '\'' +
", memory='" + memory + '\'' +
", vmId='" + vmId + '\'' +
", forceOverwrite=" + forceOverwrite +
", controllers=" + controllers +
", cleanupMode=" + cleanupMode +
'}';
return "VmSpecification{" + "vmName='" + vmName + '\'' + ", osTypeId='" + osTypeId + '\'' + ", memory='" + memory
+ '\'' + ", vmId='" + vmId + '\'' + ", forceOverwrite=" + forceOverwrite + ", controllers="
+ controllers + ", cleanupMode=" + cleanupMode + '}';
}
}

View File

@ -139,10 +139,10 @@ 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).build();
return new ImageBuilder().id(arg0.id).name(arg0.name).description(arg0.description)
.operatingSystem(operatingSystem).build();
.operatingSystem(operatingSystem).build();
}
};

View File

@ -61,5 +61,5 @@ public class AttachNicToMachine implements Function<NetworkInterfaceCard, Void>
private boolean hasBridgedAdapter(NetworkInterfaceCard nic) {
return nic.getNetworkAdapter().getNetworkAttachmentType()
.equals(NetworkAttachmentType.Bridged);
}
}
}

View File

@ -22,7 +22,6 @@ package org.jclouds.virtualbox.functions;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Named;
@ -31,6 +30,7 @@ import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.CloneMode;
@ -46,98 +46,81 @@ import com.google.common.base.Supplier;
import com.google.inject.Inject;
/**
* CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the
* followings: - cloning the master - register the clone machine -
* CloneAndRegisterMachineFromIMachineIfNotAlreadyExists will take care of the followings: - cloning
* the master - register the clone machine -
*
* @author Andrea Turli
*/
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
Function<IMachine, IMachine> {
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements Function<CloneSpec, IMachine> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<VirtualBoxManager> manager;
private final String workingDir;
private final CloneSpec cloneSpec;
private final boolean isLinkedClone;
private final MachineUtils machineUtils;
@Inject
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
Supplier<VirtualBoxManager> manager,
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir,
CloneSpec cloneSpec, boolean isLinkedClone, MachineUtils machineUtils) {
this.manager = manager;
this.workingDir = workingDir;
this.cloneSpec = cloneSpec;
this.isLinkedClone = isLinkedClone;
this.machineUtils = machineUtils;
}
private final Supplier<VirtualBoxManager> manager;
private final String workingDir;
private final MachineUtils machineUtils;
@Override
public IMachine apply(@Nullable IMachine master) {
VmSpec vmSpec = cloneSpec.getVmSpec();
try {
manager.get().getVBox().findMachine(vmSpec.getVmName());
throw new IllegalStateException("Machine " + vmSpec.getVmName()
+ " is already registered.");
} catch (VBoxException e) {
if (machineNotFoundException(e))
return cloneMachine(vmSpec, master);
else
throw e;
}
}
@Inject
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(Supplier<VirtualBoxManager> manager,
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir, MachineUtils machineUtils) {
this.manager = manager;
this.workingDir = workingDir;
this.machineUtils = machineUtils;
}
private boolean machineNotFoundException(VBoxException e) {
return e.getMessage().contains(
"VirtualBox error: Could not find a registered machine named ")
|| e.getMessage().contains(
"Could not find a registered machine with UUID {");
}
@Override
public IMachine apply(CloneSpec cloneSpec) {
VmSpec vmSpec = cloneSpec.getVmSpec();
try {
manager.get().getVBox().findMachine(vmSpec.getVmName());
throw new IllegalStateException("Machine " + vmSpec.getVmName() + " is already registered.");
} catch (VBoxException e) {
if (machineNotFoundException(e))
return cloneMachine(cloneSpec);
else
throw e;
}
}
private IMachine cloneMachine(VmSpec vmSpec, IMachine master) {
String settingsFile = manager.get().getVBox()
.composeMachineFilename(vmSpec.getVmName(), workingDir);
IMachine clonedMachine = manager
.get()
.getVBox()
.createMachine(settingsFile, vmSpec.getVmName(),
vmSpec.getOsTypeId(), vmSpec.getVmId(),
vmSpec.isForceOverwrite());
List<CloneOptions> options = new ArrayList<CloneOptions>();
if (isLinkedClone)
options.add(CloneOptions.Link);
private boolean machineNotFoundException(VBoxException e) {
return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ")
|| e.getMessage().contains("Could not find a registered machine with UUID {");
}
// TODO snapshot name
ISnapshot currentSnapshot = new TakeSnapshotIfNotAlreadyAttached(
manager, "snapshotName", "snapshotDesc").apply(master);
private IMachine cloneMachine(CloneSpec cloneSpec) {
VmSpec vmSpec = cloneSpec.getVmSpec();
NetworkSpec networkSpec = cloneSpec.getNetworkSpec();
boolean isLinkedClone = cloneSpec.isLinked();
IMachine master = cloneSpec.getMaster();
String settingsFile = manager.get().getVBox().composeMachineFilename(vmSpec.getVmName(), workingDir);
IMachine clonedMachine = manager
.get()
.getVBox()
.createMachine(settingsFile, vmSpec.getVmName(), vmSpec.getOsTypeId(), vmSpec.getVmId(),
vmSpec.isForceOverwrite());
List<CloneOptions> options = new ArrayList<CloneOptions>();
if (isLinkedClone)
options.add(CloneOptions.Link);
// clone
IProgress progress = currentSnapshot.getMachine().cloneTo(
clonedMachine, CloneMode.MachineState, options);
// TODO snapshot name
ISnapshot currentSnapshot = new TakeSnapshotIfNotAlreadyAttached(manager, "snapshotName", "snapshotDesc")
.apply(master);
if (progress.getCompleted())
logger.debug("clone done");
// clone
IProgress progress = currentSnapshot.getMachine().cloneTo(clonedMachine, CloneMode.MachineState, options);
progress.waitForCompletion(-1);
logger.debug("clone done");
// registering
manager.get().getVBox().registerMachine(clonedMachine);
// registering
manager.get().getVBox().registerMachine(clonedMachine);
// Bridged#
for (NetworkInterfaceCard nic : cloneSpec.getNetworkSpec().getNetworkInterfaceCards()){
ensureBridgedNetworkingIsAppliedToMachine(clonedMachine.getName(), nic);
}
return clonedMachine;
}
// Networking
for (NetworkInterfaceCard networkInterfaceCard : networkSpec.getNetworkInterfaceCards()) {
new AttachNicToMachine(vmSpec.getVmName(), machineUtils).apply(networkInterfaceCard);
}
private void ensureBridgedNetworkingIsAppliedToMachine(String vmName,
NetworkInterfaceCard nic) {
machineUtils.writeLockMachineAndApply(vmName,
new AttachBridgedAdapterToMachine(nic));
}
return clonedMachine;
}
}

View File

@ -29,8 +29,8 @@ import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
@ -53,7 +53,6 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -65,26 +64,24 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ComputeServiceContext context;
private final Supplier<VirtualBoxManager> manager;
private final CreateAndRegisterMachineFromIsoIfNotAlreadyExists createAndRegisterMachineFromIsoIfNotAlreadyExists;
private final GuestAdditionsInstaller guestAdditionsInstaller;
private final Predicate<SshClient> sshResponds;
private final ExecutionType executionType;
private LoadingCache<IsoSpec, URI> preConfiguration;
private final Function<IMachine, SshClient> sshClientForIMachine;
private final MachineUtils machineUtils;
private final IMachineToNodeMetadata imachineToNodeMetadata;
@Inject
public CreateAndInstallVm(ComputeServiceContext context, Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
Predicate<SshClient> sshResponds, Function<IMachine, SshClient> sshClientForIMachine,
ExecutionType executionType, MachineUtils machineUtils, @Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration) {
this.context = context;
public CreateAndInstallVm(Supplier<VirtualBoxManager> manager,
CreateAndRegisterMachineFromIsoIfNotAlreadyExists CreateAndRegisterMachineFromIsoIfNotAlreadyExists,
GuestAdditionsInstaller guestAdditionsInstaller, IMachineToNodeMetadata imachineToNodeMetadata,
Predicate<SshClient> sshResponds, Function<IMachine, SshClient> sshClientForIMachine,
ExecutionType executionType, MachineUtils machineUtils,
@Preconfiguration LoadingCache<IsoSpec, URI> preConfiguration) {
this.manager = manager;
this.createAndRegisterMachineFromIsoIfNotAlreadyExists = CreateAndRegisterMachineFromIsoIfNotAlreadyExists;
this.sshResponds = sshResponds;
@ -92,47 +89,57 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
this.executionType = executionType;
this.machineUtils = machineUtils;
this.preConfiguration = preConfiguration;
this.guestAdditionsInstaller = guestAdditionsInstaller;
this.imachineToNodeMetadata = imachineToNodeMetadata;
}
@Override
public IMachine apply(MasterSpec masterSpec) {
VmSpec vmSpec = masterSpec.getVmSpec();
IsoSpec isoSpec = masterSpec.getIsoSpec();
String vmName = vmSpec.getVmName();
final IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
IMachine vm = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec);
// Launch machine and wait for it to come online
ensureMachineIsLaunched(vmName);
URI uri = preConfiguration.getUnchecked(isoSpec);
String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL",
uri.toASCIIString());
uri.toASCIIString());
configureOsInstallationWithKeyboardSequence(vmName, installationKeySequence);
SshClient client = sshClientForIMachine.apply(vm);
logger.debug(">> awaiting installation to finish node(%s)", vmName);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh", vmName);
logger.debug(">> awaiting installation of guest additions on vm: %s", vmName);
checkState(new GuestAdditionsInstaller(context).apply(vmName));
checkState(guestAdditionsInstaller.apply(vm));
logger.debug(">> awaiting post-installation actions on vm: %s", vmName);
ListenableFuture<ExecResponse> execFuture = context.getComputeService().submitScriptOnNode(vmName,
call("cleanupUdevIfNeeded"), RunScriptOptions.NONE);
ExecResponse execResponse = Futures.getUnchecked(execFuture);
checkState(execResponse.getExitCode() == 0);
NodeMetadata vmMetadata = imachineToNodeMetadata.apply(vm);
// TODO for now this is executed on installModuleAssistantIfNeeded as a workaround to some transient execution issue.
// ListenableFuture<ExecResponse> execFuture = machineUtils.runScriptOnNode(vmMetadata, call("cleanupUdevIfNeeded"),
// RunScriptOptions.NONE);
// ExecResponse execResponse = Futures.getUnchecked(execFuture);
// checkState(execResponse.getExitCode() == 0);
logger.debug("<< installation of image complete. Powering down node(%s)", vmName);
ensureMachineHasPowerDown(vmName);
return vm;
}
private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) {
Iterable<List<Integer>> scancodelist =
transform(Splitter.on(" ").split(installationKeySequence), new StringToKeyCode());
Iterable<List<Integer>> scancodelist = transform(Splitter.on(" ").split(installationKeySequence),
new StringToKeyCode());
for (List<Integer> scancodes : scancodelist) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new SendScancodes(scancodes));
@ -140,26 +147,34 @@ public class CreateAndInstallVm implements Function<MasterSpec, IMachine> {
}
/**
* ensureMachineHasPowerDown needs to have this delay just to ensure that the machine is completely powered off
* ensureMachineHasPowerDown needs to have this delay just to ensure that the machine is
* completely powered off
*
* @param vmName
*/
private void ensureMachineHasPowerDown(String vmName) {
while(!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
} catch (RuntimeException e) {
// sometimes the machine might be powered of between the while test and the call to
// lockSessionOnMachineAndApply
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
return;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
continue;
} else {
throw e;
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Throwables.propagate(e);
}
}
}
}
private void ensureMachineIsLaunched(String vmName) {

View File

@ -20,6 +20,7 @@
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
import java.io.File;
import java.util.Set;
@ -69,8 +70,8 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
private final String workingDir;
@Inject
public CreateAndRegisterMachineFromIsoIfNotAlreadyExists(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils,
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir) {
public CreateAndRegisterMachineFromIsoIfNotAlreadyExists(Supplier<VirtualBoxManager> manager,
MachineUtils machineUtils, @Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir) {
this.manager = manager;
this.machineUtils = machineUtils;
this.workingDir = workingDir;
@ -93,11 +94,6 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
}
}
private boolean machineNotFoundException(VBoxException e) {
return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ") ||
e.getMessage().contains("Could not find a registered machine with UUID {");
}
private IMachine createMachine(IVirtualBox vBox, MasterSpec machineSpec) {
VmSpec vmSpec = machineSpec.getVmSpec();
String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir);
@ -128,7 +124,7 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
// Networking
for (NetworkInterfaceCard networkInterfaceCard : networkSpec.getNetworkInterfaceCards()) {
new AttachNicToMachine(vmName, machineUtils).apply(networkInterfaceCard);
new AttachNicToMachine(vmName, machineUtils).apply(networkInterfaceCard);
}
}
@ -136,22 +132,21 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
Set<IsoImage> dvds = controller.getIsoImages();
for (IsoImage dvd : dvds) {
String dvdSource = dvd.getSourcePath();
final IMedium dvdMedium = manager.get().getVBox().openMedium(dvdSource, DeviceType.DVD, AccessMode.ReadOnly,
vmSpecification.isForceOverwrite());
final IMedium dvdMedium = manager.get().getVBox()
.openMedium(dvdSource, DeviceType.DVD, AccessMode.ReadOnly, vmSpecification.isForceOverwrite());
ensureMachineDevicesAttached(vmName, dvdMedium, dvd.getDeviceDetails(), controller.getName());
}
}
private void ensureMachineDevicesAttached(String vmName, IMedium medium, DeviceDetails deviceDetails,
String controllerName) {
machineUtils.writeLockMachineAndApply(vmName, new AttachMediumToMachineIfNotAlreadyAttached(deviceDetails, medium,
controllerName));
machineUtils.writeLockMachineAndApply(vmName, new AttachMediumToMachineIfNotAlreadyAttached(deviceDetails,
medium, controllerName));
}
private String missingIDEControllersMessage(VmSpec vmSpecification) {
return String
.format(
"First controller is not an IDE controller. Please verify that the VM spec is a correct master node: %s",
.format("First controller is not an IDE controller. Please verify that the VM spec is a correct master node: %s",
vmSpecification);
}
@ -175,7 +170,7 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
}
public void ensureMachineHasStorageControllerNamed(String vmName, StorageController storageController) {
machineUtils.writeLockMachineAndApply(vmName, new AddIDEControllerIfNotExists(checkNotNull(
storageController, "storageController")));
machineUtils.writeLockMachineAndApply(vmName,
new AddIDEControllerIfNotExists(checkNotNull(storageController, "storageController")));
}
}

View File

@ -61,9 +61,10 @@ public class IMachineToImage implements Function<IMachine, Image> {
OsFamily family = parseOsFamilyOrUnrecognized(guestOSType.getDescription());
String version = parseVersionOrReturnEmptyString(family, guestOSType.getDescription(), osVersionMap);
OperatingSystem os = OperatingSystem.builder().description(guestOSType.getDescription()).family(family)
.version(version).is64Bit(guestOSType.getIs64Bit()).build();
.version(version).is64Bit(guestOSType.getIs64Bit()).build();
return new ImageBuilder().id("" + from.getId()).description(from.getDescription()).operatingSystem(os).build();
return new ImageBuilder().id("" + from.getId()).name(from.getName()).description(from.getDescription())
.operatingSystem(os).build();
}
}

View File

@ -18,11 +18,15 @@
*/
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
import org.jclouds.ssh.SshClient;
import org.virtualbox_4_1.IMachine;
@ -35,6 +39,11 @@ import com.google.inject.Inject;
@Singleton
public class IMachineToSshClient implements Function<IMachine, SshClient> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final SshClient.Factory sshClientFactory;
@Inject
@ -44,9 +53,10 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
@Override
public SshClient apply(final IMachine vm) {
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0l);
INetworkAdapter networkAdapter = vm.getNetworkAdapter(0L);
SshClient client = null;
checkState(networkAdapter != null);
checkNotNull(networkAdapter);
for (String nameProtocolnumberAddressInboudportGuestTargetport : networkAdapter.getNatDriver().getRedirects()) {
Iterable<String> stuff = Splitter.on(',').split(nameProtocolnumberAddressInboudportGuestTargetport);
String protocolNumber = Iterables.get(stuff, 1);
@ -56,10 +66,11 @@ public class IMachineToSshClient implements Function<IMachine, SshClient> {
// TODO: we need a way to align the default login credentials from the iso with the
// vmspec
if ("1".equals(protocolNumber) && "22".equals(targetPort)) {
client = sshClientFactory.create(new IPSocket(hostAddress, Integer.parseInt(inboundPort)),
LoginCredentials.builder().user("toor").password("password").authenticateSudo(true).build());
client = sshClientFactory.create(new IPSocket(hostAddress, Integer.parseInt(inboundPort)), LoginCredentials
.builder().user("toor").password("password").authenticateSudo(true).build());
}
}
checkNotNull(client);
return client;
}
}

View File

@ -58,13 +58,10 @@ public class IMachineToVmSpec implements Function<IMachine, VmSpec> {
// TODO some parameters are predefined cause the IMachine doesn't have the
// concept i.e.: cleanUpMode
org.jclouds.virtualbox.domain.VmSpec.Builder vmSpecBuilder = VmSpec
.builder();
org.jclouds.virtualbox.domain.VmSpec.Builder vmSpecBuilder = VmSpec.builder();
vmSpecBuilder.id(machine.getId()).name(machine.getName())
.memoryMB(machine.getMemorySize().intValue())
.osTypeId(machine.getOSTypeId()).forceOverwrite(true)
.cleanUpMode(CleanupMode.Full);
vmSpecBuilder.id(machine.getId()).name(machine.getName()).memoryMB(machine.getMemorySize().intValue())
.osTypeId(machine.getOSTypeId()).forceOverwrite(true).cleanUpMode(CleanupMode.Full);
for (StorageController storageController : controllers) {
vmSpecBuilder.controller(storageController);
@ -76,28 +73,23 @@ public class IMachineToVmSpec implements Function<IMachine, VmSpec> {
private List<StorageController> buildControllers(IMachine machine) {
List<StorageController> controllers = Lists.newArrayList();
for (IStorageController iStorageController : machine
.getStorageControllers()) {
for (IStorageController iStorageController : machine.getStorageControllers()) {
Builder storageControlleBuiler = StorageController.builder();
for (IMediumAttachment iMediumAttachment : machine
.getMediumAttachmentsOfController(iStorageController.getName())) {
for (IMediumAttachment iMediumAttachment : machine.getMediumAttachmentsOfController(iStorageController
.getName())) {
IMedium iMedium = iMediumAttachment.getMedium();
if (iMedium.getDeviceType().equals(DeviceType.HardDisk)) {
storageControlleBuiler.attachHardDisk(HardDisk.builder()
.diskpath(iMedium.getLocation()).autoDelete(true)
.controllerPort(iMediumAttachment.getPort())
.deviceSlot(iMediumAttachment.getDevice().intValue())
.build());
storageControlleBuiler.attachHardDisk(HardDisk.builder().diskpath(iMedium.getLocation())
.autoDelete(true).controllerPort(iMediumAttachment.getPort())
.deviceSlot(iMediumAttachment.getDevice().intValue()).build());
} else if (iMedium.getDeviceType().equals(DeviceType.DVD)) {
storageControlleBuiler.attachISO(iMediumAttachment.getPort(),
iMediumAttachment.getDevice().intValue(),
iMedium.getLocation());
storageControlleBuiler.attachISO(iMediumAttachment.getPort(), iMediumAttachment.getDevice().intValue(),
iMedium.getLocation());
}
}
controllers.add(storageControlleBuiler
.name(iStorageController.getName())
.bus(iStorageController.getBus()).build());
controllers.add(storageControlleBuiler.name(iStorageController.getName()).bus(iStorageController.getBus())
.build());
}
return controllers;
}

View File

@ -28,7 +28,11 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.domain.ErrorCode;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.virtualbox_4_1.*;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;

View File

@ -0,0 +1,188 @@
/**
* 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;
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.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
import java.io.File;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.compute.domain.Image;
import org.jclouds.virtualbox.domain.HardDisk;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.NetworkAdapter;
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.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.AbstractLoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
/**
* Does most of the work wrt to creating the master image.
*
* @author dralves
*
*/
public class MastersCache extends AbstractLoadingCache<Image, Master> {
private final Map<String, Master> masters = Maps.newHashMap();
private final Function<MasterSpec, IMachine> masterCreatorAndInstaller;
private final Map<String, YamlImage> imageMapping;
private final String workingDir;
private final String guestAdditionsIso;
private final String installationKeySequence;
private final String isosDir;
private Supplier<VirtualBoxManager> manager;
@Inject
public MastersCache(@Named(Constants.PROPERTY_BUILD_VERSION) String version,
@Named(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) String installationKeySequence,
@Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader,
Supplier<Map<Image, YamlImage>> yamlMapper, Supplier<VirtualBoxManager> manager) {
checkNotNull(version, "version");
checkNotNull(installationKeySequence, "installationKeySequence");
checkNotNull(manager, "vboxmanager");
this.manager = manager;
this.masterCreatorAndInstaller = masterLoader;
this.installationKeySequence = installationKeySequence;
this.workingDir = workingDir == null ? VIRTUALBOX_DEFAULT_DIR : workingDir;
File wdFile = new File(this.workingDir);
if (!wdFile.exists()) {
wdFile.mkdirs();
}
this.isosDir = wdFile.getAbsolutePath() + File.separator + "isos";
this.imageMapping = Maps.newLinkedHashMap();
for (Entry<Image, YamlImage> entry : yamlMapper.get().entrySet()) {
this.imageMapping.put(entry.getKey().getId(), entry.getValue());
}
this.guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso", isosDir,
Iterables.get(Splitter.on('r').split(version), 0));
checkState(new File(guestAdditionsIso).exists(), "guest additions iso does not exist at: " + guestAdditionsIso);
}
@Override
public Master get(Image key) throws ExecutionException {
// check if we have loaded this machine before
if (masters.containsKey(key.getId())) {
return masters.get(key);
}
// the yaml image
YamlImage yamlImage = imageMapping.get(key.getId());
checkNotNull(yamlImage, "could not find yaml image for image: " + key);
// check if the iso is here, download if not
String localIsoUrl = getFilePathOrDownload(yamlImage.iso);
String vmName = VIRTUALBOX_IMAGE_PREFIX + yamlImage.id;
String adminDisk = workingDir + File.separator + vmName + ".vdi";
HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk).autoDelete(true).controllerPort(0).deviceSlot(1)
.build();
StorageController ideController = StorageController.builder().name("IDE Controller").bus(StorageBus.IDE)
.attachISO(0, 0, localIsoUrl).attachHardDisk(hardDisk).attachISO(1, 1, guestAdditionsIso).build();
VmSpec vmSpecification = VmSpec.builder().id(yamlImage.id).name(vmName).memoryMB(512).osTypeId("")
.controller(ideController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).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(0L, networkInterfaceCard).build();
MasterSpec masterSpec = MasterSpec
.builder()
.vm(vmSpecification)
.iso(IsoSpec.builder().sourcePath(localIsoUrl)
.installationScript(installationKeySequence.replace("HOSTNAME", vmSpecification.getVmName()))
.build()).network(networkSpec).build();
IMachine masterMachine;
// try and find a master machine in vbox
try {
masterMachine = manager.get().getVBox().findMachine(vmName);
} catch (VBoxException e) {
if (machineNotFoundException(e)) {
// create the master machine if it can't be found
masterMachine = masterCreatorAndInstaller.apply(masterSpec);
} else {
throw e;
}
}
Master master = Master.builder().machine(masterMachine).spec(masterSpec).build();
masters.put(key.getId(), master);
return master;
}
private String getFilePathOrDownload(String httpUrl) throws ExecutionException {
// TODO validation
String fileName = httpUrl.substring(httpUrl.lastIndexOf('/') + 1, httpUrl.length());
File localFile = new File(isosDir, fileName);
// TODO download. for now just expect the file to be there
checkState(localFile.exists(), "iso file has not been downloaded: " + fileName);
return localFile.getAbsolutePath();
}
@Override
public Master getIfPresent(Image key) {
if (masters.containsKey(key.getId())) {
return masters.get(key.getId());
}
return null;
}
}

View File

@ -0,0 +1,105 @@
/**
mh * 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;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.jclouds.virtualbox.domain.Master;
import org.jclouds.virtualbox.domain.NetworkAdapter;
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
import org.jclouds.virtualbox.domain.NetworkSpec;
import org.jclouds.virtualbox.domain.NodeSpec;
import org.jclouds.virtualbox.domain.VmSpec;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
@Singleton
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
private final Supplier<VirtualBoxManager> manager;
private final Function<CloneSpec, IMachine> cloner;
@Inject
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner,
MachineUtils machineUtils) {
this.manager = manager;
this.cloner = cloner;
}
@Override
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
Master master = nodeSpec.getMaster();
if (master.getMachine().getCurrentSnapshot() != null) {
ISession session;
try {
session = manager.get().openMachineSession(master.getMachine());
} catch (Exception e) {
throw new RuntimeException("error opening vbox machine session: " + e.getMessage(), e);
}
session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
session.unlockMachine();
}
String masterNameWithoutPrefix = master.getSpec().getVmSpec().getVmName().replace(VIRTUALBOX_IMAGE_PREFIX, "");
String cloneName = VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + "-" + nodeSpec.getTag() + "-"
+ nodeSpec.getName();
VmSpec cloneVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).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(0L, networkInterfaceCard).build();
CloneSpec cloneSpec = CloneSpec.builder().linked(false).master(master.getMachine()).network(networkSpec)
.vm(cloneVmSpec).build();
IMachine cloned = cloner.apply(cloneSpec);
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, "").apply(cloned);
// TODO get credentials from somewhere else (they are also HC in IMachineToSshClient)
NodeAndInitialCredentials<IMachine> nodeAndInitialCredentials = new NodeAndInitialCredentials<IMachine>(cloned,
cloneName, LoginCredentials.builder().user("toor").password("password").authenticateSudo(true).build());
return nodeAndInitialCredentials;
}
}

View File

@ -0,0 +1,64 @@
/**
* 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;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.io.IOUtils;
import org.jclouds.virtualbox.config.VirtualBoxConstants;
import com.google.common.base.Supplier;
/**
* A supplier for vbox yaml config that reads a yaml whose path is stored under
* VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR.
*
* @author dralves
*
*/
public class YamlImagesFromFileConfig implements Supplier<String> {
private String yamlFilePath;
@Inject
public YamlImagesFromFileConfig(@Named(VirtualBoxConstants.VIRTUALBOX_IMAGES_DESCRIPTOR) String yamlFilePath) {
this.yamlFilePath = yamlFilePath;
}
@Override
public String get() {
checkNotNull(yamlFilePath, "yaml file path");
File yamlFile = new File(yamlFilePath);
checkState(yamlFile.exists(), "yaml file does not exist at: " + yamlFilePath);
try {
return IOUtils.toString(new FileInputStream(yamlFile));
} catch (IOException e) {
throw new RuntimeException("error reading yaml file");
}
}
}

View File

@ -19,35 +19,38 @@
package org.jclouds.virtualbox.functions.admin;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.virtualbox.domain.YamlImage;
import org.yaml.snakeyaml.Loader;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
/**
*
* @author Andrea Turli
*/
@Singleton
public class ImageFromYamlStream implements Function<InputStream, LoadingCache<String, Image>> {
public class ImagesToYamlImagesFromYamlDescriptor implements Supplier<Map<Image, YamlImage>> {
private String yamlDescriptor;
@Inject
public ImagesToYamlImagesFromYamlDescriptor(Supplier<String> yamlDescriptorSupplier) {
this.yamlDescriptor = yamlDescriptorSupplier.get();
checkNotNull(yamlDescriptor, "yaml descriptor");
checkState(!yamlDescriptor.equals(""), "yaml descriptor is empty");
}
/**
* Type-safe config class for YAML
@ -57,13 +60,8 @@ public class ImageFromYamlStream implements Function<InputStream, LoadingCache<S
public List<YamlImage> images;
}
private Object construct(String data) {
Yaml yaml = new Yaml();
return yaml.load(data);
}
@Override
public LoadingCache<String, Image> apply(InputStream source) {
public Map<Image, YamlImage> get() {
Constructor constructor = new Constructor(Config.class);
@ -71,21 +69,16 @@ public class ImageFromYamlStream implements Function<InputStream, LoadingCache<S
imageDesc.putListPropertyType("images", String.class);
constructor.addTypeDescription(imageDesc);
Yaml yaml = new Yaml(new Loader(constructor));
Config config = (Config) yaml.load(source);
Yaml yaml = new Yaml(constructor);
Config config = (Config) yaml.load(yamlDescriptor);
checkState(config != null, "missing config: class");
checkState(config.images != null, "missing images: collection");
Map<String, Image> backingMap = Maps.uniqueIndex(Iterables.transform(config.images, YamlImage.toImage),
new Function<Image, String>() {
public String apply(Image image) {
return image.getId();
}
});
LoadingCache<String, Image> cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backingMap)));
for (String node : backingMap.keySet())
cache.getUnchecked(node);
return cache;
Map<Image, YamlImage> backingMap = Maps.newLinkedHashMap();
for (YamlImage yamlImage : config.images) {
backingMap.put(YamlImage.toImage.apply(yamlImage), yamlImage);
}
return backingMap;
}
}

View File

@ -4,42 +4,50 @@ import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
import org.jclouds.virtualbox.statements.InstallGuestAdditions;
import org.jclouds.virtualbox.util.MachineUtils;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
@Singleton
public class GuestAdditionsInstaller implements Predicate<String> {
public class GuestAdditionsInstaller implements Predicate<IMachine> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ComputeServiceContext context;
private String vboxVersion;
private final IMachineToNodeMetadata imachineToNodeMetadata;
private final MachineUtils machineUtils;
private final Supplier<VirtualBoxManager> manager;
@Inject
public GuestAdditionsInstaller(ComputeServiceContext context) {
this.context = context;
}
@Inject
public GuestAdditionsInstaller(Supplier<VirtualBoxManager> manager, MachineUtils machineUtils,
IMachineToNodeMetadata imachineToNodeMetadata) {
this.machineUtils = machineUtils;
this.imachineToNodeMetadata = imachineToNodeMetadata;
this.manager = manager;
}
@Override
public boolean apply(String vmName) {
vboxVersion = Iterables.get(Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
ListenableFuture<ExecResponse> execFuture = context.getComputeService().submitScriptOnNode(vmName,
new InstallGuestAdditions(vboxVersion), RunScriptOptions.NONE);
ExecResponse execResponse = Futures.getUnchecked(execFuture);
return execResponse == null ? false : execResponse.getExitStatus() == 0;
}
@Override
public boolean apply(IMachine machine) {
String vboxVersion = Iterables.get(Splitter.on('r').split(manager.get().getVBox().getVersion()), 0);
ListenableFuture<ExecResponse> execFuture = machineUtils.runScriptOnNode(imachineToNodeMetadata.apply(machine),
new InstallGuestAdditions(vboxVersion), RunScriptOptions.NONE);
ExecResponse execResponse = Futures.getUnchecked(execFuture);
return execResponse == null ? false : execResponse.getExitStatus() == 0;
}
}

View File

@ -45,7 +45,9 @@ public class SshResponds implements Predicate<SshClient> {
} catch (SshException e) {
logger.trace("No response from ssh daemon connecting to %s: %s", client, e.getMessage());
} finally {
if (client != null) {
client.disconnect();
}
}
return false;
}

View File

@ -18,29 +18,41 @@
*/
package org.jclouds.virtualbox.util;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Throwables2;
import org.jclouds.virtualbox.functions.MutableMachine;
import org.virtualbox_4_1.*;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.scriptbuilder.domain.Statements.call;
import static org.jclouds.scriptbuilder.domain.Statements.findPid;
import static org.jclouds.scriptbuilder.domain.Statements.kill;
import static org.jclouds.scriptbuilder.domain.Statements.newStatementList;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot;
import static org.jclouds.scriptbuilder.domain.Statements.*;
import org.jclouds.compute.callables.RunScriptOnNode;
import org.jclouds.compute.callables.RunScriptOnNode.Factory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Throwables2;
import org.jclouds.virtualbox.functions.MutableMachine;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.VBoxException;
import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/**
* Utilities for executing functions on a VirtualBox machine.
*
*
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
*/
@ -56,51 +68,59 @@ public class MachineUtils {
private final Supplier<NodeMetadata> host;
@Inject
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner, Supplier<NodeMetadata> host) {
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
Supplier<NodeMetadata> host) {
super();
this.manager = manager;
this.scriptRunner = scriptRunner;
this.host = host;
}
/**
* Locks the machine and executes the given function using the machine
* matching the given id. Since the machine is locked it is possible to
* perform some modifications to the IMachine.
* <p/>
* Unlocks the machine before returning.
*
* @param machineId the id of the machine
* @param function the function to execute
* @return the result from applying the function to the machine.
*/
public <T> T writeLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
return lockSessionOnMachineAndApply(machineId, LockType.Write,
new Function<ISession, T>() {
@Override
public T apply(ISession session) {
return function.apply(session.getMachine());
}
@Override
public String toString() {
return function.toString();
}
});
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
RunScriptOptions options) {
return scriptRunner.submit(metadata, statement, options);
}
/**
* Locks the machine and executes the given function using the current
* session. Since the machine is locked it is possible to perform some
* modifications to the IMachine.
* Locks the machine and executes the given function using the machine matching the given id.
* Since the machine is locked it is possible to perform some modifications to the IMachine.
* <p/>
* Unlocks the machine before returning.
*
* @param type the kind of lock to use when initially locking the machine.
* @param machineId the id of the machine
* @param function the function to execute
*
* @param machineId
* the id of the machine
* @param function
* the function to execute
* @return the result from applying the function to the machine.
*/
public <T> T writeLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
return lockSessionOnMachineAndApply(machineId, LockType.Write, new Function<ISession, T>() {
@Override
public T apply(ISession session) {
return function.apply(session.getMachine());
}
@Override
public String toString() {
return function.toString();
}
});
}
/**
* Locks the machine and executes the given function using the current session. Since the machine
* is locked it is possible to perform some modifications to the IMachine.
* <p/>
* Unlocks the machine before returning.
*
* @param type
* the kind of lock to use when initially locking the machine.
* @param machineId
* the id of the machine
* @param function
* the function to execute
* @return the result from applying the function to the session.
*/
public <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
@ -112,9 +132,8 @@ public class MachineUtils {
session.unlockMachine();
}
} catch (VBoxException e) {
throw new RuntimeException(String.format(
"error applying %s to %s with %s lock: %s", function, machineId,
type, e.getMessage()), e);
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId,
type, e.getMessage()), e);
}
}
@ -125,25 +144,24 @@ public class MachineUtils {
private void unlockMachine(final String machineId) {
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
if (immutableMachine.getSessionState().equals(SessionState.Locked)) {
Statement kill = newStatementList(call("default"),
findPid(immutableMachine.getSessionPid().toString()), kill());
scriptRunner
.create(host.get(), kill,
runAsRoot(false).wrapInInitScript(false)).init().call();
Statement kill = newStatementList(call("default"), findPid(immutableMachine.getSessionPid().toString()),
kill());
scriptRunner.create(host.get(), kill, runAsRoot(false).wrapInInitScript(false)).init().call();
}
}
/**
* Unlocks the machine and executes the given function using the machine
* matching the given id. Since the machine is unlocked it is possible to
* delete the IMachine.
* Unlocks the machine and executes the given function using the machine matching the given id.
* Since the machine is unlocked it is possible to delete the IMachine.
* <p/>
* <p/>
* <h3>Note!</h3> Currently, this can only unlock the machine, if the lock
* was created in the current session.
*
* @param machineId the id of the machine
* @param function the function to execute
* <h3>Note!</h3> Currently, this can only unlock the machine, if the lock was created in the
* current session.
*
* @param machineId
* the id of the machine
* @param function
* the function to execute
* @return the result from applying the function to the machine.
*/
public <T> T unlockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
@ -154,31 +172,28 @@ public class MachineUtils {
return function.apply(immutableMachine);
} catch (VBoxException e) {
throw new RuntimeException(String.format(
"error applying %s to %s: %s", function, machineId,
e.getMessage()), e);
throw new RuntimeException(String.format("error applying %s to %s: %s", function, machineId, e.getMessage()),
e);
}
}
/**
* Unlocks the machine and executes the given function, if the machine is
* registered. Since the machine is unlocked it is possible to delete the
* machine.
* Unlocks the machine and executes the given function, if the machine is registered. Since the
* machine is unlocked it is possible to delete the machine.
* <p/>
*
* @param machineId the id of the machine
* @param function the function to execute
*
* @param machineId
* the id of the machine
* @param function
* the function to execute
* @return the result from applying the function to the session.
*/
public <T> T unlockMachineAndApplyOrReturnNullIfNotRegistered(String machineId,
Function<IMachine, T> function) {
public <T> T unlockMachineAndApplyOrReturnNullIfNotRegistered(String machineId, Function<IMachine, T> function) {
try {
return unlockMachineAndApply(machineId, function);
} catch (RuntimeException e) {
VBoxException vbex = Throwables2.getFirstThrowableOfType(e,
VBoxException.class);
if (vbex != null
&& vbex.getMessage().indexOf("not find a registered") == -1)
VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class);
if (vbex != null && vbex.getMessage().indexOf("not find a registered") == -1)
throw e;
return null;
}
@ -204,4 +219,8 @@ public class MachineUtils {
}.apply(immutableMachine);
}
public static boolean machineNotFoundException(VBoxException e) {
return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ")
|| e.getMessage().contains("Could not find a registered machine with UUID {");
}
}

View File

@ -6,5 +6,9 @@ function installModuleAssistantIfNeeded {
echo "OS is Ubuntu"
apt-get -f -y -qq --force-yes install build-essential module-assistant;
m-a prepare -i
rm /etc/udev/rules.d/70-persistent-net.rules;
mkdir /etc/udev/rules.d/70-persistent-net.rules;
rm -rf /dev/.udev/;
rm /lib/udev/rules.d/75-persistent-net-generator.rules
fi
}

View File

@ -19,16 +19,10 @@
package org.jclouds.virtualbox;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import java.io.File;
import java.net.URI;
import java.util.Properties;
import org.jclouds.Constants;
import org.jclouds.byon.Node;
import org.jclouds.byon.config.CacheNodeStoreModule;
@ -37,7 +31,8 @@ import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.sshj.config.SshjSshClientModule;
@ -49,14 +44,26 @@ import org.jclouds.virtualbox.util.MachineUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.VirtualBoxManager;
import org.virtualbox_4_1.jaxws.MachineState;
import java.net.URI;
import java.util.Properties;
import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code VirtualBoxClient}
*
*
* @author Adrian Cole
*/
@Test(groups = "live", singleThreaded = true, testName = "BaseVirtualBoxClientLiveTest")
@ -72,9 +79,11 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
protected String hostVersion;
protected String operatingSystemIso;
protected String guestAdditionsIso;
protected String adminDisk;
protected String workingDir;
protected String isosDir;
protected Supplier<NodeMetadata> host;
protected static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate(
new DefaultCredentialsFromImageOrOverridingCredentials());
@Override
protected void setupCredentials() {
@ -86,52 +95,44 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
}
protected void ensureIdentityPropertyIsSpecifiedOrTakeFromDefaults() {
Properties defaultVBoxProperties = new VirtualBoxPropertiesBuilder()
.build();
Properties defaultVBoxProperties = new VirtualBoxPropertiesBuilder().build();
if (!System.getProperties().containsKey("test." + provider + ".identity"))
System.setProperty("test." + provider + ".identity",
defaultVBoxProperties.getProperty(Constants.PROPERTY_IDENTITY));
defaultVBoxProperties.getProperty(Constants.PROPERTY_IDENTITY));
}
@BeforeClass(groups = "live")
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
Properties overrides = new VirtualBoxPropertiesBuilder(setupProperties()).build();
CacheNodeStoreModule hostModule = new CacheNodeStoreModule(
ImmutableMap.of(
"host",
Node.builder()
.id("host")
.name("host installing virtualbox")
.hostname("localhost")
.osFamily(OsFamily.LINUX.toString())
.osDescription(System.getProperty("os.name"))
.osVersion(System.getProperty("os.version"))
.group("ssh")
.username(System.getProperty("user.name"))
.credentialUrl(
URI.create("file://"
+ System.getProperty("user.home")
+ "/.ssh/id_rsa")).build()));
CacheNodeStoreModule hostModule = new CacheNodeStoreModule(ImmutableMap.of(
"host",
Node.builder().id("host").name("host installing virtualbox").hostname("localhost")
.osFamily(OsFamily.LINUX.toString()).osDescription(System.getProperty("os.name"))
.osVersion(System.getProperty("os.version")).group("ssh")
.username(System.getProperty("user.name"))
.credentialUrl(URI.create("file://" + System.getProperty("user.home") + "/.ssh/id_rsa"))
.build()));
context = new ComputeServiceContextFactory().createContext(provider,
identity, credential, ImmutableSet.<Module>of(
new SLF4JLoggingModule(), new SshjSshClientModule(),
hostModule), overrides);
context = new ComputeServiceContextFactory().createContext(provider, identity, credential,
ImmutableSet.<Module> of(new SLF4JLoggingModule(), new SshjSshClientModule(), hostModule), overrides);
Function<String, String> configProperties = context.utils().injector()
.getInstance(ValueOfConfigurationKeyOrNull.class);
imageId = configProperties
.apply(ComputeServiceConstants.PROPERTY_IMAGE_ID);
workingDir = configProperties
.apply(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR);
host = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<Supplier<NodeMetadata>>() {
}));
.getInstance(ValueOfConfigurationKeyOrNull.class);
imageId = "ubuntu-11.04-server-i386";
workingDir = configProperties.apply(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR);
isosDir = workingDir + File.separator + "isos";
File isosDirFile = new File(isosDir);
if (!isosDirFile.exists()) {
isosDirFile.mkdirs();
}
host = context.utils().injector().getInstance(Key.get(new TypeLiteral<Supplier<NodeMetadata>>() {
}));
// this will eagerly startup Jetty, note the impl will shut itself down
preconfigurationUri = context.utils().injector().getInstance(Key.get(new TypeLiteral<LoadingCache<IsoSpec, URI>>() {
}, Preconfiguration.class));
preconfigurationUri = context.utils().injector()
.getInstance(Key.get(new TypeLiteral<LoadingCache<IsoSpec, URI>>() {
}, Preconfiguration.class));
// this will eagerly startup Jetty, note the impl will shut itself down
manager = context.utils().injector().getInstance(Key.get(new TypeLiteral<Supplier<VirtualBoxManager>>() {
@ -141,19 +142,43 @@ public class BaseVirtualBoxClientLiveTest extends BaseVersionedServiceLiveTest {
machineUtils = context.utils().injector().getInstance(MachineUtils.class);
hostVersion = Iterables.get(
Splitter.on('r').split(
context.getProviderSpecificContext().getBuildVersion()), 0);
adminDisk = workingDir + "/testadmin.vdi";
operatingSystemIso = String.format("%s/%s.iso", workingDir, imageId);
guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso",
workingDir, hostVersion);
hostVersion = Iterables.get(Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
operatingSystemIso = String.format("%s/%s.iso", isosDir, imageId);
guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso", isosDir, hostVersion);
}
protected void undoVm(VmSpec vmSpecification) {
machineUtils.unlockMachineAndApplyOrReturnNullIfNotRegistered(
vmSpecification.getVmId(),
new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification));
machineUtils.unlockMachineAndApplyOrReturnNullIfNotRegistered(vmSpecification.getVmId(),
new UnregisterMachineIfExistsAndDeleteItsMedia(vmSpecification));
}
protected void ensureMachineHasPowerDown(String vmName) {
while (!manager.get().getVBox().findMachine(vmName).getState().equals(MachineState.POWERED_OFF)) {
try {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared, new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole().powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
} catch (RuntimeException e) {
// sometimes the machine might be powered of between the while test and the call to
// lockSessionOnMachineAndApply
if (e.getMessage().contains("Invalid machine state: PoweredOff")) {
return;
} else if (e.getMessage().contains("VirtualBox error: The object is not ready")) {
continue;
} else {
throw e;
}
}
}
}
public String adminDisk(String vmName) {
return workingDir + File.separator + vmName + ".vdi";
}
@AfterClass(groups = "live")

View File

@ -19,20 +19,17 @@
package org.jclouds.virtualbox.compute;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.net.IPSocket;
import org.jclouds.ssh.SshClient;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.functions.IMachineToSshClient;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
@ -50,17 +47,17 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien
adapter = context.utils().injector().getInstance(VirtualBoxComputeServiceAdapter.class);
}
private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate(
new DefaultCredentialsFromImageOrOverridingCredentials());
@Test
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() {
String group = "foo";
String name = "foo-ef4";
Template template = context.getComputeService().templateBuilder().build();
String machineName = VIRTUALBOX_NODE_PREFIX + "myTestId-" + group + "-" + name;
// get the image from
Image image = Iterables.get(adapter.listImages(), 0);
System.out.println(context.getComputeService().templateBuilder());
Template template = context.getComputeService().templateBuilder().fromImage(image).build();
machine = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
assertEquals(machine.getNode().getName(), name);
assertEquals(machine.getNodeId(), machine.getNode().getId());
assertEquals(machine.getNode().getName(), machineName);
// is there a place for group?
// check other things, like cpu correct, mem correct, image/os is correct
// (as possible)
@ -69,11 +66,10 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien
// InetAddresses.isInetAddress(machine.getPrimaryBackendIpAddress()) :
// machine;
doConnectViaSsh(machine.getNode(), prioritizeCredentialsFromTemplate.apply(template, machine.getCredentials()));
}
protected void doConnectViaSsh(IMachine machine, LoginCredentials creds) {
SshClient ssh = context.utils().sshFactory().create(new IPSocket("//TODO", 22), creds);
SshClient ssh = context.utils().injector().getInstance(IMachineToSshClient.class).apply(machine);
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -90,8 +86,7 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien
@Test
public void testListHardwareProfiles() {
Iterable<IMachine> profiles = adapter.listHardwareProfiles();
assertTrue(Iterables.isEmpty(profiles));
// check state;
assertEquals(1, Iterables.size(profiles));
}
@Test
@ -102,7 +97,7 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien
}
// check state;
}
@Override
protected void tearDown() throws Exception {
if (machine != null)

View File

@ -23,10 +23,8 @@ import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -46,7 +44,6 @@ import org.virtualbox_4_1.VirtualBoxManager;
import com.google.common.base.Function;
import com.google.common.base.Suppliers;
import com.google.common.collect.Iterators;
import com.google.inject.Guice;
@Test(groups = "unit")
@ -83,11 +80,25 @@ public class VirtualBoxComputeServiceAdapterTest {
replay(manager, vBox, clonedMachine, imageMachine, osType);
Function<IMachine, Image> iMachineToImage = new IMachineToImage(Suppliers.ofInstance(manager), osMap);
VirtualBoxComputeServiceAdapter adapter = new VirtualBoxComputeServiceAdapter(Suppliers.ofInstance(manager), iMachineToImage);
Iterator<Image> iterator = adapter.listImages().iterator();
Image image = Iterators.getOnlyElement(iterator);
assertEquals(image.getDescription(), VIRTUALBOX_IMAGE_PREFIX + "ubuntu-10.04");
// VirtualBoxComputeServiceAdapter adapter = new VirtualBoxComputeServiceAdapter(Suppliers.ofInstance(manager), iMachineToImage, new ImageFromYamlString(), new Supplier<String>() {
//
// @Override
// public String get() {
// return "images:\n" +
// " - id: myTestId\n" +
// " name: ubuntu-11.04-server-i386\n" +
// " description: ubuntu 11.04 server (i386)\n" +
// " os_arch: x86\n" +
// " os_family: ubuntu\n" +
// " os_description: ubuntu\n" +
// " os_version: 11.04\n" +
// " iso: http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso";
// }
// });
//
// Iterator<Image> iterator = adapter.listImages().iterator();
// Image image = Iterators.getOnlyElement(iterator);
// assertEquals(image.getDescription(), "ubuntu 11.04 server (i386)");
}
}

View File

@ -35,7 +35,7 @@ import com.google.common.io.Resources;
@Test(groups = "unit")
public class InstallGuestAdditionsTest {
@Test
@Test(enabled = false)
public void testUnixByItself() throws IOException {
InstallGuestAdditions statement = new InstallGuestAdditions("4.1.6");
assertEquals(statement.render(OsFamily.UNIX),
@ -44,7 +44,7 @@ public class InstallGuestAdditionsTest {
Charsets.UTF_8)));
}
@Test
@Test(enabled = false)
public void testUnixInInitScript() throws IOException {
Statement statement = InitScript.builder().name("install_guest_additions")
.run(new InstallGuestAdditions("4.1.6")).build();

View File

@ -19,6 +19,12 @@
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.jclouds.virtualbox.domain.StorageController;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;
@ -26,9 +32,6 @@ import org.virtualbox_4_1.IStorageController;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VBoxException;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.*;
/**
* @author Adrian Cole
*/

View File

@ -19,11 +19,11 @@
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;

View File

@ -21,12 +21,12 @@ package org.jclouds.virtualbox.functions;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.easymock.EasyMock.anyLong;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.jclouds.virtualbox.domain.DeviceDetails;
import org.jclouds.virtualbox.domain.HardDisk;

View File

@ -0,0 +1,155 @@
/**
* 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;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.testng.Assert.assertEquals;
import java.util.Set;
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;
import org.jclouds.virtualbox.domain.NetworkAdapter;
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.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
/**
* @author Andrea Turli
*/
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest")
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest extends BaseVirtualBoxClientLiveTest {
private static final boolean IS_LINKED_CLONE = true;
private MasterSpec sourceMachineSpec;
private CleanupMode mode = CleanupMode.Full;
private VmSpec clonedVmSpec;
private NetworkSpec cloneNetworkSpec;
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
String sourceName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
String cloneName = VIRTUALBOX_IMAGE_PREFIX + "Clone#"
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
StorageController ideController = StorageController
.builder()
.name("IDE Controller")
.bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(
HardDisk.builder().diskpath(adminDisk(sourceName)).controllerPort(0).deviceSlot(1)
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build();
VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName).osTypeId("").memoryMB(512)
.cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build();
Injector injector = context.utils().injector();
Function<String, String> 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.Bridged)
.build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
.build();
this.cloneNetworkSpec = NetworkSpec.builder().addNIC(0L, networkInterfaceCard).build();
sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec).network(cloneNetworkSpec).build();
this.clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(mode)
.forceOverwrite(true).build();
}
@Test
public void testCloneMachineFromAnotherMachine() throws Exception {
CloneSpec cloneSpec = null;
try {
IMachine source = getSourceNode();
cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(cloneNetworkSpec).master(source)
.linked(IS_LINKED_CLONE).build();
if (source.getCurrentSnapshot() != null) {
ISession session = manager.get().openMachineSession(source);
session.getConsole().deleteSnapshot(source.getCurrentSnapshot().getId());
session.unlockMachine();
}
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
.apply(cloneSpec);
assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName());
new LaunchMachineIfNotAlreadyRunning(manager.get(), ExecutionType.GUI, "").apply(clone);
// TODO ssh into the node
} finally {
Set<VmSpec> specs = cloneSpec == null ? ImmutableSet.of(sourceMachineSpec.getVmSpec()) : ImmutableSet.of(
cloneSpec.getVmSpec(), sourceMachineSpec.getVmSpec());
for (VmSpec spec : specs) {
undoVm(spec);
}
}
}
private IMachine getSourceNode() {
try {
Injector injector = context.utils().injector();
return injector.getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(sourceMachineSpec);
} catch (IllegalStateException e) {
// already created
return manager.get().getVBox().findMachine(sourceMachineSpec.getVmSpec().getVmId());
}
}
}

View File

@ -1,156 +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;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.testng.Assert.assertEquals;
import org.jclouds.config.ValueOfConfigurationKeyOrNull;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.HardDisk;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.NetworkAdapter;
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.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
/**
* @author Andrea Turli
*/
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest")
public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
BaseVirtualBoxClientLiveTest {
private static final boolean IS_LINKED_CLONE = true;
private CloneSpec cloneSpec;
private MasterSpec sourceMachineSpec;
private CleanupMode mode = CleanupMode.Full;
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
String sourceName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
String cloneName = VIRTUALBOX_IMAGE_PREFIX
+ "Clone#"
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
StorageController ideController = StorageController
.builder()
.name("IDE Controller")
.bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(
HardDisk.builder().diskpath(adminDisk)
.controllerPort(0).deviceSlot(1)
.autoDelete(true).build())
.attachISO(1, 1, guestAdditionsIso).build();
VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName)
.osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full)
.controller(ideController).forceOverwrite(true).build();
Injector injector = context.utils().injector();
Function<String, String> 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.Bridged).build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
.builder().addNetworkAdapter(networkAdapter).build();
NetworkSpec networkSpec = NetworkSpec.builder()
.addNIC(0L, networkInterfaceCard).build();
sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec)
.network(networkSpec).build();
VmSpec clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
.memoryMB(512).cleanUpMode(mode).forceOverwrite(true).build();
cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(networkSpec)
.build();
}
@Test
public void testCloneMachineFromAnotherMachine() throws Exception {
try {
IMachine source = getSourceNode();
if (source.getCurrentSnapshot() != null) {
ISession session = manager.get().openMachineSession(source);
session.getConsole().deleteSnapshot(
source.getCurrentSnapshot().getId());
session.unlockMachine();
}
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
manager, workingDir, cloneSpec, IS_LINKED_CLONE,
machineUtils).apply(source);
assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName());
} finally {
for (VmSpec spec : ImmutableSet.of(cloneSpec.getVmSpec(),
sourceMachineSpec.getVmSpec()))
undoVm(spec);
}
}
private IMachine getSourceNode() {
try {
Injector injector = context.utils().injector();
return injector.getInstance(
CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class)
.apply(sourceMachineSpec);
} catch (IllegalStateException e) {
// already created
return manager.get().getVBox()
.findMachine(sourceMachineSpec.getVmSpec().getVmId());
}
}
}

View File

@ -20,15 +20,11 @@
package org.jclouds.virtualbox.functions;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.equalTo;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.transform;
import static junit.framework.Assert.assertEquals;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -56,18 +52,15 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.LockType;
import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.jaxws.MachineState;
import com.google.common.base.CaseFormat;
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.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.inject.Guice;
@ -79,166 +72,118 @@ import com.google.inject.Injector;
@Test(groups = "live", singleThreaded = true, testName = "CreateAndInstallVmLiveTest")
public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest {
Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice
.createInjector(new GsonModule()).getInstance(Json.class));
Map<OsFamily, Map<String, String>> map = new BaseComputeServiceContextModule() {
}.provideOsVersionMap(new ComputeServiceConstants.ReferenceData(), Guice.createInjector(new GsonModule())
.getInstance(Json.class));
private VmSpec vmSpecification;
private MasterSpec masterSpec;
private Injector injector;
private Function<IMachine, SshClient> sshClientForIMachine;
private Predicate<SshClient> sshResponds;
private VmSpec vmSpecification;
private MasterSpec masterSpec;
private Injector injector;
private Function<IMachine, SshClient> sshClientForIMachine;
private Predicate<SshClient> sshResponds;
private String vmName;
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
String vmName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
this.vmName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk)
.autoDelete(true).controllerPort(0).deviceSlot(1).build();
StorageController ideController = StorageController.builder()
.name("IDE Controller").bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso).attachHardDisk(hardDisk)
.attachISO(1, 1, guestAdditionsIso).build();
vmSpecification = VmSpec.builder().id(vmName).name(vmName)
.memoryMB(512).osTypeId("").controller(ideController)
.forceOverwrite(true).cleanUpMode(CleanupMode.Full).build();
HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk(vmName)).autoDelete(true).controllerPort(0)
.deviceSlot(1).build();
StorageController ideController = StorageController.builder().name("IDE Controller").bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso).attachHardDisk(hardDisk).attachISO(1, 1, guestAdditionsIso).build();
vmSpecification = VmSpec.builder().id(vmName).name(vmName).memoryMB(512).osTypeId("").controller(ideController)
.forceOverwrite(true).cleanUpMode(CleanupMode.Full).build();
injector = context.utils().injector();
Function<String, String> configProperties = injector
.getInstance(ValueOfConfigurationKeyOrNull.class);
injector = context.utils().injector();
Function<String, String> configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class);
NetworkAdapter networkAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.NAT)
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
.builder().addNetworkAdapter(networkAdapter).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(0L, networkInterfaceCard).build();
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(0L, networkInterfaceCard).build();
masterSpec = MasterSpec
.builder()
.vm(vmSpecification)
.iso(IsoSpec
.builder()
.sourcePath(operatingSystemIso)
.installationScript(
configProperties.apply(
VIRTUALBOX_INSTALLATION_KEY_SEQUENCE)
.replace("HOSTNAME",
vmSpecification.getVmName()))
.build()).network(networkSpec).build();
masterSpec = MasterSpec
.builder()
.vm(vmSpecification)
.iso(IsoSpec
.builder()
.sourcePath(operatingSystemIso)
.installationScript(
configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME",
vmSpecification.getVmName())).build()).network(networkSpec).build();
undoVm(vmSpecification);
}
undoVm(vmSpecification);
}
public void testCreateImageMachineFromIso() throws Exception {
IMachine imageMachine = getVmWithGuestAdditionsInstalled();
@Test
public void testCreateImageMachineFromIso() throws Exception {
IMachine imageMachine = getVmWithGuestAdditionsInstalled();
IMachineToImage iMachineToImage = new IMachineToImage(manager, map);
Image newImage = iMachineToImage.apply(imageMachine);
assertEquals(vmName, newImage.getName());
}
IMachineToImage iMachineToImage = new IMachineToImage(manager, map);
Image newImage = iMachineToImage.apply(imageMachine);
// TODO add the description to the cache of the images or serialize to
// YAML the image desc
Set<? extends Image> images = context.getComputeService().listImages();
Iterable<String> imageIds = transform(images, extractId());
assertTrue(any(imageIds, equalTo(newImage.getId())));
}
@Test
public void testGuestAdditionsAreInstalled() throws Exception {
try {
IMachine machine = getVmWithGuestAdditionsInstalled();
@Test
public void testGuestAdditionsAreInstalled() throws Exception {
try {
IMachine machine = getVmWithGuestAdditionsInstalled();
machineUtils.applyForMachine(machine.getName(), new LaunchMachineIfNotAlreadyRunning(manager.get(),
ExecutionType.GUI, ""));
sshClientForIMachine = injector.getInstance(IMachineToSshClient.class);
SshClient client = sshClientForIMachine.apply(machine);
machineUtils.applyForMachine(machine.getName(),
new LaunchMachineIfNotAlreadyRunning(manager.get(),
ExecutionType.GUI, ""));
sshClientForIMachine = injector
.getInstance(IMachineToSshClient.class);
SshClient client = sshClientForIMachine.apply(machine);
sshResponds = injector.getInstance(SshResponds.class);
checkState(sshResponds.apply(client), "timed out waiting for guest %s to be accessible via ssh",
machine.getName());
sshResponds = injector.getInstance(SshResponds.class);
checkState(sshResponds.apply(client),
"timed out waiting for guest %s to be accessible via ssh",
machine.getName());
String vboxVersion = Iterables.get(
Splitter.on('r').split(context.getProviderSpecificContext().getBuildVersion()), 0);
assertEquals(vboxVersion, machineUtils.lockSessionOnMachineAndApply(machine.getName(), LockType.Shared,
new Function<ISession, String>() {
@Override
public String apply(ISession session) {
return session.getMachine().getGuestPropertyValue("/VirtualBox/GuestAdd/Version");
}
}));
} finally {
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
ensureMachineHasPowerDown(spec.getVmName());
}
}
}
assertTrue(machineUtils.lockSessionOnMachineAndApply(
machine.getName(), LockType.Shared,
new Function<ISession, Boolean>() {
@Override
public Boolean apply(ISession session) {
String vboxVersion = Iterables
.get(Splitter
.on('r')
.split(context
.getProviderSpecificContext()
.getBuildVersion()), 0);
return session
.getMachine()
.getGuestPropertyValue(
"/VirtualBox/GuestAdd/Version")
.equals(vboxVersion);
}
}));
} finally {
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
ensureMachineHasPowerDown(spec.getVmName());
}
}
}
private Function<Image, String> extractId() {
return new Function<Image, String>() {
private Function<Image, String> extractId() {
return new Function<Image, String>() {
@Override
public String apply(@Nullable Image input) {
return input.getId();
}
};
}
@Override
public String apply(@Nullable Image input) {
return input.getId();
}
};
}
private IMachine getVmWithGuestAdditionsInstalled() {
try {
Injector injector = context.utils().injector();
return injector.getInstance(CreateAndInstallVm.class).apply(
masterSpec);
} catch (IllegalStateException e) {
// already created
return manager.get().getVBox()
.findMachine(masterSpec.getVmSpec().getVmId());
}
}
private IMachine getVmWithGuestAdditionsInstalled() {
try {
Injector injector = context.utils().injector();
return injector.getInstance(CreateAndInstallVm.class).apply(masterSpec);
} catch (IllegalStateException e) {
// already created
return manager.get().getVBox().findMachine(masterSpec.getVmSpec().getVmId());
}
}
private void ensureMachineHasPowerDown(String vmName) {
while (!manager.get().getVBox().findMachine(vmName).getState()
.equals(MachineState.POWERED_OFF)) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole()
.powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Throwables.propagate(e);
}
}
}
@Override
@AfterClass(groups = "live")
protected void tearDown() throws Exception {
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
undoVm(spec);
}
super.tearDown();
}
@Override
@AfterClass(groups = "live")
protected void tearDown() throws Exception {
for (VmSpec spec : ImmutableSet.of(vmSpecification)) {
undoVm(spec);
}
super.tearDown();
}
}

View File

@ -23,9 +23,16 @@ import static org.testng.Assert.fail;
import java.util.UUID;
import com.google.inject.Injector;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.domain.*;
import org.jclouds.virtualbox.domain.ErrorCode;
import org.jclouds.virtualbox.domain.HardDisk;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.jclouds.virtualbox.domain.MasterSpec;
import org.jclouds.virtualbox.domain.NetworkAdapter;
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.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;
@ -33,6 +40,8 @@ import org.virtualbox_4_1.NetworkAttachmentType;
import org.virtualbox_4_1.StorageBus;
import org.virtualbox_4_1.VBoxException;
import com.google.inject.Injector;
/**
* @author Mattias Holmqvist
*/
@ -42,28 +51,23 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
private String ideControllerName;
private CleanupMode mode;
private StorageController ideController;
@Override
public void setupClient() {
super.setupClient();
ideControllerName = "IDE Controller";
mode = CleanupMode.Full;
ideController = StorageController
.builder()
.name(ideControllerName)
.bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(
HardDisk.builder().diskpath(adminDisk)
.controllerPort(0).deviceSlot(1).build())
.attachISO(1, 1, guestAdditionsIso).build();
}
@Test
public void testCreateNewMachine() throws Exception {
String vmName = "jclouds-test-create-1-node";
String vmId = UUID.randomUUID().toString();
StorageController ideController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(HardDisk.builder().diskpath(adminDisk(vmName)).controllerPort(0).deviceSlot(1).build())
.attachISO(1, 1, guestAdditionsIso).build();
VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512)
.controller(ideController).cleanUpMode(mode).osTypeId("Debian")
@ -101,6 +105,11 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
public void testCreateNewMachineWithBadOsType() throws Exception {
String vmName = "jclouds-test-create-2-node";
String vmId = UUID.randomUUID().toString();
StorageController ideController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(HardDisk.builder().diskpath(adminDisk(vmName)).controllerPort(0).deviceSlot(1).build())
.attachISO(1, 1, guestAdditionsIso).build();
VmSpec vmSpec = VmSpec.builder().id(vmId).name(vmName).memoryMB(512)
.controller(ideController).cleanUpMode(mode)

View File

@ -18,11 +18,11 @@
*/
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IMachine;

View File

@ -19,10 +19,10 @@
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.domain.Hardware;

View File

@ -19,10 +19,10 @@
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import static org.testng.AssertJUnit.assertTrue;

View File

@ -19,9 +19,9 @@
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import org.jclouds.virtualbox.domain.HardDisk;

View File

@ -18,14 +18,18 @@
*/
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.jclouds.virtualbox.domain.ExecutionType;
import org.testng.annotations.Test;
import org.virtualbox_4_1.*;
import org.virtualbox_4_1.IMachine;
import org.virtualbox_4_1.IProgress;
import org.virtualbox_4_1.ISession;
import org.virtualbox_4_1.SessionState;
import org.virtualbox_4_1.VirtualBoxManager;
@Test(groups = "unit", testName = "LaunchMachineIfNotAlreadyRunningTest")
public class LaunchMachineIfNotAlreadyRunningTest {

View File

@ -18,11 +18,11 @@
*/
package org.jclouds.virtualbox.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import org.testng.annotations.Test;
import org.virtualbox_4_1.IConsole;

View File

@ -1,56 +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.testng.Assert.assertEquals;
import java.io.InputStream;
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
/**
* @author Andrea Turli
*/
@Test(groups = "unit")
public class ImageFromYamlStreamTest {
public static final Image TEST1 = new ImageBuilder()
.id("myTestId")
.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();
@Test
public void testNodesParse() throws Exception {
InputStream is = getClass().getResourceAsStream("/testImages.yaml");
ImageFromYamlStream parser = new ImageFromYamlStream();
assertEquals(parser.apply(is).asMap(), ImmutableMap.of(TEST1.getId(), TEST1));
is.close();
}
}

View File

@ -0,0 +1,67 @@
/**
* 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.testng.Assert.assertEquals;
import java.io.InputStreamReader;
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.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
/**
* @author Andrea Turli
*/
@Test(groups = "unit")
public class ImageFromYamlStringTest {
public static final Image TEST1 = new ImageBuilder()
.id("myTestId")
.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();
@Test
public void testNodesParse() throws Exception {
final StringBuilder yamlFileLines = new StringBuilder();
for (Object line : IOUtils.readLines(new InputStreamReader(getClass().getResourceAsStream("/testImages.yaml")))) {
yamlFileLines.append(line).append("\n");
}
ImagesToYamlImagesFromYamlDescriptor parser = new ImagesToYamlImagesFromYamlDescriptor(new Supplier<String>() {
@Override
public String get() {
return yamlFileLines.toString();
}
});
assertEquals(Iterables.getFirst(parser.get().keySet(), null), TEST1);
}
}

View File

@ -19,15 +19,17 @@
package org.jclouds.virtualbox.functions.admin;
import org.eclipse.jetty.server.Server;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.testng.annotations.Test;
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 static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.*;
import static org.testng.Assert.assertEquals;
import org.eclipse.jetty.server.Server;
import org.jclouds.virtualbox.domain.IsoSpec;
import org.testng.annotations.Test;
/**
* @author Andrea Turli, Adrian Cole

View File

@ -18,17 +18,19 @@
*/
package org.jclouds.virtualbox.functions.admin;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.EasyMock.replay;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jclouds.virtualbox.domain.*;
import org.jclouds.virtualbox.domain.HardDisk;
import org.jclouds.virtualbox.domain.StorageController;
import org.jclouds.virtualbox.domain.VmSpec;
import org.testng.annotations.Test;
import org.virtualbox_4_1.CleanupMode;
import org.virtualbox_4_1.IMachine;

View File

@ -68,16 +68,14 @@ public class GuestAdditionsInstallerLiveTest extends
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
StorageController ideController = StorageController
.builder()
.name("IDE Controller")
.bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(
HardDisk.builder().diskpath(adminDisk)
.controllerPort(0).deviceSlot(1)
.autoDelete(true).build())
.attachISO(1, 1, guestAdditionsIso).build();
StorageController ideController = StorageController
.builder()
.name("IDE Controller")
.bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso)
.attachHardDisk(
HardDisk.builder().diskpath(adminDisk(sourceName)).controllerPort(0).deviceSlot(1)
.autoDelete(true).build()).attachISO(1, 1, guestAdditionsIso).build();
VmSpec sourceVmSpec = VmSpec.builder().id(sourceName).name(sourceName)
.osTypeId("").memoryMB(512).cleanUpMode(CleanupMode.Full)
@ -144,16 +142,4 @@ public class GuestAdditionsInstallerLiveTest extends
}
}
private void ensureMachineHasPowerDown(String vmName) {
machineUtils.lockSessionOnMachineAndApply(vmName, LockType.Shared,
new Function<ISession, Void>() {
@Override
public Void apply(ISession session) {
IProgress powerDownProgress = session.getConsole()
.powerDown();
powerDownProgress.waitForCompletion(-1);
return null;
}
});
}
}

View File

@ -23,6 +23,8 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE
import static org.jclouds.virtualbox.predicates.IMachinePredicates.isLinkedClone;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.jclouds.virtualbox.domain.CloneSpec;
import org.jclouds.virtualbox.domain.HardDisk;
@ -55,78 +57,67 @@ import com.google.inject.Injector;
@Test(groups = "live", singleThreaded = true, testName = "IMachinePredicatesLiveTest")
public class IMachinePredicatesLiveTest extends BaseVirtualBoxClientLiveTest {
private String osTypeId = "";
private String ideControllerName = "IDE Controller";
private String cloneName;
private String vmName;
private StorageController masterStorageController;
private MasterSpec masterMachineSpec;
private CloneSpec cloneSpec;
private String osTypeId = "";
private String ideControllerName = "IDE Controller";
private String cloneName;
private String vmName;
private StorageController masterStorageController;
private MasterSpec masterMachineSpec;
private NetworkSpec networkSpec;
private CloneSpec cloneSpec;
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
vmName = VIRTUALBOX_IMAGE_PREFIX
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
@Override
@BeforeClass(groups = "live")
public void setupClient() {
super.setupClient();
vmName = VIRTUALBOX_IMAGE_PREFIX + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
cloneName = VIRTUALBOX_IMAGE_PREFIX
+ "Clone#"
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass()
.getSimpleName());
cloneName = VIRTUALBOX_IMAGE_PREFIX + "Clone#"
+ CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, getClass().getSimpleName());
HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk)
.autoDelete(true).controllerPort(0).deviceSlot(1).build();
masterStorageController = StorageController.builder()
.name(ideControllerName).bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso).attachHardDisk(hardDisk)
.attachISO(1, 1, guestAdditionsIso).build();
VmSpec masterSpec = VmSpec.builder().id(vmName).name(vmName)
.memoryMB(512).osTypeId(osTypeId)
.controller(masterStorageController).forceOverwrite(true)
.cleanUpMode(CleanupMode.Full).build();
masterMachineSpec = MasterSpec
.builder()
.iso(IsoSpec.builder().sourcePath(operatingSystemIso)
.installationScript("").build()).vm(masterSpec)
.network(NetworkSpec.builder().build()).build();
HardDisk hardDisk = HardDisk.builder().diskpath(adminDisk(vmName)).autoDelete(true).controllerPort(0)
.deviceSlot(1).build();
masterStorageController = StorageController.builder().name(ideControllerName).bus(StorageBus.IDE)
.attachISO(0, 0, operatingSystemIso).attachHardDisk(hardDisk).attachISO(1, 1, guestAdditionsIso).build();
VmSpec masterSpec = VmSpec.builder().id(vmName).name(vmName).memoryMB(512).osTypeId(osTypeId)
.controller(masterStorageController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).build();
masterMachineSpec = MasterSpec.builder()
.iso(IsoSpec.builder().sourcePath(operatingSystemIso).installationScript("").build()).vm(masterSpec)
.network(NetworkSpec.builder().build()).build();
NetworkAdapter networkAdapter = NetworkAdapter.builder()
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
.builder().addNetworkAdapter(networkAdapter).build();
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.Bridged)
.build();
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
.build();
NetworkSpec networkSpec = NetworkSpec.builder()
.addNIC(0L, networkInterfaceCard).build();
this.networkSpec = NetworkSpec.builder().addNIC(0L, networkInterfaceCard).build();
VmSpec clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
.memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
}
cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(networkSpec)
.build();
}
@Test
public void testLinkedClone() {
@Test
public void testLinkedClone() {
Injector injector = context.utils().injector();
IMachine master = injector.getInstance(CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(
masterMachineSpec);
Injector injector = context.utils().injector();
IMachine master = injector.getInstance(
CreateAndRegisterMachineFromIsoIfNotAlreadyExists.class).apply(
masterMachineSpec);
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
manager, workingDir, cloneSpec, true, machineUtils)
.apply(master);
VmSpec clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName).memoryMB(512).cleanUpMode(CleanupMode.Full)
.forceOverwrite(true).build();
assertTrue(isLinkedClone().apply(clone));
}
this.cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(networkSpec).master(master).linked(true).build();
@BeforeMethod
@AfterMethod
void cleanUpVms() {
for (VmSpec spec : ImmutableSet.of(cloneSpec.getVmSpec(),
masterMachineSpec.getVmSpec()))
this.undoVm(spec);
}
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils)
.apply(cloneSpec);
assertTrue(isLinkedClone().apply(clone));
}
@BeforeMethod
@AfterMethod
void cleanUpVms() {
Set<VmSpec> specs = cloneSpec != null ? ImmutableSet.of(cloneSpec.getVmSpec(), masterMachineSpec.getVmSpec())
: ImmutableSet.of(masterMachineSpec.getVmSpec());
for (VmSpec spec : specs)
this.undoVm(spec);
}
}

View File

@ -19,13 +19,14 @@
package org.jclouds.virtualbox.statements;
import com.google.common.base.CaseFormat;
import com.google.inject.Injector;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import org.jclouds.virtualbox.BaseVirtualBoxClientLiveTest;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
import com.google.common.base.CaseFormat;
import com.google.inject.Injector;
/**
* @author Andrea Turli

View File

@ -31,9 +31,16 @@
<Pattern>%d %-5p [%c] (%t) %m%n</Pattern>
</layout>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%-4r [%thread] %-5level - %msg%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
<level value="debug" />
<appender-ref ref="CONSOLE" />
</root>
<logger name="org.jclouds">