8f1e70f052832ebb68ef38045d1b80638b2fca66
[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         clusterContainerService = s;\r
50     }\r
51 \r
52     void unsetClusterContainerService(IClusterContainerServices s) {\r
53         if (clusterContainerService == s) {\r
54             logger.debug("Cluster Service removed!");\r
55             clusterContainerService = null;\r
56         }\r
57     }\r
58 \r
59     @SuppressWarnings("deprecation")\r
60     private void allocateCache() {\r
61         if (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             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 (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>) 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 (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         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             containerName = (String) props.get("containerName");\r
118             logger.debug("Running containerName: {}", containerName);\r
119         } else {\r
120             // In the Global instance case the containerName is empty\r
121             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     @Override\r
183     public boolean portExists(String uuid) {\r
184         return portDB.containsKey(uuid);\r
185     }\r
186 \r
187     @Override\r
188     public NeutronPort getPort(String uuid) {\r
189         if (!portExists(uuid)) {\r
190             return null;\r
191         }\r
192         return portDB.get(uuid);\r
193     }\r
194 \r
195     @Override\r
196     public List<NeutronPort> getAllPorts() {\r
197         Set<NeutronPort> allPorts = new HashSet<NeutronPort>();\r
198         for (Entry<String, NeutronPort> entry : portDB.entrySet()) {\r
199             NeutronPort port = entry.getValue();\r
200             allPorts.add(port);\r
201         }\r
202         logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size());\r
203         List<NeutronPort> ans = new ArrayList<NeutronPort>();\r
204         ans.addAll(allPorts);\r
205         return ans;\r
206     }\r
207 \r
208     @Override\r
209     public boolean addPort(NeutronPort input) {\r
210         if (portExists(input.getID())) {\r
211             return false;\r
212         }\r
213         portDB.putIfAbsent(input.getID(), input);\r
214         // if there are no fixed IPs, allocate one for each subnet in the network\r
215         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
216         if (input.getFixedIPs().size() == 0) {\r
217             List<Neutron_IPs> list = input.getFixedIPs();\r
218             Iterator<NeutronSubnet> subnetIterator = systemCRUD.getAllSubnets().iterator();\r
219             while (subnetIterator.hasNext()) {\r
220                 NeutronSubnet subnet = subnetIterator.next();\r
221                 if (subnet.getNetworkUUID().equals(input.getNetworkUUID())) {\r
222                     list.add(new Neutron_IPs(subnet.getID()));\r
223                 }\r
224             }\r
225         }\r
226         Iterator<Neutron_IPs> fixedIPIterator = input.getFixedIPs().iterator();\r
227         while (fixedIPIterator.hasNext()) {\r
228             Neutron_IPs ip = fixedIPIterator.next();\r
229             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
230             if (ip.getIpAddress() == null) {\r
231                 ip.setIpAddress(subnet.getLowAddr());\r
232             }\r
233             if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
234                 subnet.allocateIP(ip.getIpAddress());\r
235             }\r
236             else {\r
237                 subnet.setGatewayIPAllocated();\r
238             }\r
239             subnet.addPort(input);\r
240         }\r
241         INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
242 \r
243         NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID());\r
244         network.addPort(input);\r
245         return true;\r
246     }\r
247 \r
248     @Override\r
249     public boolean removePort(String uuid) {\r
250         if (!portExists(uuid)) {\r
251             return false;\r
252         }\r
253         NeutronPort port = getPort(uuid);\r
254         portDB.remove(uuid);\r
255         INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);\r
256         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
257 \r
258         NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID());\r
259         network.removePort(port);\r
260         Iterator<Neutron_IPs> fixedIPIterator = port.getFixedIPs().iterator();\r
261         while (fixedIPIterator.hasNext()) {\r
262             Neutron_IPs ip = fixedIPIterator.next();\r
263             NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
264             if (!ip.getIpAddress().equals(subnet.getGatewayIP())) {\r
265                 subnet.releaseIP(ip.getIpAddress());\r
266             }\r
267             else {\r
268                 subnet.resetGatewayIPAllocated();\r
269             }\r
270             subnet.removePort(port);\r
271         }\r
272         return true;\r
273     }\r
274 \r
275     @Override\r
276     public boolean updatePort(String uuid, NeutronPort delta) {\r
277         if (!portExists(uuid)) {\r
278             return false;\r
279         }\r
280         NeutronPort target = portDB.get(uuid);\r
281         // remove old Fixed_IPs\r
282         if (delta.getFixedIPs() != null) {\r
283             NeutronPort port = getPort(uuid);\r
284             INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
285             for (Neutron_IPs ip: port.getFixedIPs()) {\r
286                 NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
287                 subnet.releaseIP(ip.getIpAddress());\r
288             }\r
289 \r
290             // allocate new Fixed_IPs\r
291             for (Neutron_IPs ip: delta.getFixedIPs()) {\r
292                 NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID());\r
293                 if (ip.getIpAddress() == null) {\r
294                     ip.setIpAddress(subnet.getLowAddr());\r
295                 }\r
296                 subnet.allocateIP(ip.getIpAddress());\r
297             }\r
298         }\r
299         return overwrite(target, delta);\r
300     }\r
301 \r
302     @Override\r
303     public boolean macInUse(String macAddress) {\r
304         List<NeutronPort> ports = getAllPorts();\r
305         Iterator<NeutronPort> portIterator = ports.iterator();\r
306         while (portIterator.hasNext()) {\r
307             NeutronPort port = portIterator.next();\r
308             if (macAddress.equalsIgnoreCase(port.getMacAddress())) {\r
309                 return true;\r
310             }\r
311         }\r
312         return false;\r
313     }\r
314 \r
315     @Override\r
316     public NeutronPort getGatewayPort(String subnetUUID) {\r
317         INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);\r
318         NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID);\r
319         Iterator<NeutronPort> portIterator = getAllPorts().iterator();\r
320         while (portIterator.hasNext()) {\r
321             NeutronPort port = portIterator.next();\r
322             List<Neutron_IPs> fixedIPs = port.getFixedIPs();\r
323             if (fixedIPs.size() == 1) {\r
324                 if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress())) {\r
325                     return port;\r
326                 }\r
327             }\r
328         }\r
329         return null;\r
330     }\r
331 \r
332 }\r