cfebe8b5805ebf64fbd8e7abeabb8c1b14448405
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / netvirt / openstack / netvirt / impl / SecurityGroupCacheManagerImpl.java
1 /*
2  * Copyright (c) 2014, 2015 HP, Inc. and others. 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.netvirt.openstack.netvirt.impl;
10
11 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
12 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronPortCRUD;
13 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
14 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityGroupCacheManger;
15 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
16 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
17 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
18 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
19 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityRuleCRUD;
20 import org.opendaylight.netvirt.utils.neutron.utils.NeutronUtils;
21 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
22 import org.osgi.framework.ServiceReference;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.concurrent.ConcurrentHashMap;
33
34
35 /**
36  * @author Aswin Suryanarayanan.
37  */
38
39 public class SecurityGroupCacheManagerImpl implements ConfigInterface, SecurityGroupCacheManger {
40
41     private final Map<String, Set<String>> securityGroupCache = new ConcurrentHashMap<>();
42     private static final Logger LOG = LoggerFactory.getLogger(SecurityGroupCacheManagerImpl.class);
43     private volatile SecurityServicesManager securityServicesManager;
44     private volatile INeutronPortCRUD neutronPortCache;
45     private volatile NeutronL3Adapter neutronL3Adapter;
46     private volatile INeutronSecurityRuleCRUD neutronSecurityRule;
47
48     @Override
49     public void portAdded(String securityGroupUuid, String portUuid) {
50         LOG.debug("In portAdded securityGroupUuid:" + securityGroupUuid + " portUuid:" + portUuid);
51         NeutronPort port = neutronPortCache.getPort(portUuid);
52         if (port == null) {
53             port = neutronL3Adapter.getPortFromCleanupCache(portUuid);
54             if (port == null) {
55                 LOG.error("In portAdded no neutron port found:" + " portUuid:" + portUuid);
56                 return;
57             }
58         }
59         processPortAdded(securityGroupUuid,port);
60     }
61
62     @Override
63     public void portRemoved(String securityGroupUuid, String portUuid) {
64         LOG.debug("In portRemoved securityGroupUuid:" + securityGroupUuid + " portUuid:" + portUuid);
65         NeutronPort port = neutronPortCache.getPort(portUuid);
66
67         if (port == null) {
68             port = neutronL3Adapter.getPortFromCleanupCache(portUuid);
69             if (port == null) {
70                 LOG.error("In portRemoved no neutron port found:" + " portUuid:" + portUuid);
71                 return;
72             }
73         }
74         processPortRemoved(securityGroupUuid,port);
75     }
76
77     @Override
78     public void addToCache(String remoteSgUuid, String portUuid) {
79         LOG.debug("In addToCache remoteSgUuid:" + remoteSgUuid + "portUuid:" + portUuid);
80         Set<String> portList = securityGroupCache.get(remoteSgUuid);
81         if (null == portList) {
82             portList = new HashSet<>();
83             securityGroupCache.put(remoteSgUuid, portList);
84         }
85         portList.add(portUuid);
86     }
87
88     @Override
89     public void removeFromCache(String remoteSgUuid, String portUuid) {
90         LOG.debug("In removeFromCache remoteSgUuid:" + remoteSgUuid + " portUuid:" + portUuid);
91         Set<String> portList = securityGroupCache.get(remoteSgUuid);
92         if (null == portList) {
93             LOG.debug("The port list is empty for security group:" + remoteSgUuid);
94             return;
95         }
96         for (Iterator<String> iterator = portList.iterator(); iterator.hasNext();) {
97             String cachedPort = iterator.next();
98             if (cachedPort.equals(portUuid)) {
99                 iterator.remove();
100                 break;
101             }
102         }
103         if (portList.isEmpty()) {
104             securityGroupCache.remove(remoteSgUuid);
105         }
106     }
107
108     private void processPortAdded(String securityGroupUuid, NeutronPort port) {
109         /*
110          * Itreate through the cache maintained for the security group added. For each port in the cache
111          * add the rule to allow traffic to/from the new port added.
112          */
113         LOG.debug("In processPortAdded securityGroupUuid:" + securityGroupUuid + " NeutronPort:" + port);
114         Set<String> portList = this.securityGroupCache.get(securityGroupUuid);
115         if (null == portList) {
116             LOG.debug("The port list is empty for security group:" + securityGroupUuid);
117             return;
118         }
119         for (String cachedportUuid : portList) {
120             if (cachedportUuid.equals(port.getID())) {
121                 continue;
122             }
123             NeutronPort cachedport = neutronPortCache.getPort(cachedportUuid);
124             if (null == cachedport) {
125                 LOG.error("In processPortAdded cachedport port not found in neuton cache:"
126                             + " cachedportUuid:" + cachedportUuid);
127                 continue;
128             }
129             List<NeutronSecurityRule> remoteSecurityRules = retrieveSecurityRules(securityGroupUuid, cachedportUuid);
130             for (NeutronSecurityRule securityRule : remoteSecurityRules) {
131                 if (port.getFixedIPs() == null) {
132                     continue;
133                 }
134                 for (Neutron_IPs vmIp : port.getFixedIPs()) {
135                     securityServicesManager.syncSecurityRule(cachedport, securityRule, vmIp, true);
136                 }
137             }
138         }
139     }
140
141     private void processPortRemoved(String securityGroupUuid, NeutronPort port) {
142         /*
143          * Itreate through the cache maintained for the security group added. For each port in the cache remove
144          * the rule to allow traffic to/from the  port that got deleted.
145          */
146         LOG.debug("In processPortRemoved securityGroupUuid:" + securityGroupUuid + " port:" + port);
147         Set<String> portList = this.securityGroupCache.get(securityGroupUuid);
148         if (null == portList) {
149             LOG.debug("The port list is empty for security group:" + securityGroupUuid);
150             return;
151         }
152         for (String cachedportUuid : portList) {
153             if (cachedportUuid.equals(port.getID())) {
154                 continue;
155             }
156             NeutronPort cachedport = neutronPortCache.getPort(cachedportUuid);
157             if (cachedport == null) {
158                 cachedport = neutronL3Adapter.getPortFromCleanupCache(cachedportUuid);
159                 if (null == cachedport) {
160                     LOG.error("In processPortRemoved cachedport port not found in neuton cache:"
161                                 + " cachedportUuid:" + cachedportUuid);
162                     continue;
163                 }
164             }
165             List<NeutronSecurityRule> remoteSecurityRules = retrieveSecurityRules(securityGroupUuid, cachedportUuid);
166             for (NeutronSecurityRule securityRule : remoteSecurityRules) {
167                 if (port.getFixedIPs() == null) {
168                     continue;
169                 }
170                 for (Neutron_IPs vmIp : port.getFixedIPs()) {
171                     securityServicesManager.syncSecurityRule(cachedport, securityRule, vmIp, false);
172                 }
173             }
174         }
175     }
176
177     private List<NeutronSecurityRule> retrieveSecurityRules(String securityGroupUuid, String portUuid) {
178         /*
179          * Get the list of security rules in the port with portUuid that has securityGroupUuid as a remote
180          * security group.
181          */
182         LOG.debug("In retrieveSecurityRules securityGroupUuid:" + securityGroupUuid + " portUuid:" + portUuid);
183         NeutronPort port = neutronPortCache.getPort(portUuid);
184         if (port == null) {
185             port = neutronL3Adapter.getPortFromCleanupCache(portUuid);
186             if (null == port) {
187                 LOG.error("In retrieveSecurityRules no neutron port found:" + " portUuid:" + portUuid);
188                 return null;
189             }
190         }
191         List<NeutronSecurityRule> remoteSecurityRules = new ArrayList<>();
192         List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
193         for (NeutronSecurityGroup securityGroup : securityGroups) {
194             List<NeutronSecurityRule> securityRules = getSecurityRulesforGroup(securityGroup);
195             for (NeutronSecurityRule securityRule : securityRules) {
196                 if (securityGroupUuid.equals(securityRule.getSecurityRemoteGroupID())) {
197                     remoteSecurityRules.add(securityRule);
198                 }
199             }
200         }
201         return remoteSecurityRules;
202     }
203
204     private void init() {
205         /*
206          * Rebuild the cache in case of a restart.
207          */
208         List<NeutronPort> portList = neutronPortCache.getAllPorts();
209         for (NeutronPort port:portList) {
210             List<NeutronSecurityGroup> securityGroupList = port.getSecurityGroups();
211             if ( null != securityGroupList) {
212                 for (NeutronSecurityGroup securityGroup : securityGroupList) {
213                     List<NeutronSecurityRule> securityRuleList = getSecurityRulesforGroup(securityGroup);
214                     if ( null != securityRuleList) {
215                         for (NeutronSecurityRule securityRule : securityRuleList) {
216                             if (null != securityRule.getSecurityRemoteGroupID()) {
217                                 this.addToCache(securityRule.getSecurityRemoteGroupID(), port.getID());
218                             }
219                         }
220                     }
221                 }
222             }
223         }
224     }
225
226     private List<NeutronSecurityRule> getSecurityRulesforGroup(NeutronSecurityGroup securityGroup) {
227         List<NeutronSecurityRule> securityRules = new ArrayList<>();
228         List<NeutronSecurityRule> rules = neutronSecurityRule.getAllNeutronSecurityRules();
229         for (NeutronSecurityRule securityRule : rules) {
230             if (securityGroup.getID().equals(securityRule.getSecurityRuleGroupID())) {
231                 securityRules.add(securityRule);
232             }
233         }
234         return securityRules;
235     }
236
237     @Override
238     public void setDependencies(ServiceReference serviceReference) {
239         neutronL3Adapter =
240                 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
241         securityServicesManager =
242                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
243         neutronPortCache = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, this);
244         neutronSecurityRule = (INeutronSecurityRuleCRUD) ServiceHelper.getGlobalInstance(INeutronSecurityRuleCRUD.class, this);
245         init();
246     }
247
248     @Override
249     public void setDependencies(Object impl) {
250     }
251 }