blob: 759293ac774d71a18db8bc1f1941b628ba5cd293 [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
73// forward connections and its status is listed as OFFLINE
74type 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) {
129 return commonExtractNodes(res.Body)
130}
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100131
Jamie Hannaford862ba142014-11-03 15:29:02 +0100132// DeleteResult represents the result of a delete operation.
Jamie Hannaford16bebfc2014-11-03 12:52:30 +0100133type DeleteResult struct {
134 gophercloud.ErrResult
135}
Jamie Hannaford51175a02014-11-03 13:29:44 +0100136
137type commonResult struct {
138 gophercloud.Result
139}
140
Jamie Hannaford862ba142014-11-03 15:29:02 +0100141// GetResult represents the result of a get operation.
Jamie Hannaford51175a02014-11-03 13:29:44 +0100142type GetResult struct {
143 commonResult
144}
145
Jamie Hannaford862ba142014-11-03 15:29:02 +0100146// UpdateResult represents the result of an update operation.
Jamie Hannaford00222d72014-11-03 13:58:52 +0100147type UpdateResult struct {
148 gophercloud.ErrResult
149}
150
Jamie Hannaford51175a02014-11-03 13:29:44 +0100151func (r commonResult) Extract() (*Node, error) {
152 if r.Err != nil {
153 return nil, r.Err
154 }
155
156 var response struct {
157 Node Node `mapstructure:"node"`
158 }
159
160 err := mapstructure.Decode(r.Body, &response)
161
162 return &response.Node, err
163}
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100164
Jamie Hannaford862ba142014-11-03 15:29:02 +0100165// NodeEvent represents a service event that occurred between a node and a
166// load balancer.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100167type NodeEvent struct {
168 ID int
169 DetailedMessage string
170 NodeID int
171 Type string
172 Description string
173 Category string
174 Severity string
175 RelativeURI string
176 AccountID int
177 LoadBalancerID int
178 Title string
179 Author string
180 Created string
181}
182
Jamie Hannaford862ba142014-11-03 15:29:02 +0100183// NodeEventPage is a concrete type which embeds the common SinglePageBase
184// struct, and is used when traversing node event collections.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100185type NodeEventPage struct {
186 pagination.SinglePageBase
187}
188
Jamie Hannaford862ba142014-11-03 15:29:02 +0100189// IsEmpty is a concrete function which indicates whether an NodeEventPage is
190// empty or not.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100191func (r NodeEventPage) IsEmpty() (bool, error) {
192 is, err := ExtractNodeEvents(r)
193 if err != nil {
194 return true, err
195 }
196 return len(is) == 0, nil
197}
198
Jamie Hannaford862ba142014-11-03 15:29:02 +0100199// ExtractNodeEvents accepts a Page struct, specifically a NodeEventPage
200// struct, and extracts the elements into a slice of NodeEvent structs. In
201// other words, the collection is mapped into a relevant slice.
Jamie Hannaford1fac9dd2014-11-03 14:22:40 +0100202func ExtractNodeEvents(page pagination.Page) ([]NodeEvent, error) {
203 var resp struct {
204 Events []NodeEvent `mapstructure:"nodeServiceEvents" json:"nodeServiceEvents"`
205 }
206
207 err := mapstructure.Decode(page.(NodeEventPage).Body, &resp)
208
209 return resp.Events, err
210}