Merge "Simplify overlay information mappers and managers"
[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 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.AbstractLispCommand;
14 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.lisp.LispCommandWrapper;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.LispState;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.gpe.rev170518.gpe.feature.data.grouping.GpeFeatureData;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.Lisp;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.LocalMapping;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.eid.table.grouping.eid.table.VniTable;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.lisp.feature.data.grouping.LispFeatureData;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.locator.sets.grouping.locator.sets.LocatorSet;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.register.grouping.MapRegister;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.resolvers.grouping.map.resolvers.MapResolver;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.map.servers.grouping.map.servers.MapServer;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import javax.annotation.Nonnull;
42 import java.util.concurrent.ExecutionException;
43
44 /**
45  * Created by Shakib Ahmed on 3/29/17.
46  */
47 public class LispStateManager {
48     private static final Logger LOG = LoggerFactory.getLogger(LispStateManager.class);
49
50     private HostRelatedInfoContainer hostRelatedInfoContainer;
51     private MountedDataBrokerProvider mountedDataBrokerProvider;
52     private ConfigManagerHelper lispStateHelper;
53
54     private NeutronTenantToVniMapper neutronTenantToVniMapper;
55
56     private static final short DEFAULT_PRIORITY = 1;
57     private static final short DEFAULT_WEIGHT = 1;
58     public static final String DEFAULT_XTR_KEY = "admin";
59     public static final String DEFAULT_LOCATOR_SET_NAME_PREFIX = "LS";
60     public static final String DEFAULT_MAPPINGRECORD_NAME_PREFIX = "MR_";
61
62     public LispStateManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
63         Preconditions.checkNotNull(mountedDataBrokerProvider,
64                 "MountedDataBrokerProvider found to be null!");
65         hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
66         this.mountedDataBrokerProvider= mountedDataBrokerProvider;
67         this.lispStateHelper = new ConfigManagerHelper(this.mountedDataBrokerProvider);
68         neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
69     }
70
71     public synchronized void processCreateEndPoint(AddressEndpointWithLocation addressEp) {
72         try {
73             if (lispStateHelper.isMetadataPort(addressEp)) {
74                 return;
75             }
76             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
77             LispState lispStateOfHost = configureHostIfNeeded(endpointHost);
78
79             long vni = getVni(addressEp.getTenant().getValue());
80             long vrf = vni;
81
82             Eid eid = lispStateHelper.getEid(addressEp, vni);
83             String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
84
85             addVniToVrfMappingIfNeeded(endpointHost.getHostDataBroker(), lispStateOfHost, vni, vrf);
86
87             if (lispStateHelper.getInterfaceIp(addressEp).getValue().equals(Constants.METADATA_IP)) {
88                 return;
89             }
90
91             addEidOnHostIfNeeded(endpointHost, lispStateOfHost, eid, eidMappingName);
92         } catch (LispConfigCommandFailedException e) {
93             LOG.warn("Lisp endpoint configuration failed for address endpoint: {}", addressEp);
94         }
95     }
96
97     private void addEidOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfNode, Eid eid,
98                                       String eidMappingName)
99             throws LispConfigCommandFailedException {
100         if(!lispStateOfNode.eidSetContains(eid)) {
101             addEidInEidTable(endpointHost.getHostDataBroker(), lispStateOfNode, eid, eidMappingName);
102         }
103     }
104
105     private synchronized LispState configureHostIfNeeded(EndpointHost endpointHost)
106             throws LispConfigCommandFailedException {
107         LispState lispStateOfHost = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
108
109         if (lispStateOfHost == null) {
110             LOG.debug("Configuring host {} for LISP", endpointHost.getHostName());
111             lispStateOfHost = new LispState();
112             try {
113                 enableLispOnHost(endpointHost, lispStateOfHost);
114                 enableGpeOnHostIfNeeded(endpointHost, lispStateOfHost);
115                 addLocatorSetOnHost(endpointHost, lispStateOfHost);
116                 addMapResolverOnHost(endpointHost, lispStateOfHost);
117                 enableMapRegistrationOnHostIfNeeded(endpointHost, lispStateOfHost);
118
119                 hostRelatedInfoContainer.setLispStateOfHost(endpointHost.getHostName(), lispStateOfHost);
120             } catch (LispNotFoundException e) {
121                 LOG.warn("Lisp host configuration failed: ", e.getMessage());
122                 throw new LispConfigCommandFailedException("Failed LISP configuration!");
123             }
124         }
125         return lispStateOfHost;
126     }
127
128     private void enableGpeOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
129             throws LispConfigCommandFailedException {
130         if (ConfigUtil.getInstance().isL3FlatEnabled()) {
131             enableGpeForHost(endpointHost, lispStateOfHost);
132         }
133     }
134
135     private void enableMapRegistrationOnHostIfNeeded(EndpointHost endpointHost, LispState lispStateOfHost)
136             throws LispConfigCommandFailedException {
137         if (ConfigUtil.getInstance().isLispMapRegisterEnabled()) {
138             enableMapRegister(endpointHost);
139             addMapServer(endpointHost, lispStateOfHost);
140         }
141     }
142
143     private void enableLispOnHost(EndpointHost endpointHost, LispState lispState)
144             throws LispConfigCommandFailedException {
145         AbstractLispCommand<Lisp>
146                 lispEnableCommand = LispCommandWrapper.enableLisp();
147         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), lispEnableCommand)) {
148             lispState.setLispEnabled(true);
149         } else {
150             throw new LispConfigCommandFailedException("Lisp Enable Command failed execution!");
151         }
152     }
153
154     private void enableGpeForHost(EndpointHost endpointHost, LispState lispState)
155             throws LispConfigCommandFailedException {
156         AbstractLispCommand<GpeFeatureData>
157                 gpeEnableCommand = LispCommandWrapper.enableGpe();
158         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), 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 interfaceName = lispStateHelper
170                     .readRlocInterface(endpointHost.getHostName(), endpointHost.getHostDataBroker()).get();
171             AbstractLispCommand<LocatorSet> addLocatorSetCommand = LispCommandWrapper.addLocatorSet(locatorSetName,
172                     interfaceName, DEFAULT_PRIORITY, DEFAULT_WEIGHT);
173             if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addLocatorSetCommand)) {
174                 lispState.setLocIntfToLocSetNameMapping(interfaceName, locatorSetName);
175             } else {
176                 throw new LispConfigCommandFailedException("Lisp add locator set failed for host "
177                         + endpointHost.getHostName() + " and locator interface " + interfaceName);
178             }
179         } catch (InterruptedException | ExecutionException e) {
180             throw new LispNotFoundException("No interface with Ip Address found!");
181         }
182
183     }
184
185     private void addMapResolverOnHost(EndpointHost endpointHost, LispState lispState)
186             throws LispConfigCommandFailedException {
187         IpAddress mapResolverIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
188         Preconditions.checkNotNull(mapResolverIpAddress, "Map Resolver ip not properly configured!");
189
190         AbstractLispCommand<MapResolver> addMapResolverCommand = LispCommandWrapper.
191                 addMapResolver(mapResolverIpAddress);
192         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addMapResolverCommand)) {
193             lispState.addInMapResolverSet(mapResolverIpAddress);
194         } else {
195             throw new LispConfigCommandFailedException("Lisp add map resolver for host " + endpointHost.getHostName()
196                     + " failed for ODL ip " + mapResolverIpAddress);
197         }
198     }
199
200     private void enableMapRegister(EndpointHost endpointHost)
201             throws LispConfigCommandFailedException {
202         AbstractLispCommand<MapRegister> enableMapRegisterCommand = LispCommandWrapper.enableMapRegister();
203
204         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), enableMapRegisterCommand)) {
205         } else {
206             throw new LispConfigCommandFailedException("Lisp enable mapregistration for host "
207                     + endpointHost.getHostName() + " failed!");
208         }
209
210     }
211
212     private void addMapServer(EndpointHost endpointHost, LispState lispState) throws LispConfigCommandFailedException {
213         IpAddress mapServerIpAddress = ConfigUtil.getInstance().getOdlTenantIp();
214         Preconditions.checkNotNull(mapServerIpAddress, "Mapserver ip not properly configured!");
215         AbstractLispCommand<MapServer> addMapServerCommand = LispCommandWrapper.addMapServer(mapServerIpAddress);
216
217         if (LispStateCommandExecutor.executePutCommand(endpointHost.getHostDataBroker(), addMapServerCommand)) {
218             lispState.addInMapServerSet(mapServerIpAddress);
219         } else {
220             throw new LispConfigCommandFailedException("Lisp add map server for host " + endpointHost.getHostName()
221                     + " failed for ODL ip " + mapServerIpAddress);
222         }
223     }
224
225     private void addVniToVrfMappingIfNeeded(DataBroker vppDataBroker,
226                                             LispState lispState,
227                                             long vni, long vrf) throws LispConfigCommandFailedException {
228         if (!lispState.isVniConfigured(vni)) {
229             AbstractLispCommand<VniTable> addVniToVrfMapping = LispCommandWrapper.mapVniToVrf(vni, vrf);
230             addVniToVrfMapping.setOptions(General.Operations.PUT);
231             if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addVniToVrfMapping)) {
232                 lispState.addInVniSet(vni);
233             } else {
234                 throw new LispConfigCommandFailedException("Lisp add vrf " + vrf +" for vni " +vni
235                         + " command failed!");
236             }
237         }
238     }
239
240     private void addEidInEidTable(DataBroker vppDataBroker,
241                                   LispState lispState,
242                                   Eid eid,
243                                   String eidMappingName) throws LispConfigCommandFailedException {
244         AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
245                 .addLocalMappingInEidTable(eidMappingName,
246                         eid,
247                         lispStateHelper.getFirstLocatorSetName(lispState),
248                         lispStateHelper.getDefaultHmacKey());
249         if (LispStateCommandExecutor.executePutCommand(vppDataBroker, addLocalMappingInEidTableCommand)) {
250             lispState.addEidInEidSet(eid);
251         } else {
252             throw new LispConfigCommandFailedException("Lisp add local mapping for eid " + eid + "failed!");
253         }
254     }
255
256     public synchronized void processDeleteEndpoint(AddressEndpointWithLocation addressEp) {
257         try {
258
259             if (lispStateHelper.isMetadataPort(addressEp)) {
260                 return;
261             }
262
263             EndpointHost endpointHost = lispStateHelper.getEndpointHostInformation(addressEp);
264
265             LispState lispState = hostRelatedInfoContainer.getLispStateOfHost(endpointHost.getHostName());
266
267             if (lispState == null) {
268                 LOG.debug("Endpoint not configured for LISP. EndPoint: {}", addressEp);
269             } else {
270                 long vni = getVni(addressEp.getTenant().getValue());
271                 Eid eid = lispStateHelper.getEid(addressEp, vni);
272                 String eidMappingName = lispStateHelper.constructEidMappingName(addressEp);
273
274                 deleteEidFromLocalEidTableOfHostIfNeeded(endpointHost, lispState, eid, eidMappingName);
275
276                 if (lispState.eidCount() == 0) {
277                     deleteLispStatesFromHost(endpointHost);
278                 }
279             }
280         } catch (LispConfigCommandFailedException e) {
281             LOG.warn("Lisp command execution failed: {}", e.getMessage());
282         }
283     }
284
285     private void deleteEidFromLocalEidTableOfHostIfNeeded(EndpointHost endpointHost, LispState lispState, Eid eid, String eidMappingName) throws LispConfigCommandFailedException {
286         if (lispState.eidSetContains(eid)) {
287             deleteEidFromLocalEidTableOfHost(endpointHost, lispState, eid, eidMappingName);
288         }
289     }
290
291     private void deleteEidFromLocalEidTableOfHost(EndpointHost endpointHost,
292                                        LispState lispState,
293                                        Eid eid,
294                                        String eidMappingName) throws LispConfigCommandFailedException {
295         long value = eid.getVirtualNetworkId().getValue();
296
297         AbstractLispCommand<LocalMapping> deleteLocalMappingCommand = LispCommandWrapper
298                 .deleteLocalMappingFromEidTable(eidMappingName, value);
299
300         if (LispStateCommandExecutor
301                 .executeDeleteCommand(endpointHost.getHostDataBroker(), deleteLocalMappingCommand)) {
302             LOG.debug("Successfully deleted eid {} from host {}", eid, endpointHost.getHostName());
303             lispState.deleteEid(eid);
304         } else {
305             throw new LispConfigCommandFailedException("Lisp delete local mapping command failed!");
306         }
307     }
308
309
310     private void deleteLispStatesFromHost(EndpointHost endpointHost) throws LispConfigCommandFailedException {
311         AbstractLispCommand<LispFeatureData> deleteLispFeatureData = LispCommandWrapper.deleteLispFeatureData();
312
313         if (LispStateCommandExecutor.executeDeleteCommand(endpointHost.getHostDataBroker(), deleteLispFeatureData)) {
314             hostRelatedInfoContainer.deleteLispStateOfHost(endpointHost.getHostName());
315             LOG.debug("Deleted all lisp data for host {}", endpointHost.getHostName());
316         } else {
317             throw new LispConfigCommandFailedException("Lisp delete feature data command failed!");
318         }
319     }
320
321     private long getVni(String tenantUuid) {
322         return neutronTenantToVniMapper.getVni(tenantUuid);
323     }
324 }