View Javadoc

1   /**
2    * Licensed to jclouds, Inc. (jclouds) under one or more
3    * contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  jclouds licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.jclouds.cloudloadbalancers.domain.internal;
20  
21  import static com.google.common.base.Preconditions.checkArgument;
22  import static com.google.common.base.Preconditions.checkNotNull;
23  
24  /**
25   * The nodes defined by the load balancer are responsible for servicing the requests received
26   * through the load balancer's virtual IP. By default, the load balancer employs a basic health
27   * check that ensures the node is listening on its defined port. The node is checked at the time of
28   * addition and at regular intervals as defined by the load balancer health check configuration. If
29   * a back-end node is not listening on its port or does not meet the conditions of the defined
30   * active health check for the load balancer, then the load balancer will not forward connections
31   * and its status will be listed as OFFLINE. Only nodes that are in an ONLINE status will receive
32   * and be able to service traffic from the load balancer.
33   * <p/>
34   * All nodes have an associated status that indicates whether the node is ONLINE, OFFLINE, or
35   * DRAINING. Only nodes that are in ONLINE status will receive and be able to service traffic from
36   * the load balancer. The OFFLINE status represents a node that cannot accept or service traffic. A
37   * node in DRAINING status represents a node that stops the traffic manager from sending any
38   * additional new connections to the node, but honors established sessions. If the traffic manager
39   * receives a request and session persistence requires that the node is used, the traffic manager
40   * will use it. The status is determined by the passive or active health monitors.
41   * <p/>
42   * If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the caller should
43   * assign the relevant weights to the node as part of the weight attribute of the node element. When
44   * the algorithm of the load balancer is changed to WEIGHTED_ROUND_ROBIN and the nodes do not
45   * already have an assigned weight, the service will automatically set the weight to "1" for all
46   * nodes.
47   * 
48   * @author Adrian Cole
49   * @see <a href=
50   *      "http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch04s02.html" />
51   */
52  public class BaseNode<T extends BaseNode<T>> implements Comparable<BaseNode<T>> {
53  
54     public static <T extends BaseNode<T>> Builder<T> builder() {
55        return new Builder<T>();
56     }
57  
58     @SuppressWarnings("unchecked")
59     public Builder<T> toBuilder() {
60        return new Builder<T>().from((T) this);
61     }
62  
63     public static class Builder<T extends BaseNode<T>> {
64        protected String address;
65        protected int port = -1;
66        protected Condition condition = Condition.ENABLED;
67        protected Integer weight;
68  
69        public Builder<T> address(String address) {
70           this.address = address;
71           return this;
72        }
73  
74        public Builder<T> port(int port) {
75           this.port = port;
76           return this;
77        }
78  
79        public Builder<T> condition(Condition condition) {
80           this.condition = condition;
81           return this;
82        }
83  
84        public Builder<T> weight(Integer weight) {
85           this.weight = weight;
86           return this;
87        }
88  
89        public BaseNode<T> build() {
90           return new BaseNode<T>(address, port, condition, weight);
91        }
92  
93        public Builder<T> from(T in) {
94           return address(in.getAddress()).port(in.getPort()).condition(in.getCondition()).weight(in.getWeight());
95        }
96     }
97  
98     /**
99      * Virtual IP Conditions
100     */
101    public static enum Condition {
102       /**
103        * Node is permitted to accept new connections.
104        */
105       ENABLED,
106       /**
107        * Node is not permitted to accept any new connections regardless of session persistence
108        * configuration. Existing connections are forcibly terminated.
109        */
110       DISABLED,
111       /**
112        * Node is allowed to service existing established connections and connections that are being
113        * directed to it as a result of the session persistence configuration.
114        */
115       DRAINING,
116 
117       UNRECOGNIZED;
118 
119       public static Condition fromValue(String condition) {
120          try {
121             return valueOf(checkNotNull(condition, "condition"));
122          } catch (IllegalArgumentException e) {
123             return UNRECOGNIZED;
124          }
125       }
126 
127    }
128 
129    protected String address;
130    protected int port;
131    protected Condition condition;
132    protected Integer weight;
133 
134    // for serialization only
135    protected BaseNode() {
136 
137    }
138 
139    public BaseNode(String address, int port, Condition condition, Integer weight) {
140       this.address = checkNotNull(address, "address");
141       checkArgument(port != -1, "port must be specified");
142       this.port = port;
143       this.condition = checkNotNull(condition, "condition");
144       this.weight = weight;
145    }
146 
147    public String getAddress() {
148       return address;
149    }
150 
151    public int getPort() {
152       return port;
153    }
154 
155    public Condition getCondition() {
156       return condition;
157    }
158 
159    /**
160     * the maximum weight of a node is 100.
161     */
162    public Integer getWeight() {
163       return weight;
164    }
165 
166    @Override
167    public int compareTo(BaseNode<T> arg0) {
168       return address.compareTo(arg0.address);
169    }
170 
171    @Override
172    public int hashCode() {
173       final int prime = 31;
174       int result = 1;
175       result = prime * result + ((address == null) ? 0 : address.hashCode());
176       result = prime * result + ((condition == null) ? 0 : condition.hashCode());
177       result = prime * result + port;
178       return result;
179    }
180 
181    @Override
182    public boolean equals(Object obj) {
183       if (this == obj)
184          return true;
185       if (obj == null)
186          return false;
187       if (getClass() != obj.getClass())
188          return false;
189       BaseNode<?> other = (BaseNode<?>) obj;
190       if (address == null) {
191          if (other.address != null)
192             return false;
193       } else if (!address.equals(other.address))
194          return false;
195       if (condition == null) {
196          if (other.condition != null)
197             return false;
198       } else if (!condition.equals(other.condition))
199          return false;
200       if (port != other.port)
201          return false;
202       return true;
203    }
204 
205    @Override
206    public String toString() {
207       return String.format("[address=%s, condition=%s, port=%s, weight=%s]", address, condition, port, weight);
208    }
209 
210 }