You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2015/04/08 16:38:10 UTC

jclouds-labs git commit: [JCLOUDS-850] Providing AzureTemplateBuilderLiveTest

Repository: jclouds-labs
Updated Branches:
  refs/heads/master 766caab06 -> 59f0ae490


[JCLOUDS-850] Providing AzureTemplateBuilderLiveTest


Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/59f0ae49
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/59f0ae49
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/59f0ae49

Branch: refs/heads/master
Commit: 59f0ae490fdc921944f6abd157d71e07255ed404
Parents: 766caab
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Mar 17 18:10:45 2015 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Apr 8 16:21:19 2015 +0200

----------------------------------------------------------------------
 .../AzureComputeProviderMetadata.java           |  10 +-
 .../compute/AzureComputeServiceAdapter.java     |   3 +
 .../compute/functions/LocationToLocation.java   |  10 +-
 .../compute/functions/OSImageToImage.java       |  83 ++++----
 .../azurecompute/domain/AffinityGroup.java      |  33 ----
 .../domain/ComputeCapabilities.java             |  56 ++++++
 .../jclouds/azurecompute/domain/Location.java   |  14 +-
 .../jclouds/azurecompute/domain/OSImage.java    |  18 +-
 .../org/jclouds/azurecompute/domain/Region.java |  90 +++++++++
 .../azurecompute/domain/StorageService.java     |   2 +
 .../azurecompute/features/LocationApi.java      |   2 +-
 .../options/AzureComputeTemplateOptions.java    |   6 +-
 .../suppliers/InMemoryKeyManagersSupplier.java  |  64 ++++---
 .../azurecompute/xml/AffinityGroupHandler.java  |   4 +-
 .../xml/ComputeCapabilitiesHandler.java         |   2 +-
 .../azurecompute/xml/LocationHandler.java       |  49 ++++-
 .../azurecompute/xml/OSImageHandler.java        |   9 +-
 .../AzureComputeProviderMetadataLive.java       |  24 +--
 .../compute/AzureTemplateBuilderLiveTest.java   |  49 +++++
 .../compute/functions/OSImageToImageTest.java   |  70 +++++--
 .../xml/ListAffinityGroupsHandlerTest.java      |   2 +-
 .../xml/ListLocationsHandlerTest.java           |  17 +-
 .../xml/ListOSImagesHandlerTest.java            |  15 +-
 azurecompute/src/test/resources/images.xml      | 188 ++++++++++---------
 24 files changed, 549 insertions(+), 271 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
index 5872fb3..843e264 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/AzureComputeProviderMetadata.java
@@ -19,12 +19,14 @@ package org.jclouds.azurecompute;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_REGEXP;
 import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
 
 import java.net.URI;
 import java.util.Properties;
 
-import org.jclouds.azurecompute.config.AzureComputeProperties;
+import org.jclouds.azurecompute.domain.Region;
 import org.jclouds.providers.ProviderMetadata;
 import org.jclouds.providers.internal.BaseProviderMetadata;
 
@@ -52,8 +54,8 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
       properties.setProperty(OPERATION_TIMEOUT, "60000");
       properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5");
       properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15");
-      properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
-      properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
+      properties.setProperty(TCP_RULE_FORMAT, "tcp_%s-%s");
+      properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
       return properties;
    }
 
@@ -73,7 +75,7 @@ public class AzureComputeProviderMetadata extends BaseProviderMetadata {
                  .homepage(URI.create("https://www.windowsazure.com/"))
                  .console(URI.create("https://windows.azure.com/default.aspx"))
                  .linkedServices("azureblob", "azurequeue", "azuretable")
-                 .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
+                 .iso3166Codes(Region.iso3166Codes())
                  .defaultProperties(AzureComputeProviderMetadata.defaultProperties());
       }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
index ac343a3..8481a13 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/AzureComputeServiceAdapter.java
@@ -196,6 +196,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
                     osImage.affinityGroup(),
                     osImage.label(),
                     osImage.description(),
+                    osImage.imageFamily(),
                     osImage.category(),
                     osImage.os(),
                     osImage.publisherName(),
@@ -211,6 +212,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
                        osImage.affinityGroup(),
                        osImage.label(),
                        osImage.description(),
+                       osImage.imageFamily(),
                        osImage.category(),
                        osImage.os(),
                        osImage.publisherName(),
@@ -244,6 +246,7 @@ public class AzureComputeServiceAdapter implements ComputeServiceAdapter<Deploym
                               image.affinityGroup(),
                               image.label(),
                               image.description(),
+                              image.imageFamily(),
                               image.category(),
                               image.os(),
                               image.publisherName(),

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
index 64a7be3..f334ac8 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/LocationToLocation.java
@@ -22,6 +22,7 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.jclouds.azurecompute.domain.Location;
+import org.jclouds.azurecompute.domain.Region;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.location.suppliers.all.JustProvider;
@@ -48,9 +49,14 @@ public class LocationToLocation implements Function<Location, org.jclouds.domain
       final LocationBuilder builder = new LocationBuilder();
       builder.id(location.name());
       builder.description(location.displayName());
-      builder.scope(LocationScope.REGION);
       builder.parent(getOnlyElement(justProvider.get()));
-      builder.iso3166Codes(ImmutableSet.<String>of("name", location.name()));
+
+      builder.scope(LocationScope.REGION);
+      final Region region = Region.byName(location.name());
+      if (region != null) {
+         builder.iso3166Codes(ImmutableSet.of(region.iso3166Code()));
+      }
+
       return builder.build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
index bfee989..ed2d8ca 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/compute/functions/OSImageToImage.java
@@ -18,19 +18,20 @@ package org.jclouds.azurecompute.compute.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Set;
+
 import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.domain.ImageBuilder;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.location.suppliers.all.JustProvider;
+import org.jclouds.location.predicates.LocationPredicates;
 
 import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
+import com.google.common.base.Splitter;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
 import com.google.inject.Inject;
 
 public class OSImageToImage implements Function<OSImage, Image> {
@@ -55,11 +56,21 @@ public class OSImageToImage implements Function<OSImage, Image> {
 
    private static final String ORACLE_lINUX = "Oracle Linux";
 
-   private final JustProvider provider;
+   public static String toGeoName(final String name, final String location) {
+      return name + "/" + location;
+   }
+
+   public static String[] fromGeoName(final String geoName) {
+      final String[] parts = checkNotNull(geoName, "geoName").split("/");
+      return (parts.length == 1) ? new String[]{geoName, null} : parts;
+   }
+
+   private final Supplier<Set<? extends org.jclouds.domain.Location>> locations;
 
    @Inject
-   OSImageToImage(final JustProvider provider) {
-      this.provider = provider;
+   OSImageToImage(@Memoized final Supplier<Set<? extends org.jclouds.domain.Location>> locations) {
+
+      this.locations = locations;
    }
 
    @Override
@@ -71,53 +82,36 @@ public class OSImageToImage implements Function<OSImage, Image> {
               .status(Image.Status.AVAILABLE)
               .uri(image.mediaLink())
               .providerId(image.name())
-              .location(createLocation(image.location()));
+              .location(FluentIterable.from(locations.get())
+                      .firstMatch(LocationPredicates.idEquals(image.location())).orNull());
 
       final OperatingSystem.Builder osBuilder = osFamily().apply(image);
       return builder.operatingSystem(osBuilder.build()).build();
    }
 
-   private Location createLocation(final String input) {
-      if (input == null) {
-         return null;
-      }
-      return new LocationBuilder().
-              id(input).
-              scope(LocationScope.REGION).
-              description(input).
-              parent(Iterables.getOnlyElement(provider.get())).
-              metadata(ImmutableMap.<String, Object>of("name", input)).
-              build();
-   }
-
-   public static String toGeoName(final String name, final String location) {
-      return name + "/" + location;
-   }
-
-   public static String[] fromGeoName(final String geoName) {
-      final String[] parts = checkNotNull(geoName, "geoName").split("/");
-      return (parts.length == 1) ? new String[]{geoName, null} : parts;
-   }
-
    public static Function<OSImage, OperatingSystem.Builder> osFamily() {
       return new Function<OSImage, OperatingSystem.Builder>() {
          @Override
          public OperatingSystem.Builder apply(final OSImage image) {
+            checkNotNull(image.label(), "label");
+            final String label = Splitter.on('/').split(image.label()).iterator().next();
 
-            final String label = image.label();
-            checkNotNull(label, "label");
-            OsFamily family = OsFamily.UNRECOGNIZED;
+            boolean is64Bit = false;
 
+            OsFamily family = OsFamily.UNRECOGNIZED;
             if (label.contains(CENTOS)) {
                family = OsFamily.CENTOS;
+               is64Bit = image.name().contains("x64");
             } else if (label.contains(OPENLOGIC)) {
                family = OsFamily.CENTOS;
             } else if (label.contains(SUSE)) {
                family = OsFamily.SUSE;
             } else if (label.contains(UBUNTU)) {
                family = OsFamily.UBUNTU;
+               is64Bit = image.name().contains("amd64");
             } else if (label.contains(WINDOWS)) {
                family = OsFamily.WINDOWS;
+               is64Bit = true;
             } else if (label.contains(ORACLE_lINUX)) {
                family = OsFamily.OEL;
             }
@@ -144,15 +138,16 @@ public class OSImageToImage implements Function<OSImage, Image> {
             } else if (label.equals(ORACLE_lINUX)) {
                version = label;
             }
-            if (family != OsFamily.UNRECOGNIZED) {
-               return OperatingSystem.builder().family(family).version(version)
-                       .description(image.description() + "");
-            }
-            if (image.os() == OSImage.Type.WINDOWS) {
-               return OperatingSystem.builder().family(OsFamily.WINDOWS).version(version)
-                       .description(image.description() + "");
-            }
-            return OperatingSystem.builder().family(OsFamily.LINUX).version(version).description(image.description());
+
+            return OperatingSystem.builder().
+                    family(family != OsFamily.UNRECOGNIZED
+                                    ? family
+                                    : image.os() == OSImage.Type.WINDOWS
+                                            ? OsFamily.WINDOWS
+                                            : OsFamily.LINUX).
+                    version(version).
+                    is64Bit(is64Bit).
+                    description(image.description() + "");
          }
       };
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/AffinityGroup.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/AffinityGroup.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/AffinityGroup.java
index 93c7788..e4bb196 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/AffinityGroup.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/AffinityGroup.java
@@ -24,11 +24,6 @@ import com.google.auto.value.AutoValue;
 import java.util.Date;
 import org.jclouds.javax.annotation.Nullable;
 
-/**
- * Affinity group.
- *
- * @see <a href="http://msdn.microsoft.com/en-us/library/azure/ee460797">api</a>
- */
 @AutoValue
 public abstract class AffinityGroup {
 
@@ -45,34 +40,6 @@ public abstract class AffinityGroup {
 
    }
 
-   @AutoValue
-   public abstract static class ComputeCapabilities {
-
-      ComputeCapabilities() {
-      } // For AutoValue only!
-
-      /**
-       * Specifies the role size that is available for the type of deployment.
-       *
-       * @return the role size that is available for the type of deployment
-       */
-      public abstract List<RoleSize.Type> virtualMachineRoleSizes();
-
-      /**
-       * Specifies the role size that is available for the type of deployment.
-       *
-       * @return the role size that is available for the type of deployment
-       */
-      public abstract List<RoleSize.Type> webWorkerRoleSizes();
-
-      public static ComputeCapabilities create(
-              final List<RoleSize.Type> virtualMachineRoleSizes, final List<RoleSize.Type> webWorkerRoleSizes) {
-
-         return new AutoValue_AffinityGroup_ComputeCapabilities(
-                 copyOf(virtualMachineRoleSizes), copyOf(webWorkerRoleSizes));
-      }
-   }
-
    AffinityGroup() {
    } // For AutoValue only!
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/ComputeCapabilities.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/ComputeCapabilities.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/ComputeCapabilities.java
new file mode 100644
index 0000000..4c5eba9
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/ComputeCapabilities.java
@@ -0,0 +1,56 @@
+/*
+ * 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.azurecompute.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+
+/**
+ * Shared by {@link Location} and {@link AffinityGroup}.
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/gg441293#bk_computecapabilities">docs</a>
+ * @see <a href="https://msdn.microsoft.com/en-us/library/azure/ee460797.aspx#bk_computecapabilities">docs</a>
+ */
+@AutoValue
+public abstract class ComputeCapabilities {
+
+   ComputeCapabilities() {
+   } // For AutoValue only!
+
+   /**
+    * Specifies the role size that is available for the type of deployment.
+    *
+    * @return the role size that is available for the type of deployment
+    */
+   public abstract List<RoleSize.Type> virtualMachineRoleSizes();
+
+   /**
+    * Specifies the role size that is available for the type of deployment.
+    *
+    * @return the role size that is available for the type of deployment
+    */
+   public abstract List<RoleSize.Type> webWorkerRoleSizes();
+
+   public static ComputeCapabilities create(
+           final List<RoleSize.Type> virtualMachineRoleSizes, final List<RoleSize.Type> webWorkerRoleSizes) {
+
+      return new AutoValue_ComputeCapabilities(
+              ImmutableList.copyOf(virtualMachineRoleSizes), ImmutableList.copyOf(webWorkerRoleSizes));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Location.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Location.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Location.java
index 65932f8..3ace3ee 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Location.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Location.java
@@ -17,9 +17,11 @@
 package org.jclouds.azurecompute.domain;
 
 import static com.google.common.collect.ImmutableList.copyOf;
+
 import java.util.List;
 
 import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
 
 /**
  * A data center location that is valid for your subscription.
@@ -45,7 +47,15 @@ public abstract class Location {
     */
    public abstract List<String> availableServices();
 
-   public static Location create(final String name, final String displayName, final List<String> availableServices) {
-      return new AutoValue_Location(name, displayName, copyOf(availableServices));
+   /**
+    * Specifies the roles sizes that are available for deployments in the location.
+    */
+   @Nullable
+   public abstract ComputeCapabilities computeCapabilities();
+
+   public static Location create(final String name, final String displayName, final List<String> availableServices,
+           final ComputeCapabilities computeCapabilities) {
+
+      return new AutoValue_Location(name, displayName, copyOf(availableServices), computeCapabilities);
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/OSImage.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/OSImage.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/OSImage.java
index a72ba6b..4fb7a41 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/OSImage.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/OSImage.java
@@ -27,7 +27,7 @@ import com.google.auto.value.AutoValue;
 /**
  * OS image from the image repository
  *
- * @see <a href="http://msdn.microsoft.com/en-us/library/jj157191" >api</a>
+ * @see <a href="http://msdn.microsoft.com/en-us/library/jj157191">api</a>
  */
 @AutoValue
 public abstract class OSImage {
@@ -66,6 +66,14 @@ public abstract class OSImage {
    public abstract String description();
 
    /**
+    * Specifies a value that can be used to group images.
+    *
+    * @return value that can be used to group images
+    */
+   @Nullable
+   public abstract String imageFamily();
+
+   /**
     * The repository classification of image. All user images have the category "User", but categories for other images
     * could be, for example "Canonical"
     */
@@ -102,10 +110,10 @@ public abstract class OSImage {
    public abstract List<String> eula();
 
    public static OSImage create(final String name, final String location, final String affinityGroup, final String label,
-           final String description, final String category, final Type os, final String publisherName,
-           final URI mediaLink, final int logicalSizeInGB, final List<String> eula) {
+           final String description, final String imageFamily, final String category, final Type os,
+           final String publisherName, final URI mediaLink, final int logicalSizeInGB, final List<String> eula) {
 
-      return new AutoValue_OSImage(name, location, affinityGroup, label, description, category, os, publisherName,
-              mediaLink, logicalSizeInGB, copyOf(eula));
+      return new AutoValue_OSImage(name, location, affinityGroup, label, description, imageFamily, category, os,
+              publisherName, mediaLink, logicalSizeInGB, copyOf(eula));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Region.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Region.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Region.java
new file mode 100644
index 0000000..9ba712d
--- /dev/null
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/Region.java
@@ -0,0 +1,90 @@
+/*
+ * 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.azurecompute.domain;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import java.util.Arrays;
+import java.util.Set;
+
+/**
+ * Regions used in Azure.
+ *
+ * @see <a href="http://azure.microsoft.com/en-us/regions/">this page</a>
+ */
+public enum Region {
+
+   CENTRAL_US("Central US", "US-IA"),
+   EAST_US("East US", "US-VA"),
+   EAST_US_2("East US 2", "US-VA"),
+   US_GOV_IOWA("US Gov Iowa", "US-IA"),
+   US_GOV_VIRGINIA("US Gov Virginia", "US-VA"),
+   NORTH_CENTRAL_US("North Central US", "US-IL"),
+   SOUTH_CENTRAL_US("South Central US", "US-TX"),
+   WEST_US("West US", "US-CA"),
+   NORTH_EUROPE("North Europe", "IE"),
+   WEST_EUROPE("West Europe", "NL"),
+   EAST_ASIA("East Asia", "HK"),
+   SOUTH_EAST_ASIA("Southeast Asia", "SG"),
+   JAPAN_EAST("Japan East", "JP-11"),
+   JAPAN_WEST("Japan West", "JP-27"),
+   BRAZIL_SOUTH("Brazil South", "BR"),
+   AUSTRALIA_EAST("Australia East", "AU-NSW"),
+   AUSTRALIA_SOUTH_EAST("Australia Southeast", "AU-VIC");
+
+   private final String name;
+
+   private final String iso3166Code;
+
+   Region(final String name, final String iso3166Code) {
+      this.name = name;
+      this.iso3166Code = iso3166Code;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public String iso3166Code() {
+      return iso3166Code;
+   }
+
+   public static Region byName(final String name) {
+      Preconditions.checkNotNull(name);
+
+      Region result = null;
+      for (Region region : values()) {
+         if (name.equals(region.name)) {
+            result = region;
+         }
+      }
+
+      return result;
+   }
+
+   public static Set<String> iso3166Codes() {
+      return ImmutableSet.copyOf(Iterables.transform(Arrays.asList(values()), new Function<Region, String>() {
+
+         @Override
+         public String apply(final Region region) {
+            return region.iso3166Code;
+         }
+      }));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/domain/StorageService.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/StorageService.java b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/StorageService.java
index bab3415..701ec2c 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/domain/StorageService.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/domain/StorageService.java
@@ -135,11 +135,13 @@ public abstract class StorageService {
       /**
        * Indicates the primary geographical region in which the storage account exists at this time.
        */
+      @Nullable
       public abstract String geoPrimaryRegion();
 
       /**
        * Indicates whether the primary storage region is available.
        */
+      @Nullable
       public abstract RegionStatus statusOfPrimary();
 
       /**

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/features/LocationApi.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/features/LocationApi.java b/azurecompute/src/main/java/org/jclouds/azurecompute/features/LocationApi.java
index 6002205..4ecd5b1 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/features/LocationApi.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/features/LocationApi.java
@@ -37,7 +37,7 @@ import org.jclouds.rest.annotations.XMLResponseParser;
  * your subscription.
  * <p/>
  *
- * @see <a href="http://msdn.microsoft.com/en-us/library/gg441299" />
+ * @see <a href="http://msdn.microsoft.com/en-us/library/gg441299">docs</a>
  */
 @Path("/locations")
 @Headers(keys = "x-ms-version", values = "{jclouds.api-version}")

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/options/AzureComputeTemplateOptions.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/options/AzureComputeTemplateOptions.java b/azurecompute/src/main/java/org/jclouds/azurecompute/options/AzureComputeTemplateOptions.java
index 7d4b063..0abf7ab 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/options/AzureComputeTemplateOptions.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/options/AzureComputeTemplateOptions.java
@@ -23,9 +23,8 @@ import org.jclouds.compute.options.TemplateOptions;
 import com.google.common.base.Optional;
 
 /**
- * Contains options supported by the null {@link org.jclouds.compute.ComputeService#createNodesInGroup(
- * String, int, org.jclouds.compute.options.TemplateOptions)} and null {@link org.jclouds.compute.ComputeService#createNodesInGroup(
- * String, int, org.jclouds.compute.options.TemplateOptions)} operations on the <em>gogrid</em> provider.
+ * Contains options supported by the {@link org.jclouds.compute.ComputeService#createNodesInGroup(
+ * String, int, org.jclouds.compute.options.TemplateOptions)} operation.
  *
  * <h2>Usage</h2> The recommended way to instantiate a {@link AzureComputeTemplateOptions} object is to statically
  * import {@code AzureComputeTemplateOptions.*} and invoke a static creation method followed by an instance mutator (if
@@ -327,4 +326,5 @@ public class AzureComputeTemplateOptions extends TemplateOptions implements Clon
    public AzureComputeTemplateOptions networks(final Iterable<String> networks) {
       return AzureComputeTemplateOptions.class.cast(super.networks(networks));
    }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/suppliers/InMemoryKeyManagersSupplier.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/suppliers/InMemoryKeyManagersSupplier.java b/azurecompute/src/main/java/org/jclouds/azurecompute/suppliers/InMemoryKeyManagersSupplier.java
index d96fcd8..d95a928 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/suppliers/InMemoryKeyManagersSupplier.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/suppliers/InMemoryKeyManagersSupplier.java
@@ -50,41 +50,43 @@ class InMemoryKeyManagersSupplier implements Supplier<KeyManager[]> {
    public KeyManager[] get() {
       KeyManager[] keyManagers = null;
 
-      try {
-         // split in private key and certs
-         final int privateKeyBeginIdx = identity.indexOf("-----BEGIN PRIVATE KEY");
-         final int privateKeyEndIdx = identity.indexOf("-----END PRIVATE KEY");
-         final String pemPrivateKey = identity.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
-
-         final StringBuilder pemCerts = new StringBuilder();
-         int certsBeginIdx = 0;
-         do {
-            certsBeginIdx = identity.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
-            if (certsBeginIdx >= 0) {
-               final int certsEndIdx = identity.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
-               pemCerts.append(identity.substring(certsBeginIdx, certsEndIdx));
-               certsBeginIdx = certsEndIdx;
+      // split in private key and certs
+      final int privateKeyBeginIdx = identity.indexOf("-----BEGIN PRIVATE KEY");
+      final int privateKeyEndIdx = identity.indexOf("-----END PRIVATE KEY");
+      if (privateKeyBeginIdx != -1 && privateKeyEndIdx != -1) {
+         try {
+            final String pemPrivateKey = identity.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
+
+            final StringBuilder pemCerts = new StringBuilder();
+            int certsBeginIdx = 0;
+            do {
+               certsBeginIdx = identity.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
+               if (certsBeginIdx >= 0) {
+                  final int certsEndIdx = identity.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
+                  pemCerts.append(identity.substring(certsBeginIdx, certsEndIdx));
+                  certsBeginIdx = certsEndIdx;
+               }
+            } while (certsBeginIdx != -1);
+
+            // parse private key
+            final KeySpec keySpec = Pems.privateKeySpec(ByteSource.wrap(pemPrivateKey.getBytes(Charsets.UTF_8)));
+            final PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
+
+            // parse cert(s)
+            @SuppressWarnings("unchecked")
+            final Collection<Certificate> certs = (Collection<Certificate>) CertificateFactory.getInstance("X.509").
+                    generateCertificates(new ByteArrayInputStream(pemCerts.toString().getBytes(Charsets.UTF_8)));
+
+            if (certs.isEmpty()) {
+               throw new IllegalStateException("Could not find any valid certificate");
             }
-         } while (certsBeginIdx != -1);
 
-         // parse private key
-         final KeySpec keySpec = Pems.privateKeySpec(ByteSource.wrap(pemPrivateKey.getBytes(Charsets.UTF_8)));
-         final PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
+            final X509Certificate certificate = (X509Certificate) certs.iterator().next();
 
-         // parse cert(s)
-         @SuppressWarnings("unchecked")
-         final Collection<Certificate> certs = (Collection<Certificate>) CertificateFactory.getInstance("X.509").
-                 generateCertificates(new ByteArrayInputStream(pemCerts.toString().getBytes(Charsets.UTF_8)));
-
-         if (certs.isEmpty()) {
-            throw new IllegalStateException("Could not find any valid certificate");
+            keyManagers = new KeyManager[]{new InMemoryKeyManager(certificate, privateKey)};
+         } catch (Exception e) {
+            propagate(e);
          }
-
-         final X509Certificate certificate = (X509Certificate) certs.iterator().next();
-
-         keyManagers = new KeyManager[]{new InMemoryKeyManager(certificate, privateKey)};
-      } catch (Exception e) {
-         propagate(e);
       }
 
       return keyManagers;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/xml/AffinityGroupHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/AffinityGroupHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/AffinityGroupHandler.java
index ea9bd6d..cbe6702 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/AffinityGroupHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/AffinityGroupHandler.java
@@ -29,7 +29,7 @@ import com.google.inject.Inject;
 import org.jclouds.http.functions.ParseSax;
 import org.jclouds.azurecompute.domain.AffinityGroup;
 import org.jclouds.azurecompute.domain.AffinityGroup.Capability;
-import org.jclouds.azurecompute.domain.AffinityGroup.ComputeCapabilities;
+import org.jclouds.azurecompute.domain.ComputeCapabilities;
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 
 import org.xml.sax.Attributes;
@@ -61,7 +61,7 @@ public final class AffinityGroupHandler extends ParseSax.HandlerForGeneratedRequ
    private boolean inComputeCapabilities = false;
 
    @Inject
-   AffinityGroupHandler(ComputeCapabilitiesHandler computeCapabilitiesHandler) {
+   AffinityGroupHandler(final ComputeCapabilitiesHandler computeCapabilitiesHandler) {
       this.computeCapabilitiesHandler = computeCapabilitiesHandler;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ComputeCapabilitiesHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ComputeCapabilitiesHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ComputeCapabilitiesHandler.java
index 8a2f8b1..5d13112 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ComputeCapabilitiesHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/ComputeCapabilitiesHandler.java
@@ -20,7 +20,7 @@ import static org.jclouds.util.SaxUtils.currentOrNull;
 
 import com.google.common.collect.Lists;
 import java.util.List;
-import org.jclouds.azurecompute.domain.AffinityGroup.ComputeCapabilities;
+import org.jclouds.azurecompute.domain.ComputeCapabilities;
 import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.http.functions.ParseSax;
 import org.xml.sax.Attributes;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/xml/LocationHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/LocationHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/LocationHandler.java
index 1b0ca51..f82bf58 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/LocationHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/LocationHandler.java
@@ -25,6 +25,10 @@ import org.jclouds.http.functions.ParseSax;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
+import com.google.inject.Inject;
+import org.jclouds.azurecompute.domain.ComputeCapabilities;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
 
 /**
  * @see <a href="http://msdn.microsoft.com/en-us/library/gg441293" >api</a>
@@ -37,17 +41,44 @@ final class LocationHandler extends ParseSax.HandlerForGeneratedRequestWithResul
 
    private final List<String> availableServices = Lists.newArrayList();
 
+   private ComputeCapabilities computeCapabilities;
+
+   private boolean inComputeCapabilities = false;
+
+   private final ComputeCapabilitiesHandler computeCapabilitiesHandler;
+
    private final StringBuilder currentText = new StringBuilder();
 
+   @Inject
+   LocationHandler(final ComputeCapabilitiesHandler computeCapabilitiesHandler) {
+      this.computeCapabilitiesHandler = computeCapabilitiesHandler;
+   }
+
    @Override
    public Location getResult() {
-      Location result = Location.create(name, displayName, ImmutableList.copyOf(availableServices));
-      name = displayName = null; // handler is called in a loop.
+      Location result = Location.create(
+              name, displayName, ImmutableList.copyOf(availableServices), computeCapabilities);
+
+      // handler is called in a loop.
+      name = displayName = null;
       availableServices.clear();
+      computeCapabilities = null;
+
       return result;
    }
 
    @Override
+   public void startElement(final String uri, final String localName, final String qName, final Attributes attributes)
+           throws SAXException {
+
+      if ("ComputeCapabilities".equals(qName)) {
+         inComputeCapabilities = true;
+      } else if (inComputeCapabilities) {
+         computeCapabilitiesHandler.startElement(uri, localName, qName, attributes);
+      }
+   }
+
+   @Override
    public void endElement(String ignoredUri, String ignoredName, String qName) {
       if (qName.equals("Name")) {
          name = currentOrNull(currentText);
@@ -55,12 +86,22 @@ final class LocationHandler extends ParseSax.HandlerForGeneratedRequestWithResul
          displayName = currentOrNull(currentText);
       } else if (qName.equals("AvailableService")) {
          availableServices.add(currentOrNull(currentText));
+      } else if ("ComputeCapabilities".equals(qName)) {
+         inComputeCapabilities = false;
+         computeCapabilities = computeCapabilitiesHandler.getResult();
+      } else if (inComputeCapabilities) {
+         computeCapabilitiesHandler.endElement(ignoredUri, ignoredName, qName);
       }
+
       currentText.setLength(0);
    }
 
    @Override
-   public void characters(char ch[], int start, int length) {
-      currentText.append(ch, start, length);
+   public void characters(final char ch[], final int start, final int length) {
+      if (inComputeCapabilities) {
+         computeCapabilitiesHandler.characters(ch, start, length);
+      } else {
+         currentText.append(ch, start, length);
+      }
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSImageHandler.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSImageHandler.java b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSImageHandler.java
index 69992cf..a53d988 100644
--- a/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSImageHandler.java
+++ b/azurecompute/src/main/java/org/jclouds/azurecompute/xml/OSImageHandler.java
@@ -48,6 +48,8 @@ final class OSImageHandler extends ParseSax.HandlerForGeneratedRequestWithResult
 
    private String description;
 
+   private String imageFamily;
+
    private OSImage.Type os;
 
    private URI mediaLink;
@@ -56,8 +58,6 @@ final class OSImageHandler extends ParseSax.HandlerForGeneratedRequestWithResult
 
    private final List<String> eulas = Lists.newArrayList();
 
-   private String imageFamily;
-
    private Date publishedDate;
 
    private String iconUri;
@@ -80,9 +80,8 @@ final class OSImageHandler extends ParseSax.HandlerForGeneratedRequestWithResult
 
    @Override
    public OSImage getResult() {
-      OSImage result = OSImage
-              .create(name, location, affinityGroup, label, description, category, os, publisherName, mediaLink,
-                      logicalSizeInGB, ImmutableList.copyOf(eulas));
+      OSImage result = OSImage.create(name, location, affinityGroup, label, description, imageFamily, category, os,
+              publisherName, mediaLink, logicalSizeInGB, ImmutableList.copyOf(eulas));
       resetState(); // handler is called in a loop.
       return result;
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
index 2786c63..c09f0d0 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/AzureComputeProviderMetadataLive.java
@@ -19,12 +19,14 @@ package org.jclouds.azurecompute;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_INITIAL_PERIOD;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_POLL_MAX_PERIOD;
 import static org.jclouds.azurecompute.config.AzureComputeProperties.OPERATION_TIMEOUT;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_FORMAT;
+import static org.jclouds.azurecompute.config.AzureComputeProperties.TCP_RULE_REGEXP;
 import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
 
 import com.google.auto.service.AutoService;
 import java.net.URI;
 import java.util.Properties;
-import org.jclouds.azurecompute.config.AzureComputeProperties;
+import org.jclouds.azurecompute.domain.Region;
 import org.jclouds.azurecompute.internal.BaseAzureComputeApiLiveTest;
 import org.jclouds.providers.ProviderMetadata;
 
@@ -41,14 +43,14 @@ public class AzureComputeProviderMetadataLive extends AzureComputeProviderMetada
    }
 
    public static Properties defaultProperties() {
-      Properties properties = AzureManagementApiMetadata.defaultProperties();
-      properties.setProperty(TEMPLATE, "osFamily=UBUNTU,osVersionMatches=.*14\\.10.*,loginUser=jclouds,"
+      final Properties properties = AzureManagementApiMetadata.defaultProperties();
+      properties.setProperty(TEMPLATE, "osFamily=UBUNTU,osVersionMatches=.*14\\.10,loginUser=jclouds,"
               + "locationId=" + BaseAzureComputeApiLiveTest.LOCATION);
-      properties.setProperty(OPERATION_TIMEOUT, "" + 600 * 1000);
-      properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "" + 5);
-      properties.setProperty(OPERATION_POLL_MAX_PERIOD, "" + 15);
-      properties.setProperty(AzureComputeProperties.TCP_RULE_FORMAT, "tcp_%s-%s");
-      properties.setProperty(AzureComputeProperties.TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
+      properties.setProperty(OPERATION_TIMEOUT, "600000");
+      properties.setProperty(OPERATION_POLL_INITIAL_PERIOD, "5");
+      properties.setProperty(OPERATION_POLL_MAX_PERIOD, "15");
+      properties.setProperty(TCP_RULE_FORMAT, "tcp_%s-%s");
+      properties.setProperty(TCP_RULE_REGEXP, "tcp_\\d{1,5}-\\d{1,5}");
       return properties;
    }
 
@@ -66,7 +68,7 @@ public class AzureComputeProviderMetadataLive extends AzureComputeProviderMetada
                  .homepage(URI.create("https://www.windowsazure.com/"))
                  .console(URI.create("https://windows.azure.com/default.aspx"))
                  .linkedServices("azureblob", "azurequeue", "azuretable")
-                 .iso3166Codes("US-TX", "US-IL", "IE-D", "SG", "NL-NH", "HK")
+                 .iso3166Codes(Region.iso3166Codes())
                  .defaultProperties(AzureComputeProviderMetadataLive.defaultProperties());
       }
 
@@ -76,8 +78,8 @@ public class AzureComputeProviderMetadataLive extends AzureComputeProviderMetada
       }
 
       @Override
-      public Builder fromProviderMetadata(final ProviderMetadata in) {
-         super.fromProviderMetadata(in);
+      public Builder fromProviderMetadata(final ProviderMetadata providerMetadata) {
+         super.fromProviderMetadata(providerMetadata);
          return this;
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureTemplateBuilderLiveTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..f900c34
--- /dev/null
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/AzureTemplateBuilderLiveTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.azurecompute.compute;
+
+import java.util.Set;
+import org.jclouds.azurecompute.AzureComputeProviderMetadata;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+import org.jclouds.providers.ProviderMetadata;
+import org.testng.annotations.Test;
+
+@Test(groups = "live", testName = "AzureTemplateBuilderLiveTest")
+public class AzureTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
+
+   private AzureComputeProviderMetadata providerMeta;
+
+   public AzureTemplateBuilderLiveTest() {
+      super();
+
+      provider = "azurecompute";
+   }
+
+   @Override
+   protected ProviderMetadata createProviderMetadata() {
+      if (providerMeta == null) {
+         providerMeta = new AzureComputeProviderMetadata();
+      }
+      return providerMeta;
+   }
+
+   @Override
+   protected Set<String> getIso3166Codes() {
+      return createProviderMetadata().getIso3166Codes();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/compute/functions/OSImageToImageTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/functions/OSImageToImageTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/functions/OSImageToImageTest.java
index dd17a58..eb1d1a7 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/compute/functions/OSImageToImageTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/compute/functions/OSImageToImageTest.java
@@ -23,27 +23,51 @@ import java.net.URI;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
-import com.google.common.base.Suppliers;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+
 import org.jclouds.azurecompute.domain.OSImage;
+import org.jclouds.azurecompute.domain.Region;
 import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.domain.Location;
-import org.jclouds.location.suppliers.all.JustProvider;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+
 import org.testng.annotations.Test;
 
 @Test(groups = "unit", testName = "OSImageToImageTest")
 public class OSImageToImageTest {
 
    public void testImageTransform() {
-      OSImageToImage imageToImage = new OSImageToImage(new JustProvider("azurecompute", Suppliers
-              .ofInstance(URI.create("foo")), ImmutableSet.<String>of()));
-      // OSImage OSImage = createOSImage();
+      final OSImageToImage imageToImage = new OSImageToImage(new Supplier<Set<? extends Location>>() {
+
+         private Location getLocation(final String input) {
+            final LocationBuilder builder = new LocationBuilder();
+            builder.id(input);
+            builder.description(input);
+
+            builder.scope(LocationScope.REGION);
+            final Region region = Region.byName(input);
+            if (region != null) {
+               builder.iso3166Codes(ImmutableSet.of(region.iso3166Code()));
+            }
+
+            return builder.build();
+         }
+
+         @Override
+         public Set<? extends Location> get() {
+            return ImmutableSet.of(getLocation("Central US"), getLocation("North Europe"));
+         }
+      });
+
       for (OSImage osImage : createOSImage()) {
-         org.jclouds.compute.domain.Image transformed = imageToImage.apply(osImage);
-         OperatingSystem os = OSImageToImage.osFamily().apply(osImage).build();
+         final org.jclouds.compute.domain.Image transformed = imageToImage.apply(osImage);
+         final OperatingSystem os = OSImageToImage.osFamily().apply(osImage).build();
          assertNotNull(osImage.label());
          assertNotNull(transformed.getId());
          assertEquals(transformed.getId(), osImage.name());
@@ -51,10 +75,8 @@ public class OSImageToImageTest {
          assertEquals(transformed.getOperatingSystem().getFamily(), os.getFamily());
          assertEquals(transformed.getOperatingSystem().getVersion(), os.getVersion());
          assertEquals(transformed.getProviderId(), osImage.name());
-         Location location = transformed.getLocation();
-         if (location != null) {
-            assertEquals(location.getId(), osImage.location());
-         }
+         final Location location = transformed.getLocation();
+         assertEquals(location.getId(), osImage.location());
       }
    }
 
@@ -102,6 +124,7 @@ public class OSImageToImageTest {
                       "openSUSE 13.1", // label
                       "openSUSE 13.1 brings updated desktop environments and software, lot of polishing, a brand new KDE theme, "
                       + "complete systemd integration and many other features.", // description
+                      null, // imageFamily
                       "MSDN", // category
                       OSImage.Type.WINDOWS, // os
                       "SUSE", // publisherName
@@ -111,10 +134,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create(
                       "CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "Ubuntu Server 12.04 LTS", // label
                       "Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image", //description
+                      null, // imageFamily
                       "Canonical", // category
                       OSImage.Type.LINUX, // os
                       "Canonical", // publisherName
@@ -128,6 +152,7 @@ public class OSImageToImageTest {
                       null, // affinityGroup
                       "Windows Server 2008 R2 SP1, June 2012", // label
                       "Windows Server 2008 R2 is a multi-purpose server.", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -138,10 +163,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "MSFT__Sql-Server-11EVAL-11.0.2215.0-05152012-en-us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "Microsoft SQL Server 2012 Evaluation Edition", // label
                       "SQL Server 2012 Evaluation Edition (64-bit).", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -152,10 +178,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "MSFT__Win2K12RC-Datacenter-201207.02-en.us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "Windows Server 2012 Release Candidate, July 2012", // label
                       "Windows Server 2012 incorporates Microsoft's experience building.", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -165,10 +192,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "MSFT__Win2K8R2SP1-Datacenter-201207.01-en.us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "Windows Server 2008 R2 SP1, July 2012", // label
                       "Windows Server 2008 R2 is a multi-purpose server.", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -178,10 +206,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "OpenLogic CentOS 6.2", // label
                       "This distribution of Linux is based on CentOS.", //description
+                      null, // imageFamily
                       "OpenLogic", // category
                       OSImage.Type.LINUX, // os
                       "openLogic", //publisherName
@@ -192,10 +221,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "openSUSE 12.1", // label
                       "openSUSE is a free and Linux-based operating system!", //description
+                      null, // imageFamily
                       "SUSE", // category
                       OSImage.Type.LINUX, // os
                       "SUSE", //publisherName
@@ -205,10 +235,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "SUSE__SUSE-Linux-Enterprise-Server-11SP2-20120601-en-us-30GB.vhd", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "SUSE Linux Enterprise Server", // label
                       "SUSE Linux Enterprise Server is a highly reliable value.", //description
+                      null, // imageFamily
                       "SUSE", // category
                       OSImage.Type.LINUX, // os
                       "SUSE", //publisherName
@@ -218,10 +249,11 @@ public class OSImageToImageTest {
               ),
               OSImage.create( //
                       "0b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.4", // name
-                      null, // locations
+                      "North Europe", // locations
                       null, // affinityGroup
                       "RightImage-CentOS-6.4-x64-v13.4", // label
                       null, //description
+                      null, // imageFamily
                       "RightScale with Linux", // category
                       OSImage.Type.LINUX, // os
                       "RightScale with Linux",

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListAffinityGroupsHandlerTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListAffinityGroupsHandlerTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListAffinityGroupsHandlerTest.java
index 101f658..747b0d2 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListAffinityGroupsHandlerTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListAffinityGroupsHandlerTest.java
@@ -22,7 +22,7 @@ import java.io.InputStream;
 import java.util.List;
 
 import org.jclouds.azurecompute.domain.AffinityGroup;
-import org.jclouds.azurecompute.domain.AffinityGroup.ComputeCapabilities;
+import org.jclouds.azurecompute.domain.ComputeCapabilities;
 import org.jclouds.azurecompute.domain.RoleSize;
 import org.jclouds.date.internal.SimpleDateFormatDateService;
 import org.jclouds.http.functions.BaseHandlerTest;

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListLocationsHandlerTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListLocationsHandlerTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListLocationsHandlerTest.java
index bedb8e8..9196ccd 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListLocationsHandlerTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListLocationsHandlerTest.java
@@ -32,20 +32,21 @@ public class ListLocationsHandlerTest extends BaseHandlerTest {
 
    public void test() {
       InputStream is = getClass().getResourceAsStream("/locations.xml");
-      List<Location> result = factory.create(new ListLocationsHandler(new LocationHandler())).parse(is);
+      List<Location> result = factory.create(
+              new ListLocationsHandler(new LocationHandler(new ComputeCapabilitiesHandler()))).parse(is);
 
       assertEquals(result, expected());
    }
 
    public static List<Location> expected() {
       List<String> availableServices = ImmutableList.of("Compute", "Storage", "PersistentVMRole");
-      return ImmutableList.of( //
-              Location.create("West US", "West US", availableServices), //
-              Location.create("East US", "East US", availableServices), //
-              Location.create("East Asia", "East Asia", availableServices), //
-              Location.create("Southeast Asia", "Southeast Asia", availableServices), //
-              Location.create("North Europe", "North Europe", availableServices), //
-              Location.create("West Europe", "West Europe", availableServices) //
+      return ImmutableList.of(
+              Location.create("West US", "West US", availableServices, null),
+              Location.create("East US", "East US", availableServices, null),
+              Location.create("East Asia", "East Asia", availableServices, null),
+              Location.create("Southeast Asia", "Southeast Asia", availableServices, null),
+              Location.create("North Europe", "North Europe", availableServices, null),
+              Location.create("West Europe", "West Europe", availableServices, null)
       );
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListOSImagesHandlerTest.java
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListOSImagesHandlerTest.java b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListOSImagesHandlerTest.java
index 29a9684..593da0c 100644
--- a/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListOSImagesHandlerTest.java
+++ b/azurecompute/src/test/java/org/jclouds/azurecompute/xml/ListOSImagesHandlerTest.java
@@ -48,6 +48,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "Ubuntu Server 12.04 LTS", // label
                       "Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image", //description
+                      "Ubuntu Server 12.04 LTS", // imageFamily
                       "Canonical", // category
                       OSImage.Type.LINUX, // os
                       "Canonical", //publisherName
@@ -61,10 +62,12 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "Windows Server 2008 R2 SP1, June 2012", // label
                       "Windows Server 2008 R2 is a multi-purpose server.", //description
+                      "Windows Server 2008 R2 SP1", // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
-                      URI.create("http://blobs/disks/mydeployment/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd"),
+                      URI.create("http://blobs/disks/mydeployment/"
+                              + "MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd"),
                       // mediaLink
                       30, // logicalSizeInGB
                       Collections.<String>emptyList() // eula
@@ -75,6 +78,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "Microsoft SQL Server 2012 Evaluation Edition", // label
                       "SQL Server 2012 Evaluation Edition (64-bit).", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -89,6 +93,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "Windows Server 2012 Release Candidate, July 2012", // label
                       "Windows Server 2012 incorporates Microsoft's experience building.", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -102,6 +107,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "Windows Server 2008 R2 SP1, July 2012", // label
                       "Windows Server 2008 R2 is a multi-purpose server.", //description
+                      null, // imageFamily
                       "Microsoft", // category
                       OSImage.Type.WINDOWS, // os
                       "Microsoft", //publisherName
@@ -115,10 +121,12 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "OpenLogic CentOS 6.2", // label
                       "This distribution of Linux is based on CentOS.", //description
+                      null, // imageFamily
                       "OpenLogic", // category
                       OSImage.Type.LINUX, // os
                       "openLogic", //publisherName
-                      URI.create("http://blobs/disks/mydeployment/OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd"),
+                      URI.create("http://blobs/disks/mydeployment/"
+                              + "OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd"),
                       // mediaLink
                       30, //logicalSizeInGB
                       Arrays.asList("http://www.openlogic.com/azure/service-agreement/") // eula
@@ -129,6 +137,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "openSUSE 12.1", // label
                       "openSUSE is a free and Linux-based operating system!", //description
+                      null, // imageFamily
                       "SUSE", // category
                       OSImage.Type.LINUX, // os
                       "SUSE", //publisherName
@@ -142,6 +151,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "SUSE Linux Enterprise Server", // label
                       "SUSE Linux Enterprise Server is a highly reliable value.", //description
+                      null, // imageFamily
                       "SUSE", // category
                       OSImage.Type.LINUX, // os
                       "SUSE", //publisherName
@@ -155,6 +165,7 @@ public class ListOSImagesHandlerTest extends BaseHandlerTest {
                       null, // affinityGroup
                       "RightImage-CentOS-6.4-x64-v13.4", // label
                       null, //description
+                      null, // imageFamily
                       "RightScale with Linux", // category
                       OSImage.Type.LINUX, // os
                       "RightScale with Linux",

http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/59f0ae49/azurecompute/src/test/resources/images.xml
----------------------------------------------------------------------
diff --git a/azurecompute/src/test/resources/images.xml b/azurecompute/src/test/resources/images.xml
index 179ef75..24df711 100644
--- a/azurecompute/src/test/resources/images.xml
+++ b/azurecompute/src/test/resources/images.xml
@@ -1,96 +1,98 @@
 <Images xmlns="http://schemas.microsoft.com/windowsazure">
-    <OSImage>
-        <Category>Canonical</Category>
-        <Label>Ubuntu Server 12.04 LTS</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd</Name>
-        <OS>Linux</OS>
-        <PublisherName>Canonical</PublisherName>
-        <Eula>http://www.ubuntu.com/project/about-ubuntu/licensing</Eula>
-        <Description>Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image</Description>
-    </OSImage>
-    <OSImage>
-        <Category>Microsoft</Category>
-        <Label>Windows Server 2008 R2 SP1, June 2012</Label>
-        <Location>North Europe</Location>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</Name>
-        <MediaLink>http://blobs/disks/mydeployment/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</MediaLink>
-        <OS>Windows</OS>
-        <PublisherName>Microsoft</PublisherName>
-        <Eula />
-        <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
-    </OSImage>
-    <OSImage>
-        <Category>Microsoft</Category>
-        <Label>Microsoft SQL Server 2012 Evaluation Edition</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>MSFT__Sql-Server-11EVAL-11.0.2215.0-05152012-en-us-30GB.vhd</Name>
-        <OS>Windows</OS>
-        <PublisherName>Microsoft</PublisherName>
-        <Eula>http://go.microsoft.com/fwlink/?LinkID=251820;http://go.microsoft.com/fwlink/?LinkID=131004</Eula>
-        <Description>SQL Server 2012 Evaluation Edition (64-bit).</Description>
-    </OSImage>
-    <OSImage>
-        <Category>Microsoft</Category>
-        <Label>Windows Server 2012 Release Candidate, July 2012</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>MSFT__Win2K12RC-Datacenter-201207.02-en.us-30GB.vhd</Name>
-        <OS>Windows</OS>
-        <PublisherName>Microsoft</PublisherName>
-        <Eula />
-        <Description>Windows Server 2012 incorporates Microsoft's experience building.</Description>
-    </OSImage>
-    <OSImage>
-        <Category>Microsoft</Category>
-        <Label>Windows Server 2008 R2 SP1, July 2012</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>MSFT__Win2K8R2SP1-Datacenter-201207.01-en.us-30GB.vhd</Name>
-        <OS>Windows</OS>
-        <PublisherName>Microsoft</PublisherName>
-        <Eula />
-        <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
-    </OSImage>
-    <OSImage>
-        <Category>OpenLogic</Category>
-        <Label>OpenLogic CentOS 6.2</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</Name>
-        <MediaLink>http://blobs/disks/mydeployment/OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</MediaLink>
-        <OS>Linux</OS>
-        <PublisherName>openLogic</PublisherName>
-        <Eula>http://www.openlogic.com/azure/service-agreement/</Eula>
-        <Description>This distribution of Linux is based on CentOS.</Description>
-    </OSImage>
-    <OSImage>
-        <Category>SUSE</Category>
-        <Label>openSUSE 12.1</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd</Name>
-        <OS>Linux</OS>
-        <PublisherName>SUSE</PublisherName>
-        <Eula>http://opensuse.org/</Eula>
-        <Description>openSUSE is a free and Linux-based operating system!</Description>
-    </OSImage>
-    <OSImage>
-        <Category>SUSE</Category>
-        <Label>SUSE Linux Enterprise Server</Label>
-        <LogicalSizeInGB>30</LogicalSizeInGB>
-        <Name>SUSE__SUSE-Linux-Enterprise-Server-11SP2-20120601-en-us-30GB.vhd</Name>
-        <OS>Linux</OS>
-        <PublisherName>SUSE</PublisherName>
-        <Eula>http://www.novell.com/licensing/eula/</Eula>
-        <Description>SUSE Linux Enterprise Server is a highly reliable value.</Description>
-    </OSImage>
-    <OSImage>
-        <Category>RightScale with Linux</Category>
-        <Label>RightImage-CentOS-6.4-x64-v13.4</Label>
-        <LogicalSizeInGB>10</LogicalSizeInGB>
-        <Name>0b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.4</Name>
-        <OS>Linux</OS>
-        <PublisherName>RightScale with Linux</PublisherName>
-        <Eula>;</Eula>
-        <Description/>
-    </OSImage>
+   <OSImage>
+      <Category>Canonical</Category>
+      <Label>Ubuntu Server 12.04 LTS</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>CANONICAL__Canonical-Ubuntu-12-04-amd64-server-20120528.1.3-en-us-30GB.vhd</Name>
+      <OS>Linux</OS>
+      <PublisherName>Canonical</PublisherName>
+      <Eula>http://www.ubuntu.com/project/about-ubuntu/licensing</Eula>
+      <Description>Ubuntu Server 12.04 LTS amd64 20120528 Cloud Image</Description>
+      <ImageFamily>Ubuntu Server 12.04 LTS</ImageFamily>
+   </OSImage>
+   <OSImage>
+      <Category>Microsoft</Category>
+      <Label>Windows Server 2008 R2 SP1, June 2012</Label>
+      <Location>North Europe</Location>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</Name>
+      <MediaLink>http://blobs/disks/mydeployment/MSFT__Win2K8R2SP1-120612-1520-121206-01-en-us-30GB.vhd</MediaLink>
+      <OS>Windows</OS>
+      <PublisherName>Microsoft</PublisherName>
+      <Eula />
+      <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
+      <ImageFamily>Windows Server 2008 R2 SP1</ImageFamily>
+   </OSImage>
+   <OSImage>
+      <Category>Microsoft</Category>
+      <Label>Microsoft SQL Server 2012 Evaluation Edition</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>MSFT__Sql-Server-11EVAL-11.0.2215.0-05152012-en-us-30GB.vhd</Name>
+      <OS>Windows</OS>
+      <PublisherName>Microsoft</PublisherName>
+      <Eula>http://go.microsoft.com/fwlink/?LinkID=251820;http://go.microsoft.com/fwlink/?LinkID=131004</Eula>
+      <Description>SQL Server 2012 Evaluation Edition (64-bit).</Description>
+   </OSImage>
+   <OSImage>
+      <Category>Microsoft</Category>
+      <Label>Windows Server 2012 Release Candidate, July 2012</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>MSFT__Win2K12RC-Datacenter-201207.02-en.us-30GB.vhd</Name>
+      <OS>Windows</OS>
+      <PublisherName>Microsoft</PublisherName>
+      <Eula />
+      <Description>Windows Server 2012 incorporates Microsoft's experience building.</Description>
+   </OSImage>
+   <OSImage>
+      <Category>Microsoft</Category>
+      <Label>Windows Server 2008 R2 SP1, July 2012</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>MSFT__Win2K8R2SP1-Datacenter-201207.01-en.us-30GB.vhd</Name>
+      <OS>Windows</OS>
+      <PublisherName>Microsoft</PublisherName>
+      <Eula />
+      <Description>Windows Server 2008 R2 is a multi-purpose server.</Description>
+   </OSImage>
+   <OSImage>
+      <Category>OpenLogic</Category>
+      <Label>OpenLogic CentOS 6.2</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</Name>
+      <MediaLink>http://blobs/disks/mydeployment/OpenLogic__OpenLogic-CentOS-62-20120531-en-us-30GB.vhd</MediaLink>
+      <OS>Linux</OS>
+      <PublisherName>openLogic</PublisherName>
+      <Eula>http://www.openlogic.com/azure/service-agreement/</Eula>
+      <Description>This distribution of Linux is based on CentOS.</Description>
+   </OSImage>
+   <OSImage>
+      <Category>SUSE</Category>
+      <Label>openSUSE 12.1</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>SUSE__openSUSE-12-1-20120603-en-us-30GB.vhd</Name>
+      <OS>Linux</OS>
+      <PublisherName>SUSE</PublisherName>
+      <Eula>http://opensuse.org/</Eula>
+      <Description>openSUSE is a free and Linux-based operating system!</Description>
+   </OSImage>
+   <OSImage>
+      <Category>SUSE</Category>
+      <Label>SUSE Linux Enterprise Server</Label>
+      <LogicalSizeInGB>30</LogicalSizeInGB>
+      <Name>SUSE__SUSE-Linux-Enterprise-Server-11SP2-20120601-en-us-30GB.vhd</Name>
+      <OS>Linux</OS>
+      <PublisherName>SUSE</PublisherName>
+      <Eula>http://www.novell.com/licensing/eula/</Eula>
+      <Description>SUSE Linux Enterprise Server is a highly reliable value.</Description>
+   </OSImage>
+   <OSImage>
+      <Category>RightScale with Linux</Category>
+      <Label>RightImage-CentOS-6.4-x64-v13.4</Label>
+      <LogicalSizeInGB>10</LogicalSizeInGB>
+      <Name>0b11de9248dd4d87b18621318e037d37__RightImage-CentOS-6.4-x64-v13.4</Name>
+      <OS>Linux</OS>
+      <PublisherName>RightScale with Linux</PublisherName>
+      <Eula>;</Eula>
+      <Description/>
+   </OSImage>
 </Images>