ExtractGroups accepts a Page struct, specifically a SecGroupPage struct,
and extracts the elements into a slice of SecGroup structs. In other words,
a generic collection is mapped into a relevant slice.

type CreateOpts struct {
// Required. Human-readable name for the VIP. Does not have to be unique.Namestring// Required for admins. Indicates the owner of the VIP.TenantIDstring// Optional. Describes the security group.Descriptionstring
}

CreateOpts contains all the values needed to create a new security group.

ListOpts allows the filtering and sorting of paginated collections through
the API. Filtering is achieved by passing in struct field values that map to
the floating IP attributes you want to see returned. SortKey allows you to
sort by a particular network attribute. SortDir sets the direction, and is
either `asc' or `desc'. Marker and Limit are used for pagination.

type SecGroup struct {
// The UUID for the security group.IDstring// Human-readable name for the security group. Might not be unique. Cannot be
// named "default" as that is automatically created for a tenant.Namestring// The security group description.Descriptionstring// A slice of security group rules that dictate the permitted behaviour for
// traffic entering and leaving the group.Rules []rules.SecGroupRule `json:"security_group_rules" mapstructure:"security_group_rules"`
// Owner of the security group. Only admin users can specify a TenantID
// other than their own.TenantIDstring `json:"tenant_id" mapstructure:"tenant_id"`
}

NextPageURL is invoked when a paginated collection of security groups has
reached the end of a page and the pager seeks to traverse over a new one. In
order to do this, it needs to construct the next page's URL.