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