273d4209533112d181f106e490a9b459e9477b2a
[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             }\r
228             else {\r
229                 subnet.setGatewayIPAllocated();\r
230             }\r
231             subnet.addPort(input);\r
232         }\r
233         INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
234 \r
235         NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());\r
236         network.addPort(input);\r
237         return true;\r
238     }\r
239 \r
240     public boolean removePort(String uuid) {\r
241         if (!portExists(uuid))\r
242             return false;\r
243         NeutronPort port = getPort(uuid);\r
244         portDB.remove(uuid);\r
245         INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
246         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
247 \r
248         NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());\r
249         network.removePort(port);\r
250         Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
251         while (fixedIPIterator.hasNext()) {\r
252             Neutron_IPs ip = fixedIPIterator.next();\r
253             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
254             if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
255                 subnet.releaseIP(ip.getIpAddress());\r
256             }\r
257             else {\r
258                 subnet.resetGatewayIPAllocated();\r
259             }\r
260             subnet.removePort(port);\r
261         }\r
262         return true;\r
263     }\r
264 \r
265     public boolean updatePort(String uuid, NeutronPort delta) {\r
266         if (!portExists(uuid))\r
267             return false;\r
268         NeutronPort target = portDB.get(uuid);\r
269         // remove old Fixed_IPs\r
270         NeutronPort port = getPort(uuid);\r
271         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
272         Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
273         while (fixedIPIterator.hasNext()) {\r
274             Neutron_IPs ip = fixedIPIterator.next();\r
275             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
276             subnet.releaseIP(ip.getIpAddress());\r
277         }\r
278 \r
279         // allocate new Fixed_IPs\r
280         fixedIPIterator = delta.getFixedIPs().iterator();\r
281         while (fixedIPIterator.hasNext()) {\r
282             Neutron_IPs ip = fixedIPIterator.next();\r
283             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
284             if (ip.getIpAddress() == null)\r
285                 ip.setIpAddress(subnet.getLowAddr());\r
286             subnet.allocateIP(ip.getIpAddress());\r
287         }\r
288         return overwrite(target, delta);\r
289     }\r
290 \r
291     public boolean macInUse(String macAddress) {\r
292         List<NeutronPort> ports = getAllPorts();\r
293         Iterator<NeutronPort> portIterator = ports.iterator();\r
294         while (portIterator.hasNext()) {\r
295             NeutronPort port = portIterator.next();\r
296             if (macAddress.equalsIgnoreCase(port.getMacAddress()))\r
297                 return true;\r
298         }\r
299         return false;\r
300     }\r
301 \r
302     public NeutronPort getGatewayPort(String subnetUUID) {\r
303         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
304         NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);\r
305         Iterator<NeutronPort> portIterator = getAllPorts().iterator();\r
306         while (portIterator.hasNext()) {\r
307             NeutronPort port = portIterator.next();\r
308             List<Neutron_IPs> fixedIPs = port.getFixedIPs();\r
309             if (fixedIPs.size() == 1) {\r
310                 if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress()))\r
311                     return port;\r
312             }\r
313         }\r
314         return null;\r
315     }\r
316 \r
317 }\r