updated cloudstack to include adminCredential + vlan tests

This commit is contained in:
Adrian Cole 2011-11-15 12:59:42 +02:00
parent 5842b84ad0
commit e1f66caec0
10 changed files with 258 additions and 112 deletions

View File

@ -52,6 +52,8 @@
<test.cloudstack.apiversion>2.2.12</test.cloudstack.apiversion>
<test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity>
<test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential>
<test.cloudstack.domainAdminIdentity></test.cloudstack.domainAdminIdentity>
<test.cloudstack.domainAdminCredential></test.cloudstack.domainAdminCredential>
<test.cloudstack.image-id></test.cloudstack.image-id>
<test.cloudstack.login-user></test.cloudstack.login-user>
</properties>
@ -118,6 +120,8 @@
<test.cloudstack.credential>${test.cloudstack.credential}</test.cloudstack.credential>
<test.cloudstack.image-id>${test.cloudstack.image-id}</test.cloudstack.image-id>
<test.cloudstack.login-user>${test.cloudstack.login-user}</test.cloudstack.login-user>
<test.cloudstack.domainAdminIdentity>${test.cloudstack.domainAdminIdentity}</test.cloudstack.domainAdminIdentity>
<test.cloudstack.domainAdminCredential>${test.cloudstack.domainAdminCredential}</test.cloudstack.domainAdminCredential>
</systemPropertyVariables>
</configuration>
</execution>

View File

@ -43,7 +43,7 @@ public class CreateNetworkOptions extends AccountInDomainOptions {
/**
* @param isShared
* true if network is shared, false otherwise
* true if network is shared across accounts in the Zone
*/
public CreateNetworkOptions isShared(boolean isShared) {
this.queryParameters.replaceValues("isshared", ImmutableSet.of(isShared + ""));
@ -61,7 +61,7 @@ public class CreateNetworkOptions extends AccountInDomainOptions {
/**
* @param endIP
* the ending IP address in the VLAN IP range
* the ending IP address in the network IP range. If not specified, will be defaulted to startIP
*/
public CreateNetworkOptions endIP(String endIP) {
this.queryParameters.replaceValues("endip", ImmutableSet.of(endIP));

View File

@ -27,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* Options used to control what network offerings are returned
*
* @see <a href=
* "http://download.cloud.com/releases/2.2.0/api/user/listNetworkOfferings.html"
* "http://download.cloud.com/releases/2.2.0/api_2.2.12/user/listNetworkOfferings.html"
* />
* @author Adrian Cole
*/
@ -35,6 +35,15 @@ public class ListNetworkOfferingsOptions extends BaseHttpRequestOptions {
public static final ListNetworkOfferingsOptions NONE = new ListNetworkOfferingsOptions();
/**
* @param zoneId
* list network offerings available for network creation in specific zone
*/
public ListNetworkOfferingsOptions zoneId(long zoneId) {
this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + ""));
return this;
}
/**
* @param id
* the ID of the network offering
@ -165,6 +174,14 @@ public class ListNetworkOfferingsOptions extends BaseHttpRequestOptions {
return options.id(id);
}
/**
* @see ListNetworkOfferingsOptions#zoneId
*/
public static ListNetworkOfferingsOptions zoneId(long zoneId) {
ListNetworkOfferingsOptions options = new ListNetworkOfferingsOptions();
return options.zoneId(zoneId);
}
/**
* @see ListNetworkOfferingsOptions#trafficType
*/

View File

@ -21,6 +21,7 @@ package org.jclouds.cloudstack.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.cloudstack.domain.Account;
import org.jclouds.cloudstack.domain.Account.Type;
import org.jclouds.cloudstack.domain.User;
import com.google.common.base.Predicate;
@ -57,26 +58,44 @@ public class UserPredicates {
return new ApiKeyEquals(apiKey);
}
public static enum IsUserAccount implements Predicate<User> {
INSTANCE;
@Override
public boolean apply(User input) {
return checkNotNull(input, "user").getAccountType() == Account.Type.USER;
/**
*
* @return true, if the account has user privileges
*/
public static Predicate<User> isUserAccount() {
return accountTypeEquals(Account.Type.USER);
}
@Override
public String toString() {
return "isUserAccount()";
}
}
/**
*
* @return true, if the user's apiKey is the following
*/
public static Predicate<User> isUserAccount() {
return IsUserAccount.INSTANCE;
public static Predicate<User> accountTypeEquals(Account.Type type) {
return new AccountTypeEquals(type);
}
public static class AccountTypeEquals implements Predicate<User> {
public AccountTypeEquals(Type type) {
this.type = checkNotNull(type, "type");
}
private final Account.Type type;
@Override
public boolean apply(User input) {
return checkNotNull(input, "user").getAccountType() == type;
}
@Override
public String toString() {
return "accountTypeEquals(" + type + ")";
}
}
/**
*
* @return true, if the user's apiKey is the following
*/
public static Predicate<User> isAdminAccount() {
return accountTypeEquals(Account.Type.ADMIN);
}
}

View File

@ -20,8 +20,6 @@ package org.jclouds.cloudstack.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.alwaysTrue;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.not;
import org.jclouds.cloudstack.domain.NetworkType;
import org.jclouds.cloudstack.domain.Zone;
@ -71,14 +69,6 @@ public class ZonePredicates {
};
}
/**
*
* @return true, if the zone supports creation of GuestVirtual Networks
*/
public static Predicate<Zone> supportsGuestVirtualNetworks() {
return and(supportsAdvancedNetworks(), not(supportsSecurityGroups()));
}
/**
*
* @return always returns true.

View File

@ -18,38 +18,78 @@
*/
package org.jclouds.cloudstack.compute;
import org.jclouds.compute.BaseVersionedServiceLiveTest;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.sshj.config.SshjSshClientModule;
import org.testng.annotations.Test;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.cloudstack.options.CreateNetworkOptions.Builder.vlan;
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.specifyVLAN;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.features.BaseCloudStackClientLiveTest;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.predicates.NodePredicates;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "CloudStackExperimentLiveTest")
public class CloudStackExperimentLiveTest extends BaseVersionedServiceLiveTest {
public CloudStackExperimentLiveTest(){
public class CloudStackExperimentLiveTest extends BaseCloudStackClientLiveTest {
public CloudStackExperimentLiveTest() {
provider = "cloudstack";
}
@Test
public void testAndExperiment() {
ComputeServiceContext context = null;
if (!domainAdminEnabled) {
Logger.getAnonymousLogger().log(Level.SEVERE, "domainAdmin credentials not present, skipping test");
return;
}
String group = prefix + "-vlan";
Network network = null;
Set<? extends NodeMetadata> nodes = null;
try {
context = new ComputeServiceContextFactory().createContext("cloudstack",
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties());
assert computeContext.getComputeService().listAssignableLocations().size() > 0;
assert context.getComputeService().listAssignableLocations().size() > 0;
Template template = computeContext.getComputeService().templateBuilder().build();
// get the zone we are launching into
long zoneId = Long.parseLong(template.getLocation().getId());
// find a network offering that supports vlans in our zone
long offeringId = get(
context.getApi().getOfferingClient().listNetworkOfferings(specifyVLAN(true).zoneId(zoneId)), 0).getId();
// create an arbitrary network
network = domainAdminContext.getApi()
.getNetworkClient()
// startIP/endIP/netmask/gateway must be specified together
.createNetworkInZone(zoneId, offeringId, group, group,
vlan("2").startIP("192.168.1.2").netmask("255.255.255.0").gateway("192.168.1.1"));
// set options to specify this network id
template.getOptions().as(CloudStackTemplateOptions.class).networkId(network.getId());
// launch the VM
nodes = computeContext.getComputeService().createNodesInGroup(group, 1, template);
} catch (RunNodesException e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "error creating nodes", e);
nodes = newTreeSet(concat(e.getSuccessfulNodes(), e.getNodeErrors().keySet()));
} finally {
if (context != null)
context.close();
if (nodes != null)
computeContext.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
if (network != null)
domainAdminContext.getApi().getNetworkClient().deleteNetwork(network.getId());
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.cloudstack.features;
import static com.google.common.base.Strings.emptyToNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.get;
import static org.testng.Assert.assertEquals;
@ -70,10 +71,31 @@ import com.google.inject.Module;
* @author Adrian Cole
*/
public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected String domainAdminIdentity;
protected String domainAdminCredential;
public BaseCloudStackClientLiveTest() {
provider = "cloudstack";
}
@Override
protected void setupCredentials() {
super.setupCredentials();
domainAdminIdentity = emptyToNull(System.getProperty("test." + provider + ".domainAdminIdentity"));
domainAdminCredential = emptyToNull(System.getProperty("test." + provider + ".domainAdminCredential"));
}
protected Properties setupAdminProperties() {
if (domainAdminIdentity != null && domainAdminCredential != null) {
Properties overrides = setupProperties();
overrides.setProperty(provider + ".identity", domainAdminIdentity);
overrides.setProperty(provider + ".credential", domainAdminCredential);
return overrides;
} else {
return null;
}
}
public static long defaultTemplateOrPreferredInZone(Long defaultTemplate, CloudStackClient client, long zoneId) {
long templateId = defaultTemplate != null ? defaultTemplate : getTemplateForZone(client, zoneId);
return templateId;
@ -103,21 +125,27 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
protected String prefix = System.getProperty("user.name");
protected CloudStackClient client;
protected ComputeServiceContext computeContext;
protected RestContext<CloudStackClient, CloudStackAsyncClient> context;
protected CloudStackClient client;
protected User user;
protected Predicate<IPSocket> socketTester;
protected RetryablePredicate<Long> jobComplete;
protected RetryablePredicate<VirtualMachine> virtualMachineRunning;
protected RetryablePredicate<VirtualMachine> virtualMachineDestroyed;
protected SshClient.Factory sshFactory;
protected User currentUser;
protected String password = "password";
protected Injector injector;
protected ReuseOrAssociateNewPublicIPAddress reuseOrAssociate;
protected ComputeServiceContext computeContext;
protected boolean domainAdminEnabled;
protected ComputeServiceContext domainAdminComputeContext;
protected RestContext<CloudStackClient, CloudStackAsyncClient> domainAdminContext;
protected CloudStackClient domainAdminClient;
protected User domainAdminUser;
protected void checkSSH(IPSocket socket) {
socketTester.apply(socket);
@ -136,27 +164,22 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
@BeforeGroups(groups = "live")
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
computeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), overrides);
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupProperties());
context = computeContext.getProviderSpecificContext();
client = context.getApi();
// check access
Iterable<User> users = Iterables.concat(client.getAccountClient().listAccounts());
Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(identity);
try {
currentUser = Iterables.find(users, apiKeyMatches);
} catch (NoSuchElementException e) {
throw new NoSuchElementException(String.format("none of the following users match %s: %s", apiKeyMatches,
users));
}
user = verifyCurrentUserIsOfType(context, Account.Type.USER);
if (currentUser.getAccountType() != Account.Type.USER)
throw new IllegalArgumentException(String.format(
"invalid account type: %s, please specify an apiKey of a USER, for example: %s",
currentUser.getAccountType(), Iterables.filter(users, UserPredicates.isUserAccount())));
domainAdminEnabled = setupAdminProperties() != null;
if (domainAdminEnabled) {
domainAdminComputeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new SshjSshClientModule()), setupAdminProperties());
domainAdminContext = domainAdminComputeContext.getProviderSpecificContext();
domainAdminClient = domainAdminContext.getApi();
domainAdminUser = verifyCurrentUserIsOfType(domainAdminContext, Account.Type.DOMAIN_ADMIN);
}
injector = Guice.createInjector(new SshjSshClientModule(), new Log4JLoggingModule());
sshFactory = injector.getInstance(SshClient.Factory.class);
@ -174,6 +197,25 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
injector.injectMembers(reuseOrAssociate);
}
protected static User verifyCurrentUserIsOfType(RestContext<CloudStackClient, CloudStackAsyncClient> context,
Account.Type type) {
Iterable<User> users = Iterables.concat(context.getApi().getAccountClient().listAccounts());
Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(context.getIdentity());
User currentUser;
try {
currentUser = Iterables.find(users, apiKeyMatches);
} catch (NoSuchElementException e) {
throw new NoSuchElementException(String.format("none of the following users match %s: %s", apiKeyMatches,
users));
}
if (currentUser.getAccountType() != type)
throw new IllegalArgumentException(String.format(
"invalid account type: %s, please specify an apiKey of %s, for example: %s",
currentUser.getAccountType(), type, Iterables.filter(users, UserPredicates.accountTypeEquals(type))));
return currentUser;
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (context != null)

View File

@ -19,16 +19,20 @@
package org.jclouds.cloudstack.features;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.jclouds.cloudstack.options.CreateNetworkOptions.Builder.vlan;
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.specifyVLAN;
import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.accountInDomain;
import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.id;
import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.zoneId;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jclouds.cloudstack.domain.GuestIPType;
import org.jclouds.cloudstack.domain.Network;
@ -36,12 +40,9 @@ import org.jclouds.cloudstack.domain.NetworkOffering;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.predicates.NetworkOfferingPredicates;
import org.jclouds.cloudstack.predicates.ZonePredicates;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
/**
* Tests behavior of {@code NetworkClientLiveTest}
*
@ -51,58 +52,89 @@ import com.google.common.base.Predicate;
public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
private boolean networksSupported;
private Zone zone;
private NetworkOffering offering;
private Network network;
// only delete networks we create
private boolean weCreatedNetwork;
@BeforeGroups(groups = "live")
public void setupClient() {
super.setupClient();
try {
// you can create guest direct network by Admin user, but since we are
// not admin, let's try to create a guest virtual one
zone = find(client.getZoneClient().listZones(), ZonePredicates.supportsGuestVirtualNetworks());
offering = find(client.getOfferingClient().listNetworkOfferings(),
NetworkOfferingPredicates.supportsGuestVirtualNetworks());
zone = find(client.getZoneClient().listZones(), ZonePredicates.supportsAdvancedNetworks());
networksSupported = true;
} catch (NoSuchElementException e) {
}
}
public void testCreateNetwork() throws Exception {
public void testCreateGuestVirtualNetwork() {
if (!networksSupported)
return;
final NetworkOffering offering;
try {
network = client.getNetworkClient().createNetworkInZone(zone.getId(), offering.getId(), prefix, prefix);
weCreatedNetwork = true;
} catch (IllegalStateException e) {
network = find(
client.getNetworkClient().listNetworks(
zoneId(zone.getId()).accountInDomain(currentUser.getAccount(), currentUser.getDomainId())),
new Predicate<Network>() {
offering = find(client.getOfferingClient().listNetworkOfferings(),
NetworkOfferingPredicates.supportsGuestVirtualNetworks());
@Override
public boolean apply(Network arg0) {
return arg0.getNetworkOfferingId() == offering.getId();
} catch (NoSuchElementException e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "guest networks not supported, skipping test");
return;
}
String name = prefix + "-virtual";
});
}
Network network = null;
try {
network = client.getNetworkClient().createNetworkInZone(zone.getId(), offering.getId(), name, name);
checkNetwork(network);
} catch (IllegalStateException e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "couldn't create a network, skipping test", e);
} finally {
if (network != null) {
Long jobId = client.getNetworkClient().deleteNetwork(network.getId());
if (jobId != null)
jobComplete.apply(jobId);
}
}
}
public void testCreateVLANNetwork() {
if (!networksSupported)
return;
if (!domainAdminEnabled) {
Logger.getAnonymousLogger().log(Level.SEVERE, "domainAdmin credentials not present, skipping test");
return;
}
final NetworkOffering offering;
try {
offering = get(
context.getApi().getOfferingClient().listNetworkOfferings(specifyVLAN(true).zoneId(zone.getId())), 0);
} catch (NoSuchElementException e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "VLAN networks not supported, skipping test");
return;
}
String name = prefix + "-vlan";
Network network = null;
try {
network = domainAdminContext.getApi()
.getNetworkClient()
// startIP/endIP/netmask/gateway must be specified together
.createNetworkInZone(zone.getId(), offering.getId(), name, name,
vlan("2").startIP("192.168.1.2").netmask("255.255.255.0").gateway("192.168.1.1"));
checkNetwork(network);
} catch (IllegalStateException e) {
Logger.getAnonymousLogger().log(Level.SEVERE, "couldn't create a network, skipping test", e);
} finally {
if (network != null) {
Long jobId = client.getNetworkClient().deleteNetwork(network.getId());
if (jobId != null)
jobComplete.apply(jobId);
}
}
}
@Test(dependsOnMethods = "testCreateNetwork")
public void testListNetworks() throws Exception {
if (!networksSupported)
return;
Set<Network> response = client.getNetworkClient().listNetworks(
accountInDomain(network.getAccount(), network.getDomainId()));
accountInDomain(user.getAccount(), user.getDomainId()));
assert null != response;
long networkCount = response.size();
assertTrue(networkCount >= 0);
@ -144,7 +176,8 @@ public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
assert network.getEndIP() == null : network;
break;
case DIRECT:
assert network.getNetmask() != null : network;
// TODO: I've found a network that doesn't have a netmask associated
// assert network.getNetmask() != null : network;
assert network.getGateway() != null : network;
assert network.getVLAN() != null : network;
assertEquals(network.getBroadcastURI(), URI.create("vlan://" + network.getVLAN()));
@ -154,14 +187,4 @@ public class NetworkClientLiveTest extends BaseCloudStackClientLiveTest {
}
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (network != null && weCreatedNetwork) {
Long jobId = client.getNetworkClient().deleteNetwork(network.getId());
if (jobId != null)
jobComplete.apply(jobId);
}
super.tearDown();
}
}

View File

@ -25,6 +25,7 @@ import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.isShared;
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.specifyVLAN;
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.trafficType;
import static org.jclouds.cloudstack.options.ListNetworkOfferingsOptions.Builder.zoneId;
import static org.testng.Assert.assertEquals;
import org.jclouds.cloudstack.domain.TrafficType;
@ -70,6 +71,16 @@ public class ListNetworkOfferingsOptionsTest {
assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("id"));
}
public void testZoneId() {
ListNetworkOfferingsOptions options = new ListNetworkOfferingsOptions().zoneId(6);
assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
}
public void testZoneIdStatic() {
ListNetworkOfferingsOptions options = zoneId(6);
assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid"));
}
public void testSpecifyVLAN() {
ListNetworkOfferingsOptions options = new ListNetworkOfferingsOptions().specifyVLAN(true);
assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("specifyvlan"));

View File

@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import java.util.Properties;
import java.util.logging.Logger;
import org.jclouds.Constants;
import org.jclouds.rest.RestContextFactory;
@ -33,6 +32,7 @@ import org.testng.annotations.BeforeClass;
* @author Jason King
*/
public abstract class BaseVersionedServiceLiveTest {
protected String prefix = System.getProperty("user.name");
protected String provider;
protected String identity;