View Javadoc

1   /**
2    *
3    * Copyright (C) 2011 Cloud Conscious, LLC. <info@cloudconscious.com>
4    *
5    * ====================================================================
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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   * @author Adrian Cole
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 }