Moving extensions and API versions into different sub-packages; fixing test helper methods
diff --git a/openstack/networking/v2/api_versions/doc.go b/openstack/networking/v2/api_versions/doc.go
new file mode 100644
index 0000000..83c4a6a
--- /dev/null
+++ b/openstack/networking/v2/api_versions/doc.go
@@ -0,0 +1 @@
+package networks
diff --git a/openstack/networking/v2/api_versions/errors.go b/openstack/networking/v2/api_versions/errors.go
new file mode 100644
index 0000000..83c4a6a
--- /dev/null
+++ b/openstack/networking/v2/api_versions/errors.go
@@ -0,0 +1 @@
+package networks
diff --git a/openstack/networking/v2/api_versions/requests.go b/openstack/networking/v2/api_versions/requests.go
new file mode 100644
index 0000000..90e2de3
--- /dev/null
+++ b/openstack/networking/v2/api_versions/requests.go
@@ -0,0 +1,34 @@
+package networks
+
+import (
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+)
+
+func List(c *gophercloud.ServiceClient) (*APIVersionsList, error) {
+	var resp APIVersionsList
+	_, err := perigee.Request("GET", APIVersionsURL(c), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		Results:     &resp,
+		OkCodes:     []int{200},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &resp, nil
+}
+
+func Get(c *gophercloud.ServiceClient, v string) (*APIInfoList, error) {
+	var resp APIInfoList
+	_, err := perigee.Request("GET", APIInfoURL(c, v), perigee.Options{
+		MoreHeaders: c.Provider.AuthenticatedHeaders(),
+		Results:     &resp,
+		OkCodes:     []int{200},
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return &resp, nil
+}
diff --git a/openstack/networking/v2/api_versions/requests_test.go b/openstack/networking/v2/api_versions/requests_test.go
new file mode 100644
index 0000000..cbcc8ae
--- /dev/null
+++ b/openstack/networking/v2/api_versions/requests_test.go
@@ -0,0 +1,139 @@
+package networks
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const TokenID = "123"
+
+func ServiceClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{
+		Provider: &gophercloud.ProviderClient{
+			TokenID: TokenID,
+		},
+		Endpoint: th.Endpoint(),
+	}
+}
+
+func TestList(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+    "versions": [
+        {
+            "status": "CURRENT",
+            "id": "v2.0",
+            "links": [
+                {
+                    "href": "http://23.253.228.211:9696/v2.0",
+                    "rel": "self"
+                }
+            ]
+        }
+    ]
+}`)
+	})
+
+	res, err := List(ServiceClient())
+	th.AssertNoErr(t, err)
+
+	coll, err := gophercloud.AllPages(res)
+	th.AssertNoErr(t, err)
+
+	actual := ToAPIVersions(coll)
+
+	expected := []APIVersion{
+		APIVersion{
+			Status: "CURRENT",
+			ID:     "v2.0",
+		},
+	}
+	th.AssertDeepEquals(t, expected, actual)
+}
+
+func TestAPIInfo(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	th.Mux.HandleFunc("/v2.0/", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+    "resources": [
+        {
+            "links": [
+                {
+                    "href": "http://23.253.228.211:9696/v2.0/subnets",
+                    "rel": "self"
+                }
+            ],
+            "name": "subnet",
+            "collection": "subnets"
+        },
+        {
+            "links": [
+                {
+                    "href": "http://23.253.228.211:9696/v2.0/networks",
+                    "rel": "self"
+                }
+            ],
+            "name": "network",
+            "collection": "networks"
+        },
+        {
+            "links": [
+                {
+                    "href": "http://23.253.228.211:9696/v2.0/ports",
+                    "rel": "self"
+                }
+            ],
+            "name": "port",
+            "collection": "ports"
+        }
+    ]
+}
+			`)
+	})
+
+	res, err := Get(ServiceClient(), "v2.0")
+	th.AssertNoErr(t, err)
+
+	coll, err := gophercloud.AllPages(res)
+	th.AssertNoErr(t, err)
+
+	actual := ToAPIResource(coll)
+	expected := []APIResource{
+		APIResource{
+			Name:       "subnet",
+			Collection: "subnets",
+		},
+		APIResource{
+			Name:       "network",
+			Collection: "networks",
+		},
+		APIResource{
+			Name:       "port",
+			Collection: "ports",
+		},
+	}
+	th.AssertDeepEquals(t, expected, actual)
+}
diff --git a/openstack/networking/v2/api_versions/results.go b/openstack/networking/v2/api_versions/results.go
new file mode 100644
index 0000000..159f03a
--- /dev/null
+++ b/openstack/networking/v2/api_versions/results.go
@@ -0,0 +1,11 @@
+package networks
+
+type APIVersion struct {
+	Status string
+	ID     string
+}
+
+type APIResource struct {
+	Name       string
+	Collection string
+}
diff --git a/openstack/networking/v2/api_versions/urls.go b/openstack/networking/v2/api_versions/urls.go
new file mode 100644
index 0000000..3f49261
--- /dev/null
+++ b/openstack/networking/v2/api_versions/urls.go
@@ -0,0 +1,15 @@
+package networks
+
+import (
+	"strings"
+
+	"github.com/rackspace/gophercloud"
+)
+
+func APIVersionsURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL("")
+}
+
+func APIInfoURL(c *gophercloud.ServiceClient, version string) string {
+	return c.ServiceURL(strings.TrimRight(version, "/") + "/")
+}
diff --git a/openstack/networking/v2/api_versions/urls_test.go b/openstack/networking/v2/api_versions/urls_test.go
new file mode 100644
index 0000000..1ef7f81
--- /dev/null
+++ b/openstack/networking/v2/api_versions/urls_test.go
@@ -0,0 +1,26 @@
+package networks
+
+import (
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const Endpoint = "http://localhost:57909/"
+
+func EndpointClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{Endpoint: Endpoint}
+}
+
+func TestAPIVersionsURL(t *testing.T) {
+	actual := APIVersionsURL(EndpointClient())
+	expected := Endpoint
+	th.AssertEquals(t, expected, actual)
+}
+
+func TestAPIInfoURL(t *testing.T) {
+	actual := APIInfoURL(EndpointClient(), "v2.0")
+	expected := Endpoint + "v2.0/"
+	th.AssertEquals(t, expected, actual)
+}