blob: 75524587639f23ea95fa10456432d545b2fc7e1d [file] [log] [blame]
Jamie Hannaford89f9af22014-09-17 12:21:48 +02001package subnets
Jamie Hannaford0708c002014-09-17 16:08:49 +02002
3import (
4 "strconv"
5
6 "github.com/racker/perigee"
7 "github.com/rackspace/gophercloud"
8 "github.com/rackspace/gophercloud/openstack/utils"
9 "github.com/rackspace/gophercloud/pagination"
10)
11
Jamie Hannaford686c4962014-09-23 10:46:20 +020012func maybeString(original string) *string {
13 if original != "" {
14 return &original
15 }
16 return nil
17}
18
19// ListOpts allows the filtering and sorting of paginated collections through
20// the API. Filtering is achieved by passing in struct field values that map to
21// the subnet attributes you want to see returned. SortKey allows you to sort
22// by a particular subnet attribute. SortDir sets the direction, and is either
23// `asc' or `desc'. Marker and Limit are used for pagination.
Jamie Hannaford0708c002014-09-17 16:08:49 +020024type ListOpts struct {
25 Name string
26 EnableDHCP *bool
27 NetworkID string
28 TenantID string
29 IPVersion int
30 GatewayIP string
31 CIDR string
32 ID string
Jamie Hannafordf84171d2014-09-18 14:00:01 +020033 Limit int
Jamie Hannaford686c4962014-09-23 10:46:20 +020034 Marker string
Jamie Hannafordd0f090c2014-09-22 13:44:34 +020035 SortKey string
36 SortDir string
Jamie Hannaford0708c002014-09-17 16:08:49 +020037}
38
Jamie Hannaford686c4962014-09-23 10:46:20 +020039// List returns a Pager which allows you to iterate over a collection of
40// subnets. It accepts a ListOpts struct, which allows you to filter and sort
41// the returned collection for greater efficiency.
42//
43// Default policy settings return only those subnets that are owned by the tenant
44// who submits the request, unless the request is submitted by an user with
45// administrative rights.
Jamie Hannaford0708c002014-09-17 16:08:49 +020046func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
47 // Build query parameters
48 q := make(map[string]string)
49 if opts.Name != "" {
50 q["name"] = opts.Name
51 }
52 if opts.EnableDHCP != nil {
53 q["enable_dhcp"] = strconv.FormatBool(*opts.EnableDHCP)
54 }
55 if opts.NetworkID != "" {
56 q["network_id"] = opts.NetworkID
57 }
58 if opts.TenantID != "" {
59 q["tenant_id"] = opts.TenantID
60 }
61 if opts.IPVersion != 0 {
62 q["ip_version"] = strconv.Itoa(opts.IPVersion)
63 }
64 if opts.GatewayIP != "" {
65 q["gateway_ip"] = opts.GatewayIP
66 }
67 if opts.CIDR != "" {
68 q["cidr"] = opts.CIDR
69 }
70 if opts.ID != "" {
71 q["id"] = opts.ID
72 }
Jamie Hannafordf84171d2014-09-18 14:00:01 +020073 if opts.Limit != 0 {
74 q["limit"] = strconv.Itoa(opts.Limit)
75 }
Jamie Hannaford686c4962014-09-23 10:46:20 +020076 if opts.Marker != "" {
77 q["marker"] = opts.Marker
Jamie Hannafordf84171d2014-09-18 14:00:01 +020078 }
Jamie Hannafordd0f090c2014-09-22 13:44:34 +020079 if opts.SortKey != "" {
80 q["sort_key"] = opts.SortKey
81 }
82 if opts.SortDir != "" {
83 q["sort_dir"] = opts.SortDir
84 }
Jamie Hannaford0708c002014-09-17 16:08:49 +020085
Jamie Hannaford686c4962014-09-23 10:46:20 +020086 u := listURL(c) + utils.BuildQuery(q)
Jamie Hannaford0708c002014-09-17 16:08:49 +020087 return pagination.NewPager(c, u, func(r pagination.LastHTTPResponse) pagination.Page {
88 return SubnetPage{pagination.LinkedPageBase(r)}
89 })
90}
91
Jamie Hannaford686c4962014-09-23 10:46:20 +020092// Get retrieves a specific subnet based on its unique ID.
Jamie Hannafordd9036422014-09-23 17:50:24 +020093func Get(c *gophercloud.ServiceClient, id string) GetResult {
94 var res GetResult
Jamie Hannaford686c4962014-09-23 10:46:20 +020095 _, err := perigee.Request("GET", getURL(c, id), perigee.Options{
Jamie Hannaford0708c002014-09-17 16:08:49 +020096 MoreHeaders: c.Provider.AuthenticatedHeaders(),
Jamie Hannafordd9036422014-09-23 17:50:24 +020097 Results: &res.Resp,
98 OkCodes: []int{200},
Jamie Hannaford0708c002014-09-17 16:08:49 +020099 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200100 res.Err = err
101 return res
Jamie Hannaford0708c002014-09-17 16:08:49 +0200102}
Jamie Hannaford63631432014-09-18 11:40:09 +0200103
Jamie Hannaford686c4962014-09-23 10:46:20 +0200104// Valid IP types
Jamie Hannaford63631432014-09-18 11:40:09 +0200105const (
106 IPv4 = 4
107 IPv6 = 6
108)
109
Jamie Hannaford686c4962014-09-23 10:46:20 +0200110// CreateOpts represents the attributes used when creating a new subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200111type CreateOpts struct {
Jamie Hannaford63631432014-09-18 11:40:09 +0200112 // Required
113 NetworkID string
114 CIDR string
115 // Optional
116 Name string
117 TenantID string
118 AllocationPools []AllocationPool
119 GatewayIP string
120 IPVersion int
Jamie Hannaford63631432014-09-18 11:40:09 +0200121 EnableDHCP *bool
Jamie Hannaford965ae702014-09-22 14:58:19 +0200122 DNSNameservers []string
123 HostRoutes []interface{}
Jamie Hannaford63631432014-09-18 11:40:09 +0200124}
125
Jamie Hannaford686c4962014-09-23 10:46:20 +0200126// Create accepts a CreateOpts struct and creates a new subnet using the values
127// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200128func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
129 var res CreateResult
130
Jamie Hannaford63631432014-09-18 11:40:09 +0200131 // Validate required options
132 if opts.NetworkID == "" {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200133 res.Err = errNetworkIDRequired
134 return res
Jamie Hannaford63631432014-09-18 11:40:09 +0200135 }
136 if opts.CIDR == "" {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200137 res.Err = errCIDRRequired
138 return res
Jamie Hannaford63631432014-09-18 11:40:09 +0200139 }
140 if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
Jamie Hannafordd9036422014-09-23 17:50:24 +0200141 res.Err = errInvalidIPType
142 return res
Jamie Hannaford63631432014-09-18 11:40:09 +0200143 }
144
145 type subnet struct {
146 NetworkID string `json:"network_id"`
147 CIDR string `json:"cidr"`
148 Name *string `json:"name,omitempty"`
149 TenantID *string `json:"tenant_id,omitempty"`
150 AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
151 GatewayIP *string `json:"gateway_ip,omitempty"`
152 IPVersion int `json:"ip_version,omitempty"`
Jamie Hannaford63631432014-09-18 11:40:09 +0200153 EnableDHCP *bool `json:"enable_dhcp,omitempty"`
Jamie Hannaford965ae702014-09-22 14:58:19 +0200154 DNSNameservers []string `json:"dns_nameservers,omitempty"`
155 HostRoutes []interface{} `json:"host_routes,omitempty"`
Jamie Hannaford63631432014-09-18 11:40:09 +0200156 }
157 type request struct {
158 Subnet subnet `json:"subnet"`
159 }
160
161 reqBody := request{Subnet: subnet{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200162 NetworkID: opts.NetworkID,
163 CIDR: opts.CIDR,
164 Name: maybeString(opts.Name),
165 TenantID: maybeString(opts.TenantID),
166 GatewayIP: maybeString(opts.GatewayIP),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200167 EnableDHCP: opts.EnableDHCP,
Jamie Hannaford63631432014-09-18 11:40:09 +0200168 }}
169
Jamie Hannaford63631432014-09-18 11:40:09 +0200170 if opts.IPVersion != 0 {
171 reqBody.Subnet.IPVersion = opts.IPVersion
172 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200173 if len(opts.AllocationPools) != 0 {
174 reqBody.Subnet.AllocationPools = opts.AllocationPools
175 }
Jamie Hannaford965ae702014-09-22 14:58:19 +0200176 if len(opts.DNSNameservers) != 0 {
177 reqBody.Subnet.DNSNameservers = opts.DNSNameservers
178 }
179 if len(opts.HostRoutes) != 0 {
180 reqBody.Subnet.HostRoutes = opts.HostRoutes
181 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200182
Jamie Hannaford686c4962014-09-23 10:46:20 +0200183 _, err := perigee.Request("POST", createURL(c), perigee.Options{
Jamie Hannaford63631432014-09-18 11:40:09 +0200184 MoreHeaders: c.Provider.AuthenticatedHeaders(),
185 ReqBody: &reqBody,
Jamie Hannafordd9036422014-09-23 17:50:24 +0200186 Results: &res.Resp,
Jamie Hannaford63631432014-09-18 11:40:09 +0200187 OkCodes: []int{201},
188 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200189 res.Err = err
Jamie Hannaford63631432014-09-18 11:40:09 +0200190
Jamie Hannafordd9036422014-09-23 17:50:24 +0200191 return res
Jamie Hannaford63631432014-09-18 11:40:09 +0200192}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200193
Jamie Hannaford686c4962014-09-23 10:46:20 +0200194// UpdateOpts represents the attributes used when updating an existing subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200195type UpdateOpts struct {
196 Name string
197 GatewayIP string
198 DNSNameservers []string
199 HostRoutes []interface{}
200 EnableDHCP *bool
201}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200202
Jamie Hannaford686c4962014-09-23 10:46:20 +0200203// Update accepts a UpdateOpts struct and updates an existing subnet using the
204// values provided.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200205func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200206 type subnet struct {
Jamie Hannaford965ae702014-09-22 14:58:19 +0200207 Name *string `json:"name,omitempty"`
208 GatewayIP *string `json:"gateway_ip,omitempty"`
209 DNSNameservers []string `json:"dns_nameservers,omitempty"`
210 HostRoutes []interface{} `json:"host_routes,omitempty"`
211 EnableDHCP *bool `json:"enable_dhcp,omitempty"`
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200212 }
213 type request struct {
214 Subnet subnet `json:"subnet"`
215 }
216
217 reqBody := request{Subnet: subnet{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200218 Name: maybeString(opts.Name),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200219 GatewayIP: maybeString(opts.GatewayIP),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200220 EnableDHCP: opts.EnableDHCP,
221 }}
222
Jamie Hannaford965ae702014-09-22 14:58:19 +0200223 if len(opts.DNSNameservers) != 0 {
224 reqBody.Subnet.DNSNameservers = opts.DNSNameservers
225 }
226
227 if len(opts.HostRoutes) != 0 {
228 reqBody.Subnet.HostRoutes = opts.HostRoutes
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200229 }
230
Jamie Hannafordd9036422014-09-23 17:50:24 +0200231 var res UpdateResult
Jamie Hannaford686c4962014-09-23 10:46:20 +0200232 _, err := perigee.Request("PUT", updateURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200233 MoreHeaders: c.Provider.AuthenticatedHeaders(),
234 ReqBody: &reqBody,
Jamie Hannafordd9036422014-09-23 17:50:24 +0200235 Results: &res.Resp,
Jamie Hannafordf84171d2014-09-18 14:00:01 +0200236 OkCodes: []int{200, 201},
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200237 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200238 res.Err = err
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200239
Jamie Hannafordd9036422014-09-23 17:50:24 +0200240 return res
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200241}
242
Jamie Hannaford686c4962014-09-23 10:46:20 +0200243// Delete accepts a unique ID and deletes the subnet associated with it.
Jamie Hannafordd9036422014-09-23 17:50:24 +0200244func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
245 var res DeleteResult
Jamie Hannaford686c4962014-09-23 10:46:20 +0200246 _, err := perigee.Request("DELETE", deleteURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200247 MoreHeaders: c.Provider.AuthenticatedHeaders(),
248 OkCodes: []int{204},
249 })
Jamie Hannafordd9036422014-09-23 17:50:24 +0200250 res.Err = err
251 return res
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200252}