Merge "Fix race condition when registering services"
[controller.git] / opendaylight / switchmanager / api / src / main / java / org / opendaylight / controller / switchmanager / SubnetConfig.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.switchmanager;
11
12 import java.io.Serializable;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.util.ArrayList;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19
20 import javax.xml.bind.annotation.XmlAccessType;
21 import javax.xml.bind.annotation.XmlAccessorType;
22 import javax.xml.bind.annotation.XmlAttribute;
23 import javax.xml.bind.annotation.XmlElement;
24 import javax.xml.bind.annotation.XmlRootElement;
25
26 import org.opendaylight.controller.sal.core.Node;
27 import org.opendaylight.controller.sal.core.NodeConnector;
28 import org.opendaylight.controller.sal.utils.GUIField;
29 import org.opendaylight.controller.sal.utils.NetUtils;
30 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
31
32 /**
33  * The class represents a subnet configuration.
34  */
35 @XmlRootElement
36 @XmlAccessorType(XmlAccessType.NONE)
37 public class SubnetConfig implements Cloneable, Serializable {
38     //static fields are by default excluded by Gson parser
39     private static final long serialVersionUID = 1L;
40     private static final String prettyFields[] = { GUIField.NAME.toString(),
41             GUIField.GATEWAYIP.toString(), GUIField.NODEPORTS.toString() };
42
43     // Order matters: JSP file expects following fields in the
44     // following order
45     @XmlAttribute
46     private String name;
47     @XmlAttribute
48     private String subnet; // A.B.C.D/MM  Where A.B.C.D is the Default
49                            // Gateway IP (L3) or ARP Querier IP (L2
50     @XmlElement
51     private Set<String> nodePorts; // datapath ID/port list:
52                                     // xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
53
54     public SubnetConfig() {
55     }
56
57     public SubnetConfig(String desc, String sub, Set<String> sp) {
58         name = desc;
59         subnet = sub;
60         nodePorts = sp;
61     }
62
63     public SubnetConfig(SubnetConfig subnetConfig) {
64         name = subnetConfig.name;
65         subnet = subnetConfig.subnet;
66         nodePorts = new HashSet<String>(subnetConfig.nodePorts);
67     }
68
69     public String getName() {
70         return name;
71     }
72
73     public Set<String> getNodePorts() {
74         return nodePorts;
75     }
76
77     public String getSubnet() {
78         return subnet;
79     }
80
81     public InetAddress getIPnum() {
82         InetAddress ip = null;
83         try {
84             ip = InetAddress.getByName(subnet.split("/")[0]);
85         } catch (UnknownHostException e1) {
86             return null;
87         }
88         return ip;
89     }
90
91     public Short getIPMaskLen() {
92         Short maskLen = 0;
93         if (hasValidIP()) {
94             String[] s = subnet.split("/");
95             maskLen = (s.length == 2) ? Short.valueOf(s[1]) : 32;
96         }
97         return maskLen;
98     }
99
100     private Set<Short> getPortList(String ports) {
101         /*
102          * example:
103          *     ports = "1,3,5-12"
104          *     elemArray = ["1" "3" "5-12"]
105          *     elem[2] = "5-12" --> limits = ["5" "12"]
106          *     portList = [1 3 5 6 7 8 9 10 11 12]
107          */
108         Set<Short> portList = new HashSet<Short>();
109         String[] elemArray = ports.split(",");
110         for (String elem : elemArray) {
111             if (elem.contains("-")) {
112                 String[] limits = elem.split("-");
113                 for (short j = Short.valueOf(limits[0]); j <= Short
114                         .valueOf(limits[1]); j++) {
115                     portList.add(Short.valueOf(j));
116                 }
117             } else {
118                 portList.add(Short.valueOf(elem));
119             }
120         }
121         return portList;
122     }
123
124     private boolean hasValidIP() {
125         if (subnet != null) {
126             if (NetUtils.isIPv4AddressValid(subnet)) {
127                 return true;
128             } else if (NetUtils.isIPv6AddressValid(subnet)) {
129                 return true;
130             }
131         }
132         return false;
133     }
134
135     private boolean hasValidPorts() {
136         for (String portSet : nodePorts) {
137             if (!portSet.contains("/")) {
138                 return false;
139             }
140         }
141         return true;
142     }
143
144     public boolean isValidSwitchPort(String sp) {
145         return sp.contains("/");
146     }
147
148     public boolean isValidConfig() {
149         return hasValidIP() && hasValidPorts();
150     }
151
152     @Override
153     public int hashCode() {
154         return name.hashCode();
155     }
156
157     @Override
158     public boolean equals(Object obj) {
159         /*
160          * Configuration will be stored in collection only if it is valid
161          * Hence we don't check here for uninitialized fields
162          */
163         if (this == obj)
164             return true;
165         if (obj == null)
166             return false;
167         if (getClass() != obj.getClass())
168             return false;
169         SubnetConfig that = (SubnetConfig) obj;
170         if (this.subnet.equals(that.subnet)) {
171             return true;
172         }
173         return false;
174     }
175
176     public static List<String> getGuiFieldsNames() {
177         List<String> fieldList = new ArrayList<String>();
178         for (String str : prettyFields) {
179             fieldList.add(str);
180         }
181         return fieldList;
182     }
183
184     //Utility method useful for adding to a passed Set all the
185     //NodeConnectors learnt from a string
186     private void getNodeConnectorsFromString(String codedNodeConnectors,
187             Set<NodeConnector> sp) {
188         if (codedNodeConnectors == null) {
189             return;
190         }
191         if (sp == null) {
192             return;
193         }
194         // codedNodeConnectors = xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
195         String pieces[] = codedNodeConnectors.split("/");
196         for (Short port : getPortList(pieces[1])) {
197             Node n = Node.fromString(pieces[0]);
198             if (n == null) {
199                 continue;
200             }
201             NodeConnector p = NodeConnectorCreator.createOFNodeConnector(port,
202                     n);
203             if (p == null) {
204                 continue;
205             }
206             sp.add(p);
207         }
208     }
209
210     public Set<NodeConnector> getSubnetNodeConnectors() {
211         Set<NodeConnector> sp = new HashSet<NodeConnector>();
212         if (isGlobal())
213             return sp;
214         for (String str : nodePorts) {
215             getNodeConnectorsFromString(str, sp);
216         }
217         return sp;
218     }
219
220     public Set<NodeConnector> getNodeConnectors(String codedNodeConnectors) {
221         // codedNodeConnectors = xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
222         Set<NodeConnector> sp = new HashSet<NodeConnector>();
223         getNodeConnectorsFromString(codedNodeConnectors, sp);
224         return sp;
225     }
226
227     public boolean isGlobal() {
228         // If no ports are specified to be part of the domain, then it's a global domain IP
229         return (nodePorts == null || nodePorts.isEmpty());
230     }
231
232     public void addNodeConnectors(String sp) {
233         nodePorts.add(sp);
234     }
235
236     public void removeNodeConnectors(String sp) {
237         nodePorts.remove(sp);
238     }
239
240     @Override
241     public String toString() {
242         return ("SubnetConfig [Description=" + name + ", Subnet=" + subnet
243                 + ", NodeConnectors=" + nodePorts + "]");
244     }
245
246     /**
247      * Implement clonable interface
248      */
249     @Override
250     public SubnetConfig clone() {
251         return new SubnetConfig(this);
252     }
253
254 }