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 2017/12/08 12:56:21 UTC

[6/8] jclouds git commit: Initial work towards Keystone V3 authentication

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
new file mode 100644
index 0000000..9761da0
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
@@ -0,0 +1,160 @@
+/*
+ * 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.keystone.catalog.config;
+
+import static org.jclouds.util.Suppliers2.getLastValueInMap;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.location.Provider;
+import org.jclouds.location.suppliers.ImplicitLocationSupplier;
+import org.jclouds.location.suppliers.LocationsSupplier;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.RegionIdsSupplier;
+import org.jclouds.location.suppliers.all.RegionToProvider;
+import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
+import org.jclouds.location.suppliers.implicit.FirstRegion;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
+import org.jclouds.openstack.keystone.v3.catalog.V3ServiceCatalog;
+import org.jclouds.rest.annotations.ApiVersion;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Maps;
+import com.google.inject.AbstractModule;
+import com.google.inject.Injector;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+import com.google.inject.assistedinject.FactoryModuleBuilder;
+
+public class ServiceCatalogModule extends AbstractModule {
+
+   @Override
+   protected void configure() {
+      
+   }
+   
+   @Provides
+   @Singleton
+   protected final Supplier<List<ServiceEndpoint>> provideServiceCatalog(Injector i,
+         @Named(KeystoneProperties.KEYSTONE_VERSION) String keystoneVersion) {
+      Map<String, Supplier<List<ServiceEndpoint>>> serviceCatalogs = Maps.newHashMap();
+      serviceCatalogs.put("2", i.getInstance(V2ServiceCatalog.class));
+      serviceCatalogs.put("3", i.getInstance(V3ServiceCatalog.class));
+      return serviceCatalogs.get(keystoneVersion);
+   }
+   
+   /**
+    * For global services who have no regions, such as DNS. To use, do the following
+    * <ol>
+    * <li>add this module to your {@link org.jclouds.apis.ApiMetadata#getDefaultModules()}</li>
+    * <li>create a service-specific annotation, such as {@code @CloudDNS}, and make sure that has the meta-annotation
+    * {@link javax.inject.Qualifier}</li>
+    * <li>add the above annotation to any {@code Api} classes by placing it on the type. ex.
+    * {@code @Endpoint(CloudDNS.class)}</li>
+    * <li>add the following to your {@link org.jclouds.rest.config.RestClientModule}</li>
+    *
+    * <pre>
+    * bind(new TypeLiteral&lt;Supplier&lt;URI&gt;&gt;() {
+    * }).annotatedWith(CloudDNS.class).to(new TypeLiteral&lt;Supplier&lt;URI&gt;&gt;() {
+    * });
+    * </pre>
+    */
+   public static class ProviderModule extends AbstractModule {
+      @Override
+      protected void configure() {
+         install(new FactoryModuleBuilder().build(LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
+      }
+
+      @Provides
+      @Singleton
+      protected final Supplier<URI> provideZoneIdToURISupplierForApiVersion(
+            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
+            LocationIdToURIFromAccessForTypeAndVersion.Factory factory) {
+         return getLastValueInMap(factory.createForApiTypeAndVersion(serviceType, apiVersion));
+      }
+
+      @Provides
+      @Singleton
+      final Function<ServiceEndpoint, String> provideProvider(@Provider final String provider) {
+         return new Function<ServiceEndpoint, String>() {
+            @Override
+            public String apply(ServiceEndpoint in) {
+               return provider;
+            }
+         };
+      }
+   }
+
+   public static class RegionModule extends AbstractModule {
+      @Override
+      protected void configure() {
+         install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
+               RegionIdToURIFromAccessForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
+         install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
+               RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
+         // Dynamically build the region list as opposed to from properties
+         bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
+         bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
+         bind(LocationsSupplier.class).to(RegionToProvider.class).in(Scopes.SINGLETON);
+      }
+
+      @Provides
+      @Singleton
+      protected final RegionIdToURISupplier guiceProvideRegionIdToURISupplierForApiVersion(
+              @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
+              RegionIdToURISupplier.Factory factory) {
+         return provideRegionIdToURISupplierForApiVersion(serviceType, apiVersion, factory);
+      }
+
+      // Supply the region to id map from keystone, based on the servicetype and
+      // api version in config
+      protected RegionIdToURISupplier provideRegionIdToURISupplierForApiVersion(
+            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
+            RegionIdToURISupplier.Factory factory) {
+         return factory.createForApiTypeAndVersion(serviceType, apiVersion);
+      }
+
+      @Provides
+      @Singleton
+      protected final RegionIdToAdminURISupplier guiceProvideRegionIdToAdminURISupplierForApiVersion(
+              @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
+              RegionIdToAdminURISupplier.Factory factory) {
+         return provideRegionIdToAdminURISupplierForApiVersion(serviceType, apiVersion, factory);
+      }
+
+      // Supply the region to id to AdminURL map from keystone, based on the
+      // servicetype and api version in config
+      protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion(
+            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
+            RegionIdToAdminURISupplier.Factory factory) {
+         return factory.createForApiTypeAndVersion(serviceType, apiVersion);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java
new file mode 100644
index 0000000..3ee1d78
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminEndpointResolutionStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ * Given a sets of endpoints for a particular service and version, return the
+ * URL of the admin endpoint to be used to connect to the service.
+ */
+@ImplementedBy(AdminURL.class)
+public interface AdminEndpointResolutionStrategy extends ServiceEndpointResolutionStrategy {
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java
new file mode 100644
index 0000000..b727ca1
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/AdminURL.java
@@ -0,0 +1,34 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.ADMIN;
+
+import javax.inject.Singleton;
+
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+import com.google.common.base.Predicate;
+
+@Singleton
+public class AdminURL extends BaseEndpointResolutionStrategy implements AdminEndpointResolutionStrategy {
+
+   @Override
+   protected Predicate<ServiceEndpoint> filter() {
+      return withIface(ADMIN);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java
new file mode 100644
index 0000000..23fe16d
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/BaseEndpointResolutionStrategy.java
@@ -0,0 +1,62 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import static com.google.common.collect.Iterables.tryFind;
+
+import java.net.URI;
+import java.util.Collection;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+
+/**
+ * Resolves the endpoint to be used to connect to a service based on a given
+ * predicate.
+ */
+public abstract class BaseEndpointResolutionStrategy implements ServiceEndpointResolutionStrategy {
+
+   protected abstract Predicate<ServiceEndpoint> filter();
+
+   @Nullable
+   @Override
+   public Supplier<URI> apply(Collection<ServiceEndpoint> input) {
+      Predicate<ServiceEndpoint> filter = filter();
+      Optional<ServiceEndpoint> serviceEndpoint = tryFind(input, filter);
+      return Suppliers.ofInstance(serviceEndpoint.isPresent() ? serviceEndpoint.get().url() : null);
+   }
+
+   protected static Predicate<ServiceEndpoint> withIface(final Interface iface) {
+      return new Predicate<ServiceEndpoint>() {
+         @Override
+         public boolean apply(ServiceEndpoint input) {
+            return input.iface().equals(iface);
+         }
+
+         @Override
+         public String toString() {
+            return "interface(" + iface.name().toLowerCase() + ")";
+         }
+      };
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java
new file mode 100644
index 0000000..dfe44e3
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/InternalURL.java
@@ -0,0 +1,34 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
+
+import javax.inject.Singleton;
+
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+import com.google.common.base.Predicate;
+
+@Singleton
+public class InternalURL extends BaseEndpointResolutionStrategy {
+
+   @Override
+   protected Predicate<ServiceEndpoint> filter() {
+      return withIface(INTERNAL);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java
new file mode 100644
index 0000000..cbf01f9
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/PublicURLOrInternal.java
@@ -0,0 +1,66 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import static com.google.common.base.Predicates.or;
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.inject.Singleton;
+
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+
+@Singleton
+public class PublicURLOrInternal extends BaseEndpointResolutionStrategy {
+
+   @Override
+   public Supplier<URI> apply(Collection<ServiceEndpoint> input) {
+      List<ServiceEndpoint> publicEndpointsFirst = new ArrayList<ServiceEndpoint>(input);
+      Collections.sort(publicEndpointsFirst, PublicInterfacesFirst);
+      return super.apply(publicEndpointsFirst);
+   }
+
+   @Override
+   protected Predicate<ServiceEndpoint> filter() {
+      return or(withIface(PUBLIC), withIface(INTERNAL));
+   }
+
+   private static final Comparator<ServiceEndpoint> PublicInterfacesFirst = new Comparator<ServiceEndpoint>() {
+      @Override
+      public int compare(ServiceEndpoint left, ServiceEndpoint right) {
+         // We only care about public interfaces, since the collection will be
+         // filtered only by public or internal ones
+         if (PUBLIC.equals(left.iface())) {
+            return -1;
+         } else if (PUBLIC.equals(right.iface())) {
+            return 1;
+         } else {
+            return 0;
+         }
+      };
+   };
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java
new file mode 100644
index 0000000..db1d314
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ReturnRegionOrProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.location.Provider;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+@Singleton
+public class ReturnRegionOrProvider implements ServiceEndpointToRegion {
+   private final String provider;
+
+   @Inject
+   ReturnRegionOrProvider(@Provider String provider) {
+      this.provider = provider;
+   }
+
+   @Override
+   public String apply(ServiceEndpoint input) {
+      return input.regionId() != null ? input.regionId() : provider;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java
new file mode 100644
index 0000000..da8b654
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointResolutionStrategy.java
@@ -0,0 +1,35 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import java.net.URI;
+import java.util.Collection;
+
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.inject.ImplementedBy;
+
+/**
+ * Given a sets of endpoints for a particular service and version, return the
+ * URL to be used to connect to the service.
+ */
+@ImplementedBy(PublicURLOrInternal.class)
+public interface ServiceEndpointResolutionStrategy extends Function<Collection<ServiceEndpoint>, Supplier<URI>> {
+   
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java
new file mode 100644
index 0000000..c1ed3f1
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/functions/ServiceEndpointToRegion.java
@@ -0,0 +1,27 @@
+/*
+ * 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.keystone.catalog.functions;
+
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+
+import com.google.common.base.Function;
+import com.google.inject.ImplementedBy;
+
+@ImplementedBy(ReturnRegionOrProvider.class)
+public interface ServiceEndpointToRegion extends Function<ServiceEndpoint, String> {
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
new file mode 100644
index 0000000..8adf561
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
@@ -0,0 +1,129 @@
+/*
+ * 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.keystone.catalog.suppliers;
+
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Maps.transformValues;
+import static com.google.common.collect.Multimaps.asMap;
+import static com.google.common.collect.Multimaps.index;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.annotation.Resource;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
+
+   public interface Factory {
+      
+      LocationIdToURIFromAccessForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
+            @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
+   }
+
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   protected final Supplier<List<ServiceEndpoint>> serviceEndpoints;
+   protected final ServiceEndpointResolutionStrategy resolveServiceEndpointURI;
+   protected final ServiceEndpointToRegion serviceEndpointToRegion;
+   protected final String apiType;
+   protected final String apiVersion;
+
+   @Inject
+   LocationIdToURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+         ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      this.serviceEndpoints = serviceEndpoints;
+      this.resolveServiceEndpointURI = resolveServiceEndpointURI;
+      this.serviceEndpointToRegion = serviceEndpointToRegion;
+      this.apiType = apiType;
+      this.apiVersion = apiVersion;
+   }
+
+   @Override
+   public Map<String, Supplier<URI>> get() {
+      List<ServiceEndpoint> endpoints = serviceEndpoints.get();
+
+      // Filter endpoints by service type
+      Iterable<ServiceEndpoint> endpointsForType = filter(endpoints, apiTypeEquals);
+      if (isEmpty(endpointsForType)) {
+         throw new NoSuchElementException(String.format("no endpoints for apiType %s in service endpoints %s", apiType,
+               endpoints));
+      }
+      
+      // Check if there are endpoints for a particular version, if specified and
+      // there are versioned endpoints
+      boolean checkVersionId = apiVersion != null && any(endpointsForType, versionAware);
+      Predicate<ServiceEndpoint> versionFilter = checkVersionId ? apiVersionEqualsVersionId : Predicates.<ServiceEndpoint> alwaysTrue();
+      Iterable<ServiceEndpoint> endpointsForTypeAndVersion = filter(endpointsForType, versionFilter);
+      if (isEmpty(endpointsForTypeAndVersion)) {
+         throw new NoSuchElementException(String.format(
+               "no service endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
+               endpointsForType));
+      }
+
+      logger.debug("service endpoints for apiType %s and version %s: %s", apiType, apiVersion,
+            endpointsForTypeAndVersion);
+      
+      Multimap<String, ServiceEndpoint> locationToServiceEndpoints = index(endpointsForTypeAndVersion,
+            serviceEndpointToRegion);
+      return transformValues(asMap(locationToServiceEndpoints), resolveServiceEndpointURI);
+   }
+
+   private final Predicate<ServiceEndpoint> apiVersionEqualsVersionId = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.version().equals(apiVersion);
+      }
+   };
+
+   private final Predicate<ServiceEndpoint> versionAware = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.version() != null;
+      }
+   };
+
+   private final Predicate<ServiceEndpoint> apiTypeEquals = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.type().equals(apiType);
+      }
+   };
+
+   @Override
+   public String toString() {
+      return "locationIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
new file mode 100644
index 0000000..740b7a3
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
@@ -0,0 +1,44 @@
+/*
+ * 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.keystone.catalog.suppliers;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.AdminEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Supplier;
+import com.google.inject.assistedinject.Assisted;
+
+public class RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
+      RegionIdToAdminURISupplier {
+   @Inject
+   public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+         AdminEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
+   }
+
+   @Override
+   public String toString() {
+      return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
new file mode 100644
index 0000000..0f70205
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
@@ -0,0 +1,37 @@
+/*
+ * 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.keystone.catalog.suppliers;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.common.base.Supplier;
+import com.google.inject.ImplementedBy;
+import com.google.inject.assistedinject.Assisted;
+
+@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class)
+public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
+
+   interface Factory {
+
+      RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
+               @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
new file mode 100644
index 0000000..d40b4af
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
@@ -0,0 +1,46 @@
+/*
+ * 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.keystone.catalog.suppliers;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Supplier;
+import com.google.inject.assistedinject.Assisted;
+
+public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
+      RegionIdToURISupplier {
+
+   @Inject
+   public RegionIdToURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+         ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
+   }
+
+   @Override
+   public String toString() {
+      return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java
new file mode 100644
index 0000000..ece0129
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/config/KeystoneProperties.java
@@ -0,0 +1,83 @@
+/*
+ * 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.keystone.config;
+
+import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
+
+/**
+ * Configuration properties and constants used in Keystone connections.
+ */
+public final class KeystoneProperties {
+
+   /**
+    * Type of credentials used to log into the auth service.
+    *
+    * <h3>valid values</h3>
+    * <ul>
+    * <li>apiAccessKeyCredentials</li>
+    * <li>passwordCredentials</li>
+    * <li>tokenCredentials</li>
+    * </ul>
+    *
+    * @see CredentialTypes
+    * @see <a href=
+    *      "http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html"
+    *      />
+    */
+   public static final String CREDENTIAL_TYPE = "jclouds.keystone.credential-type";
+
+   /**
+    * set this property to specify the tenant id of the authenticated user.
+    * Cannot be used simultaneously with {@link #TENANT_NAME}
+    *
+    * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
+    */
+   public static final String TENANT_ID = "jclouds.keystone.tenant-id";
+
+   /**
+    * set this property to specify the tenant name of the authenticated user.
+    * Cannot be used simultaneously with {@link #TENANT_ID}
+    *
+    * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
+    */
+   public static final String TENANT_NAME = "jclouds.keystone.tenant-name";
+
+   /**
+    * set this property to {@code true} to designate that the service requires
+    * explicit specification of either {@link #TENANT_NAME} or
+    * {@link #TENANT_ID}
+    *
+    * @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
+    */
+   public static final String REQUIRES_TENANT = "jclouds.keystone.requires-tenant";
+
+   /**
+    * type of the keystone service. ex. {@code compute}
+    *
+    * @see ServiceType
+    */
+   public static final String SERVICE_TYPE = "jclouds.keystone.service-type";
+   
+   /**
+    * Version of keystone to be used by services. Default: 3.
+    */
+   public static final String KEYSTONE_VERSION = "jclouds.keystone.version";
+
+   private KeystoneProperties() {
+      throw new AssertionError("intentionally unimplemented");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
deleted file mode 100644
index 0ac8a6c..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationApi.java
+++ /dev/null
@@ -1,91 +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.keystone.v2_0;
-
-import java.io.Closeable;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
-import org.jclouds.openstack.keystone.v2_0.domain.Access;
-import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials;
-import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials;
-import org.jclouds.rest.annotations.MapBinder;
-import org.jclouds.rest.annotations.PayloadParam;
-import org.jclouds.rest.annotations.SelectJson;
-
-import com.google.inject.name.Named;
-
-/**
- * Provides access to the OpenStack Keystone Service API.
- */
-@Consumes(MediaType.APPLICATION_JSON)
-@Path("/tokens")
-public interface AuthenticationApi extends Closeable {
-
-   /**
-    * Authenticate to generate a token.
-    *
-    * @return access with token
-    */
-   @Named("authenticate")
-   @POST
-   @SelectJson("access")
-   @MapBinder(BindAuthToJsonPayload.class)
-   Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
-         PasswordCredentials passwordCredentials);
-
-   /**
-    * Authenticate to generate a token.
-    *
-    * @return access with token
-    */
-   @Named("authenticate")
-   @POST
-   @SelectJson("access")
-   @MapBinder(BindAuthToJsonPayload.class)
-   Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
-         PasswordCredentials passwordCredentials);
-
-   /**
-    * Authenticate to generate a token.
-    *
-    * @return access with token
-    */
-   @Named("authenticate")
-   @POST
-   @SelectJson("access")
-   @MapBinder(BindAuthToJsonPayload.class)
-   Access authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName,
-         ApiAccessKeyCredentials apiAccessKeyCredentials);
-
-   /**
-    * Authenticate to generate a token.
-    *
-    * @return access with token
-    */
-   @Named("authenticate")
-   @POST
-   @SelectJson("access")
-   @MapBinder(BindAuthToJsonPayload.class)
-   Access authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
-         ApiAccessKeyCredentials apiAccessKeyCredentials);
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
index a06ea13..b8dbbcf 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java
@@ -16,18 +16,19 @@
  */
 package org.jclouds.openstack.keystone.v2_0;
 
-import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
-import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.KEYSTONE_VERSION;
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.SERVICE_TYPE;
 
 import java.net.URI;
 import java.util.Properties;
 
 import org.jclouds.apis.ApiMetadata;
-import org.jclouds.openstack.keystone.v2_0.config.AuthenticationApiModule;
-import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
-import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
+import org.jclouds.openstack.keystone.auth.config.AuthenticationModule;
+import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
+import org.jclouds.openstack.keystone.catalog.config.KeystoneAdminURLModule;
+import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule;
-import org.jclouds.openstack.keystone.v2_0.config.KeystoneHttpApiModule.KeystoneAdminURLModule;
 import org.jclouds.openstack.keystone.v2_0.config.KeystoneParserModule;
 import org.jclouds.openstack.v2_0.ServiceType;
 import org.jclouds.rest.internal.BaseHttpApiMetadata;
@@ -59,6 +60,7 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> {
       Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
       properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
+      properties.setProperty(KEYSTONE_VERSION, "2");
       return properties;
    }
 
@@ -75,8 +77,8 @@ public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> {
          .defaultEndpoint("http://localhost:5000/v${jclouds.api-version}/")
          .defaultProperties(KeystoneApiMetadata.defaultProperties())
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
-                                     .add(AuthenticationApiModule.class)
-                                     .add(KeystoneAuthenticationModule.class)
+                                     .add(AuthenticationModule.class)
+                                     .add(ServiceCatalogModule.class)
                                      .add(KeystoneAdminURLModule.class)
                                      .add(KeystoneParserModule.class)
                                      .add(KeystoneHttpApiModule.class).build());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.java
new file mode 100644
index 0000000..3efe4f8
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/auth/V2AuthenticationApi.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.keystone.v2_0.auth;
+
+import java.io.Closeable;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.openstack.keystone.auth.AuthenticationApi;
+import org.jclouds.openstack.keystone.auth.domain.ApiAccessKeyCredentials;
+import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
+import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials;
+import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload;
+import org.jclouds.openstack.keystone.v2_0.domain.Access;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.SelectJson;
+
+import com.google.inject.name.Named;
+
+/**
+ * Provides access to the OpenStack Keystone Service API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/tokens")
+public interface V2AuthenticationApi extends AuthenticationApi, Closeable {
+
+   /**
+    * Authenticate to generate a token.
+    *
+    * @return access with token
+    */
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @MapBinder(BindAuthToJsonPayload.class)
+   @Override
+   Access authenticatePassword(TenantAndCredentials<PasswordCredentials> credentials);
+
+   /**
+    * Authenticate to generate a token.
+    *
+    * @return access with token
+    */
+   @Named("authenticate")
+   @POST
+   @SelectJson("access")
+   @MapBinder(BindAuthToJsonPayload.class)
+   @Override
+   Access authenticateAccessKey(TenantAndCredentials<ApiAccessKeyCredentials> credentials);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java
index 71ef63d..5661947 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java
@@ -16,24 +16,29 @@
  */
 package org.jclouds.openstack.keystone.v2_0.binders;
 
-import com.google.common.base.Predicates;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.Iterables;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.instanceOf;
+import static com.google.common.collect.Iterables.tryFind;
+import static org.jclouds.openstack.keystone.auth.config.CredentialTypes.findCredentialType;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
 import org.jclouds.http.HttpRequest;
 import org.jclouds.json.Json;
-import org.jclouds.openstack.keystone.v2_0.config.CredentialType;
+import org.jclouds.openstack.keystone.auth.config.CredentialType;
+import org.jclouds.openstack.keystone.auth.domain.TenantAndCredentials;
 import org.jclouds.rest.MapBinder;
 import org.jclouds.rest.binders.BindToJsonPayload;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
 
-import javax.inject.Inject;
-import javax.inject.Singleton;
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
 
 @Singleton
 public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinder {
@@ -42,28 +47,35 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
       super(jsonBinder);
    }
 
-   protected void addCredentialsInArgsOrNull(GeneratedHttpRequest gRequest, Builder<String, Object> builder) {
-      for (Object arg : Iterables.filter(gRequest.getInvocation().getArgs(), Predicates.notNull())) {
-         if (arg.getClass().isAnnotationPresent(CredentialType.class)) {
-            builder.put(arg.getClass().getAnnotation(CredentialType.class).value(), arg);
-         }
-      }
+   protected TenantAndCredentials<?> findCredentialsInArgs(GeneratedHttpRequest gRequest) {
+      Optional<Object> credentials = tryFind(gRequest.getInvocation().getArgs(), instanceOf(TenantAndCredentials.class));
+      return credentials.isPresent() ? (TenantAndCredentials<?>) credentials.get() : null;
    }
 
    @Override
    public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
       checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
-               "this binder is only valid for GeneratedHttpRequests!");
+            "this binder is only valid for GeneratedHttpRequests!");
       GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
-
       Builder<String, Object> builder = ImmutableMap.builder();
-      addCredentialsInArgsOrNull(gRequest, builder);
-      // TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools
-      // still use tenantName
-      if (!Strings.isNullOrEmpty((String) postParams.get("tenantName")))
-         builder.put("tenantName", postParams.get("tenantName"));
-      else if (!Strings.isNullOrEmpty((String) postParams.get("tenantId")))
-          builder.put("tenantId", postParams.get("tenantId"));
+
+      TenantAndCredentials<?> credentials = findCredentialsInArgs(gRequest);
+      if (credentials != null) {
+         CredentialType credentialType = findCredentialType(credentials.credentials().getClass());
+         checkArgument(credentialType != null, "the given credentials must be annotated with @CredentialType");
+
+         builder.put(credentialType.value(), credentials.credentials());
+
+         // TODO: is tenantName permanent? or should we switch to tenantId at
+         // some point. seems most tools still use tenantName
+         if (credentials != null) {
+            if (!Strings.isNullOrEmpty(credentials.tenantId()))
+               builder.put("tenantId", credentials.tenantId());
+            else if (!Strings.isNullOrEmpty(credentials.tenantName()))
+               builder.put("tenantName", credentials.tenantName());
+         }
+      }
+
       R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", builder.build()));
       authRequest.getPayload().setSensitive(true);
       return authRequest;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java
new file mode 100644
index 0000000..913b0b5
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/catalog/V2ServiceCatalog.java
@@ -0,0 +1,105 @@
+/*
+ * 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.keystone.v2_0.catalog;
+
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.ADMIN;
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.INTERNAL;
+import static org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface.PUBLIC;
+
+import java.net.URI;
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint.Interface;
+import org.jclouds.openstack.keystone.v2_0.domain.Access;
+import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
+import org.jclouds.openstack.keystone.v2_0.domain.Service;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+
+@Singleton
+public class V2ServiceCatalog implements Supplier<List<ServiceEndpoint>> {
+
+   @Resource
+   private Logger logger = Logger.NULL;
+
+   private final Supplier<AuthInfo> authInfo;
+
+   @Inject
+   V2ServiceCatalog(Supplier<AuthInfo> authInfo) {
+      this.authInfo = authInfo;
+   }
+
+   @Override
+   public List<ServiceEndpoint> get() {
+      Access access = (Access) authInfo.get();
+      ImmutableList.Builder<ServiceEndpoint> serviceEndpoints = ImmutableList.builder();
+      for (Service service : access) {
+         for (Endpoint endpoint : service) {
+            if (endpoint.getAdminURL() != null) {
+               serviceEndpoints.add(toServiceEndpoint(service.getType(), ADMIN).apply(endpoint));
+            }
+            if (endpoint.getInternalURL() != null) {
+               serviceEndpoints.add(toServiceEndpoint(service.getType(), INTERNAL).apply(endpoint));
+            }
+            if (endpoint.getPublicURL() != null) {
+               serviceEndpoints.add(toServiceEndpoint(service.getType(), PUBLIC).apply(endpoint));
+            }
+         }
+      }
+
+      return serviceEndpoints.build();
+   }
+
+   private Function<Endpoint, ServiceEndpoint> toServiceEndpoint(final String type, final Interface iface) {
+      return new Function<Endpoint, ServiceEndpoint>() {
+         @Override
+         public ServiceEndpoint apply(Endpoint input) {
+            ServiceEndpoint.Builder builder = ServiceEndpoint.builder().id(input.getId()).iface(iface)
+                  .regionId(input.getRegion()).type(type).version(input.getVersionId());
+
+            switch (iface) {
+               case ADMIN:
+                  builder.url(input.getAdminURL());
+                  break;
+               case INTERNAL:
+                  builder.url(input.getInternalURL());
+                  break;
+               case PUBLIC:
+                  builder.url(input.getPublicURL());
+                  break;
+               case UNRECOGNIZED:
+                  URI url = input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL();
+                  logger.warn("Unrecognized endpoint interface for %s. Using URL: %s", input, url);
+                  builder.url(url);
+                  break;
+            }
+
+            return builder.build();
+         }
+      };
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java
deleted file mode 100644
index d6e5381..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/Authentication.java
+++ /dev/null
@@ -1,31 +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.keystone.v2_0.config;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import javax.inject.Qualifier;
-
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
-@Qualifier
-public @interface Authentication {
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
deleted file mode 100644
index 2537d63..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/AuthenticationApiModule.java
+++ /dev/null
@@ -1,33 +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.keystone.v2_0.config;
-
-import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
-
-import org.jclouds.openstack.keystone.v2_0.AuthenticationApi;
-
-import com.google.inject.AbstractModule;
-
-public class AuthenticationApiModule extends AbstractModule  {
-
-   @Override
-   protected void configure() {
-      // AuthenticationApi is used directly for filters and retry handlers, so let's bind it explicitly
-      bindHttpApi(binder(), AuthenticationApi.class);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java
deleted file mode 100644
index b0d67cc..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java
+++ /dev/null
@@ -1,38 +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.keystone.v2_0.config;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import javax.inject.Qualifier;
-
-/**
- * @see CredentialTypes
- */
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
-@Qualifier
-public @interface CredentialType {
-   /**
-    * @see CredentialTypes
-    * 
-    */
-   String value();
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java
deleted file mode 100644
index c774ae1..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java
+++ /dev/null
@@ -1,52 +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.keystone.v2_0.config;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-import java.util.Map;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Maps;
-
-/**
- * Configuration properties and constants used in Keystone connections.
- */
-public class CredentialTypes {
-
-   public static final String API_ACCESS_KEY_CREDENTIALS = "apiAccessKeyCredentials";
-
-   public static final String PASSWORD_CREDENTIALS = "passwordCredentials";
-
-   public static <T> String credentialTypeOf(T input) {
-      Class<?> authenticationType = input.getClass();
-      checkArgument(authenticationType.isAnnotationPresent(CredentialType.class),
-               "programming error: %s should have annotation %s", authenticationType, CredentialType.class.getName());
-      return authenticationType.getAnnotation(CredentialType.class).value();
-   }
-
-   public static <T> Map<String, T> indexByCredentialType(Iterable<T> iterable) {
-      return Maps.uniqueIndex(iterable, new Function<T, String>() {
-
-         @Override
-         public String apply(T input) {
-            return credentialTypeOf(input);
-         }
-
-      });
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7def8169/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
deleted file mode 100644
index 4d540fd..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java
+++ /dev/null
@@ -1,257 +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.keystone.v2_0.config;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static org.jclouds.util.Suppliers2.getLastValueInMap;
-
-import java.net.URI;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import org.jclouds.domain.Credentials;
-import org.jclouds.http.HttpRetryHandler;
-import org.jclouds.http.annotation.ClientError;
-import org.jclouds.location.Provider;
-import org.jclouds.location.suppliers.ImplicitLocationSupplier;
-import org.jclouds.location.suppliers.LocationsSupplier;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.location.suppliers.RegionIdsSupplier;
-import org.jclouds.location.suppliers.ZoneIdToURISupplier;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
-import org.jclouds.location.suppliers.all.RegionToProvider;
-import org.jclouds.location.suppliers.all.ZoneToProvider;
-import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
-import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
-import org.jclouds.location.suppliers.implicit.FirstRegion;
-import org.jclouds.location.suppliers.implicit.FirstZone;
-import org.jclouds.openstack.keystone.v2_0.domain.Access;
-import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
-import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials;
-import org.jclouds.openstack.keystone.v2_0.functions.AuthenticatePasswordCredentials;
-import org.jclouds.openstack.keystone.v2_0.handlers.RetryOnRenew;
-import org.jclouds.openstack.keystone.v2_0.suppliers.LocationIdToURIFromAccessForTypeAndVersion;
-import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
-import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
-import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
-import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersion;
-import org.jclouds.rest.annotations.ApiVersion;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSet.Builder;
-import com.google.inject.AbstractModule;
-import com.google.inject.Injector;
-import com.google.inject.Provides;
-import com.google.inject.Scopes;
-import com.google.inject.assistedinject.FactoryModuleBuilder;
-
-public class KeystoneAuthenticationModule extends AbstractModule {
-
-   /**
-    * For global services who have no regions, such as DNS. To use, do the following
-    * <ol>
-    * <li>add this module to your {@link org.jclouds.apis.ApiMetadata#getDefaultModules()}</li>
-    * <li>create a service-specific annotation, such as {@code @CloudDNS}, and make sure that has the meta-annotation
-    * {@link javax.inject.Qualifier}</li>
-    * <li>add the above annotation to any {@code Api} classes by placing it on the type. ex.
-    * {@code @Endpoint(CloudDNS.class)}</li>
-    * <li>add the following to your {@link org.jclouds.rest.config.RestClientModule}</li>
-    *
-    * <pre>
-    * bind(new TypeLiteral&lt;Supplier&lt;URI&gt;&gt;() {
-    * }).annotatedWith(CloudDNS.class).to(new TypeLiteral&lt;Supplier&lt;URI&gt;&gt;() {
-    * });
-    * </pre>
-    */
-   public static class ProviderModule extends AbstractModule {
-      @Override
-      protected void configure() {
-         install(new FactoryModuleBuilder().build(LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
-      }
-
-      @Provides
-      @Singleton
-      protected final Supplier<URI> provideZoneIdToURISupplierForApiVersion(
-            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-            LocationIdToURIFromAccessForTypeAndVersion.Factory factory) {
-         return getLastValueInMap(factory.createForApiTypeAndVersion(serviceType, apiVersion));
-      }
-
-      @Provides
-      @Singleton
-      final Function<Endpoint, String> provideProvider(@Provider final String provider) {
-         return new Function<Endpoint, String>() {
-            @Override
-            public String apply(Endpoint in) {
-               return provider;
-            }
-         };
-      }
-   }
-
-   public static class RegionModule extends AbstractModule {
-      @Override
-      protected void configure() {
-         install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
-               RegionIdToURIFromAccessForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
-         install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
-               RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
-         // dynamically build the region list as opposed to from properties
-         bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
-         bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);
-         bind(LocationsSupplier.class).to(RegionToProvider.class).in(Scopes.SINGLETON);
-      }
-
-      @Provides
-      @Singleton
-      protected final RegionIdToURISupplier guiceProvideRegionIdToURISupplierForApiVersion(
-              @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-              RegionIdToURISupplier.Factory factory) {
-         return provideRegionIdToURISupplierForApiVersion(serviceType, apiVersion, factory);
-      }
-
-      // supply the region to id map from keystone, based on the servicetype and api version in
-      // config
-      protected RegionIdToURISupplier provideRegionIdToURISupplierForApiVersion(
-            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-            RegionIdToURISupplier.Factory factory) {
-         return factory.createForApiTypeAndVersion(serviceType, apiVersion);
-      }
-
-      @Provides
-      @Singleton
-      protected final RegionIdToAdminURISupplier guiceProvideRegionIdToAdminURISupplierForApiVersion(
-              @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-              RegionIdToAdminURISupplier.Factory factory) {
-         return provideRegionIdToAdminURISupplierForApiVersion(serviceType, apiVersion, factory);
-      }
-
-      // supply the region to id to AdminURL map from keystone, based on the servicetype and api
-      // version in
-      // config
-      protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion(
-            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-            RegionIdToAdminURISupplier.Factory factory) {
-         return factory.createForApiTypeAndVersion(serviceType, apiVersion);
-      }
-
-   }
-
-   /**
-    * @deprecated All OpenStack APIs rely on regions in jclouds 2.0. To be removed in jclouds 2.0.
-    */
-   @Deprecated
-   public static class ZoneModule extends AbstractModule {
-      @Override
-      protected void configure() {
-         install(new FactoryModuleBuilder().implement(ZoneIdToURISupplier.class,
-               ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class));
-         // dynamically build the zone list as opposed to from properties
-         bind(ZoneIdsSupplier.class).to(ZoneIdsFromZoneIdToURIKeySet.class);
-         bind(ImplicitLocationSupplier.class).to(FirstZone.class).in(Scopes.SINGLETON);
-         bind(LocationsSupplier.class).to(ZoneToProvider.class).in(Scopes.SINGLETON);
-      }
-
-      // supply the zone to id map from keystone, based on the servicetype and api version in
-      // config
-      @Provides
-      @Singleton
-      protected final ZoneIdToURISupplier provideZoneIdToURISupplierForApiVersion(
-            @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-            ZoneIdToURISupplier.Factory factory) {
-         return factory.createForApiTypeAndVersion(serviceType, apiVersion);
-      }
-
-   }
-
-   @Override
-   protected void configure() {
-      bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
-   }
-
-   /**
-    * borrowing concurrency code to ensure that caching takes place properly
-    */
-   @Provides
-   @Singleton
-   @Authentication
-   protected final Supplier<String> provideAuthenticationTokenCache(final Supplier<Access> supplier)
-         throws InterruptedException, ExecutionException, TimeoutException {
-      return new Supplier<String>() {
-         @Override
-         public String get() {
-            return supplier.get().getToken().getId();
-         }
-      };
-   }
-
-   @Provides
-   @Singleton
-   protected final Map<String, Function<Credentials, Access>> provideAuthenticationMethods(Injector i) {
-      return authenticationMethods(i);
-   }
-
-   protected Map<String, Function<Credentials, Access>> authenticationMethods(Injector i) {
-      Builder<Function<Credentials, Access>> fns = ImmutableSet.<Function<Credentials, Access>> builder();
-      fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
-      fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class));
-      return CredentialTypes.indexByCredentialType(fns.build());
-   }
-
-   @Provides
-   @Singleton
-   protected final Function<Credentials, Access> authenticationMethodForCredentialType(
-         @Named(KeystoneProperties.CREDENTIAL_TYPE) String credentialType,
-         Map<String, Function<Credentials, Access>> authenticationMethods) {
-      checkArgument(authenticationMethods.containsKey(credentialType), "credential type %s not in supported list: %s",
-            credentialType, authenticationMethods.keySet());
-      return authenticationMethods.get(credentialType);
-   }
-
-   // TODO: what is the timeout of the session token? modify default accordingly
-   // PROPERTY_SESSION_INTERVAL is default to 60 seconds, but we have this here at 11 hours for now.
-   @Provides
-   @Singleton
-   public final LoadingCache<Credentials, Access> provideAccessCache(Function<Credentials, Access> getAccess) {
-      return CacheBuilder.newBuilder().expireAfterWrite(11, TimeUnit.HOURS).build(CacheLoader.from(getAccess));
-   }
-
-   // Temporary conversion of a cache to a supplier until there is a single-element cache
-   // http://code.google.com/p/guava-libraries/issues/detail?id=872
-   @Provides
-   @Singleton
-   protected final Supplier<Access> provideAccessSupplier(final LoadingCache<Credentials, Access> cache,
-         @Provider final Supplier<Credentials> creds) {
-      return new Supplier<Access>() {
-         @Override
-         public Access get() {
-            return cache.getUnchecked(creds.get());
-         }
-      };
-   }
-
-}