cdn operations; unit test stubs
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index 25b68fd..9bc73e7 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -198,7 +198,7 @@
 	var res GetResult
 	resp, err := perigee.Request("HEAD", getURL(c, containerName), perigee.Options{
 		MoreHeaders: c.Provider.AuthenticatedHeaders(),
-		OkCodes:     []int{204},
+		OkCodes:     []int{200, 204},
 	})
 	res.Header = resp.HttpResponse.Header
 	res.Err = err
diff --git a/rackspace/objectstorage/v1/cdncontainers/delegate.go b/rackspace/objectstorage/v1/cdncontainers/delegate.go
new file mode 100644
index 0000000..40c4ed1
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/delegate.go
@@ -0,0 +1,69 @@
+package cdncontainers
+
+import (
+	"github.com/rackspace/gophercloud"
+	os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+// ExtractNames interprets a page of List results when just the container
+// names are requested.
+func ExtractNames(page pagination.Page) ([]string, error) {
+	return os.ExtractNames(page)
+}
+
+// ListOpts are options for listing Rackspace CDN containers.
+type ListOpts struct {
+	EndMarker string `q:"end_marker"`
+	Format    string `q:"format"`
+	Limit     int    `q:"limit"`
+	Marker    string `q:"marker"`
+}
+
+// ToContainerListParams formats a ListOpts into a query string and boolean
+// representing whether to list complete information for each container.
+func (opts ListOpts) ToContainerListParams() (bool, string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return false, "", err
+	}
+	return false, q.String(), nil
+}
+
+// List is a function that retrieves containers associated with the account as
+// well as account metadata. It returns a pager which can be iterated with the
+// EachPage function.
+func List(c *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
+	return os.List(c, opts)
+}
+
+// Get is a function that retrieves the metadata of a container. To extract just
+// the custom metadata, pass the GetResult response to the ExtractMetadata
+// function.
+func Get(c *gophercloud.ServiceClient, containerName string) os.GetResult {
+	return os.Get(c, containerName)
+}
+
+// UpdateOpts is a structure that holds parameters for updating, creating, or
+// deleting a container's metadata.
+type UpdateOpts struct {
+	CDNEnabled   bool `h:"X-Cdn-Enabled"`
+	LogRetention bool `h:"X-Log-Retention"`
+	TTL          int  `h:"X-Ttl"`
+}
+
+// ToContainerUpdateMap formats a CreateOpts into a map of headers.
+func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) {
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+
+	return h, nil
+}
+
+// Update is a function that creates, updates, or deletes a container's
+// metadata.
+func Update(c *gophercloud.ServiceClient, containerName string, opts os.UpdateOptsBuilder) os.UpdateResult {
+	return os.Update(c, containerName, opts)
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/delegate_test.go b/rackspace/objectstorage/v1/cdncontainers/delegate_test.go
new file mode 100644
index 0000000..1b2124d
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/delegate_test.go
@@ -0,0 +1 @@
+package cdncontainers
diff --git a/rackspace/objectstorage/v1/cdncontainers/requests.go b/rackspace/objectstorage/v1/cdncontainers/requests.go
new file mode 100644
index 0000000..55122a1
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/requests.go
@@ -0,0 +1,58 @@
+package cdncontainers
+
+import (
+	"github.com/racker/perigee"
+	"github.com/rackspace/gophercloud"
+)
+
+// EnableOptsBuilder allows extensions to add additional parameters to the Enable
+// request.
+type EnableOptsBuilder interface {
+	ToCDNContainerEnableMap() (map[string]string, error)
+}
+
+// EnableOpts is a structure that holds options for enabling a CDN container.
+type EnableOpts struct {
+	// CDNEnabled indicates whether or not the container is CDN enabled. Set to
+	// `true` to enable the container. Note that changing this setting from true
+	// to false will disable the container in the CDN but only after the TTL has
+	// expired.
+	CDNEnabled bool `h:"X-Cdn-Enabled"`
+	// TTL is the time-to-live for the container (in seconds).
+	TTL int `h:"X-Ttl"`
+}
+
+// ToCDNContainerEnableMap formats an EnableOpts into a map of headers.
+func (opts EnableOpts) ToCDNContainerEnableMap() (map[string]string, error) {
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	return h, nil
+}
+
+// Enable is a function that enables/disables a CDN container.
+func Enable(c *gophercloud.ServiceClient, containerName string, opts EnableOptsBuilder) EnableResult {
+	var res EnableResult
+	h := c.Provider.AuthenticatedHeaders()
+
+	if opts != nil {
+		headers, err := opts.ToCDNContainerEnableMap()
+		if err != nil {
+			res.Err = err
+			return res
+		}
+
+		for k, v := range headers {
+			h[k] = v
+		}
+	}
+
+	resp, err := perigee.Request("PUT", enableURL(c, containerName), perigee.Options{
+		MoreHeaders: h,
+		OkCodes:     []int{201, 202, 204},
+	})
+	res.Resp = &resp.HttpResponse
+	res.Err = err
+	return res
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/requests_test.go b/rackspace/objectstorage/v1/cdncontainers/requests_test.go
new file mode 100644
index 0000000..1b2124d
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/requests_test.go
@@ -0,0 +1 @@
+package cdncontainers
diff --git a/rackspace/objectstorage/v1/cdncontainers/results.go b/rackspace/objectstorage/v1/cdncontainers/results.go
new file mode 100644
index 0000000..87e420b
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/results.go
@@ -0,0 +1,8 @@
+package cdncontainers
+
+import objectstorage "github.com/rackspace/gophercloud/openstack/objectstorage/v1"
+
+// EnableResult represents the result of a get operation.
+type EnableResult struct {
+	objectstorage.CommonResult
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/urls.go b/rackspace/objectstorage/v1/cdncontainers/urls.go
new file mode 100644
index 0000000..abcf238
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/urls.go
@@ -0,0 +1,19 @@
+package cdncontainers
+
+import "github.com/rackspace/gophercloud"
+
+func listURL(c *gophercloud.ServiceClient) string {
+	return c.Endpoint
+}
+
+func enableURL(c *gophercloud.ServiceClient, containerName string) string {
+	return c.ServiceURL(containerName)
+}
+
+func getURL(c *gophercloud.ServiceClient, containerName string) string {
+	return c.ServiceURL(containerName)
+}
+
+func updateURL(c *gophercloud.ServiceClient, containerName string) string {
+	return c.ServiceURL(containerName)
+}
diff --git a/rackspace/objectstorage/v1/cdncontainers/urls_test.go b/rackspace/objectstorage/v1/cdncontainers/urls_test.go
new file mode 100644
index 0000000..8acd01b
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdncontainers/urls_test.go
@@ -0,0 +1,38 @@
+package cdncontainers
+
+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 TestListURL(t *testing.T) {
+	actual := listURL(endpointClient())
+	expected := endpoint
+	th.CheckEquals(t, expected, actual)
+}
+
+func TestEnableURL(t *testing.T) {
+	actual := enableURL(endpointClient(), "foo")
+	expected := endpoint + "foo"
+	th.CheckEquals(t, expected, actual)
+}
+
+func TestGetURL(t *testing.T) {
+	actual := getURL(endpointClient(), "foo")
+	expected := endpoint + "foo"
+	th.CheckEquals(t, expected, actual)
+}
+
+func TestUpdateURL(t *testing.T) {
+	actual := updateURL(endpointClient(), "foo")
+	expected := endpoint + "foo"
+	th.CheckEquals(t, expected, actual)
+}
diff --git a/rackspace/objectstorage/v1/cdnobjects/delegate.go b/rackspace/objectstorage/v1/cdnobjects/delegate.go
new file mode 100644
index 0000000..e9d2ff1
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdnobjects/delegate.go
@@ -0,0 +1,11 @@
+package cdnobjects
+
+import (
+	"github.com/rackspace/gophercloud"
+	os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
+)
+
+// Delete is a function that deletes an object from the CDN.
+func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DeleteOptsBuilder) os.DeleteResult {
+	return os.Delete(c, containerName, objectName, nil)
+}
diff --git a/rackspace/objectstorage/v1/cdnobjects/delegate_test.go b/rackspace/objectstorage/v1/cdnobjects/delegate_test.go
new file mode 100644
index 0000000..03d45e5
--- /dev/null
+++ b/rackspace/objectstorage/v1/cdnobjects/delegate_test.go
@@ -0,0 +1 @@
+package cdnobjects