Initial push of Neutron interface
[controller.git] / opendaylight / networkconfiguration / neutron / implementation / src / main / java / org / opendaylight / controller / networkconfig / neutron / implementation / NeutronPortInterface.java
1 /*\r
2  * Copyright IBM Corporation, 2013.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.controller.networkconfig.neutron.implementation;\r
10 \r
11 import java.lang.reflect.Method;\r
12 import java.util.ArrayList;\r
13 import java.util.Dictionary;\r
14 import java.util.EnumSet;\r
15 import java.util.HashSet;\r
16 import java.util.Iterator;\r
17 import java.util.List;\r
18 import java.util.Set;\r
19 import java.util.Map.Entry;\r
20 import java.util.concurrent.ConcurrentMap;\r
21 \r
22 import org.apache.felix.dm.Component;\r
23 import org.opendaylight.controller.clustering.services.CacheConfigException;\r
24 import org.opendaylight.controller.clustering.services.CacheExistException;\r
25 import org.opendaylight.controller.clustering.services.IClusterContainerServices;\r
26 import org.opendaylight.controller.clustering.services.IClusterServices;\r
27 import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;\r
28 import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;\r
29 import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;\r
30 import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;\r
31 import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;\r
32 import org.opendaylight.controller.networkconfig.neutron.NeutronPort;\r
33 import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;\r
34 import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;\r
35 import org.slf4j.Logger;\r
36 import org.slf4j.LoggerFactory;\r
37 \r
38 public class NeutronPortInterface implements INeutronPortCRUD {\r
39     private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);\r
40     private String containerName = null;\r
41 \r
42     private IClusterContainerServices clusterContainerService = null;\r
43     private ConcurrentMap<String, NeutronPort> portDB;\r
44 \r
45     // methods needed for creating caches\r
46 \r
47     void setClusterContainerService(IClusterContainerServices s) {\r
48         logger.debug("Cluster Service set");\r
49         this.clusterContainerService = s;\r
50     }\r
51 \r
52     void unsetClusterContainerService(IClusterContainerServices s) {\r
53         if (this.clusterContainerService == s) {\r
54             logger.debug("Cluster Service removed!");\r
55             this.clusterContainerService = null;\r
56         }\r
57     }\r
58 \r
59     @SuppressWarnings("deprecation")\r
60     private void allocateCache() {\r
61         if (this.clusterContainerService == null) {\r
62             logger.error("un-initialized clusterContainerService, can't create cache");\r
63             return;\r
64         }\r
65         logger.debug("Creating Cache for OpenDOVE");\r
66         try {\r
67             // neutron caches\r
68             this.clusterContainerService.createCache("neutronPorts",\r
69                     EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));\r
70         } catch (CacheConfigException cce) {\r
71             logger.error("Cache couldn't be created for OpenDOVE -  check cache mode");\r
72         } catch (CacheExistException cce) {\r
73             logger.error("Cache for OpenDOVE already exists, destroy and recreate");\r
74         }\r
75         logger.debug("Cache successfully created for OpenDOVE");\r
76     }\r
77 \r
78     @SuppressWarnings({ "unchecked", "deprecation" })\r
79     private void retrieveCache() {\r
80         if (this.clusterContainerService == null) {\r
81             logger.error("un-initialized clusterContainerService, can't retrieve cache");\r
82             return;\r
83         }\r
84 \r
85         logger.debug("Retrieving cache for Neutron Ports");\r
86         portDB = (ConcurrentMap<String, NeutronPort>) this.clusterContainerService\r
87         .getCache("neutronPorts");\r
88         if (portDB == null) {\r
89             logger.error("Cache couldn't be retrieved for Neutron Ports");\r
90         }\r
91         logger.debug("Cache was successfully retrieved for Neutron Ports");\r
92     }\r
93 \r
94     @SuppressWarnings("deprecation")\r
95     private void destroyCache() {\r
96         if (this.clusterContainerService == null) {\r
97             logger.error("un-initialized clusterMger, can't destroy cache");\r
98             return;\r
99         }\r
100         logger.debug("Destroying Cache for HostTracker");\r
101         this.clusterContainerService.destroyCache("neutronPorts");\r
102     }\r
103 \r
104     private void startUp() {\r
105         allocateCache();\r
106         retrieveCache();\r
107     }\r
108 \r
109     /**\r
110      * Function called by the dependency manager when all the required\r
111      * dependencies are satisfied\r
112      *\r
113      */\r
114     void init(Component c) {\r
115         Dictionary<?, ?> props = c.getServiceProperties();\r
116         if (props != null) {\r
117             this.containerName = (String) props.get("containerName");\r
118             logger.debug("Running containerName: {}", this.containerName);\r
119         } else {\r
120             // In the Global instance case the containerName is empty\r
121             this.containerName = "";\r
122         }\r
123         startUp();\r
124     }\r
125 \r
126     /**\r
127      * Function called by the dependency manager when at least one dependency\r
128      * become unsatisfied or when the component is shutting down because for\r
129      * example bundle is being stopped.\r
130      *\r
131      */\r
132     void destroy() {\r
133         destroyCache();\r
134     }\r
135 \r
136     /**\r
137      * Function called by dependency manager after "init ()" is called and after\r
138      * the services provided by the class are registered in the service registry\r
139      *\r
140      */\r
141     void start() {\r
142     }\r
143 \r
144     /**\r
145      * Function called by the dependency manager before the services exported by\r
146      * the component are unregistered, this will be followed by a "destroy ()"\r
147      * calls\r
148      *\r
149      */\r
150     void stop() {\r
151     }\r
152 \r
153     // this method uses reflection to update an object from it's delta.\r
154 \r
155     private boolean overwrite(Object target, Object delta) {\r
156         Method[] methods = target.getClass().getMethods();\r
157 \r
158         for(Method toMethod: methods){\r
159             if(toMethod.getDeclaringClass().equals(target.getClass())\r
160                     && toMethod.getName().startsWith("set")){\r
161 \r
162                 String toName = toMethod.getName();\r
163                 String fromName = toName.replace("set", "get");\r
164 \r
165                 try {\r
166                     Method fromMethod = delta.getClass().getMethod(fromName);\r
167                     Object value = fromMethod.invoke(delta, (Object[])null);\r
168                     if(value != null){\r
169                         toMethod.invoke(target, value);\r
170                     }\r
171                 } catch (Exception e) {\r
172                     e.printStackTrace();\r
173                     return false;\r
174                 }\r
175             }\r
176         }\r
177         return true;\r
178     }\r
179 \r
180     // IfNBPortCRUD methods\r
181 \r
182     public boolean portExists(String uuid) {\r
183         return portDB.containsKey(uuid);\r
184     }\r
185 \r
186     public NeutronPort getPort(String uuid) {\r
187         if (!portExists(uuid))\r
188             return null;\r
189         return portDB.get(uuid);\r
190     }\r
191 \r
192     public List<NeutronPort> getAllPorts() {\r
193         Set<NeutronPort> allPorts = new HashSet<NeutronPort>();\r
194         for (Entry<String, NeutronPort> entry : portDB.entrySet()) {\r
195             NeutronPort port = entry.getValue();\r
196             allPorts.add(port);\r
197         }\r
198         logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());\r
199         List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
200         ans.addAll(allPorts);\r
201         return ans;\r
202     }\r
203 \r
204     public boolean addPort(NeutronPort input) {\r
205         if (portExists(input.getID()))\r
206             return false;\r
207         portDB.putIfAbsent(input.getID(), input);\r
208         // if there are no fixed IPs, allocate one for each subnet in the network\r
209         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
210         if (input.getFixedIPs().size() == 0) {\r
211             List<Neutron_IPs> list = input.getFixedIPs();\r
212             Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();\r
213             while (subnetIterator.hasNext()) {\r
214                 NeutronSubnet subnet = subnetIterator.next();\r
215                 if (subnet.getNetworkUUID().equals(input.getNetworkUUID()))\r
216                     list.add(new Neutron_IPs(subnet.getID()));\r
217             }\r
218         }\r
219         Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();\r
220         while (fixedIPIterator.hasNext()) {\r
221             Neutron_IPs ip = fixedIPIterator.next();\r
222             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
223             if (ip.getIpAddress() == null)\r
224                 ip.setIpAddress(subnet.getLowAddr());\r
225             if (!ip.getIpAddress().equals(subnet.getGatewayIP()))\r
226                 subnet.allocateIP(ip.getIpAddress());\r
227             else\r
228                 subnet.setGatewayIPAllocated();\r
229             subnet.addPort(input);\r
230         }\r
231         INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
232 \r
233         NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());\r
234         network.addPort(input);\r
235         return true;\r
236     }\r
237 \r
238     public boolean removePort(String uuid) {\r
239         if (!portExists(uuid))\r
240             return false;\r
241         NeutronPort port = getPort(uuid);\r
242         portDB.remove(uuid);\r
243         INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
244         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
245 \r
246         NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());\r
247         network.removePort(port);\r
248         Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
249         while (fixedIPIterator.hasNext()) {\r
250             Neutron_IPs ip = fixedIPIterator.next();\r
251             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
252             if (!ip.getIpAddress().equals(subnet.getGatewayIP()))\r
253                 subnet.releaseIP(ip.getIpAddress());\r
254             else\r
255                 subnet.resetGatewayIPAllocated();\r
256             subnet.removePort(port);\r
257         }\r
258         return true;\r
259     }\r
260 \r
261     public boolean updatePort(String uuid, NeutronPort delta) {\r
262         if (!portExists(uuid))\r
263             return false;\r
264         NeutronPort target = portDB.get(uuid);\r
265         // remove old Fixed_IPs\r
266         NeutronPort port = getPort(uuid);\r
267         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
268         Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
269         while (fixedIPIterator.hasNext()) {\r
270             Neutron_IPs ip = fixedIPIterator.next();\r
271             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
272             subnet.releaseIP(ip.getIpAddress());\r
273         }\r
274 \r
275         // allocate new Fixed_IPs\r
276         fixedIPIterator = delta.getFixedIPs().iterator();\r
277         while (fixedIPIterator.hasNext()) {\r
278             Neutron_IPs ip = fixedIPIterator.next();\r
279             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
280             if (ip.getIpAddress() == null)\r
281                 ip.setIpAddress(subnet.getLowAddr());\r
282             subnet.allocateIP(ip.getIpAddress());\r
283         }\r
284         return overwrite(target, delta);\r
285     }\r
286 \r
287     public boolean macInUse(String macAddress) {\r
288         List<NeutronPort> ports = getAllPorts();\r
289         Iterator<NeutronPort> portIterator = ports.iterator();\r
290         while (portIterator.hasNext()) {\r
291             NeutronPort port = portIterator.next();\r
292             if (macAddress.equalsIgnoreCase(port.getMacAddress()))\r
293                 return true;\r
294         }\r
295         return false;\r
296     }\r
297 \r
298     public NeutronPort getGatewayPort(String subnetUUID) {\r
299         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
300         NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);\r
301         Iterator<NeutronPort> portIterator = getAllPorts().iterator();\r
302         while (portIterator.hasNext()) {\r
303             NeutronPort port = portIterator.next();\r
304             List<Neutron_IPs> fixedIPs = port.getFixedIPs();\r
305             if (fixedIPs.size() == 1) {\r
306                 if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress()))\r
307                     return port;\r
308             }\r
309         }\r
310         return null;\r
311     }\r
312 \r
313 }\r