Adding error pages
diff --git a/rackspace/lb/v1/lbs/fixtures.go b/rackspace/lb/v1/lbs/fixtures.go
index db6545a..a31fe79 100644
--- a/rackspace/lb/v1/lbs/fixtures.go
+++ b/rackspace/lb/v1/lbs/fixtures.go
@@ -430,3 +430,54 @@
 		w.WriteHeader(http.StatusOK)
 	})
 }
+
+func mockGetErrorPageResponse(t *testing.T, id int) {
+	th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", 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, `
+{
+  "errorpage": {
+    "content": "<html>DEFAULT ERROR PAGE</html>"
+  }
+}
+			`)
+	})
+}
+
+func mockSetErrorPageResponse(t *testing.T, id int) {
+	th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "PUT")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		th.TestJSONRequest(t, r, `
+{
+	"errorpage": {
+		"content": "<html>New error page</html>"
+	}
+}
+		`)
+
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+	"errorpage": {
+		"content": "<html>New error page</html>"
+	}
+}
+			`)
+	})
+}
+
+func mockDeleteErrorPageResponse(t *testing.T, id int) {
+	th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "DELETE")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+		w.WriteHeader(http.StatusOK)
+	})
+}
diff --git a/rackspace/lb/v1/lbs/requests.go b/rackspace/lb/v1/lbs/requests.go
index 81431b0..2dd1595 100644
--- a/rackspace/lb/v1/lbs/requests.go
+++ b/rackspace/lb/v1/lbs/requests.go
@@ -452,3 +452,42 @@
 
 	return res
 }
+
+func GetErrorPage(client *gophercloud.ServiceClient, id int) ErrorPageResult {
+	var res ErrorPageResult
+
+	_, res.Err = perigee.Request("GET", errorPageURL(client, id), perigee.Options{
+		MoreHeaders: client.AuthenticatedHeaders(),
+		Results:     &res.Body,
+		OkCodes:     []int{200},
+	})
+
+	return res
+}
+
+func SetErrorPage(client *gophercloud.ServiceClient, id int, html string) ErrorPageResult {
+	var res ErrorPageResult
+
+	type stringMap map[string]string
+	reqBody := map[string]stringMap{"errorpage": stringMap{"content": html}}
+
+	_, res.Err = perigee.Request("PUT", errorPageURL(client, id), perigee.Options{
+		MoreHeaders: client.AuthenticatedHeaders(),
+		Results:     &res.Body,
+		ReqBody:     &reqBody,
+		OkCodes:     []int{200},
+	})
+
+	return res
+}
+
+func DeleteErrorPage(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
+	var res gophercloud.ErrResult
+
+	_, res.Err = perigee.Request("DELETE", errorPageURL(client, id), perigee.Options{
+		MoreHeaders: client.AuthenticatedHeaders(),
+		OkCodes:     []int{200},
+	})
+
+	return res
+}
diff --git a/rackspace/lb/v1/lbs/requests_test.go b/rackspace/lb/v1/lbs/requests_test.go
index 35ccfd7..acea25c 100644
--- a/rackspace/lb/v1/lbs/requests_test.go
+++ b/rackspace/lb/v1/lbs/requests_test.go
@@ -297,3 +297,40 @@
 	th.AssertNoErr(t, err)
 	th.AssertEquals(t, true, res)
 }
+
+func TestGetErrorPage(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockGetErrorPageResponse(t, id1)
+
+	content, err := GetErrorPage(client.ServiceClient(), id1).Extract()
+	th.AssertNoErr(t, err)
+
+	expected := &ErrorPage{Content: "<html>DEFAULT ERROR PAGE</html>"}
+	th.AssertDeepEquals(t, expected, content)
+}
+
+func TestSetErrorPage(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockSetErrorPageResponse(t, id1)
+
+	html := "<html>New error page</html>"
+	content, err := SetErrorPage(client.ServiceClient(), id1, html).Extract()
+	th.AssertNoErr(t, err)
+
+	expected := &ErrorPage{Content: html}
+	th.AssertDeepEquals(t, expected, content)
+}
+
+func TestDeleteErrorPage(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockDeleteErrorPageResponse(t, id1)
+
+	err := DeleteErrorPage(client.ServiceClient(), id1).ExtractErr()
+	th.AssertNoErr(t, err)
+}
diff --git a/rackspace/lb/v1/lbs/results.go b/rackspace/lb/v1/lbs/results.go
index d015d9b..21cc2dd 100644
--- a/rackspace/lb/v1/lbs/results.go
+++ b/rackspace/lb/v1/lbs/results.go
@@ -273,3 +273,38 @@
 	err := mapstructure.Decode(page.(AlgorithmPage).Body, &resp)
 	return resp.Algorithms, err
 }
+
+// ErrorPage represents the HTML file that is shown to an end user who is
+// attempting to access a load balancer node that is offline/unavailable.
+//
+// During provisioning, every load balancer is configured with a default error
+// page that gets displayed when traffic is requested for an offline node.
+//
+// You can add a single custom error page with an HTTP-based protocol to a load
+// balancer. Page updates override existing content. If a custom error page is
+// deleted, or the load balancer is changed to a non-HTTP protocol, the default
+// error page is restored.
+type ErrorPage struct {
+	Content string
+}
+
+// ErrorPageResult represents the result of an error page operation -
+// specifically getting or creating one.
+type ErrorPageResult struct {
+	gophercloud.Result
+}
+
+// Extract interprets any commonResult as an ErrorPage, if possible.
+func (r ErrorPageResult) Extract() (*ErrorPage, error) {
+	if r.Err != nil {
+		return nil, r.Err
+	}
+
+	var response struct {
+		ErrorPage ErrorPage `mapstructure:"errorpage"`
+	}
+
+	err := mapstructure.Decode(r.Body, &response)
+
+	return &response.ErrorPage, err
+}
diff --git a/rackspace/lb/v1/lbs/urls.go b/rackspace/lb/v1/lbs/urls.go
index 5100e94..bf1e8b5 100644
--- a/rackspace/lb/v1/lbs/urls.go
+++ b/rackspace/lb/v1/lbs/urls.go
@@ -11,6 +11,7 @@
 	protocolsPath  = "protocols"
 	algorithmsPath = "algorithms"
 	logPath        = "connectionlogging"
+	epPath         = "errorpage"
 )
 
 func resourceURL(c *gophercloud.ServiceClient, id int) string {
@@ -32,3 +33,7 @@
 func loggingURL(c *gophercloud.ServiceClient, id int) string {
 	return c.ServiceURL(path, strconv.Itoa(id), logPath)
 }
+
+func errorPageURL(c *gophercloud.ServiceClient, id int) string {
+	return c.ServiceURL(path, strconv.Itoa(id), epPath)
+}