Issue 383: started to resolve eCloud compatibility problems

This commit is contained in:
Adrian Cole 2010-10-31 18:41:26 -07:00
parent 5385374ddb
commit 1eda57537b
20 changed files with 268 additions and 133 deletions

View File

@ -408,6 +408,45 @@ public abstract class BaseComputeServiceLiveTest {
testGet();
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testListNodes() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getProviderId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
public void testGetNodesWithDetails() throws Exception {
for (NodeMetadata node : client.listNodesDetailsMatching(all())) {
assert node.getProviderId() != null : node;
assert node.getLocation() != null : node;
assertEquals(node.getType(), ComputeType.NODE);
assert node instanceof NodeMetadata;
NodeMetadata nodeMetadata = (NodeMetadata) node;
assert nodeMetadata.getProviderId() != null : nodeMetadata;
// nullable
// assert nodeMetadata.getImage() != null : node;
// user specified name is not always supported
// assert nodeMetadata.getName() != null : nodeMetadata;
if (nodeMetadata.getState() == NodeState.RUNNING) {
assert nodeMetadata.getPublicAddresses() != null : nodeMetadata;
assert nodeMetadata.getPublicAddresses().size() > 0 || nodeMetadata.getPrivateAddresses().size() > 0 : nodeMetadata;
assertNotNull(nodeMetadata.getPrivateAddresses());
}
}
}
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
public void testDestroyNodes() {
client.destroyNodesMatching(withTag(tag));
for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node;
assertEquals(context.getCredentialStore().get("node#" + node.getId()), null);
}
}
private Set<? extends NodeMetadata> refreshNodes() {
return filter(client.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED)));
}
@ -445,34 +484,6 @@ public abstract class BaseComputeServiceLiveTest {
assert t.getOptions().isIncludeMetadata() : "The metadata option should be 'true' " + "for the created template";
}
public void testListNodes() throws Exception {
for (ComputeMetadata node : client.listNodes()) {
assert node.getProviderId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testGetNodesWithDetails() throws Exception {
for (NodeMetadata node : client.listNodesDetailsMatching(all())) {
assert node.getProviderId() != null : node;
assert node.getLocation() != null : node;
assertEquals(node.getType(), ComputeType.NODE);
assert node instanceof NodeMetadata;
NodeMetadata nodeMetadata = (NodeMetadata) node;
assert nodeMetadata.getProviderId() != null : nodeMetadata;
// nullable
// assert nodeMetadata.getImage() != null : node;
// user specified name is not always supported
// assert nodeMetadata.getName() != null : nodeMetadata;
if (nodeMetadata.getState() == NodeState.RUNNING) {
assert nodeMetadata.getPublicAddresses() != null : nodeMetadata;
assert nodeMetadata.getPublicAddresses().size() > 0 || nodeMetadata.getPrivateAddresses().size() > 0 : nodeMetadata;
assertNotNull(nodeMetadata.getPrivateAddresses());
}
}
}
public void testListImages() throws Exception {
for (Image image : client.listImages()) {
assert image.getProviderId() != null : image;
@ -606,11 +617,7 @@ public abstract class BaseComputeServiceLiveTest {
@AfterTest
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (nodes != null) {
client.destroyNodesMatching(withTag(tag));
for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), withTag(tag))) {
assert node.getState() == NodeState.TERMINATED : node;
assertEquals(context.getCredentialStore().get("node#" + node.getId()), null);
}
testDestroyNodes();
}
context.close();
}

View File

@ -371,6 +371,21 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testTemplateMatch();
}
@Override
public void testGetNodesWithDetails() throws Exception {
super.testGetNodesWithDetails();
}
@Override
public void testListNodes() throws Exception {
super.testListNodes();
}
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
@Override
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
super.cleanup();

View File

@ -22,6 +22,9 @@ package org.jclouds.vcloud.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.parseOsFamilyOrNull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import org.jclouds.compute.domain.Image;
@ -44,7 +47,7 @@ public class ImageForVCloudExpressVAppTemplate implements Function<VCloudExpress
@Inject
protected ImageForVCloudExpressVAppTemplate(FindLocationForResource findLocationForResource,
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider) {
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider) {
this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource");
this.credentialsProvider = checkNotNull(credentialsProvider, "credentialsProvider");
}
@ -67,11 +70,17 @@ public class ImageForVCloudExpressVAppTemplate implements Function<VCloudExpress
return builder.build();
}
public static final Pattern OS_PATTERN = Pattern.compile("(([^ ]*) ([0-9.]+) ?.*)");
protected OperatingSystem parseOs(VCloudExpressVAppTemplate from) {
OperatingSystemBuilder builder = new OperatingSystemBuilder();
builder.family(parseOsFamilyOrNull("vcloudexpress", checkNotNull(from, "vapp template").getName()));
builder.description(from.getName());
builder.is64Bit(from.getName().indexOf("64") != -1);
Matcher matcher = OS_PATTERN.matcher(from.getName());
if (matcher.find()) {
builder.version(matcher.group(3));
}
return builder.build();
}

View File

@ -174,7 +174,8 @@ public class CommonVCloudRestClientModule<S extends CommonVCloudClient, A extend
@Provides
@org.jclouds.vcloud.endpoints.VDC
@Singleton
protected String provideDefaultVDCName(@org.jclouds.vcloud.endpoints.VDC Supplier<Map<String, String>> vDCtoOrgSupplier) {
protected String provideDefaultVDCName(
@org.jclouds.vcloud.endpoints.VDC Supplier<Map<String, String>> vDCtoOrgSupplier) {
Map<String, String> vDCtoOrg = vDCtoOrgSupplier.get();
checkState(vDCtoOrg.keySet().size() > 0, "No vdcs present!");
return get(vDCtoOrg.keySet(), 0);
@ -408,12 +409,11 @@ public class CommonVCloudRestClientModule<S extends CommonVCloudClient, A extend
@Provides
@Network
@Singleton
protected URI provideDefaultNetwork(@org.jclouds.vcloud.endpoints.VDC URI defaultVDC, CommonVCloudClient client,
Injector injector) {
protected URI provideDefaultNetwork(@org.jclouds.vcloud.endpoints.VDC URI defaultVDC, Injector injector) {
if (authException.get() != null)
throw authException.get();
try {
org.jclouds.vcloud.domain.VDC vDC = client.getVDC(defaultVDC);
org.jclouds.vcloud.domain.VDC vDC = injector.getInstance(CommonVCloudClient.class).getVDC(defaultVDC);
Map<String, ReferenceType> networks = vDC.getAvailableNetworks();
checkState(networks.size() > 0, "No networks present in vDC: " + vDC.getName());
if (networks.size() == 1)
@ -425,18 +425,7 @@ public class CommonVCloudRestClientModule<S extends CommonVCloudClient, A extend
checkState(network != null, String.format("network named %s not in %s", networkName, networks.keySet()));
return network.getHref();
} catch (ConfigurationException e) {
// TODO FIXME XXX: In Terremark Enterprise environment with multiple VDC's this does not
// work well.
// Each VDC will have differnt network subnets. So we cannot assume the default VDC's
// networks will
// work with non-default VDC's. So make PROPERTY_VCLOUD_DEFAULT_NETWORK optional. If
// this property
// is not set, they are expected to add NetworkConfig to the options when launching a
// server.
return null;
// throw new
// IllegalStateException(String.format("you must specify the property %s as one of %s",
// PROPERTY_VCLOUD_DEFAULT_NETWORK, networks.keySet()), e);
return findDefaultNetworkForVDC(vDC, networks, injector);
}
} catch (AuthorizationException e) {
authException.set(e);
@ -444,6 +433,12 @@ public class CommonVCloudRestClientModule<S extends CommonVCloudClient, A extend
}
}
protected URI findDefaultNetworkForVDC(org.jclouds.vcloud.domain.VDC vDC, Map<String, ReferenceType> networks,
Injector injector) {
logger.warn("default network for vdc %s not set", vDC.getName());
return Iterables.getLast(networks.values()).getHref();
}
@Provides
@Singleton
protected Org provideOrg(CommonVCloudClient discovery) {

View File

@ -216,7 +216,6 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
checkFilters(request);
}
public void testCaptureVAppInVDC() throws SecurityException, NoSuchMethodException, IOException {
Method method = VCloudAsyncClient.class.getMethod("captureVAppInVDC", URI.class, URI.class, String.class,
CaptureVAppOptions[].class);
@ -242,8 +241,8 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
CaptureVAppOptions[].class);
HttpRequest request = processor.createRequest(method, URI
.create("https://vcenterprise.bluelock.com/api/v1.0/vdc/1"), URI
.create("https://vcenterprise.bluelock.com/api/v1.0/vapp/201"), "my-template",
new CaptureVAppOptions().withDescription("The description of the new vApp Template"));
.create("https://vcenterprise.bluelock.com/api/v1.0/vapp/201"), "my-template", new CaptureVAppOptions()
.withDescription("The description of the new vApp Template"));
assertRequestLineEquals(request,
"POST https://vcenterprise.bluelock.com/api/v1.0/vdc/1/action/captureVApp HTTP/1.1");
@ -258,8 +257,6 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
checkFilters(request);
}
public void testlistOrgs() throws SecurityException, NoSuchMethodException, IOException {
Method method = VCloudAsyncClient.class.getMethod("listOrgs");
HttpRequest request = processor.createRequest(method);
@ -857,12 +854,13 @@ public class VCloudAsyncClientTest extends RestClientTest<VCloudAsyncClient> {
}
@Override
protected String provideDefaultVDCName(@org.jclouds.vcloud.endpoints.VDC Supplier<Map<String, String>> vDCtoOrgSupplier) {
protected String provideDefaultVDCName(
@org.jclouds.vcloud.endpoints.VDC Supplier<Map<String, String>> vDCtoOrgSupplier) {
return "vdc";
}
@Override
protected URI provideDefaultNetwork(URI vdc, CommonVCloudClient client, Injector injector) {
protected URI provideDefaultNetwork(URI vdc, Injector injector) {
return URI.create("https://vcenterprise.bluelock.com/api/v1.0/network/1990");
}

View File

@ -694,7 +694,7 @@ public class VCloudExpressAsyncClientTest extends RestClientTest<VCloudExpressAs
}
@Override
protected URI provideDefaultNetwork(URI vdc, CommonVCloudClient client, Injector injector) {
protected URI provideDefaultNetwork(URI vdc, Injector injector) {
return URI.create("https://vcloud.safesecureweb.com/network/1990");
}

View File

@ -25,7 +25,7 @@ import java.util.Properties;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.logging.jdk.config.JDKLoggingModule;
import org.jclouds.vcloud.VCloudExpressContextBuilder;
import org.jclouds.vcloud.compute.config.VCloudExpressComputeServiceContextModule;
import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule;
import org.jclouds.vcloud.terremark.config.TerremarkECloudRestClientModule;
import com.google.inject.Injector;
@ -52,8 +52,7 @@ public class TerremarkECloudContextBuilder extends VCloudExpressContextBuilder {
@Override
protected void addContextModule(List<Module> modules) {
// TODO make ecloud version which retrieves passwords from the vapptemplate description
modules.add(new VCloudExpressComputeServiceContextModule());
modules.add(new TerremarkVCloudComputeServiceContextModule());
}
@Override

View File

@ -37,6 +37,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpResponseException;
import org.jclouds.vcloud.compute.internal.VCloudExpressComputeClientImpl;
import org.jclouds.vcloud.domain.Status;
import org.jclouds.vcloud.domain.Task;
@ -46,6 +47,7 @@ import org.jclouds.vcloud.domain.VCloudExpressVApp;
import org.jclouds.vcloud.domain.VCloudExpressVAppTemplate;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import org.jclouds.vcloud.terremark.TerremarkECloudClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressClient;
import org.jclouds.vcloud.terremark.domain.InternetService;
import org.jclouds.vcloud.terremark.domain.Node;
@ -63,16 +65,16 @@ import com.google.common.collect.Sets;
@Singleton
public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl {
protected final TerremarkVCloudExpressClient client;
protected final TerremarkVCloudClient client;
protected final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider;
protected final Provider<String> passwordGenerator;
protected final Map<String, Credentials> credentialStore;
@Inject
protected TerremarkVCloudComputeClient(TerremarkVCloudExpressClient client,
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
@Named("PASSWORD") Provider<String> passwordGenerator, Predicate<URI> successTester,
Map<Status, NodeState> vAppStatusToNodeState, Map<String, Credentials> credentialStore) {
protected TerremarkVCloudComputeClient(TerremarkVCloudClient client,
PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
@Named("PASSWORD") Provider<String> passwordGenerator, Predicate<URI> successTester,
Map<Status, NodeState> vAppStatusToNodeState, Map<String, Credentials> credentialStore) {
super(client, successTester, vAppStatusToNodeState);
this.client = client;
this.credentialsProvider = credentialsProvider;
@ -82,7 +84,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
@Override
public VCloudExpressVApp start(@Nullable URI VDC, URI templateId, String name,
InstantiateVAppTemplateOptions options, int... portsToOpen) {
InstantiateVAppTemplateOptions options, int... portsToOpen) {
if (options.getDiskSizeKilobytes() != null) {
logger.warn("trmk does not support resizing the primary disk; unsetting disk size");
}
@ -92,7 +94,7 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
String password = null;
VCloudExpressVAppTemplate template = client.getVAppTemplate(templateId);
if (template.getDescription().indexOf("Windows") != -1
&& options instanceof TerremarkInstantiateVAppTemplateOptions) {
&& options instanceof TerremarkInstantiateVAppTemplateOptions) {
password = passwordGenerator.get();
TerremarkInstantiateVAppTemplateOptions.class.cast(options).getProperties().put("password", password);
}
@ -100,8 +102,8 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
VCloudExpressVApp vAppResponse = super.start(VDC, templateId, name, options, portsToOpen);
if (password != null) {
credentialStore.put("node#" + vAppResponse.getHref().toASCIIString(), new Credentials(defaultCredentials.identity,
password));
credentialStore.put("node#" + vAppResponse.getHref().toASCIIString(), new Credentials(
defaultCredentials.identity, password));
}
if (portsToOpen.length > 0)
createPublicAddressMappedToPorts(vAppResponse.getHref(), portsToOpen);
@ -116,51 +118,67 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
InternetService is = null;
Protocol protocol;
switch (port) {
case 22:
protocol = Protocol.TCP;
break;
case 80:
case 8080:
protocol = Protocol.HTTP;
break;
case 443:
protocol = Protocol.HTTPS;
break;
default:
protocol = Protocol.HTTP;
break;
case 22:
protocol = Protocol.TCP;
break;
case 80:
case 8080:
protocol = Protocol.HTTP;
break;
case 443:
protocol = Protocol.HTTPS;
break;
default:
protocol = Protocol.HTTP;
break;
}
if (ip == null) {
if (client instanceof TerremarkVCloudExpressClient) {
is = TerremarkVCloudExpressClient.class.cast(client).addInternetServiceToVDC(
vApp.getVDC().getHref(),
vApp.getName() + "-" + port,
protocol,
port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
vApp.getVDC().getHref(),
vApp.getName() + "-" + port,
protocol,
port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
ip = is.getPublicIpAddress();
} else {
logger.debug(">> creating InternetService in vDC %s:%s:%d", vApp.getVDC().getName(), protocol, port);
ip = TerremarkECloudClient.class.cast(client).activatePublicIpInVDC(vApp.getVDC().getHref());
// http://support.theenterprisecloud.com/kb/default.asp?id=706&Lang=1&SID=
// response with a 500 error code means we should look for an existing public ip to
// use
try {
ip = TerremarkECloudClient.class.cast(client).activatePublicIpInVDC(vApp.getVDC().getHref());
} catch (HttpResponseException e) {
if (e.getResponse().getStatusCode() == 500) {
logger.warn(">> no more ip addresses available, looking for one to re-use");
for (PublicIpAddress existingIp : client.getPublicIpsAssociatedWithVDC(vApp.getVDC().getHref())) {
Set<InternetService> services = client.getInternetServicesOnPublicIp(existingIp.getId());
if (services.size() == 0) {
ip = existingIp;
break;
}
}
if (ip == null)
throw e;
} else {
throw e;
}
}
is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
}
} else {
logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress(), protocol, port);
is = client.addInternetServiceToExistingIp(
ip.getId(),
vApp.getName() + "-" + port,
protocol,
port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port, protocol, port,
withDescription(String.format("port %d access to serverId: %s name: %s", port, vApp.getName(),
vApp.getName())));
}
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(),
is.getProtocol(), is.getPort());
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getName(), is.getPublicIpAddress().getAddress(), is
.getProtocol(), is.getPort());
logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress(), is.getPort(),
privateAddress, port);
privateAddress, port);
Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port);
logger.debug("<< added Node(%s)", node.getName());
}
@ -174,13 +192,13 @@ public class TerremarkVCloudComputeClient extends VCloudExpressComputeClientImpl
if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
ipAddresses.add(service.getPublicIpAddress());
logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getName(), service.getPublicIpAddress()
.getAddress(), service.getPort(), node.getIpAddress(), node.getPort());
.getAddress(), service.getPort(), node.getIpAddress(), node.getPort());
client.deleteNode(node.getId());
logger.debug("<< deleted Node(%s)", node.getName());
Set<Node> nodes = client.getNodes(service.getId());
if (nodes.size() == 0) {
logger.debug(">> deleting InternetService(%s) %s:%d", service.getName(), service.getPublicIpAddress()
.getAddress(), service.getPort());
.getAddress(), service.getPort());
client.deleteInternetService(service.getId());
logger.debug("<< deleted InternetService(%s)", service.getName());
continue SERVICE;

View File

@ -32,7 +32,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.Logger;
import org.jclouds.util.Utils;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.compute.domain.OrgAndName;
import org.jclouds.vcloud.terremark.domain.KeyPair;
@ -48,11 +48,11 @@ public class CreateUniqueKeyPair implements Function<OrgAndName, KeyPair> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final TerremarkVCloudExpressClient trmkClient;
protected final TerremarkVCloudClient trmkClient;
protected Supplier<String> randomSuffix;
@Inject
CreateUniqueKeyPair(TerremarkVCloudExpressClient trmkClient, Supplier<String> randomSuffix) {
CreateUniqueKeyPair(TerremarkVCloudClient trmkClient, Supplier<String> randomSuffix) {
this.trmkClient = trmkClient;
this.randomSuffix = randomSuffix;
}

View File

@ -28,7 +28,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.compute.domain.KeyPairCredentials;
import org.jclouds.vcloud.terremark.compute.domain.OrgAndName;
import org.jclouds.vcloud.terremark.domain.KeyPair;
@ -44,12 +44,11 @@ public class DeleteKeyPair {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
final TerremarkVCloudExpressClient terremarkClient;
final TerremarkVCloudClient terremarkClient;
final ConcurrentMap<OrgAndName, KeyPairCredentials> credentialsMap;
@Inject
DeleteKeyPair(TerremarkVCloudExpressClient terremarkClient,
ConcurrentMap<OrgAndName, KeyPairCredentials> credentialsMap) {
DeleteKeyPair(TerremarkVCloudClient terremarkClient, ConcurrentMap<OrgAndName, KeyPairCredentials> credentialsMap) {
this.terremarkClient = terremarkClient;
this.credentialsMap = credentialsMap;
}

View File

@ -25,10 +25,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.domain.VCloudExpressVAppTemplate;
/**
@ -36,15 +40,20 @@ import org.jclouds.vcloud.domain.VCloudExpressVAppTemplate;
*/
@Singleton
public class ParseVAppTemplateDescriptionToGetDefaultLoginCredentials implements
PopulateDefaultLoginCredentialsForImageStrategy {
PopulateDefaultLoginCredentialsForImageStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
public static final Pattern USER_PASSWORD_PATTERN = Pattern
.compile(".*[Uu]sername: ([a-z]+) ?.*\n[Pp]assword: ([^ \n\r]+) ?\r?\n.*");
.compile(".*[Uu]sername: ([a-z]+) ?.*\n[Pp]assword: ([^ \n\r]+) ?\r?\n.*");
@Override
public Credentials execute(Object resourceToAuthenticate) {
checkNotNull(resourceToAuthenticate);
checkArgument(resourceToAuthenticate instanceof VCloudExpressVAppTemplate, "Resource must be an VAppTemplate (for Terremark)");
checkArgument(resourceToAuthenticate instanceof VCloudExpressVAppTemplate,
"Resource must be an VAppTemplate (for Terremark)");
VCloudExpressVAppTemplate template = (VCloudExpressVAppTemplate) resourceToAuthenticate;
String search = template.getDescription() != null ? template.getDescription() : template.getName();
if (search.indexOf("Windows") >= 0) {
@ -54,8 +63,9 @@ public class ParseVAppTemplateDescriptionToGetDefaultLoginCredentials implements
if (matcher.find()) {
return new Credentials(matcher.group(1), matcher.group(2));
} else {
throw new RuntimeException("could not parse username/password for image: " + template.getHref() + "\n"
+ search);
logger.warn("could not parse username/password for image: " + template.getHref() + "\n"
+ search);
return null;
}
}
}

View File

@ -19,17 +19,27 @@
package org.jclouds.vcloud.terremark.config;
import java.net.URI;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.inject.Singleton;
import org.jclouds.http.RequiresHttp;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.vcloud.VCloudExpressAsyncClient;
import org.jclouds.vcloud.VCloudExpressClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.network.OrgNetwork;
import org.jclouds.vcloud.terremark.TerremarkECloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkECloudClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Injector;
import com.google.inject.Provides;
/**
@ -70,4 +80,31 @@ public class TerremarkECloudRestClientModule extends
return in;
}
@Override
protected URI findDefaultNetworkForVDC(org.jclouds.vcloud.domain.VDC vDC, Map<String, ReferenceType> networks,
final Injector injector) {
// TODO FIXME XXX: In Terremark Enterprise environment with multiple VDC's this does not
// work well.
// Each VDC will have differnt network subnets. So we cannot assume the default VDC's
// networks will
// work with non-default VDC's. So make PROPERTY_VCLOUD_DEFAULT_NETWORK optional. If
// this property
// is not set, they are expected to add NetworkConfig to the options when launching a
// server.
logger.warn("default network for vdc %s not set", vDC.getName());
try {
return Iterables.find(networks.values(), new Predicate<ReferenceType>() {
@Override
public boolean apply(ReferenceType input) {
OrgNetwork network = injector.getInstance(TerremarkECloudClient.class).getNetwork(input.getHref());
// TODO: get extension data on this network and check NetworkType == DMZ
return network.getDescription() != null &&network.getDescription().toLowerCase().contains("dmz");
}
}).getHref();
} catch (NoSuchElementException e) {
throw new ResourceNotFoundException("no dmz networks in vdc " + vDC.getName() + ": " + networks);
}
}
}

View File

@ -54,10 +54,11 @@ public class ParseTerremarkVCloudErrorFromHttpResponse implements HttpErrorHandl
try {
String content = parseErrorFromContentOrNull(command, response);
if (response.getMessage() != null && ((response.getMessage().indexOf("because there is a pending task running") != -1)
|| (response.getMessage().indexOf("because it is already powered off") != -1)
|| (response.getMessage().indexOf("already exists") != -1)
|| (response.getMessage().indexOf("same name exists") != -1)))
if (response.getMessage() != null
&& ((response.getMessage().indexOf("because there is a pending task running") != -1)
|| (response.getMessage().indexOf("because it is already powered off") != -1)
|| (response.getMessage().indexOf("already exists") != -1) || (response.getMessage()
.indexOf("same name exists") != -1)))
exception = new IllegalStateException(response.getMessage(), exception);
else
switch (response.getStatusCode()) {
@ -80,8 +81,9 @@ public class ParseTerremarkVCloudErrorFromHttpResponse implements HttpErrorHandl
}
exception = new ResourceNotFoundException(message, exception);
break;
default:
exception = new HttpResponseException(command, response, content);
case 501:
if (response.getMessage() != null && (response.getMessage().indexOf("NotImplemented") != -1))
exception = new UnsupportedOperationException(response.getMessage(), exception);
}
} finally {
releasePayload(response);

View File

@ -51,8 +51,8 @@ import org.jclouds.util.Utils;
import org.jclouds.vcloud.CommonVCloudClient;
import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogItemSupplier;
import org.jclouds.vcloud.VCloudExpressAsyncClientTest.VCloudRestClientModuleExtension.TestOrgCatalogSupplier;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.VCloudSession;
import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl;
import org.jclouds.vcloud.domain.network.NetworkConfig;
@ -604,7 +604,7 @@ public class TerremarkECloudAsyncClientTest extends RestClientTest<TerremarkEClo
}
@Override
protected URI provideDefaultNetwork(URI vdc, CommonVCloudClient client, Injector injector) {
protected URI provideDefaultNetwork(URI vdc, Injector injector) {
return URI.create("https://vcloud.safesecureweb.com/network/1990");
}
}

View File

@ -745,7 +745,7 @@ public class TerremarkVCloudExpressAsyncClientTest extends RestClientTest<Terrem
}
@Override
protected URI provideDefaultNetwork(URI vdc, CommonVCloudClient client, Injector injector) {
protected URI provideDefaultNetwork(URI vdc, Injector injector) {
return URI.create("https://vcloud.safesecureweb.com/network/1990");
}
}

View File

@ -33,8 +33,10 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.vcloud.domain.VCloudExpressVApp;
import org.jclouds.vcloud.terremark.TerremarkECloudAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkECloudClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.testng.annotations.Test;
/**
@ -50,13 +52,14 @@ public class TerremarkECloudComputeServiceLiveTestDisabled extends BaseComputeSe
@Override
public void setServiceDefaults() {
tag = "trmke";
tag = "te";
}
@Test
public void testTemplateBuilder() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), false);
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "10.04");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
assert defaultTemplate.getLocation().getDescription() != null;// different per org
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
@ -90,7 +93,8 @@ public class TerremarkECloudComputeServiceLiveTestDisabled extends BaseComputeSe
assert image.getProviderId() != null : image;
// image.getLocationId() can be null, if it is a location-free image
assertEquals(image.getType(), ComputeType.IMAGE);
if (image.getOperatingSystem().getFamily() != OsFamily.WINDOWS) {
if (image.getOperatingSystem().getFamily() != OsFamily.WINDOWS
&& image.getOperatingSystem().getFamily() != OsFamily.SOLARIS) {
assert image.getDefaultCredentials() != null && image.getDefaultCredentials().identity != null : image;
assert image.getDefaultCredentials().credential != null : image;
}
@ -105,9 +109,18 @@ public class TerremarkECloudComputeServiceLiveTestDisabled extends BaseComputeSe
assertEquals(node.getType(), ComputeType.NODE);
NodeMetadata allData = client.getNodeMetadata(node.getId());
System.out.println(allData.getHardware());
RestContext<TerremarkVCloudClient, TerremarkVCloudClient> tmContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
VCloudExpressVApp vApp = tmContext.getApi().findVAppInOrgVDCNamed(null, null, allData.getName());
assertEquals(vApp.getName(), allData.getName());
}
}
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
@Override
protected JschSshClientModule getSshModule() {
return new JschSshClientModule();

View File

@ -34,6 +34,7 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.jclouds.vcloud.domain.VCloudExpressVApp;
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressClient;
import org.testng.annotations.Test;
@ -105,13 +106,18 @@ public class TerremarkVCloudExpressComputeServiceLiveTest extends BaseComputeSer
assertEquals(node.getType(), ComputeType.NODE);
NodeMetadata allData = client.getNodeMetadata(node.getId());
System.out.println(allData.getHardware());
RestContext<TerremarkVCloudExpressClient, TerremarkVCloudExpressAsyncClient> tmContext = new ComputeServiceContextFactory()
RestContext<TerremarkVCloudClient, TerremarkVCloudClient> tmContext = new ComputeServiceContextFactory()
.createContext(provider, identity, credential).getProviderSpecificContext();
VCloudExpressVApp vApp = tmContext.getApi().findVAppInOrgVDCNamed(null, null, allData.getName());
assertEquals(vApp.getName(), allData.getName());
}
}
@Override
public void testDestroyNodes() {
super.testDestroyNodes();
}
@Override
protected JschSshClientModule getSshModule() {
return new JschSshClientModule();

View File

@ -81,7 +81,21 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
assertEquals(creds.credential, "vpncubed");
verify(template);
}
@Test
public void testEC() throws IOException {
InputStream is = getClass().getResourceAsStream("/terremark/ec_description.txt");
String description = new String(ByteStreams.toByteArray(is));
VCloudExpressVAppTemplate template = createMock(VCloudExpressVAppTemplate.class);
expect(template.getDescription()).andReturn(description).atLeastOnce();
replay(template);
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials();
Credentials creds = converter.execute(template);
assertEquals(creds.identity, "ecloud");
assertEquals(creds.credential, "TmrkCl0ud1s#1!");
verify(template);
}
@Test
public void testWindows() throws IOException {
InputStream is = getClass().getResourceAsStream("/terremark/windows_description.txt");

View File

@ -71,6 +71,13 @@ public class ParseTerremarkVCloudErrorFromHttpResponseTest extends BaseHttpError
"", "", AuthorizationException.class);
}
@Test
public void test501SetsNotImplementedMakesUnsupportedOperationException() {
assertCodeMakes("POST", URI
.create("https://services.enterprisecloud.terremark.com/api/v0.8b-ext2.5/vapp/49373/action/undeploy"),
501, "HTTP/1.1 501 NotImplemented", "", UnsupportedOperationException.class);
}
@Test
public void testbecause_there_is_a_pending_task_runningSetsIllegalStateException() {
assertCodeMakes("GET", URI.create("https://services.vcloudexpress.terremark.com/api/v0.8a-ext1.6/vdc/32"), 500,

View File

@ -0,0 +1,6 @@
username: ecloud
password: TmrkCl0ud1s#1!
This template consists of a base Ubuntu Server 10.04 installation. Additional software is available via apt. Updates are available via Software Updater.
The hostname and base IP will be set as part of the server creation process based on user input.