bump jclouds version to 1.9.0
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/911ab593 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/911ab593 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/911ab593 Branch: refs/heads/master Commit: 911ab593d888b78210a32b0f78ed5be434ecbdc6 Parents: 77a7f6f Author: Andrea Turli <[email protected]> Authored: Mon Mar 30 19:03:22 2015 +0200 Committer: Andrea Turli <[email protected]> Committed: Mon Mar 30 19:03:22 2015 +0200 ---------------------------------------------------------------------- locations/jclouds/pom.xml | 13 +- .../location/jclouds/JcloudsLocation.java | 477 +++++++++---------- .../brooklyn/location/jclouds/JcloudsUtil.java | 76 +-- .../GoogleComputeEngineHttpApiModule.java | 171 ------- pom.xml | 12 +- 5 files changed, 283 insertions(+), 466 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/911ab593/locations/jclouds/pom.xml ---------------------------------------------------------------------- diff --git a/locations/jclouds/pom.xml b/locations/jclouds/pom.xml index b3f5625..2046ada 100644 --- a/locations/jclouds/pom.xml +++ b/locations/jclouds/pom.xml @@ -7,9 +7,9 @@ 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 @@ -33,7 +33,7 @@ <relativePath>../../pom.xml</relativePath> </parent> - <dependencies> + <dependencies> <dependency> <groupId>org.apache.brooklyn</groupId> <artifactId>brooklyn-core</artifactId> @@ -95,7 +95,7 @@ <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> - + <dependency> <groupId>${jclouds.groupId}.driver</groupId> <artifactId>jclouds-slf4j</artifactId> @@ -158,11 +158,6 @@ <artifactId>docker</artifactId> <version>${jclouds.version}</version> </dependency> - <dependency> - <groupId>${jclouds.groupId}.labs</groupId> - <artifactId>vcloud-director</artifactId> - <version>${jclouds.version}</version> - </dependency> <!-- these two seem needed here to prevent Eclipse IDE from getting wrong version of logback-core --> <dependency> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/911ab593/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java index 4fdbebe..d0c52d8 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java @@ -51,7 +51,6 @@ import java.util.regex.Pattern; import javax.annotation.Nullable; -import org.jclouds.abiquo.compute.options.AbiquoTemplateOptions; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.compute.ComputeService; import org.jclouds.compute.RunNodesException; @@ -88,10 +87,35 @@ import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Splitter; +import com.google.common.base.Stopwatch; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import com.google.common.io.Files; +import com.google.common.net.HostAndPort; +import com.google.common.primitives.Ints; +import com.google.common.reflect.TypeToken; + import brooklyn.config.ConfigKey; import brooklyn.config.ConfigKey.HasConfigKey; import brooklyn.config.ConfigUtils; -import brooklyn.entity.basic.Entities; import brooklyn.entity.basic.Sanitizer; import brooklyn.entity.rebind.persister.LocationWithObjectStore; import brooklyn.entity.rebind.persister.PersistenceObjectStore; @@ -111,7 +135,6 @@ import brooklyn.location.basic.SshMachineLocation; import brooklyn.location.cloud.AbstractCloudMachineProvisioningLocation; import brooklyn.location.cloud.AvailabilityZoneExtension; import brooklyn.location.cloud.CloudMachineNamer; -import brooklyn.location.jclouds.BrooklynImageChooser.ComputeServiceAwareChooser; import brooklyn.location.jclouds.JcloudsPredicates.NodeInLocation; import brooklyn.location.jclouds.networking.JcloudsPortForwarderExtension; import brooklyn.location.jclouds.templates.PortableTemplateBuilder; @@ -150,32 +173,6 @@ import brooklyn.util.text.TemplateProcessor; import brooklyn.util.time.Duration; import brooklyn.util.time.Time; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Charsets; -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Objects; -import com.google.common.base.Optional; -import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.base.Splitter; -import com.google.common.base.Stopwatch; -import com.google.common.base.Supplier; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.collect.Sets.SetView; -import com.google.common.io.Files; -import com.google.common.net.HostAndPort; -import com.google.common.primitives.Ints; -import com.google.common.reflect.TypeToken; - /** * For provisioning and managing VMs in a particular provider/region, using jclouds. * Configuration flags are defined in {@link JcloudsLocationConfig}. @@ -183,40 +180,40 @@ import com.google.common.reflect.TypeToken; @SuppressWarnings("serial") public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation implements JcloudsLocationConfig, RichMachineProvisioningLocation<SshMachineLocation>, LocationWithObjectStore { - // TODO After converting from Groovy to Java, this is now very bad code! It relies entirely on putting + // TODO After converting from Groovy to Java, this is now very bad code! It relies entirely on putting // things into and taking them out of maps; it's not type-safe, and it's thus very error-prone. - // In Groovy, that's considered ok but not in Java. + // In Groovy, that's considered ok but not in Java. // TODO test (and fix) ability to set config keys from flags // TODO we say config is inherited, but it isn't the case for many "deep" / jclouds properties // e.g. when we pass getRawLocalConfigBag() in and decorate it with additional flags // (inheritance only works when we call getConfig in this class) - + public static final Logger LOG = LoggerFactory.getLogger(JcloudsLocation.class); - + public static final String ROOT_USERNAME = "root"; - /** these userNames are known to be the preferred/required logins in some common/default images + /** these userNames are known to be the preferred/required logins in some common/default images * where root@ is not allowed to log in */ public static final List<String> ROOT_ALIASES = ImmutableList.of("ubuntu", "ec2-user"); public static final List<String> COMMON_USER_NAMES_TO_TRY = ImmutableList.<String>builder().add(ROOT_USERNAME).addAll(ROOT_ALIASES).add("admin").build(); - + private static final Pattern LIST_PATTERN = Pattern.compile("^\\[(.*)\\]$"); private static final Pattern INTEGER_PATTERN = Pattern.compile("^\\d*$"); - + private static boolean loggedSshKeysHint = false; - + private final Map<String,Map<String, ? extends Object>> tagMapping = Maps.newLinkedHashMap(); @SetFromFlag // so it's persisted private final Map<JcloudsSshMachineLocation,String> vmInstanceIds = Maps.newLinkedHashMap(); - + static { Networking.init(); } - + public JcloudsLocation() { super(); } - + /** typically wants at least ACCESS_IDENTITY and ACCESS_CREDENTIAL */ public JcloudsLocation(Map<?,?> conf) { super(conf); @@ -225,21 +222,21 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im @Override public JcloudsLocation configure(Map<?,?> properties) { super.configure(properties); - + if (config().getLocalBag().containsKey("providerLocationId")) { LOG.warn("Using deprecated 'providerLocationId' key in "+this); if (!config().getLocalBag().containsKey(CLOUD_REGION_ID)) config().addToLocalBag(MutableMap.of(CLOUD_REGION_ID.getName(), (String)config().getLocalBag().getStringKey("providerLocationId"))); } - + if (isDisplayNameAutoGenerated() || !groovyTruth(getDisplayName())) { setDisplayName(elvis(getProvider(), "unknown") + (groovyTruth(getRegion()) ? ":"+getRegion() : "") + (groovyTruth(getEndpoint()) ? ":"+getEndpoint() : "")); } - + setCreationString(config().getLocalBag()); - + if (getConfig(MACHINE_CREATION_SEMAPHORE) == null) { Integer maxConcurrent = getConfig(MAX_CONCURRENT_MACHINE_CREATIONS); if (maxConcurrent == null || maxConcurrent < 1) { @@ -249,7 +246,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } return this; } - + @Override public void init() { super.init(); @@ -257,7 +254,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im addExtension(AvailabilityZoneExtension.class, new AwsAvailabilityZoneExtension(getManagementContext(), this)); } } - + @Override public JcloudsLocation newSubLocation(Map<?,?> newFlags) { return newSubLocation(getClass(), newFlags); @@ -299,11 +296,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im public String getIdentity() { return getConfig(ACCESS_IDENTITY); } - + public String getCredential() { return getConfig(ACCESS_CREDENTIAL); } - + /** returns the location ID used by the provider, if set, e.g. us-west-1 */ public String getRegion() { return getConfig(CLOUD_REGION_ID); @@ -316,7 +313,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im public String getUser(ConfigBag config) { return (String) config.getWithDeprecation(USER, JCLOUDS_KEY_USERNAME); } - + protected Semaphore getMachineCreationSemaphore() { return checkNotNull(getConfig(MACHINE_CREATION_SEMAPHORE), MACHINE_CREATION_SEMAPHORE.getName()); } @@ -334,7 +331,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return new JcloudsMachineNamer(config); } } - + protected Collection<JcloudsLocationCustomizer> getCustomizers(ConfigBag setup) { @SuppressWarnings("deprecation") JcloudsLocationCustomizer customizer = setup.get(JCLOUDS_LOCATION_CUSTOMIZER); @@ -383,12 +380,12 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im // TODO remove tagMapping, or promote it // (i think i favour removing it, letting the config come in from the entity) - + public void setTagMapping(Map<String,Map<String, ? extends Object>> val) { tagMapping.clear(); tagMapping.putAll(val); } - + // TODO Decide on semantics. If I give "TomcatServer" and "Ubuntu", then must I get back an image that matches both? // Currently, just takes first match that it finds... public Map<String,Object> getProvisioningFlags(Collection<String> tags) { @@ -406,7 +403,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } return result; } - + public static final Set<ConfigKey<?>> getAllSupportedProperties() { Set<String> configsOnClass = Sets.newLinkedHashSet( Iterables.transform(ConfigUtils.getStaticKeysOnClass(JcloudsLocation.class), @@ -428,7 +425,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return input.getName(); } })); - + SetView<String> extrasInList = Sets.difference(configsInList, configsOnClass); // notInList is normal if (!extrasInList.isEmpty()) @@ -440,12 +437,12 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return getComputeService(MutableMap.of()); } public ComputeService getComputeService(Map<?,?> flags) { - ConfigBag conf = (flags==null || flags.isEmpty()) + ConfigBag conf = (flags==null || flags.isEmpty()) ? config().getBag() : ConfigBag.newInstanceExtending(config().getBag(), flags); return getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(conf, true); } - + /** @deprecated since 0.7.0 use {@link #listMachines()} */ @Deprecated public Set<? extends ComputeMetadata> listNodes() { return listNodes(MutableMap.of()); @@ -456,41 +453,41 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im public Set<? extends ComputeMetadata> listNodes(Map<?,?> flags) { return getComputeService(flags).listNodes(); } - + @Override public Map<String, MachineMetadata> listMachines() { - Set<? extends ComputeMetadata> nodes = + Set<? extends ComputeMetadata> nodes = getRegion()!=null ? getComputeService().listNodesDetailsMatching(new NodeInLocation(getRegion(), true)) : getComputeService().listNodes(); Map<String,MachineMetadata> result = new LinkedHashMap<String, MachineMetadata>(); - + for (ComputeMetadata node: nodes) result.put(node.getId(), getMachineMetadata(node)); - + return result; } protected MachineMetadata getMachineMetadata(ComputeMetadata node) { if (node==null) return null; - return new BasicMachineMetadata(node.getId(), node.getName(), + return new BasicMachineMetadata(node.getId(), node.getName(), ((node instanceof NodeMetadata) ? Iterators.tryFind( ((NodeMetadata)node).getPublicAddresses().iterator(), Predicates.alwaysTrue() ).orNull() : null), ((node instanceof NodeMetadata) ? ((NodeMetadata)node).getStatus()==Status.RUNNING : null), node); } - + public MachineMetadata getMachineMetadata(MachineLocation l) { if (l instanceof JcloudsSshMachineLocation) { return getMachineMetadata( ((JcloudsSshMachineLocation)l).node ); } return null; } - + @Override public void killMachine(String cloudServiceId) { getComputeService().destroyNode(cloudServiceId); } - + @Override public void killMachine(MachineLocation l) { MachineMetadata m = getMachineMetadata(l); @@ -498,7 +495,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im killMachine(m.getId()); } - /** attaches a string describing where something is being created + /** attaches a string describing where something is being created * (provider, region/location and/or endpoint, callerContext) */ protected void setCreationString(ConfigBag config) { config.setDescription(elvis(config.get(CLOUD_PROVIDER), "unknown")+ @@ -508,7 +505,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // ----------------- obtaining a new machine ------------------------ - + public JcloudsSshMachineLocation obtain() throws NoMachinesAvailableException { return obtain(MutableMap.of()); } @@ -539,11 +536,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } String msg = String.format("Failed to get VM after %d attempt%s.", attempts, attempts == 1 ? "" : "s"); - Exception cause = (exceptions.size() == 1) + Exception cause = (exceptions.size() == 1) ? exceptions.get(0) : new CompoundRuntimeException(msg + " - " + "First cause is "+exceptions.get(0)+" (listed in primary trace); " - + "plus " + (exceptions.size()-1) + " more (e.g. the last is "+exceptions.get(exceptions.size()-1)+")", + + "plus " + (exceptions.size()-1) + " more (e.g. the last is "+exceptions.get(exceptions.size()-1)+")", exceptions.get(0), exceptions); if (exceptions.get(exceptions.size()-1) instanceof NoMachinesAvailableException) { @@ -571,7 +568,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im String groupId = elvis(setup.get(GROUP_ID), cloudMachineNamer.generateNewGroupId()); NodeMetadata node = null; JcloudsSshMachineLocation sshMachineLocation = null; - + try { LOG.info("Creating VM "+setup.getDescription()+" in "+this); @@ -585,7 +582,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } else { LOG.debug("Acquired in {} machine-creation permit immediately", this); } - + Stopwatch provisioningStopwatch = Stopwatch.createStarted(); Duration templateTimestamp, provisionTimestamp, usableTimestamp, customizedTimestamp; @@ -606,20 +603,20 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } LOG.debug("jclouds using template {} / options {} to provision machine in {}", new Object[] {template, template.getOptions(), setup.getDescription()}); - + if (!setup.getUnusedConfig().isEmpty()) LOG.debug("NOTE: unused flags passed to obtain VM in "+setup.getDescription()+": "+ setup.getUnusedConfig()); - + templateTimestamp = Duration.of(provisioningStopwatch); template.getOptions().getUserMetadata().put("Name", cloudMachineNamer.generateNewMachineUniqueNameFromGroupId(groupId)); - + nodes = computeService.createNodesInGroup(groupId, 1, template); provisionTimestamp = Duration.of(provisioningStopwatch); } finally { machineCreationSemaphore.release(); } - + node = Iterables.getOnlyElement(nodes, null); LOG.debug("jclouds created {} for {}", node, setup.getDescription()); if (node == null) @@ -631,19 +628,19 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im sshHostAndPortOverride = Optional.of(portForwarder.openPortForwarding( node, node.getLoginPort(), - Optional.<Integer>absent(), - Protocol.TCP, + Optional.<Integer>absent(), + Protocol.TCP, Cidr.UNIVERSAL)); } else { sshHostAndPortOverride = Optional.absent(); } - + if (waitForSshable && skipJcloudsSshing) { // once that host:port is definitely reachable, we can create the user waitForReachable(computeService, node, sshHostAndPortOverride, node.getCredentials(), setup); userCredentials = createUser(computeService, node, sshHostAndPortOverride, setup); } - + // Figure out which login-credentials to use LoginCredentials customCredentials = setup.get(CUSTOM_CREDENTIALS); if (customCredentials != null) { @@ -666,7 +663,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im // store the credentials, in case they have changed setup.putIfNotNull(JcloudsLocationConfig.PASSWORD, userCredentials.getOptionalPassword().orNull()); setup.putIfNotNull(JcloudsLocationConfig.PRIVATE_KEY_DATA, userCredentials.getOptionalPrivateKey().orNull()); - + // Wait for the VM to be reachable over SSH if (waitForSshable) { waitForReachable(computeService, node, sshHostAndPortOverride, userCredentials, setup); @@ -674,7 +671,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.debug("Skipping ssh check for {} ({}) due to config waitForSshable=false", node, setup.getDescription()); } usableTimestamp = Duration.of(provisioningStopwatch); - + // Create a JcloudsSshMachineLocation, and register it sshMachineLocation = registerJcloudsSshMachineLocation(computeService, node, userCredentials, sshHostAndPortOverride, setup); if (template!=null && sshMachineLocation.getTemplate()==null) { @@ -710,11 +707,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im List<String> customisationForLogging = new ArrayList<String>(); // Apply same securityGroups rules to iptables, if iptables is running on the node if (waitForSshable) { - + String setupScript = setup.get(JcloudsLocationConfig.CUSTOM_MACHINE_SETUP_SCRIPT_URL); if (Strings.isNonBlank(setupScript)) { customisationForLogging.add("custom setup script "+setupScript); - + String setupVarsString = setup.get(JcloudsLocationConfig.CUSTOM_MACHINE_SETUP_SCRIPT_VARS); Map<String, String> substitutions = (setupVarsString != null) ? Splitter.on(",").withKeyValueSeparator(":").split(setupVarsString) @@ -723,19 +720,19 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im String script = TemplateProcessor.processTemplateContents(scriptContent, getManagementContext(), substitutions); sshMachineLocation.execCommands("Customizing node " + this, ImmutableList.of(script)); } - + if (setup.get(JcloudsLocationConfig.MAP_DEV_RANDOM_TO_DEV_URANDOM)) { customisationForLogging.add("point /dev/random to urandom"); - - sshMachineLocation.execCommands("using urandom instead of random", + + sshMachineLocation.execCommands("using urandom instead of random", Arrays.asList("sudo mv /dev/random /dev/random-real", "sudo ln -s /dev/urandom /dev/random")); } - + if (setup.get(GENERATE_HOSTNAME)) { customisationForLogging.add("configure hostname"); - - sshMachineLocation.execCommands("Generate hostname " + node.getName(), + + sshMachineLocation.execCommands("Generate hostname " + node.getName(), Arrays.asList("sudo hostname " + node.getName(), "sudo sed -i \"s/HOSTNAME=.*/HOSTNAME=" + node.getName() + "/g\" /etc/sysconfig/network", "sudo bash -c \"echo 127.0.0.1 `hostname` >> /etc/hosts\"") @@ -745,12 +742,12 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (setup.get(OPEN_IPTABLES)) { @SuppressWarnings("unchecked") Iterable<Integer> inboundPorts = (Iterable<Integer>) setup.get(INBOUND_PORTS); - + if (inboundPorts == null || Iterables.isEmpty(inboundPorts)) { LOG.info("No ports to open in iptables (no inbound ports) for {} at {}", sshMachineLocation, this); } else { customisationForLogging.add("open iptables"); - + List<String> iptablesRules = createIptablesRulesForNetworkInterface(inboundPorts); iptablesRules.add(IptablesCommands.saveIptablesRules()); List<String> batch = Lists.newArrayList(); @@ -769,36 +766,36 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im sshMachineLocation.execCommands("List iptables rules", ImmutableList.of(IptablesCommands.listIptablesRule())); } } - + if (setup.get(STOP_IPTABLES)) { customisationForLogging.add("stop iptables"); - + List<String> cmds = ImmutableList.of(IptablesCommands.iptablesServiceStop(), IptablesCommands.iptablesServiceStatus()); sshMachineLocation.execCommands("Stopping iptables", cmds); } - + List<String> extraKeyUrlsToAuth = setup.get(EXTRA_PUBLIC_KEY_URLS_TO_AUTH); if (extraKeyUrlsToAuth!=null && !extraKeyUrlsToAuth.isEmpty()) { List<String> extraKeyDataToAuth = MutableList.of(); for (String keyUrl: extraKeyUrlsToAuth) { extraKeyDataToAuth.add(ResourceUtils.create().getResourceAsString(keyUrl)); } - sshMachineLocation.execCommands("Authorizing ssh keys", + sshMachineLocation.execCommands("Authorizing ssh keys", ImmutableList.of(new AuthorizeRSAPublicKeys(extraKeyDataToAuth).render(org.jclouds.scriptbuilder.domain.OsFamily.UNIX))); } } else { - // Otherwise we have deliberately not waited to be ssh'able, so don't try now to + // Otherwise we have deliberately not waited to be ssh'able, so don't try now to // ssh to exec these commands! } - + // Apply any optional app-specific customization. for (JcloudsLocationCustomizer customizer : getCustomizers(setup)) { customizer.customize(this, computeService, sshMachineLocation); } - + customizedTimestamp = Duration.of(provisioningStopwatch); - + LOG.info("Finished VM "+setup.getDescription()+" creation:" + " "+sshMachineLocation.getUser()+"@"+sshMachineLocation.getAddress()+":"+sshMachineLocation.getPort() + (Boolean.TRUE.equals(setup.get(LOG_CREDENTIALS)) @@ -818,11 +815,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // sometimes AWS nodes come up busted (eg ssh not allowed); just throw it back (and maybe try for another one) boolean destroyNode = (node != null) && Boolean.TRUE.equals(setup.get(DESTROY_ON_FAILURE)); - - LOG.error("Failed to start VM for {}{}: {}", + + LOG.error("Failed to start VM for {}{}: {}", new Object[] {setup.getDescription(), (destroyNode ? " (destroying "+node+")" : ""), e.getMessage()}); LOG.debug(Throwables.getStackTraceAsString(e)); - + if (destroyNode) { if (sshMachineLocation != null) { releaseSafely(sshMachineLocation); @@ -830,22 +827,22 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im releaseNodeSafely(node); } } - + throw Exceptions.propagate(e); } } - + // ------------- constructing the template, etc ------------------------ - + private static interface CustomizeTemplateBuilder { void apply(TemplateBuilder tb, ConfigBag props, Object v); } - + public static interface CustomizeTemplateOptions { void apply(TemplateOptions tb, ConfigBag props, Object v); } - + /** properties which cause customization of the TemplateBuilder */ public static final Map<ConfigKey<?>,CustomizeTemplateBuilder> SUPPORTED_TEMPLATE_BUILDER_PROPERTIES = ImmutableMap.<ConfigKey<?>,CustomizeTemplateBuilder>builder() .put(OS_64_BIT, new CustomizeTemplateBuilder() { @@ -906,7 +903,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im /* done in the code, but included here so that it is in the map */ }}) .build(); - + /** properties which cause customization of the TemplateOptions */ public static final Map<ConfigKey<?>,CustomizeTemplateOptions> SUPPORTED_TEMPLATE_OPTIONS_PROPERTIES = ImmutableMap.<ConfigKey<?>,CustomizeTemplateOptions>builder() .put(SECURITY_GROUPS, new CustomizeTemplateOptions() { @@ -1008,7 +1005,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (v != null) { t.overrideLoginPrivateKey(((CharSequence)v).toString()); } - }}) + }}) .put(KEY_PAIR, new CustomizeTemplateOptions() { public void apply(TemplateOptions t, ConfigBag props, Object v) { if (t instanceof EC2TemplateOptions) { @@ -1038,7 +1035,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } else { LOG.info("ignoring auto-generate-floating-ips({}) in VM creation because not supported for cloud/type ({})", v, t); } - }}) + }}) .put(AUTO_ASSIGN_FLOATING_IP, new CustomizeTemplateOptions() { public void apply(TemplateOptions t, ConfigBag props, Object v) { if (t instanceof NovaTemplateOptions) { @@ -1048,14 +1045,6 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } else { LOG.info("ignoring auto-assign-floating-ip({}) in VM creation because not supported for cloud/type ({})", v, t); } - }}) - .put(OVERRIDE_RAM, new CustomizeTemplateOptions() { - public void apply(TemplateOptions t, ConfigBag props, Object v) { - if (t instanceof AbiquoTemplateOptions) { - ((AbiquoTemplateOptions)t).overrideRam((Integer)v); - } else { - LOG.info("ignoring overrideRam({}) in VM creation because not supported for cloud/type ({})", v, t); - } }}) .put(NETWORK_NAME, new CustomizeTemplateOptions() { public void apply(TemplateOptions t, ConfigBag props, Object v) { @@ -1128,7 +1117,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (!Strings.isEmpty(config.get(CLOUD_REGION_ID))) { templateBuilder.locationId(config.get(CLOUD_REGION_ID)); } - + // Apply the template builder and options properties for (Map.Entry<ConfigKey<?>, CustomizeTemplateBuilder> entry : SUPPORTED_TEMPLATE_BUILDER_PROPERTIES.entrySet()) { ConfigKey<?> name = entry.getKey(); @@ -1151,10 +1140,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im for (JcloudsLocationCustomizer customizer : getCustomizers(config)) { customizer.customize(this, computeService, templateBuilder); } - + LOG.debug("jclouds using templateBuilder {} for provisioning in {} for {}", new Object[] { templateBuilder, this, config.getDescription()}); - + // Finally try to build the template Template template; try { @@ -1183,7 +1172,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im + "see list of images in log. Root cause: "+e, e); } TemplateOptions options = template.getOptions(); - + for (Map.Entry<ConfigKey<?>, CustomizeTemplateOptions> entry : SUPPORTED_TEMPLATE_OPTIONS_PROPERTIES.entrySet()) { ConfigKey<?> key = entry.getKey(); CustomizeTemplateOptions code = entry.getValue(); @@ -1193,7 +1182,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return template; } - + protected void logAvailableTemplates(ConfigBag config) { LOG.info("Loading available images at "+this+" for reference..."); ConfigBag m1 = ConfigBag.newInstanceCopying(config); @@ -1209,7 +1198,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im for (Image img: imgs) { LOG.info(" Image: "+img); } - + Set<? extends Hardware> profiles = computeServiceLessRestrictive.listHardwareProfiles(); LOG.info(""+profiles.size()+" available profiles at "+this); for (Hardware profile: profiles) { @@ -1222,12 +1211,12 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.info(" Location: "+assignableLocation); } } - + protected SshMachineLocation createTemporarySshMachineLocation(HostAndPort hostAndPort, LoginCredentials creds, ConfigBag config) { Optional<String> initialPassword = creds.getOptionalPassword(); Optional<String> initialPrivateKey = creds.getOptionalPrivateKey(); String initialUser = creds.getUser(); - + Map<String,Object> sshProps = Maps.newLinkedHashMap(config.getAllConfig()); sshProps.put("user", initialUser); sshProps.put("address", hostAndPort.getHostText()); @@ -1235,7 +1224,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (initialPassword.isPresent()) sshProps.put("password", initialPassword.get()); if (initialPrivateKey.isPresent()) sshProps.put("privateKeyData", initialPrivateKey.get()); if (initialPrivateKey.isPresent()) sshProps.put("privateKeyData", initialPrivateKey.get()); - + if (isManaged()) { return getManagementContext().getLocationManager().createLocation(sshProps, SshMachineLocation.class); } else { @@ -1249,39 +1238,39 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected LoginCredentials createUser(ComputeService computeService, NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, ConfigBag config) { Image image = (node.getImageId() != null) ? computeService.getImage(node.getImageId()) : null; UserCreation userCreation = createUserStatements(image, config); - + if (!userCreation.statements.isEmpty()) { // If unsure of OS family, default to unix for rendering statements. org.jclouds.scriptbuilder.domain.OsFamily scriptOsFamily; if (node.getOperatingSystem() == null) { scriptOsFamily = org.jclouds.scriptbuilder.domain.OsFamily.UNIX; } else { - scriptOsFamily = (node.getOperatingSystem().getFamily() == org.jclouds.compute.domain.OsFamily.WINDOWS) + scriptOsFamily = (node.getOperatingSystem().getFamily() == org.jclouds.compute.domain.OsFamily.WINDOWS) ? org.jclouds.scriptbuilder.domain.OsFamily.WINDOWS : org.jclouds.scriptbuilder.domain.OsFamily.UNIX; } - + List<String> commands = Lists.newArrayList(); for (Statement statement : userCreation.statements) { InitAdminAccess initAdminAccess = new InitAdminAccess(new AdminAccessConfiguration.Default()); initAdminAccess.visit(statement); commands.add(statement.render(scriptOsFamily)); } - + LoginCredentials initialCredentials = node.getCredentials(); Optional<String> initialPassword = initialCredentials.getOptionalPassword(); Optional<String> initialPrivateKey = initialCredentials.getOptionalPrivateKey(); String initialUser = initialCredentials.getUser(); String address = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getHostText() : JcloudsUtil.getFirstReachableAddress(computeService.getContext(), node); int port = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getPort() : node.getLoginPort(); - + Map<String,Object> sshProps = Maps.newLinkedHashMap(config.getAllConfig()); sshProps.put("user", initialUser); sshProps.put("address", address); sshProps.put("port", port); if (initialPassword.isPresent()) sshProps.put("password", initialPassword.get()); if (initialPrivateKey.isPresent()) sshProps.put("privateKeyData", initialPrivateKey.get()); - + // TODO Retrying lots of times as workaround for vcloud-director. There the guest customizations // can cause the VM to reboot shortly after it was ssh'able. Map<String,Object> execProps = Maps.newLinkedHashMap(); @@ -1301,7 +1290,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } else { sshLoc = new SshMachineLocation(sshProps); } - + int exitcode = sshLoc.execScript(execProps, "create-user", commands); if (exitcode != 0) { LOG.warn("exit code {} when creating user for {}; usage may subsequently fail", exitcode, node); @@ -1314,13 +1303,13 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return userCreation.createdUserCredentials; } - + /** * Setup the TemplateOptions to create the user. */ protected LoginCredentials initTemplateForCreateUser(Template template, ConfigBag config) { UserCreation userCreation = createUserStatements(template.getImage(), config); - + if (userCreation.statements.size() > 0) { TemplateOptions options = template.getOptions(); options.runScript(new StatementList(userCreation.statements)); @@ -1328,38 +1317,38 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return userCreation.createdUserCredentials; } - + protected static class UserCreation { public final LoginCredentials createdUserCredentials; public final List<Statement> statements; - + public UserCreation(LoginCredentials creds, List<Statement> statements) { this.createdUserCredentials = creds; this.statements = statements; } } - + /** * Returns the commands required to create the user, to be used for connecting (e.g. over ssh) * to the machine; also returns the expected login credentials. * <p> - * The returned login credentials may be null if we haven't done any user-setup and no specific + * The returned login credentials may be null if we haven't done any user-setup and no specific * user was supplied (i.e. if {@code dontCreateUser} was true and {@code user} was null or blank). * In which case, the caller should use the jclouds node's login credentials. * <p> - * There are quite a few configuration options. Depending on their values, the user-creation + * There are quite a few configuration options. Depending on their values, the user-creation * behaves differently: * <ul> * <li>{@code dontCreateUser} says not to run any user-setup commands at all. If {@code user} is * non-empty (including with the default value), then that user will subsequently be used, * otherwise the (inferred) {@code loginUser} will be used. * <li>{@code loginUser} refers to the existing user that jclouds should use when setting up the VM. - * Normally this will be inferred from the image (i.e. doesn't need to be explicitly set), but sometimes + * Normally this will be inferred from the image (i.e. doesn't need to be explicitly set), but sometimes * the image gets it wrong so this can be a handy override. * <li>{@code user} is the username for brooklyn to subsequently use when ssh'ing to the machine. * If not explicitly set, its value will default to the username of the user running brooklyn. * <ul> - * <li>If the {@code user} value is null or empty, then the (inferred) {@code loginUser} will + * <li>If the {@code user} value is null or empty, then the (inferred) {@code loginUser} will * subsequently be used, setting up the password/authorizedKeys for that loginUser. * <li>If the {@code user} is "root", then setup the password/authorizedKeys for root. * <li>If the {@code user} equals the (inferred) {@code loginUser}, then don't try to create this @@ -1373,16 +1362,16 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im * Related is {@code publicKeyFile}, which is used to populate publicKeyData. * <li>{@code password} is the password to set for the user. If null or blank, then a random password * will be auto-generated and set. - * <li>{@code privateKeyData} is the key to use when subsequent ssh'ing, if not null or blank. + * <li>{@code privateKeyData} is the key to use when subsequent ssh'ing, if not null or blank. * Note the default is to use {@code ~/.ssh/id_rsa} or {@code ~/.ssh/id_dsa}. * The subsequent preferences for ssh'ing are: * <ul> * <li>Use the {@code privateKeyData} if not null or blank (including if using default) - * <li>Use the {@code password} (or the auto-generated password if that is blank). + * <li>Use the {@code password} (or the auto-generated password if that is blank). * </ul> * <li>{@code grantUserSudo} determines whether or not the created user may run the sudo command.</li> * </ul> - * + * * @param image The image being used to create the VM * @param config Configuration for creating the VM * @return The commands required to create the user, along with the expected login credentials for that user, @@ -1390,7 +1379,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im */ protected UserCreation createUserStatements(@Nullable Image image, ConfigBag config) { //NB: private key is not installed remotely, just used to get/validate the public key - + LoginCredentials createdUserCreds = null; String user = getUser(config); String explicitLoginUser = config.get(LOGIN_USER); @@ -1401,18 +1390,18 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im credential.checkNoErrors().logAnyWarnings(); String passwordToSet = Strings.isNonBlank(credential.getPassword()) ? credential.getPassword() : Identifiers.makeRandomId(12); List<Statement> statements = Lists.newArrayList(); - + if (dontCreateUser) { // dontCreateUser: // if caller has not specified a user, we'll just continue to use the loginUser; // if caller *has*, we set up our credentials assuming that user and credentials already exist - + if (Strings.isBlank(user)) { - // createdUserCreds returned from this method will be null; + // createdUserCreds returned from this method will be null; // we will use the creds returned by jclouds on the node LOG.info("Not setting up any user (subsequently using loginUser {})", user, loginUser); config.put(USER, loginUser); - + } else { LOG.info("Not creating user {}, and not installing its password or authorizing keys (assuming it exists)", user); @@ -1422,7 +1411,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im createdUserCreds = LoginCredentials.builder().user(user).privateKey(credential.getPrivateKeyData()).build(); } } - + } else if (Strings.isBlank(user) || user.equals(loginUser) || user.equals(ROOT_USERNAME)) { // For subsequent ssh'ing, we'll be using the loginUser if (Strings.isBlank(user)) { @@ -1431,28 +1420,28 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // Using the pre-existing loginUser; setup the publicKey/password so can login as expected - - // *Always* change the password (unless dontCreateUser was specified) + + // *Always* change the password (unless dontCreateUser was specified) statements.add(new ReplaceShadowPasswordEntry(Sha512Crypt.function(), user, passwordToSet)); createdUserCreds = LoginCredentials.builder().user(user).password(passwordToSet).build(); - + if (Strings.isNonBlank(credential.getPublicKeyData())) { statements.add(new AuthorizeRSAPublicKeys("~"+user+"/.ssh", ImmutableList.of(credential.getPublicKeyData()))); if (!credential.isUsingPassword() && Strings.isNonBlank(credential.getPrivateKeyData())) { createdUserCreds = LoginCredentials.builder().user(user).privateKey(credential.getPrivateKeyData()).build(); } } - + } else { String pubKey = credential.getPublicKeyData(); String privKey = credential.getPrivateKeyData(); - + if (credential.isEmpty()) { /* * TODO have an explicit `create_new_key_per_machine` config key. * error if privateKeyData is set in this case. * publicKeyData automatically added to EXTRA_SSH_KEY_URLS_TO_AUTH. - * + * * if this config key is not set, use a key `brooklyn_id_rsa` and `.pub` in `MGMT_BASE_DIR`, * with permission 0600, creating it if necessary, and logging the fact that this was created. */ @@ -1470,21 +1459,21 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // ensure credential is not used any more, as we have extracted all useful info credential = null; - + // Create the user // note AdminAccess requires _all_ fields set, due to http://code.google.com/p/jclouds/issues/detail?id=1095 AdminAccess.Builder adminBuilder = AdminAccess.builder() .adminUsername(user) .grantSudoToAdminUser(grantUserSudo); - + boolean useKey = Strings.isNonBlank(pubKey); - + // always set this password; if not supplied, it will be a random string adminBuilder.adminPassword(passwordToSet); // log the password also, in case we need it LOG.debug("Password '"+passwordToSet+"' being created for user '"+user+"' at the machine we are about to provision in "+this+"; "+ (useKey ? "however a key will be used to access it" : "this will be the only way to log in")); - + if (grantUserSudo && config.get(JcloudsLocationConfig.DISABLE_ROOT_AND_PASSWORD_SSH)) { // the default - set root password which we forget, because we have sudo acct // (and lock out root and passwords from ssh) @@ -1492,26 +1481,26 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im adminBuilder.loginPassword(Identifiers.makeRandomId(12)); } else { adminBuilder.resetLoginPassword(false); - adminBuilder.loginPassword(Identifiers.makeRandomId(12)+"-ignored"); + adminBuilder.loginPassword(Identifiers.makeRandomId(12)+"-ignored"); } - + if (useKey) { adminBuilder.authorizeAdminPublicKey(true).adminPublicKey(pubKey); } else { adminBuilder.authorizeAdminPublicKey(false).adminPublicKey(Identifiers.makeRandomId(12)+"-ignored"); } - + // jclouds wants us to give it the private key, otherwise it might refuse to authorize the public key // (in AdminAccess.build, if adminUsername != null && adminPassword != null); // we don't want to give it the private key, but we *do* want the public key authorized; // this code seems to trigger that. // (we build the creds below) adminBuilder.installAdminPrivateKey(false).adminPrivateKey(Identifiers.makeRandomId(12)+"-ignored"); - + // lock SSH means no root login and no passwordless login // if we're using a password or we don't have sudo, then don't do this! adminBuilder.lockSsh(useKey && grantUserSudo && !config.get(JcloudsLocationConfig.DISABLE_ROOT_AND_PASSWORD_SSH)); - + statements.add(adminBuilder.build()); if (useKey) { @@ -1520,7 +1509,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im createdUserCreds = LoginCredentials.builder().user(user).password(passwordToSet).build(); } } - + String customTemplateOptionsScript = config.get(CUSTOM_TEMPLATE_OPTIONS_SCRIPT_CONTENTS); if (Strings.isNonBlank(customTemplateOptionsScript)) { statements.add(new LiteralStatement(customTemplateOptionsScript)); @@ -1544,7 +1533,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im setHostnameUpdatingCredentials(setup, metadata); return rebindMachine(setup); } - + /** * Brings an existing machine with the given details under management. * <p> @@ -1558,20 +1547,20 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im public JcloudsSshMachineLocation rebindMachine(ConfigBag setup) throws NoMachinesAvailableException { try { if (setup.getDescription()==null) setCreationString(setup); - + final String rawId = (String) setup.getStringKey("id"); final String rawHostname = (String) setup.getStringKey("hostname"); String user = checkNotNull(getUser(setup), "user"); final String rawRegion = (String) setup.getStringKey("region"); - - LOG.info("Rebinding to VM {} ({}@{}), in jclouds location for provider {}", - new Object[] {rawId!=null ? rawId : "<lookup>", - user, - (rawHostname != null ? rawHostname : "<unspecified>"), + + LOG.info("Rebinding to VM {} ({}@{}), in jclouds location for provider {}", + new Object[] {rawId!=null ? rawId : "<lookup>", + user, + (rawHostname != null ? rawHostname : "<unspecified>"), getProvider()}); - + ComputeService computeService = getConfig(COMPUTE_SERVICE_REGISTRY).findComputeService(setup, true); - + Set<? extends NodeMetadata> candidateNodes = computeService.listNodesDetailsMatching(new Predicate<ComputeMetadata>() { @Override public boolean apply(ComputeMetadata input) { @@ -1585,18 +1574,18 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (!(input instanceof NodeMetadata)) return false; if (rawHostname!=null && rawHostname.equalsIgnoreCase( ((NodeMetadata)input).getHostname() )) return true; if (rawHostname!=null && ((NodeMetadata)input).getPublicAddresses().contains(rawHostname)) return true; - + if (rawId!=null && rawId.equalsIgnoreCase( ((NodeMetadata)input).getHostname() )) return true; if (rawId!=null && ((NodeMetadata)input).getPublicAddresses().contains(rawId)) return true; // don't do private IP's because those might be repeated - + if (rawId!=null && rawId.equalsIgnoreCase( ((NodeMetadata)input).getProviderId() )) return true; if (rawHostname!=null && rawHostname.equalsIgnoreCase( ((NodeMetadata)input).getProviderId() )) return true; - + return false; } }); - + if (candidateNodes.isEmpty()) throw new IllegalArgumentException("Jclouds node not found for rebind, looking for id="+rawId+" and hostname="+rawHostname); if (candidateNodes.size()>1) @@ -1609,12 +1598,12 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im //override credentials node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(expectedCredentials).build(); } - + // TODO confirm we can SSH ? // NB if rawHostname not set, get the hostname using getPublicHostname(node, Optional.<HostAndPort>absent(), setup); return registerJcloudsSshMachineLocation(computeService, node, null, Optional.<HostAndPort>absent(), setup); - + } catch (IOException e) { throw Exceptions.propagate(e); } @@ -1626,20 +1615,20 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // -------------- create the SshMachineLocation instance, and connect to it etc ------------------------ - + /** @deprecated since 0.7.0 use {@link #registerJcloudsSshMachineLocation(ComputeService, NodeMetadata, LoginCredentials, Optional, ConfigBag)} */ @Deprecated protected final JcloudsSshMachineLocation registerJcloudsSshMachineLocation(NodeMetadata node, String vmHostname, Optional<HostAndPort> sshHostAndPort, ConfigBag setup) throws IOException { LOG.warn("Using deprecated registerJcloudsSshMachineLocation: now wants computeService passed", new Throwable("source of deprecated registerJcloudsSshMachineLocation invocation")); return registerJcloudsSshMachineLocation(null, node, null, sshHostAndPort, setup); } - + protected JcloudsSshMachineLocation registerJcloudsSshMachineLocation(ComputeService computeService, NodeMetadata node, LoginCredentials initialCredentials, Optional<HostAndPort> sshHostAndPort, ConfigBag setup) throws IOException { if (initialCredentials==null) initialCredentials = node.getCredentials(); - + String vmHostname = getPublicHostname(node, sshHostAndPort, setup); - + JcloudsSshMachineLocation machine = createJcloudsSshMachineLocation(computeService, node, vmHostname, sshHostAndPort, setup); machine.setParent(this); vmInstanceIds.put(machine, node.getId()); @@ -1667,7 +1656,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im // fine, it resolves } catch (Exception e) { // occurs if an unresolvable hostname is given as vmHostname, and the machine only has private IP addresses but they are reachable - // TODO cleanup use of getPublicHostname so its semantics are clearer, returning reachable hostname or ip, and + // TODO cleanup use of getPublicHostname so its semantics are clearer, returning reachable hostname or ip, and // do this check/fix there instead of here! Exceptions.propagateIfFatal(e); LOG.debug("Could not resolve reported address '"+address+"' for "+vmHostname+" ("+setup.getDescription()+"/"+node+"), requesting reachable address"); @@ -1675,18 +1664,18 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im // this has sometimes already been done in waitForReachable (unless skipped) but easy enough to do again address = JcloudsUtil.getFirstReachableAddress(computeService.getContext(), node); } - + if (LOG.isDebugEnabled()) - LOG.debug("creating JcloudsSshMachineLocation representation for {}@{} ({}/{}) for {}/{}", + LOG.debug("creating JcloudsSshMachineLocation representation for {}@{} ({}/{}) for {}/{}", new Object[] { - getUser(setup), - address, + getUser(setup), + address, Sanitizer.sanitize(sshConfig), sshHostAndPort, - setup.getDescription(), + setup.getDescription(), node }); - + if (isManaged()) { return getManagementContext().getLocationManager().createLocation(LocationSpec.create(JcloudsSshMachineLocation.class) .configure("displayName", vmHostname) @@ -1711,8 +1700,8 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.warn("Using deprecated JcloudsSshMachineLocation constructor because "+this+" is not managed"); return new JcloudsSshMachineLocation(MutableMap.builder() .put("displayName", vmHostname) - .put("address", address) - .put("port", sshHostAndPort.isPresent() ? sshHostAndPort.get().getPort() : node.getLoginPort()) + .put("address", address) + .put("port", sshHostAndPort.isPresent() ? sshHostAndPort.get().getPort() : node.getLoginPort()) .put("user", getUser(setup)) // don't think "config" does anything .putAll(sshConfig) @@ -1731,7 +1720,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } // -------------- give back the machines------------------ - + protected Map<String,Object> extractSshConfig(ConfigBag setup, NodeMetadata node) { ConfigBag nodeConfig = new ConfigBag(); if (node!=null && node.getCredentials() != null) { @@ -1755,7 +1744,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected String extractNodeLocationId(ConfigBag setup, NodeMetadata node, LocationScope scope) { org.jclouds.domain.Location nodeLoc = node.getLocation(); - if(nodeLoc == null) return null; + if(nodeLoc == null) return null; do { if (nodeLoc.getScope() == scope) return nodeLoc.getId(); nodeLoc = nodeLoc.getParent(); @@ -1771,9 +1760,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.info("Attempted release of unknown machine "+machine+" in "+toString()); throw new IllegalArgumentException("Unknown machine "+machine); } - + LOG.info("Releasing machine {} in {}, instance id {}", new Object[] {machine, this, instanceId}); - + Exception tothrow = null; try { releasePortForwarding(machine); @@ -1809,7 +1798,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected void releaseNodeSafely(NodeMetadata node) { String instanceId = node.getId(); LOG.info("Releasing node {} in {}, instance id {}", new Object[] {node, this, instanceId}); - + try { releaseNode(instanceId); } catch (Exception e) { @@ -1840,7 +1829,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected void releasePortForwarding(SshMachineLocation machine) { // TODO Implementation needs revisisted. It relies on deprecated PortForwardManager methods. - + boolean usePortForwarding = Boolean.TRUE.equals(machine.getConfig(USE_PORT_FORWARDING)); JcloudsPortForwarderExtension portForwarder = machine.getConfig(PORT_FORWARDER); PortForwardManager portForwardManager = machine.getConfig(PORT_FORWARDING_MANAGER); @@ -1849,7 +1838,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im if (portForwarder == null) { LOG.debug("No port-forwarding to close (because portForwarder null) on release of " + machine); } else { - // Release the port-forwarding for the login-port, which was explicilty created by JcloudsLocation + // Release the port-forwarding for the login-port, which was explicilty created by JcloudsLocation if (usePortForwarding && node != null) { HostAndPort sshHostAndPortOverride = machine.getSshHostAndPort(); LOG.debug("Closing port-forwarding at {} for machine {}: {}->{}", new Object[] {this, machine, sshHostAndPortOverride, node.getLoginPort()}); @@ -1867,7 +1856,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } else { mappings = ImmutableSet.of(); } - + for (PortMapping mapping : mappings) { HostAndPort publicEndpoint = mapping.getPublicEndpoint(); int targetPort = mapping.getPrivatePort(); @@ -1878,7 +1867,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } } } - + // Forget all port mappings associated with this VM if (portForwardManager != null) { portForwardManager.forgetPortMappings(machine); @@ -1898,9 +1887,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im OsCredential localCredentials = LocationConfigUtils.getOsCredential(setup).checkNoErrors(); LoginCredentials nodeCredentials = LoginCredentials.fromCredentials(node.getCredentials()); - LOG.debug("Credentials extracted for {}: {}/{} with {}/{}", new Object[] { node, + LOG.debug("Credentials extracted for {}: {}/{} with {}/{}", new Object[] { node, user, nodeCredentials.getUser(), localCredentials, nodeCredentials }); - + if (Strings.isNonBlank(nodeCredentials.getUser())) { if (Strings.isBlank(user)) { setup.put(USER, user = nodeCredentials.getUser()); @@ -1909,7 +1898,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im LOG.warn("overriding username 'root' in favour of '"+nodeCredentials.getUser()+"' at {}; this behaviour may be removed in future", node); setup.put(USER, user = nodeCredentials.getUser()); } - + String pkd = Strings.maybeNonBlank(localCredentials.getPrivateKeyData()).or(nodeCredentials.getOptionalPrivateKey().orNull()); String pwd = Strings.maybeNonBlank(localCredentials.getPassword()).or(nodeCredentials.getOptionalPassword().orNull()); if (Strings.isBlank(user) || (Strings.isBlank(pkd) && pwd==null)) { @@ -1918,14 +1907,14 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return null; } else { LoginCredentials.Builder resultBuilder = LoginCredentials.builder().user(user); - if (pwd!=null && (Strings.isBlank(pkd) || localCredentials.isUsingPassword())) + if (pwd!=null && (Strings.isBlank(pkd) || localCredentials.isUsingPassword())) resultBuilder.password(pwd); - else // pkd guaranteed non-blank due to above + else // pkd guaranteed non-blank due to above resultBuilder.privateKey(pkd); - return resultBuilder.build(); + return resultBuilder.build(); } } - + LOG.warn("No node-credentials or admin-access available for node "+node+" in "+this+"; will likely fail subsequently"); return null; } @@ -1933,21 +1922,21 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected void waitForReachable(final ComputeService computeService, final NodeMetadata node, Optional<HostAndPort> hostAndPortOverride, final LoginCredentials expectedCredentials, ConfigBag setup) { String waitForSshable = setup.get(WAIT_FOR_SSHABLE); checkArgument(!"false".equalsIgnoreCase(waitForSshable), "waitForReachable called despite waitForSshable=%s", waitForSshable); - + String vmIp = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getHostText() : JcloudsUtil.getFirstReachableAddress(computeService.getContext(), node); if (vmIp==null) LOG.warn("Unable to extract IP for "+node+" ("+setup.getDescription()+"): subsequent connection attempt will likely fail"); - + int vmPort = hostAndPortOverride.isPresent() ? hostAndPortOverride.get().getPortOrDefault(22) : 22; - + long delayMs = -1; try { delayMs = Time.parseTimeString(""+waitForSshable); } catch (Exception e) { // normal if 'true'; just fall back to default } - if (delayMs<0) + if (delayMs<0) delayMs = Time.parseTimeString(WAIT_FOR_SSHABLE.getDefaultValue()); - + String user = expectedCredentials.getUser(); if (LOG.isDebugEnabled()) { Optional<String> password; @@ -1959,7 +1948,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im password = expectedCredentials.getOptionalPassword().isPresent() ? Optional.of("******") : Optional.<String>absent(); key = expectedCredentials.getOptionalPrivateKey().isPresent() ? Optional.of("******") : Optional.<String>absent(); } - LOG.debug("VM {}: reported online, now waiting {} for it to be sshable on {}@{}:{}{}; using credentials password={}; key={}", + LOG.debug("VM {}: reported online, now waiting {} for it to be sshable on {}@{}:{}{}; using credentials password={}; key={}", new Object[] { setup.getDescription(), Time.makeTimeStringRounded(delayMs), user, vmIp, vmPort, @@ -1968,7 +1957,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im key.or("<absent>") }); } - + Callable<Boolean> checker; if (hostAndPortOverride.isPresent()) { final SshMachineLocation machine = createTemporarySshMachineLocation(hostAndPortOverride.get(), expectedCredentials, setup); @@ -1981,14 +1970,14 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im checker = new Callable<Boolean>() { public Boolean call() { Statement statement = Statements.newStatementList(exec("hostname")); - ExecResponse response = computeService.runScriptOnNode(node.getId(), statement, + ExecResponse response = computeService.runScriptOnNode(node.getId(), statement, overrideLoginCredentials(expectedCredentials).runAsRoot(false)); return response.getExitStatus() == 0; }}; } - + Stopwatch stopwatch = Stopwatch.createStarted(); - + ReferenceWithError<Boolean> reachable = new Repeater() .every(1,SECONDS) .until(checker) @@ -2000,7 +1989,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im user+"@"+vmIp+" ("+setup.getDescription()+") after waiting "+ Time.makeTimeStringRounded(delayMs), reachable.getError()); } - + LOG.debug("VM {}: is sshable after {} on {}@{}",new Object[] { setup.getDescription(), Time.makeTimeStringRounded(stopwatch), user, vmIp}); @@ -2011,13 +2000,13 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected void setHostnameUpdatingCredentials(ConfigBag setup, NodeMetadata metadata) { List<String> usersTried = new ArrayList<String>(); - + String originalUser = getUser(setup); if (groovyTruth(originalUser)) { if (setHostname(setup, metadata, false)) return; usersTried.add(originalUser); } - + LoginCredentials credentials = metadata.getCredentials(); if (credentials!=null) { if (Strings.isNonBlank(credentials.getUser())) setup.put(USER, credentials.getUser()); @@ -2030,7 +2019,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } usersTried.add(getUser(setup)); } - + for (String u: COMMON_USER_NAMES_TO_TRY) { setup.put(USER, u); if (setHostname(setup, metadata, false)) { @@ -2044,7 +2033,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im setup.put(USER, originalUser); setHostname(setup, metadata, true); } - + protected boolean setHostname(ConfigBag setup, NodeMetadata metadata, boolean rethrow) { try { setup.put(SshTool.PROP_HOST, getPublicHostname(metadata, Optional.<HostAndPort>absent(), setup)); @@ -2052,7 +2041,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } catch (Exception e) { if (rethrow) { LOG.warn("couldn't connect to "+metadata+" when trying to discover hostname (rethrowing): "+e); - throw Exceptions.propagate(e); + throw Exceptions.propagate(e); } return false; } @@ -2060,13 +2049,13 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im /** * Attempts to obtain the hostname or IP of the node, as advertised by the cloud provider. - * Prefers public, reachable IPs. + * Prefers public, reachable IPs. * For some clouds (e.g. aws-ec2), it will attempt to find the public hostname. */ protected String getPublicHostname(NodeMetadata node, Optional<HostAndPort> sshHostAndPort, ConfigBag setup) { String provider = (setup != null) ? setup.get(CLOUD_PROVIDER) : null; if (provider == null) provider= getProvider(); - + if ("aws-ec2".equals(provider)) { HostAndPort inferredHostAndPort = null; if (!sshHostAndPort.isPresent()) { @@ -2089,10 +2078,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } } } - + return getPublicHostnameGeneric(node, setup); } - + private String getPublicHostnameGeneric(NodeMetadata node, @Nullable ConfigBag setup) { //prefer the public address to the hostname because hostname is sometimes wrong/abbreviated //(see that javadoc; also e.g. on rackspace, the hostname lacks the domain) @@ -2106,17 +2095,17 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im return null; } } - + private String getPublicHostnameAws(HostAndPort sshHostAndPort, ConfigBag setup) { SshMachineLocation sshLocByIp = null; try { ConfigBag sshConfig = extractSshConfig(setup, new ConfigBag()); - + // TODO messy way to get an SSH session if (isManaged()) { sshLocByIp = getManagementContext().getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class) - .configure("address", sshHostAndPort.getHostText()) - .configure("port", sshHostAndPort.getPort()) + .configure("address", sshHostAndPort.getHostText()) + .configure("port", sshHostAndPort.getPort()) .configure("user", getUser(setup)) .configure(sshConfig.getAllConfig())); } else { @@ -2128,7 +2117,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im .build(); sshLocByIp = new SshMachineLocation(locationProps); } - + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); ByteArrayOutputStream errStream = new ByteArrayOutputStream(); int exitcode = sshLocByIp.execCommands( @@ -2147,9 +2136,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im Streams.closeQuietly(sshLocByIp); } } - + // ------------ static converters (could go to a new file) ------------------ - + public static File asFile(Object o) { if (o instanceof File) return (File)o; if (o == null) return null; @@ -2221,7 +2210,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im protected static String[] toStringArray(Object v) { return toListOfStrings(v).toArray(new String[0]); } - + protected static List<String> toListOfStrings(Object v) { List<String> result = Lists.newArrayList(); if (v instanceof Iterable) { @@ -2239,7 +2228,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } return result; } - + protected static byte[] toByteArray(Object v) { if (v instanceof byte[]) { return (byte[]) v; @@ -2249,7 +2238,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im throw new IllegalArgumentException("Invalid type for byte[]: "+v+" of type "+v.getClass()); } } - + // Handles GString protected static Map<String,String> toMapStringString(Object v) { if (v instanceof Map<?,?>) { @@ -2267,7 +2256,7 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im (v != null ? " of type "+v.getClass() : "")); } } - + private List<String> createIptablesRulesForNetworkInterface(Iterable<Integer> ports) { List<String> iptablesRules = Lists.newArrayList(); for (Integer port : ports) { @@ -2275,10 +2264,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im } return iptablesRules; } - + @Override public PersistenceObjectStore newPersistenceObjectStore(String container) { return new JcloudsBlobStoreBasedObjectStore(this, container); } - + } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/911ab593/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java ---------------------------------------------------------------------- diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java index b910e9f..90c6035 100644 --- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java +++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsUtil.java @@ -65,16 +65,6 @@ import org.jclouds.util.Predicates2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import brooklyn.entity.basic.Sanitizer; -import brooklyn.util.collections.MutableList; -import brooklyn.util.config.ConfigBag; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.net.Protocol; -import brooklyn.util.ssh.BashCommands; -import brooklyn.util.ssh.IptablesCommands; -import brooklyn.util.ssh.IptablesCommands.Chain; -import brooklyn.util.ssh.IptablesCommands.Policy; - import com.google.common.annotations.Beta; import com.google.common.base.Charsets; import com.google.common.base.Function; @@ -88,12 +78,22 @@ import com.google.common.collect.Maps; import com.google.common.io.Files; import com.google.inject.Module; +import brooklyn.entity.basic.Sanitizer; +import brooklyn.util.collections.MutableList; +import brooklyn.util.config.ConfigBag; +import brooklyn.util.exceptions.Exceptions; +import brooklyn.util.net.Protocol; +import brooklyn.util.ssh.BashCommands; +import brooklyn.util.ssh.IptablesCommands; +import brooklyn.util.ssh.IptablesCommands.Chain; +import brooklyn.util.ssh.IptablesCommands.Policy; + public class JcloudsUtil implements JcloudsLocationConfig { - + // TODO Review what utility methods are needed, and what is now supported in jclouds 1.1 - + private static final Logger LOG = LoggerFactory.getLogger(JcloudsUtil.class); - + /** * @deprecated since 0.7; see {@link BashCommands} */ @@ -150,15 +150,15 @@ public class JcloudsUtil implements JcloudsLocationConfig { /** * @throws RunScriptOnNodesException * @throws IllegalStateException If do not find exactly one matching node - * + * * @deprecated since 0.7 */ @Deprecated public static ExecResponse runScriptOnNode(ComputeService computeService, NodeMetadata node, Statement statement, String scriptName) throws RunScriptOnNodesException { // TODO Includes workaround for NodeMetadata's equals/hashcode method being wrong. - + Map<? extends NodeMetadata, ExecResponse> scriptResults = computeService.runScriptOnNodesMatching( - JcloudsUtil.predicateMatchingById(node), + JcloudsUtil.predicateMatchingById(node), statement, new RunScriptOptions().nameTask(scriptName)); if (scriptResults.isEmpty()) { @@ -169,7 +169,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { return Iterables.getOnlyElement(scriptResults.values()); } } - + /** * @deprecated since 0.7; {@see #installJavaAndCurl(OperatingSystem)} */ @@ -231,7 +231,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { public static ComputeService findComputeService(ConfigBag conf) { return ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, true); } - + /** * @deprecated since 0.7; see {@link ComputeServiceRegistry#findComputeService(ConfigBag, boolean)} */ @@ -240,28 +240,28 @@ public class JcloudsUtil implements JcloudsLocationConfig { return ComputeServiceRegistryImpl.INSTANCE.findComputeService(conf, allowReuse); } - /** + /** * Returns the jclouds modules we typically install - * + * * @deprecated since 0.7; see {@link ComputeServiceRegistry} */ @Deprecated public static ImmutableSet<Module> getCommonModules() { return ImmutableSet.<Module> of( - new SshjSshClientModule(), + new SshjSshClientModule(), new SLF4JLoggingModule(), new BouncyCastleCryptoModule()); } - - /** + + /** * Temporary constructor to address https://issues.apache.org/jira/browse/JCLOUDS-615. * <p> * See https://issues.apache.org/jira/browse/BROOKLYN-6 . * When https://issues.apache.org/jira/browse/JCLOUDS-615 is fixed in the jclouds we use, - * we can remove the useSoftlayerFix argument. + * we can remove the useSoftlayerFix argument. * <p> * (Marked Beta as that argument will likely be removed.) - * + * * @since 0.7.0 */ @Beta public static BlobStoreContext newBlobstoreContext(String provider, @Nullable String endpoint, String identity, String credential) { @@ -309,7 +309,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { String publicKey = Files.toString(publicKeyFile, Charsets.UTF_8); return addAuthorizedKeysToRoot(publicKey); } - + /** * @deprecated since 0.7 */ @@ -321,7 +321,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { } public static String getFirstReachableAddress(ComputeServiceContext context, NodeMetadata node) { - // To pick the address, it relies on jclouds `sshForNode().apply(Node)` to check all IPs of node (private+public), + // To pick the address, it relies on jclouds `sshForNode().apply(Node)` to check all IPs of node (private+public), // to find one that is reachable. It does `openSocketFinder.findOpenSocketOnNode(node, node.getLoginPort(), ...)`. // This keeps trying for time org.jclouds.compute.reference.ComputeServiceConstants.Timeouts.portOpen. // TODO Want to configure this timeout here. @@ -342,7 +342,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { Exceptions.propagateIfFatal(e); /* i've seen: java.lang.IllegalStateException: Optional.get() cannot be called on an absent value * from org.jclouds.crypto.ASN1Codec.createASN1Sequence(ASN1Codec.java:86), if the ssh key has a passphrase, against AWS. - * + * * others have reported: java.lang.IllegalArgumentException: DER length more than 4 bytes * when using a key with a passphrase (perhaps from other clouds?); not sure if that's this callpath or a different one. */ @@ -350,14 +350,14 @@ public class JcloudsUtil implements JcloudsLocationConfig { } return client.getHostAddress(); } - + // Suggest at least 15 minutes for timeout public static String waitForPasswordOnAws(ComputeService computeService, final NodeMetadata node, long timeout, TimeUnit timeUnit) throws TimeoutException { ComputeServiceContext computeServiceContext = computeService.getContext(); AWSEC2Api ec2Client = computeServiceContext.unwrapApi(AWSEC2Api.class); final WindowsApi client = ec2Client.getWindowsApi().get(); final String region = node.getLocation().getParent().getId(); - + // The Administrator password will take some time before it is ready - Amazon says sometimes 15 minutes. // So we create a predicate that tests if the password is ready, and wrap it in a retryable predicate. Predicate<String> passwordReady = new Predicate<String>() { @@ -368,7 +368,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { return !Strings.isNullOrEmpty(data.getPasswordData()); } }; - + LOG.info("Waiting for password, for "+node.getProviderId()+":"+node.getId()); Predicate<String> passwordReadyRetryable = Predicates2.retry(passwordReady, timeUnit.toMillis(timeout), 10*1000, TimeUnit.MILLISECONDS); boolean ready = passwordReadyRetryable.apply(node.getProviderId()); @@ -389,17 +389,21 @@ public class JcloudsUtil implements JcloudsLocationConfig { public static Map<Integer, Integer> dockerPortMappingsFor(JcloudsLocation docker, String containerId) { ComputeServiceContext context = null; try { + Properties properties = new Properties(); + properties.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, Boolean.toString(true)); + properties.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, Boolean.toString(true)); context = ContextBuilder.newBuilder("docker") .endpoint(docker.getEndpoint()) - .credentials("docker", "docker") + .credentials(docker.getIdentity(), docker.getCredential()) + .overrides(properties) .modules(ImmutableSet.<Module>of(new SLF4JLoggingModule(), new SshjSshClientModule())) .build(ComputeServiceContext.class); DockerApi api = context.unwrapApi(DockerApi.class); - Container container = api.getRemoteApi().inspectContainer(containerId); + Container container = api.getContainerApi().inspectContainer(containerId); Map<Integer, Integer> portMappings = Maps.newLinkedHashMap(); - Map<String, List<Map<String, String>>> ports = container.getNetworkSettings().getPorts(); + Map<String, List<Map<String, String>>> ports = container.networkSettings().ports(); if (ports == null) ports = ImmutableMap.<String, List<Map<String,String>>>of(); - + LOG.debug("Docker will forward these ports {}", ports); for (Map.Entry<String, List<Map<String, String>>> entrySet : ports.entrySet()) { String containerPort = Iterables.get(Splitter.on("/").split(entrySet.getKey()), 0); @@ -427,7 +431,7 @@ public class JcloudsUtil implements JcloudsLocationConfig { public static void mapSecurityGroupRuleToIpTables(ComputeService computeService, NodeMetadata node, LoginCredentials credentials, String networkInterface, Iterable<Integer> ports) { for (Integer port : ports) { - String insertIptableRule = IptablesCommands.insertIptablesRule(Chain.INPUT, networkInterface, + String insertIptableRule = IptablesCommands.insertIptablesRule(Chain.INPUT, networkInterface, Protocol.TCP, port, Policy.ACCEPT); Statement statement = Statements.newStatementList(exec(insertIptableRule)); ExecResponse response = computeService.runScriptOnNode(node.getId(), statement,
