Merge pull request #294 from takaishi/add_protocol_for_security_group

NeutronV2: add protocols
diff --git a/README.md b/README.md
index 8d8d0a5..60ca479 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@
 
 // Option 1: Pass in the values yourself
 opts := gophercloud.AuthOptions{
-  IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
+  IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
   Username: "{username}",
   Password: "{password}",
 }
diff --git a/acceptance/openstack/client_test.go b/acceptance/openstack/client_test.go
index 2758f60..eed3a82 100644
--- a/acceptance/openstack/client_test.go
+++ b/acceptance/openstack/client_test.go
@@ -5,6 +5,7 @@
 import (
 	"os"
 	"testing"
+	"time"
 
 	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack"
@@ -38,3 +39,48 @@
 		t.Logf("Located a storage service at endpoint: [%s]", storage.Endpoint)
 	}
 }
+
+func TestReauth(t *testing.T) {
+	ao, err := openstack.AuthOptionsFromEnv()
+	if err != nil {
+		t.Fatalf("Unable to obtain environment auth options: %v", err)
+	}
+
+	// Allow reauth
+	ao.AllowReauth = true
+
+	provider, err := openstack.NewClient(ao.IdentityEndpoint)
+	if err != nil {
+		t.Fatalf("Unable to create provider: %v", err)
+	}
+
+	err = openstack.Authenticate(provider, ao)
+	if err != nil {
+		t.Fatalf("Unable to authenticate: %v", err)
+	}
+
+	t.Logf("Creating a compute client")
+	_, err = openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
+		Region: os.Getenv("OS_REGION_NAME"),
+	})
+	if err != nil {
+		t.Fatalf("Unable to create compute client: %v", err)
+	}
+
+	t.Logf("Sleeping for 1 second")
+	time.Sleep(1 * time.Second)
+	t.Logf("Attempting to reauthenticate")
+
+	err = provider.ReauthFunc()
+	if err != nil {
+		t.Fatalf("Unable to reauthenticate: %v", err)
+	}
+
+	t.Logf("Creating a compute client")
+	_, err = openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
+		Region: os.Getenv("OS_REGION_NAME"),
+	})
+	if err != nil {
+		t.Fatalf("Unable to create compute client: %v", err)
+	}
+}
diff --git a/auth_options.go b/auth_options.go
index 3ee97df..eabf182 100644
--- a/auth_options.go
+++ b/auth_options.go
@@ -1,7 +1,7 @@
 package gophercloud
 
 /*
-AuthOptions stores information needed to authenticate to an OpenStack cluster.
+AuthOptions stores information needed to authenticate to an OpenStack Cloud.
 You can populate one manually, or use a provider's AuthOptionsFromEnv() function
 to read relevant information from the standard environment variables. Pass one
 to a provider's AuthenticatedClient function to authenticate and obtain a
@@ -31,9 +31,16 @@
 	DomainName string `json:"name,omitempty"`
 
 	// The TenantID and TenantName fields are optional for the Identity V2 API.
+	// The same fields are known as project_id and project_name in the Identity
+	// V3 API, but are collected as TenantID and TenantName here in both cases.
 	// Some providers allow you to specify a TenantName instead of the TenantId.
 	// Some require both. Your provider's authentication policies will determine
 	// how these fields influence authentication.
+	// If DomainID or DomainName are provided, they will also apply to TenantName.
+	// It is not currently possible to authenticate with Username and a Domain
+	// and scope to a Project in a different Domain by using TenantName. To
+	// accomplish that, the ProjectID will need to be provided to the TenantID
+	// option.
 	TenantID   string `json:"tenantId,omitempty"`
 	TenantName string `json:"tenantName,omitempty"`
 
@@ -132,14 +139,6 @@
 	// if insufficient or incompatible information is present.
 	var req request
 
-	// Test first for unrecognized arguments.
-	if opts.TenantID != "" {
-		return nil, ErrTenantIDProvided{}
-	}
-	if opts.TenantName != "" {
-		return nil, ErrTenantNameProvided{}
-	}
-
 	if opts.Password == "" {
 		if opts.TokenID != "" {
 			// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
@@ -252,15 +251,12 @@
 
 	if opts.TenantID != "" {
 		scope.ProjectID = opts.TenantID
-		opts.TenantID = ""
-		opts.TenantName = ""
 	} else {
 		if opts.TenantName != "" {
 			scope.ProjectName = opts.TenantName
 			scope.DomainID = opts.DomainID
 			scope.DomainName = opts.DomainName
 		}
-		opts.TenantName = ""
 	}
 
 	if scope.ProjectName != "" {
diff --git a/doc.go b/doc.go
index fb81a9d..b559516 100644
--- a/doc.go
+++ b/doc.go
@@ -4,11 +4,13 @@
 resources.
 
 Provider structs represent the service providers that offer and manage a
-collection of services. Examples of providers include: OpenStack, Rackspace,
-HP. These are defined like so:
+collection of services. The IdentityEndpoint is typically refered to as
+"auth_url" in information provided by the cloud operator. Additionally,
+the cloud may refer to TenantID or TenantName as project_id and project_name.
+These are defined like so:
 
   opts := gophercloud.AuthOptions{
-    IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
+    IdentityEndpoint: "https://openstack.example.com:5000/v2.0",
     Username: "{username}",
     Password: "{password}",
     TenantID: "{tenant_id}",
diff --git a/openstack/compute/v2/extensions/keypairs/results.go b/openstack/compute/v2/extensions/keypairs/results.go
index f4d8d35..4c785a2 100644
--- a/openstack/compute/v2/extensions/keypairs/results.go
+++ b/openstack/compute/v2/extensions/keypairs/results.go
@@ -5,7 +5,7 @@
 	"github.com/gophercloud/gophercloud/pagination"
 )
 
-// KeyPair is an SSH key known to the OpenStack cluster that is available to be injected into
+// KeyPair is an SSH key known to the OpenStack Cloud that is available to be injected into
 // servers.
 type KeyPair struct {
 	// Name is used to refer to this keypair from other services within this region.
diff --git a/openstack/db/v1/instances/testing/fixtures.go b/openstack/db/v1/instances/testing/fixtures.go
index 79ee9c3..9347ee1 100644
--- a/openstack/db/v1/instances/testing/fixtures.go
+++ b/openstack/db/v1/instances/testing/fixtures.go
@@ -27,22 +27,22 @@
     "id": "1",
     "links": [
       {
-        "href": "https://my-openstack.com/v1.0/1234/flavors/1",
+        "href": "https://openstack.example.com/v1.0/1234/flavors/1",
         "rel": "self"
       },
       {
-        "href": "https://my-openstack.com/v1.0/1234/flavors/1",
+        "href": "https://openstack.example.com/v1.0/1234/flavors/1",
         "rel": "bookmark"
       }
     ]
   },
   "links": [
     {
-      "href": "https://my-openstack.com/v1.0/1234/instances/1",
+      "href": "https://openstack.example.com/v1.0/1234/instances/1",
       "rel": "self"
     }
   ],
-  "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com",
+  "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.openstack.example.com",
   "id": "{instanceID}",
   "name": "json_rack_instance",
   "status": "BUILD",
@@ -114,14 +114,14 @@
 	Flavor: instances.Flavor{
 		ID: "1",
 		Links: []gophercloud.Link{
-			{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "self"},
-			{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "bookmark"},
+			{Href: "https://openstack.example.com/v1.0/1234/flavors/1", Rel: "self"},
+			{Href: "https://openstack.example.com/v1.0/1234/flavors/1", Rel: "bookmark"},
 		},
 	},
-	Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.my-openstack.com",
+	Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.openstack.example.com",
 	ID:       instanceID,
 	Links: []gophercloud.Link{
-		{Href: "https://my-openstack.com/v1.0/1234/instances/1", Rel: "self"},
+		{Href: "https://openstack.example.com/v1.0/1234/instances/1", Rel: "self"},
 	},
 	Name:   "json_rack_instance",
 	Status: "BUILD",