initial os-quota-set api; GET unit test
diff --git a/openstack/compute/v2/extensions/quota/doc.go b/openstack/compute/v2/extensions/quota/doc.go
new file mode 100644
index 0000000..9d62849
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/doc.go
@@ -0,0 +1,3 @@
+// Package quotas provides information and interaction with Quotas
+// extension for the OpenStack Compute service.
+package quotas
diff --git a/openstack/compute/v2/extensions/quota/fixtures.go b/openstack/compute/v2/extensions/quota/fixtures.go
new file mode 100644
index 0000000..992beff
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/fixtures.go
@@ -0,0 +1,59 @@
+// +build fixtures
+
+package quotas
+
+import (
+	"fmt"
+	"net/http"
+	"testing"
+
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/testhelper/client"
+)
+
+// GetOutput is a sample response to a Get call.
+const GetOutput = `
+{
+   "quota_set" : {
+      "instances" : 25,
+      "security_groups" : 10,
+      "security_group_rules" : 20,
+      "cores" : 200,
+      "injected_file_content_bytes" : 10240,
+      "injected_files" : 5,
+      "metadata_items" : 128,
+      "ram" : 200000,
+      "keypairs" : 10,
+      "injected_file_path_bytes" : 255
+   }
+}
+`
+
+const FirstTenantID = "555544443333222211110000ffffeeee"
+
+// FirstQuota is the first result in ListOutput.
+var FirstQuota = Quota{
+	FixedIps:                 0,
+	FloatingIps:              0,
+	InjectedFileContentBytes: 10240,
+	InjectedFilePathBytes:    255,
+	InjectedFiles:            5,
+	KeyPairs:                 10,
+	MetadataItems:            128,
+	Ram:                      200000,
+	SecurityGroupRules:       20,
+	SecurityGroups:           10,
+	Cores:                    200,
+	Instances:                25,
+}
+
+// HandleGetSuccessfully configures the test server to respond to a Get request for sample tenant
+func HandleGetSuccessfully(t *testing.T) {
+	th.Mux.HandleFunc("/os-quota-sets/"+FirstTenantID, func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "GET")
+		th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+
+		w.Header().Add("Content-Type", "application/json")
+		fmt.Fprintf(w, GetOutput)
+	})
+}
diff --git a/openstack/compute/v2/extensions/quota/requests.go b/openstack/compute/v2/extensions/quota/requests.go
new file mode 100644
index 0000000..7c3de24
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/requests.go
@@ -0,0 +1,19 @@
+package quotas
+
+import (
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+func List(client *gophercloud.ServiceClient) pagination.Pager {
+	return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
+		return QuotaPage{pagination.SinglePageBase(r)}
+	})
+}
+
+// Get returns public data about a previously created Quota.
+func Get(client *gophercloud.ServiceClient, name string) GetResult {
+	var res GetResult
+	_, res.Err = client.Get(getURL(client, name), &res.Body, nil)
+	return res
+}
diff --git a/openstack/compute/v2/extensions/quota/requests_test.go b/openstack/compute/v2/extensions/quota/requests_test.go
new file mode 100644
index 0000000..ec55cc7
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/requests_test.go
@@ -0,0 +1,16 @@
+package quotas
+
+import (
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/testhelper/client"
+	"testing"
+)
+
+func TestGet(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	HandleGetSuccessfully(t)
+	actual, err := Get(client.ServiceClient(), FirstTenantID).Extract()
+	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, &FirstQuota, actual)
+}
diff --git a/openstack/compute/v2/extensions/quota/results.go b/openstack/compute/v2/extensions/quota/results.go
new file mode 100644
index 0000000..07031f1
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/results.go
@@ -0,0 +1,117 @@
+package quotas
+
+import (
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/pagination"
+)
+
+// Quota is a set of operational limits that allow for control of compute usage.
+const sample = `
+{
+  "quota_set" : {
+	"fixed_ips" : -1,
+	"security_groups" : 10,
+	"id" : "56b6c3eb639e48c691052919e5a60dc3",
+	"injected_files" : 5,
+	"injected_file_path_bytes" : 255,
+	"cores" : 108,
+	"security_group_rules" : 20,
+	"keypairs" : 10,
+	"instances" : 25,
+	"ram" : 204800,
+	"metadata_items" : 128,
+	"injected_file_content_bytes" : 10240
+  }
+}
+`
+
+type Quota struct {
+	//ID is tenant associated with this quota_set
+	ID string `mapstructure:"id"`
+	//FixedIps is number of fixed ips alloted this quota_set
+	FixedIps int `mapstructure:"fixed_ips"`
+	// FloatingIps is number of floatinh ips alloted this quota_set
+	FloatingIps int `mapstructure:"floating_ips"`
+	// InjectedFileContentBytes is content bytes allowed for each injected file
+	InjectedFileContentBytes int `mapstructure:"injected_file_content_bytes"`
+	// InjectedFilePathBytes is allowed bytes for each injected file path
+	InjectedFilePathBytes int `mapstructure:"injected_file_path_bytes"`
+	// InjectedFiles is injected files allowed for each project
+	InjectedFiles int `mapstructure:"injected_files"`
+	// KeyPairs is number of ssh keypairs
+	KeyPairs int `mapstructure:"keypairs"`
+	// MetadataItems is number of metadata items allowed for each instance
+	MetadataItems int `mapstructure:"metadata_items"`
+	// Ram is megabytes allowed for each instance
+	Ram int `mapstructure:"ram"`
+	// SecurityGroupRules is rules allowed for each security group
+	SecurityGroupRules int `mapstructure:"security_group_rules"`
+	// SecurityGroups security groups allowed for each project
+	SecurityGroups int `mapstructure:"security_groups"`
+	// Cores is number of instance cores allowed for each project
+	Cores int `mapstructure:"cores"`
+	// Instances is number of instances allowed for each project
+	Instances int `mapstructure:"instances"`
+}
+
+// QuotaPage stores a single, only page of Quota results from a List call.
+type QuotaPage struct {
+	pagination.SinglePageBase
+}
+
+// IsEmpty determines whether or not a QuotaPage is empty.
+func (page QuotaPage) IsEmpty() (bool, error) {
+	ks, err := ExtractQuotas(page)
+	return len(ks) == 0, err
+}
+
+// ExtractQuotas interprets a page of results as a slice of Quotas.
+func ExtractQuotas(page pagination.Page) ([]Quota, error) {
+	var resp struct {
+		Quotas []Quota `mapstructure:"quotas"`
+	}
+
+	err := mapstructure.Decode(page.(QuotaPage).Body, &resp)
+	results := make([]Quota, len(resp.Quotas))
+	for i, q := range resp.Quotas {
+		results[i] = q
+	}
+	return results, err
+}
+
+type quotaResult struct {
+	gophercloud.Result
+}
+
+// Extract is a method that attempts to interpret any Quota resource response as a Quota struct.
+func (r quotaResult) Extract() (*Quota, error) {
+	if r.Err != nil {
+		return nil, r.Err
+	}
+
+	var res struct {
+		Quota *Quota `json:"quota_set" mapstructure:"quota_set"`
+	}
+
+	err := mapstructure.Decode(r.Body, &res)
+	return res.Quota, err
+}
+
+// CreateResult is the response from a Create operation. Call its Extract method to interpret it
+// as a Quota.
+type CreateResult struct {
+	quotaResult
+}
+
+// GetResult is the response from a Get operation. Call its Extract method to interpret it
+// as a Quota.
+type GetResult struct {
+	quotaResult
+}
+
+// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
+// the call succeeded or failed.
+type DeleteResult struct {
+	gophercloud.ErrResult
+}
diff --git a/openstack/compute/v2/extensions/quota/urls.go b/openstack/compute/v2/extensions/quota/urls.go
new file mode 100644
index 0000000..2900b89
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/urls.go
@@ -0,0 +1,25 @@
+package quotas
+
+import "github.com/rackspace/gophercloud"
+
+const resourcePath = "os-quota-sets"
+
+func resourceURL(c *gophercloud.ServiceClient) string {
+	return c.ServiceURL(resourcePath)
+}
+
+func listURL(c *gophercloud.ServiceClient) string {
+	return resourceURL(c)
+}
+
+func createURL(c *gophercloud.ServiceClient) string {
+	return resourceURL(c)
+}
+
+func getURL(c *gophercloud.ServiceClient, name string) string {
+	return c.ServiceURL(resourcePath, name)
+}
+
+func deleteURL(c *gophercloud.ServiceClient, name string) string {
+	return getURL(c, name)
+}
diff --git a/openstack/compute/v2/extensions/quota/urls_test.go b/openstack/compute/v2/extensions/quota/urls_test.go
new file mode 100644
index 0000000..cc0daf7
--- /dev/null
+++ b/openstack/compute/v2/extensions/quota/urls_test.go
@@ -0,0 +1,40 @@
+package quotas
+
+import (
+	"testing"
+
+	th "github.com/rackspace/gophercloud/testhelper"
+	"github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestListURL(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	c := client.ServiceClient()
+
+	th.CheckEquals(t, c.Endpoint+"os-quota-sets", listURL(c))
+}
+
+func TestCreateURL(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	c := client.ServiceClient()
+
+	th.CheckEquals(t, c.Endpoint+"os-quota-sets", createURL(c))
+}
+
+func TestGetURL(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	c := client.ServiceClient()
+
+	th.CheckEquals(t, c.Endpoint+"os-quota-sets/wat", getURL(c, "wat"))
+}
+
+func TestDeleteURL(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+	c := client.ServiceClient()
+
+	th.CheckEquals(t, c.Endpoint+"os-quota-sets/wat", deleteURL(c, "wat"))
+}