IDs are actually integers apparently
diff --git a/openstack/compute/v2/extensions/defsecrules/fixtures.go b/openstack/compute/v2/extensions/defsecrules/fixtures.go
index 4aa7530..4fe2211 100644
--- a/openstack/compute/v2/extensions/defsecrules/fixtures.go
+++ b/openstack/compute/v2/extensions/defsecrules/fixtures.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"net/http"
+	"strconv"
 	"testing"
 
 	th "github.com/rackspace/gophercloud/testhelper"
@@ -24,7 +25,7 @@
   "security_group_default_rules": [
     {
       "from_port": 80,
-      "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+      "id": 1,
       "ip_protocol": "TCP",
       "ip_range": {
         "cidr": "10.10.10.0/24"
@@ -65,16 +66,15 @@
     "ip_range": {
       "cidr": "10.10.12.0/24"
     },
-    "to_port": 80,
-		"id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5"
+    "to_port": 80
   }
 }
 `)
 	})
 }
 
-func mockGetRuleResponse(t *testing.T, ruleID string) {
-	url := rootPath + "/" + ruleID
+func mockGetRuleResponse(t *testing.T, ruleID int) {
+	url := rootPath + "/" + strconv.Itoa(ruleID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "GET")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
@@ -85,7 +85,7 @@
 		fmt.Fprintf(w, `
 {
   "security_group_default_rule": {
-    "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "id": 1,
     "from_port": 80,
     "to_port": 80,
     "ip_protocol": "TCP",
@@ -98,8 +98,8 @@
 	})
 }
 
-func mockDeleteRuleResponse(t *testing.T, ruleID string) {
-	url := rootPath + "/" + ruleID
+func mockDeleteRuleResponse(t *testing.T, ruleID int) {
+	url := rootPath + "/" + strconv.Itoa(ruleID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "DELETE")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
diff --git a/openstack/compute/v2/extensions/defsecrules/requests.go b/openstack/compute/v2/extensions/defsecrules/requests.go
index f324a00..d411a37 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests.go
@@ -35,7 +35,7 @@
 	CIDR string `json:"cidr,omitempty"`
 }
 
-// CreateRuleOptsBuilder builds the create rule options into a serializable format.
+// CreateOptsBuilder builds the create rule options into a serializable format.
 type CreateOptsBuilder interface {
 	ToRuleCreateMap() (map[string]interface{}, error)
 }
@@ -65,6 +65,7 @@
 	return map[string]interface{}{"security_group_default_rule": rule}, nil
 }
 
+// Create is the operation responsible for creating a new default rule.
 func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
 	var result CreateResult
 
@@ -85,7 +86,7 @@
 }
 
 // Get will return details for a particular default rule.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
+func Get(client *gophercloud.ServiceClient, id int) GetResult {
 	var result GetResult
 
 	_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
@@ -98,7 +99,7 @@
 }
 
 // Delete will permanently delete a default rule from the project.
-func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
+func Delete(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
 	var result gophercloud.ErrResult
 
 	_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
diff --git a/openstack/compute/v2/extensions/defsecrules/requests_test.go b/openstack/compute/v2/extensions/defsecrules/requests_test.go
index bc12849..5f43b34 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests_test.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests_test.go
@@ -9,7 +9,7 @@
 	"github.com/rackspace/gophercloud/testhelper/client"
 )
 
-const ruleID = "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5"
+const ruleID = 1
 
 func TestList(t *testing.T) {
 	th.SetupHTTP()
diff --git a/openstack/compute/v2/extensions/defsecrules/results.go b/openstack/compute/v2/extensions/defsecrules/results.go
index 5f84b0e..8404b82 100644
--- a/openstack/compute/v2/extensions/defsecrules/results.go
+++ b/openstack/compute/v2/extensions/defsecrules/results.go
@@ -8,6 +8,8 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// DefaultRule represents a default rule - which is identical to a
+// normal security rule.
 type DefaultRule secgroups.Rule
 
 // DefaultRulePage is a single page of a DefaultRule collection.
diff --git a/openstack/compute/v2/extensions/defsecrules/urls.go b/openstack/compute/v2/extensions/defsecrules/urls.go
index cc928ab..07244f7 100644
--- a/openstack/compute/v2/extensions/defsecrules/urls.go
+++ b/openstack/compute/v2/extensions/defsecrules/urls.go
@@ -1,11 +1,15 @@
 package defsecrules
 
-import "github.com/rackspace/gophercloud"
+import (
+	"strconv"
+
+	"github.com/rackspace/gophercloud"
+)
 
 const rulepath = "os-security-group-default-rules"
 
-func resourceURL(c *gophercloud.ServiceClient, id string) string {
-	return c.ServiceURL(rulepath, id)
+func resourceURL(c *gophercloud.ServiceClient, id int) string {
+	return c.ServiceURL(rulepath, strconv.Itoa(id))
 }
 
 func rootURL(c *gophercloud.ServiceClient) string {
diff --git a/openstack/compute/v2/extensions/secgroups/fixtures.go b/openstack/compute/v2/extensions/secgroups/fixtures.go
index 2cf4ea5..7943c71 100644
--- a/openstack/compute/v2/extensions/secgroups/fixtures.go
+++ b/openstack/compute/v2/extensions/secgroups/fixtures.go
@@ -16,7 +16,7 @@
   "security_groups": [
     {
       "description": "default",
-      "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+      "id": 1,
       "name": "default",
       "rules": [],
       "tenant_id": "openstack"
@@ -71,7 +71,7 @@
 {
   "security_group": {
     "description": "something",
-    "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "id": 1,
     "name": "test",
     "rules": [],
     "tenant_id": "openstack"
@@ -81,8 +81,8 @@
 	})
 }
 
-func mockUpdateGroupResponse(t *testing.T, groupID string) {
-	url := fmt.Sprintf("%s/%s", rootPath, groupID)
+func mockUpdateGroupResponse(t *testing.T, groupID int) {
+	url := fmt.Sprintf("%s/%d", rootPath, groupID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "PUT")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
@@ -102,7 +102,7 @@
 {
   "security_group": {
     "description": "something",
-    "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "id": 1,
     "name": "new_name",
     "rules": [],
     "tenant_id": "openstack"
@@ -112,8 +112,8 @@
 	})
 }
 
-func mockGetGroupsResponse(t *testing.T, groupID string) {
-	url := fmt.Sprintf("%s/%s", rootPath, groupID)
+func mockGetGroupsResponse(t *testing.T, groupID int) {
+	url := fmt.Sprintf("%s/%d", rootPath, groupID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "GET")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
@@ -125,7 +125,7 @@
 {
   "security_group": {
     "description": "default",
-    "id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "id": 1,
     "name": "default",
     "rules": [
       {
@@ -136,11 +136,11 @@
         },
         "ip_protocol": "TCP",
         "to_port": 85,
-        "parent_group_id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+        "parent_group_id": 1,
         "ip_range": {
 						"cidr": "0.0.0.0"
 				},
-        "id": "ebe599e2-6b8c-457c-b1ff-a75e48f10923"
+        "id": 2
       }
     ],
     "tenant_id": "openstack"
@@ -150,8 +150,8 @@
 	})
 }
 
-func mockDeleteGroupResponse(t *testing.T, groupID string) {
-	url := fmt.Sprintf("%s/%s", rootPath, groupID)
+func mockDeleteGroupResponse(t *testing.T, groupID int) {
+	url := fmt.Sprintf("%s/%d", rootPath, groupID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "DELETE")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
@@ -171,7 +171,7 @@
     "from_port": 22,
     "ip_protocol": "TCP",
     "to_port": 22,
-    "parent_group_id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "parent_group_id": 1,
     "cidr": "0.0.0.0/0"
   }
 }	`)
@@ -186,18 +186,18 @@
     "group": {},
     "ip_protocol": "TCP",
     "to_port": 22,
-    "parent_group_id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+    "parent_group_id": 1,
     "ip_range": {
       "cidr": "0.0.0.0/0"
     },
-    "id": "f9a97fcf-3a97-47b0-b76f-919136afb7ed"
+    "id": 2
   }
 }`)
 	})
 }
 
-func mockDeleteRuleResponse(t *testing.T, ruleID string) {
-	url := fmt.Sprintf("/os-security-group-rules/%s", ruleID)
+func mockDeleteRuleResponse(t *testing.T, ruleID int) {
+	url := fmt.Sprintf("/os-security-group-rules/%d", ruleID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
 		th.TestMethod(t, r, "DELETE")
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
diff --git a/openstack/compute/v2/extensions/secgroups/requests.go b/openstack/compute/v2/extensions/secgroups/requests.go
index 3147310..3707840 100644
--- a/openstack/compute/v2/extensions/secgroups/requests.go
+++ b/openstack/compute/v2/extensions/secgroups/requests.go
@@ -108,7 +108,7 @@
 
 // Update will modify the mutable properties of a security group, notably its
 // name and description.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
+func Update(client *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult {
 	var result UpdateResult
 
 	reqBody, err := opts.ToSecGroupUpdateMap()
@@ -128,7 +128,7 @@
 }
 
 // Get will return details for a particular security group.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
+func Get(client *gophercloud.ServiceClient, id int) GetResult {
 	var result GetResult
 
 	_, result.Err = perigee.Request("GET", resourceURL(client, id), perigee.Options{
@@ -141,7 +141,7 @@
 }
 
 // Delete will permanently delete a security group from the project.
-func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
+func Delete(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
 	var result gophercloud.ErrResult
 
 	_, result.Err = perigee.Request("DELETE", resourceURL(client, id), perigee.Options{
@@ -156,7 +156,7 @@
 // existing security group.
 type CreateRuleOpts struct {
 	// Required - the ID of the group that this rule will be added to.
-	ParentGroupID string `json:"parent_group_id"`
+	ParentGroupID int `json:"parent_group_id"`
 
 	// Required - the lower bound of the port range that will be opened.
 	FromPort int `json:"from_port"`
@@ -188,7 +188,7 @@
 func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
 	rule := make(map[string]interface{})
 
-	if opts.ParentGroupID == "" {
+	if opts.ParentGroupID == 0 {
 		return rule, errors.New("A ParentGroupID must be set")
 	}
 	if opts.FromPort == 0 {
@@ -242,7 +242,7 @@
 }
 
 // DeleteRule will permanently delete a rule from a security group.
-func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
+func DeleteRule(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
 	var result gophercloud.ErrResult
 
 	_, result.Err = perigee.Request("DELETE", resourceRuleURL(client, id), perigee.Options{
diff --git a/openstack/compute/v2/extensions/secgroups/requests_test.go b/openstack/compute/v2/extensions/secgroups/requests_test.go
index f2f6eb4..1c5d22f 100644
--- a/openstack/compute/v2/extensions/secgroups/requests_test.go
+++ b/openstack/compute/v2/extensions/secgroups/requests_test.go
@@ -10,8 +10,8 @@
 
 const (
 	serverID = "{serverID}"
-	groupID  = "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5"
-	ruleID   = "a4070a0f-5383-454c-872d-58c034bc981b"
+	groupID  = 1
+	ruleID   = 2
 )
 
 func TestList(t *testing.T) {
@@ -32,7 +32,7 @@
 
 		expected := []SecurityGroup{
 			SecurityGroup{
-				ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+				ID:          groupID,
 				Description: "default",
 				Name:        "default",
 				Rules:       []Rule{},
@@ -67,7 +67,7 @@
 
 		expected := []SecurityGroup{
 			SecurityGroup{
-				ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+				ID:          groupID,
 				Description: "default",
 				Name:        "default",
 				Rules:       []Rule{},
@@ -99,7 +99,7 @@
 	th.AssertNoErr(t, err)
 
 	expected := &SecurityGroup{
-		ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		ID:          groupID,
 		Name:        "test",
 		Description: "something",
 		TenantID:    "openstack",
@@ -119,7 +119,7 @@
 	th.AssertNoErr(t, err)
 
 	expected := &SecurityGroup{
-		ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		ID:          groupID,
 		Name:        "new_name",
 		Description: "something",
 		TenantID:    "openstack",
@@ -138,7 +138,7 @@
 	th.AssertNoErr(t, err)
 
 	expected := &SecurityGroup{
-		ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		ID:          groupID,
 		Description: "default",
 		Name:        "default",
 		TenantID:    "openstack",
@@ -149,8 +149,8 @@
 				IPProtocol:    "TCP",
 				IPRange:       IPRange{CIDR: "0.0.0.0"},
 				Group:         Group{TenantID: "openstack", Name: "default"},
-				ParentGroupID: "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
-				ID:            "ebe599e2-6b8c-457c-b1ff-a75e48f10923",
+				ParentGroupID: groupID,
+				ID:            ruleID,
 			},
 		},
 	}
@@ -175,7 +175,7 @@
 	mockAddRuleResponse(t)
 
 	opts := CreateRuleOpts{
-		ParentGroupID: "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		ParentGroupID: groupID,
 		FromPort:      22,
 		ToPort:        22,
 		IPProtocol:    "TCP",
@@ -190,9 +190,9 @@
 		ToPort:        22,
 		Group:         Group{},
 		IPProtocol:    "TCP",
-		ParentGroupID: "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		ParentGroupID: groupID,
 		IPRange:       IPRange{CIDR: "0.0.0.0/0"},
-		ID:            "f9a97fcf-3a97-47b0-b76f-919136afb7ed",
+		ID:            ruleID,
 	}
 
 	th.AssertDeepEquals(t, expected, rule)
diff --git a/openstack/compute/v2/extensions/secgroups/results.go b/openstack/compute/v2/extensions/secgroups/results.go
index aaf5052..e2ac853 100644
--- a/openstack/compute/v2/extensions/secgroups/results.go
+++ b/openstack/compute/v2/extensions/secgroups/results.go
@@ -10,7 +10,7 @@
 // SecurityGroup represents a security group.
 type SecurityGroup struct {
 	// The unique ID of the group.
-	ID string
+	ID int
 
 	// The human-readable name of the group, which needs to be unique.
 	Name string
@@ -29,7 +29,7 @@
 // security group operates and what inbound traffic it allows in.
 type Rule struct {
 	// The unique ID
-	ID string
+	ID int
 
 	// The lower bound of the port range which this security group should open up
 	FromPort int `mapstructure:"from_port"`
@@ -44,7 +44,7 @@
 	IPRange IPRange `mapstructure:"ip_range"`
 
 	// The security group ID to which this rule belongs
-	ParentGroupID string `mapstructure:"parent_group_id"`
+	ParentGroupID int `mapstructure:"parent_group_id"`
 
 	// Not documented.
 	Group Group
diff --git a/openstack/compute/v2/extensions/secgroups/urls.go b/openstack/compute/v2/extensions/secgroups/urls.go
index f4760b6..2363d20 100644
--- a/openstack/compute/v2/extensions/secgroups/urls.go
+++ b/openstack/compute/v2/extensions/secgroups/urls.go
@@ -1,14 +1,18 @@
 package secgroups
 
-import "github.com/rackspace/gophercloud"
+import (
+	"strconv"
+
+	"github.com/rackspace/gophercloud"
+)
 
 const (
 	secgrouppath = "os-security-groups"
 	rulepath     = "os-security-group-rules"
 )
 
-func resourceURL(c *gophercloud.ServiceClient, id string) string {
-	return c.ServiceURL(secgrouppath, id)
+func resourceURL(c *gophercloud.ServiceClient, id int) string {
+	return c.ServiceURL(secgrouppath, strconv.Itoa(id))
 }
 
 func rootURL(c *gophercloud.ServiceClient) string {
@@ -23,8 +27,8 @@
 	return c.ServiceURL(rulepath)
 }
 
-func resourceRuleURL(c *gophercloud.ServiceClient, id string) string {
-	return c.ServiceURL(rulepath, id)
+func resourceRuleURL(c *gophercloud.ServiceClient, id int) string {
+	return c.ServiceURL(rulepath, strconv.Itoa(id))
 }
 
 func serverActionURL(c *gophercloud.ServiceClient, id string) string {