The list queues methods for the QueueApi.
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queue.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queue.java
new file mode 100644
index 0000000..15ac4f0
--- /dev/null
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queue.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to jclouds, Inc. (jclouds) under one or more
+ * contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  jclouds 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.marconi.v1.domain;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import org.jclouds.javax.annotation.Nullable;
+
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A queue.
+ *
+ * @author Everett Toews
+ */
+public class Queue {
+
+   private final String name;
+   private final Map<String, String> metadata;
+
+   protected Queue(String name, @Nullable Map<String, String> metadata) {
+      this.name = checkNotNull(name, "id required");
+      this.metadata = metadata;
+   }
+
+   /**
+    * @return The name of this queue.
+    */
+   public String getName() {
+      return name;
+   }
+
+   /**
+    * @return The key/value metadata for this queue.
+    */
+   public Optional<Map<String, String>> getMetadata() {
+      return Optional.fromNullable(metadata);
+   }
+
+   @Override
+   public int hashCode() {
+      return Objects.hashCode(name);
+   }
+
+   @Override
+   public boolean equals(Object obj) {
+      if (this == obj) return true;
+      if (obj == null || getClass() != obj.getClass()) return false;
+      Queue that = Queue.class.cast(obj);
+      return Objects.equal(this.name, that.name);
+   }
+
+   protected Objects.ToStringHelper string() {
+      return Objects.toStringHelper(this).omitNullValues()
+         .add("name", name).add("metadata", metadata);
+   }
+
+   @Override
+   public String toString() {
+      return string().toString();
+   }
+
+   public static Builder builder() {
+      return new ConcreteBuilder();
+   }
+
+   public Builder toBuilder() {
+      return new ConcreteBuilder().fromMessage(this);
+   }
+
+   public static abstract class Builder {
+      protected abstract Builder self();
+
+      protected String name;
+      protected Map<String, String> metadata;
+
+      /**
+       * @param name The name of this queue.
+       */
+      public Builder name(String name) {
+         this.name = name;
+         return self();
+      }
+
+      /**
+       * @param metadata The key/value metadata for this queue.
+       */
+      public Builder metadata(Map<String, String> metadata) {
+         this.metadata = metadata;
+         return self();
+      }
+
+      public Queue build() {
+         return new Queue(name, metadata);
+      }
+
+      public Builder fromMessage(Queue in) {
+         return this.name(in.getName()).metadata(in.getMetadata().orNull());
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+
+}
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queues.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queues.java
new file mode 100644
index 0000000..6ef6a93
--- /dev/null
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/domain/Queues.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.marconi.v1.domain;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import org.jclouds.openstack.marconi.v1.options.ListQueuesOptions;
+import org.jclouds.openstack.marconi.v1.options.StreamOptions;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import java.beans.ConstructorProperties;
+
+import static org.jclouds.http.utils.Queries.queryParser;
+
+public class Queues extends PaginatedCollection<Queue> {
+   public static final Queues EMPTY = new Queues(ImmutableSet.<Queue> of(), ImmutableSet.<Link> of());
+
+   @ConstructorProperties({ "queues", "links" })
+   protected Queues(Iterable<Queue> queues, Iterable<Link> links) {
+      super(queues, links);
+   }
+
+   /**
+    * Only call this method if {@code nextMarker().isPresent()} returns true.
+    *
+    * @return The options necessary to get the next page of queues.
+    */
+   public ListQueuesOptions nextListQueuesOptions() {
+      return ListQueuesOptions.class.cast(nextMarker().get());
+   }
+
+   @Override
+   public Optional<Object> nextMarker() {
+      Optional<Link> nextMarkerLink = Iterables.tryFind(getLinks(), IS_NEXT_LINK);
+      return nextMarkerLink.transform(TO_LIST_OPTIONS);
+   }
+
+   private static final Predicate<Link> IS_NEXT_LINK = new Predicate<Link>() {
+      @Override
+      public boolean apply(Link link) {
+         return Link.Relation.NEXT == link.getRelation();
+      }
+   };
+
+   private static final Function<Link, Object> TO_LIST_OPTIONS = new Function<Link, Object>() {
+      @Override
+      public Object apply(Link link) {
+         Multimap<String, String> queryParams = queryParser().apply(link.getHref().getRawQuery());
+         ListQueuesOptions listQueuesOptions = ListQueuesOptions.Builder.queryParameters(queryParams);
+
+         return listQueuesOptions;
+      }
+   };
+}
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/features/QueueApi.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/features/QueueApi.java
index c80c610..a2fc044 100644
--- a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/features/QueueApi.java
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/features/QueueApi.java
@@ -16,15 +16,21 @@
  */
 package org.jclouds.openstack.marconi.v1.features;
 
-import org.jclouds.Fallbacks;
+import org.jclouds.collect.PagedIterable;
 import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
+import org.jclouds.openstack.marconi.v1.domain.Queue;
 import org.jclouds.openstack.marconi.v1.domain.QueueStats;
+import org.jclouds.openstack.marconi.v1.domain.Queues;
 import org.jclouds.openstack.marconi.v1.functions.ParseQueueStats;
+import org.jclouds.openstack.marconi.v1.functions.ParseQueues;
+import org.jclouds.openstack.marconi.v1.functions.QueuesToPagedIterable;
+import org.jclouds.openstack.marconi.v1.options.ListQueuesOptions;
 import org.jclouds.rest.annotations.BinderParam;
 import org.jclouds.rest.annotations.Fallback;
 import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.ResponseParser;
 import org.jclouds.rest.annotations.SkipEncoding;
+import org.jclouds.rest.annotations.Transform;
 import org.jclouds.rest.binders.BindToJsonPayload;
 
 import javax.inject.Named;
@@ -35,9 +41,14 @@
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import java.util.Map;
 
+import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import static org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import static org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
+
 /**
  * Provides access to Queues via their REST API.
  *
@@ -46,8 +57,6 @@
 @SkipEncoding({'/', '='})
 @RequestFilters(AuthenticateRequest.class)
 public interface QueueApi {
-   // TODO: Move name parameter into MarconiApi.getQueueApiForZone(String name, String zone)
-
    /**
     * Create a queue.
     *
@@ -57,7 +66,7 @@
    @Named("queue:create")
    @PUT
    @Path("queues/{name}")
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    boolean create(@PathParam("name") String name);
 
    /**
@@ -69,7 +78,7 @@
    @Named("queue:delete")
    @DELETE
    @Path("queues/{name}")
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    boolean delete(@PathParam("name") String name);
 
    /**
@@ -81,10 +90,33 @@
    @Named("queue:get")
    @GET
    @Path("queues/{name}")
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    boolean exists(@PathParam("name") String name);
 
-   // TODO stream method!
+   /**
+    * List the queues.
+    *
+    * @param detailed Determines whether queue metadata is included in the list.
+    */
+   @Named("queue:list")
+   @GET
+   @Consumes(MediaType.APPLICATION_JSON)
+   @ResponseParser(ParseQueues.class)
+   @Transform(QueuesToPagedIterable.class)
+   @Path("queues")
+   @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+   PagedIterable<Queue> list(@QueryParam("detailed") boolean detailed);
+
+   /**
+    * Use this method to manually page through the list of queues.
+    */
+   @Named("record:list")
+   @GET
+   @ResponseParser(ParseQueues.class)
+   @Consumes(MediaType.APPLICATION_JSON)
+   @Fallback(EmptyPaginatedCollectionOnNotFoundOr404.class)
+   @Path("queues")
+   Queues list(ListQueuesOptions options);
 
    /**
     * Sets metadata for the specified queue.
@@ -102,7 +134,7 @@
    @PUT
    @Path("queues/{name}/metadata")
    @Produces(MediaType.APPLICATION_JSON)
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    boolean setMetadata(@PathParam("name") String name,
                        @BinderParam(BindToJsonPayload.class) Map<String, String> metadata);
 
@@ -116,7 +148,7 @@
    @GET
    @Path("queues/{name}/metadata")
    @Consumes(MediaType.APPLICATION_JSON)
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    Map<String, String> getMetadata(@PathParam("name") String name);
 
 
@@ -131,6 +163,6 @@
    @Path("queues/{name}/stats")
    @Consumes(MediaType.APPLICATION_JSON)
    @ResponseParser(ParseQueueStats.class)
-   @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+   @Fallback(FalseOnNotFoundOr404.class)
    QueueStats getStats(@PathParam("name") String name);
 }
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/ParseQueues.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/ParseQueues.java
new file mode 100644
index 0000000..825a573
--- /dev/null
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/ParseQueues.java
@@ -0,0 +1,54 @@
+/*
+ * 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.marconi.v1.functions;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.openstack.marconi.v1.domain.Queue;
+import org.jclouds.openstack.marconi.v1.domain.Queues;
+import org.jclouds.openstack.v2_0.domain.Link;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+
+import javax.inject.Inject;
+import java.beans.ConstructorProperties;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * @author Everett Toews
+ */
+public class ParseQueues implements Function<HttpResponse, PaginatedCollection<Queue>> {
+
+   private final ParseJson<Queues> json;
+
+   @Inject
+   ParseQueues(ParseJson<Queues> json) {
+      this.json = checkNotNull(json, "json");
+   }
+
+   @Override
+   public PaginatedCollection<Queue> apply(HttpResponse response) {
+      // An empty message stream has a 204 response code
+      if (response.getStatusCode() == 204) {
+         return Queues.EMPTY;
+      }
+
+      return json.apply(response);
+   }
+}
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/QueuesToPagedIterable.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/QueuesToPagedIterable.java
new file mode 100644
index 0000000..93d553a
--- /dev/null
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/functions/QueuesToPagedIterable.java
@@ -0,0 +1,75 @@
+/*
+ * 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.marconi.v1.functions;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.internal.Arg0ToPagedIterable;
+import org.jclouds.openstack.marconi.v1.MarconiApi;
+import org.jclouds.openstack.marconi.v1.domain.Queue;
+import org.jclouds.openstack.marconi.v1.features.QueueApi;
+import org.jclouds.openstack.marconi.v1.options.ListQueuesOptions;
+import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import javax.inject.Inject;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.openstack.marconi.v1.options.ListQueuesOptions.Builder.queryParameters;
+
+/**
+ * @author Everett Toews
+ */
+@Beta
+public class QueuesToPagedIterable extends Arg0ToPagedIterable.FromCaller<Queue, QueuesToPagedIterable> {
+
+   private final MarconiApi api;
+
+   @Inject
+   protected QueuesToPagedIterable(MarconiApi api) {
+      this.api = checkNotNull(api, "api");
+   }
+
+   @Override
+   protected Function<Object, IterableWithMarker<Queue>> markerToNextForArg0(Optional<Object> arg0) {
+      String zone = String.class.cast(arg0.get());
+
+      return new ListQueuesAtMarker(api.getQueueApiForZone(zone));
+   }
+
+   private static class ListQueuesAtMarker implements Function<Object, IterableWithMarker<Queue>> {
+      private final QueueApi api;
+
+      @Inject
+      protected ListQueuesAtMarker(QueueApi api) {
+         this.api = checkNotNull(api, "api");
+      }
+
+      public PaginatedCollection<Queue> apply(Object input) {
+         PaginationOptions paginationOptions = PaginationOptions.class.cast(input);
+         ListQueuesOptions listQueuesOptions = queryParameters(paginationOptions.buildQueryParameters());
+
+         return api.list(listQueuesOptions);
+      }
+
+      public String toString() {
+         return "ListRecordsAtMarker";
+      }
+   }
+}
diff --git a/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/options/ListQueuesOptions.java b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/options/ListQueuesOptions.java
new file mode 100644
index 0000000..1ce60d4
--- /dev/null
+++ b/openstack-marconi/src/main/java/org/jclouds/openstack/marconi/v1/options/ListQueuesOptions.java
@@ -0,0 +1,110 @@
+/*
+ * 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.marconi.v1.options;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Options used to control the messages returned in the response.
+ */
+public class ListQueuesOptions extends PaginationOptions {
+
+   public static final ListQueuesOptions NONE = new ListQueuesOptions();
+
+   /**
+    * {@inheritDoc}
+    */
+   @Override
+   public ListQueuesOptions queryParameters(Multimap<String, String> queryParams) {
+      checkNotNull(queryParams, "queryParams");
+      queryParameters.putAll(queryParams);
+      return this;
+   }
+
+   /**
+    * @see Builder#marker(String)
+    */
+   @Override
+   public ListQueuesOptions marker(String marker) {
+      super.marker(marker);
+      return this;
+   }
+
+   /**
+    * @see Builder#limit(int)
+    */
+   @Override
+   public ListQueuesOptions limit(int limit) {
+      super.limit(limit);
+      return this;
+
+   }
+
+   /**
+    * @see Builder#detailed(boolean)
+    */
+   public ListQueuesOptions detailed(boolean detailed) {
+      queryParameters.put("detailed", Boolean.toString(detailed));
+      return this;
+   }
+
+   /**
+    * @return The String representation of the marker for these StreamOptions.
+    */
+   public String getMarker() {
+      return Iterables.getOnlyElement(queryParameters.get("marker"));
+   }
+
+   public static class Builder {
+      /**
+       * @see PaginationOptions#queryParameters(Multimap)
+       */
+      public static ListQueuesOptions queryParameters(Multimap<String, String> queryParams) {
+         ListQueuesOptions options = new ListQueuesOptions();
+         return options.queryParameters(queryParams);
+      }
+
+      /**
+       * Specifies the name of the last queue received in a previous request, or none to get the first page of results.
+       */
+      public static ListQueuesOptions marker(String marker) {
+         ListQueuesOptions options = new ListQueuesOptions();
+         return options.marker(marker);
+      }
+
+      /**
+       * Specifies the number of queues to return. The default value for the number of queues returned is 10. If you do
+       * not specify this parameter, the default number of queues is returned.
+       */
+      public static ListQueuesOptions limit(int limit) {
+         ListQueuesOptions options = new ListQueuesOptions();
+         return options.limit(limit);
+      }
+
+      /**
+       * Determines whether queue metadata is included in the list.
+       */
+      public static ListQueuesOptions detailed(boolean detailed) {
+         ListQueuesOptions options = new ListQueuesOptions();
+         return options.detailed(detailed);
+      }
+   }
+}
diff --git a/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiLiveTest.java b/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiLiveTest.java
index cb3dfa3..ae00c64 100644
--- a/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiLiveTest.java
+++ b/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiLiveTest.java
@@ -19,7 +19,9 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import org.jclouds.openstack.marconi.v1.domain.CreateMessage;
+import org.jclouds.openstack.marconi.v1.domain.Queue;
 import org.jclouds.openstack.marconi.v1.domain.QueueStats;
+import org.jclouds.openstack.marconi.v1.domain.Queues;
 import org.jclouds.openstack.marconi.v1.internal.BaseMarconiApiLiveTest;
 import org.testng.annotations.Test;
 
@@ -27,6 +29,7 @@
 import java.util.Map;
 import java.util.UUID;
 
+import static org.jclouds.openstack.marconi.v1.options.ListQueuesOptions.Builder.limit;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertNotNull;
@@ -35,20 +38,96 @@
 @Test(groups = "live", testName = "QueueApiLiveTest", singleThreaded = true)
 public class QueueApiLiveTest extends BaseMarconiApiLiveTest {
 
+   public void listZeroPagesOfQueues() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertTrue(queues.isEmpty());
+      }
+   }
+
+   @Test(dependsOnMethods = { "listZeroPagesOfQueues" })
    public void create() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         boolean success = queueApi.create("jclouds-test");
 
-         assertTrue(success);
+         for (int i=0; i < 6; i++) {
+            boolean success = queueApi.create("jclouds-test-" + i);
+
+            assertTrue(success);
+         }
       }
    }
 
    @Test(dependsOnMethods = { "create" })
+   public void listOnePageOfQueues() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertEquals(queues.size(), 6);
+
+         for (Queue queue: queues) {
+            assertNotNull(queue.getName());
+            assertFalse(queue.getMetadata().isPresent());
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = { "listOnePageOfQueues" })
+   public void createMore() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+
+         for (int i=6; i < 12; i++) {
+            boolean success = queueApi.create("jclouds-test-" + i);
+
+            assertTrue(success);
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = { "createMore" })
+   public void listManyPagesOfQueues() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertEquals(queues.size(), 12);
+
+         for (Queue queue: queues) {
+            assertNotNull(queue.getName());
+            assertFalse(queue.getMetadata().isPresent());
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = { "listManyPagesOfQueues" })
+   public void listManyPagesOfQueuesManually() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+
+         Queues queues = queueApi.list(limit(6));
+
+         while(queues.nextMarker().isPresent()) {
+            assertEquals(queues.size(), 6);
+
+            for (Queue queue: queues) {
+               assertNotNull(queue.getName());
+               assertFalse(queue.getMetadata().isPresent());
+            }
+
+            queues = queueApi.list(queues.nextListQueuesOptions());
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = { "listManyPagesOfQueuesManually" })
    public void exists() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         boolean success = queueApi.exists("jclouds-test");
+         boolean success = queueApi.exists("jclouds-test-1");
 
          assertTrue(success);
       }
@@ -59,17 +138,39 @@
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
          Map<String, String> metadata = ImmutableMap.of("key1", "value1");
-         boolean success = queueApi.setMetadata("jclouds-test", metadata);
+         boolean success = queueApi.setMetadata("jclouds-test-1", metadata);
 
          assertTrue(success);
       }
    }
 
    @Test(dependsOnMethods = { "setMetadata" })
+   public void listManyPagesOfQueuesWithDetails() throws Exception {
+      for (String zoneId : api.getConfiguredZones()) {
+         QueueApi queueApi = api.getQueueApiForZone(zoneId);
+         List<Queue> queues = queueApi.list(true).concat().toList();
+
+         assertEquals(queues.size(), 12);
+
+         for (Queue queue: queues) {
+            assertNotNull(queue.getName());
+            assertTrue(queue.getMetadata().isPresent());
+
+            if (queue.getName().equals("jclouds-test-1")) {
+               assertEquals(queue.getMetadata().get().get("key1"), "value1");
+            }
+            else {
+               assertTrue(queue.getMetadata().get().isEmpty());
+            }
+         }
+      }
+   }
+
+   @Test(dependsOnMethods = { "listManyPagesOfQueuesWithDetails" })
    public void getMetadata() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         Map<String, String> metadata = queueApi.getMetadata("jclouds-test");
+         Map<String, String> metadata = queueApi.getMetadata("jclouds-test-1");
 
          assertEquals(metadata.get("key1"), "value1");
       }
@@ -79,7 +180,7 @@
    public void getStatsWithoutTotal() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         QueueStats stats = queueApi.getStats("jclouds-test");
+         QueueStats stats = queueApi.getStats("jclouds-test-1");
 
          assertEquals(stats.getMessagesStats().getClaimed(), 0);
          assertEquals(stats.getMessagesStats().getFree(), 0);
@@ -92,7 +193,7 @@
    @Test(dependsOnMethods = { "getStatsWithoutTotal" })
    public void getStatsWithTotal() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
-         MessageApi messageApi = api.getMessageApiForZoneAndQueue(zoneId, "jclouds-test");
+         MessageApi messageApi = api.getMessageApiForZoneAndQueue(zoneId, "jclouds-test-1");
 
          UUID clientId = UUID.fromString("3381af92-2b9e-11e3-b191-71861300734c");
          String json1 = "{\"event\":{\"type\":\"hockey\",\"players\":[\"bob\",\"jim\",\"sally\"]}}";
@@ -102,7 +203,7 @@
          messageApi.create(clientId, message);
 
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         QueueStats stats = queueApi.getStats("jclouds-test");
+         QueueStats stats = queueApi.getStats("jclouds-test-1");
 
          assertEquals(stats.getMessagesStats().getClaimed(), 0);
          assertEquals(stats.getMessagesStats().getFree(), 1);
@@ -118,9 +219,12 @@
    public void delete() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         boolean success = queueApi.delete("jclouds-test");
 
-         assertTrue(success);
+         for (int i=0; i < 12; i++) {
+            boolean success = queueApi.delete("jclouds-test-" + i);
+
+            assertTrue(success);
+         }
       }
    }
 
@@ -128,7 +232,7 @@
    public void doesNotExist() throws Exception {
       for (String zoneId : api.getConfiguredZones()) {
          QueueApi queueApi = api.getQueueApiForZone(zoneId);
-         boolean success = queueApi.exists("jclouds-test");
+         boolean success = queueApi.exists("jclouds-test-1");
 
          assertFalse(success);
       }
diff --git a/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiMockTest.java b/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiMockTest.java
index 375f24d..cafc1de 100644
--- a/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiMockTest.java
+++ b/openstack-marconi/src/test/java/org/jclouds/openstack/marconi/v1/features/QueueApiMockTest.java
@@ -17,19 +17,25 @@
 package org.jclouds.openstack.marconi.v1.features;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
 import com.squareup.okhttp.mockwebserver.MockResponse;
 import com.squareup.okhttp.mockwebserver.MockWebServer;
 import com.squareup.okhttp.mockwebserver.RecordedRequest;
 import org.jclouds.openstack.marconi.v1.MarconiApi;
+import org.jclouds.openstack.marconi.v1.domain.Queue;
 import org.jclouds.openstack.marconi.v1.domain.QueueStats;
+import org.jclouds.openstack.marconi.v1.domain.Queues;
 import org.jclouds.openstack.v2_0.internal.BaseOpenStackMockTest;
 import org.testng.annotations.Test;
 
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
 
+import static org.jclouds.openstack.marconi.v1.options.ListQueuesOptions.Builder.limit;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
 /**
@@ -122,6 +128,120 @@
       }
    }
 
+   public void listZeroPagesOfQueues() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(new MockResponse().setBody(accessRackspace));
+      server.enqueue(new MockResponse().setResponseCode(204));
+
+      try {
+         MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");
+         QueueApi queueApi = api.getQueueApiForZone("DFW");
+
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertTrue(queues.isEmpty());
+
+         assertEquals(server.getRequestCount(), 2);
+         assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?detailed=false HTTP/1.1");
+      }
+      finally {
+         server.shutdown();
+      }
+   }
+
+   public void listOnePageOfQueues() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(new MockResponse().setBody(accessRackspace));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"queues\": [{\"href\": \"/v1/queues/jclouds-test\", \"name\": \"jclouds-test\"}], \"links\": [{\"href\": \"/v1/queues?detailed=false&marker=jclouds-test\", \"rel\": \"next\"}]}"));
+      server.enqueue(new MockResponse().setResponseCode(204));
+
+      try {
+         MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");
+         QueueApi queueApi = api.getQueueApiForZone("DFW");
+
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertEquals(queues.size(), 1);
+         assertEquals(Iterables.getOnlyElement(queues).getName(), "jclouds-test");
+         assertFalse(Iterables.getOnlyElement(queues).getMetadata().isPresent());
+
+         assertEquals(server.getRequestCount(), 3);
+         assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?detailed=false HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?detailed=false&marker=jclouds-test HTTP/1.1");
+      }
+      finally {
+         server.shutdown();
+      }
+   }
+
+   public void listManyPagesOfQueues() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(new MockResponse().setBody(accessRackspace));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"queues\": [{\"href\": \"/v1/queues/jclouds-test-1\", \"name\": \"jclouds-test-1\"}, {\"href\": \"/v1/queues/jclouds-test-10\", \"name\": \"jclouds-test-10\"}, {\"href\": \"/v1/queues/jclouds-test-11\", \"name\": \"jclouds-test-11\"}, {\"href\": \"/v1/queues/jclouds-test-12\", \"name\": \"jclouds-test-12\"}, {\"href\": \"/v1/queues/jclouds-test-2\", \"name\": \"jclouds-test-2\"}, {\"href\": \"/v1/queues/jclouds-test-3\", \"name\": \"jclouds-test-3\"}, {\"href\": \"/v1/queues/jclouds-test-4\", \"name\": \"jclouds-test-4\"}, {\"href\": \"/v1/queues/jclouds-test-5\", \"name\": \"jclouds-test-5\"}, {\"href\": \"/v1/queues/jclouds-test-6\", \"name\": \"jclouds-test-6\"}, {\"href\": \"/v1/queues/jclouds-test-7\", \"name\": \"jclouds-test-7\"}], \"links\": [{\"href\": \"/v1/queues?detailed=false&marker=jclouds-test-7\", \"rel\": \"next\"}]}"));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"queues\": [{\"href\": \"/v1/queues/jclouds-test-8\", \"name\": \"jclouds-test-8\"}, {\"href\": \"/v1/queues/jclouds-test-9\", \"name\": \"jclouds-test-9\"}], \"links\": [{\"href\": \"/v1/queues?marker=jclouds-test-9&detailed=false\", \"rel\": \"next\"}]}"));
+      server.enqueue(new MockResponse().setResponseCode(204));
+
+      try {
+         MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");
+         QueueApi queueApi = api.getQueueApiForZone("DFW");
+
+         List<Queue> queues = queueApi.list(false).concat().toList();
+
+         assertEquals(queues.size(), 12);
+
+         for (Queue queue: queues) {
+            assertNotNull(queue.getName());
+            assertFalse(queue.getMetadata().isPresent());
+         }
+
+         assertEquals(server.getRequestCount(), 4);
+         assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?detailed=false HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?detailed=false&marker=jclouds-test-7 HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?marker=jclouds-test-9&detailed=false HTTP/1.1");
+      }
+      finally {
+         server.shutdown();
+      }
+   }
+
+   public void listManyPagesOfQueuesManually() throws Exception {
+      MockWebServer server = mockOpenStackServer();
+      server.enqueue(new MockResponse().setBody(accessRackspace));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"queues\": [{\"href\": \"/v1/queues/jclouds-test-1\", \"name\": \"jclouds-test-1\"}, {\"href\": \"/v1/queues/jclouds-test-10\", \"name\": \"jclouds-test-10\"}, {\"href\": \"/v1/queues/jclouds-test-11\", \"name\": \"jclouds-test-11\"}, {\"href\": \"/v1/queues/jclouds-test-12\", \"name\": \"jclouds-test-12\"}, {\"href\": \"/v1/queues/jclouds-test-2\", \"name\": \"jclouds-test-2\"}, {\"href\": \"/v1/queues/jclouds-test-3\", \"name\": \"jclouds-test-3\"}], \"links\": [{\"href\": \"/v1/queues?marker=jclouds-test-3&limit=6\", \"rel\": \"next\"}]}"));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"queues\": [{\"href\": \"/v1/queues/jclouds-test-4\", \"name\": \"jclouds-test-4\"}, {\"href\": \"/v1/queues/jclouds-test-5\", \"name\": \"jclouds-test-5\"}, {\"href\": \"/v1/queues/jclouds-test-6\", \"name\": \"jclouds-test-6\"}, {\"href\": \"/v1/queues/jclouds-test-7\", \"name\": \"jclouds-test-7\"}, {\"href\": \"/v1/queues/jclouds-test-8\", \"name\": \"jclouds-test-8\"}, {\"href\": \"/v1/queues/jclouds-test-9\", \"name\": \"jclouds-test-9\"}], \"links\": [{\"href\": \"/v1/queues?marker=jclouds-test-9&limit=6\", \"rel\": \"next\"}]}"));
+      server.enqueue(new MockResponse().setResponseCode(204));
+
+      try {
+         MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");
+         QueueApi queueApi = api.getQueueApiForZone("DFW");
+
+         Queues queues = queueApi.list(limit(6));
+
+         while(queues.nextMarker().isPresent()) {
+            assertEquals(queues.size(), 6);
+
+            for (Queue queue: queues) {
+               assertNotNull(queue.getName());
+               assertFalse(queue.getMetadata().isPresent());
+            }
+
+            queues = queueApi.list(queues.nextListQueuesOptions());
+         }
+
+         assertEquals(server.getRequestCount(), 4);
+         assertEquals(server.takeRequest().getRequestLine(), "POST /tokens HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?limit=6 HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?marker=jclouds-test-3&limit=6 HTTP/1.1");
+         assertEquals(server.takeRequest().getRequestLine(), "GET /v1/123123/queues?marker=jclouds-test-9&limit=6 HTTP/1.1");
+      }
+      finally {
+         server.shutdown();
+      }
+   }
+
    public void setMetadata() throws Exception {
       MockWebServer server = mockOpenStackServer();
       server.enqueue(new MockResponse().setBody(accessRackspace));
@@ -170,8 +290,7 @@
    public void getQueueStatsWithoutTotal() throws Exception {
       MockWebServer server = mockOpenStackServer();
       server.enqueue(new MockResponse().setBody(accessRackspace));
-      server.enqueue(new MockResponse().setResponseCode(200)
-            .setBody("{\"messages\":{\"claimed\":0,\"total\":0,\"free\":0}}"));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"messages\":{\"claimed\":0,\"total\":0,\"free\":0}}"));
 
       try {
          MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");
@@ -196,8 +315,7 @@
    public void getQueueStatsWithTotal() throws Exception {
       MockWebServer server = mockOpenStackServer();
       server.enqueue(new MockResponse().setBody(accessRackspace));
-      server.enqueue(new MockResponse().setResponseCode(200)
-            .setBody("{\"messages\": {\"claimed\": 0, \"oldest\": {\"age\": 0, \"href\": \"/v1/queues/jclouds-test/messages/526558b3f4919b655feba3a7\", \"created\": \"2013-10-21T16:39:15Z\"}, \"total\": 4, \"newest\": {\"age\": 0, \"href\": \"/v1/queues/jclouds-test/messages/526558b33ac24e663fc545e7\", \"created\": \"2013-10-21T16:39:15Z\"}, \"free\": 4}}"));
+      server.enqueue(new MockResponse().setResponseCode(200).setBody("{\"messages\": {\"claimed\": 0, \"oldest\": {\"age\": 0, \"href\": \"/v1/queues/jclouds-test/messages/526558b3f4919b655feba3a7\", \"created\": \"2013-10-21T16:39:15Z\"}, \"total\": 4, \"newest\": {\"age\": 0, \"href\": \"/v1/queues/jclouds-test/messages/526558b33ac24e663fc545e7\", \"created\": \"2013-10-21T16:39:15Z\"}, \"free\": 4}}"));
 
       try {
          MarconiApi api = api(server.getUrl("/").toString(), "openstack-marconi");