Choose a version from an API base endpoint.
diff --git a/openstack/utils/choose_version.go b/openstack/utils/choose_version.go
new file mode 100644
index 0000000..e1ddf6b
--- /dev/null
+++ b/openstack/utils/choose_version.go
@@ -0,0 +1,81 @@
+package utils
+
+import (
+	"fmt"
+
+	"github.com/racker/perigee"
+)
+
+// Version is a supported API version, corresponding to a vN package within the appropriate service.
+type Version struct {
+	ID       string
+	Priority int
+}
+
+// ChooseVersion queries the base endpoint of a API to choose the most recent non-experimental alternative from a service's
+// published versions.
+// It returns the highest-Priority Version among the alternatives that are provided, as well as its corresponding endpoint.
+func ChooseVersion(baseEndpoint string, recognized []*Version) (*Version, string, error) {
+	type linkResp struct {
+		Href string `json:"href"`
+		Rel  string `json:"rel"`
+	}
+
+	type valueResp struct {
+		ID     string     `json:"id"`
+		Status string     `json:"status"`
+		Links  []linkResp `json:"links"`
+	}
+
+	type versionsResp struct {
+		Values []valueResp `json:"values"`
+	}
+
+	type response struct {
+		Versions versionsResp `json:"versions"`
+	}
+
+	var resp response
+	_, err := perigee.Request("GET", baseEndpoint, perigee.Options{
+		Results: &resp,
+		OkCodes: []int{200},
+	})
+
+	if err != nil {
+		return nil, "", err
+	}
+
+	byID := make(map[string]*Version)
+	for _, version := range recognized {
+		byID[version.ID] = version
+	}
+
+	var highest *Version
+	var endpoint string
+
+	for _, value := range resp.Versions.Values {
+		if matching, ok := byID[value.ID]; ok {
+			if highest == nil || matching.Priority > highest.Priority {
+				highest = matching
+
+				found := false
+				for _, link := range value.Links {
+					if link.Rel == "self" {
+						found = true
+						endpoint = link.Href
+					}
+				}
+
+				if !found {
+					return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, baseEndpoint)
+				}
+			}
+		}
+	}
+
+	if highest == nil || endpoint == "" {
+		return nil, "", fmt.Errorf("No supported version available from endpoint %s", baseEndpoint)
+	}
+
+	return highest, endpoint, nil
+}
diff --git a/openstack/utils/choose_version_test.go b/openstack/utils/choose_version_test.go
new file mode 100644
index 0000000..a252790
--- /dev/null
+++ b/openstack/utils/choose_version_test.go
@@ -0,0 +1,57 @@
+package utils
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	"github.com/rackspace/gophercloud/testhelper"
+)
+
+func TestChooseVersion(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintf(w, `
+      {
+        "versions": {
+          "values": [
+            {
+              "status": "stable",
+              "id": "v3.0",
+              "links": [
+                { "href": "https://example.com:1000/", "rel": "self" }
+              ]
+            },
+            {
+              "status": "stable",
+              "id": "v2.0",
+              "links": [
+                { "href": "https://example.com:2000/", "rel": "self" }
+              ]
+            }
+          ]
+        }
+      }
+    `)
+	})
+
+	v2 := &Version{ID: "v2.0", Priority: 2}
+	v3 := &Version{ID: "v3.0", Priority: 3}
+
+	v, endpoint, err := ChooseVersion(testhelper.Endpoint(), []*Version{v2, v3})
+
+	if err != nil {
+		t.Fatalf("Unexpected error from ChooseVersion: %v", err)
+	}
+
+	if v != v3 {
+		t.Errorf("Expected %#v to win, but %#v did instead", v3, v)
+	}
+
+	expected := "https://example.com:1000/"
+	if endpoint != expected {
+		t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint)
+	}
+}