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 javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeServiceAdapter;
|
import org.jclouds.compute.ComputeServiceAdapter;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
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.jclouds.virtualbox.domain.YamlImage;
|
||||||
import org.virtualbox_4_1.CleanupMode;
|
import org.virtualbox_4_1.CleanupMode;
|
||||||
import org.virtualbox_4_1.IMachine;
|
import org.virtualbox_4_1.IMachine;
|
||||||
|
@ -62,13 +63,13 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
||||||
|
|
||||||
private final Supplier<VirtualBoxManager> manager;
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
private final Map<Image, YamlImage> images;
|
private final Map<Image, YamlImage> images;
|
||||||
private final LoadingCache<Image, IMachine> mastersLoader;
|
private final LoadingCache<Image, Master> mastersLoader;
|
||||||
private final Function<IMachine, NodeAndInitialCredentials<IMachine>> cloneCreator;
|
private final Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
|
public VirtualBoxComputeServiceAdapter(Supplier<VirtualBoxManager> manager,
|
||||||
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, IMachine> mastersLoader,
|
Supplier<Map<Image, YamlImage>> imagesMapper, LoadingCache<Image, Master> mastersLoader,
|
||||||
Function<IMachine, NodeAndInitialCredentials<IMachine>> cloneCreator) {
|
Function<NodeSpec, NodeAndInitialCredentials<IMachine>> cloneCreator) {
|
||||||
this.manager = checkNotNull(manager, "manager");
|
this.manager = checkNotNull(manager, "manager");
|
||||||
this.images = imagesMapper.get();
|
this.images = imagesMapper.get();
|
||||||
this.mastersLoader = mastersLoader;
|
this.mastersLoader = mastersLoader;
|
||||||
|
@ -79,8 +80,9 @@ public class VirtualBoxComputeServiceAdapter implements ComputeServiceAdapter<IM
|
||||||
public NodeAndInitialCredentials<IMachine> createNodeWithGroupEncodedIntoName(String tag, String name,
|
public NodeAndInitialCredentials<IMachine> createNodeWithGroupEncodedIntoName(String tag, String name,
|
||||||
Template template) {
|
Template template) {
|
||||||
try {
|
try {
|
||||||
IMachine master = mastersLoader.get(template.getImage());
|
Master master = mastersLoader.get(template.getImage());
|
||||||
return cloneCreator.apply(master);
|
NodeSpec nodeSpec = NodeSpec.builder().master(master).name(name).tag(tag).template(template).build();
|
||||||
|
return cloneCreator.apply(nodeSpec);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
package org.jclouds.virtualbox.config;
|
package org.jclouds.virtualbox.config;
|
||||||
|
|
||||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_PRECONFIGURATION_URL;
|
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.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -60,16 +57,19 @@ import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
import org.jclouds.virtualbox.Host;
|
import org.jclouds.virtualbox.Host;
|
||||||
import org.jclouds.virtualbox.Preconfiguration;
|
import org.jclouds.virtualbox.Preconfiguration;
|
||||||
import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter;
|
import org.jclouds.virtualbox.compute.VirtualBoxComputeServiceAdapter;
|
||||||
|
import org.jclouds.virtualbox.domain.CloneSpec;
|
||||||
import org.jclouds.virtualbox.domain.ExecutionType;
|
import org.jclouds.virtualbox.domain.ExecutionType;
|
||||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||||
|
import org.jclouds.virtualbox.domain.Master;
|
||||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||||
import org.jclouds.virtualbox.domain.YamlImage;
|
import org.jclouds.virtualbox.domain.YamlImage;
|
||||||
|
import org.jclouds.virtualbox.functions.CloneAndRegisterMachineFromIMachineIfNotAlreadyExists;
|
||||||
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
import org.jclouds.virtualbox.functions.CreateAndInstallVm;
|
||||||
import org.jclouds.virtualbox.functions.IMachineToHardware;
|
import org.jclouds.virtualbox.functions.IMachineToHardware;
|
||||||
import org.jclouds.virtualbox.functions.IMachineToImage;
|
import org.jclouds.virtualbox.functions.IMachineToImage;
|
||||||
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
|
import org.jclouds.virtualbox.functions.IMachineToNodeMetadata;
|
||||||
import org.jclouds.virtualbox.functions.IMachineToSshClient;
|
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.NodeCreator;
|
||||||
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
|
import org.jclouds.virtualbox.functions.YamlImagesFromFileConfig;
|
||||||
import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor;
|
import org.jclouds.virtualbox.functions.admin.ImagesToYamlImagesFromYamlDescriptor;
|
||||||
|
@ -134,14 +134,16 @@ public class VirtualBoxComputeServiceContextModule extends
|
||||||
bind(new TypeLiteral<Supplier<String>>() {
|
bind(new TypeLiteral<Supplier<String>>() {
|
||||||
}).to((Class) YamlImagesFromFileConfig.class);
|
}).to((Class) YamlImagesFromFileConfig.class);
|
||||||
// the master machines cache
|
// the master machines cache
|
||||||
bind(new TypeLiteral<LoadingCache<Image, IMachine>>() {
|
bind(new TypeLiteral<LoadingCache<Image, Master>>() {
|
||||||
}).to((Class) MasterImages.class);
|
}).to((Class) MastersCache.class);
|
||||||
// the master creating function
|
// the master creating function
|
||||||
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
|
bind(new TypeLiteral<Function<MasterSpec, IMachine>>() {
|
||||||
}).to((Class) CreateAndInstallVm.class);
|
}).to((Class) CreateAndInstallVm.class);
|
||||||
// the machine cloning function
|
// the machine cloning function
|
||||||
bind(new TypeLiteral<Function<IMachine, NodeAndInitialCredentials<IMachine>>>() {
|
bind(new TypeLiteral<Function<IMachine, NodeAndInitialCredentials<IMachine>>>() {
|
||||||
}).to((Class) NodeCreator.class);
|
}).to((Class) NodeCreator.class);
|
||||||
|
bind(new TypeLiteral<Function<CloneSpec, IMachine>>() {
|
||||||
|
}).to((Class) CloneAndRegisterMachineFromIMachineIfNotAlreadyExists.class);
|
||||||
|
|
||||||
// for byon
|
// for byon
|
||||||
bind(new TypeLiteral<Function<URI, InputStream>>() {
|
bind(new TypeLiteral<Function<URI, InputStream>>() {
|
||||||
|
|
|
@ -19,10 +19,12 @@
|
||||||
|
|
||||||
package org.jclouds.virtualbox.domain;
|
package org.jclouds.virtualbox.domain;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
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
|
* A complete specification of a "clone" node with networking setup
|
||||||
* and the physical machine specification.
|
* and the physical machine specification.
|
||||||
|
@ -31,6 +33,8 @@ public class CloneSpec {
|
||||||
|
|
||||||
private final VmSpec vmSpec;
|
private final VmSpec vmSpec;
|
||||||
private final NetworkSpec networkSpec;
|
private final NetworkSpec networkSpec;
|
||||||
|
private final IMachine master;
|
||||||
|
private final boolean isLinked;
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -40,6 +44,8 @@ public class CloneSpec {
|
||||||
|
|
||||||
private VmSpec vmSpec;
|
private VmSpec vmSpec;
|
||||||
private NetworkSpec networkSpec;
|
private NetworkSpec networkSpec;
|
||||||
|
private IMachine master;
|
||||||
|
private boolean isLinked;
|
||||||
|
|
||||||
public Builder vm(VmSpec vmSpec) {
|
public Builder vm(VmSpec vmSpec) {
|
||||||
this.vmSpec = vmSpec;
|
this.vmSpec = vmSpec;
|
||||||
|
@ -50,18 +56,31 @@ public class CloneSpec {
|
||||||
this.networkSpec = networkSpec;
|
this.networkSpec = networkSpec;
|
||||||
return this;
|
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() {
|
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(vmSpec, "vmSpec");
|
||||||
checkNotNull(networkSpec, "networkSpec");
|
checkNotNull(networkSpec, "networkSpec");
|
||||||
|
checkNotNull(master, "master");
|
||||||
this.vmSpec = vmSpec;
|
this.vmSpec = vmSpec;
|
||||||
this.networkSpec = networkSpec;
|
this.networkSpec = networkSpec;
|
||||||
|
this.master = master;
|
||||||
|
this.isLinked = isLinked;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VmSpec getVmSpec() {
|
public VmSpec getVmSpec() {
|
||||||
|
@ -71,6 +90,14 @@ public class CloneSpec {
|
||||||
public NetworkSpec getNetworkSpec() {
|
public NetworkSpec getNetworkSpec() {
|
||||||
return networkSpec;
|
return networkSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IMachine getMaster() {
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLinked() {
|
||||||
|
return isLinked;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
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(vmSpec, "vmSpec");
|
||||||
checkNotNull(isoSpec, "isoSpec");
|
checkNotNull(isoSpec, "isoSpec");
|
||||||
checkNotNull(networkSpec, "networkSpec");
|
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
|
* @author Andrea Turli
|
||||||
*/
|
*/
|
||||||
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
||||||
Function<IMachine, IMachine> {
|
Function<CloneSpec, IMachine> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
@ -60,24 +60,20 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
||||||
|
|
||||||
private final Supplier<VirtualBoxManager> manager;
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
private final String workingDir;
|
private final String workingDir;
|
||||||
private final CloneSpec cloneSpec;
|
|
||||||
private final boolean isLinkedClone;
|
|
||||||
private final MachineUtils machineUtils;
|
private final MachineUtils machineUtils;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
public CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
||||||
Supplier<VirtualBoxManager> manager,
|
Supplier<VirtualBoxManager> manager,
|
||||||
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir,
|
@Named(VirtualBoxConstants.VIRTUALBOX_WORKINGDIR) String workingDir,
|
||||||
CloneSpec cloneSpec, boolean isLinkedClone, MachineUtils machineUtils) {
|
MachineUtils machineUtils) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.workingDir = workingDir;
|
this.workingDir = workingDir;
|
||||||
this.cloneSpec = cloneSpec;
|
|
||||||
this.isLinkedClone = isLinkedClone;
|
|
||||||
this.machineUtils = machineUtils;
|
this.machineUtils = machineUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMachine apply(@Nullable IMachine master) {
|
public IMachine apply(CloneSpec cloneSpec) {
|
||||||
VmSpec vmSpec = cloneSpec.getVmSpec();
|
VmSpec vmSpec = cloneSpec.getVmSpec();
|
||||||
try {
|
try {
|
||||||
manager.get().getVBox().findMachine(vmSpec.getVmName());
|
manager.get().getVBox().findMachine(vmSpec.getVmName());
|
||||||
|
@ -85,7 +81,7 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
||||||
+ " is already registered.");
|
+ " is already registered.");
|
||||||
} catch (VBoxException e) {
|
} catch (VBoxException e) {
|
||||||
if (machineNotFoundException(e))
|
if (machineNotFoundException(e))
|
||||||
return cloneMachine(vmSpec, master);
|
return cloneMachine(cloneSpec);
|
||||||
else
|
else
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +94,10 @@ public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExists implements
|
||||||
"Could not find a registered machine with UUID {");
|
"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()
|
String settingsFile = manager.get().getVBox()
|
||||||
.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
||||||
IMachine clonedMachine = manager
|
IMachine clonedMachine = manager
|
||||||
|
|
|
@ -53,7 +53,6 @@ import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.jclouds.virtualbox.functions;
|
package org.jclouds.virtualbox.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Set;
|
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) {
|
private IMachine createMachine(IVirtualBox vBox, MasterSpec machineSpec) {
|
||||||
VmSpec vmSpec = machineSpec.getVmSpec();
|
VmSpec vmSpec = machineSpec.getVmSpec();
|
||||||
String settingsFile = vBox.composeMachineFilename(vmSpec.getVmName(), workingDir);
|
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_IMAGE_PREFIX;
|
||||||
import static org.jclouds.virtualbox.config.VirtualBoxConstants.VIRTUALBOX_INSTALLATION_KEY_SEQUENCE;
|
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.config.VirtualBoxConstants.VIRTUALBOX_WORKINGDIR;
|
||||||
|
import static org.jclouds.virtualbox.util.MachineUtils.machineNotFoundException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -38,6 +39,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.virtualbox.domain.HardDisk;
|
import org.jclouds.virtualbox.domain.HardDisk;
|
||||||
import org.jclouds.virtualbox.domain.IsoSpec;
|
import org.jclouds.virtualbox.domain.IsoSpec;
|
||||||
|
import org.jclouds.virtualbox.domain.Master;
|
||||||
import org.jclouds.virtualbox.domain.MasterSpec;
|
import org.jclouds.virtualbox.domain.MasterSpec;
|
||||||
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
import org.jclouds.virtualbox.domain.NetworkAdapter;
|
||||||
import org.jclouds.virtualbox.domain.NetworkInterfaceCard;
|
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.IMachine;
|
||||||
import org.virtualbox_4_1.NetworkAttachmentType;
|
import org.virtualbox_4_1.NetworkAttachmentType;
|
||||||
import org.virtualbox_4_1.StorageBus;
|
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.Function;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
@ -63,25 +67,28 @@ import com.google.common.collect.Maps;
|
||||||
* @author dralves
|
* @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 Map<String, Master> masters = Maps.newHashMap();
|
||||||
private final Function<MasterSpec, IMachine> mastersLoader;
|
private final Function<MasterSpec, IMachine> masterCreatorAndInstaller;
|
||||||
private final Map<String, YamlImage> imageMapping;
|
private final Map<String, YamlImage> imageMapping;
|
||||||
private final String workingDir;
|
private final String workingDir;
|
||||||
private final String adminDisk;
|
private final String adminDisk;
|
||||||
private final String guestAdditionsIso;
|
private final String guestAdditionsIso;
|
||||||
private final String installationKeySequence;
|
private final String installationKeySequence;
|
||||||
private final String isosDir;
|
private final String isosDir;
|
||||||
|
private Supplier<VirtualBoxManager> manager;
|
||||||
|
|
||||||
@Inject
|
@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_INSTALLATION_KEY_SEQUENCE) String installationKeySequence,
|
||||||
@Named(VIRTUALBOX_WORKINGDIR) String workingDir, Function<MasterSpec, IMachine> masterLoader,
|
@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(version, "version");
|
||||||
checkNotNull(installationKeySequence, "installationKeySequence");
|
checkNotNull(installationKeySequence, "installationKeySequence");
|
||||||
this.mastersLoader = masterLoader;
|
checkNotNull(manager, "vboxmanager");
|
||||||
|
this.manager = manager;
|
||||||
|
this.masterCreatorAndInstaller = masterLoader;
|
||||||
this.installationKeySequence = installationKeySequence;
|
this.installationKeySequence = installationKeySequence;
|
||||||
this.workingDir = workingDir == null ? VIRTUALBOX_DEFAULT_DIR : workingDir;
|
this.workingDir = workingDir == null ? VIRTUALBOX_DEFAULT_DIR : workingDir;
|
||||||
File wdFile = new File(this.workingDir);
|
File wdFile = new File(this.workingDir);
|
||||||
|
@ -100,13 +107,12 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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())) {
|
if (masters.containsKey(key.getId())) {
|
||||||
return masters.get(key);
|
return masters.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNotNull(key, "key");
|
|
||||||
|
|
||||||
// the yaml image
|
// the yaml image
|
||||||
YamlImage yamlImage = imageMapping.get(key.getId());
|
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("")
|
VmSpec vmSpecification = VmSpec.builder().id(yamlImage.id).name(vmName).memoryMB(512).osTypeId("")
|
||||||
.controller(ideController).forceOverwrite(true).cleanUpMode(CleanupMode.Full).build();
|
.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()
|
NetworkAdapter networkAdapter = NetworkAdapter.builder().networkAttachmentType(NetworkAttachmentType.NAT)
|
||||||
.addNIC(0L, networkInterfaceCard).build();
|
.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
|
MasterSpec masterSpec = MasterSpec
|
||||||
.builder()
|
.builder()
|
||||||
|
@ -140,12 +145,25 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
||||||
.iso(
|
.iso(
|
||||||
IsoSpec.builder().sourcePath(localIsoUrl)
|
IsoSpec.builder().sourcePath(localIsoUrl)
|
||||||
.installationScript(installationKeySequence.replace("HOSTNAME", vmSpecification.getVmName())).build())
|
.installationScript(installationKeySequence.replace("HOSTNAME", vmSpecification.getVmName())).build())
|
||||||
.network(networkSpec)
|
.network(networkSpec).build();
|
||||||
.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);
|
Master master = Master.builder().machine(masterMachine).spec(masterSpec).build();
|
||||||
masters.put(key.getId(), masterMachine);
|
|
||||||
return masterMachine;
|
masters.put(key.getId(), master);
|
||||||
|
|
||||||
|
return master;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFilePathOrDownload(String httpUrl) throws ExecutionException {
|
private String getFilePathOrDownload(String httpUrl) throws ExecutionException {
|
||||||
|
@ -158,7 +176,7 @@ public class MasterImages extends AbstractLoadingCache<Image, IMachine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IMachine getIfPresent(Image key) {
|
public Master getIfPresent(Image key) {
|
||||||
if (masters.containsKey(key.getId())) {
|
if (masters.containsKey(key.getId())) {
|
||||||
return masters.get(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;
|
package org.jclouds.virtualbox.functions;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
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.IMachine;
|
||||||
|
import org.virtualbox_4_1.ISession;
|
||||||
|
import org.virtualbox_4_1.VirtualBoxManager;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
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
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
public NodeAndInitialCredentials<IMachine> apply(IMachine input) {
|
private final Function<CloneSpec, IMachine> cloner;
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
|
@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.
|
* Utilities for executing functions on a VirtualBox machine.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
|
* @author Adrian Cole, Mattias Holmqvist, Andrea Turli
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class MachineUtils {
|
public class MachineUtils {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final Supplier<VirtualBoxManager> manager;
|
private final Supplier<VirtualBoxManager> manager;
|
||||||
private final Factory scriptRunner;
|
private final Factory scriptRunner;
|
||||||
private final Supplier<NodeMetadata> host;
|
private final Supplier<NodeMetadata> host;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner, Supplier<NodeMetadata> host) {
|
public MachineUtils(Supplier<VirtualBoxManager> manager, RunScriptOnNode.Factory scriptRunner,
|
||||||
super();
|
Supplier<NodeMetadata> host) {
|
||||||
this.manager = manager;
|
super();
|
||||||
this.scriptRunner = scriptRunner;
|
this.manager = manager;
|
||||||
this.host = host;
|
this.scriptRunner = scriptRunner;
|
||||||
}
|
this.host = host;
|
||||||
|
}
|
||||||
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
|
||||||
RunScriptOptions options) {
|
|
||||||
return scriptRunner.submit(metadata, statement, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public ListenableFuture<ExecResponse> runScriptOnNode(NodeMetadata metadata, Statement statement,
|
||||||
* Locks the machine and executes the given function using the machine
|
RunScriptOptions options) {
|
||||||
* matching the given id. Since the machine is locked it is possible to
|
return scriptRunner.submit(metadata, statement, options);
|
||||||
* perform some modifications to the IMachine.
|
}
|
||||||
* <p/>
|
|
||||||
* Unlocks the machine before returning.
|
|
||||||
*
|
|
||||||
* @param machineId the id of the machine
|
|
||||||
* @param function the function to execute
|
|
||||||
* @return the result from applying the function to the machine.
|
|
||||||
*/
|
|
||||||
public <T> T writeLockMachineAndApply(final String machineId, final Function<IMachine, T> function) {
|
|
||||||
return lockSessionOnMachineAndApply(machineId, LockType.Write,
|
|
||||||
new Function<ISession, T>() {
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public T apply(ISession session) {
|
* Locks the machine and executes the given function using the machine matching the given id. Since the machine is
|
||||||
return function.apply(session.getMachine());
|
* 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
|
@Override
|
||||||
public String toString() {
|
public T apply(ISession session) {
|
||||||
return function.toString();
|
return function.apply(session.getMachine());
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
@Override
|
||||||
return new MutableMachine(manager, type).apply(machineId);
|
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);
|
IMachine immutableMachine = manager.get().getVBox().findMachine(machineId);
|
||||||
if (immutableMachine.getSessionState().equals(SessionState.Locked)) {
|
return function.apply(immutableMachine);
|
||||||
Statement kill = newStatementList(call("default"),
|
|
||||||
findPid(immutableMachine.getSessionPid().toString()), kill());
|
} catch (VBoxException e) {
|
||||||
scriptRunner
|
throw new RuntimeException(String.format("error applying %s to %s: %s", function, machineId, e.getMessage()), e);
|
||||||
.create(host.get(), kill,
|
}
|
||||||
runAsRoot(false).wrapInInitScript(false)).init().call();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
* Unlocks the machine and executes the given function using the machine
|
public String toString() {
|
||||||
* matching the given id. Since the machine is unlocked it is possible to
|
return function.toString();
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
}
|
}.apply(immutableMachine);
|
||||||
|
}
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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
|
* @author Andrea Turli
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest")
|
@Test(groups = "live", singleThreaded = true, testName = "CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest")
|
||||||
public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
public class CloneAndRegisterMachineFromIMachineIfNotAlreadyExistsLiveTest extends
|
||||||
BaseVirtualBoxClientLiveTest {
|
BaseVirtualBoxClientLiveTest {
|
||||||
|
|
||||||
private static final boolean IS_LINKED_CLONE = true;
|
private static final boolean IS_LINKED_CLONE = true;
|
||||||
|
@ -61,6 +61,10 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
||||||
|
|
||||||
private CleanupMode mode = CleanupMode.Full;
|
private CleanupMode mode = CleanupMode.Full;
|
||||||
|
|
||||||
|
private VmSpec clonedVmSpec;
|
||||||
|
|
||||||
|
private NetworkSpec cloneNetworkSpec;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@BeforeClass(groups = "live")
|
@BeforeClass(groups = "live")
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
|
@ -101,19 +105,20 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
||||||
|
|
||||||
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
NetworkAdapter networkAdapter = NetworkAdapter.builder()
|
||||||
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
|
.networkAttachmentType(NetworkAttachmentType.Bridged).build();
|
||||||
|
|
||||||
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
NetworkInterfaceCard networkInterfaceCard = NetworkInterfaceCard
|
||||||
.builder().addNetworkAdapter(networkAdapter).build();
|
.builder().addNetworkAdapter(networkAdapter).build();
|
||||||
|
|
||||||
NetworkSpec networkSpec = NetworkSpec.builder()
|
this.cloneNetworkSpec = NetworkSpec.builder()
|
||||||
.addNIC(0L, networkInterfaceCard).build();
|
.addNIC(0L, networkInterfaceCard).build();
|
||||||
|
|
||||||
sourceMachineSpec = MasterSpec.builder().iso(isoSpec).vm(sourceVmSpec)
|
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();
|
.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 {
|
public void testCloneMachineFromAnotherMachine() throws Exception {
|
||||||
try {
|
try {
|
||||||
IMachine source = getSourceNode();
|
IMachine source = getSourceNode();
|
||||||
|
CloneSpec cloneSpec = CloneSpec.builder().vm(clonedVmSpec).network(cloneNetworkSpec).master(source)
|
||||||
|
.linked(IS_LINKED_CLONE)
|
||||||
|
.build();
|
||||||
if (source.getCurrentSnapshot() != null) {
|
if (source.getCurrentSnapshot() != null) {
|
||||||
ISession session = manager.get().openMachineSession(source);
|
ISession session = manager.get().openMachineSession(source);
|
||||||
session.getConsole().deleteSnapshot(
|
session.getConsole().deleteSnapshot(
|
||||||
|
@ -130,8 +137,7 @@ public class CloneAndRegisterMachineFromIsoIfNotAlreadyExistsLiveTest extends
|
||||||
}
|
}
|
||||||
|
|
||||||
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
IMachine clone = new CloneAndRegisterMachineFromIMachineIfNotAlreadyExists(
|
||||||
manager, workingDir, cloneSpec, IS_LINKED_CLONE,
|
manager, workingDir,machineUtils).apply(cloneSpec);
|
||||||
machineUtils).apply(source);
|
|
||||||
assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName());
|
assertEquals(clone.getName(), cloneSpec.getVmSpec().getVmName());
|
||||||
} finally {
|
} finally {
|
||||||
for (VmSpec spec : ImmutableSet.of(cloneSpec.getVmSpec(),
|
for (VmSpec spec : ImmutableSet.of(cloneSpec.getVmSpec(),
|
Loading…
Reference in New Issue