blob: 57835dc4b5d2ce5226f60d183c2c512b472fb6bd [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
Jamie Hannaford862ba142014-11-03 15:29:02 +010052// Condition represents the condition of a node.
Jamie Hannaford940cece2014-11-03 10:59:36 +010053type Condition string
54
55const (
56 // ENABLED indicates that the node is permitted to accept new connections.
57 ENABLED Condition = "ENABLED"
58
59 // DISABLED indicates that the node is not permitted to accept any new
60 // connections regardless of session persistence configuration. Existing
61 // connections are forcibly terminated.
62 DISABLED Condition = "DISABLED"
63
64 // DRAINING indicates that the node is allowed to service existing
65 // established connections and connections that are being directed to it as a
66 // result of the session persistence configuration.
Jamie Hannaford00222d72014-11-03 13:58:52 +010067 DRAINING Condition = "DRAINING"
Jamie Hannaford940cece2014-11-03 10:59:36 +010068)
69
70// Status indicates whether the node can accept service traffic. If a node is
71// not listening on its port or does not meet the conditions of the defined
72// active health check for the load balancer, then the load balancer does not
Jamie Hannaford227d9592014-11-13 10:32:07 +010073// forward connections, and its status is listed as OFFLINE.
Jamie Hannaford940cece2014-11-03 10:59:36 +010074type Status string
75
76const (
77 // ONLINE indicates that the node is healthy and capable of receiving traffic
78 // from the load balancer.
79 ONLINE Status = "ONLINE"
80
81 // OFFLINE indicates that the node is not in a position to receive service
82 // traffic. It is usually switched into this state when a health check is not
83 // satisfied with the node's response time.
84 OFFLINE Status = "OFFLINE"
85)
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +010086
87// NodePage is the page returned by a pager when traversing over a collection
88// of nodes.
89type NodePage struct {
90 pagination.SinglePageBase
91}
92
93// IsEmpty checks whether a NodePage struct is empty.
94func (p NodePage) IsEmpty() (bool, error) {
95 is, err := ExtractNodes(p)
96 if err != nil {
97 return true, nil
98 }
99 return len(is) == 0, nil
100}
101
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100102func commonExtractNodes(body interface{}) ([]Node, error) {
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +0100103 var resp struct {
104 Nodes []Node `mapstructure:"nodes" json:"nodes"`
105 }
106
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100107 err := mapstructure.Decode(body, &resp)
Jamie Hannaford3cfa00a2014-11-03 11:16:35 +0100108
109 return resp.Nodes, err
110}
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100111
112// ExtractNodes accepts a Page struct, specifically a NodePage struct, and
113// extracts the elements into a slice of Node structs. In other words, a
114// generic collection is mapped into a relevant slice.
115func ExtractNodes(page pagination.Page) ([]Node, error) {
116 return commonExtractNodes(page.(NodePage).Body)
117}
118
119// CreateResult represents the result of a create operation. Since multiple
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100120// nodes can be added in one operation, this result represents multiple nodes
121// and should be treated as a typical pagination Page. Use its ExtractNodes
122// method to get out a slice of Node structs.
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100123type CreateResult struct {
124 pagination.SinglePageBase
125}
126
Jamie Hannaford862ba142014-11-03 15:29:02 +0100127// ExtractNodes extracts a slice of Node structs from a CreateResult.
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100128func (res CreateResult) ExtractNodes() ([]Node, error) {
Ash Wilsondbee4782015-06-24 09:57:32 -0400129 if res.Err != nil {
130 return nil, res.Err
131 }
Jamie Hannaforded8b89a2014-11-03 12:24:19 +0100132 return commonExtractNodes(res.Body)
133}
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100134
Jamie Hannaford862ba142014-11-03 15:29:02 +0100135// DeleteResult represents the result of a delete operation.
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100136type DeleteResult struct {
137 gophercloud.ErrResult
138}
Jamie Hannaford51175a02014-11-03 13:29:44 +0100139
140type commonResult struct {
141 gophercloud.Result
142}
143
Jamie Hannaford862ba142014-11-03 15:29:02 +0100144// GetResult represents the result of a get operation.
Jamie Hannaford51175a02014-11-03 13:29:44 +0100145type GetResult struct {
146 commonResult
147}
148
Jamie Hannaford862ba142014-11-03 15:29:02 +0100149// UpdateResult represents the result of an update operation.
Jamie Hannaford00222d72014-11-03 13:58:52 +0100150type UpdateResult struct {
151 gophercloud.ErrResult
152}
153
Jamie Hannaford51175a02014-11-03 13:29:44 +0100154func (r commonResult) Extract() (*Node, error) {
155 if r.Err != nil {
156 return nil, r.Err
157 }
158
159 var response struct {
160 Node Node `mapstructure:"node"`
161 }
162
163 err := mapstructure.Decode(r.Body, &response)
164
165 return &response.Node, err
166}
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100167
Jamie Hannaford862ba142014-11-03 15:29:02 +0100168// NodeEvent represents a service event that occurred between a node and a
169// load balancer.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100170type NodeEvent struct {
171 ID int
172 DetailedMessage string
173 NodeID int
174 Type string
175 Description string
176 Category string
177 Severity string
178 RelativeURI string
179 AccountID int
180 LoadBalancerID int
181 Title string
182 Author string
183 Created string
184}
185
Jamie Hannaford862ba142014-11-03 15:29:02 +0100186// NodeEventPage is a concrete type which embeds the common SinglePageBase
187// struct, and is used when traversing node event collections.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100188type NodeEventPage struct {
189 pagination.SinglePageBase
190}
191
Jamie Hannaford862ba142014-11-03 15:29:02 +0100192// IsEmpty is a concrete function which indicates whether an NodeEventPage is
193// empty or not.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100194func (r NodeEventPage) IsEmpty() (bool, error) {
195 is, err := ExtractNodeEvents(r)
196 if err != nil {
197 return true, err
198 }
199 return len(is) == 0, nil
200}
201
Jamie Hannaford862ba142014-11-03 15:29:02 +0100202// ExtractNodeEvents accepts a Page struct, specifically a NodeEventPage
203// struct, and extracts the elements into a slice of NodeEvent structs. In
204// other words, the collection is mapped into a relevant slice.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100205func ExtractNodeEvents(page pagination.Page) ([]NodeEvent, error) {
206 var resp struct {
207 Events []NodeEvent `mapstructure:"nodeServiceEvents" json:"nodeServiceEvents"`
208 }
209
210 err := mapstructure.Decode(page.(NodeEventPage).Body, &resp)
211
212 return resp.Events, err
213}