http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java new file mode 100644 index 0000000..8d5a10c --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java @@ -0,0 +1,342 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.extensions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT; +import static org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet.DEFAULT_INTERNAL_NETWORK_RANGE; +import static org.jclouds.googlecomputeengine.predicates.NetworkFirewallPredicates.equalsIpPermission; +import static org.jclouds.googlecomputeengine.predicates.NetworkFirewallPredicates.providesIpPermission; +import static org.jclouds.util.Predicates2.retry; + +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.compute.domain.SecurityGroup; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Location; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Firewall; +import org.jclouds.googlecomputeengine.domain.Instance; +import org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface; +import org.jclouds.googlecomputeengine.domain.Network; +import org.jclouds.googlecomputeengine.domain.Operation; +import org.jclouds.googlecomputeengine.domain.SlashEncodedIds; +import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange; +import org.jclouds.googlecomputeengine.options.FirewallOptions; +import org.jclouds.googlecomputeengine.options.ListOptions; +import org.jclouds.googlecomputeengine.options.ListOptions.Builder; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.net.domain.IpProtocol; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import com.google.common.util.concurrent.Atomics; + +/** + * An extension to compute service to allow for the manipulation of {@link org.jclouds.compute.domain.SecurityGroup}s. Implementation + * is optional by providers. + */ +public class GoogleComputeEngineSecurityGroupExtension implements SecurityGroupExtension { + + protected final Supplier<String> userProject; + protected final GroupNamingConvention.Factory namingConvention; + protected final LoadingCache<NetworkAndAddressRange, Network> networkCreator; + protected final Function<Network, SecurityGroup> groupConverter; + protected final GoogleComputeEngineApi api; + protected final Predicate<AtomicReference<Operation>> operationDonePredicate; + protected final long operationCompleteCheckInterval; + protected final long operationCompleteCheckTimeout; + + @Inject + public GoogleComputeEngineSecurityGroupExtension(GoogleComputeEngineApi api, + @UserProject Supplier<String> userProject, + GroupNamingConvention.Factory namingConvention, + LoadingCache<NetworkAndAddressRange, Network> networkCreator, + Function<Network, SecurityGroup> groupConverter, + @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate, + @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval, + @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) { + this.api = checkNotNull(api, "api"); + this.userProject = checkNotNull(userProject, "userProject"); + this.namingConvention = checkNotNull(namingConvention, "namingConvention"); + this.networkCreator = checkNotNull(networkCreator, "networkCreator"); + this.groupConverter = checkNotNull(groupConverter, "groupConverter"); + this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval, + "operation completed check interval"); + this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout, + "operation completed check timeout"); + this.operationDonePredicate = checkNotNull(operationDonePredicate, "operationDonePredicate"); + } + + @Override + public Set<SecurityGroup> listSecurityGroups() { + return api.getNetworkApiForProject(userProject.get()).list().concat().transform(groupConverter).toSet(); + } + + @Override + public Set<SecurityGroup> listSecurityGroupsInLocation(final Location location) { + return listSecurityGroups(); + } + + @Override + public Set<SecurityGroup> listSecurityGroupsForNode(String id) { + SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(id); + + Instance instance = api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(), + slashEncodedIds.getSecondId()); + + if (instance == null) { + return ImmutableSet.of(); + } + + ImmutableSet.Builder builder = ImmutableSet.builder(); + + + for (NetworkInterface nwInterface : instance.getNetworkInterfaces()) { + String networkUrl = nwInterface.getNetwork().getPath(); + Network nw = api.getNetworkApiForProject(userProject.get()).get(networkUrl.substring(networkUrl.lastIndexOf('/') + 1)); + + SecurityGroup grp = groupForTagsInNetwork(nw, instance.getTags().getItems()); + if (grp != null) { + builder.add(grp); + } + } + + return builder.build(); + } + + @Override + public SecurityGroup getSecurityGroupById(String id) { + checkNotNull(id, "id"); + Network network = api.getNetworkApiForProject(userProject.get()).get(id); + + if (network == null) { + return null; + } + + return groupConverter.apply(network); + } + + @Override + public SecurityGroup createSecurityGroup(String name, Location location) { + return createSecurityGroup(name); + } + + public SecurityGroup createSecurityGroup(String name) { + checkNotNull(name, "name"); + + NetworkAndAddressRange nAr = new NetworkAndAddressRange(name, DEFAULT_INTERNAL_NETWORK_RANGE, null); + + Network nw = networkCreator.apply(nAr); + + return groupConverter.apply(nw); + } + + @Override + public boolean removeSecurityGroup(String id) { + checkNotNull(id, "id"); + if (api.getNetworkApiForProject(userProject.get()).get(id) == null) { + return false; + } + + ListOptions options = new ListOptions.Builder().filter("network eq .*/" + id); + + FluentIterable<Firewall> fws = api.getFirewallApiForProject(userProject.get()).list(options).concat(); + + for (Firewall fw : fws) { + AtomicReference<Operation> operation = Atomics.newReference(api.getFirewallApiForProject(userProject.get()) + .delete(fw.getName())); + + retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval, + MILLISECONDS).apply(operation); + + checkState(!operation.get().getHttpError().isPresent(), "Could not delete firewall, operation failed" + operation); + } + + AtomicReference<Operation> operation = Atomics.newReference( + api.getNetworkApiForProject(userProject.get()).delete(id)); + + retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval, + MILLISECONDS).apply(operation); + + checkState(!operation.get().getHttpError().isPresent(), "Could not create network, operation failed" + operation); + + return true; + } + + @Override + public SecurityGroup addIpPermission(IpPermission ipPermission, SecurityGroup group) { + checkNotNull(group, "group"); + checkNotNull(ipPermission, "ipPermission"); + + checkNotNull(api.getNetworkApiForProject(userProject.get()).get(group.getId()) == null, "network for group is null"); + + ListOptions options = new ListOptions.Builder().filter("network eq .*/" + group.getName()); + + if (api.getFirewallApiForProject(userProject.get()).list(options).concat().anyMatch(providesIpPermission(ipPermission))) { + // Permission already exists. + return group; + } + + FirewallOptions fwOptions = new FirewallOptions(); + String uniqueFwName = namingConvention.createWithoutPrefix().uniqueNameForGroup(group.getName()); + fwOptions.name(uniqueFwName); + fwOptions.network(group.getUri()); + if (!ipPermission.getGroupIds().isEmpty()) { + fwOptions.sourceTags(ipPermission.getGroupIds()); + } + if (!ipPermission.getCidrBlocks().isEmpty()) { + fwOptions.sourceRanges(ipPermission.getCidrBlocks()); + } + Firewall.Rule.Builder ruleBuilder = Firewall.Rule.builder(); + ruleBuilder.IpProtocol(ipPermission.getIpProtocol()); + if (ipPermission.getFromPort() > 0) { + if (ipPermission.getFromPort() == ipPermission.getToPort()) { + ruleBuilder.addPort(ipPermission.getToPort()); + } else { + ruleBuilder.addPortRange(ipPermission.getFromPort(), ipPermission.getToPort()); + } + } + fwOptions.addAllowedRule(ruleBuilder.build()); + + AtomicReference<Operation> operation = Atomics.newReference(api.getFirewallApiForProject(userProject + .get()).createInNetwork( + uniqueFwName, + group.getUri(), + fwOptions)); + + retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval, + MILLISECONDS).apply(operation); + + checkState(!operation.get().getHttpError().isPresent(), "Could not create firewall, operation failed" + operation); + + return getSecurityGroupById(group.getId()); + } + + @Override + public SecurityGroup addIpPermission(IpProtocol protocol, int fromPort, int toPort, + Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> cidrBlocks, + Iterable<String> groupIds, SecurityGroup group) { + + IpPermission.Builder permBuilder = IpPermission.builder(); + permBuilder.ipProtocol(protocol); + permBuilder.fromPort(fromPort); + permBuilder.toPort(toPort); + permBuilder.groupIds(groupIds); + permBuilder.cidrBlocks(cidrBlocks); + + return addIpPermission(permBuilder.build(), group); + + } + + @Override + public SecurityGroup removeIpPermission(IpPermission ipPermission, SecurityGroup group) { + checkNotNull(group, "group"); + checkNotNull(ipPermission, "ipPermission"); + + checkNotNull(api.getNetworkApiForProject(userProject.get()).get(group.getId()) == null, "network for group is null"); + + ListOptions options = new ListOptions.Builder().filter("network eq .*/" + group.getName()); + + FluentIterable<Firewall> fws = api.getFirewallApiForProject(userProject.get()).list(options).concat(); + + for (Firewall fw : fws) { + if (equalsIpPermission(ipPermission).apply(fw)) { + AtomicReference<Operation> operation = Atomics.newReference(api.getFirewallApiForProject(userProject.get()) + .delete(fw.getName())); + + retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval, + MILLISECONDS).apply(operation); + + checkState(!operation.get().getHttpError().isPresent(), "Could not delete firewall, operation failed" + operation); + } + } + + return getSecurityGroupById(group.getId()); + } + + @Override + public SecurityGroup removeIpPermission(IpProtocol protocol, int fromPort, int toPort, + Multimap<String, String> tenantIdGroupNamePairs, Iterable<String> cidrBlocks, + Iterable<String> groupIds, SecurityGroup group) { + + IpPermission.Builder permBuilder = IpPermission.builder(); + permBuilder.ipProtocol(protocol); + permBuilder.fromPort(fromPort); + permBuilder.toPort(toPort); + permBuilder.groupIds(groupIds); + permBuilder.cidrBlocks(cidrBlocks); + + return removeIpPermission(permBuilder.build(), group); + + } + + @Override + public boolean supportsTenantIdGroupNamePairs() { + return false; + } + + @Override + public boolean supportsTenantIdGroupIdPairs() { + return false; + } + + @Override + public boolean supportsGroupIds() { + return true; + } + + @Override + public boolean supportsPortRangesForGroups() { + return true; + } + + private SecurityGroup groupForTagsInNetwork(Network nw, final Set <String> tags) { + ListOptions opts = new Builder().filter("network eq .*/" + nw.getName()); + Set<Firewall> fws = api.getFirewallApiForProject(userProject.get()).list(opts).concat() + .filter(new Predicate<Firewall>() { + @Override + public boolean apply(final Firewall input) { + // If any of the targetTags on the firewall apply or the firewall has no target tags... + return Iterables.any(input.getTargetTags(), Predicates.in(tags)) + || Predicates.equalTo(0).apply(input.getTargetTags().size()); + } + }).toSet(); + + if (fws.isEmpty()) { + return null; + } + + return groupConverter.apply(nw); + } +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java new file mode 100644 index 0000000..80b18b1 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; + +import javax.inject.Singleton; + +import org.jclouds.compute.options.TemplateOptions; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +/** + * Prepares metadata from the provided TemplateOptions + */ +@Singleton +public class BuildInstanceMetadata implements Function<TemplateOptions, ImmutableMap.Builder<String, String>> { + + @Override + public ImmutableMap.Builder apply(TemplateOptions input) { + ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + if (input.getPublicKey() != null) { + builder.put("sshKeys", format("%s:%s %s@localhost", checkNotNull(input.getLoginUser(), + "loginUser cannot be null"), input.getPublicKey(), input.getLoginUser())); + } + builder.putAll(input.getUserMetadata()); + return builder; + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java new file mode 100644 index 0000000..1d2508b --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import com.google.common.base.Predicate; +import org.jclouds.compute.functions.GroupNamingConvention; + +import javax.inject.Inject; + +/** + * The convention for naming instance tags that firewall rules recognise. + */ +public class FirewallTagNamingConvention { + + public static class Factory { + + private final GroupNamingConvention.Factory namingConvention; + + @Inject + public Factory(GroupNamingConvention.Factory namingConvention) { + this.namingConvention = namingConvention; + } + + public FirewallTagNamingConvention get(String groupName) { + return new FirewallTagNamingConvention(namingConvention.create().sharedNameForGroup(groupName)); + } + } + + private final String sharedResourceName; + + public FirewallTagNamingConvention(String sharedResourceName) { + this.sharedResourceName = sharedResourceName; + } + + public String name(int port) { + return String.format("%s-port-%s", sharedResourceName, port); + } + + public Predicate<? super String> isFirewallTag() { + return new Predicate<String>() { + @Override + public boolean apply(String input) { + return input != null && input.startsWith(sharedResourceName + "-port-"); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java new file mode 100644 index 0000000..ea069e0 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import javax.annotation.Resource; +import javax.inject.Named; + +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.googlecomputeengine.domain.Firewall; +import org.jclouds.googlecomputeengine.domain.Firewall.Rule; +import org.jclouds.logging.Logger; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.net.domain.IpProtocol; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Range; + +/** + * A function for transforming a GCE-specific Firewall into a generic + * IpPermission object. + */ +public class FirewallToIpPermission implements Function<Firewall, Iterable<IpPermission>> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + public FirewallToIpPermission() { + } + + + @Override + public Iterable<IpPermission> apply(Firewall fw) { + ImmutableSet.Builder setBuilder = ImmutableSet.builder(); + + for (Rule rule : fw.getAllowed()) { + if (!rule.getPorts().isEmpty()) { + for (Range<Integer> r : rule.getPorts().asRanges()) { + IpPermission.Builder builder = populateBuilder(fw, rule.getIpProtocol()); + builder.fromPort(r.lowerEndpoint()); + builder.toPort(r.upperEndpoint()); + setBuilder.add(builder.build()); + } + } else { + setBuilder.add(populateBuilder(fw, rule.getIpProtocol()).build()); + } + } + + return setBuilder.build(); + } + + /** + * Convenience method for populating common parts of the IpPermission. + * @param fw + * @param protocol + * @return a pre-populated builder. + */ + private IpPermission.Builder populateBuilder(Firewall fw, IpProtocol protocol) { + IpPermission.Builder builder = IpPermission.builder(); + + builder.ipProtocol(protocol); + + if (!fw.getSourceRanges().isEmpty()) { + builder.cidrBlocks(fw.getSourceRanges()); + } + if (!fw.getSourceTags().isEmpty()) { + builder.groupIds(fw.getSourceTags()); + } + + return builder; + } +} + http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java new file mode 100644 index 0000000..b783fc9 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Joiner.on; +import static com.google.common.collect.Iterables.getLast; +import static com.google.common.collect.Iterables.limit; +import static com.google.common.collect.Iterables.skip; +import static org.jclouds.compute.domain.Image.Status; + +import java.util.List; + +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.googlecomputeengine.domain.Image; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +/** + * Transforms a google compute domain specific image to a generic Image object. + */ +public class GoogleComputeEngineImageToImage implements Function<Image, org.jclouds.compute.domain.Image> { + + + @Override + public org.jclouds.compute.domain.Image apply(Image image) { + ImageBuilder builder = new ImageBuilder() + .id(image.getName()) + .name(image.getName()) + .providerId(image.getId()) + .description(image.getDescription().orNull()) + .status(Status.AVAILABLE) + .uri(image.getSelfLink()); + + List<String> splits = Lists.newArrayList(image.getName().split("-")); + OperatingSystem.Builder osBuilder = defaultOperatingSystem(image); + if (splits == null || splits.size() == 0 || splits.size() < 3) { + return builder.operatingSystem(osBuilder.build()).build(); + } + + OsFamily family = OsFamily.fromValue(splits.get(0)); + if (family != OsFamily.UNRECOGNIZED) { + osBuilder.family(family); + } + + String version = on(".").join(limit(skip(splits, 1), splits.size() - 2)); + osBuilder.version(version); + + if (image.getDeprecated().isPresent()) { + builder.userMetadata(ImmutableMap.of("deprecatedState", image.getDeprecated().get().getState().orNull())); + } + builder.version(getLast(splits)); + return builder.operatingSystem(osBuilder.build()).build(); + } + + private OperatingSystem.Builder defaultOperatingSystem(Image image) { + return OperatingSystem.builder() + .family(OsFamily.LINUX) + .is64Bit(true) + .description(image.getName()); + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java new file mode 100644 index 0000000..c1ddea1 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_IMAGE_METADATA_KEY; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Location; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Instance; +import org.jclouds.googlecomputeengine.domain.InstanceInZone; +import org.jclouds.googlecomputeengine.domain.SlashEncodedIds; + +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableSet; + +/** + * Transforms a google compute domain Instance into a generic NodeMetatada object. + */ +public class InstanceInZoneToNodeMetadata implements Function<InstanceInZone, NodeMetadata> { + + private final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus; + private final GroupNamingConvention nodeNamingConvention; + private final Supplier<Map<URI, ? extends Image>> images; + private final Supplier<Map<URI, ? extends Hardware>> hardwares; + private final Supplier<Map<URI, ? extends Location>> locations; + private final FirewallTagNamingConvention.Factory firewallTagNamingConvention; + private final GoogleComputeEngineApi api; + private final Supplier<String> userProject; + + @Inject + public InstanceInZoneToNodeMetadata(Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus, + GroupNamingConvention.Factory namingConvention, + @Memoized Supplier<Map<URI, ? extends Image>> images, + @Memoized Supplier<Map<URI, ? extends Hardware>> hardwares, + @Memoized Supplier<Map<URI, ? extends Location>> locations, + FirewallTagNamingConvention.Factory firewallTagNamingConvention, + GoogleComputeEngineApi api, + @UserProject Supplier<String> userProject) { + this.toPortableNodeStatus = toPortableNodeStatus; + this.nodeNamingConvention = namingConvention.createWithoutPrefix(); + this.images = images; + this.hardwares = hardwares; + this.locations = locations; + this.firewallTagNamingConvention = checkNotNull(firewallTagNamingConvention, "firewallTagNamingConvention"); + this.api = checkNotNull(api, "api"); + this.userProject = checkNotNull(userProject, "userProject"); + } + + @Override + public NodeMetadata apply(InstanceInZone instanceInZone) { + Instance input = instanceInZone.getInstance(); + + String group = groupFromMapOrName(input.getMetadata().getItems(), + input.getName(), nodeNamingConvention); + FluentIterable<String> tags = FluentIterable.from(input.getTags().getItems()); + if (group != null) { + tags = tags.filter(Predicates.not(firewallTagNamingConvention.get(group).isFirewallTag())); + } + + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + + builder.id(SlashEncodedIds.fromTwoIds(checkNotNull(locations.get().get(input.getZone()), + "location for %s", input.getZone()) + .getId(), input.getName()).slashEncode()) + .name(input.getName()) + .providerId(input.getId()) + .hostname(input.getName()) + .location(checkNotNull(locations.get().get(input.getZone()), "location for %s", input.getZone())) + .hardware(hardwares.get().get(input.getMachineType())) + .status(toPortableNodeStatus.get(input.getStatus())) + .tags(tags) + .uri(input.getSelfLink()) + .userMetadata(input.getMetadata().getItems()) + .group(group) + .privateAddresses(collectPrivateAddresses(input)) + .publicAddresses(collectPublicAddresses(input)); + + if (input.getMetadata().getItems().containsKey(GCE_IMAGE_METADATA_KEY)) { + try { + URI imageUri = URI.create(input.getMetadata().getItems() + .get(GCE_IMAGE_METADATA_KEY)); + + Map<URI, ? extends Image> imagesMap = images.get(); + + Image image = checkNotNull(imagesMap.get(imageUri), + "no image for %s. images: %s", imageUri, + imagesMap.values()); + builder.imageId(image.getId()); + } catch (IllegalArgumentException e) { + // Swallow any exception here - it just means we don't actually have a valid image URI, so we skip it. + } + } + + return builder.build(); + } + + private Set<String> collectPrivateAddresses(Instance input) { + ImmutableSet.Builder<String> privateAddressesBuilder = ImmutableSet.builder(); + for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) { + if (networkInterface.getNetworkIP().isPresent()) { + privateAddressesBuilder.add(networkInterface.getNetworkIP().get()); + } + } + return privateAddressesBuilder.build(); + } + + private Set<String> collectPublicAddresses(Instance input) { + ImmutableSet.Builder<String> publicAddressesBuilder = ImmutableSet.builder(); + for (Instance.NetworkInterface networkInterface : input.getNetworkInterfaces()) { + for (Instance.NetworkInterface.AccessConfig accessConfig : networkInterface.getAccessConfigs()) { + if (accessConfig.getNatIP().isPresent()) { + publicAddressesBuilder.add(accessConfig.getNatIP().get()); + } + } + } + return publicAddressesBuilder.build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java new file mode 100644 index 0000000..e12a4a3 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getOnlyElement; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.domain.Location; +import org.jclouds.googlecomputeengine.domain.MachineType; +import org.jclouds.googlecomputeengine.domain.MachineTypeInZone; +import org.jclouds.googlecomputeengine.domain.SlashEncodedIds; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Inject; + +/** + * Transforms a google compute domain specific machine type to a generic Hardware object. + */ +public class MachineTypeInZoneToHardware implements Function<MachineTypeInZone, Hardware> { + + private final Supplier<Map<URI, ? extends Location>> locations; + + @Inject + public MachineTypeInZoneToHardware(@Memoized Supplier<Map<URI, ? extends Location>> locations) { + this.locations = locations; + } + + @Override + public Hardware apply(final MachineTypeInZone input) { + Iterable<? extends Location> zonesForMachineType = filter(locations.get().values(), new Predicate<Location>() { + @Override + public boolean apply(Location l) { + return l.getId().equals(input.getMachineType().getZone()); + } + }); + + Location location = checkNotNull(getOnlyElement(zonesForMachineType), + "location for %s", + input.getMachineType().getZone()); + + return new HardwareBuilder() + .id(SlashEncodedIds.fromTwoIds(input.getMachineType().getZone(), input.getMachineType().getName()).slashEncode()) + .location(location) + .name(input.getMachineType().getName()) + .hypervisor("kvm") + .processor(new Processor(input.getMachineType().getGuestCpus(), 1.0)) + .providerId(input.getMachineType().getId()) + .ram(input.getMachineType().getMemoryMb()) + .uri(input.getMachineType().getSelfLink()) + .volumes(collectVolumes(input.getMachineType())) + .supportsImage(Predicates.<Image>alwaysTrue()) + .build(); + } + + private Iterable<Volume> collectVolumes(MachineType input) { + ImmutableSet.Builder<Volume> volumes = ImmutableSet.builder(); + for (MachineType.ScratchDisk disk : input.getScratchDisks()) { + volumes.add(new VolumeBuilder() + .type(Volume.Type.LOCAL) + .size(new Integer(disk.getDiskGb()).floatValue()) + .bootDevice(true) + .durable(false).build()); + } + return volumes.build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java new file mode 100644 index 0000000..1a9be54 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.compute.domain.SecurityGroup; +import org.jclouds.compute.domain.SecurityGroupBuilder; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Firewall; +import org.jclouds.googlecomputeengine.domain.Network; +import org.jclouds.googlecomputeengine.options.ListOptions; +import org.jclouds.logging.Logger; +import org.jclouds.net.domain.IpPermission; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableSet; + +/** + * A function for transforming a GCE-specific Network into a generic + * SecurityGroup object. + */ +public class NetworkToSecurityGroup implements Function<Network, SecurityGroup> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final Function<Firewall, Iterable<IpPermission>> firewallToPerms; + private final GoogleComputeEngineApi api; + private final Supplier<String> project; + + @Inject + public NetworkToSecurityGroup(Function<Firewall, Iterable<IpPermission>> firewallToPerms, + GoogleComputeEngineApi api, + @UserProject Supplier<String> project) { + this.firewallToPerms = firewallToPerms; + this.api = api; + this.project = project; + } + + @Override + public SecurityGroup apply(Network network) { + SecurityGroupBuilder builder = new SecurityGroupBuilder(); + + builder.id(network.getName()); + builder.providerId(network.getId()); + builder.name(network.getName()); + builder.uri(network.getSelfLink()); + + ImmutableSet.Builder permBuilder = ImmutableSet.builder(); + + ListOptions options = new ListOptions.Builder().filter("network eq .*/" + network.getName()); + + for (Firewall fw : api.getFirewallApiForProject(project.get()).list(options).concat()) { + permBuilder.addAll(firewallToPerms.apply(fw)); + } + + builder.ipPermissions(permBuilder.build()); + + return builder.build(); + } +} + http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java new file mode 100644 index 0000000..3301c8f --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Sets; + +@Singleton +public class OrphanedGroupsFromDeadNodes implements Function<Set<? extends NodeMetadata>, Set<String>> { + + private final Predicate<String> isOrphanedGroupPredicate; + + @Inject + public OrphanedGroupsFromDeadNodes(Predicate<String> isOrphanedGroupPredicate) { + this.isOrphanedGroupPredicate = isOrphanedGroupPredicate; + } + + + @Override + public Set<String> apply(Set<? extends NodeMetadata> deadNodes) { + Set<String> groups = Sets.newLinkedHashSet(); + for (NodeMetadata deadNode : deadNodes) { + groups.add(deadNode.getGroup()); + } + Set<String> orphanedGroups = Sets.newLinkedHashSet(); + for (String group : groups) { + if (isOrphanedGroupPredicate.apply(group)) { + orphanedGroups.add(group); + } + } + return orphanedGroups; + } + + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java new file mode 100644 index 0000000..2f880de --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION; + +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.googlecomputeengine.domain.Region; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +/** + * Transforms a google compute domain specific region to a generic Region object. + */ +public class RegionToLocation implements Function<Region, Location> { + + @Override + public Location apply(Region input) { + return new LocationBuilder() + .description(input.getDescription().orNull()) + .metadata(ImmutableMap.of("selfLink", (Object) checkNotNull(input.getSelfLink(), "region URI"))) + .id(input.getName()) + .scope(LocationScope.REGION) + .parent(GOOGLE_PROVIDER_LOCATION) + .build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java new file mode 100644 index 0000000..0dc1c78 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/ZoneToLocation.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GOOGLE_PROVIDER_LOCATION; + +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationBuilder; +import org.jclouds.domain.LocationScope; +import org.jclouds.googlecomputeengine.domain.Zone; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +/** + * Transforms a google compute domain specific zone to a generic Zone object. + */ +public class ZoneToLocation implements Function<Zone, Location> { + + @Override + public Location apply(Zone input) { + return new LocationBuilder() + .description(input.getDescription().orNull()) + .metadata(ImmutableMap.of("selfLink", (Object) checkNotNull(input.getSelfLink(), "zone URI"))) + .id(input.getName()) + .scope(LocationScope.ZONE) + .parent(GOOGLE_PROVIDER_LOCATION) + .build(); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/loaders/FindNetworkOrCreate.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/loaders/FindNetworkOrCreate.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/loaders/FindNetworkOrCreate.java new file mode 100644 index 0000000..2c84787 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/loaders/FindNetworkOrCreate.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.loaders; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Network; +import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheLoader; + +public class FindNetworkOrCreate extends CacheLoader<NetworkAndAddressRange, Network> { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + protected final GoogleComputeEngineApi api; + protected final Function<NetworkAndAddressRange, Network> networkCreator; + protected final Supplier<String> userProject; + + @Inject + public FindNetworkOrCreate(GoogleComputeEngineApi api, + Function<NetworkAndAddressRange, Network> networkCreator, + @UserProject Supplier<String> userProject) { + this.api = checkNotNull(api, "api"); + this.networkCreator = checkNotNull(networkCreator, "networkCreator"); + this.userProject = checkNotNull(userProject, "userProject"); + } + + @Override + public Network load(NetworkAndAddressRange in) { + Network network = api.getNetworkApiForProject(userProject.get()).get(in.getName()); + if (network != null) { + return network; + } else { + return networkCreator.apply(in); + } + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java new file mode 100644 index 0000000..c6aad00 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/options/GoogleComputeEngineTemplateOptions.java @@ -0,0 +1,382 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.options; + +import static com.google.common.base.Optional.fromNullable; +import static org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.googlecomputeengine.domain.Instance; +import org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + +/** + * Instance options specific to Google Compute Engine. + */ +public class GoogleComputeEngineTemplateOptions extends TemplateOptions { + + private Optional<URI> network = Optional.absent(); + private Optional<String> networkName = Optional.absent(); + private Set<Instance.ServiceAccount> serviceAccounts = Sets.newLinkedHashSet(); + private boolean enableNat = true; + private Set<PersistentDisk> disks = Sets.newLinkedHashSet(); + private Optional<Long> bootDiskSize = Optional.absent(); + private boolean keepBootDisk = false; + + @Override + public GoogleComputeEngineTemplateOptions clone() { + GoogleComputeEngineTemplateOptions options = new GoogleComputeEngineTemplateOptions(); + copyTo(options); + return options; + } + + @Override + public void copyTo(TemplateOptions to) { + super.copyTo(to); + if (to instanceof GoogleComputeEngineTemplateOptions) { + GoogleComputeEngineTemplateOptions eTo = GoogleComputeEngineTemplateOptions.class.cast(to); + eTo.network(getNetwork().orNull()); + eTo.serviceAccounts(getServiceAccounts()); + eTo.enableNat(isEnableNat()); + eTo.disks(getDisks()); + eTo.keepBootDisk(shouldKeepBootDisk()); + } + } + + /** + * @deprecated See TemplateOptions#networks + * @see #getNetworkName() + */ + @Deprecated + public GoogleComputeEngineTemplateOptions network(String networkName) { + return this.networks(networkName); + } + + /** + * @see #getNetwork() + */ + public GoogleComputeEngineTemplateOptions network(URI network) { + this.network = fromNullable(network); + return this; + } + + /** + * @see #getServiceAccounts() + * @see ServiceAccount + */ + public GoogleComputeEngineTemplateOptions addServiceAccount(ServiceAccount serviceAccout) { + this.serviceAccounts.add(serviceAccout); + return this; + } + + /** + * @see #getServiceAccounts() + * @see ServiceAccount + */ + public GoogleComputeEngineTemplateOptions serviceAccounts(Set<ServiceAccount> serviceAccounts) { + this.serviceAccounts = Sets.newLinkedHashSet(serviceAccounts); + return this; + } + + /** + * @see #getDisks() + * @see org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk + */ + public GoogleComputeEngineTemplateOptions addDisk(PersistentDisk disk) { + this.disks.add(disk); + return this; + } + + /** + * @see #getDisks() + * @see org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk + */ + public GoogleComputeEngineTemplateOptions disks(Set<PersistentDisk> disks) { + this.disks = Sets.newLinkedHashSet(disks); + return this; + } + + /** + * @see #isEnableNat() + */ + public GoogleComputeEngineTemplateOptions enableNat(boolean enableNat) { + this.enableNat = enableNat; + return this; + } + + /** + * @see #getBootDiskSize() + */ + public GoogleComputeEngineTemplateOptions bootDiskSize(Long bootDiskSize) { + this.bootDiskSize = fromNullable(bootDiskSize); + return this; + } + + /** + * @see #shouldKeepBootDisk() + */ + public GoogleComputeEngineTemplateOptions keepBootDisk(boolean keepBootDisk) { + this.keepBootDisk = keepBootDisk; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions blockOnPort(int port, int seconds) { + return GoogleComputeEngineTemplateOptions.class.cast(super.blockOnPort(port, seconds)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions inboundPorts(int... ports) { + return GoogleComputeEngineTemplateOptions.class.cast(super.inboundPorts(ports)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions authorizePublicKey(String publicKey) { + return GoogleComputeEngineTemplateOptions.class.cast(super.authorizePublicKey(publicKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions installPrivateKey(String privateKey) { + return GoogleComputeEngineTemplateOptions.class.cast(super.installPrivateKey(privateKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions blockUntilRunning(boolean blockUntilRunning) { + return GoogleComputeEngineTemplateOptions.class.cast(super.blockUntilRunning(blockUntilRunning)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions dontAuthorizePublicKey() { + return GoogleComputeEngineTemplateOptions.class.cast(super.dontAuthorizePublicKey()); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions nameTask(String name) { + return GoogleComputeEngineTemplateOptions.class.cast(super.nameTask(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions runAsRoot(boolean runAsRoot) { + return GoogleComputeEngineTemplateOptions.class.cast(super.runAsRoot(runAsRoot)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions runScript(Statement script) { + return GoogleComputeEngineTemplateOptions.class.cast(super.runScript(script)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions overrideLoginCredentials(LoginCredentials overridingCredentials) { + return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginCredentials(overridingCredentials)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions overrideLoginPassword(String password) { + return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginPassword(password)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions overrideLoginPrivateKey(String privateKey) { + return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginPrivateKey(privateKey)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions overrideLoginUser(String loginUser) { + return GoogleComputeEngineTemplateOptions.class.cast(super.overrideLoginUser(loginUser)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions overrideAuthenticateSudo(boolean authenticateSudo) { + return GoogleComputeEngineTemplateOptions.class.cast(super.overrideAuthenticateSudo(authenticateSudo)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions userMetadata(Map<String, String> userMetadata) { + return GoogleComputeEngineTemplateOptions.class.cast(super.userMetadata(userMetadata)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions userMetadata(String key, String value) { + return GoogleComputeEngineTemplateOptions.class.cast(super.userMetadata(key, value)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions nodeNames(Iterable<String> nodeNames) { + return GoogleComputeEngineTemplateOptions.class.cast(super.nodeNames(nodeNames)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions networks(Iterable<String> networks) { + return GoogleComputeEngineTemplateOptions.class.cast(super.networks(networks)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions networks(String... networks) { + return GoogleComputeEngineTemplateOptions.class.cast(super.networks(networks)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions tags(Iterable<String> tags) { + return GoogleComputeEngineTemplateOptions.class.cast(super.tags(tags)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions wrapInInitScript(boolean wrapInInitScript) { + return GoogleComputeEngineTemplateOptions.class.cast(super.wrapInInitScript(wrapInInitScript)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions runScript(String script) { + return GoogleComputeEngineTemplateOptions.class.cast(super.runScript(script)); + } + + /** + * {@inheritDoc} + */ + @Override + public GoogleComputeEngineTemplateOptions blockOnComplete(boolean blockOnComplete) { + return GoogleComputeEngineTemplateOptions.class.cast(super.blockOnComplete(blockOnComplete)); + } + + /** + * @return the ServiceAccounts to enable in the instances. + */ + public Set<Instance.ServiceAccount> getServiceAccounts() { + return serviceAccounts; + } + + /** + * @return the PersistentDisks for this instance. + */ + public Set<PersistentDisk> getDisks() { + return disks; + } + + /** + * @return the URI of an existing network the instances will be attached to. If no network URI or network name are + * provided a new network will be created for the project. + */ + public Optional<URI> getNetwork() { + return network; + } + + /** + * @return the name of an existing network the instances will be attached to, the network is assumed to belong to + * user's project. If no network URI network name are provided a new network will be created for the project. + * <b>Note that this is now pulling from the first element in the networks field from TemplateOptions.</b> + */ + public Optional<String> getNetworkName() { + return fromNullable(Iterables.getFirst(getNetworks(), null)); + } + + /** + * @return whether an AccessConfig with Type ONE_TO_ONE_NAT should be enabled in the instances. When true + * instances will have a NAT address that will be publicly accessible. + */ + public boolean isEnableNat() { + return enableNat; + } + + /** + * @return the boot disk size, if specified. Defaults to 10gb. + */ + public Optional<Long> getBootDiskSize() { + return bootDiskSize; + } + + /** + * @return whether we should keep the boot disk around when deleting the instance. Defaults to false. + */ + public boolean shouldKeepBootDisk() { + return keepBootDisk; + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java new file mode 100644 index 0000000..38066ba --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/predicates/AllNodesInGroupTerminated.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.all; +import static com.google.common.collect.Sets.filter; +import static org.jclouds.compute.predicates.NodePredicates.TERMINATED; +import static org.jclouds.compute.predicates.NodePredicates.all; +import static org.jclouds.compute.predicates.NodePredicates.inGroup; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeService; + +import com.google.common.base.Predicate; + +@Singleton +public class AllNodesInGroupTerminated implements Predicate<String> { + + private final ComputeService computeService; + + @Inject + public AllNodesInGroupTerminated(ComputeService computeService) { + this.computeService = checkNotNull(computeService, "compute service"); + } + + + @Override + public boolean apply(String groupName) { + return all(filter(computeService.listNodesDetailsMatching(all()), inGroup(groupName)), TERMINATED); + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java new file mode 100644 index 0000000..14af9cd --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/CreateNodesWithGroupEncodedIntoNameThenAddToSet.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.strategy; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableSet.of; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT; +import static org.jclouds.util.Predicates2.retry; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.Constants; +import org.jclouds.compute.config.CustomizationResponse; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName; +import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap; +import org.jclouds.compute.strategy.ListNodesStrategy; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention; +import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Firewall; +import org.jclouds.googlecomputeengine.domain.Network; +import org.jclouds.googlecomputeengine.domain.Operation; +import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange; +import org.jclouds.googlecomputeengine.features.FirewallApi; +import org.jclouds.googlecomputeengine.options.FirewallOptions; + +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.Atomics; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; + +public class CreateNodesWithGroupEncodedIntoNameThenAddToSet extends + org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet { + + public static final String EXTERIOR_RANGE = "0.0.0.0/0"; + public static final String DEFAULT_INTERNAL_NETWORK_RANGE = "10.0.0.0/8"; + + private final GoogleComputeEngineApi api; + private final Supplier<String> userProject; + private final LoadingCache<NetworkAndAddressRange, Network> networkMap; + private final Predicate<AtomicReference<Operation>> operationDonePredicate; + private final long operationCompleteCheckInterval; + private final long operationCompleteCheckTimeout; + private final FirewallTagNamingConvention.Factory firewallTagNamingConvention; + + @Inject + protected CreateNodesWithGroupEncodedIntoNameThenAddToSet( + CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy, + ListNodesStrategy listNodesStrategy, + GroupNamingConvention.Factory namingConvention, + @Named(Constants.PROPERTY_USER_THREADS) + ListeningExecutorService userExecutor, + CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory + customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, + GoogleComputeEngineApi api, + @UserProject Supplier<String> userProject, + @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate, + @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval, + @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout, + LoadingCache<NetworkAndAddressRange, Network> networkMap, + FirewallTagNamingConvention.Factory firewallTagNamingConvention) { + super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor, + customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory); + + this.api = checkNotNull(api, "google compute api"); + this.userProject = checkNotNull(userProject, "user project name"); + this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval, + "operation completed check interval"); + this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout, + "operation completed check timeout"); + this.operationDonePredicate = checkNotNull(operationDonePredicate, "operationDonePredicate"); + this.networkMap = checkNotNull(networkMap, "networkMap"); + this.firewallTagNamingConvention = checkNotNull(firewallTagNamingConvention, "firewallTagNamingConvention"); + } + + @Override + public synchronized Map<?, ListenableFuture<Void>> execute(String group, int count, + Template template, + Set<NodeMetadata> goodNodes, + Map<NodeMetadata, Exception> badNodes, + Multimap<NodeMetadata, CustomizationResponse> customizationResponses) { + + String sharedResourceName = namingConvention.create().sharedNameForGroup(group); + Template mutableTemplate = template.clone(); + GoogleComputeEngineTemplateOptions templateOptions = GoogleComputeEngineTemplateOptions.class.cast(mutableTemplate + .getOptions()); + assert template.getOptions().equals(templateOptions) : "options didn't clone properly"; + + // get or create the network and create a firewall with the users configuration + Network network = getOrCreateNetwork(templateOptions, sharedResourceName); + getOrCreateFirewalls(templateOptions, network, firewallTagNamingConvention.get(group)); + templateOptions.network(network.getSelfLink()); + templateOptions.userMetadata(ComputeServiceConstants.NODE_GROUP_KEY, group); + + return super.execute(group, count, mutableTemplate, goodNodes, badNodes, customizationResponses); + } + + /** + * Try and find a network either previously created by jclouds or user defined. + */ + private Network getOrCreateNetwork(GoogleComputeEngineTemplateOptions templateOptions, String sharedResourceName) { + + String networkName = templateOptions.getNetworkName().or(sharedResourceName); + + return networkMap.apply(new NetworkAndAddressRange(networkName, DEFAULT_INTERNAL_NETWORK_RANGE, null)); + } + + /** + * Ensures that a firewall exists for every inbound port that the instance requests. + * <p> + * For each port, there must be a firewall with a name following the {@link FirewallTagNamingConvention}, + * with a target tag also following the {@link FirewallTagNamingConvention}, which opens the requested port + * for all sources on both TCP and UDP protocols. + * @see org.jclouds.googlecomputeengine.features.FirewallApi#patch(String, org.jclouds.googlecomputeengine.options.FirewallOptions) + */ + private void getOrCreateFirewalls(GoogleComputeEngineTemplateOptions templateOptions, Network network, + FirewallTagNamingConvention naming) { + + String projectName = userProject.get(); + FirewallApi firewallApi = api.getFirewallApiForProject(projectName); + Set<AtomicReference<Operation>> operations = Sets.newHashSet(); + + for (Integer port : templateOptions.getInboundPorts()) { + String name = naming.name(port); + Firewall firewall = firewallApi.get(name); + if (firewall == null) { + ImmutableSet<Firewall.Rule> rules = ImmutableSet.of(Firewall.Rule.permitTcpRule(port), Firewall.Rule.permitUdpRule(port)); + FirewallOptions firewallOptions = new FirewallOptions() + .name(name) + .network(network.getSelfLink()) + .allowedRules(rules) + .sourceTags(templateOptions.getTags()) + .sourceRanges(of(DEFAULT_INTERNAL_NETWORK_RANGE, EXTERIOR_RANGE)) + .targetTags(ImmutableSet.of(name)); + AtomicReference<Operation> operation = Atomics.newReference(firewallApi.createInNetwork( + firewallOptions.getName(), + network.getSelfLink(), + firewallOptions)); + operations.add(operation); + } + } + + for (AtomicReference<Operation> operation : operations) { + retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval, + MILLISECONDS).apply(operation); + checkState(!operation.get().getHttpError().isPresent(), + "Could not create firewall, operation failed" + operation); + } + } + +} http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java new file mode 100644 index 0000000..082d9ed --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/strategy/PopulateDefaultLoginCredentialsForImageStrategy.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.googlecomputeengine.compute.strategy; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE; + +import java.security.NoSuchAlgorithmException; +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.TemplateBuilderSpec; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.ssh.internal.RsaSshKeyPairGenerator; + +import com.google.inject.Inject; + +@Singleton +public class PopulateDefaultLoginCredentialsForImageStrategy implements + org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy { + + private final TemplateBuilderSpec templateBuilder; + private final RsaSshKeyPairGenerator keyPairGenerator; + private String compoundKey; + + @Inject + PopulateDefaultLoginCredentialsForImageStrategy(@Named(TEMPLATE) String templateSpec, + RsaSshKeyPairGenerator keyPairGenerator) + throws NoSuchAlgorithmException { + this.templateBuilder = TemplateBuilderSpec.parse(checkNotNull(templateSpec, "template builder spec")); + checkNotNull(templateBuilder.getLoginUser(), "template builder spec must provide a loginUser"); + this.keyPairGenerator = checkNotNull(keyPairGenerator, "keypair generator"); + } + + @PostConstruct + private void generateKeys() { + Map<String, String> keys = keyPairGenerator.get(); + // as we need to store both the pubk and the pk, store them separated by : (base64 does not contain that char) + compoundKey = String.format("%s:%s", checkNotNull(keys.get("public"), "public key cannot be null"), + checkNotNull(keys.get("private"), "private key cannot be null")); + } + + @Override + public LoginCredentials apply(Object image) { + return LoginCredentials.builder() + .authenticateSudo(templateBuilder.getAuthenticateSudo() != null ? + templateBuilder.getAuthenticateSudo() : false) + .privateKey(compoundKey) + .user(templateBuilder.getLoginUser()).build(); + } + +}
