Issue 387: revised terremark to use the password in the vAppTemplate description to use as adminPassword during sudo

This commit is contained in:
Adrian Cole 2010-10-26 20:20:36 -07:00
parent b4ad8fed1f
commit faa57c71bb
8 changed files with 97 additions and 23 deletions

View File

@ -80,6 +80,14 @@ public class TerremarkVCloudExpressVAppToNodeMetadata extends VCloudExpressVAppT
if (credentialsMap.containsKey(orgAndName)) {
Credentials creds = credentialsMap.get(orgAndName);
node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(creds).build();
credentialStore.put(node.getId(), creds);
}
// this is going to need refactoring.. we really need a credential list in the store per
// node.
String adminPasswordKey = node.getId() + "/adminPassword";
if (credentialStore.containsKey(adminPasswordKey)) {
node = NodeMetadataBuilder.fromNodeMetadata(node).adminPassword(
credentialStore.get(adminPasswordKey).credential).build();
}
return node;
}

View File

@ -28,11 +28,14 @@ import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
import static org.jclouds.compute.predicates.NodePredicates.parentLocationId;
import static org.jclouds.compute.predicates.NodePredicates.withTag;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.vcloud.terremark.compute.domain.OrgAndName;
import com.google.common.base.Function;
@ -47,16 +50,24 @@ public class CleanupOrphanKeys {
final Function<NodeMetadata, OrgAndName> nodeToOrgAndName;
final DeleteKeyPair deleteKeyPair;
final ListNodesStrategy listNodes;
final Map<String, Credentials> credentialStore;
@Inject
CleanupOrphanKeys(Function<NodeMetadata, OrgAndName> nodeToOrgAndName, DeleteKeyPair deleteKeyPair,
ListNodesStrategy listNodes) {
Map<String, Credentials> credentialStore, ListNodesStrategy listNodes) {
this.nodeToOrgAndName = nodeToOrgAndName;
this.deleteKeyPair = deleteKeyPair;
this.listNodes = listNodes;
this.credentialStore = credentialStore;
}
public void execute(Iterable<? extends NodeMetadata> deadOnes) {
// TODO refactor so that admin passwords are cached properly, probably as a list value in the
// credentialStore
for (NodeMetadata node : deadOnes){
credentialStore.remove(node.getId());
credentialStore.remove(node.getId() + "/adminPassword");
}
Iterable<OrgAndName> orgTags = filter(transform(deadOnes, nodeToOrgAndName), notNull());
for (OrgAndName orgTag : orgTags) {
Iterable<? extends NodeMetadata> nodesInOrg = listNodes.listDetailsOnNodesMatching(parentLocationId(orgTag

View File

@ -22,13 +22,16 @@ package org.jclouds.vcloud.terremark.compute.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.vcloud.domain.VCloudExpressVApp;
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeClient;
import org.jclouds.vcloud.terremark.compute.functions.TemplateToInstantiateOptions;
@ -44,21 +47,35 @@ public class TerremarkVCloudAddNodeWithTagStrategy implements AddNodeWithTagStra
protected final TerremarkVCloudComputeClient computeClient;
protected final TemplateToInstantiateOptions getOptions;
protected final Function<VCloudExpressVApp, NodeMetadata> vAppToNodeMetadata;
private final Map<String, Credentials> credentialStore;
@Inject
protected TerremarkVCloudAddNodeWithTagStrategy(TerremarkVCloudComputeClient computeClient,
Function<VCloudExpressVApp, NodeMetadata> vAppToNodeMetadata, TemplateToInstantiateOptions getOptions) {
Function<VCloudExpressVApp, NodeMetadata> vAppToNodeMetadata, TemplateToInstantiateOptions getOptions,
Map<String, Credentials> credentialStore) {
this.computeClient = computeClient;
this.vAppToNodeMetadata = vAppToNodeMetadata;
this.getOptions = checkNotNull(getOptions, "getOptions");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
}
@Override
public NodeMetadata addNodeWithTag(String tag, String name, Template template) {
TerremarkInstantiateVAppTemplateOptions options = getOptions.apply(template);
VCloudExpressVApp vApp = computeClient.start(URI.create(template.getLocation().getId()),
URI.create(template.getImage().getId()), name, options, template.getOptions().getInboundPorts());
return vAppToNodeMetadata.apply(vApp);
VCloudExpressVApp vApp = computeClient.start(URI.create(template.getLocation().getId()), URI.create(template
.getImage().getId()), name, options, template.getOptions().getInboundPorts());
NodeMetadata node = vAppToNodeMetadata.apply(vApp);
NodeMetadataBuilder builder = NodeMetadataBuilder.fromNodeMetadata(node);
// TODO refactor this so that it is automatic in any provider
if (template.getImage().getAdminPassword() != null) {
builder.adminPassword(template.getImage().getAdminPassword());
// this is going to need refactoring.. we really need a credential list in the store per
// node. we need to store the credential here explicitly, as there's no connection from a node
// in vcloud to the image it was created with.
credentialStore.put(node.getId() + "/adminPassword", new Credentials("root", template.getImage()
.getAdminPassword()));
}
return builder.build();
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.vcloud.terremark.compute.suppliers;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Sets.newLinkedHashSet;
import java.util.Set;
@ -30,6 +32,7 @@ import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
@ -38,7 +41,6 @@ import org.jclouds.vcloud.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -70,7 +72,23 @@ public class VAppTemplatesInOrgs implements Supplier<Set<? extends Image>> {
@Override
public Set<? extends Image> get() {
logger.debug(">> providing vAppTemplates");
return newLinkedHashSet(Iterables.concat(Iterables.transform(organizatonsForLocations.apply(locations.get()),
imagesInOrg)));
return newLinkedHashSet(transform(
concat(transform(organizatonsForLocations.apply(locations.get()), imagesInOrg)),
new Function<Image, Image>() {
@Override
public Image apply(Image from) {
ImageBuilder builder = ImageBuilder.fromImage(from);
// the password in the image is the sudo password
// TODO refactor authenticate image logic so that it can populate the
// adminPassword
// value
// independently
if (from.getDefaultCredentials() != null)
builder.adminPassword(from.getDefaultCredentials().credential);
return builder.build();
}
}));
}
}

View File

@ -436,11 +436,9 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
endpoint = checkNotNull(System.getProperty("test." + provider + ".endpoint"), "test." + provider + ".endpoint");
apiversion = checkNotNull(System.getProperty("test." + provider + ".apiversion"), "test." + provider
+ ".apiversion");
credential = System.getProperty("test." + provider + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
protected Properties setupProperties() {
@ -448,8 +446,11 @@ public abstract class TerremarkClientLiveTest extends VCloudExpressClientLiveTes
overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true");
overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true");
overrides.setProperty(provider + ".identity", identity);
if (credential != null)
overrides.setProperty(provider + ".credential", credential);
if (endpoint != null)
overrides.setProperty(provider + ".endpoint", endpoint);
if (apiversion != null)
overrides.setProperty(provider + ".apiversion", apiversion);
return overrides;
}

View File

@ -33,6 +33,7 @@ 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.TerremarkVCloudExpressAsyncClient;
import org.jclouds.vcloud.terremark.TerremarkVCloudExpressClient;
import org.testng.annotations.Test;
@ -104,6 +105,10 @@ 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()
.createContext(provider, identity, credential).getProviderSpecificContext();
VCloudExpressVApp vApp = tmContext.getApi().findVAppInOrgVDCNamed(null, null, allData.getName());
assertEquals(vApp.getName(), allData.getName());
}
}

View File

@ -26,10 +26,12 @@ import static org.easymock.classextension.EasyMock.verify;
import static org.jclouds.compute.predicates.NodePredicates.parentLocationId;
import java.net.URI;
import java.util.Map;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.vcloud.terremark.compute.domain.OrgAndName;
import org.jclouds.vcloud.terremark.compute.functions.NodeMetadataToOrgAndName;
import org.testng.annotations.Test;
@ -67,6 +69,7 @@ public class CleanupOrphanKeysTest {
// setup expectations
expect(strategy.nodeToOrgAndName.apply(nodeMetadata)).andReturn(null).atLeastOnce();
expectCleanupCredentialStore(strategy, nodeMetadata);
// replay mocks
replay(nodeMetadata);
@ -93,6 +96,7 @@ public class CleanupOrphanKeysTest {
.andReturn(ImmutableSet.of(nodeMetadata));
expect(nodeMetadata.getTag()).andReturn(orgTag.getName()).atLeastOnce();
expect(nodeMetadata.getState()).andReturn(NodeState.RUNNING).atLeastOnce();
expectCleanupCredentialStore(strategy, nodeMetadata);
// replay mocks
replay(nodeMetadata);
@ -120,6 +124,7 @@ public class CleanupOrphanKeysTest {
expect(nodeMetadata.getTag()).andReturn(orgTag.getName()).atLeastOnce();
expect(nodeMetadata.getState()).andReturn(NodeState.TERMINATED).atLeastOnce();
strategy.deleteKeyPair.execute(orgTag);
expectCleanupCredentialStore(strategy, nodeMetadata);
// replay mocks
replay(nodeMetadata);
@ -133,6 +138,12 @@ public class CleanupOrphanKeysTest {
verifyStrategy(strategy);
}
private void expectCleanupCredentialStore(CleanupOrphanKeys strategy, NodeMetadata nodeMetadata) {
expect(nodeMetadata.getId()).andReturn("1").times(2);
expect(strategy.credentialStore.remove("1")).andReturn(null);
expect(strategy.credentialStore.remove("1/adminPassword")).andReturn(null);
}
public void testWhenNoneLeftWithTag() {
// create mocks
CleanupOrphanKeys strategy = setupStrategy();
@ -145,6 +156,7 @@ public class CleanupOrphanKeysTest {
expect((Object) strategy.listNodes.listDetailsOnNodesMatching(parentLocationId(orgTag.getOrg().toASCIIString())))
.andReturn(ImmutableSet.of());
strategy.deleteKeyPair.execute(orgTag);
expectCleanupCredentialStore(strategy, nodeMetadata);
// replay mocks
replay(nodeMetadata);
@ -162,20 +174,22 @@ public class CleanupOrphanKeysTest {
verify(strategy.nodeToOrgAndName);
verify(strategy.deleteKeyPair);
verify(strategy.listNodes);
verify(strategy.credentialStore);
}
private CleanupOrphanKeys setupStrategy() {
NodeMetadataToOrgAndName nodeToOrgAndName = createMock(NodeMetadataToOrgAndName.class);
DeleteKeyPair deleteKeyPair = createMock(DeleteKeyPair.class);
ListNodesStrategy listNodes = createMock(ListNodesStrategy.class);
return new CleanupOrphanKeys(nodeToOrgAndName, deleteKeyPair, listNodes);
Map<String, Credentials> credentialStore = createMock(Map.class);
return new CleanupOrphanKeys(nodeToOrgAndName, deleteKeyPair, credentialStore, listNodes);
}
private void replayStrategy(CleanupOrphanKeys strategy) {
replay(strategy.nodeToOrgAndName);
replay(strategy.deleteKeyPair);
replay(strategy.listNodes);
replay(strategy.credentialStore);
}
}