Apparently there's an update too :boom:
diff --git a/openstack/compute/v2/extensions/secgroups/fixtures.go b/openstack/compute/v2/extensions/secgroups/fixtures.go
index 519bc74..1446912 100644
--- a/openstack/compute/v2/extensions/secgroups/fixtures.go
+++ b/openstack/compute/v2/extensions/secgroups/fixtures.go
@@ -81,6 +81,37 @@
 	})
 }
 
+func mockUpdateGroupResponse(t *testing.T, groupID string) {
+	url := fmt.Sprintf("%s/%s", rootPath, groupID)
+	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+		th.TestMethod(t, r, "POST")
+		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+		th.TestJSONRequest(t, r, `
+{
+	"security_group": {
+		"name": "new_name"
+	}
+}
+	`)
+
+		w.Header().Add("Content-Type", "application/json")
+		w.WriteHeader(http.StatusOK)
+
+		fmt.Fprintf(w, `
+{
+	"security_group": {
+		"description": "something",
+		"id": "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		"name": "new_name",
+		"rules": [],
+		"tenant_id": "openstack"
+	}
+}
+`)
+	})
+}
+
 func mockGetGroupsResponse(t *testing.T, groupID string) {
 	url := fmt.Sprintf("%s/%s", rootPath, groupID)
 	th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
diff --git a/openstack/compute/v2/extensions/secgroups/requests.go b/openstack/compute/v2/extensions/secgroups/requests.go
index acd43f2..505439e 100644
--- a/openstack/compute/v2/extensions/secgroups/requests.go
+++ b/openstack/compute/v2/extensions/secgroups/requests.go
@@ -25,7 +25,7 @@
 	return commonList(client, listByServerURL(client, serverID))
 }
 
-type CreateOpts struct {
+type GroupOpts struct {
 	// Optional - the name of your security group. If no value provided, null
 	// will be set.
 	Name string `json:"name,omitempty"`
@@ -35,6 +35,8 @@
 	Description string `json:"description,omitempty"`
 }
 
+type CreateOpts GroupOpts
+
 func Create(client *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
 	var result CreateResult
 
@@ -52,6 +54,25 @@
 	return result
 }
 
+type UpdateOpts GroupOpts
+
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
+	var result UpdateResult
+
+	reqBody := struct {
+		UpdateOpts `json:"security_group"`
+	}{opts}
+
+	_, result.Err = perigee.Request("POST", resourceURL(client, id), perigee.Options{
+		Results:     &result.Body,
+		ReqBody:     &reqBody,
+		MoreHeaders: client.AuthenticatedHeaders(),
+		OkCodes:     []int{200},
+	})
+
+	return result
+}
+
 func Get(client *gophercloud.ServiceClient, id string) GetResult {
 	var result GetResult
 
diff --git a/openstack/compute/v2/extensions/secgroups/requests_test.go b/openstack/compute/v2/extensions/secgroups/requests_test.go
index cf13056..37008ac 100644
--- a/openstack/compute/v2/extensions/secgroups/requests_test.go
+++ b/openstack/compute/v2/extensions/secgroups/requests_test.go
@@ -108,6 +108,26 @@
 	th.AssertDeepEquals(t, expected, group)
 }
 
+func TestUpdate(t *testing.T) {
+	th.SetupHTTP()
+	defer th.TeardownHTTP()
+
+	mockUpdateGroupResponse(t, groupID)
+
+	opts := UpdateOpts{Name: "new_name"}
+	group, err := Update(client.ServiceClient(), groupID, opts).Extract()
+	th.AssertNoErr(t, err)
+
+	expected := &SecurityGroup{
+		ID:          "b0e0d7dd-2ca4-49a9-ba82-c44a148b66a5",
+		Name:        "new_name",
+		Description: "something",
+		TenantID:    "openstack",
+		Rules:       []Rule{},
+	}
+	th.AssertDeepEquals(t, expected, group)
+}
+
 func TestGet(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()
diff --git a/openstack/compute/v2/extensions/secgroups/results.go b/openstack/compute/v2/extensions/secgroups/results.go
index c814048..17adf44 100644
--- a/openstack/compute/v2/extensions/secgroups/results.go
+++ b/openstack/compute/v2/extensions/secgroups/results.go
@@ -71,6 +71,10 @@
 	commonResult
 }
 
+type UpdateResult struct {
+	commonResult
+}
+
 func (r commonResult) Extract() (*SecurityGroup, error) {
 	if r.Err != nil {
 		return nil, r.Err