4c02be45546f46db2e16544f03397850a2ed6dd4
[netvirt.git] /
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.translator.crud.INeutronPortCRUD;
12 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityGroupCRUD;
13 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
14 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
15 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityGroupCacheManger;
16 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
17 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
18 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
19 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
20 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityRule;
21 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
22 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSecurityRuleCRUD;
23 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
26 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
27 import org.osgi.framework.ServiceReference;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.ArrayList;
32 import java.util.HashSet;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.concurrent.ConcurrentHashMap;
39
40
41 /**
42  * @author Aswin Suryanarayanan.
43  */
44
45 public class SecurityGroupCacheManagerImpl implements ConfigInterface, SecurityGroupCacheManger {
46
47     private final Map<String, Map<String, NodeId>> securityGroupCache = new ConcurrentHashMap<>();
48     private static final Logger LOG = LoggerFactory.getLogger(SecurityGroupCacheManagerImpl.class);
49     private volatile SecurityServicesManager securityServicesManager;
50     private volatile Southbound southbound;
51     private volatile INeutronPortCRUD neutronPortCache;
52     private volatile NeutronL3Adapter neutronL3Adapter;
53     private volatile INeutronSecurityRuleCRUD neutronSecurityRule;
54
55     @Override
56     public void portAdded(String securityGroupUuid, String portUuid) {
57         LOG.debug("In portAdded securityGroupUuid: {} portUuid: {} " , securityGroupUuid, portUuid);
58         NeutronPort port = neutronL3Adapter.getPortPreferablyFromCleanupCache(portUuid);
59         if(port == null) {
60             return;
61         }
62         processPortAdded(securityGroupUuid, port);
63     }
64
65     @Override
66     public void portRemoved(String securityGroupUuid, String portUuid) {
67         LOG.debug("In portRemoved securityGroupUuid: {} portUuid: {} " , securityGroupUuid, portUuid);
68         NeutronPort port = neutronL3Adapter.getPortPreferablyFromCleanupCache(portUuid);
69         if(port == null) {
70             return;
71         }
72         processPortRemoved(securityGroupUuid, port);
73     }
74
75     @Override
76     public void addToCache(String remoteSgUuid, String portUuid, NodeId nodeId) {
77         LOG.debug("In addToCache remoteSgUuid:" + remoteSgUuid + " portUuid:" + portUuid);
78         Map<String, NodeId> remoteSgPorts = securityGroupCache.get(remoteSgUuid);
79         if (null == remoteSgPorts) {
80             remoteSgPorts = new HashMap<>();
81             securityGroupCache.put(remoteSgUuid, remoteSgPorts);
82         }
83         remoteSgPorts.put(portUuid, nodeId);
84     }
85
86     @Override
87     public void removeFromCache(String remoteSgUuid, String portUuid) {
88         LOG.debug("In removeFromCache remoteSgUuid:" + remoteSgUuid + " portUuid:" + portUuid);
89         Map<String, NodeId> remoteSgPorts = securityGroupCache.get(remoteSgUuid);
90         if (null == remoteSgPorts) {
91             LOG.debug("The port list is empty for security group:" + remoteSgUuid);
92             return;
93         }
94         Set<String> portSet = remoteSgPorts.keySet();
95         for (Iterator<String> iterator = portSet.iterator(); iterator.hasNext();) {
96             String cachedPort = iterator.next();
97             if (cachedPort.equals(portUuid)) {
98                 iterator.remove();
99                 break;
100             }
101         }
102         if (portSet.isEmpty()) {
103             securityGroupCache.remove(remoteSgUuid);
104         }
105     }
106
107     private void processPortAdded(String securityGroupUuid, NeutronPort port) {
108         processSyncRule(securityGroupUuid, port, true);
109     }
110
111     private void processSyncRule(String securityGroupUuid, NeutronPort port, boolean write) {
112         /*
113          * Itreate through the cache maintained for the security group added. For each port in the cache
114          * add the rule to allow traffic to/from the new port added.
115          */
116         LOG.debug("In processPortAdded securityGroupUuid: {}, NeutronPort: {}", securityGroupUuid, port);
117         Map<String, NodeId> portMap = securityGroupCache.get(securityGroupUuid);
118         if (null == portMap) {
119             LOG.debug("The port list is empty for security group: {}", securityGroupUuid);
120             return;
121         }
122         Set portSet = portMap.entrySet();
123         Iterator itr = portSet.iterator();
124         Map<String, List<NeutronSecurityRule>> secGrpRulesMap = new HashMap<String, List<NeutronSecurityRule>>();
125         while(itr.hasNext()) {
126             Map.Entry<String, NodeId> portEntry = (Map.Entry)itr.next();
127             String cachedportUuid = portEntry.getKey();
128             NodeId nodeId = portEntry.getValue();
129             if (cachedportUuid.equals(port.getID())) {
130                 continue;
131             }
132             NeutronPort cachedport = neutronL3Adapter.getPortPreferablyFromCleanupCache(cachedportUuid);
133             if(cachedport == null) {
134                 continue;
135             }
136             retrieveAndSyncSecurityRules(securityGroupUuid, cachedport, nodeId, secGrpRulesMap, port, write);
137         }
138     }
139
140     private void processPortRemoved(String securityGroupUuid, NeutronPort port) {
141         processSyncRule(securityGroupUuid, port, false);
142     }
143
144     private void retrieveAndSyncSecurityRules(String securityGroupUuid, NeutronPort cachedport, NodeId nodeId,
145             Map<String, List<NeutronSecurityRule> > secGrpRulesMap, NeutronPort currentPort, boolean write) {
146         /*
147          * Get the list of security rules in the port with portUuid that has securityGroupUuid as a remote
148          * security group.
149          */
150         List<NeutronSecurityRule> securityRules =  new ArrayList<NeutronSecurityRule>();
151         List<NeutronSecurityGroup> securityGroups = cachedport.getSecurityGroups();
152         for (NeutronSecurityGroup securityGroup : securityGroups) {
153             securityRules = secGrpRulesMap.get(securityGroup.getSecurityGroupUUID());
154             if (securityRules == null) {
155                 securityRules = getSecurityRulesforGroup(securityGroup);
156                 secGrpRulesMap.put(securityGroup.getSecurityGroupUUID(), securityRules);
157             }
158             for (NeutronSecurityRule securityRule : securityRules) {
159                 if (securityGroupUuid.equals(securityRule.getSecurityRemoteGroupID())) {
160                     if (currentPort.getFixedIPs() == null) {
161                         continue;
162                     }
163                     for (Neutron_IPs vmIp : currentPort.getFixedIPs()) {
164                         if (write) {
165                             securityServicesManager.syncSecurityRule(cachedport, securityRule, vmIp, nodeId, securityGroup, true);
166                         } else {
167                             securityServicesManager.syncSecurityRule(cachedport, securityRule, vmIp, nodeId, securityGroup, false);
168                         }
169                     }
170                 }
171             }
172         }
173     }
174
175     private void init() {
176         /*
177          * Rebuild the cache in case of a restart.
178          */
179         Map<String, NodeId> portNodeCache = getPortNodeCache();
180         List<NeutronPort> portList = neutronPortCache.getAllPorts();
181         for (NeutronPort port:portList) {
182             List<NeutronSecurityGroup> securityGroupList = port.getSecurityGroups();
183             if ( null != securityGroupList) {
184                 for (NeutronSecurityGroup securityGroup : securityGroupList) {
185                     List<NeutronSecurityRule> securityRuleList = getSecurityRulesforGroup(securityGroup);
186                     if ( null != securityRuleList) {
187                         for (NeutronSecurityRule securityRule : securityRuleList) {
188                             if (null != securityRule.getSecurityRemoteGroupID()) {
189                                 this.addToCache(securityRule.getSecurityRemoteGroupID(), port.getID(), portNodeCache.get(port.getID()));
190                             }
191                         }
192                     }
193                 }
194             }
195         }
196     }
197
198     private Map<String, NodeId> getPortNodeCache() {
199         Map<String, NodeId> portNodeCache = new HashMap();
200         List<Node> toplogyNodes = southbound.readOvsdbTopologyNodes();
201
202         for (Node topologyNode : toplogyNodes) {
203             try {
204                 Node node = southbound.getBridgeNode(topologyNode,Constants.INTEGRATION_BRIDGE);
205                 if (node == null) {
206                     LOG.error("getNode: br-int interface is not found for node:{}", topologyNode.getNodeId().getValue());
207                 }
208                 List<OvsdbTerminationPointAugmentation> ovsdbPorts = southbound.getTerminationPointsOfBridge(node);
209                 for (OvsdbTerminationPointAugmentation ovsdbPort : ovsdbPorts) {
210                     String uuid = southbound.getInterfaceExternalIdsValue(ovsdbPort,
211                                                             Constants.EXTERNAL_ID_INTERFACE_ID);
212                     NodeId nodeId = node.getNodeId();
213                     if (null != uuid && null != nodeId) {
214                         portNodeCache.put(uuid, nodeId);
215                     }
216                 }
217             } catch (Exception e) {
218                 LOG.error("Exception during handlingNeutron network delete", e);
219             }
220         }
221         return portNodeCache;
222     }
223
224     private List<NeutronSecurityRule> getSecurityRulesforGroup(NeutronSecurityGroup securityGroup) {
225         List<NeutronSecurityRule> securityRules = new ArrayList<>();
226         List<NeutronSecurityRule> rules = neutronSecurityRule.getAllNeutronSecurityRules();
227         for (NeutronSecurityRule securityRule : rules) {
228             if (securityGroup.getID().equals(securityRule.getSecurityRuleGroupID())) {
229                 securityRules.add(securityRule);
230             }
231         }
232         return securityRules;
233     }
234
235     @Override
236     public void setDependencies(ServiceReference serviceReference) {
237         neutronL3Adapter =
238                 (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
239         securityServicesManager =
240                 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
241         southbound =
242                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.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 }