Initial commit of experimental, new, v0.2.0 API
diff --git a/openstack/identity/requests.go b/openstack/identity/requests.go
new file mode 100644
index 0000000..0012a17
--- /dev/null
+++ b/openstack/identity/requests.go
@@ -0,0 +1,103 @@
+package identity
+
+import (
+	"github.com/racker/perigee"
+)
+
+type AuthResults map[string]interface{}
+
+// AuthOptions lets anyone calling Authenticate() supply the required access credentials.
+// At present, only Identity V2 API support exists; therefore, only Username, Password,
+// and optionally, TenantId are provided.  If future Identity API versions become available,
+// alternative fields unique to those versions may appear here.
+type AuthOptions struct {
+	// Endpoint specifies the HTTP endpoint offering the Identity V2 API.
+	// Required.
+	Endpoint string
+
+	// Username is required if using Identity V2 API.
+	// Consult with your provider's control panel to discover your
+	// account's username.
+	Username string
+
+	// At most one of Password or ApiKey is required if using Identity V2 API.
+	// Consult with your provider's control panel to discover your
+	// account's preferred method of authentication.
+	Password, ApiKey string
+
+	// The TenantId field is optional for the Identity V2 API.
+	TenantId string
+
+	// The TenantName can be specified instead of the TenantId
+	TenantName string
+
+	// AllowReauth should be set to true if you grant permission for Gophercloud to cache
+	// your credentials in memory, and to allow Gophercloud to attempt to re-authenticate
+	// automatically if/when your token expires.  If you set it to false, it will not cache
+	// these settings, but re-authentication will not be possible.  This setting defaults
+	// to false.
+	AllowReauth bool
+}
+
+func Authenticate(options AuthOptions) (AuthResults, error) {
+	var ar AuthResults
+
+	if options.Endpoint == "" {
+		return nil, ErrEndpoint
+	}
+
+	if (options.Username == "") || (options.Password == "" && options.ApiKey == "") {
+		return nil, ErrCredentials
+	}
+
+	err := perigee.Post(options.Endpoint, perigee.Options{
+		ReqBody: &AuthContainer{
+			Auth: getAuthCredentials(options),
+		},
+		Results: &ar,
+	})
+	return ar, err
+}
+
+func getAuthCredentials(options AuthOptions) Auth {
+	if options.ApiKey == "" {
+		return Auth{
+			PasswordCredentials: &struct {
+				Username string `json:"username"`
+				Password string `json:"password"`
+			}{
+				Username: options.Username,
+				Password: options.Password,
+			},
+			TenantId:   options.TenantId,
+			TenantName: options.TenantName,
+		}
+	} else {
+		return Auth{
+			ApiKeyCredentials: &struct {
+				Username string `json:"username"`
+				ApiKey   string `json:"apiKey"`
+			}{
+				Username: options.Username,
+				ApiKey:   options.ApiKey,
+			},
+			TenantId:   options.TenantId,
+			TenantName: options.TenantName,
+		}
+	}
+}
+
+// AuthContainer provides a JSON encoding wrapper for passing credentials to the Identity
+// service.  You will not work with this structure directly.
+type AuthContainer struct {
+	Auth Auth `json:"auth"`
+}
+
+// Auth provides a JSON encoding wrapper for passing credentials to the Identity
+// service.  You will not work with this structure directly.
+type Auth struct {
+	PasswordCredentials interface{} `json:"passwordCredentials,omitempty"`
+	ApiKeyCredentials   interface{} `json:"RAX-KSKEY:apiKeyCredentials,omitempty"`
+	TenantId            string      `json:"tenantId,omitempty"`
+	TenantName          string      `json:"tenantName,omitempty"`
+}