blob: 69a57cd1823db0aa6adaf5c83662ebf2850eb8f2 [file] [log] [blame]
Jamie Hannaford21a3eb12014-11-03 10:34:29 +01001package nodes
2
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +01003import (
4 "github.com/mitchellh/mapstructure"
Jamie Hannaford16bebfc2014-11-03 12:52:30 +01005 "github.com/rackspace/gophercloud"
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +01006 "github.com/rackspace/gophercloud/pagination"
7)
8
Jamie Hannaford940cece2014-11-03 10:59:36 +01009// Node represents a back-end device, usually a virtual machine, that can
10// handle traffic. It is assigned traffic based on its parent load balancer.
Jamie Hannaford21a3eb12014-11-03 10:34:29 +010011type Node struct {
Jamie Hannaford940cece2014-11-03 10:59:36 +010012 // The IP address or CIDR for this back-end node.
13 Address string
14
15 // The unique ID for this node.
16 ID int
17
18 // The port on which traffic is sent and received.
19 Port int
20
21 // The node's status.
22 Status Status
23
24 // The node's condition.
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +010025 Condition Condition
Jamie Hannaford940cece2014-11-03 10:59:36 +010026
27 // The priority at which this node will receive traffic if a weighted
28 // algorithm is used by its parent load balancer. Ranges from 1 to 100.
29 Weight int
30
31 // Type of node.
32 Type Type
Jamie Hannaford21a3eb12014-11-03 10:34:29 +010033}
Jamie Hannaford940cece2014-11-03 10:59:36 +010034
35// Type indicates whether the node is of a PRIMARY or SECONDARY nature.
36type Type string
37
38const (
39 // PRIMARY nodes are in the normal rotation to receive traffic from the load
40 // balancer.
41 PRIMARY Type = "PRIMARY"
42
43 // SECONDARY nodes are only in the rotation to receive traffic from the load
44 // balancer when all the primary nodes fail. This provides a failover feature
45 // that automatically routes traffic to the secondary node in the event that
46 // the primary node is disabled or in a failing state. Note that active
47 // health monitoring must be enabled on the load balancer to enable the
48 // failover feature to the secondary node.
49 SECONDARY Type = "SECONDARY"
50)
51
52type Condition string
53
54const (
55 // ENABLED indicates that the node is permitted to accept new connections.
56 ENABLED Condition = "ENABLED"
57
58 // DISABLED indicates that the node is not permitted to accept any new
59 // connections regardless of session persistence configuration. Existing
60 // connections are forcibly terminated.
61 DISABLED Condition = "DISABLED"
62
63 // DRAINING indicates that the node is allowed to service existing
64 // established connections and connections that are being directed to it as a
65 // result of the session persistence configuration.
Jamie Hannaford00222d72014-11-03 13:58:52 +010066 DRAINING Condition = "DRAINING"
Jamie Hannaford940cece2014-11-03 10:59:36 +010067)
68
69// Status indicates whether the node can accept service traffic. If a node is
70// not listening on its port or does not meet the conditions of the defined
71// active health check for the load balancer, then the load balancer does not
72// forward connections and its status is listed as OFFLINE
73type Status string
74
75const (
76 // ONLINE indicates that the node is healthy and capable of receiving traffic
77 // from the load balancer.
78 ONLINE Status = "ONLINE"
79
80 // OFFLINE indicates that the node is not in a position to receive service
81 // traffic. It is usually switched into this state when a health check is not
82 // satisfied with the node's response time.
83 OFFLINE Status = "OFFLINE"
84)
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +010085
86// NodePage is the page returned by a pager when traversing over a collection
87// of nodes.
88type NodePage struct {
89 pagination.SinglePageBase
90}
91
92// IsEmpty checks whether a NodePage struct is empty.
93func (p NodePage) IsEmpty() (bool, error) {
94 is, err := ExtractNodes(p)
95 if err != nil {
96 return true, nil
97 }
98 return len(is) == 0, nil
99}
100
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100101func commonExtractNodes(body interface{}) ([]Node, error) {
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +0100102 var resp struct {
103 Nodes []Node `mapstructure:"nodes" json:"nodes"`
104 }
105
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100106 err := mapstructure.Decode(body, &resp)
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +0100107
108 return resp.Nodes, err
109}
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100110
111// ExtractNodes accepts a Page struct, specifically a NodePage struct, and
112// extracts the elements into a slice of Node structs. In other words, a
113// generic collection is mapped into a relevant slice.
114func ExtractNodes(page pagination.Page) ([]Node, error) {
115 return commonExtractNodes(page.(NodePage).Body)
116}
117
118// CreateResult represents the result of a create operation. Since multiple
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100119// nodes can be added in one operation, this result represents multiple nodes
120// and should be treated as a typical pagination Page. Use its ExtractNodes
121// method to get out a slice of Node structs.
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100122type CreateResult struct {
123 pagination.SinglePageBase
124}
125
126func (res CreateResult) ExtractNodes() ([]Node, error) {
127 return commonExtractNodes(res.Body)
128}
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100129
130type DeleteResult struct {
131 gophercloud.ErrResult
132}
Jamie Hannaford51175a02014-11-03 13:29:44 +0100133
134type commonResult struct {
135 gophercloud.Result
136}
137
138type GetResult struct {
139 commonResult
140}
141
Jamie Hannaford00222d72014-11-03 13:58:52 +0100142type UpdateResult struct {
143 gophercloud.ErrResult
144}
145
Jamie Hannaford51175a02014-11-03 13:29:44 +0100146func (r commonResult) Extract() (*Node, error) {
147 if r.Err != nil {
148 return nil, r.Err
149 }
150
151 var response struct {
152 Node Node `mapstructure:"node"`
153 }
154
155 err := mapstructure.Decode(r.Body, &response)
156
157 return &response.Node, err
158}
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100159
160type NodeEvent struct {
161 ID int
162 DetailedMessage string
163 NodeID int
164 Type string
165 Description string
166 Category string
167 Severity string
168 RelativeURI string
169 AccountID int
170 LoadBalancerID int
171 Title string
172 Author string
173 Created string
174}
175
176type NodeEventPage struct {
177 pagination.SinglePageBase
178}
179
180func (r NodeEventPage) IsEmpty() (bool, error) {
181 is, err := ExtractNodeEvents(r)
182 if err != nil {
183 return true, err
184 }
185 return len(is) == 0, nil
186}
187
188func ExtractNodeEvents(page pagination.Page) ([]NodeEvent, error) {
189 var resp struct {
190 Events []NodeEvent `mapstructure:"nodeServiceEvents" json:"nodeServiceEvents"`
191 }
192
193 err := mapstructure.Decode(page.(NodeEventPage).Body, &resp)
194
195 return resp.Events, err
196}