mirror of https://github.com/apache/jclouds.git
added the possiblity for master machines to survive the jvm. first run creates and installs the master vm subsequent calls fetch the already created master from vm
This commit is contained in:
parent
690bc9a4dc
commit
d0b4d81f9f
|
@ -29,11 +29,12 @@ import java.util.Map;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.NodeSpec;
|
||||
import org.jclouds.virtualbox.domain.YamlImage;
|
||||
import org.virtualbox_4_1.CleanupMode;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
|
@ -62,13 +63,13 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
|||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Map<Image, YamlImage> images;
|
||||
private final LoadingCache<Image, IMachine> mastersLoader;
|
||||
private final Function<IMachine, NodeAndInitialCredentials<IMachine>> cloneCreator;
|
||||
private final LoadingCache<Image, Master> mastersLoader;
|
||||
private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator;
|
||||
|
||||
@Inject
|
||||
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
|
||||
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, IMachine> mastersLoader,
|
||||
Function<IMachine, NodeAndInitialCredentials<IMachine>> cloneCreator) {
|
||||
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader,
|
||||
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator) {
|
||||
this.manager = checkNotNull(manager, "manager");
|
||||
this.images = imagesMapper.get();
|
||||
this.mastersLoader = mastersLoader;
|
||||
|
@ -79,8 +80,9 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
|||
public NodeAndInitialCredentials<IMachine> createNodeWithGroupEncodedIntoName(String tag, String name,
|
||||
Template template) {
|
||||
try {
|
||||
IMachine master = mastersLoader.get(template.getImage());
|
||||
return cloneCreator.apply(master);
|
||||
Master master = mastersLoader.get(template.getImage());
|
||||
NodeSpec nodeSpec = NodeSpec.builder().master(master).name(name).tag(tag).template(template).build();
|
||||
return cloneCreator.apply(nodeSpec);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
package org.jclouds.virtualbox.config;
|
||||
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PROVIDER;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WEBSERVER_CREDENTIAL;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WEBSERVER_IDENTITY;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
|
@ -60,16 +57,19 @@ import org.jclouds.sshj.config.SshjSshClientModule;
|
|||
import org.jclouds.virtualbox.Host;
|
||||
import org.jclouds.virtualbox.Preconfiguration;
|
||||
import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.YamlImage;
|
||||
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||
import org.jclouds.virtualbox.functions.IMachineToHardware;
|
||||
import org.jclouds.virtualbox.functions.IMachineToImage;
|
||||
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
|
||||
import org.jclouds.virtualbox.functions.IMachineToSshClient;
|
||||
import org.jclouds.virtualbox.functions.MasterImages;
|
||||
import org.jclouds.virtualbox.functions.MastersCache;
|
||||
import org.jclouds.virtualbox.functions.NodeCreator;
|
||||
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
|
||||
import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor;
|
||||
|
@ -134,14 +134,16 @@ public class VirtualBoxComputeServiceContextModule extends
|
|||
bind(new TypeLiteral<Supplier<String>>() {
|
||||
}).to((Class) YamlImagesFromFileConfig.class);
|
||||
// the master machines cache
|
||||
bind(new TypeLiteral<LoadingCache<Image, IMachine>>() {
|
||||
}).to((Class) MasterImages.class);
|
||||
bind(new TypeLiteral<LoadingCache<Image, Master>>() {
|
||||
}).to((Class) MastersCache.class);
|
||||
// the master creating function
|
||||
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
|
||||
}).to((Class) CreateAndInstallVm.class);
|
||||
// the machine cloning function
|
||||
bind(new TypeLiteral<Function<IMachine, NodeAndInitialCredentials<IMachine>>>() {
|
||||
}).to((Class) NodeCreator.class);
|
||||
bind(new TypeLiteral<Function<CloneSpec, IMachine>>() {
|
||||
}).to((Class) CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.class);
|
||||
|
||||
// for byon
|
||||
bind(new TypeLiteral<Function<URI, InputStream>>() {
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
|
||||
package org.jclouds.virtualbox.domain;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* A complete specification of a "clone" node with networking setup
|
||||
* and the physical machine specification.
|
||||
|
@ -31,6 +33,8 @@ public class CloneSpec {
|
|||
|
||||
private final VmSpec vmSpec;
|
||||
private final NetworkSpec networkSpec;
|
||||
private final IMachine master;
|
||||
private final boolean isLinked;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
|
@ -40,6 +44,8 @@ public class CloneSpec {
|
|||
|
||||
private VmSpec vmSpec;
|
||||
private NetworkSpec networkSpec;
|
||||
private IMachine master;
|
||||
private boolean isLinked;
|
||||
|
||||
public Builder vm(VmSpec vmSpec) {
|
||||
this.vmSpec = vmSpec;
|
||||
|
@ -50,18 +56,31 @@ public class CloneSpec {
|
|||
this.networkSpec = networkSpec;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder master(IMachine master){
|
||||
this.master = master;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder linked(boolean isLinked){
|
||||
this.isLinked = isLinked;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CloneSpec build() {
|
||||
return new CloneSpec(vmSpec, networkSpec);
|
||||
return new CloneSpec(vmSpec, networkSpec, master ,isLinked);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CloneSpec(VmSpec vmSpec, NetworkSpec networkSpec) {
|
||||
public CloneSpec(VmSpec vmSpec, NetworkSpec networkSpec, IMachine master, boolean isLinked) {
|
||||
checkNotNull(vmSpec, "vmSpec");
|
||||
checkNotNull(networkSpec, "networkSpec");
|
||||
checkNotNull(master, "master");
|
||||
this.vmSpec = vmSpec;
|
||||
this.networkSpec = networkSpec;
|
||||
this.master = master;
|
||||
this.isLinked = isLinked;
|
||||
}
|
||||
|
||||
public VmSpec getVmSpec() {
|
||||
|
@ -71,6 +90,14 @@ public class CloneSpec {
|
|||
public NetworkSpec getNetworkSpec() {
|
||||
return networkSpec;
|
||||
}
|
||||
|
||||
public IMachine getMaster() {
|
||||
return master;
|
||||
}
|
||||
|
||||
public boolean isLinked() {
|
||||
return isLinked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.jclouds.virtualbox.domain;
|
||||
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
|
||||
public class Master {
|
||||
|
||||
private final IMachine machine;
|
||||
private final MasterSpec spec;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private IMachine machine;
|
||||
private MasterSpec spec;
|
||||
|
||||
public Builder machine(IMachine machine){
|
||||
this.machine = machine;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder spec(MasterSpec spec){
|
||||
this.spec = spec;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Master build(){
|
||||
return new Master(machine,spec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Master(IMachine machine, MasterSpec spec) {
|
||||
super();
|
||||
this.machine = machine;
|
||||
this.spec = spec;
|
||||
}
|
||||
|
||||
public IMachine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
public MasterSpec getSpec() {
|
||||
return spec;
|
||||
}
|
||||
|
||||
}
|
|
@ -64,7 +64,7 @@ public class MasterSpec {
|
|||
|
||||
}
|
||||
|
||||
public MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec) {
|
||||
private MasterSpec(VmSpec vmSpec, IsoSpec isoSpec, NetworkSpec networkSpec) {
|
||||
checkNotNull(vmSpec, "vmSpec");
|
||||
checkNotNull(isoSpec, "isoSpec");
|
||||
checkNotNull(networkSpec, "networkSpec");
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.jclouds.virtualbox.domain;
|
||||
|
||||
import org.jclouds.compute.domain.Template;
|
||||
|
||||
public class NodeSpec {
|
||||
|
||||
private final Master master;
|
||||
private final String name;
|
||||
private final String tag;
|
||||
private final Template template;
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private Master master;
|
||||
private String name;
|
||||
private String tag;
|
||||
private Template template;
|
||||
|
||||
public Builder master(Master master) {
|
||||
this.master = master;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder tag(String tag) {
|
||||
this.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder template(Template template) {
|
||||
this.template = template;
|
||||
return this;
|
||||
}
|
||||
|
||||
public NodeSpec build() {
|
||||
return new NodeSpec(master, name, tag, template);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private NodeSpec(Master master, String name, String tag, Template template) {
|
||||
super();
|
||||
this.master = master;
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
public Master getMaster() {
|
||||
return master;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public Template getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
}
|
|
@ -52,7 +52,7 @@ import com.google.inject.Inject;
|
|||
* @author Andrea Turli
|
||||
*/
|
||||
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
||||
Function<IMachine, IMachine> {
|
||||
Function<CloneSpec, IMachine> {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
|
@ -60,24 +60,20 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
|||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final String workingDir;
|
||||
private final CloneSpec cloneSpec;
|
||||
private final boolean isLinkedClone;
|
||||
private final MachineUtils machineUtils;
|
||||
|
||||
@Inject
|
||||
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
||||
Supplier<VirtualBoxManager> manager,
|
||||
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir,
|
||||
CloneSpec cloneSpec, boolean isLinkedClone, MachineUtils machineUtils) {
|
||||
MachineUtils machineUtils) {
|
||||
this.manager = manager;
|
||||
this.workingDir = workingDir;
|
||||
this.cloneSpec = cloneSpec;
|
||||
this.isLinkedClone = isLinkedClone;
|
||||
this.machineUtils = machineUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMachine apply(@Nullable IMachine master) {
|
||||
public IMachine apply(CloneSpec cloneSpec) {
|
||||
VmSpec vmSpec = cloneSpec.getVmSpec();
|
||||
try {
|
||||
manager.get().getVBox().findMachine(vmSpec.getVmName());
|
||||
|
@ -85,7 +81,7 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
|||
+ " is already registered.");
|
||||
} catch (VBoxException e) {
|
||||
if (machineNotFoundException(e))
|
||||
return cloneMachine(vmSpec, master);
|
||||
return cloneMachine(cloneSpec);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
|
@ -98,7 +94,10 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
|||
"Could not find a registered machine with UUID {");
|
||||
}
|
||||
|
||||
private IMachine cloneMachine(VmSpec vmSpec, IMachine master) {
|
||||
private IMachine cloneMachine(CloneSpec cloneSpec) {
|
||||
VmSpec vmSpec = cloneSpec.getVmSpec();
|
||||
boolean isLinkedClone = cloneSpec.isLinked();
|
||||
IMachine master = cloneSpec.getMaster();
|
||||
String settingsFile = manager.get().getVBox()
|
||||
.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
||||
IMachine clonedMachine = manager
|
||||
|
|
|
@ -53,7 +53,6 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.jclouds.virtualbox.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
@ -93,11 +94,6 @@ public class CreateAndRegisterMachineFromIsoIfNotAlreadyExists implements Functi
|
|||
}
|
||||
}
|
||||
|
||||
private boolean machineNotFoundException(VBoxException e) {
|
||||
return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ") ||
|
||||
e.getMessage().contains("Could not find a registered machine with UUID {");
|
||||
}
|
||||
|
||||
private IMachine createMachine(IVirtualBox vBox, MasterSpec machineSpec) {
|
||||
VmSpec vmSpec = machineSpec.getVmSpec();
|
||||
String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_DEFAU
|
|||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_IMAGE_PREFIX;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
|
||||
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
@ -38,6 +39,7 @@ import org.jclouds.Constants;
|
|||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.virtualbox.domain.HardDisk;
|
||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
||||
|
@ -49,6 +51,8 @@ import org.virtualbox_4_1.CleanupMode;
|
|||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||
import org.virtualbox_4_1.StorageBus;
|
||||
import org.virtualbox_4_1.VBoxException;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Splitter;
|
||||
|
@ -63,25 +67,28 @@ import com.google.common.collect.Maps;
|
|||
* @author dralves
|
||||
*
|
||||
*/
|
||||
public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
||||
public class MastersCache extends AbstractLoadingCache<Image, Master> {
|
||||
|
||||
private final Map<String, IMachine> masters = Maps.newHashMap();
|
||||
private final Function<MasterSpec, IMachine> mastersLoader;
|
||||
private final Map<String, Master> masters = Maps.newHashMap();
|
||||
private final Function<MasterSpec, IMachine> masterCreatorAndInstaller;
|
||||
private final Map<String, YamlImage> imageMapping;
|
||||
private final String workingDir;
|
||||
private final String adminDisk;
|
||||
private final String guestAdditionsIso;
|
||||
private final String installationKeySequence;
|
||||
private final String isosDir;
|
||||
private Supplier<VirtualBoxManager> manager;
|
||||
|
||||
@Inject
|
||||
public MasterImages(@Named(Constants.PROPERTY_BUILD_VERSION) String version,
|
||||
public MastersCache(@Named(Constants.PROPERTY_BUILD_VERSION) String version,
|
||||
@Named(VIRTUALBOX_INSTALLATION_KEY_SEQUENCE) String installationKeySequence,
|
||||
@Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader,
|
||||
Supplier<Map<Image, YamlImage>> yamlMapper) {
|
||||
Supplier<Map<Image, YamlImage>> yamlMapper, Supplier<VirtualBoxManager> manager) {
|
||||
checkNotNull(version, "version");
|
||||
checkNotNull(installationKeySequence, "installationKeySequence");
|
||||
this.mastersLoader = masterLoader;
|
||||
checkNotNull(manager, "vboxmanager");
|
||||
this.manager = manager;
|
||||
this.masterCreatorAndInstaller = masterLoader;
|
||||
this.installationKeySequence = installationKeySequence;
|
||||
this.workingDir = workingDir == null ? VIRTUALBOX_DEFAULT_DIR : workingDir;
|
||||
File wdFile = new File(this.workingDir);
|
||||
|
@ -100,13 +107,12 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IMachine get(Image key) throws ExecutionException {
|
||||
public Master get(Image key) throws ExecutionException {
|
||||
// check if we have loaded this machine before
|
||||
if (masters.containsKey(key.getId())) {
|
||||
return masters.get(key);
|
||||
}
|
||||
|
||||
checkNotNull(key, "key");
|
||||
|
||||
// the yaml image
|
||||
YamlImage yamlImage = imageMapping.get(key.getId());
|
||||
|
||||
|
@ -124,15 +130,14 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
|||
|
||||
VmSpec vmSpecification = VmSpec.builder().id(yamlImage.id).name(vmName).memoryMB(512).osTypeId("")
|
||||
.controller(ideController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).build();
|
||||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
.builder().addNetworkAdapter(networkAdapter).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
||||
.addNIC(0L, networkInterfaceCard).build();
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||
.tcpRedirectRule("127.0.0.1", 2222, "", 22).build();
|
||||
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard.builder().addNetworkAdapter(networkAdapter)
|
||||
.build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder().addNIC(0L, networkInterfaceCard).build();
|
||||
|
||||
MasterSpec masterSpec = MasterSpec
|
||||
.builder()
|
||||
|
@ -140,12 +145,25 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
|||
.iso(
|
||||
IsoSpec.builder().sourcePath(localIsoUrl)
|
||||
.installationScript(installationKeySequence.replace("HOSTNAME", vmSpecification.getVmName())).build())
|
||||
.network(networkSpec)
|
||||
.build();
|
||||
.network(networkSpec).build();
|
||||
|
||||
IMachine masterMachine;
|
||||
|
||||
// try and find a master machine in vbox
|
||||
try {
|
||||
masterMachine = manager.get().getVBox().findMachine(masterSpec.getVmSpec().getVmId());
|
||||
} catch (VBoxException e) {
|
||||
if (machineNotFoundException(e))
|
||||
masterMachine = masterCreatorAndInstaller.apply(masterSpec);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
|
||||
IMachine masterMachine = mastersLoader.apply(masterSpec);
|
||||
masters.put(key.getId(), masterMachine);
|
||||
return masterMachine;
|
||||
Master master = Master.builder().machine(masterMachine).spec(masterSpec).build();
|
||||
|
||||
masters.put(key.getId(), master);
|
||||
|
||||
return master;
|
||||
}
|
||||
|
||||
private String getFilePathOrDownload(String httpUrl) throws ExecutionException {
|
||||
|
@ -158,7 +176,7 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public IMachine getIfPresent(Image key) {
|
||||
public Master getIfPresent(Image key) {
|
||||
if (masters.containsKey(key.getId())) {
|
||||
return masters.get(key.getId());
|
||||
}
|
|
@ -1,15 +1,60 @@
|
|||
/**
|
||||
* 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 javax.inject.Inject;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||
import org.jclouds.virtualbox.domain.Master;
|
||||
import org.jclouds.virtualbox.domain.NodeSpec;
|
||||
import org.virtualbox_4_1.IMachine;
|
||||
import org.virtualbox_4_1.ISession;
|
||||
import org.virtualbox_4_1.VirtualBoxManager;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
public class NodeCreator implements Function<IMachine, NodeAndInitialCredentials<IMachine>> {
|
||||
public class NodeCreator implements Function<NodeSpec, NodeAndInitialCredentials<IMachine>> {
|
||||
|
||||
@Override
|
||||
public NodeAndInitialCredentials<IMachine> apply(IMachine input) {
|
||||
throw new UnsupportedOperationException();
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Function<CloneSpec, IMachine> cloner;
|
||||
|
||||
@Inject
|
||||
public NodeCreator(Supplier<VirtualBoxManager> manager, Function<CloneSpec, IMachine> cloner) {
|
||||
this.manager = manager;
|
||||
this.cloner = cloner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeAndInitialCredentials<IMachine> apply(NodeSpec nodeSpec) {
|
||||
|
||||
Master master = nodeSpec.getMaster();
|
||||
|
||||
if (master.getMachine().getCurrentSnapshot() != null) {
|
||||
ISession session = manager.get().openMachineSession(master.getMachine());
|
||||
session.getConsole().deleteSnapshot(master.getMachine().getCurrentSnapshot().getId());
|
||||
session.unlockMachine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,173 +52,172 @@ import com.google.inject.Inject;
|
|||
|
||||
/**
|
||||
* Utilities for executing functions on a VirtualBox machine.
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
public class MachineUtils {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Factory scriptRunner;
|
||||
private final Supplier<NodeMetadata> host;
|
||||
private final Supplier<VirtualBoxManager> manager;
|
||||
private final Factory scriptRunner;
|
||||
private final Supplier<NodeMetadata> host;
|
||||
|
||||
@Inject
|
||||
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner, Supplier<NodeMetadata> host) {
|
||||
super();
|
||||
this.manager = manager;
|
||||
this.scriptRunner = scriptRunner;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
||||
RunScriptOptions options) {
|
||||
return scriptRunner.submit(metadata, statement, options);
|
||||
}
|
||||
@Inject
|
||||
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
|
||||
Supplier<NodeMetadata> host) {
|
||||
super();
|
||||
this.manager = manager;
|
||||
this.scriptRunner = scriptRunner;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the machine and executes the given function using the machine
|
||||
* matching the given id. Since the machine is locked it is possible to
|
||||
* perform some modifications to the IMachine.
|
||||
* <p/>
|
||||
* Unlocks the machine before returning.
|
||||
*
|
||||
* @param machineId the id of the machine
|
||||
* @param function the function to execute
|
||||
* @return the result from applying the function to the machine.
|
||||
*/
|
||||
public <T> T writeLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
||||
return lockSessionOnMachineAndApply(machineId, LockType.Write,
|
||||
new Function<ISession, T>() {
|
||||
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
||||
RunScriptOptions options) {
|
||||
return scriptRunner.submit(metadata, statement, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T apply(ISession session) {
|
||||
return function.apply(session.getMachine());
|
||||
}
|
||||
/**
|
||||
* Locks the machine and executes the given function using the machine matching the given id. Since the machine is
|
||||
* locked it is possible to perform some modifications to the IMachine.
|
||||
* <p/>
|
||||
* Unlocks the machine before returning.
|
||||
*
|
||||
* @param machineId
|
||||
* the id of the machine
|
||||
* @param function
|
||||
* the function to execute
|
||||
* @return the result from applying the function to the machine.
|
||||
*/
|
||||
public <T> T writeLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
||||
return lockSessionOnMachineAndApply(machineId, LockType.Write, new Function<ISession, T>() {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return function.toString();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the machine and executes the given function using the current
|
||||
* session. Since the machine is locked it is possible to perform some
|
||||
* modifications to the IMachine.
|
||||
* <p/>
|
||||
* Unlocks the machine before returning.
|
||||
*
|
||||
* @param type the kind of lock to use when initially locking the machine.
|
||||
* @param machineId the id of the machine
|
||||
* @param function the function to execute
|
||||
* @return the result from applying the function to the session.
|
||||
*/
|
||||
public <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
|
||||
try {
|
||||
ISession session = lockSessionOnMachine(type, machineId);
|
||||
try {
|
||||
return function.apply(session);
|
||||
} finally {
|
||||
session.unlockMachine();
|
||||
}
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format(
|
||||
"error applying %s to %s with %s lock: %s", function, machineId,
|
||||
type, e.getMessage()), e);
|
||||
@Override
|
||||
public T apply(ISession session) {
|
||||
return function.apply(session.getMachine());
|
||||
}
|
||||
}
|
||||
|
||||
private ISession lockSessionOnMachine(LockType type, String machineId) {
|
||||
return new MutableMachine(manager, type).apply(machineId);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return function.toString();
|
||||
}
|
||||
|
||||
private void unlockMachine(final String machineId) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks the machine and executes the given function using the current session. Since the machine is locked it is
|
||||
* possible to perform some modifications to the IMachine.
|
||||
* <p/>
|
||||
* Unlocks the machine before returning.
|
||||
*
|
||||
* @param type
|
||||
* the kind of lock to use when initially locking the machine.
|
||||
* @param machineId
|
||||
* the id of the machine
|
||||
* @param function
|
||||
* the function to execute
|
||||
* @return the result from applying the function to the session.
|
||||
*/
|
||||
public <T> T lockSessionOnMachineAndApply(String machineId, LockType type, Function<ISession, T> function) {
|
||||
try {
|
||||
ISession session = lockSessionOnMachine(type, machineId);
|
||||
try {
|
||||
return function.apply(session);
|
||||
} finally {
|
||||
session.unlockMachine();
|
||||
}
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format("error applying %s to %s with %s lock: %s", function, machineId, type,
|
||||
e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private ISession lockSessionOnMachine(LockType type, String machineId) {
|
||||
return new MutableMachine(manager, type).apply(machineId);
|
||||
}
|
||||
|
||||
private void unlockMachine(final String machineId) {
|
||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
if (immutableMachine.getSessionState().equals(SessionState.Locked)) {
|
||||
Statement kill = newStatementList(call("default"), findPid(immutableMachine.getSessionPid().toString()), kill());
|
||||
scriptRunner.create(host.get(), kill, runAsRoot(false).wrapInInitScript(false)).init().call();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the machine and executes the given function using the machine matching the given id. Since the machine is
|
||||
* unlocked it is possible to delete the IMachine.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <h3>Note!</h3> Currently, this can only unlock the machine, if the lock was created in the current session.
|
||||
*
|
||||
* @param machineId
|
||||
* the id of the machine
|
||||
* @param function
|
||||
* the function to execute
|
||||
* @return the result from applying the function to the machine.
|
||||
*/
|
||||
public <T> T unlockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
||||
|
||||
try {
|
||||
unlockMachine(machineId);
|
||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
if (immutableMachine.getSessionState().equals(SessionState.Locked)) {
|
||||
Statement kill = newStatementList(call("default"),
|
||||
findPid(immutableMachine.getSessionPid().toString()), kill());
|
||||
scriptRunner
|
||||
.create(host.get(), kill,
|
||||
runAsRoot(false).wrapInInitScript(false)).init().call();
|
||||
return function.apply(immutableMachine);
|
||||
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format("error applying %s to %s: %s", function, machineId, e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the machine and executes the given function, if the machine is registered. Since the machine is unlocked it
|
||||
* is possible to delete the machine.
|
||||
* <p/>
|
||||
*
|
||||
* @param machineId
|
||||
* the id of the machine
|
||||
* @param function
|
||||
* the function to execute
|
||||
* @return the result from applying the function to the session.
|
||||
*/
|
||||
public <T> T unlockMachineAndApplyOrReturnNullIfNotRegistered(String machineId, Function<IMachine, T> function) {
|
||||
try {
|
||||
return unlockMachineAndApply(machineId, function);
|
||||
} catch (RuntimeException e) {
|
||||
VBoxException vbex = Throwables2.getFirstThrowableOfType(e, VBoxException.class);
|
||||
if (vbex != null && vbex.getMessage().indexOf("not find a registered") == -1)
|
||||
throw e;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param machineId
|
||||
* @param function
|
||||
* @return
|
||||
*/
|
||||
public <T> T applyForMachine(final String machineId, final Function<IMachine, T> function) {
|
||||
final IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
return new Function<IMachine, T>() {
|
||||
@Override
|
||||
public T apply(IMachine machine) {
|
||||
return function.apply(machine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the machine and executes the given function using the machine
|
||||
* matching the given id. Since the machine is unlocked it is possible to
|
||||
* delete the IMachine.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <h3>Note!</h3> Currently, this can only unlock the machine, if the lock
|
||||
* was created in the current session.
|
||||
*
|
||||
* @param machineId the id of the machine
|
||||
* @param function the function to execute
|
||||
* @return the result from applying the function to the machine.
|
||||
*/
|
||||
public <T> T unlockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
||||
|
||||
try {
|
||||
unlockMachine(machineId);
|
||||
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
return function.apply(immutableMachine);
|
||||
|
||||
} catch (VBoxException e) {
|
||||
throw new RuntimeException(String.format(
|
||||
"error applying %s to %s: %s", function, machineId,
|
||||
e.getMessage()), e);
|
||||
@Override
|
||||
public String toString() {
|
||||
return function.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the machine and executes the given function, if the machine is
|
||||
* registered. Since the machine is unlocked it is possible to delete the
|
||||
* machine.
|
||||
* <p/>
|
||||
*
|
||||
* @param machineId the id of the machine
|
||||
* @param function the function to execute
|
||||
* @return the result from applying the function to the session.
|
||||
*/
|
||||
public <T> T unlockMachineAndApplyOrReturnNullIfNotRegistered(String machineId,
|
||||
Function<IMachine, T> function) {
|
||||
try {
|
||||
return unlockMachineAndApply(machineId, function);
|
||||
} catch (RuntimeException e) {
|
||||
VBoxException vbex = Throwables2.getFirstThrowableOfType(e,
|
||||
VBoxException.class);
|
||||
if (vbex != null
|
||||
&& vbex.getMessage().indexOf("not find a registered") == -1)
|
||||
throw e;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param machineId
|
||||
* @param function
|
||||
* @return
|
||||
*/
|
||||
public <T> T applyForMachine(final String machineId, final Function<IMachine, T> function) {
|
||||
final IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||
return new Function<IMachine, T>() {
|
||||
@Override
|
||||
public T apply(IMachine machine) {
|
||||
return function.apply(machine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return function.toString();
|
||||
}
|
||||
}.apply(immutableMachine);
|
||||
}
|
||||
}.apply(immutableMachine);
|
||||
}
|
||||
|
||||
public static boolean machineNotFoundException(VBoxException e) {
|
||||
return e.getMessage().contains("VirtualBox error: Could not find a registered machine named ")
|
||||
|| e.getMessage().contains("Could not find a registered machine with UUID {");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@ import com.google.inject.Injector;
|
|||
/**
|
||||
* @author Andrea Turli
|
||||
*/
|
||||
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest")
|
||||
public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
||||
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest")
|
||||
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest extends
|
||||
BaseVirtualBoxClientLiveTest {
|
||||
|
||||
private static final boolean IS_LINKED_CLONE = true;
|
||||
|
@ -61,6 +61,10 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
|||
|
||||
private CleanupMode mode = CleanupMode.Full;
|
||||
|
||||
private VmSpec clonedVmSpec;
|
||||
|
||||
private NetworkSpec cloneNetworkSpec;
|
||||
|
||||
@Override
|
||||
@BeforeClass(groups = "live")
|
||||
public void setupClient() {
|
||||
|
@ -101,19 +105,20 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
|||
|
||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
|
||||
|
||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||
.builder().addNetworkAdapter(networkAdapter).build();
|
||||
|
||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
||||
this.cloneNetworkSpec = NetworkSpec.builder()
|
||||
.addNIC(0L, networkInterfaceCard).build();
|
||||
|
||||
sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec)
|
||||
.network(networkSpec).build();
|
||||
.network(cloneNetworkSpec).build();
|
||||
|
||||
VmSpec clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
|
||||
this.clonedVmSpec = VmSpec.builder().id(cloneName).name(cloneName)
|
||||
.memoryMB(512).cleanUpMode(mode).forceOverwrite(true).build();
|
||||
|
||||
cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(networkSpec)
|
||||
.build();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -121,7 +126,9 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
|||
public void testCloneMachineFromAnotherMachine() throws Exception {
|
||||
try {
|
||||
IMachine source = getSourceNode();
|
||||
|
||||
CloneSpec cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(cloneNetworkSpec).master(source)
|
||||
.linked(IS_LINKED_CLONE)
|
||||
.build();
|
||||
if (source.getCurrentSnapshot() != null) {
|
||||
ISession session = manager.get().openMachineSession(source);
|
||||
session.getConsole().deleteSnapshot(
|
||||
|
@ -130,8 +137,7 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
|||
}
|
||||
|
||||
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
||||
manager, workingDir, cloneSpec, IS_LINKED_CLONE,
|
||||
machineUtils).apply(source);
|
||||
manager, workingDir,machineUtils).apply(cloneSpec);
|
||||
assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName());
|
||||
} finally {
|
||||
for (VmSpec spec : ImmutableSet.of(cloneSpec.getVmSpec(),
|
Loading…
Reference in New Issue