Adding ability to list LB algorithms
diff --git a/rackspace/lb/v1/lbs/fixtures.go b/rackspace/lb/v1/lbs/fixtures.go
index 007fa15..53f5334 100644
--- a/rackspace/lb/v1/lbs/fixtures.go
+++ b/rackspace/lb/v1/lbs/fixtures.go
@@ -349,3 +349,35 @@
 	`)
 	})
 }
+
+func mockListAlgorithmsResponse(t *testing.T) {
+	th.Mux.HandleFunc("/loadbalancers/algorithms", 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, `
+{
+  "algorithms": [
+    {
+      "name": "LEAST_CONNECTIONS"
+    },
+    {
+      "name": "RANDOM"
+    },
+    {
+      "name": "ROUND_ROBIN"
+    },
+    {
+      "name": "WEIGHTED_LEAST_CONNECTIONS"
+    },
+    {
+      "name": "WEIGHTED_ROUND_ROBIN"
+    }
+  ]
+}
+			`)
+	})
+}
diff --git a/rackspace/lb/v1/lbs/requests.go b/rackspace/lb/v1/lbs/requests.go
index 7c5be06..63b8513 100644
--- a/rackspace/lb/v1/lbs/requests.go
+++ b/rackspace/lb/v1/lbs/requests.go
@@ -104,7 +104,7 @@
 
 	// Optional - algorithm that defines how traffic should be directed between
 	// back-end nodes.
-	Algorithm Algorithm
+	Algorithm string
 
 	// Optional - current connection logging configuration.
 	ConnectionLogging *ConnectionLogging
@@ -320,7 +320,7 @@
 	HalfClosed enabledState
 
 	// Optional - see the Algorithm field in CreateOpts for more information.
-	Algorithm Algorithm
+	Algorithm string
 
 	// Optional - see the Port field in CreateOpts for more information.
 	Port int
@@ -393,3 +393,12 @@
 		return ProtocolPage{pagination.SinglePageBase(r)}
 	})
 }
+
+// ListAlgorithms is the operation responsible for returning a paginated
+// collection of load balancer algorithms.
+func ListAlgorithms(client *gophercloud.ServiceClient) pagination.Pager {
+	url := algorithmsURL(client)
+	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
+		return AlgorithmPage{pagination.SinglePageBase(r)}
+	})
+}
diff --git a/rackspace/lb/v1/lbs/requests_test.go b/rackspace/lb/v1/lbs/requests_test.go
index 033cd7f..fa1e658 100644
--- a/rackspace/lb/v1/lbs/requests_test.go
+++ b/rackspace/lb/v1/lbs/requests_test.go
@@ -34,7 +34,7 @@
 				ID:        71,
 				Protocol:  "HTTP",
 				Port:      80,
-				Algorithm: RAND,
+				Algorithm: "RANDOM",
 				Status:    ACTIVE,
 				NodeCount: 3,
 				VIPs: []vips.VIP{
@@ -87,7 +87,7 @@
 		Protocol:   "HTTP",
 		HalfClosed: false,
 		Port:       83,
-		Algorithm:  RAND,
+		Algorithm:  "RANDOM",
 		Status:     BUILD,
 		Timeout:    30,
 		Cluster:    Cluster{Name: "ztm-n01.staging1.lbaas.rackspace.net"},
@@ -158,7 +158,7 @@
 		ID:                2000,
 		Protocol:          "HTTP",
 		Port:              80,
-		Algorithm:         RAND,
+		Algorithm:         "RANDOM",
 		Status:            ACTIVE,
 		Timeout:           30,
 		ConnectionLogging: ConnectionLogging{Enabled: true},
@@ -217,7 +217,7 @@
 		Name:          "a-new-loadbalancer",
 		Protocol:      "TCP",
 		HalfClosed:    Enabled,
-		Algorithm:     RAND,
+		Algorithm:     "RANDOM",
 		Port:          8080,
 		Timeout:       100,
 		HTTPSRedirect: Disabled,
@@ -258,3 +258,33 @@
 	th.AssertNoErr(t, err)
 	th.AssertEquals(t, 1, count)
 }
+
+func TestListAlgorithms(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockListAlgorithmsResponse(t)
+
+	count := 0
+
+	err := ListAlgorithms(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
+		count++
+		actual, err := ExtractAlgorithms(page)
+		th.AssertNoErr(t, err)
+
+		expected := []Algorithm{
+			Algorithm{Name: "LEAST_CONNECTIONS"},
+			Algorithm{Name: "RANDOM"},
+			Algorithm{Name: "ROUND_ROBIN"},
+			Algorithm{Name: "WEIGHTED_LEAST_CONNECTIONS"},
+			Algorithm{Name: "WEIGHTED_ROUND_ROBIN"},
+		}
+
+		th.CheckDeepEquals(t, expected, actual)
+
+		return true, nil
+	})
+
+	th.AssertNoErr(t, err)
+	th.AssertEquals(t, 1, count)
+}
diff --git a/rackspace/lb/v1/lbs/results.go b/rackspace/lb/v1/lbs/results.go
index d73d823..a556f21 100644
--- a/rackspace/lb/v1/lbs/results.go
+++ b/rackspace/lb/v1/lbs/results.go
@@ -19,27 +19,10 @@
 }
 
 // Algorithm defines how traffic should be directed between back-end nodes.
-type Algorithm string
-
-const (
-	// LC directs traffic to the node with the lowest number of connections.
-	LC = "LEAST_CONNECTIONS"
-
-	// RAND directs traffic to nodes at random.
-	RAND = "RANDOM"
-
-	// RR directs traffic to each of the nodes in turn.
-	RR = "ROUND_ROBIN"
-
-	// WLC directs traffic to a node based on the number of concurrent
-	// connections and its weight.
-	WLC = "WEIGHTED_LEAST_CONNECTIONS"
-
-	// WRR directs traffic to a node according to the RR algorithm, but with
-	// different proportions of traffic being directed to the back-end nodes.
-	// Weights must be defined as part of the node configuration.
-	WRR = "WEIGHTED_ROUND_ROBIN"
-)
+type Algorithm struct {
+	// The name of the algorithm, e.g RANDOM, ROUND_ROBIN, etc.
+	Name string
+}
 
 // Status represents the potential state of a load balancer resource.
 type Status string
@@ -95,7 +78,7 @@
 
 	// Defines how traffic should be directed between back-end nodes. The default
 	// algorithm is RANDOM. See Algorithm type for a list of accepted values.
-	Algorithm Algorithm
+	Algorithm string
 
 	// The current status of the load balancer.
 	Status Status
@@ -266,8 +249,32 @@
 	var resp struct {
 		Protocols []Protocol `mapstructure:"protocols" json:"protocols"`
 	}
-
 	err := mapstructure.Decode(page.(ProtocolPage).Body, &resp)
-
 	return resp.Protocols, err
 }
+
+// AlgorithmPage is the page returned by a pager when traversing over a
+// collection of LB algorithms.
+type AlgorithmPage struct {
+	pagination.SinglePageBase
+}
+
+// IsEmpty checks whether a ProtocolPage struct is empty.
+func (p AlgorithmPage) IsEmpty() (bool, error) {
+	is, err := ExtractAlgorithms(p)
+	if err != nil {
+		return true, nil
+	}
+	return len(is) == 0, nil
+}
+
+// ExtractAlgorithms accepts a Page struct, specifically a AlgorithmPage struct,
+// and extracts the elements into a slice of Algorithm structs. In other
+// words, a generic collection is mapped into a relevant slice.
+func ExtractAlgorithms(page pagination.Page) ([]Algorithm, error) {
+	var resp struct {
+		Algorithms []Algorithm `mapstructure:"algorithms" json:"algorithms"`
+	}
+	err := mapstructure.Decode(page.(AlgorithmPage).Body, &resp)
+	return resp.Algorithms, err
+}
diff --git a/rackspace/lb/v1/lbs/urls.go b/rackspace/lb/v1/lbs/urls.go
index 1de038c..7b435b3 100644
--- a/rackspace/lb/v1/lbs/urls.go
+++ b/rackspace/lb/v1/lbs/urls.go
@@ -7,8 +7,9 @@
 )
 
 const (
-	path          = "loadbalancers"
-	protocolsPath = "protocols"
+	path           = "loadbalancers"
+	protocolsPath  = "protocols"
+	algorithmsPath = "algorithms"
 )
 
 func resourceURL(c *gophercloud.ServiceClient, id int) string {
@@ -22,3 +23,7 @@
 func protocolsURL(c *gophercloud.ServiceClient) string {
 	return c.ServiceURL(path, protocolsPath)
 }
+
+func algorithmsURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL(path, algorithmsPath)
+}