http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInRegionToImage.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInRegionToImage.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInRegionToImage.java
new file mode 100644
index 0000000..35a6787
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInRegionToImage.java
@@ -0,0 +1,68 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.domain.Location;
+import org.jclouds.openstack.nova.v2_0.domain.Image.Status;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.ImageInRegion;
+
+import com.google.common.base.Function;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Supplier;
+
+/**
+ * A function for transforming a nova-specific Image into a generic Image 
object.
+ */
+public class ImageInRegionToImage implements Function<ImageInRegion, Image> {
+   private final Map<Status, org.jclouds.compute.domain.Image.Status> 
toPortableImageStatus;
+   private final Function<org.jclouds.openstack.nova.v2_0.domain.Image, 
OperatingSystem> imageToOs;
+   private final Supplier<Map<String, Location>> locationIndex;
+
+   @Inject
+   public 
ImageInRegionToImage(Map<org.jclouds.openstack.nova.v2_0.domain.Image.Status, 
Image.Status> toPortableImageStatus,
+            Function<org.jclouds.openstack.nova.v2_0.domain.Image, 
OperatingSystem> imageToOs,
+            Supplier<Map<String, Location>> locationIndex) {
+      this.toPortableImageStatus = checkNotNull(toPortableImageStatus, 
"toPortableImageStatus");
+      this.imageToOs = checkNotNull(imageToOs, "imageToOs");
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+   }
+
+   @Override
+   public Image apply(ImageInRegion imageInRegion) {
+      Location location = locationIndex.get().get(imageInRegion.getRegion());
+      checkState(location != null, "location %s not in locationIndex: %s", 
imageInRegion.getRegion(), locationIndex.get());
+      org.jclouds.openstack.nova.v2_0.domain.Image image = 
imageInRegion.getImage();
+      return new 
ImageBuilder().id(imageInRegion.slashEncode()).providerId(image.getId()).name(image.getName())
+               
.userMetadata(image.getMetadata()).operatingSystem(imageToOs.apply(image)).description(image.getName())
+               
.location(location).status(toPortableImageStatus.get(image.getStatus())).build();
+   }
+
+   @Override
+   public String toString() {
+      return MoreObjects.toStringHelper(this).toString();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
deleted file mode 100644
index c2f6f6c..0000000
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ImageInZoneToImage.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.openstack.nova.v2_0.compute.functions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.ImageBuilder;
-import org.jclouds.compute.domain.OperatingSystem;
-import org.jclouds.domain.Location;
-import org.jclouds.openstack.nova.v2_0.domain.Image.Status;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ImageInZone;
-
-import com.google.common.base.Function;
-import com.google.common.base.MoreObjects;
-import com.google.common.base.Supplier;
-
-/**
- * A function for transforming a nova-specific Image into a generic Image 
object.
- */
-public class ImageInZoneToImage implements Function<ImageInZone, Image> {
-   private final Map<Status, org.jclouds.compute.domain.Image.Status> 
toPortableImageStatus;
-   private final Function<org.jclouds.openstack.nova.v2_0.domain.Image, 
OperatingSystem> imageToOs;
-   private final Supplier<Map<String, Location>> locationIndex;
-
-   @Inject
-   public 
ImageInZoneToImage(Map<org.jclouds.openstack.nova.v2_0.domain.Image.Status, 
Image.Status> toPortableImageStatus, 
-            Function<org.jclouds.openstack.nova.v2_0.domain.Image, 
OperatingSystem> imageToOs,
-            Supplier<Map<String, Location>> locationIndex) {
-      this.toPortableImageStatus = checkNotNull(toPortableImageStatus, 
"toPortableImageStatus");
-      this.imageToOs = checkNotNull(imageToOs, "imageToOs");
-      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
-   }
-
-   @Override
-   public Image apply(ImageInZone imageInZone) {
-      Location location = locationIndex.get().get(imageInZone.getZone());
-      checkState(location != null, "location %s not in locationIndex: %s", 
imageInZone.getZone(), locationIndex.get());
-      org.jclouds.openstack.nova.v2_0.domain.Image image = 
imageInZone.getImage();
-      return new 
ImageBuilder().id(imageInZone.slashEncode()).providerId(image.getId()).name(image.getName())
-               
.userMetadata(image.getMetadata()).operatingSystem(imageToOs.apply(image)).description(image.getName())
-               
.location(location).status(toPortableImageStatus.get(image.getStatus())).build();
-   }
-   
-   @Override
-   public String toString() {
-      return MoreObjects.toStringHelper(this).toString();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInRegionToSecurityGroup.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInRegionToSecurityGroup.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInRegionToSecurityGroup.java
new file mode 100644
index 0000000..08b4e2d
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInRegionToSecurityGroup.java
@@ -0,0 +1,73 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Map;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.domain.SecurityGroupBuilder;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.SecurityGroupInRegion;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+
+
+/**
+ * A function for transforming a Nova-specific SecurityGroup into a generic
+ * SecurityGroup object.
+ */
+@Singleton
+public class NovaSecurityGroupInRegionToSecurityGroup implements 
Function<SecurityGroupInRegion, SecurityGroup> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   protected final 
Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> 
baseConverter;
+   protected final Supplier<Map<String, Location>> locationIndex;
+
+   @Inject
+   public 
NovaSecurityGroupInRegionToSecurityGroup(Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup,
 SecurityGroup> baseConverter,
+                                                 Supplier<Map<String, 
Location>> locationIndex) {
+      this.baseConverter = checkNotNull(baseConverter, "baseConverter");
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+   }
+
+   @Override
+   public SecurityGroup apply(SecurityGroupInRegion group) {
+      SecurityGroupBuilder builder = 
SecurityGroupBuilder.fromSecurityGroup(baseConverter.apply(group.getSecurityGroup()));
+
+      Location region = locationIndex.get().get(group.getRegion());
+      checkState(region != null, "location %s not in locationIndex: %s", 
group.getRegion(), locationIndex.get());
+
+      builder.location(region);
+
+      builder.id(group.getRegion() + "/" + group.getSecurityGroup().getId());
+
+      return builder.build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
deleted file mode 100644
index 1991e77..0000000
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/NovaSecurityGroupInZoneToSecurityGroup.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.openstack.nova.v2_0.compute.functions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Map;
-
-import javax.annotation.Resource;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.compute.domain.SecurityGroup;
-import org.jclouds.compute.domain.SecurityGroupBuilder;
-import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.domain.Location;
-import org.jclouds.logging.Logger;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.inject.Inject;
-
-
-/**
- * A function for transforming a Nova-specific SecurityGroup into a generic
- * SecurityGroup object.
- */
-@Singleton
-public class NovaSecurityGroupInZoneToSecurityGroup implements 
Function<SecurityGroupInZone, SecurityGroup> {
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   protected Logger logger = Logger.NULL;
-
-   protected final 
Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup, SecurityGroup> 
baseConverter;
-   protected final Supplier<Map<String, Location>> locationIndex;
-
-   @Inject
-   public 
NovaSecurityGroupInZoneToSecurityGroup(Function<org.jclouds.openstack.nova.v2_0.domain.SecurityGroup,
 SecurityGroup> baseConverter,
-                                                 Supplier<Map<String, 
Location>> locationIndex) {
-      this.baseConverter = checkNotNull(baseConverter, "baseConverter");
-      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
-   }
-
-   @Override
-   public SecurityGroup apply(SecurityGroupInZone group) {
-      SecurityGroupBuilder builder = 
SecurityGroupBuilder.fromSecurityGroup(baseConverter.apply(group.getSecurityGroup()));
-
-      Location zone = locationIndex.get().get(group.getZone());
-      checkState(zone != null, "location %s not in locationIndex: %s", 
group.getZone(), locationIndex.get());
-
-      builder.location(zone);
-
-      builder.id(group.getZone() + "/" + group.getSecurityGroup().getId());
-
-      return builder.build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByRegionId.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByRegionId.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByRegionId.java
new file mode 100644
index 0000000..1a42952
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByRegionId.java
@@ -0,0 +1,73 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.filter;
+
+import java.util.Set;
+
+import javax.inject.Inject;
+
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.domain.LocationScope;
+import 
org.jclouds.openstack.nova.v2_0.compute.predicates.AllNodesInGroupTerminated;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+public class OrphanedGroupsByRegionId implements Function<Set<? extends 
NodeMetadata>, Multimap<String, String>> {
+   private final Predicate<RegionAndName> allNodesInGroupTerminated;
+
+   @Inject
+   protected OrphanedGroupsByRegionId(ComputeService computeService) {
+      this(new AllNodesInGroupTerminated(checkNotNull(computeService, 
"computeService")));
+   }
+
+   @VisibleForTesting
+   OrphanedGroupsByRegionId(Predicate<RegionAndName> 
allNodesInGroupTerminated) {
+      this.allNodesInGroupTerminated = checkNotNull(allNodesInGroupTerminated, 
"allNodesInGroupTerminated");
+   }
+
+   public Multimap<String, String> apply(Set<? extends NodeMetadata> 
deadNodes) {
+      Iterable<? extends NodeMetadata> nodesWithGroup = filter(deadNodes, 
NodePredicates.hasGroup());
+      Set<RegionAndName> regionAndGroupNames = 
ImmutableSet.copyOf(filter(transform(nodesWithGroup,
+               new Function<NodeMetadata, RegionAndName>() {
+
+                  @Override
+                  public RegionAndName apply(NodeMetadata input) {
+                     String regionId = input.getLocation().getScope() == 
LocationScope.HOST ? input.getLocation()
+                              .getParent().getId() : 
input.getLocation().getId();
+                     return RegionAndName.fromRegionAndName(regionId, 
input.getGroup());
+                  }
+
+               }), allNodesInGroupTerminated));
+      Multimap<String, String> regionToRegionAndGroupNames = 
Multimaps.transformValues(Multimaps.index(regionAndGroupNames,
+               RegionAndName.REGION_FUNCTION), RegionAndName.NAME_FUNCTION);
+      return regionToRegionAndGroupNames;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
deleted file mode 100644
index f49330f..0000000
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/OrphanedGroupsByZoneId.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.openstack.nova.v2_0.compute.functions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Sets.filter;
-
-import java.util.Set;
-
-import javax.inject.Inject;
-
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.predicates.NodePredicates;
-import org.jclouds.domain.LocationScope;
-import 
org.jclouds.openstack.nova.v2_0.compute.predicates.AllNodesInGroupTerminated;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-
-public class OrphanedGroupsByZoneId implements Function<Set<? extends 
NodeMetadata>, Multimap<String, String>> {
-   private final Predicate<ZoneAndName> allNodesInGroupTerminated;
-
-   @Inject
-   protected OrphanedGroupsByZoneId(ComputeService computeService) {
-      this(new AllNodesInGroupTerminated(checkNotNull(computeService, 
"computeService")));
-   }
-
-   @VisibleForTesting
-   OrphanedGroupsByZoneId(Predicate<ZoneAndName> allNodesInGroupTerminated) {
-      this.allNodesInGroupTerminated = checkNotNull(allNodesInGroupTerminated, 
"allNodesInGroupTerminated");
-   }
-
-   public Multimap<String, String> apply(Set<? extends NodeMetadata> 
deadNodes) {
-      Iterable<? extends NodeMetadata> nodesWithGroup = filter(deadNodes, 
NodePredicates.hasGroup());
-      Set<ZoneAndName> zoneAndGroupNames = 
ImmutableSet.copyOf(filter(transform(nodesWithGroup,
-               new Function<NodeMetadata, ZoneAndName>() {
-
-                  @Override
-                  public ZoneAndName apply(NodeMetadata input) {
-                     String zoneId = input.getLocation().getScope() == 
LocationScope.HOST ? input.getLocation()
-                              .getParent().getId() : 
input.getLocation().getId();
-                     return ZoneAndName.fromZoneAndName(zoneId, 
input.getGroup());
-                  }
-
-               }), allNodesInGroupTerminated));
-      Multimap<String, String> zoneToZoneAndGroupNames = 
Multimaps.transformValues(Multimaps.index(zoneAndGroupNames,
-               ZoneAndName.ZONE_FUNCTION), ZoneAndName.NAME_FUNCTION);
-      return zoneToZoneAndGroupNames;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
index cdbb0d9..94309c8 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
@@ -26,7 +26,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
 
 import com.google.common.base.Function;
@@ -36,25 +36,25 @@ import com.google.common.cache.LoadingCache;
 /**
  * A function for removing and deallocating an ip address from a node
  */
-public class RemoveFloatingIpFromNodeAndDeallocate implements 
Function<ZoneAndId, ZoneAndId> {
+public class RemoveFloatingIpFromNodeAndDeallocate implements 
Function<RegionAndId, RegionAndId> {
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
 
    private final NovaApi novaApi;
-   private final LoadingCache<ZoneAndId, Iterable<? extends FloatingIP>> 
floatingIpCache;
+   private final LoadingCache<RegionAndId, Iterable<? extends FloatingIP>> 
floatingIpCache;
 
    @Inject
    public RemoveFloatingIpFromNodeAndDeallocate(NovaApi novaApi,
-            @Named("FLOATINGIP") LoadingCache<ZoneAndId, Iterable<? extends 
FloatingIP>> floatingIpCache) {
+            @Named("FLOATINGIP") LoadingCache<RegionAndId, Iterable<? extends 
FloatingIP>> floatingIpCache) {
       this.novaApi = checkNotNull(novaApi, "novaApi");
       this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
    }
 
    @Override
-   public ZoneAndId apply(ZoneAndId id) {
-      FloatingIPApi floatingIpApi = 
novaApi.getFloatingIPExtensionForZone(id.getZone()).get();
+   public RegionAndId apply(RegionAndId id) {
+      FloatingIPApi floatingIpApi = 
novaApi.getFloatingIPApi(id.getRegion()).get();
       for (FloatingIP ip : floatingIpCache.getUnchecked(id)) {
          logger.debug(">> removing floatingIp(%s) from node(%s)", ip, id);
          floatingIpApi.removeFromServer(ip.getIp(), id.getId());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
index 46d4679..4f80b7b 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/SecurityGroupRuleToIpPermission.java
@@ -32,8 +32,8 @@ import org.jclouds.domain.Location;
 import org.jclouds.logging.Logger;
 import org.jclouds.net.domain.IpPermission;
 import org.jclouds.openstack.nova.v2_0.domain.SecurityGroupRule;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.SecurityGroupInRegion;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -50,16 +50,16 @@ public class SecurityGroupRuleToIpPermission implements 
Function<SecurityGroupRu
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final Predicate<AtomicReference<ZoneAndName>> 
returnSecurityGroupExistsInZone;
+   protected final Predicate<AtomicReference<RegionAndName>> 
returnSecurityGroupExistsInRegion;
    protected final Supplier<Map<String, Location>> locationIndex;
-   LoadingCache<ZoneAndName, SecurityGroupInZone> groupMap;
+   LoadingCache<RegionAndName, SecurityGroupInRegion> groupMap;
 
    @Inject
-   public SecurityGroupRuleToIpPermission(@Named("SECURITYGROUP_PRESENT") 
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
+   public SecurityGroupRuleToIpPermission(@Named("SECURITYGROUP_PRESENT") 
Predicate<AtomicReference<RegionAndName>> returnSecurityGroupExistsInRegion,
                                           Supplier<Map<String, Location>> 
locationIndex,
-                                          LoadingCache<ZoneAndName, 
SecurityGroupInZone> groupMap) {
-      this.returnSecurityGroupExistsInZone = 
checkNotNull(returnSecurityGroupExistsInZone,
-              "returnSecurityGroupExistsInZone");
+                                          LoadingCache<RegionAndName, 
SecurityGroupInRegion> groupMap) {
+      this.returnSecurityGroupExistsInRegion = 
checkNotNull(returnSecurityGroupExistsInRegion,
+              "returnSecurityGroupExistsInRegion");
       this.locationIndex = checkNotNull(locationIndex, "locationIndex");
       this.groupMap = checkNotNull(groupMap, "groupMap");
    }
@@ -71,26 +71,26 @@ public class SecurityGroupRuleToIpPermission implements 
Function<SecurityGroupRu
       builder.fromPort(rule.getFromPort());
       builder.toPort(rule.getToPort());
       if (rule.getGroup() != null) {
-         String zone = getFirst(filter(locationIndex.get().keySet(), 
isSecurityGroupInZone(rule.getGroup().getName())),
+         String region = getFirst(filter(locationIndex.get().keySet(), 
isSecurityGroupInRegion(rule.getGroup().getName())),
                  null);
-         if (zone != null) {
-            SecurityGroupInZone group = 
groupMap.getUnchecked(ZoneAndName.fromZoneAndName(zone, 
rule.getGroup().getName()));
-            builder.groupId(zone + "/" + group.getSecurityGroup().getId());
+         if (region != null) {
+            SecurityGroupInRegion group = 
groupMap.getUnchecked(RegionAndName.fromRegionAndName(region, 
rule.getGroup().getName()));
+            builder.groupId(region + "/" + group.getSecurityGroup().getId());
          }
       }
       if (rule.getIpRange() != null)
          builder.cidrBlock(rule.getIpRange());
-      
+
       return builder.build();
    }
 
-   protected Predicate<String> isSecurityGroupInZone(final String groupName) {
+   protected Predicate<String> isSecurityGroupInRegion(final String groupName) 
{
       return new Predicate<String>() {
 
          @Override
-         public boolean apply(String zone) {
-            AtomicReference<ZoneAndName> securityGroupInZoneRef = 
Atomics.newReference(ZoneAndName.fromZoneAndName(zone, groupName));
-            return 
returnSecurityGroupExistsInZone.apply(securityGroupInZoneRef);
+         public boolean apply(String region) {
+            AtomicReference<RegionAndName> securityGroupInRegionRef = 
Atomics.newReference(RegionAndName.fromRegionAndName(region, groupName));
+            return 
returnSecurityGroupExistsInRegion.apply(securityGroupInRegionRef);
          }
       };
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInRegionToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInRegionToNodeMetadata.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInRegionToNodeMetadata.java
new file mode 100644
index 0000000..2134bb2
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInRegionToNodeMetadata.java
@@ -0,0 +1,207 @@
+/*
+ * 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.openstack.nova.v2_0.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.newHashSet;
+import static 
org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
+import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName;
+import static org.jclouds.openstack.nova.v2_0.domain.Address.createV4;
+import static org.jclouds.openstack.nova.v2_0.domain.Address.createV6;
+
+import java.net.Inet4Address;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.ComputeMetadata;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.nova.v2_0.domain.Address;
+import org.jclouds.openstack.nova.v2_0.domain.Server;
+import org.jclouds.openstack.nova.v2_0.domain.Server.Status;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.ServerInRegion;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.util.InetAddresses2;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.net.InetAddresses;
+
+/**
+ * A function for transforming a nova-specific Server into a generic
+ * NodeMetadata object.
+ */
+public class ServerInRegionToNodeMetadata implements Function<ServerInRegion, 
NodeMetadata> {
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   protected Map<Status, org.jclouds.compute.domain.NodeMetadata.Status> 
toPortableNodeStatus;
+   protected final Supplier<Map<String, Location>> locationIndex;
+   protected final Supplier<Set<? extends Image>> images;
+   protected final Supplier<Set<? extends Hardware>> hardwares;
+   protected final GroupNamingConvention nodeNamingConvention;
+
+   @Inject
+   public ServerInRegionToNodeMetadata(Map<Server.Status, NodeMetadata.Status> 
toPortableNodeStatus,
+            Supplier<Map<String, Location>> locationIndex, @Memoized 
Supplier<Set<? extends Image>> images,
+            @Memoized Supplier<Set<? extends Hardware>> hardwares, 
GroupNamingConvention.Factory namingConvention) {
+      this.toPortableNodeStatus = checkNotNull(toPortableNodeStatus, 
"toPortableNodeStatus");
+      this.nodeNamingConvention = checkNotNull(namingConvention, 
"namingConvention").createWithoutPrefix();
+      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
+      this.images = checkNotNull(images, "images");
+      this.hardwares = checkNotNull(hardwares, "hardwares");
+   }
+
+   @Override
+   public NodeMetadata apply(ServerInRegion serverInRegion) {
+      Location region = locationIndex.get().get(serverInRegion.getRegion());
+      checkState(region != null, "location %s not in locationIndex: %s", 
serverInRegion.getRegion(), locationIndex.get());
+      Server from = serverInRegion.getServer();
+
+      NodeMetadataBuilder builder = new NodeMetadataBuilder();
+      builder.id(serverInRegion.slashEncode());
+      builder.providerId(from.getId());
+      builder.name(from.getName());
+      builder.hostname(from.getName());
+      builder.location(from.getHostId() != null ? new 
LocationBuilder().scope(LocationScope.HOST).id(from.getHostId())
+            .description(from.getHostId()).parent(region).build() : region);
+      builder.group(groupFromMapOrName(from.getMetadata(), from.getName(), 
nodeNamingConvention));
+      addMetadataAndParseTagsFromCommaDelimitedValue(builder, 
from.getMetadata());
+
+      if (from.getImage() != null) {
+         
builder.imageId(RegionAndId.fromRegionAndId(serverInRegion.getRegion(), 
from.getImage().getId()).slashEncode());
+      }
+
+      
builder.operatingSystem(findOperatingSystemForServerOrNull(serverInRegion));
+      builder.hardware(findHardwareForServerOrNull(serverInRegion));
+      builder.status(toPortableNodeStatus.get(from.getStatus()));
+
+      Set<Address> addresses = newHashSet(from.getAddresses().values());
+      if (from.getAccessIPv4() != null) {
+         addresses.add(createV4(from.getAccessIPv4()));
+      }
+      if (from.getAccessIPv6() != null) {
+         addresses.add(createV6(from.getAccessIPv6()));
+      }
+
+      builder.publicAddresses(
+            filter(
+                  transform(
+                        filter(addresses, not(isPrivateAddress)),
+                        AddressToStringTransformationFunction.INSTANCE),
+                  isInet4Address));
+
+      builder.privateAddresses(
+            filter(
+                  transform(
+                        filter(addresses, isPrivateAddress),
+                        AddressToStringTransformationFunction.INSTANCE),
+                  isInet4Address));
+
+      for (Link link : from.getLinks()) {
+         if (link.getRelation().equals(Link.Relation.SELF)) {
+            builder.uri(link.getHref());
+         }
+      }
+
+      return builder.build();
+   }
+
+   private static final Predicate<Address> isPrivateAddress = new 
Predicate<Address>() {
+      public boolean apply(Address in) {
+         return InetAddresses2.IsPrivateIPAddress.INSTANCE.apply(in.getAddr());
+      }
+   };
+
+   public static final Predicate<String> isInet4Address = new 
Predicate<String>() {
+      @Override
+      public boolean apply(String input) {
+         try {
+            // Note we can do this, as InetAddress is now on the white list
+            return InetAddresses.forString(input) instanceof Inet4Address;
+         } catch (IllegalArgumentException e) {
+            // could be a hostname
+            return true;
+         }
+      }
+
+   };
+
+   private enum AddressToStringTransformationFunction implements 
Function<Address, String> {
+      INSTANCE;
+      @Override
+      public String apply(Address address) {
+         return address.getAddr();
+      }
+   }
+
+   protected Hardware findHardwareForServerOrNull(ServerInRegion 
serverInRegion) {
+      return findObjectOfTypeForServerOrNull(hardwares.get(), "hardware", 
serverInRegion.getServer().getFlavor().getId(),
+            serverInRegion);
+   }
+
+   protected OperatingSystem findOperatingSystemForServerOrNull(ServerInRegion 
serverInRegion) {
+      if (serverInRegion.getServer().getImage() != null) {
+         Image image = findObjectOfTypeForServerOrNull(
+               images.get(), "image", 
serverInRegion.getServer().getImage().getId(), serverInRegion);
+
+         return (image != null) ? image.getOperatingSystem() : null;
+      } else {
+         return null;
+      }
+
+   }
+
+   public <T extends ComputeMetadata> T findObjectOfTypeForServerOrNull(Set<? 
extends T> supply, String type,
+         final String objectId, final RegionAndId serverInRegion) {
+      try {
+         return find(supply, new Predicate<T>() {
+            @Override
+            public boolean apply(T input) {
+               return 
input.getId().equals(RegionAndId.fromRegionAndId(serverInRegion.getRegion(), 
objectId).slashEncode());
+            }
+         });
+      } catch (NoSuchElementException e) {
+         logger.trace("could not find %s with id(%s) for server(%s)", type, 
objectId, serverInRegion);
+      }
+      return null;
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
deleted file mode 100644
index 57d66c2..0000000
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/ServerInZoneToNodeMetadata.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.openstack.nova.v2_0.compute.functions;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.find;
-import static com.google.common.collect.Iterables.transform;
-import static com.google.common.collect.Sets.newHashSet;
-import static 
org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromCommaDelimitedValue;
-import static org.jclouds.compute.util.ComputeServiceUtils.groupFromMapOrName;
-import static org.jclouds.openstack.nova.v2_0.domain.Address.createV4;
-import static org.jclouds.openstack.nova.v2_0.domain.Address.createV6;
-
-import java.net.Inet4Address;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-
-import javax.annotation.Resource;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.jclouds.collect.Memoized;
-import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.compute.domain.Hardware;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.NodeMetadataBuilder;
-import org.jclouds.compute.domain.OperatingSystem;
-import org.jclouds.compute.functions.GroupNamingConvention;
-import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.domain.Location;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.logging.Logger;
-import org.jclouds.openstack.nova.v2_0.domain.Address;
-import org.jclouds.openstack.nova.v2_0.domain.Server;
-import org.jclouds.openstack.nova.v2_0.domain.Server.Status;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ServerInZone;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
-import org.jclouds.openstack.v2_0.domain.Link;
-import org.jclouds.util.InetAddresses2;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.net.InetAddresses;
-
-/**
- * A function for transforming a nova-specific Server into a generic
- * NodeMetadata object.
- */
-public class ServerInZoneToNodeMetadata implements Function<ServerInZone, 
NodeMetadata> {
-   @Resource
-   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
-   protected Logger logger = Logger.NULL;
-   
-   protected Map<Status, org.jclouds.compute.domain.NodeMetadata.Status> 
toPortableNodeStatus;
-   protected final Supplier<Map<String, Location>> locationIndex;
-   protected final Supplier<Set<? extends Image>> images;
-   protected final Supplier<Set<? extends Hardware>> hardwares;
-   protected final GroupNamingConvention nodeNamingConvention;
-
-   @Inject
-   public ServerInZoneToNodeMetadata(Map<Server.Status, NodeMetadata.Status> 
toPortableNodeStatus,
-            Supplier<Map<String, Location>> locationIndex, @Memoized 
Supplier<Set<? extends Image>> images,
-            @Memoized Supplier<Set<? extends Hardware>> hardwares, 
GroupNamingConvention.Factory namingConvention) {
-      this.toPortableNodeStatus = checkNotNull(toPortableNodeStatus, 
"toPortableNodeStatus");
-      this.nodeNamingConvention = checkNotNull(namingConvention, 
"namingConvention").createWithoutPrefix();
-      this.locationIndex = checkNotNull(locationIndex, "locationIndex");
-      this.images = checkNotNull(images, "images");
-      this.hardwares = checkNotNull(hardwares, "hardwares");
-   }
-
-   @Override
-   public NodeMetadata apply(ServerInZone serverInZone) {
-      Location zone = locationIndex.get().get(serverInZone.getZone());
-      checkState(zone != null, "location %s not in locationIndex: %s", 
serverInZone.getZone(), locationIndex.get());
-      Server from = serverInZone.getServer();
-
-      NodeMetadataBuilder builder = new NodeMetadataBuilder();
-      builder.id(serverInZone.slashEncode());
-      builder.providerId(from.getId());
-      builder.name(from.getName());
-      builder.hostname(from.getName());
-      builder.location(from.getHostId() != null ? new 
LocationBuilder().scope(LocationScope.HOST).id(from.getHostId())
-            .description(from.getHostId()).parent(zone).build() : zone);
-      builder.group(groupFromMapOrName(from.getMetadata(), from.getName(), 
nodeNamingConvention));
-      addMetadataAndParseTagsFromCommaDelimitedValue(builder, 
from.getMetadata());
-
-      if (from.getImage() != null) {
-         builder.imageId(ZoneAndId.fromZoneAndId(serverInZone.getZone(), 
from.getImage().getId()).slashEncode());
-      }
-
-      
builder.operatingSystem(findOperatingSystemForServerOrNull(serverInZone));
-      builder.hardware(findHardwareForServerOrNull(serverInZone));
-      builder.status(toPortableNodeStatus.get(from.getStatus()));
-
-      Set<Address> addresses = newHashSet(from.getAddresses().values());
-      if (from.getAccessIPv4() != null) {
-         addresses.add(createV4(from.getAccessIPv4()));
-      }
-      if (from.getAccessIPv6() != null) {
-         addresses.add(createV6(from.getAccessIPv6()));
-      }
-
-      builder.publicAddresses(
-            filter(
-                  transform(
-                        filter(addresses, not(isPrivateAddress)),
-                        AddressToStringTransformationFunction.INSTANCE),
-                  isInet4Address));
-
-      builder.privateAddresses(
-            filter(
-                  transform(
-                        filter(addresses, isPrivateAddress),
-                        AddressToStringTransformationFunction.INSTANCE),
-                  isInet4Address));
-
-      for (Link link : from.getLinks()) {
-         if (link.getRelation().equals(Link.Relation.SELF)) {
-            builder.uri(link.getHref());
-         }
-      }
-      
-      return builder.build();
-   }
-   
-   private static final Predicate<Address> isPrivateAddress = new 
Predicate<Address>() {
-      public boolean apply(Address in) {
-         return InetAddresses2.IsPrivateIPAddress.INSTANCE.apply(in.getAddr());
-      }
-   };
-   
-   public static final Predicate<String> isInet4Address = new 
Predicate<String>() {
-      @Override
-      public boolean apply(String input) {
-         try {
-            // Note we can do this, as InetAddress is now on the white list
-            return InetAddresses.forString(input) instanceof Inet4Address;
-         } catch (IllegalArgumentException e) {
-            // could be a hostname
-            return true;
-         }
-      }
-
-   };
-
-   private enum AddressToStringTransformationFunction implements 
Function<Address, String> {
-      INSTANCE;
-      @Override
-      public String apply(Address address) {
-         return address.getAddr();
-      }
-   }
-
-   protected Hardware findHardwareForServerOrNull(ServerInZone serverInZone) {
-      return findObjectOfTypeForServerOrNull(hardwares.get(), "hardware", 
serverInZone.getServer().getFlavor().getId(),
-            serverInZone);
-   }
-
-   protected OperatingSystem findOperatingSystemForServerOrNull(ServerInZone 
serverInZone) {
-      if (serverInZone.getServer().getImage() != null) {
-         Image image = findObjectOfTypeForServerOrNull(
-               images.get(), "image", 
serverInZone.getServer().getImage().getId(), serverInZone);
-
-         return (image != null) ? image.getOperatingSystem() : null;
-      } else {
-         return null;
-      }
-
-   }
-
-   public <T extends ComputeMetadata> T findObjectOfTypeForServerOrNull(Set<? 
extends T> supply, String type,
-         final String objectId, final ZoneAndId serverInZone) {
-      try {
-         return find(supply, new Predicate<T>() {
-            @Override
-            public boolean apply(T input) {
-               return 
input.getId().equals(ZoneAndId.fromZoneAndId(serverInZone.getZone(), 
objectId).slashEncode());
-            }
-         });
-      } catch (NoSuchElementException e) {
-         logger.trace("could not find %s with id(%s) for server(%s)", type, 
objectId, serverInZone);
-      }
-      return null;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/CreateUniqueKeyPair.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/CreateUniqueKeyPair.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/CreateUniqueKeyPair.java
index 71852dc..9d521c4 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/CreateUniqueKeyPair.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/CreateUniqueKeyPair.java
@@ -28,7 +28,7 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
 import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi;
 
 import com.google.common.base.Optional;
@@ -36,7 +36,7 @@ import com.google.common.cache.CacheLoader;
 import com.google.inject.Inject;
 
 @Singleton
-public class CreateUniqueKeyPair extends CacheLoader<ZoneAndName, KeyPair> {
+public class CreateUniqueKeyPair extends CacheLoader<RegionAndName, KeyPair> {
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
@@ -50,15 +50,15 @@ public class CreateUniqueKeyPair extends 
CacheLoader<ZoneAndName, KeyPair> {
    }
 
    @Override
-   public KeyPair load(ZoneAndName zoneAndName) {
-      String zoneId = checkNotNull(zoneAndName, "zoneAndName").getZone();
-      String prefix = zoneAndName.getName();
+   public KeyPair load(RegionAndName regionAndName) {
+      String regionId = checkNotNull(regionAndName, 
"regionAndName").getRegion();
+      String prefix = regionAndName.getName();
 
-      Optional<? extends KeyPairApi> api = 
novaApi.getKeyPairExtensionForZone(zoneId);
-      checkArgument(api.isPresent(), "Key pairs are required, but the 
extension is not available in zone %s!",
-            zoneId);
+      Optional<? extends KeyPairApi> api = novaApi.getKeyPairApi(regionId);
+      checkArgument(api.isPresent(), "Key pairs are required, but the 
extension is not available in region %s!",
+            regionId);
 
-      logger.debug(">> creating keyPair zone(%s) prefix(%s)", zoneId, prefix);
+      logger.debug(">> creating keyPair region(%s) prefix(%s)", regionId, 
prefix);
 
       KeyPair keyPair = null;
       while (keyPair == null) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/FindSecurityGroupOrCreate.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/FindSecurityGroupOrCreate.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/FindSecurityGroupOrCreate.java
index d072e37..23ee514 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/FindSecurityGroupOrCreate.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/FindSecurityGroupOrCreate.java
@@ -23,60 +23,60 @@ import java.util.concurrent.atomic.AtomicReference;
 import javax.inject.Inject;
 import javax.inject.Named;
 
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
-import 
org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.SecurityGroupInRegion;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionSecurityGroupNameAndPorts;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.cache.CacheLoader;
 import com.google.common.util.concurrent.Atomics;
 
-public class FindSecurityGroupOrCreate extends CacheLoader<ZoneAndName, 
SecurityGroupInZone> {
+public class FindSecurityGroupOrCreate extends CacheLoader<RegionAndName, 
SecurityGroupInRegion> {
 
-   protected final Predicate<AtomicReference<ZoneAndName>> 
returnSecurityGroupExistsInZone;
-   protected final Function<ZoneSecurityGroupNameAndPorts, 
SecurityGroupInZone> groupCreator;
+   protected final Predicate<AtomicReference<RegionAndName>> 
returnSecurityGroupExistsInRegion;
+   protected final Function<RegionSecurityGroupNameAndPorts, 
SecurityGroupInRegion> groupCreator;
 
    @Inject
    public FindSecurityGroupOrCreate(
-            @Named("SECURITYGROUP_PRESENT") 
Predicate<AtomicReference<ZoneAndName>> returnSecurityGroupExistsInZone,
-            Function<ZoneSecurityGroupNameAndPorts, SecurityGroupInZone> 
groupCreator) {
-      this.returnSecurityGroupExistsInZone = 
checkNotNull(returnSecurityGroupExistsInZone,
-               "returnSecurityGroupExistsInZone");
+            @Named("SECURITYGROUP_PRESENT") 
Predicate<AtomicReference<RegionAndName>> returnSecurityGroupExistsInRegion,
+            Function<RegionSecurityGroupNameAndPorts, SecurityGroupInRegion> 
groupCreator) {
+      this.returnSecurityGroupExistsInRegion = 
checkNotNull(returnSecurityGroupExistsInRegion,
+               "returnSecurityGroupExistsInRegion");
       this.groupCreator = checkNotNull(groupCreator, "groupCreator");
    }
 
    @Override
-   public SecurityGroupInZone load(ZoneAndName in) {
-      AtomicReference<ZoneAndName> securityGroupInZoneRef = 
Atomics.newReference(checkNotNull(in,
-               "zoneSecurityGroupNameAndPorts"));
-      if (returnSecurityGroupExistsInZone.apply(securityGroupInZoneRef)) {
-         return returnExistingSecurityGroup(securityGroupInZoneRef);
+   public SecurityGroupInRegion load(RegionAndName in) {
+      AtomicReference<RegionAndName> securityGroupInRegionRef = 
Atomics.newReference(checkNotNull(in,
+               "regionSecurityGroupNameAndPorts"));
+      if (returnSecurityGroupExistsInRegion.apply(securityGroupInRegionRef)) {
+         return returnExistingSecurityGroup(securityGroupInRegionRef);
       } else {
          return createNewSecurityGroup(in);
       }
    }
 
-   private SecurityGroupInZone 
returnExistingSecurityGroup(AtomicReference<ZoneAndName> 
securityGroupInZoneRef) {
-      ZoneAndName securityGroupInZone = securityGroupInZoneRef.get();
-      checkState(securityGroupInZone instanceof SecurityGroupInZone,
+   private SecurityGroupInRegion 
returnExistingSecurityGroup(AtomicReference<RegionAndName> 
securityGroupInRegionRef) {
+      RegionAndName securityGroupInRegion = securityGroupInRegionRef.get();
+      checkState(securityGroupInRegion instanceof SecurityGroupInRegion,
                "programming error: predicate %s should update the atomic 
reference to the actual security group found",
-               returnSecurityGroupExistsInZone);
-      return SecurityGroupInZone.class.cast(securityGroupInZone);
+               returnSecurityGroupExistsInRegion);
+      return SecurityGroupInRegion.class.cast(securityGroupInRegion);
    }
 
-   private SecurityGroupInZone createNewSecurityGroup(ZoneAndName in) {
+   private SecurityGroupInRegion createNewSecurityGroup(RegionAndName in) {
       checkState(
-               checkNotNull(in, "zoneSecurityGroupNameAndPorts") instanceof 
ZoneSecurityGroupNameAndPorts,
-               "programming error: when issuing get to this cacheloader, you 
need to pass an instance of ZoneSecurityGroupNameAndPorts, not %s",
+               checkNotNull(in, "regionSecurityGroupNameAndPorts") instanceof 
RegionSecurityGroupNameAndPorts,
+               "programming error: when issuing get to this cacheloader, you 
need to pass an instance of RegionSecurityGroupNameAndPorts, not %s",
                in);
-      ZoneSecurityGroupNameAndPorts zoneSecurityGroupNameAndPorts = 
ZoneSecurityGroupNameAndPorts.class.cast(in);
-      return groupCreator.apply(zoneSecurityGroupNameAndPorts);
+      RegionSecurityGroupNameAndPorts regionSecurityGroupNameAndPorts = 
RegionSecurityGroupNameAndPorts.class.cast(in);
+      return groupCreator.apply(regionSecurityGroupNameAndPorts);
    }
 
    @Override
    public String toString() {
-      return "returnExistingSecurityGroupInZoneOrCreateAsNeeded()";
+      return "returnExistingSecurityGroupInRegionOrCreateAsNeeded()";
    }
 
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
index e4a9caa..1487a13 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
@@ -21,7 +21,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
 
 import com.google.common.base.Optional;
@@ -30,12 +30,12 @@ import com.google.common.cache.CacheLoader;
 import com.google.common.collect.ImmutableSet;
 
 /**
- * Each zone may or may not have the floating ip function present. In order to 
safely proceed, we
- * must allow the user to determine if a zone has floating ip services before 
attempting to use
+ * Each region may or may not have the floating ip function present. In order 
to safely proceed, we
+ * must allow the user to determine if a region has floating ip services 
before attempting to use
  * them.
  */
 @Singleton
-public class LoadFloatingIpsForInstance extends CacheLoader<ZoneAndId, 
Iterable<? extends FloatingIP>> {
+public class LoadFloatingIpsForInstance extends CacheLoader<RegionAndId, 
Iterable<? extends FloatingIP>> {
    private final NovaApi api;
 
    @Inject
@@ -44,9 +44,9 @@ public class LoadFloatingIpsForInstance extends 
CacheLoader<ZoneAndId, Iterable<
    }
 
    @Override
-   public Iterable<? extends FloatingIP> load(final ZoneAndId key) throws 
Exception {
-      String zone = key.getZone();
-      Optional<? extends FloatingIPApi> ipApiOptional = 
api.getFloatingIPExtensionForZone(zone);
+   public Iterable<? extends FloatingIP> load(final RegionAndId key) throws 
Exception {
+      String region = key.getRegion();
+      Optional<? extends FloatingIPApi> ipApiOptional = 
api.getFloatingIPApi(region);
       if (ipApiOptional.isPresent()) {
          return ipApiOptional.get().list().filter(
                   new Predicate<FloatingIP>() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
index 2778afc..519c0c0 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
@@ -196,10 +196,10 @@ public class NovaTemplateOptions extends TemplateOptions 
implements Cloneable {
 
    /**
     * <h3>Note</h3>
-    * 
-    * This requires that {@link NovaApi#getExtensionForZone(String)} to return
+    *
+    * This requires that {@link NovaApi#getExtensionForRegion(String)} to 
return
     * {@link Optional#isPresent present}
-    * 
+    *
     * @return true if auto assignment of a floating ip to each vm is enabled
     */
    public boolean shouldAutoAssignFloatingIp() {
@@ -229,7 +229,7 @@ public class NovaTemplateOptions extends TemplateOptions 
implements Cloneable {
    /**
     * <h3>Note</h3>
     *
-    * This requires that {@link NovaApi#getKeyPairExtensionForZone(String)} to 
return
+    * This requires that {@link NovaApi#getKeyPairExtensionApi(String)} to 
return
     * {@link Optional#isPresent present}
     *
     * @return true if auto generation of keypairs is enabled
@@ -241,7 +241,7 @@ public class NovaTemplateOptions extends TemplateOptions 
implements Cloneable {
    /**
     * if unset, generate a default group prefixed with {@link jclouds#} 
according
     * to {@link #getInboundPorts()}
-    * 
+    *
     * @see 
org.jclouds.openstack.nova.v2_0.options.CreateServerOptions#getSecurityGroupNames
     * @deprecated Use {@link TemplateOptions#getGroups()} instead.
     */
@@ -301,14 +301,14 @@ public class NovaTemplateOptions extends TemplateOptions 
implements Cloneable {
       }
 
       /**
-       * @see NovaTemplateOptions#shouldGenerateKeyPair() 
+       * @see NovaTemplateOptions#shouldGenerateKeyPair()
        */
       public static NovaTemplateOptions generateKeyPair(boolean enable) {
          return new NovaTemplateOptions().generateKeyPair(enable);
       }
 
       /**
-       * @see NovaTemplateOptions#getKeyPairName() 
+       * @see NovaTemplateOptions#getKeyPairName()
        */
       public static NovaTemplateOptions keyPairName(String keyPairName) {
          return new NovaTemplateOptions().keyPairName(keyPairName);
@@ -645,8 +645,8 @@ public class NovaTemplateOptions extends TemplateOptions 
implements Cloneable {
    }
 
    /**
-    * OpenStack can be configured to write metadata to a special configuration 
drive that will be 
-    * attached to the instance when it boots. The instance can retrieve any 
information that would 
+    * OpenStack can be configured to write metadata to a special configuration 
drive that will be
+    * attached to the instance when it boots. The instance can retrieve any 
information that would
     * normally be available through the metadata service by mounting this disk 
and reading files from it.
     * To enable the config drive, set this parameter to "true".
     * This has to be enabled for user data cases.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/predicates/AllNodesInGroupTerminated.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/predicates/AllNodesInGroupTerminated.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/predicates/AllNodesInGroupTerminated.java
index a4b63e9..6fb1d58 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/predicates/AllNodesInGroupTerminated.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/predicates/AllNodesInGroupTerminated.java
@@ -28,15 +28,15 @@ import javax.inject.Inject;
 
 import org.jclouds.compute.ComputeService;
 import org.jclouds.compute.domain.ComputeMetadata;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 
-public class AllNodesInGroupTerminated implements Predicate<ZoneAndName> {
+public class AllNodesInGroupTerminated implements Predicate<RegionAndName> {
    private final ComputeService computeService;
 
-   
+
    //TODO: TESTME
    @Inject
    public AllNodesInGroupTerminated(ComputeService computeService) {
@@ -44,10 +44,10 @@ public class AllNodesInGroupTerminated implements 
Predicate<ZoneAndName> {
    }
 
    @Override
-   public boolean apply(ZoneAndName input) {
-      // new nodes can have the zone as their location, existing nodes, the 
parent is the
+   public boolean apply(RegionAndName input) {
+      // new nodes can have the region as their location, existing nodes, the 
parent is the
       // location
-      return 
all(computeService.listNodesDetailsMatching(Predicates.<ComputeMetadata> 
or(locationId(input.getZone()),
-               parentLocationId(input.getZone()))), 
and(inGroup(input.getName()), TERMINATED));
+      return 
all(computeService.listNodesDetailsMatching(Predicates.<ComputeMetadata> 
or(locationId(input.getRegion()),
+               parentLocationId(input.getRegion()))), 
and(inGroup(input.getName()), TERMINATED));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
index 79bd021..9361999 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -45,9 +45,9 @@ import 
org.jclouds.openstack.nova.v2_0.compute.functions.AllocateAndAddFloatingI
 import 
org.jclouds.openstack.nova.v2_0.compute.options.NodeAndNovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
-import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
-import 
org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.SecurityGroupInRegion;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndName;
+import 
org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionSecurityGroupNameAndPorts;
 
 import com.google.common.base.Function;
 import com.google.common.base.Throwables;
@@ -64,8 +64,8 @@ public class 
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
          CreateNodesWithGroupEncodedIntoNameThenAddToSet {
 
    private final AllocateAndAddFloatingIpToNode createAndAddFloatingIpToNode;
-   private final LoadingCache<ZoneAndName, SecurityGroupInZone> 
securityGroupCache;
-   private final LoadingCache<ZoneAndName, KeyPair> keyPairCache;
+   private final LoadingCache<RegionAndName, SecurityGroupInRegion> 
securityGroupCache;
+   private final LoadingCache<RegionAndName, KeyPair> keyPairCache;
    private final NovaApi novaApi;
 
    @Inject
@@ -76,8 +76,8 @@ public class 
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
             CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory 
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
             @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService 
userExecutor,
             AllocateAndAddFloatingIpToNode createAndAddFloatingIpToNode,
-            LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
-            LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaApi novaApi) {
+            LoadingCache<RegionAndName, SecurityGroupInRegion> 
securityGroupCache,
+            LoadingCache<RegionAndName, KeyPair> keyPairCache, NovaApi 
novaApi) {
       super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, 
userExecutor,
                customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
       this.securityGroupCache = checkNotNull(securityGroupCache, 
"securityGroupCache");
@@ -97,21 +97,21 @@ public class 
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
 
       assert template.getOptions().equals(templateOptions) : "options didn't 
clone properly";
 
-      String zone = mutableTemplate.getLocation().getId();
+      String region = mutableTemplate.getLocation().getId();
 
       if (templateOptions.shouldAutoAssignFloatingIp()) {
-         checkArgument(novaApi.getFloatingIPExtensionForZone(zone).isPresent(),
+         checkArgument(novaApi.getFloatingIPApi(region).isPresent(),
                   "Floating IPs are required by options, but the extension is 
not available! options: %s",
                   templateOptions);
       }
 
-      boolean keyPairExtensionPresent = 
novaApi.getKeyPairExtensionForZone(zone).isPresent();
+      boolean keyPairExtensionPresent = 
novaApi.getKeyPairApi(region).isPresent();
       if (templateOptions.shouldGenerateKeyPair()) {
          checkArgument(keyPairExtensionPresent,
                   "Key Pairs are required by options, but the extension is not 
available! options: %s", templateOptions);
-         KeyPair keyPair = 
keyPairCache.getUnchecked(ZoneAndName.fromZoneAndName(zone, 
namingConvention.create()
+         KeyPair keyPair = 
keyPairCache.getUnchecked(RegionAndName.fromRegionAndName(region, 
namingConvention.create()
                   .sharedNameForGroup(group)));
-         keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, 
keyPair.getName()), keyPair);
+         keyPairCache.asMap().put(RegionAndName.fromRegionAndName(region, 
keyPair.getName()), keyPair);
          templateOptions.keyPairName(keyPair.getName());
       } else if (templateOptions.getKeyPairName() != null) {
          checkArgument(keyPairExtensionPresent,
@@ -120,11 +120,11 @@ public class 
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
             String pem = templateOptions.getLoginPrivateKey();
             KeyPair keyPair = 
KeyPair.builder().name(templateOptions.getKeyPairName())
                      
.fingerprint(fingerprintPrivateKey(pem)).privateKey(pem).build();
-            keyPairCache.asMap().put(ZoneAndName.fromZoneAndName(zone, 
keyPair.getName()), keyPair);
+            keyPairCache.asMap().put(RegionAndName.fromRegionAndName(region, 
keyPair.getName()), keyPair);
          }
       }
 
-      boolean securityGroupExtensionPresent = 
novaApi.getSecurityGroupExtensionForZone(zone).isPresent();
+      boolean securityGroupExtensionPresent = 
novaApi.getSecurityGroupApi(region).isPresent();
       List<Integer> inboundPorts = 
Ints.asList(templateOptions.getInboundPorts());
       if (!templateOptions.getGroups().isEmpty()) {
          checkArgument(securityGroupExtensionPresent,
@@ -134,7 +134,7 @@ public class 
ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
          if (templateOptions.getGroups().isEmpty() && !inboundPorts.isEmpty()) 
{
             String securityGroupName = 
namingConvention.create().sharedNameForGroup(group);
             try {
-               securityGroupCache.get(new ZoneSecurityGroupNameAndPorts(zone, 
securityGroupName, inboundPorts));
+               securityGroupCache.get(new 
RegionSecurityGroupNameAndPorts(region, securityGroupName, inboundPorts));
             } catch (ExecutionException e) {
                throw Throwables.propagate(e.getCause());
             }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
index d763406..0956c48 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaHttpApiModule.java
@@ -97,12 +97,12 @@ public class NovaHttpApiModule extends 
HttpApiModule<NovaApi> {
 
    @Provides
    @Singleton
-   public LoadingCache<String, Set<? extends Extension>> 
provideExtensionsByZone(final Provider<NovaApi> novaApi) {
+   public LoadingCache<String, Set<? extends Extension>> 
provideExtensionsByRegion(final Provider<NovaApi> novaApi) {
       return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
             .build(new CacheLoader<String, Set<? extends Extension>>() {
                @Override
                public Set<? extends Extension> load(String key) throws 
Exception {
-                  return novaApi.get().getExtensionApiForZone(key).list();
+                  return novaApi.get().getExtensionApi(key).list();
                }
             });
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/HostAggregate.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/HostAggregate.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/HostAggregate.java
index 1c8673c..d5e75a3 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/HostAggregate.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/HostAggregate.java
@@ -36,16 +36,16 @@ import com.google.common.collect.ImmutableSet;
 
 /**
  * Aggregates can be manipulated using the Aggregate Extension to Nova (alias 
"OS-AGGREGATES")
- * 
+ *
  * @see org.jclouds.openstack.nova.v2_0.extensions.HostAggregateApi
 */
 public class HostAggregate {
 
-   public static Builder<?> builder() { 
+   public static Builder<?> builder() {
       return new ConcreteBuilder();
    }
-   
-   public Builder<?> toBuilder() { 
+
+   public Builder<?> toBuilder() {
       return new ConcreteBuilder().fromHostAggregate(this);
    }
 
@@ -60,8 +60,8 @@ public class HostAggregate {
       protected Date created;
       protected Date updated;
       protected Map<String, String> metadata = ImmutableMap.of();
-   
-      /** 
+
+      /**
        * @see HostAggregate#getId()
        */
       public T id(String id) {
@@ -69,7 +69,7 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getName()
        */
       public T name(String name) {
@@ -77,7 +77,7 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getAvailabilityZone()
        */
       public T availabilityZone(String availabilityZone) {
@@ -85,11 +85,11 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getHosts()
        */
       public T hosts(Set<String> hosts) {
-         this.hosts = ImmutableSet.copyOf(checkNotNull(hosts, "hosts"));      
+         this.hosts = ImmutableSet.copyOf(checkNotNull(hosts, "hosts"));
          return self();
       }
 
@@ -97,7 +97,7 @@ public class HostAggregate {
          return hosts(ImmutableSet.copyOf(in));
       }
 
-      /** 
+      /**
        * @see HostAggregate#getState()
        */
       public T state(String state) {
@@ -105,7 +105,7 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getCreated()
        */
       public T created(Date created) {
@@ -113,7 +113,7 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getUpdated()
        */
       public T updated(Date updated) {
@@ -121,18 +121,18 @@ public class HostAggregate {
          return self();
       }
 
-      /** 
+      /**
        * @see HostAggregate#getMetadata()
        */
       public T metadata(Map<String, String> metadata) {
-         this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, 
"metadata"));     
+         this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, 
"metadata"));
          return self();
       }
 
       public HostAggregate build() {
          return new HostAggregate(id, name, availabilityZone, hosts, state, 
created, updated, metadata);
       }
-      
+
       public T fromHostAggregate(HostAggregate in) {
          return this
                   .id(in.getId())
@@ -174,11 +174,11 @@ public class HostAggregate {
       this.id = checkNotNull(id, "id");
       this.name = checkNotNull(name, "name");
       this.availabilityZone = checkNotNull(availabilityZone, 
"availabilityZone");
-      this.hosts = hosts == null ? ImmutableSet.<String>of() : 
ImmutableSet.copyOf(hosts);      
+      this.hosts = hosts == null ? ImmutableSet.<String>of() : 
ImmutableSet.copyOf(hosts);
       this.state = checkNotNull(state, "state");
       this.created = checkNotNull(created, "created");
       this.updated = Optional.fromNullable(updated);
-      this.metadata = metadata == null ? ImmutableMap.<String, String>of() : 
ImmutableMap.copyOf(metadata);     
+      this.metadata = metadata == null ? ImmutableMap.<String, String>of() : 
ImmutableMap.copyOf(metadata);
    }
 
    public String getId() {
@@ -190,8 +190,6 @@ public class HostAggregate {
    }
 
    /**
-    * note: an "Availability Zone" is different from a Nova "Zone"
-    * 
     * @return the availability zone this aggregate is in
     */
    public String getAvailabilityZone() {
@@ -237,12 +235,12 @@ public class HostAggregate {
                && Objects.equal(this.updated, that.updated)
                && Objects.equal(this.metadata, that.metadata);
    }
-   
+
    protected ToStringHelper string() {
       return MoreObjects.toStringHelper(this)
             .add("id", id).add("name", name).add("availabilityZone", 
availabilityZone).add("hosts", hosts).add("state", state).add("created", 
created).add("updated", updated).add("metadata", metadata);
    }
-   
+
    @Override
    public String toString() {
       return string().toString();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java
new file mode 100644
index 0000000..e59e4dd
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java
@@ -0,0 +1,69 @@
+/*
+ * 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.openstack.nova.v2_0.domain.regionscoped;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.gson.annotations.SerializedName;
+
+import java.beans.ConstructorProperties;
+
+public class AvailabilityZone {
+
+   @SerializedName("zoneName")
+   private final String name;
+   private final ZoneState state;
+
+   @ConstructorProperties({"zoneName" , "zoneState"})
+   protected AvailabilityZone(String name, ZoneState state) {
+      this.name = name;
+      this.state = state;
+   }
+
+   public String getName() {
+      return name;
+   }
+
+   public ZoneState getState() {
+      return state;
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name, state);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this != obj) return false;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      AvailabilityZone that = AvailabilityZone.class.cast(obj);
+      return Objects.equal(this.name, that.name) && Objects.equal(this.state, 
that.state);
+   }
+
+   protected MoreObjects.ToStringHelper string() {
+      return MoreObjects.toStringHelper(this)
+            .add("name", name)
+            .add("state", state);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/FlavorInRegion.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/FlavorInRegion.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/FlavorInRegion.java
new file mode 100644
index 0000000..5617673
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/FlavorInRegion.java
@@ -0,0 +1,43 @@
+/*
+ * 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.openstack.nova.v2_0.domain.regionscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.openstack.nova.v2_0.domain.Flavor;
+
+public class FlavorInRegion extends RegionAndId {
+   protected final Flavor image;
+
+   public FlavorInRegion(Flavor image, String regionId) {
+      super(regionId, checkNotNull(image, "image").getId());
+      this.image = image;
+   }
+
+   public Flavor getFlavor() {
+      return image;
+   }
+
+   // superclass hashCode/equals are good enough, and help us use RegionAndId 
and FlavorInRegion
+   // interchangeably as Map keys
+
+   @Override
+   public String toString() {
+      return "[image=" + image + ", regionId=" + regionId + "]";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/744cd5d7/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/ImageInRegion.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/ImageInRegion.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/ImageInRegion.java
new file mode 100644
index 0000000..e1bf68e
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/ImageInRegion.java
@@ -0,0 +1,43 @@
+/*
+ * 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.openstack.nova.v2_0.domain.regionscoped;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.openstack.nova.v2_0.domain.Image;
+
+public class ImageInRegion extends RegionAndId {
+   protected final Image image;
+
+   public ImageInRegion(Image image, String regionId) {
+      super(regionId, checkNotNull(image, "image").getId());
+      this.image = image;
+   }
+
+   public Image getImage() {
+      return image;
+   }
+
+   // superclass hashCode/equals are good enough, and help us use RegionAndId 
and ImageInRegion
+   // interchangeably as Map keys
+
+   @Override
+   public String toString() {
+      return "[image=" + image + ", regionId=" + regionId + "]";
+   }
+
+}

Reply via email to