Java tutorial
/* * 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.aliyun.ecs.compute; 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.FluentIterable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.jclouds.aliyun.ecs.ECSComputeServiceApi; import org.jclouds.aliyun.ecs.compute.strategy.CleanupResources; import org.jclouds.aliyun.ecs.domain.AvailableResource; import org.jclouds.aliyun.ecs.domain.AvailableZone; import org.jclouds.aliyun.ecs.domain.Image; import org.jclouds.aliyun.ecs.domain.Instance; import org.jclouds.aliyun.ecs.domain.InstanceRequest; import org.jclouds.aliyun.ecs.domain.InstanceType; import org.jclouds.aliyun.ecs.domain.Region; import org.jclouds.aliyun.ecs.domain.SupportedResource; import org.jclouds.aliyun.ecs.domain.options.CreateInstanceOptions; import org.jclouds.aliyun.ecs.domain.options.ListImagesOptions; import org.jclouds.aliyun.ecs.domain.options.ListInstancesOptions; import org.jclouds.aliyun.ecs.domain.options.TagOptions; import org.jclouds.aliyun.ecs.domain.regionscoped.ImageInRegion; import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId; import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.Template; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.util.ComputeServiceUtils; import org.jclouds.logging.Logger; import javax.annotation.Nullable; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import java.util.List; import java.util.Map; import java.util.Set; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.contains; import static com.google.common.collect.Lists.newArrayList; import static java.lang.String.format; import static org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId.fromSlashEncoded; import static org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId.slashEncodeRegionAndId; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; /** * defines the connection between the {@link ECSComputeServiceApi} implementation and * the jclouds {@link org.jclouds.compute.ComputeService} */ @Singleton public class ECSComputeServiceAdapter implements ComputeServiceAdapter<Instance, InstanceType, ImageInRegion, Region> { private final ECSComputeServiceApi api; private final Predicate<String> instanceSuspendedPredicate; private final Supplier<Set<String>> regionIds; private final CleanupResources cleanupResources; @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; @Inject ECSComputeServiceAdapter(ECSComputeServiceApi api, @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> instanceSuspendedPredicate, @org.jclouds.location.Region Supplier<Set<String>> regionIds, CleanupResources cleanupResources) { this.api = api; this.instanceSuspendedPredicate = instanceSuspendedPredicate; this.regionIds = regionIds; this.cleanupResources = cleanupResources; } @Override public NodeAndInitialCredentials<Instance> createNodeWithGroupEncodedIntoName(String group, String name, Template template) { String instanceType = template.getHardware().getId(); String regionId = template.getLocation().getId(); String imageId = template.getImage().getId(); ECSServiceTemplateOptions templateOptions = template.getOptions().as(ECSServiceTemplateOptions.class); String keyPairName = templateOptions.getKeyPairName(); String securityGroupId = Iterables.getOnlyElement(templateOptions.getGroups()); String vSwitchId = templateOptions.getVSwitchId(); Instance.InternetChargeType internetChargeType = Instance.InternetChargeType .fromValue(templateOptions.getInternetChargeType()); int internetMaxBandwidthOut = templateOptions.getInternetMaxBandwidthOut(); String instanceChargeType = templateOptions.getInstanceChargeType(); Map<String, String> tags = ComputeServiceUtils.metadataAndTagsAsValuesOfEmptyString(templateOptions); tags = new ImmutableMap.Builder().putAll(tags).put(vSwitchId, "").build(); TagOptions tagOptions = TagOptions.Builder.tags(tags); InstanceRequest instanceRequest = api.instanceApi().create(regionId, RegionAndId.fromSlashEncoded(imageId).id(), securityGroupId, name, instanceType, CreateInstanceOptions.Builder.vSwitchId(vSwitchId).internetChargeType(internetChargeType.toString()) .internetMaxBandwidthOut(internetMaxBandwidthOut).instanceChargeType(instanceChargeType) .instanceName(name).keyPairName(keyPairName).tagOptions(tagOptions)); String regionAndInstanceId = slashEncodeRegionAndId(regionId, instanceRequest.getInstanceId()); if (!instanceSuspendedPredicate.apply(regionAndInstanceId)) { final String message = format( "Instance %s was not created correctly. The associated resources created for it will be destroyed", instanceRequest.getInstanceId()); logger.warn(message); cleanupResources.cleanupNode(RegionAndId.create(regionId, instanceRequest.getInstanceId())); cleanupResources.cleanupSecurityGroupIfOrphaned(regionId, securityGroupId); } api.instanceApi().allocatePublicIpAddress(regionId, instanceRequest.getInstanceId()); api.instanceApi().powerOn(instanceRequest.getInstanceId()); Instance instance = Iterables.get(api.instanceApi().list(regionId, ListInstancesOptions.Builder.instanceIds(instanceRequest.getInstanceId())), 0); // Safe to pass null credentials here, as jclouds will default populate // the node with the default credentials from the image, or the ones in // the options, if provided. return new NodeAndInitialCredentials(instance, slashEncodeRegionAndId(regionId, instanceRequest.getInstanceId()), null); } @Override public Iterable<InstanceType> listHardwareProfiles() { final ImmutableSet.Builder<String> instanceTypeIdsBuilder = ImmutableSet.builder(); for (String regionId : getAvailableLocationNames()) { instanceTypeIdsBuilder.addAll(getInstanceTypeIds(regionId)); } final Set<String> ids = instanceTypeIdsBuilder.build(); List<InstanceType> instanceTypes = FluentIterable.from(api.instanceApi().listTypes()) .filter(new Predicate<InstanceType>() { @Override public boolean apply(@Nullable InstanceType input) { return contains(ids, input.id()); } }).toList(); return instanceTypes; } private List<String> getInstanceTypeIds(String regionId) { List<String> instanceTypeIds = Lists.newArrayList(); for (AvailableZone availableZone : api.instanceApi().listInstanceTypesByAvailableZone(regionId)) { for (AvailableResource availableResource : availableZone.availableResources() .get("AvailableResource")) { for (SupportedResource supportedResource : availableResource.supportedResources() .get("SupportedResource")) { if (SupportedResource.Status.AVAILABLE == supportedResource.status()) { instanceTypeIds.add(supportedResource.value()); } } } } return instanceTypeIds; } @Override public Iterable<ImageInRegion> listImages() { final ImmutableList.Builder<ImageInRegion> imagesInRegion = ImmutableList.builder(); for (final String regionId : getAvailableLocationNames()) { imagesInRegion .addAll(api.imageApi().list(regionId).concat().transform(new Function<Image, ImageInRegion>() { @Override public ImageInRegion apply(Image image) { return ImageInRegion.create(regionId, image); } })); } return imagesInRegion.build(); } @Override public ImageInRegion getImage(final String id) { RegionAndId regionAndId = fromSlashEncoded(id); Image image = api.imageApi() .list(regionAndId.regionId(), ListImagesOptions.Builder.imageIds(regionAndId.id())) .firstMatch(Predicates.<Image>notNull()).orNull(); if (image == null) return null; return ImageInRegion.create(regionAndId.regionId(), image); } @Override public Iterable<Region> listLocations() { return FluentIterable.from(api.regionAndZoneApi().describeRegions()).filter(new Predicate<Region>() { @Override public boolean apply(Region region) { return regionIds.get().isEmpty() ? true : regionIds.get().contains(region.id()); } }).toList(); } @Override public Instance getNode(final String id) { RegionAndId regionAndId = fromSlashEncoded(id); return api.instanceApi() .list(regionAndId.regionId(), ListInstancesOptions.Builder.instanceIds(regionAndId.id())) .firstMatch(Predicates.<Instance>notNull()).orNull(); } @Override public void destroyNode(String id) { checkState(cleanupResources.cleanupNode(RegionAndId.fromSlashEncoded(id)), "server(%s) and its resources still there after deleting!?", id); } @Override public void rebootNode(String id) { api.instanceApi().reboot(id); } @Override public void resumeNode(String id) { api.instanceApi().powerOn(id); } @Override public void suspendNode(String id) { api.instanceApi().powerOff(id); } @Override public Iterable<Instance> listNodes() { final ImmutableList.Builder<Instance> instances = ImmutableList.builder(); for (String regionId : getAvailableLocationNames()) { instances.addAll(api.instanceApi().list(regionId).concat()); } return instances.build(); } @Override public Iterable<Instance> listNodesByIds(final Iterable<String> ids) { final ImmutableList.Builder<Instance> instancesBuilder = ImmutableList.builder(); for (String regionId : getAvailableLocationNames()) { instancesBuilder.addAll(api.instanceApi().list(regionId, ListInstancesOptions.Builder.instanceIds(Iterables.toArray(ids, String.class)))); } return instancesBuilder.build(); } private List<String> getAvailableLocationNames() { return newArrayList(Iterables.transform(listLocations(), new Function<Region, String>() { @Override public String apply(Region location) { return location.id(); } })); } }