Completely untested code for tokens and tenants.
diff --git a/openstack/identity/v2/tenants/doc.go b/openstack/identity/v2/tenants/doc.go
new file mode 100644
index 0000000..473a302
--- /dev/null
+++ b/openstack/identity/v2/tenants/doc.go
@@ -0,0 +1,7 @@
+/*
+Package tenants contains API calls that query for information about tenants on an OpenStack deployment.
+
+See: http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
+And: http://developer.openstack.org/api-ref-identity-v2.html#admin-tenants
+*/
+package tenants
diff --git a/openstack/identity/v2/tenants/requests.go b/openstack/identity/v2/tenants/requests.go
new file mode 100644
index 0000000..5ffeaa7
--- /dev/null
+++ b/openstack/identity/v2/tenants/requests.go
@@ -0,0 +1,33 @@
+package tenants
+
+import (
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+// ListOpts filters the Tenants that are returned by the List call.
+type ListOpts struct {
+	// Marker is the ID of the last Tenant on the previous page.
+	Marker string `q:"marker"`
+
+	// Limit specifies the page size.
+	Limit int `q:"limit"`
+}
+
+// List enumerates the Tenants to which the current token has access.
+func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
+	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
+		return TenantPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
+	}
+
+	url := listURL(client)
+	if opts != nil {
+		q, err := gophercloud.BuildQueryString(opts)
+		if err != nil {
+			return pagination.Pager{Err: err}
+		}
+		url += q.String()
+	}
+
+	return pagination.NewPager(client, url, createPage)
+}
diff --git a/openstack/identity/v2/tenants/results.go b/openstack/identity/v2/tenants/results.go
new file mode 100644
index 0000000..e4e3f47
--- /dev/null
+++ b/openstack/identity/v2/tenants/results.go
@@ -0,0 +1,75 @@
+package tenants
+
+import (
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+// Tenant is a grouping of users in the identity service.
+type Tenant struct {
+	// ID is a unique identifier for this tenant.
+	ID string `mapstructure:"id"`
+
+	// Name is a friendlier user-facing name for this tenant.
+	Name string `mapstructure:"name"`
+
+	// Description is a human-readable explanation of this Tenant's purpose.
+	Description string `mapstructure:"description"`
+
+	// Enabled indicates whether or not a tenant is active.
+	Enabled bool `mapstructure:"enabled"`
+}
+
+// TenantPage is a single page of Tenant results.
+type TenantPage struct {
+	pagination.LinkedPageBase
+}
+
+// IsEmpty determines whether or not a page of Tenants contains any results.
+func (page TenantPage) IsEmpty() (bool, error) {
+	tenants, err := ExtractTenants(page)
+	if err != nil {
+		return false, err
+	}
+	return len(tenants) == 0, nil
+}
+
+// NextPageURL extracts the "next" link from the tenants_links section of the result.
+func (page TenantPage) NextPageURL() (string, error) {
+	type link struct {
+		Href string `mapstructure:"href"`
+		Rel  string `mapstructure:"rel"`
+	}
+	type resp struct {
+		Links []link `mapstructure:"tenants_links"`
+	}
+
+	var r resp
+	err := mapstructure.Decode(page.Body, &r)
+	if err != nil {
+		return "", err
+	}
+
+	var url string
+	for _, l := range r.Links {
+		if l.Rel == "next" {
+			url = l.Href
+		}
+	}
+	if url == "" {
+		return "", nil
+	}
+
+	return url, nil
+}
+
+// ExtractTenants returns a slice of Tenants contained in a single page of results.
+func ExtractTenants(page pagination.Page) ([]Tenant, error) {
+	casted := page.(TenantPage).Body
+	var response struct {
+		Tenants []Tenant `mapstructure:"tenants"`
+	}
+
+	err := mapstructure.Decode(casted, &response)
+	return response.Tenants, err
+}
diff --git a/openstack/identity/v2/tenants/urls.go b/openstack/identity/v2/tenants/urls.go
new file mode 100644
index 0000000..1dd6ce0
--- /dev/null
+++ b/openstack/identity/v2/tenants/urls.go
@@ -0,0 +1,7 @@
+package tenants
+
+import "github.com/rackspace/gophercloud"
+
+func listURL(client *gophercloud.ServiceClient) string {
+	return client.ServiceURL("tenants")
+}