blob: 5a078634b875170c7aeb3800faec6c49ab527fba [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 Hannaford0708c002014-09-17 16:08:49 +020093func Get(c *gophercloud.ServiceClient, id string) (*Subnet, error) {
94 var s Subnet
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(),
97 Results: &struct {
98 Subnet *Subnet `json:"subnet"`
99 }{&s},
100 OkCodes: []int{200},
101 })
102 if err != nil {
103 return nil, err
104 }
105 return &s, nil
106}
Jamie Hannaford63631432014-09-18 11:40:09 +0200107
Jamie Hannaford686c4962014-09-23 10:46:20 +0200108// Valid IP types
Jamie Hannaford63631432014-09-18 11:40:09 +0200109const (
110 IPv4 = 4
111 IPv6 = 6
112)
113
Jamie Hannaford686c4962014-09-23 10:46:20 +0200114// CreateOpts represents the attributes used when creating a new subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200115type CreateOpts struct {
Jamie Hannaford63631432014-09-18 11:40:09 +0200116 // Required
117 NetworkID string
118 CIDR string
119 // Optional
120 Name string
121 TenantID string
122 AllocationPools []AllocationPool
123 GatewayIP string
124 IPVersion int
Jamie Hannaford63631432014-09-18 11:40:09 +0200125 EnableDHCP *bool
Jamie Hannaford965ae702014-09-22 14:58:19 +0200126 DNSNameservers []string
127 HostRoutes []interface{}
Jamie Hannaford63631432014-09-18 11:40:09 +0200128}
129
Jamie Hannaford686c4962014-09-23 10:46:20 +0200130// Create accepts a CreateOpts struct and creates a new subnet using the values
131// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200132func Create(c *gophercloud.ServiceClient, opts CreateOpts) (*Subnet, error) {
Jamie Hannaford63631432014-09-18 11:40:09 +0200133 // Validate required options
134 if opts.NetworkID == "" {
Jamie Hannaford686c4962014-09-23 10:46:20 +0200135 return nil, errNetworkIDRequired
Jamie Hannaford63631432014-09-18 11:40:09 +0200136 }
137 if opts.CIDR == "" {
Jamie Hannaford686c4962014-09-23 10:46:20 +0200138 return nil, errCIDRRequired
Jamie Hannaford63631432014-09-18 11:40:09 +0200139 }
140 if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
Jamie Hannaford686c4962014-09-23 10:46:20 +0200141 return nil, errInvalidIPType
Jamie Hannaford63631432014-09-18 11:40:09 +0200142 }
143
144 type subnet struct {
145 NetworkID string `json:"network_id"`
146 CIDR string `json:"cidr"`
147 Name *string `json:"name,omitempty"`
148 TenantID *string `json:"tenant_id,omitempty"`
149 AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
150 GatewayIP *string `json:"gateway_ip,omitempty"`
151 IPVersion int `json:"ip_version,omitempty"`
Jamie Hannaford63631432014-09-18 11:40:09 +0200152 EnableDHCP *bool `json:"enable_dhcp,omitempty"`
Jamie Hannaford965ae702014-09-22 14:58:19 +0200153 DNSNameservers []string `json:"dns_nameservers,omitempty"`
154 HostRoutes []interface{} `json:"host_routes,omitempty"`
Jamie Hannaford63631432014-09-18 11:40:09 +0200155 }
156 type request struct {
157 Subnet subnet `json:"subnet"`
158 }
159
160 reqBody := request{Subnet: subnet{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200161 NetworkID: opts.NetworkID,
162 CIDR: opts.CIDR,
163 Name: maybeString(opts.Name),
164 TenantID: maybeString(opts.TenantID),
165 GatewayIP: maybeString(opts.GatewayIP),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200166 EnableDHCP: opts.EnableDHCP,
Jamie Hannaford63631432014-09-18 11:40:09 +0200167 }}
168
Jamie Hannaford63631432014-09-18 11:40:09 +0200169 if opts.IPVersion != 0 {
170 reqBody.Subnet.IPVersion = opts.IPVersion
171 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200172 if len(opts.AllocationPools) != 0 {
173 reqBody.Subnet.AllocationPools = opts.AllocationPools
174 }
Jamie Hannaford965ae702014-09-22 14:58:19 +0200175 if len(opts.DNSNameservers) != 0 {
176 reqBody.Subnet.DNSNameservers = opts.DNSNameservers
177 }
178 if len(opts.HostRoutes) != 0 {
179 reqBody.Subnet.HostRoutes = opts.HostRoutes
180 }
Jamie Hannaford63631432014-09-18 11:40:09 +0200181
182 type response struct {
183 Subnet *Subnet `json:"subnet"`
184 }
185
186 var res response
Jamie Hannaford686c4962014-09-23 10:46:20 +0200187 _, err := perigee.Request("POST", createURL(c), perigee.Options{
Jamie Hannaford63631432014-09-18 11:40:09 +0200188 MoreHeaders: c.Provider.AuthenticatedHeaders(),
189 ReqBody: &reqBody,
190 Results: &res,
191 OkCodes: []int{201},
192 })
193 if err != nil {
194 return nil, err
195 }
196
197 return res.Subnet, nil
198}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200199
Jamie Hannaford686c4962014-09-23 10:46:20 +0200200// UpdateOpts represents the attributes used when updating an existing subnet.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200201type UpdateOpts struct {
202 Name string
203 GatewayIP string
204 DNSNameservers []string
205 HostRoutes []interface{}
206 EnableDHCP *bool
207}
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200208
Jamie Hannaford686c4962014-09-23 10:46:20 +0200209// Update accepts a UpdateOpts struct and updates an existing subnet using the
210// values provided.
Jamie Hannaford965ae702014-09-22 14:58:19 +0200211func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) (*Subnet, error) {
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200212 type subnet struct {
Jamie Hannaford965ae702014-09-22 14:58:19 +0200213 Name *string `json:"name,omitempty"`
214 GatewayIP *string `json:"gateway_ip,omitempty"`
215 DNSNameservers []string `json:"dns_nameservers,omitempty"`
216 HostRoutes []interface{} `json:"host_routes,omitempty"`
217 EnableDHCP *bool `json:"enable_dhcp,omitempty"`
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200218 }
219 type request struct {
220 Subnet subnet `json:"subnet"`
221 }
222
223 reqBody := request{Subnet: subnet{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200224 Name: maybeString(opts.Name),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200225 GatewayIP: maybeString(opts.GatewayIP),
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200226 EnableDHCP: opts.EnableDHCP,
227 }}
228
Jamie Hannaford965ae702014-09-22 14:58:19 +0200229 if len(opts.DNSNameservers) != 0 {
230 reqBody.Subnet.DNSNameservers = opts.DNSNameservers
231 }
232
233 if len(opts.HostRoutes) != 0 {
234 reqBody.Subnet.HostRoutes = opts.HostRoutes
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200235 }
236
237 type response struct {
238 Subnet *Subnet `json:"subnet"`
239 }
240
241 var res response
Jamie Hannaford686c4962014-09-23 10:46:20 +0200242 _, err := perigee.Request("PUT", updateURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200243 MoreHeaders: c.Provider.AuthenticatedHeaders(),
244 ReqBody: &reqBody,
245 Results: &res,
Jamie Hannafordf84171d2014-09-18 14:00:01 +0200246 OkCodes: []int{200, 201},
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200247 })
248 if err != nil {
249 return nil, err
250 }
251
252 return res.Subnet, nil
253}
254
Jamie Hannaford686c4962014-09-23 10:46:20 +0200255// Delete accepts a unique ID and deletes the subnet associated with it.
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200256func Delete(c *gophercloud.ServiceClient, id string) error {
Jamie Hannaford686c4962014-09-23 10:46:20 +0200257 _, err := perigee.Request("DELETE", deleteURL(c, id), perigee.Options{
Jamie Hannafordd11e20c2014-09-18 12:03:01 +0200258 MoreHeaders: c.Provider.AuthenticatedHeaders(),
259 OkCodes: []int{204},
260 })
261 return err
262}