1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.ec2.config;
20
21 import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
22
23 import java.net.URI;
24 import java.util.Map;
25 import java.util.Set;
26 import java.util.Map.Entry;
27
28 import javax.annotation.Resource;
29 import javax.inject.Inject;
30 import javax.inject.Singleton;
31
32 import org.jclouds.aws.config.WithZonesFormSigningRestClientModule;
33 import org.jclouds.ec2.EC2AsyncClient;
34 import org.jclouds.ec2.EC2Client;
35 import org.jclouds.ec2.domain.AvailabilityZoneInfo;
36 import org.jclouds.ec2.services.AMIAsyncClient;
37 import org.jclouds.ec2.services.AMIClient;
38 import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
39 import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
40 import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
41 import org.jclouds.ec2.services.ElasticBlockStoreClient;
42 import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
43 import org.jclouds.ec2.services.ElasticIPAddressClient;
44 import org.jclouds.ec2.services.InstanceAsyncClient;
45 import org.jclouds.ec2.services.InstanceClient;
46 import org.jclouds.ec2.services.KeyPairAsyncClient;
47 import org.jclouds.ec2.services.KeyPairClient;
48 import org.jclouds.ec2.services.SecurityGroupAsyncClient;
49 import org.jclouds.ec2.services.SecurityGroupClient;
50 import org.jclouds.ec2.services.WindowsAsyncClient;
51 import org.jclouds.ec2.services.WindowsClient;
52 import org.jclouds.http.HttpResponseException;
53 import org.jclouds.http.RequiresHttp;
54 import org.jclouds.location.Region;
55 import org.jclouds.location.Zone;
56 import org.jclouds.logging.Logger;
57 import org.jclouds.rest.ConfiguresRestClient;
58
59 import com.google.common.base.Predicates;
60 import com.google.common.base.Splitter;
61 import com.google.common.collect.ImmutableMap;
62 import com.google.common.collect.ImmutableSet;
63 import com.google.common.collect.Maps;
64 import com.google.common.collect.ImmutableMap.Builder;
65 import com.google.inject.ConfigurationException;
66 import com.google.inject.Injector;
67 import com.google.inject.Key;
68 import com.google.inject.name.Names;
69
70
71
72
73
74
75 @RequiresHttp
76 @ConfiguresRestClient
77 public class EC2RestClientModule<S extends EC2Client, A extends EC2AsyncClient> extends
78 WithZonesFormSigningRestClientModule<S, A> {
79
80 public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
81 .put(AMIClient.class, AMIAsyncClient.class)
82 .put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)
83 .put(InstanceClient.class, InstanceAsyncClient.class)
84 .put(KeyPairClient.class, KeyPairAsyncClient.class)
85 .put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)
86 .put(WindowsClient.class, WindowsAsyncClient.class)
87 .put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)
88 .put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)
89 .build();
90
91 public static EC2RestClientModule<EC2Client, EC2AsyncClient> create() {
92 return new EC2RestClientModule<EC2Client, EC2AsyncClient>(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
93 }
94
95 public EC2RestClientModule(Class<S> sync, Class<A> async, Map<Class<?>, Class<?>> delegateMap) {
96 super(sync, async, delegateMap);
97 }
98
99 @Override
100 protected void bindRegionsToProvider() {
101 bindRegionsToProvider(RegionIdsToURI.class);
102 }
103
104 @Override
105 protected void bindZonesToProvider() {
106 bindZonesToProvider(RegionIdToZoneId.class);
107 }
108
109 @Singleton
110 public static class RegionIdsToURI implements javax.inject.Provider<Map<String, URI>> {
111 private final AvailabilityZoneAndRegionClient client;
112 private final Injector injector;
113
114 @Inject
115 public RegionIdsToURI(EC2Client client, Injector injector) {
116 this.client = client.getAvailabilityZoneAndRegionServices();
117 this.injector = injector;
118 }
119
120 @Singleton
121 @Region
122 @Override
123 public Map<String, URI> get() {
124 try {
125 String regionString = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_REGIONS)));
126 Set<String> regions = ImmutableSet.copyOf(Splitter.on(',').split(regionString));
127 if (regions.size() > 0)
128 return Maps.filterKeys(client.describeRegions(), Predicates.in(regions));
129 } catch (ConfigurationException e) {
130
131
132 }
133 return client.describeRegions();
134
135 }
136 }
137
138 @Singleton
139 public static class RegionIdToZoneId implements javax.inject.Provider<Map<String, String>> {
140 @Resource
141 protected Logger logger = Logger.NULL;
142
143 private final AvailabilityZoneAndRegionClient client;
144 private final Map<String, URI> regions;
145
146 @Inject
147 public RegionIdToZoneId(EC2Client client, @Region Map<String, URI> regions) {
148 this.client = client.getAvailabilityZoneAndRegionServices();
149 this.regions = regions;
150 }
151
152 @Singleton
153 @Zone
154 @Override
155 public Map<String, String> get() {
156 Builder<String, String> map = ImmutableMap.builder();
157 HttpResponseException exception = null;
158 for (Entry<String, URI> region : regions.entrySet()) {
159 try {
160 for (AvailabilityZoneInfo zoneInfo : client.describeAvailabilityZonesInRegion(region.getKey())) {
161 map.put(zoneInfo.getZone(), region.getKey());
162 }
163 } catch (HttpResponseException e) {
164 if (e.getMessage().contains("Unable to tunnel through proxy")) {
165 exception = e;
166 logger.error(e, "Could not describe availability zones in Region: %s", region.getKey());
167 } else {
168 throw e;
169 }
170 }
171 }
172 ImmutableMap<String, String> result = map.build();
173 if (result.isEmpty() && exception != null) {
174 throw exception;
175 }
176 return result;
177 }
178
179 }
180
181 }