mirror of https://github.com/apache/jclouds.git
Merge pull request #161 from andreisavu/specify-ip-address
Allow user the specify the ip address for a cloudstack vm
This commit is contained in:
commit
9b432304f5
|
@ -29,6 +29,8 @@ import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options used to control what disk offerings are returned
|
* Options used to control what disk offerings are returned
|
||||||
*
|
*
|
||||||
|
@ -50,7 +52,7 @@ public class DeployVirtualMachineOptions extends AccountInDomainOptions {
|
||||||
* parameter passed is from an ISO object, the diskOfferingId refers to a
|
* parameter passed is from an ISO object, the diskOfferingId refers to a
|
||||||
* ROOT Disk Volume created.
|
* ROOT Disk Volume created.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param diskofferingid
|
||||||
* the ID of the disk offering
|
* the ID of the disk offering
|
||||||
*/
|
*/
|
||||||
public DeployVirtualMachineOptions diskOfferingId(long diskofferingid) {
|
public DeployVirtualMachineOptions diskOfferingId(long diskofferingid) {
|
||||||
|
@ -104,6 +106,35 @@ public class DeployVirtualMachineOptions extends AccountInDomainOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ipAddress
|
||||||
|
* the requested ip address (2.2.12 only option)
|
||||||
|
*/
|
||||||
|
public DeployVirtualMachineOptions ipAddress(String ipAddress) {
|
||||||
|
this.queryParameters.replaceValues("ipaddress", ImmutableSet.of(ipAddress));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ipToNetworkList
|
||||||
|
* mapping ip addresses to network ids (2.2.12 only option)
|
||||||
|
*/
|
||||||
|
public DeployVirtualMachineOptions ipToNetworkList(Map<String, Long> ipToNetworkList) {
|
||||||
|
int count = 0;
|
||||||
|
for(String ip : ipToNetworkList.keySet()) {
|
||||||
|
this.queryParameters.replaceValues(
|
||||||
|
String.format("ipnetworklist[%d].ip", count),
|
||||||
|
ImmutableSet.of(ip)
|
||||||
|
);
|
||||||
|
this.queryParameters.replaceValues(
|
||||||
|
String.format("ipnetworklist[%d].networkid", count),
|
||||||
|
ImmutableSet.of("" + ipToNetworkList.get(ip))
|
||||||
|
);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param networkId
|
* @param networkId
|
||||||
* network id used by virtual machine
|
* network id used by virtual machine
|
||||||
|
@ -236,6 +267,22 @@ public class DeployVirtualMachineOptions extends AccountInDomainOptions {
|
||||||
return options.name(name);
|
return options.name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DeployVirtualMachineOptions#ipAddress
|
||||||
|
*/
|
||||||
|
public static DeployVirtualMachineOptions ipAddress(String ipAddress) {
|
||||||
|
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
||||||
|
return options.ipAddress(ipAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DeployVirtualMachineOptions#ipToNetworkList
|
||||||
|
*/
|
||||||
|
public static DeployVirtualMachineOptions ipToNetworkList(Map<String, Long> ipToNetworkList) {
|
||||||
|
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
||||||
|
return options.ipToNetworkList(ipToNetworkList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DeployVirtualMachineOptions#networkId
|
* @see DeployVirtualMachineOptions#networkId
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -136,7 +136,9 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
protected RetryablePredicate<Long> jobComplete;
|
protected RetryablePredicate<Long> jobComplete;
|
||||||
protected RetryablePredicate<Long> adminJobComplete;
|
protected RetryablePredicate<Long> adminJobComplete;
|
||||||
protected RetryablePredicate<VirtualMachine> virtualMachineRunning;
|
protected RetryablePredicate<VirtualMachine> virtualMachineRunning;
|
||||||
|
protected RetryablePredicate<VirtualMachine> adminVirtualMachineRunning;
|
||||||
protected RetryablePredicate<VirtualMachine> virtualMachineDestroyed;
|
protected RetryablePredicate<VirtualMachine> virtualMachineDestroyed;
|
||||||
|
protected RetryablePredicate<VirtualMachine> adminVirtualMachineDestroyed;
|
||||||
protected SshClient.Factory sshFactory;
|
protected SshClient.Factory sshFactory;
|
||||||
protected String password = "password";
|
protected String password = "password";
|
||||||
|
|
||||||
|
@ -196,9 +198,15 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5, 5,
|
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5, 5,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
injector.injectMembers(virtualMachineRunning);
|
injector.injectMembers(virtualMachineRunning);
|
||||||
|
adminVirtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(adminClient), 600, 5, 5,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
injector.injectMembers(adminVirtualMachineRunning);
|
||||||
virtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(client), 600, 5, 5,
|
virtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(client), 600, 5, 5,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
injector.injectMembers(virtualMachineDestroyed);
|
injector.injectMembers(virtualMachineDestroyed);
|
||||||
|
adminVirtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(adminClient), 600, 5, 5,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
injector.injectMembers(adminVirtualMachineDestroyed);
|
||||||
reuseOrAssociate = new ReuseOrAssociateNewPublicIPAddress(client, jobComplete);
|
reuseOrAssociate = new ReuseOrAssociateNewPublicIPAddress(client, jobComplete);
|
||||||
injector.injectMembers(reuseOrAssociate);
|
injector.injectMembers(reuseOrAssociate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,28 +18,44 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudstack.features;
|
package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Predicates.equalTo;
|
import static com.google.common.base.Predicates.equalTo;
|
||||||
import static com.google.common.base.Predicates.in;
|
import static com.google.common.base.Predicates.in;
|
||||||
import static com.google.common.base.Predicates.or;
|
import static com.google.common.base.Predicates.or;
|
||||||
import static com.google.common.collect.Iterables.find;
|
import static com.google.common.collect.Iterables.find;
|
||||||
import static com.google.common.collect.Iterables.get;
|
import static com.google.common.collect.Iterables.get;
|
||||||
|
import static com.google.common.collect.Iterables.getFirst;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
import static com.google.common.collect.Sets.filter;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
import static org.testng.Assert.fail;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
import org.jclouds.cloudstack.domain.AsyncJob;
|
import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
|
import org.jclouds.cloudstack.domain.GuestIPType;
|
||||||
import org.jclouds.cloudstack.domain.NIC;
|
import org.jclouds.cloudstack.domain.NIC;
|
||||||
import org.jclouds.cloudstack.domain.Network;
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.NetworkOffering;
|
||||||
import org.jclouds.cloudstack.domain.ServiceOffering;
|
import org.jclouds.cloudstack.domain.ServiceOffering;
|
||||||
|
import org.jclouds.cloudstack.domain.Template;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.domain.Zone;
|
import org.jclouds.cloudstack.domain.Zone;
|
||||||
|
import org.jclouds.cloudstack.options.CreateNetworkOptions;
|
||||||
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
||||||
|
import org.jclouds.cloudstack.options.ListNetworkOfferingsOptions;
|
||||||
|
import org.jclouds.cloudstack.options.ListNetworksOptions;
|
||||||
|
import org.jclouds.cloudstack.options.ListTemplatesOptions;
|
||||||
import org.jclouds.cloudstack.options.ListVirtualMachinesOptions;
|
import org.jclouds.cloudstack.options.ListVirtualMachinesOptions;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
@ -52,7 +68,8 @@ import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
import com.google.common.net.HostSpecifier;
|
import com.google.common.net.HostSpecifier;
|
||||||
import org.testng.collections.Sets;
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code VirtualMachineClientLiveTest}
|
* Tests behavior of {@code VirtualMachineClientLiveTest}
|
||||||
|
@ -61,6 +78,8 @@ import org.testng.collections.Sets;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", singleThreaded = true, testName = "VirtualMachineClientLiveTest")
|
@Test(groups = "live", singleThreaded = true, testName = "VirtualMachineClientLiveTest")
|
||||||
public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
|
private final static Logger logger = Logger.getAnonymousLogger();
|
||||||
|
|
||||||
private VirtualMachine vm = null;
|
private VirtualMachine vm = null;
|
||||||
|
|
||||||
static final Ordering<ServiceOffering> DEFAULT_SIZE_ORDERING = new Ordering<ServiceOffering>() {
|
static final Ordering<ServiceOffering> DEFAULT_SIZE_ORDERING = new Ordering<ServiceOffering>() {
|
||||||
|
@ -111,6 +130,25 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
virtualMachineRunning);
|
virtualMachineRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static VirtualMachine createVirtualMachineInNetworkWithIp(
|
||||||
|
CloudStackClient client, long templateId, Set<Network> networks, Map<String, Long> ipToNetwork,
|
||||||
|
RetryablePredicate<Long> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
||||||
|
|
||||||
|
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
||||||
|
|
||||||
|
long zoneId = getFirst(networks, null).getZoneId();
|
||||||
|
options.networkIds(Iterables.transform(networks, new Function<Network, Long>() {
|
||||||
|
@Override
|
||||||
|
public Long apply(@Nullable Network network) {
|
||||||
|
return network.getId();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
options.ipToNetworkList(ipToNetwork);
|
||||||
|
|
||||||
|
return createVirtualMachineWithOptionsInZone(options, zoneId, templateId,
|
||||||
|
client, jobComplete, virtualMachineRunning);
|
||||||
|
}
|
||||||
|
|
||||||
public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options, long zoneId,
|
public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options, long zoneId,
|
||||||
long templateId, CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
long templateId, CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
||||||
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
||||||
|
@ -150,6 +188,99 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
checkVm(vm);
|
checkVm(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateVirtualMachineWithSpecificIp() throws Exception {
|
||||||
|
Long templateId = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
|
Network network = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Template template = getOnlyElement(
|
||||||
|
client.getTemplateClient().listTemplates(ListTemplatesOptions.Builder.id(templateId)));
|
||||||
|
logger.info("Using template: " + template);
|
||||||
|
|
||||||
|
Set<Network> allSafeNetworksInZone = adminClient.getNetworkClient().listNetworks(
|
||||||
|
ListNetworksOptions.Builder.zoneId(template.getZoneId()).isSystem(false));
|
||||||
|
for(Network net : allSafeNetworksInZone) {
|
||||||
|
if(net.getName().equals(prefix + "-ip-network")) {
|
||||||
|
logger.info("Deleting VMs in network: " + net);
|
||||||
|
|
||||||
|
Set<VirtualMachine> machinesInNetwork = adminClient.getVirtualMachineClient().listVirtualMachines(
|
||||||
|
ListVirtualMachinesOptions.Builder.networkId(net.getId()));
|
||||||
|
|
||||||
|
for(VirtualMachine machine : machinesInNetwork) {
|
||||||
|
if (machine.getState().equals(VirtualMachine.State.RUNNING)) {
|
||||||
|
logger.info("Deleting VM: " + machine);
|
||||||
|
destroyMachine(machine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert adminJobComplete.apply(
|
||||||
|
adminClient.getNetworkClient().deleteNetwork(net.getId())) : net;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkOffering offering = getFirst(
|
||||||
|
client.getOfferingClient().listNetworkOfferings(
|
||||||
|
ListNetworkOfferingsOptions.Builder.zoneId(template.getZoneId()).specifyVLAN(true)), null);
|
||||||
|
checkNotNull(offering, "No network offering found");
|
||||||
|
logger.info("Using network offering: " + offering);
|
||||||
|
|
||||||
|
network = adminClient.getNetworkClient().createNetworkInZone(
|
||||||
|
template.getZoneId(), offering.getId(), prefix + "-ip-network", "",
|
||||||
|
CreateNetworkOptions.Builder.startIP("192.168.0.1").endIP("192.168.0.5")
|
||||||
|
.netmask("255.255.255.0").gateway("192.168.0.1").vlan("21"));
|
||||||
|
logger.info("Created network: " + network);
|
||||||
|
|
||||||
|
Network requiredNetwork = getOnlyElement(filter(adminClient.getNetworkClient().listNetworks(
|
||||||
|
ListNetworksOptions.Builder.zoneId(template.getZoneId())), new Predicate<Network>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(@Nullable Network network) {
|
||||||
|
return network.isDefault() &&
|
||||||
|
network.getGuestIPType() == GuestIPType.VIRTUAL &&
|
||||||
|
network.getNetworkOfferingId() == 6 &&
|
||||||
|
network.getId() == 204;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
logger.info("Required network: " + requiredNetwork);
|
||||||
|
|
||||||
|
String ipAddress = "192.168.0.4";
|
||||||
|
|
||||||
|
Map<String, Long> ipToNetwork = Maps.newHashMap();
|
||||||
|
ipToNetwork.put(ipAddress, network.getId());
|
||||||
|
|
||||||
|
vm = createVirtualMachineInNetworkWithIp(
|
||||||
|
adminClient, templateId, ImmutableSet.of(requiredNetwork, network),
|
||||||
|
ipToNetwork, adminJobComplete, adminVirtualMachineRunning);
|
||||||
|
logger.info("Created VM: " + vm);
|
||||||
|
|
||||||
|
boolean hasStaticIpNic = false;
|
||||||
|
for(NIC nic : vm.getNICs()) {
|
||||||
|
if (nic.getNetworkId() == network.getId()) {
|
||||||
|
hasStaticIpNic = true;
|
||||||
|
assertEquals(nic.getIPAddress(), ipAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert hasStaticIpNic;
|
||||||
|
checkVm(vm);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (vm != null) {
|
||||||
|
destroyMachine(vm);
|
||||||
|
vm = null;
|
||||||
|
}
|
||||||
|
if (network != null) {
|
||||||
|
long jobId = adminClient.getNetworkClient().deleteNetwork(network.getId());
|
||||||
|
adminJobComplete.apply(jobId);
|
||||||
|
network = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void destroyMachine(VirtualMachine virtualMachine) {
|
||||||
|
assert adminJobComplete.apply(
|
||||||
|
adminClient.getVirtualMachineClient().destroyVirtualMachine(virtualMachine.getId())) : virtualMachine;
|
||||||
|
assert adminVirtualMachineDestroyed.apply(virtualMachine);
|
||||||
|
}
|
||||||
|
|
||||||
private void conditionallyCheckSSH() {
|
private void conditionallyCheckSSH() {
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
assert HostSpecifier.isValid(vm.getIPAddress());
|
assert HostSpecifier.isValid(vm.getIPAddress());
|
||||||
|
@ -194,9 +325,8 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
protected void tearDown() {
|
protected void tearDown() {
|
||||||
if (vm != null) {
|
if (vm != null) {
|
||||||
assert jobComplete.apply(client.getVirtualMachineClient().stopVirtualMachine(vm.getId())) : vm;
|
destroyMachine(vm);
|
||||||
assert jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId())) : vm;
|
vm = null;
|
||||||
assert virtualMachineDestroyed.apply(vm);
|
|
||||||
}
|
}
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue