1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.aws.ec2.compute.suppliers;
20
21 import static com.google.common.collect.Iterables.concat;
22 import static com.google.common.collect.Iterables.transform;
23 import static com.google.common.collect.Maps.uniqueIndex;
24 import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_AMI_QUERY;
25 import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_CC_AMI_QUERY;
26 import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_CC_REGIONS;
27
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.concurrent.ExecutorService;
31 import java.util.concurrent.Future;
32
33 import javax.annotation.Resource;
34 import javax.inject.Inject;
35 import javax.inject.Named;
36 import javax.inject.Singleton;
37
38 import org.jclouds.Constants;
39 import org.jclouds.aws.ec2.compute.config.ClusterCompute;
40 import org.jclouds.compute.domain.Image;
41 import org.jclouds.compute.reference.ComputeServiceConstants;
42 import org.jclouds.ec2.compute.domain.RegionAndName;
43 import org.jclouds.location.Region;
44 import org.jclouds.logging.Logger;
45
46 import com.google.common.base.Function;
47 import com.google.common.base.Splitter;
48 import com.google.common.base.Supplier;
49 import com.google.common.base.Throwables;
50 import com.google.common.collect.ImmutableMultimap;
51 import com.google.common.collect.ImmutableSet;
52 import com.google.common.collect.Iterables;
53 import com.google.common.collect.Multimap;
54 import com.google.common.util.concurrent.Futures;
55
56
57
58
59
60 @Singleton
61 public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndName, ? extends Image>> {
62 @Resource
63 @Named(ComputeServiceConstants.COMPUTE_LOGGER)
64 protected Logger logger = Logger.NULL;
65
66 private final Map<RegionAndName, Image> images;
67 private final Set<String> clusterComputeIds;
68 private final CallForImages.Factory factory;
69 private final ExecutorService executor;
70
71 private final Iterable<String> regions;
72 private final String amiQuery;
73 private final Iterable<String> clusterRegions;
74 private final String ccAmiQuery;
75
76 @Inject
77 protected AWSRegionAndNameToImageSupplier(@Region Set<String> regions,
78 @Named(PROPERTY_EC2_AMI_QUERY) String amiQuery, @Named(PROPERTY_EC2_CC_REGIONS) String clusterRegions,
79 @Named(PROPERTY_EC2_CC_AMI_QUERY) String ccAmiQuery, Map<RegionAndName, Image> images,
80 CallForImages.Factory factory, @ClusterCompute Set<String> clusterComputeIds,
81 @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
82 this.factory = factory;
83 this.regions = regions;
84 this.amiQuery = amiQuery;
85 this.clusterRegions = Splitter.on(',').split(clusterRegions);
86 this.ccAmiQuery = ccAmiQuery;
87 this.images = images;
88 this.clusterComputeIds = clusterComputeIds;
89 this.executor = executor;
90 }
91
92 @Override
93 public Map<RegionAndName, ? extends Image> get() {
94 Future<Iterable<Image>> normalImages = images(regions, amiQuery, PROPERTY_EC2_AMI_QUERY);
95 ImmutableSet<Image> clusterImages;
96 try {
97 clusterImages = ImmutableSet.copyOf(images(clusterRegions, ccAmiQuery, PROPERTY_EC2_CC_AMI_QUERY).get());
98 } catch (Exception e) {
99 logger.warn(e, "Error parsing images in query %s", ccAmiQuery);
100 Throwables.propagate(e);
101 return null;
102 }
103 Iterables.addAll(clusterComputeIds, transform(clusterImages, new Function<Image, String>() {
104
105 @Override
106 public String apply(Image arg0) {
107 return arg0.getId();
108 }
109 }));
110 Iterable<? extends Image> parsedImages;
111 try {
112 parsedImages = ImmutableSet.copyOf(concat(clusterImages, normalImages.get()));
113 } catch (Exception e) {
114 logger.warn(e, "Error parsing images in query %s", amiQuery);
115 Throwables.propagate(e);
116 return null;
117 }
118
119 images.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
120
121 @Override
122 public RegionAndName apply(Image from) {
123 return new RegionAndName(from.getLocation().getId(), from.getProviderId());
124 }
125
126 }));
127 return images;
128 }
129
130 private Future<Iterable<Image>> images(Iterable<String> regions, String query, String tag) {
131 if (query.equals("")) {
132 logger.debug(">> no %s specified, skipping image parsing", tag);
133 return Futures.<Iterable<Image>> immediateFuture(ImmutableSet.<Image> of());
134 } else {
135 return executor.submit(factory.parseImagesFromRegionsUsingFilter(regions, QueryStringToMultimap.INSTANCE
136 .apply(query)));
137 }
138 }
139
140 public static enum QueryStringToMultimap implements Function<String, Multimap<String, String>> {
141 INSTANCE;
142 @Override
143 public Multimap<String, String> apply(String arg0) {
144 ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
145 for (String pair : Splitter.on(';').split(arg0)) {
146 String[] keyValue = pair.split("=");
147 if (keyValue.length == 1)
148 builder.putAll(keyValue[0], ImmutableSet.<String> of());
149 else
150 builder.putAll(keyValue[0], Splitter.on(',').split(keyValue[1]));
151 }
152 return builder.build();
153 }
154 }
155 }