http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java new file mode 100644 index 0000000..3a26d34 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java @@ -0,0 +1,439 @@ +/* + * 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; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.tryFind; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.CENTOS_PROJECT; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.DEBIAN_PROJECT; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_BOOT_DISK_SUFFIX; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_DELETE_BOOT_DISK_METADATA_KEY; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_IMAGE_METADATA_KEY; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL; +import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT; +import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type; +import static org.jclouds.googlecomputeengine.predicates.InstancePredicates.isBootDisk; +import static org.jclouds.util.Predicates2.retry; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.annotation.Resource; +import javax.inject.Named; + +import org.jclouds.collect.Memoized; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Location; +import org.jclouds.domain.LoginCredentials; +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.Disk; +import org.jclouds.googlecomputeengine.domain.Image; +import org.jclouds.googlecomputeengine.domain.Instance; +import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk; +import org.jclouds.googlecomputeengine.domain.Instance.PersistentAttachedDisk; +import org.jclouds.googlecomputeengine.domain.InstanceInZone; +import org.jclouds.googlecomputeengine.domain.InstanceTemplate; +import org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk; +import org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk.Mode; +import org.jclouds.googlecomputeengine.domain.MachineType; +import org.jclouds.googlecomputeengine.domain.MachineTypeInZone; +import org.jclouds.googlecomputeengine.domain.Operation; +import org.jclouds.googlecomputeengine.domain.SlashEncodedIds; +import org.jclouds.googlecomputeengine.domain.Zone; +import org.jclouds.googlecomputeengine.features.InstanceApi; +import org.jclouds.http.HttpResponse; +import org.jclouds.logging.Logger; + +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.primitives.Ints; +import com.google.common.util.concurrent.Atomics; +import com.google.common.util.concurrent.UncheckedTimeoutException; +import com.google.inject.Inject; + +public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone> { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final GoogleComputeEngineApi api; + private final Supplier<String> userProject; + private final Supplier<Map<URI, ? extends Location>> zones; + private final Function<TemplateOptions, ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions; + private final Predicate<AtomicReference<Operation>> retryOperationDonePredicate; + private final long operationCompleteCheckInterval; + private final long operationCompleteCheckTimeout; + private final FirewallTagNamingConvention.Factory firewallTagNamingConvention; + + @Inject + public GoogleComputeEngineServiceAdapter(GoogleComputeEngineApi api, + @UserProject Supplier<String> userProject, + Function<TemplateOptions, + ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions, + @Named("zone") Predicate<AtomicReference<Operation>> operationDonePredicate, + @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval, + @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout, + @Memoized Supplier<Map<URI, ? extends Location>> zones, + FirewallTagNamingConvention.Factory firewallTagNamingConvention) { + this.api = checkNotNull(api, "google compute api"); + this.userProject = checkNotNull(userProject, "user project name"); + this.metatadaFromTemplateOptions = checkNotNull(metatadaFromTemplateOptions, + "metadata from template options function"); + this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval, + "operation completed check interval"); + this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout, + "operation completed check timeout"); + this.retryOperationDonePredicate = retry(operationDonePredicate, operationCompleteCheckTimeout, + operationCompleteCheckInterval, TimeUnit.MILLISECONDS); + this.zones = checkNotNull(zones, "zones"); + this.firewallTagNamingConvention = checkNotNull(firewallTagNamingConvention, "firewallTagNamingConvention"); + } + + @Override + public NodeAndInitialCredentials<InstanceInZone> createNodeWithGroupEncodedIntoName( + final String group, final String name, final Template template) { + + checkNotNull(template, "template"); + + GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone(); + checkState(options.getNetwork().isPresent(), "network was not present in template options"); + Hardware hardware = checkNotNull(template.getHardware(), "hardware must be set"); + + checkNotNull(hardware.getUri(), "hardware must have a URI"); + checkNotNull(template.getImage().getUri(), "image URI is null"); + + // Note that the ordering is significant here - the first disk must be the boot disk. + List<PersistentDisk> disks = Lists.newArrayList(); + + if (!tryFind(options.getDisks(), isBootDisk()).isPresent()) { + Disk bootDisk = createBootDisk(template, name); + + disks.add(new PersistentDisk(Mode.READ_WRITE, + bootDisk.getSelfLink(), + null, + true, + true)); + } + + disks.addAll(options.getDisks()); + + InstanceTemplate instanceTemplate = InstanceTemplate.builder() + .forMachineType(hardware.getUri()); + + if (options.isEnableNat()) { + instanceTemplate.addNetworkInterface(options.getNetwork().get(), Type.ONE_TO_ONE_NAT); + } else { + instanceTemplate.addNetworkInterface(options.getNetwork().get()); + } + + instanceTemplate.disks(disks); + + LoginCredentials credentials = getFromImageAndOverrideIfRequired(template.getImage(), options); + + ImmutableMap.Builder<String, String> metadataBuilder = metatadaFromTemplateOptions.apply(options); + + metadataBuilder.put(GCE_IMAGE_METADATA_KEY, template.getImage().getUri().toString()); + + if (!options.shouldKeepBootDisk()) { + metadataBuilder.put(GCE_DELETE_BOOT_DISK_METADATA_KEY, Boolean.TRUE.toString()); + } + + instanceTemplate.metadata(metadataBuilder.build()); + instanceTemplate.serviceAccounts(options.getServiceAccounts()); + + final InstanceApi instanceApi = api.getInstanceApiForProject(userProject.get()); + final String zone = template.getLocation().getId(); + Operation operation = instanceApi.createInZone(name, zone, instanceTemplate); + + if (options.shouldBlockUntilRunning()) { + waitOperationDone(operation); + } + + // some times the newly created instances are not immediately returned + AtomicReference<Instance> instance = Atomics.newReference(); + + retry(new Predicate<AtomicReference<Instance>>() { + @Override + public boolean apply(AtomicReference<Instance> input) { + input.set(instanceApi.getInZone(zone, name)); + return input.get() != null; + } + }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance); + + if (!options.getTags().isEmpty()) { + Operation tagsOperation = instanceApi.setTagsInZone(zone, + name, options.getTags(), instance.get().getTags().getFingerprint()); + + waitOperationDone(tagsOperation); + + retry(new Predicate<AtomicReference<Instance>>() { + @Override + public boolean apply(AtomicReference<Instance> input) { + input.set(instanceApi.getInZone(zone, name)); + return input.get() != null; + } + }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance); + } + + // Add tags for security groups + final FirewallTagNamingConvention naming = firewallTagNamingConvention.get(group); + Set<String> tags = FluentIterable.from(Ints.asList(options.getInboundPorts())) + .transform(new Function<Integer, String>(){ + @Override + public String apply(Integer input) { + return input != null + ? naming.name(input) + : null; + } + }) + .toSet(); + instanceApi.setTagsInZone(zone, instance.get().getName(), tags, instance.get().getTags().getFingerprint()); + + InstanceInZone instanceInZone = new InstanceInZone(instance.get(), zone); + + return new NodeAndInitialCredentials<InstanceInZone>(instanceInZone, instanceInZone.slashEncode(), credentials); + } + + private Disk createBootDisk(Template template, String instanceName) { + URI imageUri = template.getImage().getUri(); + + GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone(); + + int diskSize = options.getBootDiskSize().or(10l).intValue(); + + String diskName = instanceName + "-" + GCE_BOOT_DISK_SUFFIX; + + Operation diskOperation = api.getDiskApiForProject(userProject.get()) + .createFromImageWithSizeInZone(imageUri.toString(), + diskName, + diskSize, + template.getLocation().getId()); + + waitOperationDone(diskOperation); + + return api.getDiskApiForProject(userProject.get()).getInZone(template.getLocation().getId(), + diskName); + } + + @Override + public Iterable<MachineTypeInZone> listHardwareProfiles() { + ImmutableSet.Builder<MachineTypeInZone> builder = ImmutableSet.builder(); + + for (final Location zone : zones.get().values()) { + builder.addAll(api.getMachineTypeApiForProject(userProject.get()) + .listInZone(zone.getId()) + .concat() + .filter(new Predicate<MachineType>() { + @Override + public boolean apply(MachineType input) { + return !input.getDeprecated().isPresent(); + } + }) + .transform(new Function<MachineType, MachineTypeInZone>() { + + @Override + public MachineTypeInZone apply(MachineType arg0) { + return new MachineTypeInZone(arg0, arg0.getZone()); + } + })); + } + + return builder.build(); + } + + @Override + public Iterable<Image> listImages() { + return ImmutableSet.<Image>builder() + .addAll(api.getImageApiForProject(userProject.get()).list().concat()) + .addAll(api.getImageApiForProject(DEBIAN_PROJECT).list().concat()) + .addAll(api.getImageApiForProject(CENTOS_PROJECT).list().concat()) + .build(); + } + + @Override + public Image getImage(String id) { + return Objects.firstNonNull(api.getImageApiForProject(userProject.get()).get(id), + Objects.firstNonNull(api.getImageApiForProject(DEBIAN_PROJECT).get(id), + api.getImageApiForProject(CENTOS_PROJECT).get(id))); + + } + + @Override + public Iterable<Zone> listLocations() { + return api.getZoneApiForProject(userProject.get()).list().concat(); + } + + @Override + public InstanceInZone getNode(String name) { + SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name); + + Instance instance = api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(), + slashEncodedIds.getSecondId()); + + return instance == null ? null : new InstanceInZone(instance, slashEncodedIds.getFirstId()); + } + + @Override + public Iterable<InstanceInZone> listNodes() { + return FluentIterable.from(zones.get().values()).transformAndConcat(new Function<Location, ImmutableSet<InstanceInZone>>() { + @Override + public ImmutableSet<InstanceInZone> apply(final Location input) { + return api.getInstanceApiForProject(userProject.get()).listInZone(input.getId()).concat() + .transform(new Function<Instance, InstanceInZone>() { + + @Override + public InstanceInZone apply(Instance arg0) { + return new InstanceInZone(arg0, input.getId()); + } + }).toSet(); + } + }).toSet(); + } + + @Override + public Iterable<InstanceInZone> listNodesByIds(final Iterable<String> ids) { + return filter(listNodes(), new Predicate<InstanceInZone>() { + + @Override + public boolean apply(InstanceInZone instanceInZone) { + return contains(ids, instanceInZone.getInstance().getName()); + } + }); + } + + @Override + public void destroyNode(final String name) { + SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name); + String diskName = null; + try { + Instance instance = api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(), + slashEncodedIds.getSecondId()); + if (instance.getMetadata().getItems().get(GCE_DELETE_BOOT_DISK_METADATA_KEY).equals("true")) { + Optional<AttachedDisk> disk = tryFind(instance.getDisks(), new Predicate<AttachedDisk>() { + @Override + public boolean apply(AttachedDisk input) { + return PersistentAttachedDisk.class.isInstance(input) && + PersistentAttachedDisk.class.cast(input).isBoot(); + } + }); + if (disk.isPresent()) { + diskName = PersistentAttachedDisk.class.cast(disk.get()).getSourceDiskName(); + } + } + } catch (Exception e) { + // TODO: what exception actually gets thrown here if the instance doesn't really exist? + } + waitOperationDone(api.getInstanceApiForProject(userProject.get()).deleteInZone(slashEncodedIds.getFirstId(), + slashEncodedIds.getSecondId())); + + if (diskName != null) { + waitOperationDone(api.getDiskApiForProject(userProject.get()).deleteInZone(slashEncodedIds.getFirstId(), + diskName)); + } + + } + + @Override + public void rebootNode(final String name) { + SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name); + + waitOperationDone(api.getInstanceApiForProject(userProject.get()).resetInZone(slashEncodedIds.getFirstId(), + slashEncodedIds.getSecondId())); + } + + @Override + public void resumeNode(String name) { + throw new UnsupportedOperationException("resume is not supported by GCE"); + } + + @Override + public void suspendNode(String name) { + throw new UnsupportedOperationException("suspend is not supported by GCE"); + } + + private LoginCredentials getFromImageAndOverrideIfRequired(org.jclouds.compute.domain.Image image, + GoogleComputeEngineTemplateOptions options) { + LoginCredentials defaultCredentials = image.getDefaultCredentials(); + String[] keys = defaultCredentials.getPrivateKey().split(":"); + String publicKey = keys[0]; + String privateKey = keys[1]; + + LoginCredentials.Builder credentialsBuilder = defaultCredentials.toBuilder(); + credentialsBuilder.privateKey(privateKey); + + // LoginCredentials from image stores the public key along with the private key in the privateKey field + // @see GoogleComputePopulateDefaultLoginCredentialsForImageStrategy + // so if options doesn't have a public key set we set it from the default + if (options.getPublicKey() == null) { + options.authorizePublicKey(publicKey); + } + if (options.hasLoginPrivateKeyOption()) { + credentialsBuilder.privateKey(options.getPrivateKey()); + } + if (options.getLoginUser() != null) { + credentialsBuilder.identity(options.getLoginUser()); + } + if (options.hasLoginPasswordOption()) { + credentialsBuilder.password(options.getLoginPassword()); + } + if (options.shouldAuthenticateSudo() != null) { + credentialsBuilder.authenticateSudo(options.shouldAuthenticateSudo()); + } + LoginCredentials credentials = credentialsBuilder.build(); + options.overrideLoginCredentials(credentials); + return credentials; + } + + private void waitOperationDone(Operation operation) { + AtomicReference<Operation> operationRef = Atomics.newReference(operation); + + // wait for the operation to complete + if (!retryOperationDonePredicate.apply(operationRef)) { + throw new UncheckedTimeoutException("operation did not reach DONE state" + operationRef.get()); + } + + // check if the operation failed + if (operationRef.get().getHttpError().isPresent()) { + HttpResponse response = operationRef.get().getHttpError().get(); + throw new IllegalStateException("operation failed. Http Error Code: " + response.getStatusCode() + + " HttpError: " + response.getMessage()); + } + } + +}
http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java new file mode 100644 index 0000000..730c515 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java @@ -0,0 +1,283 @@ +/* + * 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.config; + +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Maps.uniqueIndex; +import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; + +import java.net.URI; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Named; +import javax.inject.Singleton; + +import com.google.inject.Scopes; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.SecurityGroup; +import org.jclouds.compute.extensions.ImageExtension; +import org.jclouds.compute.extensions.SecurityGroupExtension; +import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; +import org.jclouds.domain.Location; +import org.jclouds.googlecomputeengine.GoogleComputeEngineApi; +import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineService; +import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineServiceAdapter; +import org.jclouds.googlecomputeengine.compute.extensions.GoogleComputeEngineSecurityGroupExtension; +import org.jclouds.googlecomputeengine.compute.functions.BuildInstanceMetadata; +import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention; +import org.jclouds.googlecomputeengine.compute.functions.FirewallToIpPermission; +import org.jclouds.googlecomputeengine.compute.functions.GoogleComputeEngineImageToImage; +import org.jclouds.googlecomputeengine.compute.functions.InstanceInZoneToNodeMetadata; +import org.jclouds.googlecomputeengine.compute.functions.MachineTypeInZoneToHardware; +import org.jclouds.googlecomputeengine.compute.functions.NetworkToSecurityGroup; +import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadNodes; +import org.jclouds.googlecomputeengine.compute.functions.RegionToLocation; +import org.jclouds.googlecomputeengine.compute.functions.ZoneToLocation; +import org.jclouds.googlecomputeengine.compute.loaders.FindNetworkOrCreate; +import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions; +import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated; +import org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet; +import org.jclouds.googlecomputeengine.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; +import org.jclouds.googlecomputeengine.compute.strategy.UseNodeCredentialsButOverrideFromTemplate; +import org.jclouds.googlecomputeengine.config.UserProject; +import org.jclouds.googlecomputeengine.domain.Firewall; +import org.jclouds.googlecomputeengine.domain.Image; +import org.jclouds.googlecomputeengine.domain.Instance; +import org.jclouds.googlecomputeengine.domain.InstanceInZone; +import org.jclouds.googlecomputeengine.domain.MachineTypeInZone; +import org.jclouds.googlecomputeengine.domain.Network; +import org.jclouds.googlecomputeengine.domain.Region; +import org.jclouds.googlecomputeengine.domain.Zone; +import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange; +import org.jclouds.googlecomputeengine.functions.CreateNetworkIfNeeded; +import org.jclouds.net.domain.IpPermission; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +public class GoogleComputeEngineServiceContextModule + extends ComputeServiceAdapterContextModule<InstanceInZone, MachineTypeInZone, Image, Zone> { + + @Override + protected void configure() { + super.configure(); + + bind(ComputeService.class).to(GoogleComputeEngineService.class); + + bind(new TypeLiteral<ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone>>() {}) + .to(GoogleComputeEngineServiceAdapter.class); + + bind(new TypeLiteral<Function<InstanceInZone, NodeMetadata>>() {}) + .to(InstanceInZoneToNodeMetadata.class); + + bind(new TypeLiteral<Function<MachineTypeInZone, Hardware>>() {}) + .to(MachineTypeInZoneToHardware.class); + + bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {}) + .to(GoogleComputeEngineImageToImage.class); + + bind(new TypeLiteral<Function<Region, Location>>() { + }) + .to(RegionToLocation.class); + + bind(new TypeLiteral<Function<Zone, Location>>() {}) + .to(ZoneToLocation.class); + + bind(new TypeLiteral<Function<Firewall, Iterable<IpPermission>>>() {}) + .to(FirewallToIpPermission.class); + + bind(new TypeLiteral<Function<Network, SecurityGroup>>() {}) + .to(NetworkToSecurityGroup.class); + + bind(new TypeLiteral<Function<TemplateOptions, ImmutableMap.Builder<String, String>>>() {}) + .to(BuildInstanceMetadata.class); + + bind(org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy.class) + .to(PopulateDefaultLoginCredentialsForImageStrategy.class); + + bind(org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to( + CreateNodesWithGroupEncodedIntoNameThenAddToSet.class); + + bind(TemplateOptions.class).to(GoogleComputeEngineTemplateOptions.class); + + bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Set<String>>>() {}) + .to(OrphanedGroupsFromDeadNodes.class); + + bind(new TypeLiteral<Predicate<String>>() {}).to(AllNodesInGroupTerminated.class); + + bind(new TypeLiteral<Function<NetworkAndAddressRange, Network>>() {}) + .to(CreateNetworkIfNeeded.class); + + bind(new TypeLiteral<CacheLoader<NetworkAndAddressRange, Network>>() {}) + .to(FindNetworkOrCreate.class); + + bind(new TypeLiteral<SecurityGroupExtension>() {}) + .to(GoogleComputeEngineSecurityGroupExtension.class); + + bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class); + + install(new LocationsFromComputeServiceAdapterModule<InstanceInZone, MachineTypeInZone, Image, Zone>() {}); + + bind(FirewallTagNamingConvention.Factory.class).in(Scopes.SINGLETON); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>> provideImagesMap( + AtomicReference<AuthorizationException> authException, + final Supplier<Set<? extends org.jclouds.compute.domain.Image>> images, + @Named(PROPERTY_SESSION_INTERVAL) long seconds) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>>() { + @Override + public Map<URI, ? extends org.jclouds.compute.domain.Image> get() { + return uniqueIndex(images.get(), new Function<org.jclouds.compute.domain.Image, URI>() { + @Override + public URI apply(org.jclouds.compute.domain.Image input) { + return input.getUri(); + } + }); + } + }, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<URI, ? extends Hardware>> provideHardwaresMap( + AtomicReference<AuthorizationException> authException, + final Supplier<Set<? extends Hardware>> hardwares, + @Named(PROPERTY_SESSION_INTERVAL) long seconds) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<URI, ? extends Hardware>>() { + @Override + public Map<URI, ? extends Hardware> get() { + return uniqueIndex(hardwares.get(), new Function<Hardware, URI>() { + @Override + public URI apply(Hardware input) { + return input.getUri(); + } + }); + } + }, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<URI, ? extends Location>> provideZones( + AtomicReference<AuthorizationException> authException, + final GoogleComputeEngineApi api, final Function<Zone, Location> zoneToLocation, + @UserProject final Supplier<String> userProject, + @Named(PROPERTY_SESSION_INTERVAL) long seconds) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<URI, ? extends Location>>() { + @Override + public Map<URI, ? extends Location> get() { + return uniqueIndex(transform(api.getZoneApiForProject(userProject.get()).list().concat(), zoneToLocation), + new Function<Location, URI>() { + @Override + public URI apply(Location input) { + return (URI) input.getMetadata().get("selfLink"); + } + }); + } + }, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + @Memoized + public Supplier<Map<URI, Region>> provideRegions( + AtomicReference<AuthorizationException> authException, + final GoogleComputeEngineApi api, + @UserProject final Supplier<String> userProject, + @Named(PROPERTY_SESSION_INTERVAL) long seconds) { + return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, + new Supplier<Map<URI, Region>>() { + @Override + public Map<URI, Region> get() { + return uniqueIndex(api.getRegionApiForProject(userProject.get()).list().concat(), + new Function<Region, URI>() { + @Override + public URI apply(Region input) { + return input.getSelfLink(); + } + }); + } + }, + seconds, TimeUnit.SECONDS); + } + + @Provides + @Singleton + protected LoadingCache<NetworkAndAddressRange, Network> networkMap( + CacheLoader<NetworkAndAddressRange, Network> in) { + return CacheBuilder.newBuilder().build(in); + } + + @Override + protected Optional<ImageExtension> provideImageExtension(Injector i) { + return Optional.absent(); + } + + @Override + protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) { + return Optional.of(i.getInstance(SecurityGroupExtension.class)); + } + + @VisibleForTesting + public static final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus = + ImmutableMap.<Instance.Status, NodeMetadata.Status>builder() + .put(Instance.Status.PROVISIONING, NodeMetadata.Status.PENDING) + .put(Instance.Status.STAGING, NodeMetadata.Status.PENDING) + .put(Instance.Status.RUNNING, NodeMetadata.Status.RUNNING) + .put(Instance.Status.STOPPING, NodeMetadata.Status.PENDING) + .put(Instance.Status.STOPPED, NodeMetadata.Status.SUSPENDED) + .put(Instance.Status.TERMINATED, NodeMetadata.Status.TERMINATED).build(); + + @Singleton + @Provides + protected Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus() { + return toPortableNodeStatus; + } +} http://git-wip-us.apache.org/repos/asf/stratos/blob/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java new file mode 100644 index 0000000..f1113e0 --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/extensions/GoogleComputeEngineSecurityGroupExtension.java @@ -0,0 +1,338 @@ +/* + * 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.getToPort() > 0) { + 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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/BuildInstanceMetadata.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallTagNamingConvention.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/FirewallToIpPermission.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/GoogleComputeEngineImageToImage.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/InstanceInZoneToNodeMetadata.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java new file mode 100644 index 0000000..16091cd --- /dev/null +++ b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/MachineTypeInZoneToHardware.java @@ -0,0 +1,100 @@ +/* + * 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.ImmutableMap; +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()); + + // TODO Figure out a robust way to deal with machineTypes with imageSizeGb==0 rather than just blocking them. + 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()) + .userMetadata(ImmutableMap.of("imageSpaceGb", Integer.toString(input.getMachineType().getImageSpaceGb()))) + .volumes(collectVolumes(input.getMachineType())) + .supportsImage(input.getMachineType().getImageSpaceGb() > 0 + ? Predicates.<Image>alwaysTrue() + : Predicates.<Image>alwaysFalse()) + .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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/NetworkToSecurityGroup.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/OrphanedGroupsFromDeadNodes.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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/4203d59b/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java ---------------------------------------------------------------------- diff --git a/dependencies/jclouds/apis/gce/1.8.0-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/functions/RegionToLocation.java b/dependencies/jclouds/apis/gce/1.8.0-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.0-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(); + } +}
