Merge "Neutron floatingIp dissasociate fix"
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / LispStateManager.java
1 /*
2  * Copyright (c) 2017 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.lisp;
10
11 import com.google.common.base.Preconditions;
12
13 import java.util.concurrent.ExecutionException;
14
15 import javax.annotation.Nonnull;
16
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.NativeForwardPathsTables;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801._native.forward.paths.tables._native.forward.paths.table.NativeForwardPath;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170801.gpe.feature.data.grouping.GpeFeatureData;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.Lisp;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.dp.subtable.grouping.local.mappings.LocalMapping;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.dp.subtable.grouping.local.mappings.local.mapping.Eid;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.eid.table.grouping.eid.table.VniTable;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.itr.remote.locator.sets.grouping.ItrRemoteLocatorSet;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.lisp.feature.data.grouping.LispFeatureData;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.locator.sets.grouping.locator.sets.LocatorSet;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.map.register.grouping.MapRegister;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.map.resolvers.grouping.map.resolvers.MapResolver;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170911.map.servers.grouping.map.servers.MapServer;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public class LispStateManager {
49     private static final Logger LOG = LoggerFactory.getLogger(LispStateManager.class);
50
51     private HostRelatedInfoContainer hostRelatedInfoContainer;
52     private MountedDataBrokerProvider mountedDataBrokerProvider;
53     private ConfigManagerHelper lispStateHelper;
54
55     private NeutronTenantToVniMapper neutronTenantToVniMapper;
56
57     private static final short DEFAULT_PRIORITY = 1;
58     private static final short DEFAULT_WEIGHT = 1;
59     public static final String DEFAULT_XTR_KEY = "admin";
60     public static final String DEFAULT_LOCATOR_SET_NAME_PREFIX = "LS";
61     public static final String DEFAULT_MAPPING_RECORD_NAME_PREFIX = "MR_";
62
63     public LispStateManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
64         Preconditions.checkNotNull(mountedDataBrokerProvider,
65                 "MountedDataBrokerProvider found to be null!");
66         hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
67         this.mountedDataBrokerProvider= mountedDataBrokerProvider;
68         this.lispStateHelper = new ConfigManagerHelper(this.mountedDataBrokerProvider);
69         neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
70     }
71
72     public synchronized void processCreateEndPoint(AddressEndpointWithLocation addressEp) {
73         try {
74             if (lispStateHelper.isMetadataPort(addressEp)) {
75                 return;
76             }
77             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
78             LispState lispStateOfHost = configureHostIfNeeded(endpointHost);
79
80             long vni = getVni(addressEp.getTenant().getValue());
81             long vrf = vni;
82
83             Eid eid = lispStateHelper.getEid(addressEp, vni);
84             String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
85
86             addVniSpecificConfigurationsIfNeeded(endpointHost, lispStateOfHost, vni, vrf);
87
88             if (lispStateHelper.getInterfaceIp(addressEp).getValue().equals(Constants.METADATA_IP)) {
89                 return;
90             }
91
92             addEidOnHostIfNeeded(endpointHost, lispStateOfHost, eid, eidMappingName);
93         } catch (LispConfigCommandFailedException e) {
94             LOG.warn("Lisp endpoint configuration failed for address endpoint: {}", addressEp);
95         }
96     }
97
98     private void addEidOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfNode, Eid eid,
99                                       String eidMappingName)
100             throws LispConfigCommandFailedException {
101         if(!lispStateOfNode.eidSetContains(eid)) {
102             addEidInEidTable(endpointHost, lispStateOfNode, eid, eidMappingName);
103         }
104     }
105
106     private synchronized LispState configureHostIfNeeded(EndpointHost endpointHost)
107             throws LispConfigCommandFailedException {
108         LispState lispStateOfHost = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
109
110         if (lispStateOfHost == null) {
111             LOG.debug("Configuring host {} for LISP", endpointHost.getHostName());
112             lispStateOfHost = new LispState();
113             try {
114                 enableLispOnHost(endpointHost, lispStateOfHost);
115                 enableGpeOnHostIfNeeded(endpointHost, lispStateOfHost);
116                 addLocatorSetOnHost(endpointHost, lispStateOfHost);
117                 addMapResolverOnHost(endpointHost, lispStateOfHost);
118                 enableMapRegistrationOnHostIfNeeded(endpointHost, lispStateOfHost);
119
120                 hostRelatedInfoContainer.setLispStateOfHost(endpointHost.getHostName(), lispStateOfHost);
121             } catch (LispNotFoundException e) {
122                 LOG.warn("Lisp host configuration failed: ", e.getMessage());
123                 throw new LispConfigCommandFailedException("Failed LISP configuration!");
124             }
125         }
126         return lispStateOfHost;
127     }
128
129     private void enableGpeOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
130             throws LispConfigCommandFailedException {
131         if (ConfigUtil.getInstance().isL3FlatEnabled()) {
132             enableGpeForHost(endpointHost, lispStateOfHost);
133         }
134     }
135
136     private void enableMapRegistrationOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
137             throws LispConfigCommandFailedException {
138         if (ConfigUtil.getInstance().isLispMapRegisterEnabled()) {
139             enableMapRegister(endpointHost);
140             addMapServer(endpointHost, lispStateOfHost);
141         }
142     }
143
144     private void enableLispOnHost(EndpointHost endpointHost, LispState lispState)
145             throws LispConfigCommandFailedException {
146         LOG.debug("Enabling LISP on host {}", endpointHost.getHostName());
147         AbstractLispCommand<Lisp> lispEnableCommand = LispCommandWrapper.enableLisp();
148         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), lispEnableCommand)) {
149             lispState.setLispEnabled(true);
150         } else {
151             throw new LispConfigCommandFailedException("Lisp Enable Command failed execution!");
152         }
153     }
154
155     private void enableGpeForHost(EndpointHost endpointHost, LispState lispState)
156             throws LispConfigCommandFailedException {
157         AbstractLispCommand<GpeFeatureData> gpeEnableCommand = LispCommandWrapper.enableGpe();
158         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), gpeEnableCommand)) {
159             lispState.setGpeEnabled(true);
160         } else {
161             throw new LispConfigCommandFailedException("GPE Enable Command failed execution!");
162         }
163     }
164
165     private void addLocatorSetOnHost(EndpointHost endpointHost, LispState lispState)
166             throws LispNotFoundException, LispConfigCommandFailedException {
167         try {
168             String locatorSetName = lispStateHelper.constructLocatorSetName(lispState.getLocatorCount());
169             String lispDataInterfaceName = lispStateHelper
170                     .getLispDataRlocInterfaceName(endpointHost.getHostName()).get();
171             AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
172                     lispDataInterfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
173             if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addLocatorSetCommand)) {
174                 lispState.setLocIntfToLocSetNameMapping(lispDataInterfaceName, locatorSetName);
175             } else {
176                 throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
177                         + endpointHost.getHostName() + " and locator interface " + lispDataInterfaceName);
178             }
179
180             addExtraItrRlocLocatorSetIfNeeded(endpointHost, lispDataInterfaceName);
181         } catch (InterruptedException | ExecutionException e) {
182             throw new LispNotFoundException("No interface with Ip Address found!");
183         }
184     }
185
186     private void addExtraItrRlocLocatorSetIfNeeded(EndpointHost endpointHost, String lispDataInterfaceName)
187             throws LispNotFoundException, LispConfigCommandFailedException {
188         String lispCpRlocInterfaceName = lispStateHelper.getLispCpRlocInterfaceName(endpointHost);
189         if (lispCpRlocInterfaceName == null
190                 || lispCpRlocInterfaceName.isEmpty()
191                 || lispCpRlocInterfaceName.equals(lispDataInterfaceName)) {
192             return;
193         }
194
195         addItrLocatorSet(endpointHost, lispCpRlocInterfaceName);
196     }
197
198     private void addItrLocatorSet(EndpointHost endpointHost, String lispCpInterfaceName)
199             throws LispNotFoundException, LispConfigCommandFailedException {
200         String locatorSetName = lispStateHelper.constructLocatorSetNameForItrRloc();
201         AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
202                 lispCpInterfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
203         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addLocatorSetCommand)) {
204             throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
205                     + endpointHost.getHostName() + " and locator interface " + lispCpInterfaceName);
206         }
207
208         AbstractLispCommand<ItrRemoteLocatorSet> addItrRlocCommand = LispCommandWrapper.addItrRloc(locatorSetName);
209         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addItrRlocCommand)) {
210             throw new LispConfigCommandFailedException("Lisp add Itr Rloc command failed for host "
211                     + endpointHost.getHostName() + " and locator set " + locatorSetName);
212         }
213     }
214
215     private void addMapResolverOnHost(EndpointHost endpointHost, LispState lispState)
216             throws LispConfigCommandFailedException {
217         IpAddress mapResolverIpAddress = ConfigUtil.getInstance().getOdlIp();
218         Preconditions.checkNotNull(mapResolverIpAddress, "Map Resolver ip not properly configured!");
219
220         AbstractLispCommand<MapResolver> addMapResolverCommand = LispCommandWrapper.
221                 addMapResolver(mapResolverIpAddress);
222         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addMapResolverCommand)) {
223             lispState.addInMapResolverSet(mapResolverIpAddress);
224         } else {
225             throw new LispConfigCommandFailedException("Lisp add map resolver for host " + endpointHost.getHostName()
226                     + " failed for ODL ip " + mapResolverIpAddress);
227         }
228     }
229
230     private void enableMapRegister(EndpointHost endpointHost)
231             throws LispConfigCommandFailedException {
232         AbstractLispCommand<MapRegister> enableMapRegisterCommand = LispCommandWrapper.enableMapRegister();
233
234         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), enableMapRegisterCommand)) {
235             throw new LispConfigCommandFailedException("Lisp enable mapregistration for host "
236                     + endpointHost.getHostName() + " failed!");
237         }
238
239     }
240
241     private void addMapServer(EndpointHost endpointHost, LispState lispState) throws LispConfigCommandFailedException {
242         IpAddress mapServerIpAddress = ConfigUtil.getInstance().getOdlIp();
243         Preconditions.checkNotNull(mapServerIpAddress, "Mapserver ip not properly configured!");
244         AbstractLispCommand<MapServer> addMapServerCommand = LispCommandWrapper.addMapServer(mapServerIpAddress);
245
246         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addMapServerCommand)) {
247             lispState.addInMapServerSet(mapServerIpAddress);
248         } else {
249             throw new LispConfigCommandFailedException("Lisp add map server for host " + endpointHost.getHostName()
250                     + " failed for ODL ip " + mapServerIpAddress);
251         }
252     }
253
254     private void addVniSpecificConfigurationsIfNeeded(EndpointHost endpointHost,
255                                                       LispState lispState,
256                                                       long vni, long vrf) throws LispConfigCommandFailedException {
257         if (!lispState.isVniConfigured(vni)) {
258             addVniToVrfMapping(endpointHost, lispState, vni, vrf);
259             addGpeNativeForwardPath(endpointHost, vrf,
260                     hostRelatedInfoContainer.getPhysicalInterfaceState(endpointHost.getHostName())
261                             .getIp(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC));
262         }
263     }
264
265     private void addVniToVrfMapping(EndpointHost endpointHost,
266                                     LispState lispState,
267                                     long vni, long vrf) throws LispConfigCommandFailedException {
268         AbstractLispCommand<VniTable> addVniToVrfMapping = LispCommandWrapper.mapVniToVrf(vni, vrf);
269         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addVniToVrfMapping)) {
270             lispState.addInVniSet(vni);
271         } else {
272             throw new LispConfigCommandFailedException("Lisp add vrf " + vrf +" for vni " +vni
273                     + " command failed!");
274         }
275     }
276
277     private void addGpeNativeForwardPath(EndpointHost endpointHost,
278                                          long vrf, IpAddress nativeForwardIp) throws LispConfigCommandFailedException {
279         AbstractLispCommand<NativeForwardPath> addNativeForwardingIp =
280                 LispCommandWrapper.addNativeForwardEntry(vrf, nativeForwardIp);
281         if (!LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addNativeForwardingIp)) {
282             throw new LispConfigCommandFailedException("Lisp add native forwarding to ip " + addNativeForwardingIp
283                     + " for vrf " + vrf + " command failed!");
284         }
285     }
286
287     private void addEidInEidTable(EndpointHost endpointHost,
288                                   LispState lispState,
289                                   Eid eid,
290                                   String eidMappingName) throws LispConfigCommandFailedException {
291         AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
292                 .addLocalMappingInEidTable(eidMappingName,
293                         eid,
294                         lispStateHelper.getFirstLocatorSetName(lispState),
295                         lispStateHelper.getDefaultHmacKey());
296         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostName(), addLocalMappingInEidTableCommand)) {
297             lispState.addEidInEidSet(eid);
298         } else {
299             throw new LispConfigCommandFailedException("Lisp add local mapping for eid " + eid + "failed!");
300         }
301     }
302
303     public synchronized void processDeleteEndpoint(AddressEndpointWithLocation addressEp) {
304         try {
305
306             if (lispStateHelper.isMetadataPort(addressEp)) {
307                 return;
308             }
309
310             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
311
312             LispState lispState = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
313
314             if (lispState == null) {
315                 LOG.debug("Endpoint not configured for LISP. EndPoint: {}", addressEp);
316             } else {
317                 long vni = getVni(addressEp.getTenant().getValue());
318                 Eid eid = lispStateHelper.getEid(addressEp, vni);
319                 String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
320
321                 deleteEidFromLocalEidTableOfHostIfNeeded(endpointHost, lispState, eid, eidMappingName);
322
323                 if (lispState.eidCount() == 0) {
324                     deleteLispStatesFromHost(endpointHost);
325                     deleteNativeForwardPathsTables(endpointHost);
326                 }
327             }
328         } catch (LispConfigCommandFailedException e) {
329             LOG.warn("Lisp command execution failed: {}", e.getMessage());
330         }
331     }
332
333     private void deleteEidFromLocalEidTableOfHostIfNeeded(EndpointHost endpointHost, LispState lispState, Eid eid,
334         String eidMappingName) throws LispConfigCommandFailedException {
335         if (lispState.eidSetContains(eid)) {
336             deleteEidFromLocalEidTableOfHost(endpointHost, lispState, eid, eidMappingName);
337         }
338     }
339
340     private void deleteEidFromLocalEidTableOfHost(EndpointHost endpointHost,
341                                        LispState lispState,
342                                        Eid eid,
343                                        String eidMappingName) throws LispConfigCommandFailedException {
344         long value = eid.getVirtualNetworkId().getValue();
345
346         AbstractLispCommand<LocalMapping> deleteLocalMappingCommand = LispCommandWrapper
347                 .deleteLocalMappingFromEidTable(eidMappingName, value);
348
349         if (LispStateCommandExecutor
350                 .executeDeleteCommand(endpointHost.getHostName(), deleteLocalMappingCommand)) {
351             LOG.debug("Successfully deleted eid {} from host {}", eid, endpointHost.getHostName());
352             lispState.deleteEid(eid);
353         } else {
354             throw new LispConfigCommandFailedException("Lisp delete local mapping command failed!");
355         }
356     }
357
358
359     private void deleteLispStatesFromHost(EndpointHost endpointHost) throws LispConfigCommandFailedException {
360         AbstractLispCommand<LispFeatureData> deleteLispFeatureData = LispCommandWrapper.deleteLispFeatureData();
361
362         if (LispStateCommandExecutor.executeDeleteCommand(endpointHost.getHostName(), deleteLispFeatureData)) {
363             hostRelatedInfoContainer.deleteLispStateOfHost(endpointHost.getHostName());
364             LOG.debug("Deleted all lisp data for host {}", endpointHost.getHostName());
365         } else {
366             throw new LispConfigCommandFailedException("Lisp delete feature data command failed!");
367         }
368     }
369
370     private void deleteNativeForwardPathsTables(EndpointHost endpointHost)
371             throws LispConfigCommandFailedException {
372         AbstractLispCommand<NativeForwardPathsTables> deleteNativeForwardPathsTables = LispCommandWrapper
373                 .deleteNativeForwardPathsTables();
374
375         if (!LispStateCommandExecutor.executeDeleteCommand(endpointHost.getHostName(),
376                 deleteNativeForwardPathsTables)) {
377             throw new LispConfigCommandFailedException("Delete Native Forward Paths Tables command failed!");
378         }
379     }
380
381     private long getVni(String tenantUuid) {
382         return neutronTenantToVniMapper.getVni(tenantUuid);
383     }
384 }