blob: 5c5744c3c1f3f55561d37632e053e2648ef5d4d0 [file] [log] [blame]
Jamie Hannaford89f9af22014-09-17 12:21:48 +02001package subnets
Jamie Hannaford0708c002014-09-17 16:08:49 +02002
3import (
Jamie Hannafordd9036422014-09-23 17:50:24 +02004 "fmt"
5
Jamie Hannaford0708c002014-09-17 16:08:49 +02006 "github.com/mitchellh/mapstructure"
Jamie Hannafordd9036422014-09-23 17:50:24 +02007 "github.com/rackspace/gophercloud"
Jamie Hannaford0708c002014-09-17 16:08:49 +02008 "github.com/rackspace/gophercloud/pagination"
9)
10
Jamie Hannafordd9036422014-09-23 17:50:24 +020011type commonResult struct {
12 gophercloud.CommonResult
13}
14
Jamie Hannafordf3114832014-09-24 11:00:43 +020015// Extract is a function that accepts a result and extracts a subnet resource.
Jamie Hannafordd9036422014-09-23 17:50:24 +020016func (r commonResult) Extract() (*Subnet, error) {
17 if r.Err != nil {
18 return nil, r.Err
19 }
20
21 var res struct {
22 Subnet *Subnet `json:"subnet"`
23 }
24
25 err := mapstructure.Decode(r.Resp, &res)
26 if err != nil {
27 return nil, fmt.Errorf("Error decoding Neutron subnet: %v", err)
28 }
29
30 return res.Subnet, nil
31}
32
Jamie Hannafordf3114832014-09-24 11:00:43 +020033// CreateResult represents the result of a create operation.
Jamie Hannafordd9036422014-09-23 17:50:24 +020034type CreateResult struct {
35 commonResult
36}
37
Jamie Hannafordf3114832014-09-24 11:00:43 +020038// GetResult represents the result of a get operation.
Jamie Hannafordd9036422014-09-23 17:50:24 +020039type GetResult struct {
40 commonResult
41}
42
Jamie Hannafordf3114832014-09-24 11:00:43 +020043// UpdateResult represents the result of an update operation.
Jamie Hannafordd9036422014-09-23 17:50:24 +020044type UpdateResult struct {
45 commonResult
46}
47
Jamie Hannafordf3114832014-09-24 11:00:43 +020048// DeleteResult represents the result of a delete operation.
Jamie Hannafordd9036422014-09-23 17:50:24 +020049type DeleteResult commonResult
50
Jamie Hannafordf2835402014-09-23 11:01:21 +020051// AllocationPool represents a sub-range of cidr available for dynamic
52// allocation to ports, e.g. {Start: "10.0.0.2", End: "10.0.0.254"}
Jamie Hannaford0708c002014-09-17 16:08:49 +020053type AllocationPool struct {
Jamie Hannaford63631432014-09-18 11:40:09 +020054 Start string `json:"start"`
55 End string `json:"end"`
Jamie Hannaford0708c002014-09-17 16:08:49 +020056}
57
Jamie Hannafordf2835402014-09-23 11:01:21 +020058// HostRoute represents a route that should be used by devices with IPs from
59// a subnet (not including local subnet route).
60type HostRoute struct {
61 DestinationCIDR string `json:"destination"`
62 NextHop string `json:"nexthop"`
63}
64
Jamie Hannaford686c4962014-09-23 10:46:20 +020065// Subnet represents a subnet. See package documentation for a top-level
66// description of what this is.
Jamie Hannaford0708c002014-09-17 16:08:49 +020067type Subnet struct {
Jamie Hannaford965ae702014-09-22 14:58:19 +020068 // UUID representing the subnet
69 ID string `mapstructure:"id" json:"id"`
70 // UUID of the parent network
71 NetworkID string `mapstructure:"network_id" json:"network_id"`
72 // Human-readable name for the subnet. Might not be unique.
73 Name string `mapstructure:"name" json:"name"`
74 // IP version, either `4' or `6'
75 IPVersion int `mapstructure:"ip_version" json:"ip_version"`
76 // CIDR representing IP range for this subnet, based on IP version
77 CIDR string `mapstructure:"cidr" json:"cidr"`
78 // Default gateway used by devices in this subnet
79 GatewayIP string `mapstructure:"gateway_ip" json:"gateway_ip"`
80 // DNS name servers used by hosts in this subnet.
81 DNSNameservers []string `mapstructure:"dns_nameservers" json:"dns_nameservers"`
82 // Sub-ranges of CIDR available for dynamic allocation to ports. See AllocationPool.
Jamie Hannaford0708c002014-09-17 16:08:49 +020083 AllocationPools []AllocationPool `mapstructure:"allocation_pools" json:"allocation_pools"`
Jamie Hannaford965ae702014-09-22 14:58:19 +020084 // Routes that should be used by devices with IPs from this subnet (not including local subnet route).
Jamie Hannafordf2835402014-09-23 11:01:21 +020085 HostRoutes []HostRoute `mapstructure:"host_routes" json:"host_routes"`
Jamie Hannaford965ae702014-09-22 14:58:19 +020086 // Specifies whether DHCP is enabled for this subnet or not.
87 EnableDHCP bool `mapstructure:"enable_dhcp" json:"enable_dhcp"`
88 // Owner of network. Only admin users can specify a tenant_id other than its own.
89 TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
Jamie Hannaford0708c002014-09-17 16:08:49 +020090}
91
Jamie Hannaford686c4962014-09-23 10:46:20 +020092// SubnetPage is the page returned by a pager when traversing over a collection
93// of subnets.
Jamie Hannaford0708c002014-09-17 16:08:49 +020094type SubnetPage struct {
95 pagination.LinkedPageBase
96}
97
Jamie Hannaford686c4962014-09-23 10:46:20 +020098// NextPageURL is invoked when a paginated collection of subnets has reached
99// the end of a page and the pager seeks to traverse over a new one. In order
100// to do this, it needs to construct the next page's URL.
101func (p SubnetPage) NextPageURL() (string, error) {
Jamie Hannaford0708c002014-09-17 16:08:49 +0200102 type link struct {
103 Href string `mapstructure:"href"`
104 Rel string `mapstructure:"rel"`
105 }
106 type resp struct {
107 Links []link `mapstructure:"subnets_links"`
108 }
109
110 var r resp
Jamie Hannaford686c4962014-09-23 10:46:20 +0200111 err := mapstructure.Decode(p.Body, &r)
Jamie Hannaford0708c002014-09-17 16:08:49 +0200112 if err != nil {
113 return "", err
114 }
115
116 var url string
117 for _, l := range r.Links {
118 if l.Rel == "next" {
119 url = l.Href
120 }
121 }
122 if url == "" {
123 return "", nil
124 }
125
126 return url, nil
127}
128
Jamie Hannaford686c4962014-09-23 10:46:20 +0200129// IsEmpty checks whether a SubnetPage struct is empty.
130func (p SubnetPage) IsEmpty() (bool, error) {
131 is, err := ExtractSubnets(p)
Jamie Hannaford0708c002014-09-17 16:08:49 +0200132 if err != nil {
133 return true, nil
134 }
135 return len(is) == 0, nil
136}
137
Jamie Hannaford686c4962014-09-23 10:46:20 +0200138// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct,
139// and extracts the elements into a slice of Subnet structs. In other words,
140// a generic collection is mapped into a relevant slice.
Jamie Hannaford0708c002014-09-17 16:08:49 +0200141func ExtractSubnets(page pagination.Page) ([]Subnet, error) {
142 var resp struct {
143 Subnets []Subnet `mapstructure:"subnets" json:"subnets"`
144 }
145
146 err := mapstructure.Decode(page.(SubnetPage).Body, &resp)
147 if err != nil {
148 return nil, err
149 }
150
151 return resp.Subnets, nil
152}