diff --git a/labs/virtualbox/README.md b/labs/virtualbox/README.md index b618fa9d92..84fd2d6f4e 100644 --- a/labs/virtualbox/README.md +++ b/labs/virtualbox/README.md @@ -1,64 +1,238 @@ +# VirtualBox as a local cloud provider +jclouds-virtualbox is a local cloud provider modelled on the virtualbox hypervisor. Similar to other jclouds supported providers, it supports the same portable abstractions offered by jclouds. -#Setup +##Setup -Have virtualbox 4.1.20r80170 installed. +Please follow these steps to configure your workstation for jclouds-virtualbox: -Have an ssh daemon with passwordless login to localhost (i.e. "ssh [me]@localhost" must work without password). -To achieve that, be sure you have your ssh public key (at System.getProperty("user.home") + "/.ssh/id_rsa") in your '.ssh/authorized_keys'. -Please look at [this example]http://www.linuxproblem.org/art_9.html for more details. +- install the latest VirtualBox release (please visit https://www.virtualbox.org/wiki/Downloads) +- assign passwordless ssh and passwordless sudo rights to your user -You can have also specify '-Dvirtualbox.identity' and '-Dvirtualbox.credential' if you want to use a username and password of your local machine. +### Passwordless ssh -In order to make available a preseed file, jclouds-vbox will start a PreseedServer at `http://localhost:23232` that will serve a preseed.cfg file. -Make sure your firewall rules are not blocking this port. -If you need to override this default you can use -Djclouds.virtualbox.preconfigurationurl=http://localhost:PORT/preseed.cfg, with a different PORT. +jclouds-virtualbox uses the current user.name and private key for sending commands to localhost over ssh. -That's it! +The current user (user.name) should have passwordless ssh. On a *nix system, you can enable this feature using `ssh-keygen` and `ssh-copy-id`. --------------- +- ssh-keygen \- creates the public and private keys (by default in `${user.home}/.ssh/id_rsa.pub` and `${user.home}/.ssh/id_rsa`) +> $ ssh-keygen +- ssh-copy-id \- copies the user’s public key to a specified host’s `authorized_keys` file. +ssh-copy-id also assigns proper permission to the remote-host’s home, ~/.ssh, and ~/.ssh/authorized_keys -#Running a local cloud +In this case: +> $ ssh-copy-id -i ~/.ssh/id_rsa your-user@localhost -Enjoy local cloud goodness by running: +If your system does not have an `ssh-copy-id` command, use something like this: +> $ cat ~/.ssh/id_rsa.pub | ssh your-user@localhost "cat -> ~/.ssh/authorized_keys" -"mvn clean install clojure:repl" +### Passwordless sudo -> (use 'org.jclouds.compute2) -> (import 'org.jclouds.scriptbuilder.statements.login.AdminAccess) -> (def compute (compute-service "virtualbox" "user" "password" :sshj :slf4j)) -> (create-nodes compute "local-cluster" 2 (build-template compute { :run-script (AdminAccess/standard) } )) +You need to have passwordless sudo rights on localhost. This is done by editing the sudoers file (/etc/sudoers). Use caution when editing this file, as introducing errors will lock you out of the system. Therefore, it is recommended to edit this file through the visudo command. + +The sudoers file should have a line like this (replace your-user): +> your-user ALL=(ALL) NOPASSWD: ALL + +At this point, you should be able to login to localhost with `ssh your-user@localhost` without password. + +#How it works + + + --------------- ------------- + | Image(s) | | Node(s) | + --------------- ------------- + ------------------------------- ------- + | VirtualBox || Jetty | + ------------------------------- ------- + --------- passwordless ssh+sudo ---------------------------------------- + | jclouds | ---------------------------> | localhost | + --------- ---------------------------------------- + +###Components +- jclouds \- acts as a java (or clojure) client to access to virtualbox functionalities +- localhost \- hosts the VirtualBox hypervisor and a jetty server which is automatically installed by jclouds-virtualbox during Images creation +- VirtualBox \- jclouds-virtualbox assumes that the latest VirtualBox is installed (please see https://www.virtualbox.org/wiki/Downloads) +- Jetty \- in this scenario, this http server is used to serve the preseed.cfg specified in YAML descriptor file +- Image \- it logically represents a master VM (Virtual Machine) that can be cloned. It is a union of 2 sets of entities: + * a list of supported images, described in the YAML descriptor files + * a list of existing virtualbox VMs with name starting with "jclouds-image-0x0-" +- Node \- is a virtualbox VM, linked cloned from another virtualbox VM marked as Image + +## Image creation + + ssh --------------- + /----------------------------------> | Image(s) | + | --------------- + | ------------------------------- ------- + | | VirtualBox || Jetty | + | ------------------------------- ------- + --------- passwordless ssh+sudo ---------------------------------------- + | jclouds | ---------------------------> | localhost | + --------- ---------------------------------------- + +The OS supported by jclouds-virtualbox are described in a YAML file `default-images.yaml` stored at `src/main/resources/`. + +For each OS supported, it stores the following information: +a unique id, a name, a description, an os_arch, os_family, os_description, os_version, the iso url, the iso md5, username and credential to access this vm, a keystroke sequence for the OS installer and a preseed configuration file that contains the settings for this OS installation. + +For example, the corresponding YAML section for ubuntu 10.04.4 server (32 bit) looks like: + + - id: ubuntu-10.04.4-server-i386 + name: ubuntu-10.04-server-i386 + description: ubuntu 10.04.4 server (i386) + os_arch: x86 + os_family: ubuntu + os_description: ubuntu + os_version: 10.04.4 + iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-i386.iso + iso_md5: fc08a01e78348e3918180ea91a6883bb + username: toor + credential: password + keystroke_sequence: | + + /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg + debian-installer=en_US auto locale=en_US kbd-chooser/method=us + hostname=vmName + fb=false debconf/frontend=noninteractive + console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us + initrd=/install/initrd.gz -- + preseed_cfg: | + ## Options to set on the command line + d-i debian-installer/locale string en_US + d-i console-setup/ask_detect boolean false + d-i console-setup/layoutcode string us + d-i netcfg/get_hostname string unassigned-hostname + d-i netcfg/get_domain string unassigned-domain + d-i time/zone string UTC + d-i clock-setup/utc-auto boolean true + d-i clock-setup/utc boolean true + d-i kbd-chooser/method select American English + d-i netcfg/wireless_wep string + d-i base-installer/kernel/override-image string linux-server + d-i 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-auto/purge_lvm_from_device boolean true + d-i partman-lvm/confirm boolean true + d-i partman-lvm/device_remove_lvm boolean true + d-i partman-auto/choose_recipe select atomic + d-i partman/confirm_write_new_label boolean true + d-i partman/confirm_nooverwrite boolean true + d-i partman/choose_partition select finish + d-i partman/confirm boolean true + # 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 + 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 + +The OS isos and guest additions isos will be stored in the jclouds working directory (by default ~/.jclouds-vbox/isos/) + +##Cloning nodes + + ssh --------------- ------------- + /----------------------------------> | Node(s) | | Image | + | --------------- ------------- + | ------------------------------- + | | VirtualBox | + | ------------------------------- + --------- (a) passwordless ssh+sudo ---------------------------------------- + | jclouds | ---------------------------> | localhost | + --------- ---------------------------------------- + +###Cloning strategy +By default, a new node is cloned from a matching 'Image' with 'CloneOptions.Link'. This advanced option will save a lot of disk space and installation time as opposed to creating completely unique VMs for each new node. + +### Networking +Each Node will have 2 NICs (Network Interface Cards) to enable an NAT+Host-Only networking strategy: + +* NIC1 at port 0 will be attached to Host-Only network to allow localhost-nodes communication and node-node communication +* NIC2 at port 1 will be attached to NAT network to give each node internet access -------------- #Interacting with jclouds-vbox and connecting to machines -For java guidance look into src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java. +For java guidance, please see [src/test/java/org/jclouds/virtualbox/compute/VirtualBoxExperimentLiveTest.java]. For now nat+host-only is the only available network configuration, nodes should be accessible from the host by: -> ssh -i ~/.ssh/id_rsa -o "UserKnownHostsFile /dev/null" -o StrictHostKeyChecking=no me@192.168.86.X + ssh user@192.168.56.X -where X is the node index with regard to creation order starting at 2 (2,3,4, etc...) +where: -It *should* behave as any other provider, if not please report. +- user \- has passwordless ssh and sudo rights +- X (2-253) \- is assigned by DHCP server of `vboxnet0` + +-------------- + + +#Customization + +##Identity and Credential +By default, jclouds-virtualbox will try to use the current user (with passwordless ssh and sudo rights), but you can also override this default by specifying +`-Dvirtualbox.identity` and `-Dvirtualbox.credential`, if you want to use another user available on your local machine. + +##Preseed file +In order to make available a preseed file, jclouds-virtualbox will start a PreseedServer at `http://localhost:23232` that will serve a preseed.cfg file. +Make sure your firewall rules are not blocking this port. +If you need to override this default you can use `-Djclouds.virtualbox.preconfigurationurl=http://localhost:PORT/preseed.cfg`, with a different PORT. + +##Working directory +By default, cached isos for the OSs, guest additions, VMs and most configs are kept at the default working directory named `~/.jclouds-vbox/`, +you can override the default working directory using `-Dtest.virtualbox.workingDir=/path/to/your/workingDir`. + +##Host-Only network +jclouds-virtualbox needs an Host-Only network with DHCP enabled. This DHCP server will be responsible for assigning local IP addresses to the Nodes created by jclouds-virtualbox. + +jclouds-virtualbox will automatically create an Host-Only network with these settings: + +- IPv4: 192.168.56.1 +- IPv4 Network Mask: 255.255.255.0 +- DHCP Server: enabled + +with +- Server Address: 192.168.56.254 +- Server Mask: 255.255.255.0 +- Lower Address Bound: 192.168.56.2 +- Upper Address Bound: 192.168.56.253 + +Check virtualbox->Preferences->Networks for more details. + +**NB**: jclouds-virtualbox will not edit/replace a pre-exisiting Host-Only network. -------------- #Notes: -- jclouds-vbox is still at alpha stage please report any issues you find. -- jclouds-vbox has been mostly tested on Mac OSX, it might work on Linux iff vbox is running and correctly set up, but it won't work on windows for the moment. -- cached isos, vm's and most configs are kept at ~/.jclouds-vbox/ by default, you can override -Dtest.virtualbox.workingDir=/path/to/your/workingDir. -- jclouds-vbox assumes vbox has the default host-only network vboxnet0, that the network is in 192.168.86.0/255.255.255.0 and that the host has address 1 in this network. +- jclouds-virtualbox is still at alpha stage please report any issues you find at [jclouds issues](https://github.com/jclouds/jclouds/issues?state=open) or [jclouds google group](http://groups.google.com/group/jclouds). +- jclouds-virtualbox has been tested on Mac OSX, it might work on Linux iff vbox is running and set up correctly. However, it will not currently run on Windows. -------------- -#Throubleshooting +#Troubleshooting -As jclouds vbox support is quite new things might go wrong sometimes. The procedure to make things work again is the following: +As jclouds vbox support is quite new, issues may occasionally arise. Please follow these steps to get things going again: -1. Remove all relevant vm's (named "jclouds-* ") with the vbox GUI. Make sure to select "delete all files". -- Step one should be enough most of the times, but if it fails (by throwing some error): -2. kill all vbox processes (VboxHadless, VBoxSVC, VBoxXPCOMIPCD, VirtualBox, vboxwebsrv) -3. delete manually the files by executing: "rm -rf ~/.jclouds-vbox/jclouds-*" -4. restart the vbox GUI and make sure to delete all remaining machines ignoring all errors. - \ No newline at end of file +1. Remove all relevant VMs (named "jclouds-* ") with the vbox GUI. Make sure to select "delete all files". This step will solve most issues. +2. If you are still receiving errors, please try the following steps to resolve any issues: + * Kill all vbox processes (VboxHadless, VBoxSVC, VBoxXPCOMIPCD, VirtualBox, vboxwebsrv) + * Manually delete the files by executing: "rm -rf ~/.jclouds-vbox/jclouds-*" + * Restart the vbox GUI and make sure to delete all remaining machines while ignoring all errors diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxApiMetadata.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxApiMetadata.java index 027981ec2e..6a3f32be5b 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxApiMetadata.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/VirtualBoxApiMetadata.java @@ -22,7 +22,6 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAULT_DIR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_MEMORY; 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.VIRTUALBOX_WORKINGDIR; @@ -61,14 +60,6 @@ public class VirtualBoxApiMetadata extends BaseApiMetadata { public static Properties defaultProperties() { Properties properties = BaseApiMetadata.defaultProperties(); - - properties.put(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE, " " - + "/install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL " - + "debian-installer=en_US auto locale=en_US kbd-chooser/method=us " - + "hostname=" + "HOSTNAME " - + "fb=false debconf/frontend=noninteractive " - + "console-setup/ask_detect=false keyboard-configuration/layoutcode=us " - + "initrd=/install/initrd.gz -- "); String workingDir = System.getProperty("test.virtualbox.workingDir", VIRTUALBOX_DEFAULT_DIR); properties.put(VIRTUALBOX_WORKINGDIR, workingDir); @@ -80,7 +71,7 @@ public class VirtualBoxApiMetadata extends BaseApiMetadata { + File.separator + "images.yaml"); properties.put(VIRTUALBOX_IMAGES_DESCRIPTOR, yamlDescriptor); - properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232/preseed.cfg"); + properties.put(VIRTUALBOX_PRECONFIGURATION_URL, "http://10.0.2.2:23232"); properties.setProperty(TEMPLATE, "osFamily=UBUNTU,osVersionMatches=12.04.1,os64Bit=true,osArchMatches=amd64"); return properties; } @@ -97,8 +88,8 @@ public class VirtualBoxApiMetadata extends BaseApiMetadata { .defaultCredential("CHANGE_ME") .defaultEndpoint("http://localhost:18083/") .documentation(URI.create("https://github.com/jclouds/jclouds/tree/master/labs/virtualbox")) - .version("4.2.4") - .buildVersion("4.2.4") + .version("4.2.6") + .buildVersion("4.2.6") .defaultProperties(VirtualBoxApiMetadata.defaultProperties()) .view(ComputeServiceContext.class) .defaultModules(ImmutableSet.>of(HardcodeLocalhostAsNodeMetadataSupplier.class, VirtualBoxComputeServiceContextModule.class)); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapter.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapter.java index 972b6d935a..e7f8872606 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapter.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapter.java @@ -65,7 +65,7 @@ import com.google.common.collect.Sets; import com.google.inject.Singleton; /** - * Defines the connection between the {@link org.virtualbox_4_1.VirtualBoxManager} implementation + * Defines the connection between the {@link org.virtualbox_4_2.VirtualBoxManager} implementation * and the jclouds {@link org.jclouds.compute.ComputeService} * * @author Mattias Holmqvist, Andrea Turli, David Alves diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java index a3f5d8804c..40d01797f4 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/config/VirtualBoxConstants.java @@ -37,8 +37,6 @@ public interface VirtualBoxConstants { 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_IMAGES_DESCRIPTOR = "jclouds.virtualbox.image.descriptor.yaml"; diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachine.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachine.java new file mode 100644 index 0000000000..a0f45b4c40 --- /dev/null +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachine.java @@ -0,0 +1,48 @@ +/** + * 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 com.google.common.base.Function; +import org.virtualbox_4_2.DeviceType; +import org.virtualbox_4_2.IMachine; + +import java.util.Map; + +/** + * @author Andrea Turli + */ +public class ApplyBootOrderToMachine implements Function { + + + private Map positionAndDeviceType; + + public ApplyBootOrderToMachine(Map positionAndDeviceType) { + this.positionAndDeviceType = positionAndDeviceType; + } + + @Override + public Void apply(IMachine machine) { + for(long position : positionAndDeviceType.keySet()) { + machine.setBootOrder(position, positionAndDeviceType.get(position)); + } + machine.saveSettings(); + return null; + } +} diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyMemoryToMachine.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyMemoryToMachine.java index 1691fbc454..8d7e51f5b4 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyMemoryToMachine.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/ApplyMemoryToMachine.java @@ -26,7 +26,7 @@ import com.google.common.base.Function; /** * @author Mattias Holmqvist */ -public class ApplyMemoryToMachine implements Function { +public class ApplyMemoryToMachine implements Function { private long memorySize; @@ -35,7 +35,7 @@ public class ApplyMemoryToMachine implements Function { } @Override - public Object apply(IMachine machine) { + public Void apply(IMachine machine) { machine.setMemorySize(memorySize); machine.saveSettings(); return null; diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java index c1497fd8c9..eb29239b0f 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndInstallVm.java @@ -18,6 +18,7 @@ */ package org.jclouds.virtualbox.functions; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.transform; import static org.jclouds.scriptbuilder.domain.Statements.call; @@ -96,14 +97,14 @@ public class CreateAndInstallVm implements Function { VmSpec vmSpec = masterSpec.getVmSpec(); IsoSpec isoSpec = masterSpec.getIsoSpec(); String masterName = vmSpec.getVmName(); - IMachine masterMachine = createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec); + IMachine masterMachine = + checkNotNull(createAndRegisterMachineFromIsoIfNotAlreadyExists.apply(masterSpec), "master machine"); // Launch machine and wait for it to come online machineController.ensureMachineIsLaunched(masterName); String installationKeySequence = isoSpec.getInstallationKeySequence().replace("PRECONFIGURATION_URL", preconfigurationUrl); - configureOsInstallationWithKeyboardSequence(masterName, installationKeySequence); - + masterMachine.setExtraData(GUEST_OS_USER, masterSpec.getLoginCredentials().getUser()); masterMachine.setExtraData(GUEST_OS_PASSWORD, masterSpec.getLoginCredentials().getPassword()); @@ -155,7 +156,6 @@ public class CreateAndInstallVm implements Function { private void configureOsInstallationWithKeyboardSequence(String vmName, String installationKeySequence) { Iterable> scancodelist = transform(Splitter.on(" ").split(installationKeySequence), new StringToKeyCode()); - for (List scancodes : scancodelist) { machineUtils.sharedLockMachineAndApplyToSession(vmName, new SendScancodes(scancodes)); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExists.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExists.java index a8227d5343..f7e83a9cd2 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExists.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/CreateAndRegisterMachineFromIsoIfNotAlreadyExists.java @@ -23,7 +23,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException; import java.io.File; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -32,6 +34,8 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import org.jclouds.virtualbox.config.VirtualBoxConstants; @@ -116,6 +120,10 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi NetworkSpec networkSpec = machineSpec.getNetworkSpec(); String vmName = vmSpec.getVmName(); + // Change BootOrder + Map positionAndDeviceType = ImmutableMap.of(1l, DeviceType.HardDisk); + ensureMachineHasDesiredBootOrder(vmName, positionAndDeviceType); + // Change RAM ensureMachineHasMemory(vmName, vmSpec.getMemory()); @@ -171,6 +179,10 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi } } + private void ensureMachineHasDesiredBootOrder(String vmName, Map positionAndDeviceType) { + machineUtils.writeLockMachineAndApply(vmName, new ApplyBootOrderToMachine(positionAndDeviceType)); + } + private void ensureMachineHasMemory(String vmName, final long memorySize) { machineUtils.writeLockMachineAndApply(vmName, new ApplyMemoryToMachine(memorySize)); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IpAddressesLoadingCache.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IpAddressesLoadingCache.java index b02707b8a6..f56fd57e0d 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IpAddressesLoadingCache.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IpAddressesLoadingCache.java @@ -71,8 +71,10 @@ public class IpAddressesLoadingCache extends String query = String.format("/VirtualBox/GuestInfo/Net/%s/V4/IP", machineNameOrIdAndNicPort.getSlotText()); String ipAddress = Strings.nullToEmpty(manager.get().getVBox() .findMachine(machineNameOrIdAndNicPort.getMachineNameOrId()).getGuestPropertyValue(query)); - logger.debug("<< vm(%s) has IP address(%s) at slot(%s)", machineNameOrIdAndNicPort.getMachineNameOrId(), + if(!ipAddress.isEmpty()) { + logger.debug("<< vm(%s) has IP address(%s) at slot(%s)", machineNameOrIdAndNicPort.getMachineNameOrId(), ipAddress, machineNameOrIdAndNicPort.getSlotText()); + } masters.put(machineNameOrIdAndNicPort, ipAddress); return ipAddress; } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java index 81042bc231..2c5af77823 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/MastersLoadingCache.java @@ -25,7 +25,6 @@ import static com.google.common.base.Preconditions.checkState; import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; 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_NODE_NAME_SEPARATOR; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR; @@ -112,7 +111,6 @@ public class MastersLoadingCache extends AbstractLoadingCache { private final Function masterCreatorAndInstaller; private final Map imageMapping; private final String workingDir; - private final String installationKeySequence; private final String isosDir; private final Supplier manager; private final String version; @@ -126,7 +124,6 @@ public class MastersLoadingCache extends AbstractLoadingCache { @Inject public MastersLoadingCache(@BuildVersion String version, - @Named(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) String installationKeySequence, @Named(VIRTUALBOX_PRECONFIGURATION_URL) String preconfigurationUrl, @Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function masterLoader, Supplier> yamlMapper, Supplier manager, @@ -134,7 +131,6 @@ public class MastersLoadingCache extends AbstractLoadingCache { @Provider Supplier providerSupplier, HardcodedHostToHostNodeMetadata hardcodedHostToHostNodeMetadata) { this.manager = checkNotNull(manager, "vboxmanager can't be null"); this.masterCreatorAndInstaller = masterLoader; - this.installationKeySequence = checkNotNull(installationKeySequence, "installationKeySequence can't be null"); this.workingDir = workingDir == null ? VIRTUALBOX_DEFAULT_DIR : workingDir; this.isosDir = workingDir + File.separator + "isos"; this.imageMapping = Maps.newLinkedHashMap(); @@ -235,16 +231,20 @@ public class MastersLoadingCache extends AbstractLoadingCache { NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); - return MasterSpec - .builder() - .vm(vmSpecification) - .iso(IsoSpec.builder().sourcePath(localIsoUrl) - .installationScript(installationKeySequence.replace("HOSTNAME", vmSpecification.getVmName())).build()) - .network(networkSpec) - .credentials(LoginCredentials.builder() - .user(currentImage.username) - .password(currentImage.credential) - .authenticateSudo(true).build()).build(); + String installationSequence = currentImage.keystroke_sequence.replace("HOSTNAME", vmSpecification.getVmName()); + return MasterSpec.builder() + .vm(vmSpecification) + .iso(IsoSpec.builder() + .sourcePath(localIsoUrl) + .installationScript(installationSequence) + .build()) + .network(networkSpec) + .credentials(LoginCredentials.builder() + .user(currentImage.username) + .password(currentImage.credential) + .authenticateSudo(true) + .build()) + .build(); } @Override @@ -267,18 +267,18 @@ public class MastersLoadingCache extends AbstractLoadingCache { List statements = new ImmutableList.Builder().add( Statements.saveHttpResponseTo(URI.create(httpUrl), isosDir, fileName)).build(); StatementList statementList = new StatementList(statements); - NodeMetadata hostNodeMetadata = hardcodedHostToHostNodeMetadata.apply(host.get()); - ListenableFuture future = runScriptOnNodeFactory.submit(hostNodeMetadata, statementList, + NodeMetadata hostNode = checkNotNull(hardcodedHostToHostNodeMetadata.apply(host.get()), "hostNode"); + ListenableFuture future = runScriptOnNodeFactory.submit(hostNode, statementList, runAsRoot(false)); Futures.getUnchecked(future); if (expectedMd5 != null) { String filePath = isosDir + File.separator + fileName; - ListenableFuture md5future = runScriptOnNodeFactory.submit(hostNodeMetadata, new Md5(filePath), + ListenableFuture md5future = runScriptOnNodeFactory.submit(hostNode, new Md5(filePath), runAsRoot(false)); ExecResponse responseMd5 = Futures.getUnchecked(md5future); - assert responseMd5.getExitStatus() == 0 : hostNodeMetadata.getId() + ": " + responseMd5; + assert responseMd5.getExitStatus() == 0 : hostNode.getId() + ": " + responseMd5; checkNotNull(responseMd5.getOutput(), "iso_md5 missing"); String actualMd5 = responseMd5.getOutput().trim(); checkState(actualMd5.equals(expectedMd5), "md5 of %s is %s but expected %s", filePath, actualMd5, expectedMd5); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java index 3243dcfd04..efcf7cb54e 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/NodeCreator.java @@ -19,54 +19,39 @@ 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.GUEST_OS_PASSWORD; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.GUEST_OS_USER; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_GUEST_MEMORY; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_NAME_SEPARATOR; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_NODE_PREFIX; + import com.google.common.base.*; + import com.google.common.collect.ImmutableSet; + import com.google.common.collect.Iterables; + import com.google.common.io.Files; + import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; + import org.jclouds.compute.domain.NodeMetadata; + import org.jclouds.compute.domain.NodeMetadataBuilder; + import org.jclouds.compute.options.RunScriptOptions; + import org.jclouds.compute.reference.ComputeServiceConstants; + import org.jclouds.domain.LoginCredentials; + import org.jclouds.logging.Logger; + import org.jclouds.util.Strings2; + import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; + import org.jclouds.virtualbox.domain.*; + import org.jclouds.virtualbox.statements.DeleteGShadowLock; + import org.jclouds.virtualbox.statements.PasswordlessSudo; + import org.jclouds.virtualbox.util.MachineController; + import org.jclouds.virtualbox.util.MachineUtils; + import org.jclouds.virtualbox.util.NetworkUtils; + import org.virtualbox_4_2.*; + import com.google.common.collect.ImmutableList; -import javax.annotation.Resource; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; + import javax.annotation.Resource; + import javax.inject.Inject; + import javax.inject.Named; + import javax.inject.Singleton; -import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; -import org.jclouds.compute.callables.RunScriptOnNode; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeMetadataBuilder; -import org.jclouds.compute.options.RunScriptOptions; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.domain.LoginCredentials; -import org.jclouds.logging.Logger; -import org.jclouds.virtualbox.config.VirtualBoxComputeServiceContextModule; -import org.jclouds.virtualbox.domain.CloneSpec; -import org.jclouds.virtualbox.domain.Master; -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.statements.DeleteGShadowLock; -import org.jclouds.virtualbox.statements.PasswordlessSudo; -import org.jclouds.virtualbox.util.MachineController; -import org.jclouds.virtualbox.util.MachineUtils; -import org.jclouds.virtualbox.util.NetworkUtils; -import org.virtualbox_4_2.CleanupMode; -import org.virtualbox_4_2.IMachine; -import org.virtualbox_4_2.IProgress; -import org.virtualbox_4_2.ISession; -import org.virtualbox_4_2.LockType; -import org.virtualbox_4_2.NetworkAttachmentType; -import org.virtualbox_4_2.VirtualBoxManager; + import java.io.File; + import java.io.IOException; -import com.google.common.base.Function; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; + import static com.google.common.base.Preconditions.checkNotNull; + import static com.google.common.base.Preconditions.checkState; + import static org.jclouds.virtualbox.config.VirtualBoxConstants.*; /** * Creates nodes, by cloning a master vm and based on the provided {@link NodeSpec}. Must be @@ -88,26 +73,182 @@ public class NodeCreator implements Function manager, Function cloner, - MachineUtils machineUtils, RunScriptOnNode.Factory scriptRunnerFactory, MachineController machineController, + MachineUtils machineUtils, MachineController machineController, NetworkUtils networkUtils, - @Named(VIRTUALBOX_GUEST_MEMORY) String ram) { - this.manager = manager; - this.cloner = cloner; - this.networkUtils = networkUtils; - this.machineUtils = machineUtils; - this.machineController = machineController; - this.ram = Integer.valueOf(ram); + @Named(VIRTUALBOX_GUEST_MEMORY) String ram, + @Named(VIRTUALBOX_WORKINGDIR) String workingDir) { + this.manager = checkNotNull(manager, "manager"); + this.cloner = checkNotNull(cloner, "cloner"); + this.networkUtils = checkNotNull(networkUtils, "networkUtils"); + this.machineUtils = checkNotNull(machineUtils, "machineUtils"); + this.machineController = checkNotNull(machineController, "machineController"); + this.ram = checkNotNull(Integer.valueOf(ram), "ram"); + this.workingDir = checkNotNull(workingDir, "workingDir"); } @Override public synchronized NodeAndInitialCredentials apply(NodeSpec nodeSpec) { checkNotNull(nodeSpec, "NodeSpec"); Master master = checkNotNull(nodeSpec.getMaster(), "Master"); - + IMachine masterMachine = master.getMachine(); + String guestOsUser = masterMachine.getExtraData(GUEST_OS_USER); + String guestOsPassword = masterMachine.getExtraData(GUEST_OS_PASSWORD); + + cleanUpMaster(master); + CloneSpec cloneSpec = configureCloneSpec(nodeSpec, guestOsUser, guestOsPassword); + IMachine clone = cloner.apply(cloneSpec); + String cloneName = cloneSpec.getVmSpec().getVmName(); + logger.debug("<< cloned a vm(%s) from master(%s)", cloneName, nodeSpec.getMaster().getMachine().getName()); + machineController.ensureMachineIsLaunched(cloneName); + logger.debug("<< cloned vm(%s) is up and running", cloneName); + + reconfigureNetworkInterfaces(masterMachine, guestOsUser, guestOsPassword, cloneSpec.getNetworkSpec(), clone); + + postConfigurations(clone, guestOsUser, guestOsPassword); + + LoginCredentials credentials = LoginCredentials.builder() + .user(guestOsUser) + .password(guestOsPassword) + .authenticateSudo(true) + .build(); + return new NodeAndInitialCredentials(clone, cloneName, credentials); + } + + private void reconfigureNetworkInterfaces(IMachine masterMachine, String guestOsUser, String guestOsPassword, NetworkSpec networkSpec, IMachine clone) { + reconfigureHostOnlyInterfaceIfNeeded(guestOsUser, guestOsPassword, clone.getName(), masterMachine.getOSTypeId()); + logger.debug("<< reconfigured hostOnly interface of node(%s)", clone.getName()); + reconfigureNatInterfaceIfNeeded(guestOsUser, guestOsPassword, clone.getOSTypeId(), clone, networkSpec); + logger.debug("<< reconfigured NAT interface of node(%s)", clone.getName()); + } + + /** + * {@see DeleteGShadowLock} and {@see PasswordlessSudo} for a detailed explanation + * + * @param clone the target machine + * @param guestOsUser the user to access the target machine + * @param guestOsPassword the password to access the target machine + */ + private void postConfigurations(IMachine clone, String guestOsUser, String guestOsPassword) { + NodeMetadata partialNodeMetadata = buildPartialNodeMetadata(clone, guestOsUser, guestOsPassword); + machineUtils.runScriptOnNode(partialNodeMetadata, new DeleteGShadowLock(), RunScriptOptions.NONE); + machineUtils.runScriptOnNode(partialNodeMetadata, new PasswordlessSudo(partialNodeMetadata.getCredentials().identity), RunScriptOptions.Builder.runAsRoot(true)); + } + + private CloneSpec configureCloneSpec( + NodeSpec nodeSpec, String guestOsUser, String guestOsPassword) { + + String cloneName = generateCloneName(nodeSpec); + + VmSpec cloneVmSpec = VmSpec.builder() + .id(cloneName) + .name(cloneName) + .memoryMB(ram) + .osTypeId(nodeSpec.getMaster().getMachine().getOSTypeId()) + .guestUser(guestOsUser) + .guestPassword(guestOsPassword) + .cleanUpMode(CleanupMode.Full) + .forceOverwrite(true) + .build(); + + // case 'vbox host is localhost': NAT + HOST-ONLY + NetworkSpec networkSpec = networkUtils.createNetworkSpecWhenVboxIsLocalhost(); + + return CloneSpec.builder() + .linked(true) + .master(nodeSpec.getMaster().getMachine()) + .network(networkSpec) + .vm(cloneVmSpec).build(); + } + + private void cleanUpMaster(Master master) { + deleteExistingSnapshot(master); + } + + private void reconfigureHostOnlyInterfaceIfNeeded(final String username, final String password, + String vmName, String osTypeId) { + final String scriptName = "hostOnly"; + if (osTypeId.contains("RedHat")) { + File scriptFile = copyScriptToWorkingDir("redHatAndDerivatives", scriptName); + copyToNodeAndExecScript(username, password, vmName, scriptFile); + } + } + + private void reconfigureNatInterfaceIfNeeded(final String guestOsUser, final String guestOsPassword, + String osTypeId, IMachine clone, NetworkSpec networkSpec) { + + final String scriptName = "nat"; + final String folder = "redHatAndDerivatives"; + if (osTypeId.contains("RedHat")) { + File scriptFile = copyScriptToWorkingDir(folder, scriptName); + copyToNodeAndExecScript(guestOsUser, guestOsPassword, clone.getName(), scriptFile); + } else if (osTypeId.contains("Ubuntu") || osTypeId.contains("Debian")) { + NodeMetadata partialNodeMetadata = buildPartialNodeMetadata(clone, guestOsUser, guestOsPassword); + + Optional optionalNatIfaceCard = Iterables.tryFind( + networkSpec.getNetworkInterfaceCards(), + new Predicate() { + + @Override + public boolean apply(NetworkInterfaceCard nic) { + return nic.getNetworkAdapter().getNetworkAttachmentType() + .equals(NetworkAttachmentType.NAT); + } + }); + + checkState(networkUtils.enableNetworkInterface(partialNodeMetadata, optionalNatIfaceCard.get()), + "cannot enable NAT Interface on vm(%s)", clone.getName()); + } + } + + private File copyScriptToWorkingDir(String folder, String scriptName) { + File scriptFile = new File(workingDir + "/conf/" + "/" + folder + "/" + scriptName); + scriptFile.getParentFile().mkdirs(); + if (!scriptFile.exists()) { + try { + Files.write(Strings2.toStringAndClose(getClass().getResourceAsStream("/" + folder + "/" + scriptName)), scriptFile, Charsets.UTF_8); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return scriptFile; + } + + private void copyToNodeAndExecScript(final String username, final String password, + String vmName, final File scriptFile) { + machineUtils.sharedLockMachineAndApplyToSession(vmName, new Function() { + + @Override + public Void apply(ISession session) { + String scriptName = scriptFile.getName(); + + manager.get().getSessionObject().getConsole().getGuest() + .createSession(username, password, null, null) + .copyTo(scriptFile.getAbsolutePath(), "/tmp/" + scriptName, null); + + manager.get().getSessionObject().getConsole().getGuest() + .createSession(username, password, null, null) + .processCreate("/bin/chmod", ImmutableList.of("777", "/tmp/" + scriptName), null, null, 5 * 1000l); + + manager.get().getSessionObject().getConsole().getGuest() + .createSession(username, password, null, null) + .processCreate("/bin/sh", ImmutableList.of("/tmp/" + scriptName), null, null, 5 * 1000l); + return null; + } + }); + } + + private String generateCloneName(NodeSpec nodeSpec) { + String masterNameWithoutPrefix = nodeSpec.getMaster().getMachine().getName().replace(VIRTUALBOX_IMAGE_PREFIX, ""); + return VIRTUALBOX_NODE_PREFIX + masterNameWithoutPrefix + VIRTUALBOX_NODE_NAME_SEPARATOR + + nodeSpec.getTag() + VIRTUALBOX_NODE_NAME_SEPARATOR + nodeSpec.getName(); + } + + private void deleteExistingSnapshot(Master master) { if (master.getMachine().getCurrentSnapshot() != null) { ISession session; try { @@ -121,86 +262,18 @@ public class NodeCreator implements Function optionalNatIfaceCard = Iterables.tryFind( - networkSpec.getNetworkInterfaceCards(), - new Predicate() { - - @Override - public boolean apply(NetworkInterfaceCard nic) { - return nic.getNetworkAdapter().getNetworkAttachmentType() - .equals(NetworkAttachmentType.NAT); - } - }); - CloneSpec cloneSpec = CloneSpec.builder().linked(true).master(master.getMachine()).network(networkSpec) - .vm(cloneVmSpec).build(); - - IMachine cloned = cloner.apply(cloneSpec); - logger.debug("<< cloned a vm(%s) from master(%s)", cloneName, master.getMachine().getName()); - machineController.ensureMachineIsLaunched(cloneVmSpec.getVmName()); - - // IMachineToNodeMetadata produces the final ip's but these need to be set before so we build a - // NodeMetadata just for the sake of running the gshadow and setip scripts - NodeMetadata partialNodeMetadata = buildPartialNodeMetadata(cloned); - - // see DeleteGShadowLock for a detailed explanation - machineUtils.runScriptOnNode(partialNodeMetadata, new DeleteGShadowLock(), RunScriptOptions.NONE); - - - if(optionalNatIfaceCard.isPresent()) - checkState(networkUtils.enableNetworkInterface(partialNodeMetadata, optionalNatIfaceCard.get()), - "cannot enable NAT Interface on vm(%s)", cloneName); - - // apply passwordless ssh script to each clone - machineUtils.runScriptOnNode(partialNodeMetadata, new PasswordlessSudo(partialNodeMetadata.getCredentials().identity), RunScriptOptions.Builder.runAsRoot(true)); - - LoginCredentials credentials = partialNodeMetadata.getCredentials(); - return new NodeAndInitialCredentials(cloned, cloneName, credentials); - } - private NodeMetadata buildPartialNodeMetadata(IMachine clone) { + private NodeMetadata buildPartialNodeMetadata(IMachine clone, String guestOsUser, String guestOsPassword) { NodeMetadataBuilder nodeMetadataBuilder = new NodeMetadataBuilder(); nodeMetadataBuilder.id(clone.getName()); nodeMetadataBuilder.status(VirtualBoxComputeServiceContextModule.toPortableNodeStatus.get(clone.getState())); - long slot = findSlotForNetworkAttachment(clone, NetworkAttachmentType.HostOnly); - nodeMetadataBuilder.publicAddresses(ImmutableSet.of(networkUtils.getIpAddressFromNicSlot(clone.getName(), slot))); - String guestOsUser = clone.getExtraData(GUEST_OS_USER); - String guestOsPassword = clone.getExtraData(GUEST_OS_PASSWORD); + nodeMetadataBuilder.publicAddresses(ImmutableSet.of(networkUtils.getValidHostOnlyIpFromVm(clone.getName()))); nodeMetadataBuilder.credentials(LoginCredentials.builder() .user(guestOsUser) .password(guestOsPassword) - .authenticateSudo(true).build()); + .authenticateSudo(true).build()); return nodeMetadataBuilder.build(); } - - private long findSlotForNetworkAttachment(IMachine clone, NetworkAttachmentType networkAttachmentType) { - long slot = -1; - long i = 0; - while (slot == -1 && i < 4) { - if(clone.getNetworkAdapter(i).getAttachmentType().equals(networkAttachmentType)) { - slot = i; - break; - } - i++; - } - checkState(slot!=-1); - return slot; - } - } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java index 88ef7186a2..57f2b2fbd0 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/statements/EnableNetworkInterface.java @@ -65,8 +65,8 @@ public class EnableNetworkInterface implements Statement { private List getStatements(String iface) { List statements = Lists.newArrayList(); - statements.add(exec(String.format("echo auto %s >> /etc/network/interfaces", iface))); // - statements.add(exec(String.format("echo iface %s inet dhcp >> /etc/network/interfaces", iface))); // + statements.add(exec(String.format("echo auto %s >> /etc/network/interfaces", iface))); + statements.add(exec(String.format("echo iface %s inet dhcp >> /etc/network/interfaces", iface))); statements.add(exec("/etc/init.d/networking restart")); return statements; } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java index bd45006bd6..5039b9c0a1 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/MachineUtils.java @@ -73,8 +73,7 @@ public class MachineUtils { @Inject - public MachineUtils(Supplier manager, RunScriptOnNode.Factory scriptRunner, - IpAddressesLoadingCache ipAddressesLoadingCache) { + public MachineUtils(Supplier manager, RunScriptOnNode.Factory scriptRunner) { this.manager = manager; this.scriptRunner = scriptRunner; } @@ -217,7 +216,7 @@ public class MachineUtils { private ISession lockSession(String machineId, LockType type, int retries) { int count = 0; IMachine immutableMachine = manager.get().getVBox().findMachine(machineId); - ISession session = null; + ISession session; while (true) { try { session = manager.get().getSessionObject(); diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/NetworkUtils.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/NetworkUtils.java index fba6a13f81..72bfc835f9 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/NetworkUtils.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/util/NetworkUtils.java @@ -25,6 +25,7 @@ import static org.jclouds.compute.options.RunScriptOptions.Builder.runAsRoot; import java.net.URI; import java.util.List; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -32,6 +33,7 @@ import javax.annotation.Resource; import javax.inject.Named; import javax.inject.Singleton; +import com.google.common.util.concurrent.Uninterruptibles; import org.jclouds.compute.callables.RunScriptOnNode; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.NodeMetadata; @@ -93,10 +95,9 @@ public class NetworkUtils { private final Supplier hostSupplier; @Inject - public NetworkUtils(Supplier manager, MachineUtils machineUtils, - MachineController machineController, Supplier host, @Provider Supplier providerSupplier, - IpAddressesLoadingCache ipAddressesLoadingCache, Supplier hostSupplier, - RunScriptOnNode.Factory scriptRunnerFactory) { + public NetworkUtils(Supplier manager, MachineUtils machineUtils, Supplier host, + @Provider Supplier providerSupplier, IpAddressesLoadingCache ipAddressesLoadingCache, + Supplier hostSupplier, RunScriptOnNode.Factory scriptRunnerFactory) { this.manager = manager; this.machineUtils = machineUtils; this.host = checkNotNull(host, "host can't be null"); @@ -131,9 +132,8 @@ public class NetworkUtils { } public boolean enableNetworkInterface(NodeMetadata nodeMetadata, NetworkInterfaceCard networkInterfaceCard) { - ListenableFuture execEnableNetworkInterface = null; - execEnableNetworkInterface = machineUtils.runScriptOnNode(nodeMetadata, new EnableNetworkInterface( - networkInterfaceCard), RunScriptOptions.NONE); + ListenableFuture execEnableNetworkInterface = machineUtils.runScriptOnNode(nodeMetadata, + new EnableNetworkInterface(networkInterfaceCard), RunScriptOptions.NONE); ExecResponse execEnableNetworkInterfaceResponse = Futures.getUnchecked(execEnableNetworkInterface); return execEnableNetworkInterfaceResponse.getExitStatus() == 0; } @@ -208,14 +208,9 @@ public class NetworkUtils { null); } - /** - * @param availableNetworkInterfaces - * @param hostOnlyIfIpAddress - * @return - */ private Iterable filterAvailableNetworkInterfaceByHostOnlyAndDHCPenabled( Iterable availableNetworkInterfaces) { - Iterable filteredNetworkInterfaces = Iterables.filter(availableNetworkInterfaces, + return Iterables.filter(availableNetworkInterfaces, new Predicate() { @Override public boolean apply(IHostNetworkInterface iHostNetworkInterface) { @@ -232,24 +227,28 @@ public class NetworkUtils { return iHostNetworkInterface.getInterfaceType().equals(HostNetworkInterfaceType.HostOnly) && match; } }); - return filteredNetworkInterfaces; } public String getValidHostOnlyIpFromVm(String machineNameOrId) { long nicSlot = 0; + int count = 0; String ipAddress = ""; while (nicSlot < 4 && ipAddress.isEmpty()) { - MachineNameOrIdAndNicSlot machineNameOrIdAndNicSlot = MachineNameOrIdAndNicSlot.fromParts(machineNameOrId, - nicSlot); - ipAddress = getIpAddressFromNicSlot(machineNameOrIdAndNicSlot); - if (!isValidIpForHostOnly(machineNameOrIdAndNicSlot, ipAddress)) { - ipAddressesLoadingCache.invalidate(machineNameOrIdAndNicSlot); - ipAddress = ""; + MachineNameOrIdAndNicSlot machineNameOrIdAndNicSlot = + MachineNameOrIdAndNicSlot.fromParts(machineNameOrId, nicSlot); + while (count < 10 && ipAddress.isEmpty()) { + Uninterruptibles.sleepUninterruptibly(3, TimeUnit.SECONDS); + ipAddress = getIpAddressFromNicSlot(machineNameOrIdAndNicSlot); + if (!isValidIpForHostOnly(ipAddress)) { + ipAddressesLoadingCache.invalidate(machineNameOrIdAndNicSlot); + ipAddress = ""; + } + count++; } nicSlot++; } return checkNotNull(Strings.emptyToNull(ipAddress), - String.format("Cannot find a valid IP address for the %s's HostOnly NIC", machineNameOrId)); + String.format("Cannot find a valid IP address for the %s's HostOnly NIC", machineNameOrId)); } public String getIpAddressFromNicSlot(String machineNameOrId, long nicSlot) { @@ -267,7 +266,7 @@ public class NetworkUtils { } } - public boolean isValidIpForHostOnly(MachineNameOrIdAndNicSlot machineNameOrIdAndNicSlot, String ip) { + public boolean isValidIpForHostOnly(String ip) { return !ip.isEmpty() && isIpv4(ip) && !ipBelongsToNatRange(ip) && !ipEqualsToNatGateway(ip); } @@ -287,12 +286,12 @@ public class NetworkUtils { return ip.startsWith("10.0.3"); } - protected String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter, String network) { + protected String getIpAddressFromBridgedNIC(INetworkAdapter networkAdapter) { // RetrieveActiveBridgedInterfaces List activeBridgedInterfaces = new RetrieveActiveBridgedInterfaces(scriptRunnerFactory) .apply(hostSupplier.get()); BridgedIf activeBridgedIf = checkNotNull(Iterables.get(activeBridgedInterfaces, 0), "activeBridgedInterfaces"); - network = activeBridgedIf.getIpAddress(); + String network = activeBridgedIf.getIpAddress(); // scan ip RunScriptOnNode ipScanRunScript = scriptRunnerFactory.create(hostSupplier.get(), diff --git a/labs/virtualbox/src/main/resources/default-images.yaml b/labs/virtualbox/src/main/resources/default-images.yaml index e6be3668dd..1714f796a3 100644 --- a/labs/virtualbox/src/main/resources/default-images.yaml +++ b/labs/virtualbox/src/main/resources/default-images.yaml @@ -1,273 +1,4 @@ images: - - id: ubuntu-10.04.4-server-i386 - name: ubuntu-10.04-server-i386 - description: ubuntu 10.04.4 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 10.04.4 - iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-i386.iso - iso_md5: fc08a01e78348e3918180ea91a6883bb - username: toor - credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US - d-i console-setup/ask_detect boolean false - d-i console-setup/layoutcode string us - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - d-i 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-auto/purge_lvm_from_device boolean true - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # 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 - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-10.04.4-server-amd64 - name: ubuntu-10.04-server-amd64 - description: ubuntu 10.04.4 server (amd64) - os_arch: amd64 - os_family: ubuntu - os_description: ubuntu - os_version: 10.04.4 - os_64bit: true - iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-amd64.iso - iso_md5: 9b218654cdcdf9722171648c52f8a088 - username: toor - credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US - d-i console-setup/ask_detect boolean false - d-i console-setup/layoutcode string us - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - d-i 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-auto/purge_lvm_from_device boolean true - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # 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 - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-11.04-i386 - name: ubuntu-11.04-server-i386 - description: ubuntu 11.04 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 11.04 - iso: http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US.utf8 - d-i console-setup/ask_detect boolean false - d-i console-setup/layout string USA - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - # Continue without a default route - # Not working , specify a dummy in the DHCP - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive - d-i debconf debconf/frontend select Noninteractive - d-i pkgsel/install-language-support boolean false - tasksel tasksel/first multiselect standard, ubuntu-server - d-i partman-auto/method string lvm - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # Write the changes to disks and configure LVM? - d-i partman-lvm/confirm boolean true - d-i partman-lvm/confirm_nooverwrite boolean true - d-i partman-auto-lvm/guided_size string max - ## Default user, we can get away with a recipe to change this - d-i passwd/user-fullname string toor - d-i passwd/username string toor - d-i passwd/user-password password password - d-i passwd/user-password-again password password - d-i user-setup/encrypt-home boolean false - d-i user-setup/allow-password-weak boolean true - # Individual additional packages to install - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-11.10-i386 - name: ubuntu-11.10-server-i386 - description: ubuntu 11.10 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 11.10 - iso: http://releases.ubuntu.com/11.10/ubuntu-11.10-server-i386.iso - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US.utf8 - d-i console-setup/ask_detect boolean false - d-i console-setup/layout string USA - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - # Continue without a default route - # Not working , specify a dummy in the DHCP - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive - d-i debconf debconf/frontend select Noninteractive - d-i pkgsel/install-language-support boolean false - tasksel tasksel/first multiselect standard, ubuntu-server - d-i partman-auto/method string lvm - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # Write the changes to disks and configure LVM? - d-i partman-lvm/confirm boolean true - d-i partman-lvm/confirm_nooverwrite boolean true - d-i partman-auto-lvm/guided_size string max - ## Default user, we can get away with a recipe to change this - d-i passwd/user-fullname string toor - d-i passwd/username string toor - d-i passwd/user-password password password - d-i passwd/user-password-again password password - d-i user-setup/encrypt-home boolean false - d-i user-setup/allow-password-weak boolean true - # Individual additional packages to install - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - id: ubuntu-12.04.1-amd64 name: ubuntu-12.04.1-server-amd64 description: ubuntu 12.04.1 server (amd64) @@ -280,11 +11,7 @@ images: iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17 username: toor credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - console-setup/ask_detect=false keyboard-configuration/layoutcode=us - initrd=/install/initrd.gz -- + keystroke_sequence: /install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL debian-installer=en_US auto locale=en_US kbd-chooser/method=us hostname=HOSTNAME fb=false debconf/frontend=noninteractive console-setup/ask_detect=false keyboard-configuration/layoutcode=us initrd=/install/initrd.gz -- preseed_cfg: | ## Options to set on the command line d-i debian-installer/locale string en_US.utf8 @@ -351,4 +78,66 @@ images: #choose-mirror-bin mirror/http/directory string /ubuntu #choose-mirror-bin mirror/suite select maverick #d-i debian-installer/allow_unauthenticated string true - choose-mirror-bin mirror/http/proxy string \ No newline at end of file + choose-mirror-bin mirror/http/proxy string + - id: centos-6.3-amd64 + name: centos-6.3-amd64 + description: centos-6.3 (amd64) + os_arch: amd64 + os_family: RedHat + os_description: RedHat + os_version: 6.3 + os_64bit: true + iso: http://www.mirrorservice.org/sites/mirror.centos.org/6.3/isos/x86_64/CentOS-6.3-x86_64-minimal.iso + iso_md5: 087713752fa88c03a5e8471c661ad1a2 + username: toor + credential: password + keystroke_sequence: text ks=PRECONFIGURATION_URL + preseed_cfg: | + ## Options to set on the command line + install + cdrom + lang en_US.UTF-8 + keyboard us + network --bootproto=dhcp + rootpw --iscrypted $1$damlkd,f$UC/u5pUts5QiU3ow.CSso/ + firewall --enabled --service=ssh + authconfig --enableshadow --passalgo=sha512 + selinux --disabled + timezone UTC + bootloader --location=mbr --driveorder=sda --append="crashkernel=auto rhgb quiet" + zerombr yes + + clearpart --all --drives=sda --initlabel + autopart + auth --useshadow --enablemd5 + #skip answers to the First Boot process + firstboot --disable + #reboot machine + reboot + + %packages --ignoremissing + @core + @ Base + @ Development Tools + mc + wget + bzip2 + kernel-devel + kernel-headers + -ipw2100-firmware + -ipw2200-firmware + -ivtv-firmware + %end + + %post + /usr/bin/yum -y install sudo gcc make gcc-c++ kernel-devel-`uname -r` zlib-devel openssl-devel readline-devel sqlite-devel perl dkms acpid + /etc/init.d/haldaemon stop + /etc/init.d/acpid start + /etc/init.d/haldaemon start + /usr/sbin/groupadd toor + /usr/sbin/useradd toor -g toor -G wheel + echo "password"|passwd --stdin toor + echo "toor ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/toor + chmod 0440 /etc/sudoers.d/toor + sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers + %end \ No newline at end of file diff --git a/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh b/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh index 1eb542f1a5..164dc6f98e 100644 --- a/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh +++ b/labs/virtualbox/src/main/resources/functions/cleanupUdevIfNeeded.sh @@ -3,4 +3,5 @@ function cleanupUdevIfNeeded { then rm /etc/udev/rules.d/70-persistent-net.rules fi + } \ No newline at end of file diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java index 6ada4c739d..4d3ade4761 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/BaseVirtualBoxClientLiveTest.java @@ -22,9 +22,9 @@ package org.jclouds.virtualbox; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import java.io.File; +import java.io.IOException; import java.util.concurrent.TimeUnit; import javax.inject.Inject; @@ -40,6 +40,7 @@ import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.config.ValueOfConfigurationKeyOrNull; import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.sshj.config.SshjSshClientModule; +import org.jclouds.util.Strings2; import org.jclouds.virtualbox.config.VirtualBoxConstants; import org.jclouds.virtualbox.domain.HardDisk; import org.jclouds.virtualbox.domain.IsoSpec; @@ -118,6 +119,7 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT @Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) protected String workingDir; protected String isosDir; + protected String keystrokeSequence; @Inject protected Supplier host; @Inject protected Factory runScriptOnNodeFactory; @Inject protected RetryIfSocketNotYetOpen socketTester; @@ -151,6 +153,12 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT hostVersion = Iterables.get(Splitter.on('-').split(view.utils().injector().getInstance(Key.get(String.class, BuildVersion.class))), 0); operatingSystemIso = String.format("%s/%s.iso", isosDir, template.getImage().getName()); guestAdditionsIso = String.format("%s/VBoxGuestAdditions_%s.iso", isosDir, hostVersion); + keystrokeSequence = ""; + try { + keystrokeSequence = Strings2.toStringAndClose(getClass().getResourceAsStream("/default-keystroke-sequence")); + } catch (IOException e) { + throw new RuntimeException("error reading default-keystroke-sequence file"); + } } protected void undoVm(String vmNameOrId) { @@ -188,14 +196,10 @@ public class BaseVirtualBoxClientLiveTest extends BaseComputeServiceContextLiveT VmSpec sourceVmSpec = VmSpec.builder().id(masterName).name(masterName).osTypeId("").memoryMB(512) .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Injector injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); IsoSpec isoSpec = IsoSpec .builder() .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - sourceVmSpec.getVmName())).build(); + .installationScript(keystrokeSequence).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java index fd180604ed..deb2b3b887 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/compute/VirtualBoxComputeServiceAdapterLiveTest.java @@ -24,6 +24,8 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; +import java.util.Random; + import javax.inject.Inject; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; @@ -44,21 +46,37 @@ import com.google.common.collect.Iterables; @Test(groups = "live", singleThreaded = true, testName = "VirtualBoxComputeServiceAdapterLiveTest") public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClientLiveTest { - private NodeAndInitialCredentials machine; + private NodeAndInitialCredentials ubuntu; + private NodeAndInitialCredentials centos; @Inject protected VirtualBoxComputeServiceAdapter adapter; + @Test public void testCreatedNodeHasExpectedNameAndWeCanConnectViaSsh() { String group = "foo"; String name = "foo-ef9"; Template template = view.getComputeService().templateBuilder().build(); - machine = adapter.createNodeWithGroupEncodedIntoName(group, name, template); - assertTrue(machine.getNode().getName().contains(group)); - assertTrue(machine.getNode().getName().contains(name)); - assertTrue(machine.getNode().getName().startsWith(VIRTUALBOX_NODE_PREFIX)); - doConnectViaSsh(machine.getNode(), prioritizeCredentialsFromTemplate.apply(template, machine.getCredentials())); + ubuntu = adapter.createNodeWithGroupEncodedIntoName(group, name, template); + assertTrue(ubuntu.getNode().getName().contains(group)); + assertTrue(ubuntu.getNode().getName().contains(name)); + assertTrue(ubuntu.getNode().getName().startsWith(VIRTUALBOX_NODE_PREFIX)); + doConnectViaSsh(ubuntu.getNode(), prioritizeCredentialsFromTemplate.apply(template, ubuntu.getCredentials())); + } + + @Test + public void testCreatedCentosNodeHasExpectedNameAndWeCanConnectViaSsh() { + String group = "foo"; + String name = "centos6-" + new Random(100).nextInt(); + Template template = view.getComputeService().templateBuilder() + .imageId("centos-6.3-amd64") + .build(); + centos = adapter.createNodeWithGroupEncodedIntoName(group, name, template); + assertTrue(centos.getNode().getName().contains(group)); + assertTrue(centos.getNode().getName().contains(name)); + assertTrue(centos.getNode().getName().startsWith(VIRTUALBOX_NODE_PREFIX)); + doConnectViaSsh(centos.getNode(), prioritizeCredentialsFromTemplate.apply(template, centos.getCredentials())); } protected void doConnectViaSsh(IMachine machine, LoginCredentials creds) { @@ -91,8 +109,10 @@ public class VirtualBoxComputeServiceAdapterLiveTest extends BaseVirtualBoxClien @AfterGroups(groups = "live") @Override protected void tearDownContext() { - if (machine != null) - adapter.destroyNode(machine.getNodeId() + ""); + if (ubuntu != null) + adapter.destroyNode(ubuntu.getNodeId() + ""); + if (centos != null) + adapter.destroyNode(centos.getNodeId() + ""); super.tearDownContext(); } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachineTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachineTest.java new file mode 100644 index 0000000000..5048504054 --- /dev/null +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/ApplyBootOrderToMachineTest.java @@ -0,0 +1,56 @@ +/** + * 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.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import com.google.common.collect.ImmutableMap; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.virtualbox_4_2.DeviceType; +import org.virtualbox_4_2.IMachine; +import org.virtualbox_4_2.VBoxException; + +import java.util.Map; + +/** + * @author Andrea Turli + */ +@Test(groups = "unit", testName = "ApplyBootOrderToMachineTest") +public class ApplyBootOrderToMachineTest { + + @Test + public void testSetBootOrderSuccessful() throws Exception { + Map positionAndDeviceType = ImmutableMap.of(1l, DeviceType.HardDisk); + IMachine machine = createMock(IMachine.class); + for(long position : positionAndDeviceType.keySet()) { + machine.setBootOrder(position, positionAndDeviceType.get(position)); + } + machine.saveSettings(); + replay(machine); + new ApplyBootOrderToMachine(positionAndDeviceType).apply(machine); + verify(machine); + } + +} diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java index 9543ccc589..8b06b98b33 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest.java @@ -19,11 +19,10 @@ package org.jclouds.virtualbox.functions; +import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX; -import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE; import 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; @@ -43,7 +42,6 @@ import org.virtualbox_4_2.NetworkAttachmentType; import org.virtualbox_4_2.StorageBus; import com.google.common.base.CaseFormat; -import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.inject.Injector; @@ -63,35 +61,49 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest exten instanceName = VIRTUALBOX_IMAGE_PREFIX + 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(instanceName)).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(instanceName)) + .controllerPort(0) + .deviceSlot(1) + .autoDelete(true) + .build()) + .attachISO(1, 1, guestAdditionsIso) + .build(); - VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) - .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); + VmSpec instanceVmSpec = VmSpec.builder() + .id(instanceName) + .name(instanceName) + .osTypeId("") + .memoryMB(512) + .cleanUpMode(CleanupMode.Full) + .controller(ideController) + .forceOverwrite(true) + .build(); - Injector injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); - IsoSpec isoSpec = IsoSpec - .builder() - .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); + IsoSpec isoSpec = IsoSpec.builder() + .sourcePath(operatingSystemIso) + .installationScript(keystrokeSequence) + .build(); - NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) - .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); - NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter) - .build(); - - NetworkSpec networkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); - machineSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); + NetworkAdapter networkAdapter = NetworkAdapter.builder() + .networkAttachmentType(NetworkAttachmentType.NAT) + .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); + NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder() + .addNetworkAdapter(networkAdapter) + .build(); + NetworkSpec networkSpec = NetworkSpec.builder() + .addNIC(networkInterfaceCard) + .build(); + machineSpec = MasterSpec.builder() + .iso(isoSpec) + .vm(instanceVmSpec) + .network(networkSpec) + .build(); } @Test @@ -99,8 +111,9 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest exten IMachine source = getVmWithGuestAdditionsInstalled(); CloneSpec cloneSpec = CloneSpec.builder().vm(machineSpec.getVmSpec()).network(machineSpec.getNetworkSpec()) .master(source).linked(true).build(); - IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) - .apply(cloneSpec); + IMachine clone = checkNotNull( + new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(manager, workingDir, machineUtils) + .apply(cloneSpec), "clone"); assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName()); } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java index 5d66492a99..4583c318aa 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/CreateAndInstallVmLiveTest.java @@ -21,7 +21,6 @@ package org.jclouds.virtualbox.functions; import static com.google.common.base.Preconditions.checkState; 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.net.URI; @@ -105,13 +104,10 @@ public class CreateAndInstallVmLiveTest extends BaseVirtualBoxClientLiveTest { .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); IsoSpec isoSpec = IsoSpec .builder() .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); + .installationScript(keystrokeSequence).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly) .build(); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java index 0e4b3ef2f8..232ecf41de 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/ImageFromYamlStringTest.java @@ -41,12 +41,12 @@ import com.google.common.collect.Iterables; public class ImageFromYamlStringTest { public static final Image TEST1 = new ImageBuilder() - .id("ubuntu-10.04.4-server-i386") - .name("ubuntu-10.04-server-i386") + .id("ubuntu-12.04.1-amd64") + .name("ubuntu-12.04.1-server-amd64") .description("ubuntu") .operatingSystem( - OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("10.04.4") - .arch("x86").build()) + OperatingSystem.builder().description("ubuntu").family(OsFamily.UBUNTU).version("12.04.1") + .arch("amd64").build()) .status(Image.Status.AVAILABLE).build(); Map images; diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java index 1123aa4307..12612a2c82 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/GuestAdditionsInstallerLiveTest.java @@ -21,7 +21,6 @@ package org.jclouds.virtualbox.predicates; import static com.google.common.base.Preconditions.checkState; 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 org.jclouds.config.ValueOfConfigurationKeyOrNull; @@ -86,14 +85,6 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); - IsoSpec isoSpec = IsoSpec - .builder() - .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); - NetworkAdapter networkAdapter = NetworkAdapter.builder() .networkAttachmentType(NetworkAttachmentType.HostOnly) .build(); @@ -101,7 +92,6 @@ public class GuestAdditionsInstallerLiveTest extends BaseVirtualBoxClientLiveTes .addHostInterfaceName("vboxnet0").slot(0L).build(); instanceNetworkSpec = NetworkSpec.builder().addNIC(networkInterfaceCard).build(); - //cloneSpec = MasterSpec.builder().iso(isoSpec).vm(instanceVmSpec).network(networkSpec).build(); } @Test diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java index 8d34246ce2..5374a82a58 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/predicates/IMachinePredicatesLiveTest.java @@ -20,7 +20,6 @@ package org.jclouds.virtualbox.predicates; 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.predicates.IMachinePredicates.isLinkedClone; import static org.testng.Assert.assertTrue; @@ -80,13 +79,10 @@ public class IMachinePredicatesLiveTest extends BaseVirtualBoxClientLiveTest { .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); Injector injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); IsoSpec isoSpec = IsoSpec .builder() .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); + .installationScript(keystrokeSequence).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java index 10e6dde81b..17ba9dea54 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineControllerLiveTest.java @@ -20,7 +20,6 @@ package org.jclouds.virtualbox.util; 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.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.assertEquals; @@ -78,14 +77,10 @@ public class MachineControllerLiveTest extends BaseVirtualBoxClientLiveTest { VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Injector injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); IsoSpec isoSpec = IsoSpec .builder() .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); + .installationScript(keystrokeSequence).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.HostOnly) .build(); diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java index a946de4df2..91361bd146 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/util/MachineUtilsLiveTest.java @@ -21,7 +21,6 @@ package org.jclouds.virtualbox.util; import static com.google.common.base.Preconditions.checkState; 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.AssertJUnit.assertEquals; import org.jclouds.config.ValueOfConfigurationKeyOrNull; @@ -75,14 +74,10 @@ public class MachineUtilsLiveTest extends BaseVirtualBoxClientLiveTest { VmSpec instanceVmSpec = VmSpec.builder().id(instanceName).name(instanceName).osTypeId("").memoryMB(512) .cleanUpMode(CleanupMode.Full).controller(ideController).forceOverwrite(true).build(); - Injector injector = view.utils().injector(); - Function configProperties = injector.getInstance(ValueOfConfigurationKeyOrNull.class); IsoSpec isoSpec = IsoSpec .builder() .sourcePath(operatingSystemIso) - .installationScript( - configProperties.apply(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE).replace("HOSTNAME", - instanceVmSpec.getVmName())).build(); + .installationScript(keystrokeSequence).build(); NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT) .tcpRedirectRule("127.0.0.1", 2222, "", 22).build(); diff --git a/labs/virtualbox/src/test/resources/default-images.yaml b/labs/virtualbox/src/test/resources/default-images.yaml index 1b0b2482c4..1714f796a3 100644 --- a/labs/virtualbox/src/test/resources/default-images.yaml +++ b/labs/virtualbox/src/test/resources/default-images.yaml @@ -1,273 +1,4 @@ images: - - id: ubuntu-10.04.4-server-i386 - name: ubuntu-10.04-server-i386 - description: ubuntu 10.04.4 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 10.04.4 - iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-i386.iso - iso_md5: fc08a01e78348e3918180ea91a6883bb - username: toor - credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US - d-i console-setup/ask_detect boolean false - d-i console-setup/layoutcode string us - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - d-i 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-auto/purge_lvm_from_device boolean true - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # 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 - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-10.04.4-server-amd64 - name: ubuntu-10.04-server-amd64 - description: ubuntu 10.04.4 server (amd64) - os_arch: amd64 - os_family: ubuntu - os_description: ubuntu - os_version: 10.04.4 - os_64bit: true - iso: http://releases.ubuntu.com/10.04.4/ubuntu-10.04.4-server-amd64.iso - iso_md5: 9b218654cdcdf9722171648c52f8a088 - username: toor - credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - console-setup/ask_detect=false console-setup/modelcode=pc105 console-setup/layoutcode=us - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US - d-i console-setup/ask_detect boolean false - d-i console-setup/layoutcode string us - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - d-i 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-auto/purge_lvm_from_device boolean true - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # 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 - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-11.04-i386 - name: ubuntu-11.04-server-i386 - description: ubuntu 11.04 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 11.04 - iso: http://releases.ubuntu.com/11.04/ubuntu-11.04-server-i386.iso - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US.utf8 - d-i console-setup/ask_detect boolean false - d-i console-setup/layout string USA - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - # Continue without a default route - # Not working , specify a dummy in the DHCP - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive - d-i debconf debconf/frontend select Noninteractive - d-i pkgsel/install-language-support boolean false - tasksel tasksel/first multiselect standard, ubuntu-server - d-i partman-auto/method string lvm - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # Write the changes to disks and configure LVM? - d-i partman-lvm/confirm boolean true - d-i partman-lvm/confirm_nooverwrite boolean true - d-i partman-auto-lvm/guided_size string max - ## Default user, we can get away with a recipe to change this - d-i passwd/user-fullname string toor - d-i passwd/username string toor - d-i passwd/user-password password password - d-i passwd/user-password-again password password - d-i user-setup/encrypt-home boolean false - d-i user-setup/allow-password-weak boolean true - # Individual additional packages to install - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - - id: ubuntu-11.10-i386 - name: ubuntu-11.10-server-i386 - description: ubuntu 11.10 server (i386) - os_arch: x86 - os_family: ubuntu - os_description: ubuntu - os_version: 11.10 - iso: http://releases.ubuntu.com/11.10/ubuntu-11.10-server-i386.iso - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - debian-installer=en_US auto locale=en_US kbd-chooser/method=us - hostname=vmName - fb=false debconf/frontend=noninteractive - keyboard-configuration/layout=USA keyboard-configuration/variant=USA console-setup/ask_detect=false - initrd=/install/initrd.gz -- - preseed_cfg: | - ## Options to set on the command line - d-i debian-installer/locale string en_US.utf8 - d-i console-setup/ask_detect boolean false - d-i console-setup/layout string USA - d-i netcfg/get_hostname string unassigned-hostname - d-i netcfg/get_domain string unassigned-domain - # Continue without a default route - # Not working , specify a dummy in the DHCP - d-i time/zone string UTC - d-i clock-setup/utc-auto boolean true - d-i clock-setup/utc boolean true - d-i kbd-chooser/method select American English - d-i netcfg/wireless_wep string - d-i base-installer/kernel/override-image string linux-server - # Choices: Dialog, Readline, Gnome, Kde, Editor, Noninteractive - d-i debconf debconf/frontend select Noninteractive - d-i pkgsel/install-language-support boolean false - tasksel tasksel/first multiselect standard, ubuntu-server - d-i partman-auto/method string lvm - d-i partman-lvm/confirm boolean true - d-i partman-lvm/device_remove_lvm boolean true - d-i partman-auto/choose_recipe select atomic - d-i partman/confirm_write_new_label boolean true - d-i partman/confirm_nooverwrite boolean true - d-i partman/choose_partition select finish - d-i partman/confirm boolean true - # Write the changes to disks and configure LVM? - d-i partman-lvm/confirm boolean true - d-i partman-lvm/confirm_nooverwrite boolean true - d-i partman-auto-lvm/guided_size string max - ## Default user, we can get away with a recipe to change this - d-i passwd/user-fullname string toor - d-i passwd/username string toor - d-i passwd/user-password password password - d-i passwd/user-password-again password password - d-i user-setup/encrypt-home boolean false - d-i user-setup/allow-password-weak boolean true - # Individual additional packages to install - d-i pkgsel/include string openssh-server ntp - # Whether to upgrade packages after debootstrap. - # Allowed values: none, safe-upgrade, full-upgrade - d-i pkgsel/upgrade select full-upgrade - d-i grub-installer/only_debian boolean true - d-i grub-installer/with_other_os boolean true - d-i finish-install/reboot_in_progress note - #For the update - d-i pkgsel/update-policy select none - # debconf-get-selections --install - #Use mirror - choose-mirror-bin mirror/http/proxy string - id: ubuntu-12.04.1-amd64 name: ubuntu-12.04.1-server-amd64 description: ubuntu 12.04.1 server (amd64) @@ -280,11 +11,7 @@ images: iso_md5: a8c667e871f48f3a662f3fbf1c3ddb17 username: toor credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - console-setup/ask_detect=false keyboard-configuration/layoutcode=us - initrd=/install/initrd.gz -- + keystroke_sequence: /install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL debian-installer=en_US auto locale=en_US kbd-chooser/method=us hostname=HOSTNAME fb=false debconf/frontend=noninteractive console-setup/ask_detect=false keyboard-configuration/layoutcode=us initrd=/install/initrd.gz -- preseed_cfg: | ## Options to set on the command line d-i debian-installer/locale string en_US.utf8 @@ -356,19 +83,15 @@ images: name: centos-6.3-amd64 description: centos-6.3 (amd64) os_arch: amd64 - os_family: centos - os_description: centos + os_family: RedHat + os_description: RedHat os_version: 6.3 os_64bit: true - iso: http://www.mirrorservice.org/sites/mirror.centos.org/6.3/isos/i386/CentOS-6.3-x86_64-LiveCD.iso - iso_md5: 9953ff1cc2ef31da89a0e1f993ee6335 - username: root + iso: http://www.mirrorservice.org/sites/mirror.centos.org/6.3/isos/x86_64/CentOS-6.3-x86_64-minimal.iso + iso_md5: 087713752fa88c03a5e8471c661ad1a2 + username: toor credential: password - keystroke_sequence: | - - /install/vmlinuz noapic preseed/url=http://10.0.2.2:8080/src/test/resources/preseed.cfg - console-setup/ask_detect=false keyboard-configuration/layoutcode=us - initrd=/install/initrd.gz -- + keystroke_sequence: text ks=PRECONFIGURATION_URL preseed_cfg: | ## Options to set on the command line install @@ -381,16 +104,23 @@ images: authconfig --enableshadow --passalgo=sha512 selinux --disabled timezone UTC - bootloader --location=mbr - text - skipx - zerombr - clearpart --all --initlabel + bootloader --location=mbr --driveorder=sda --append="crashkernel=auto rhgb quiet" + zerombr yes + + clearpart --all --drives=sda --initlabel autopart auth --useshadow --enablemd5 - firstboot --disabled - reboot%packages --ignoremissing + #skip answers to the First Boot process + firstboot --disable + #reboot machine + reboot + + %packages --ignoremissing @core + @ Base + @ Development Tools + mc + wget bzip2 kernel-devel kernel-headers @@ -398,11 +128,16 @@ images: -ipw2200-firmware -ivtv-firmware %end + %post - /usr/bin/yum -y install sudo - /usr/sbin/groupadd veewee - /usr/sbin/useradd veewee -g veewee -G wheel - echo "veewee"|passwd --stdin veewee - echo "veewee ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/veewee - chmod 0440 /etc/sudoers.d/veewee - %end + /usr/bin/yum -y install sudo gcc make gcc-c++ kernel-devel-`uname -r` zlib-devel openssl-devel readline-devel sqlite-devel perl dkms acpid + /etc/init.d/haldaemon stop + /etc/init.d/acpid start + /etc/init.d/haldaemon start + /usr/sbin/groupadd toor + /usr/sbin/useradd toor -g toor -G wheel + echo "password"|passwd --stdin toor + echo "toor ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/toor + chmod 0440 /etc/sudoers.d/toor + sed -i "s/^.*requiretty/#Defaults requiretty/" /etc/sudoers + %end \ No newline at end of file diff --git a/labs/virtualbox/src/test/resources/default-keystroke-sequence b/labs/virtualbox/src/test/resources/default-keystroke-sequence new file mode 100644 index 0000000000..be075aea7f --- /dev/null +++ b/labs/virtualbox/src/test/resources/default-keystroke-sequence @@ -0,0 +1 @@ + /install/vmlinuz noapic preseed/url=PRECONFIGURATION_URL debian-installer=en_US auto locale=en_US kbd-chooser/method=us hostname=hostname fb=false debconf/frontend=noninteractive console-setup/ask_detect=false keyboard-configuration/layoutcode=us " initrd=/install/initrd.gz -- \ No newline at end of file diff --git a/labs/virtualbox/src/test/resources/redHatAndDerivatives/hostOnly b/labs/virtualbox/src/test/resources/redHatAndDerivatives/hostOnly new file mode 100644 index 0000000000..44aef55b25 --- /dev/null +++ b/labs/virtualbox/src/test/resources/redHatAndDerivatives/hostOnly @@ -0,0 +1,8 @@ +#!/bin/bash +sudo ip link set eth1 name eth0 +# configure eth0 +MAC_ETH0=`ifconfig -a | grep eth0 | awk '{ print $5}'`; sed "s/HWADDR.*/HWADDR\=\"$MAC_ETH0\"/g" /etc/sysconfig/network-scripts/ifcfg-eth0 > /tmp/ifcfg-eth0; +sudo cp /tmp/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0; +# restart network +sudo rm /etc/udev/rules.d/70-persistent-net.rules +sudo /etc/init.d/network restart diff --git a/labs/virtualbox/src/test/resources/redHatAndDerivatives/nat b/labs/virtualbox/src/test/resources/redHatAndDerivatives/nat new file mode 100644 index 0000000000..a27d202562 --- /dev/null +++ b/labs/virtualbox/src/test/resources/redHatAndDerivatives/nat @@ -0,0 +1,12 @@ +#!/bin/bash +sudo ip link set eth2 name eth1 +sudo cp /etc/sysconfig/network-scripts/ifcfg-eth0 /tmp/ifcfg-eth1 +sudo chown toor.toor /tmp/ifcfg-eth1 +# configure eth1 +MAC_ETH1=`ifconfig -a | grep eth1 | awk '{ print $5}'`; sed "s/HWADDR.*/HWADDR\=\"$MAC_ETH1\"/g" /tmp/ifcfg-eth1 > /tmp/ifcfg-eth12; +sed "/UUID/d" /tmp/ifcfg-eth12 > /tmp/ifcfg-eth13; +sed "s/DEVICE.*/DEVICE\=\"eth1\"/g" /tmp/ifcfg-eth13 > /tmp/ifcfg-eth14; +sudo cp /tmp/ifcfg-eth14 /etc/sysconfig/network-scripts/ifcfg-eth1; +# restart network +sudo rm /etc/udev/rules.d/70-persistent-net.rules +sudo /etc/init.d/network restart