Adding Rackspace delegates
diff --git a/openstack/identity/v2/users/requests.go b/openstack/identity/v2/users/requests.go
index d0c2fdd..e6bb591 100644
--- a/openstack/identity/v2/users/requests.go
+++ b/openstack/identity/v2/users/requests.go
@@ -103,7 +103,7 @@
 func Get(client *gophercloud.ServiceClient, id string) GetResult {
 	var result GetResult
 
-	_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
+	_, result.Err = perigee.Request("GET", ResourceURL(client, id), perigee.Options{
 		Results:     &result.Body,
 		MoreHeaders: client.AuthenticatedHeaders(),
 		OkCodes:     []int{200},
@@ -147,7 +147,7 @@
 func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
 	var result UpdateResult
 
-	_, result.Err = perigee.Request("PUT", resourceURL(client, id), perigee.Options{
+	_, result.Err = perigee.Request("PUT", ResourceURL(client, id), perigee.Options{
 		Results:     &result.Body,
 		ReqBody:     opts.ToUserUpdateMap(),
 		MoreHeaders: client.AuthenticatedHeaders(),
@@ -161,7 +161,7 @@
 func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
 	var result DeleteResult
 
-	_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
+	_, result.Err = perigee.Request("DELETE", ResourceURL(client, id), perigee.Options{
 		MoreHeaders: client.AuthenticatedHeaders(),
 		OkCodes:     []int{204},
 	})
diff --git a/openstack/identity/v2/users/urls.go b/openstack/identity/v2/users/urls.go
index f59cafc..a40160c 100644
--- a/openstack/identity/v2/users/urls.go
+++ b/openstack/identity/v2/users/urls.go
@@ -7,7 +7,7 @@
 	userPath   = "users"
 )
 
-func resourceURL(c *gophercloud.ServiceClient, id string) string {
+func ResourceURL(c *gophercloud.ServiceClient, id string) string {
 	return c.ServiceURL(userPath, id)
 }
 
diff --git a/rackspace/identity/v2/users/delegate.go b/rackspace/identity/v2/users/delegate.go
new file mode 100644
index 0000000..07c7c97
--- /dev/null
+++ b/rackspace/identity/v2/users/delegate.go
@@ -0,0 +1,130 @@
+package users
+
+import (
+	"errors"
+
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+	os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+// List returns a pager that allows traversal over a collection of users.
+func List(client *gophercloud.ServiceClient) pagination.Pager {
+	return os.List(client)
+}
+
+type commonOpts struct {
+	// Required. The username to assign to the user. When provided, the username
+	// must:
+	// - start with an alphabetical (A-Za-z) character
+	// - have a minimum length of 1 character
+	//
+	// The username may contain upper and lowercase characters, as well as any of
+	// the following special character: . - @ _
+	Username string
+
+	// Required. Email address for the user account.
+	Email string
+
+	// Required. Indicates whether the user can authenticate after the user
+	// account is created. If no value is specified, the default value is true.
+	Enabled os.EnabledState
+
+	// Optional. The password to assign to the user. If provided, the password
+	// must:
+	// - start with an alphabetical (A-Za-z) character
+	// - have a minimum length of 8 characters
+	// - contain at least one uppercase character, one lowercase character, and
+	//   one numeric character.
+	//
+	// The password may contain any of the following special characters: . - @ _
+	Password string
+}
+
+// CreateOpts represents the options needed when creating new users.
+type CreateOpts commonOpts
+
+// ToUserCreateMap assembles a request body based on the contents of a CreateOpts.
+func (opts CreateOpts) ToUserCreateMap() (map[string]interface{}, error) {
+	m := make(map[string]interface{})
+
+	if opts.Username == "" {
+		return m, errors.New("Username is a required field")
+	}
+	if opts.Enabled == nil {
+		return m, errors.New("Enabled is a required field")
+	}
+	if opts.Email == "" {
+		return m, errors.New("Email is a required field")
+	}
+
+	if opts.Username != "" {
+		m["username"] = opts.Username
+	}
+	if opts.Email != "" {
+		m["email"] = opts.Email
+	}
+	if opts.Enabled != nil {
+		m["enabled"] = opts.Enabled
+	}
+	if opts.Password != "" {
+		m["OS-KSADM:password"] = opts.Password
+	}
+
+	return map[string]interface{}{"user": m}, nil
+}
+
+// Create is the operation responsible for creating new users.
+func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult {
+	return CreateResult{os.Create(client, opts)}
+}
+
+// Get requests details on a single user, either by ID.
+func Get(client *gophercloud.ServiceClient, id string) GetResult {
+	return GetResult{os.Get(client, id)}
+}
+
+// UpdateOptsBuilder allows extentions to add additional attributes to the Update request.
+type UpdateOptsBuilder interface {
+	ToUserUpdateMap() map[string]interface{}
+}
+
+// UpdateOpts specifies the base attributes that may be updated on an existing server.
+type UpdateOpts commonOpts
+
+// ToUserUpdateMap formats an UpdateOpts structure into a request body.
+func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} {
+	m := make(map[string]interface{})
+
+	if opts.Username != "" {
+		m["username"] = opts.Username
+	}
+	if opts.Enabled != nil {
+		m["enabled"] = &opts.Enabled
+	}
+	if opts.Email != "" {
+		m["email"] = opts.Email
+	}
+
+	return map[string]interface{}{"user": m}
+}
+
+// Update is the operation responsible for updating exist users by their UUID.
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
+	var result UpdateResult
+
+	_, result.Err = perigee.Request("POST", os.ResourceURL(client, id), perigee.Options{
+		Results:     &result.Body,
+		ReqBody:     opts.ToUserUpdateMap(),
+		MoreHeaders: client.AuthenticatedHeaders(),
+		OkCodes:     []int{200},
+	})
+
+	return result
+}
+
+// Delete is the operation responsible for permanently deleting an API user.
+func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
+	return os.Delete(client, id)
+}
diff --git a/rackspace/identity/v2/users/delegate_test.go b/rackspace/identity/v2/users/delegate_test.go
new file mode 100644
index 0000000..4461c8c
--- /dev/null
+++ b/rackspace/identity/v2/users/delegate_test.go
@@ -0,0 +1,99 @@
+package users
+
+import (
+	"testing"
+
+	os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
+	"github.com/rackspace/gophercloud/pagination"
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestList(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockListResponse(t)
+
+	count := 0
+
+	err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
+		count++
+		users, err := os.ExtractUsers(page)
+
+		th.AssertNoErr(t, err)
+		th.AssertEquals(t, "u1000", users[0].ID)
+		th.AssertEquals(t, "u1001", users[1].ID)
+
+		return true, nil
+	})
+
+	th.AssertNoErr(t, err)
+	th.AssertEquals(t, 1, count)
+}
+
+func TestCreateUser(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockCreateUser(t)
+
+	opts := CreateOpts{
+		Username: "new_user",
+		Enabled:  os.Disabled,
+		Email:    "new_user@foo.com",
+		Password: "foo",
+	}
+
+	user, err := Create(client.ServiceClient(), opts).Extract()
+
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, "123456", user.ID)
+	th.AssertEquals(t, "5830280", user.DomainID)
+	th.AssertEquals(t, "DFW", user.DefaultRegion)
+}
+
+func TestGetUser(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockGetUser(t)
+
+	user, err := Get(client.ServiceClient(), "new_user").Extract()
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, true, user.Enabled)
+	th.AssertEquals(t, "true", user.MultiFactorEnabled)
+}
+
+func TestUpdateUser(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockUpdateUser(t)
+
+	id := "c39e3de9be2d4c779f1dfd6abacc176d"
+
+	opts := UpdateOpts{
+		Enabled: os.Enabled,
+		Email:   "new_email@foo.com",
+	}
+
+	user, err := Update(client.ServiceClient(), id, opts).Extract()
+
+	th.AssertNoErr(t, err)
+
+	th.AssertEquals(t, true, user.Enabled)
+	th.AssertEquals(t, "new_email@foo.com", user.Email)
+}
+
+func TestDeleteServer(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	os.MockDeleteUser(t)
+
+	res := Delete(client.ServiceClient(), "c39e3de9be2d4c779f1dfd6abacc176d")
+	th.AssertNoErr(t, res.Err)
+}
diff --git a/rackspace/identity/v2/users/fixtures.go b/rackspace/identity/v2/users/fixtures.go
new file mode 100644
index 0000000..e843966
--- /dev/null
+++ b/rackspace/identity/v2/users/fixtures.go
@@ -0,0 +1,138 @@
+package users
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	th "github.com/rackspace/gophercloud/testhelper"
+	fake "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func mockListResponse(t *testing.T) {
+	th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+		"users":[
+				{
+						"id": "u1000",
+						"username": "jqsmith",
+						"email": "john.smith@example.org",
+						"enabled": true
+				},
+				{
+						"id": "u1001",
+						"username": "jqsmith",
+						"email": "jane.smith@example.org",
+						"enabled": true
+				}
+		]
+}
+	`)
+	})
+}
+
+func mockCreateUser(t *testing.T) {
+	th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		th.TestJSONRequest(t, r, `
+{
+    "user": {
+        "username": "new_user",
+        "enabled": false,
+        "email": "new_user@foo.com",
+				"OS-KSADM:password": "foo"
+    }
+}
+  `)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+  "user": {
+    "RAX-AUTH:defaultRegion": "DFW",
+    "RAX-AUTH:domainId": "5830280",
+    "id": "123456",
+    "username": "new_user",
+    "email": "new_user@foo.com",
+    "enabled": false
+  }
+}
+`)
+	})
+}
+
+func mockGetUser(t *testing.T) {
+	th.Mux.HandleFunc("/users/new_user", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+	"user": {
+		"RAX-AUTH:defaultRegion": "DFW",
+		"RAX-AUTH:domainId": "5830280",
+		"RAX-AUTH:multiFactorEnabled": "true",
+		"id": "c39e3de9be2d4c779f1dfd6abacc176d",
+		"username": "jqsmith",
+		"email": "john.smith@example.org",
+		"enabled": true
+	}
+}
+`)
+	})
+}
+
+func mockUpdateUser(t *testing.T) {
+	th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		th.TestJSONRequest(t, r, `
+{
+	"user": {
+		"email": "new_email@foo.com",
+		"enabled": true
+	}
+}
+`)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+	"user": {
+		"RAX-AUTH:defaultRegion": "DFW",
+		"RAX-AUTH:domainId": "5830280",
+		"RAX-AUTH:multiFactorEnabled": "true",
+		"id": "123456",
+		"username": "jqsmith",
+		"email": "new_email@foo.com",
+		"enabled": true
+	}
+}
+`)
+	})
+}
+
+func mockDeleteUser(t *testing.T) {
+	th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		w.WriteHeader(http.StatusNoContent)
+	})
+}
diff --git a/rackspace/identity/v2/users/results.go b/rackspace/identity/v2/users/results.go
new file mode 100644
index 0000000..495a6e8
--- /dev/null
+++ b/rackspace/identity/v2/users/results.go
@@ -0,0 +1,88 @@
+package users
+
+import (
+	os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
+
+	"github.com/mitchellh/mapstructure"
+)
+
+// User represents a user resource that exists on the API.
+type User struct {
+	// The UUID for this user.
+	ID string
+
+	// The human name for this user.
+	Name string
+
+	// The username for this user.
+	Username string
+
+	// Indicates whether the user is enabled (true) or disabled (false).
+	Enabled bool
+
+	// The email address for this user.
+	Email string
+
+	// The ID of the tenant to which this user belongs.
+	TenantID string `mapstructure:"tenant_id"`
+
+	// Specifies the default region for the user account. This value is inherited
+	// from the user administrator when the account is created.
+	DefaultRegion string `mapstructure:"RAX-AUTH:defaultRegion"`
+
+	// Identifies the domain that contains the user account. This value is
+	// inherited from the user administrator when the account is created.
+	DomainID string `mapstructure:"RAX-AUTH:domainId"`
+
+	// The password value that the user needs for authentication. If the Add user
+	// request included a password value, this attribute is not included in the
+	// response.
+	Password string `mapstructure:"OS-KSADM:password"`
+
+	// Indicates whether the user has enabled multi-factor authentication.
+	MultiFactorEnabled string `mapstructure:"RAX-AUTH:multiFactorEnabled"`
+}
+
+// CreateResult represents the result of a Create operation
+type CreateResult struct {
+	os.CreateResult
+}
+
+// GetResult represents the result of a Get operation
+type GetResult struct {
+	os.GetResult
+}
+
+// UpdateResult represents the result of an Update operation
+type UpdateResult struct {
+	os.UpdateResult
+}
+
+func commonExtract(resp interface{}, err error) (*User, error) {
+	if err != nil {
+		return nil, err
+	}
+
+	var respStruct struct {
+		User *User `json:"user"`
+	}
+
+	err = mapstructure.Decode(resp, &respStruct)
+
+	return respStruct.User, err
+}
+
+// Extract will get the Snapshot object out of the GetResult object.
+func (r GetResult) Extract() (*User, error) {
+	return commonExtract(r.Body, r.Err)
+}
+
+// Extract will get the Snapshot object out of the CreateResult object.
+func (r CreateResult) Extract() (*User, error) {
+	return commonExtract(r.Body, r.Err)
+}
+
+// Extract will get the Snapshot object out of the UpdateResult object.
+func (r UpdateResult) Extract() (*User, error) {
+	return commonExtract(r.Body, r.Err)
+}