2432933f0108fc4f930e68ab5a18ef38b1ea5cba
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / util / ConfigManagerHelper.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.util;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispState;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispNotFoundException;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostIdToInterfaceInfoMapper;
22 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.Ipv4Afi;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.Containment;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.dp.subtable.grouping.local.mappings.local.mapping.Eid;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.hmac.key.grouping.HmacKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.Routing;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.RoutingBuilder;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import javax.annotation.Nonnull;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Set;
68
69
70 /**
71  * Created by Shakib Ahmed on 3/31/17.
72  */
73 public class ConfigManagerHelper {
74     private static final Logger LOG = LoggerFactory.getLogger(ConfigManagerHelper.class);
75
76     private static final String TENANT_INTERFACE = "tenant-interface";
77     private MountedDataBrokerProvider mountedDataBrokerProvider;
78
79     public ConfigManagerHelper(MountedDataBrokerProvider mountedDataBrokerProvider) {
80         this.mountedDataBrokerProvider = mountedDataBrokerProvider;
81     }
82
83     public Optional<DataBroker> getPotentialExternalDataBroker(AddressEndpointWithLocation addressEpWithLoc) {
84         ExternalLocationCase externalLocationCase = resolveAndValidateLocation(addressEpWithLoc);
85         InstanceIdentifier<?> vppNodeIid = externalLocationCase.getExternalNodeMountPoint();
86         String interfacePath = externalLocationCase.getExternalNodeConnector();
87
88         Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
89
90         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
91                 "Cannot resolve data broker for interface path: {}", interfacePath);
92
93         return potentialVppDataProvider;
94     }
95
96     public Optional<DataBroker> getPotentialExternalDataBroker(ExternalLocation externalLocation) {
97         InstanceIdentifier<?> vppNodeIid = externalLocation.getExternalNodeMountPoint();
98
99         Optional<DataBroker> potentialVppDataProvider;
100         potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
101
102         Preconditions.checkState(potentialVppDataProvider.isPresent(), "Data Broker missing");
103
104         return potentialVppDataProvider;
105     }
106
107     public Optional<DataBroker> getPotentialExternalDataBroker(VppEndpoint vppEp) {
108         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEp.getVppNodeId());
109         Optional<DataBroker> potentialVppDataProvider =
110                 mountedDataBrokerProvider.getDataBrokerForMountPoint(vppNodeIid);
111
112         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
113                 "Cannot resolve data broker for Vpp Endpoint: {}", vppEp);
114         return potentialVppDataProvider;
115     }
116
117     public Optional<DataBroker> getPotentialExternalDataBroker(String hostId) {
118         InstanceIdentifier<Node> nodeIid = VppIidFactory.getNetconfNodeIid(new NodeId(hostId));
119         Optional<DataBroker> potentialVppDataProvider = mountedDataBrokerProvider.getDataBrokerForMountPoint(nodeIid);
120         Preconditions.checkArgument(potentialVppDataProvider.isPresent(),
121                 "Data Broker not found for {}", hostId);
122         return potentialVppDataProvider;
123     }
124
125     public Optional<String> getHostName(AddressEndpointWithLocation addrEp) {
126         ExternalLocationCase locationCase = resolveAndValidateLocation(addrEp);
127         NodeKey nodeKey = locationCase.getExternalNodeMountPoint().firstKeyOf(Node.class);
128         String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
129                 "Host Id extraction failed from address endpoint: {}", addrEp);
130         return Optional.fromNullable(hostId);
131     }
132
133     public Optional<String> getHostName(ExternalLocation externalLocation) {
134         NodeKey nodeKey = externalLocation.getExternalNodeMountPoint().firstKeyOf(Node.class);
135         String hostId = Preconditions.checkNotNull(nodeKey.getNodeId().getValue(),
136                 "Host Id extraction failed from address endpoint: {}", externalLocation);
137
138         return Optional.fromNullable(hostId);
139     }
140
141     public ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
142         Preconditions.checkNotNull(addrEpWithLoc.getAbsoluteLocation(), "Absolute location for " +
143                 "AddressEndpointWithLocation missing: " + addrEpWithLoc.toString() );
144         LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
145         if (!(locationType instanceof ExternalLocationCase)) {
146             throw new IllegalArgumentException("Endpoint does not have external location " + addrEpWithLoc);
147         }
148         ExternalLocationCase result = (ExternalLocationCase) locationType;
149         if (result.getExternalNodeMountPoint() == null || result.getExternalNodeConnector() == null) {
150             throw new IllegalArgumentException(
151                     "Endpoint does not have external-node-mount-point or external-node-connector " + addrEpWithLoc);
152         }
153         return result;
154     }
155
156     //This is almost identical to VBD's equivalent method
157     public ListenableFuture<String> readRlocInterface(@Nonnull String hostName, @Nonnull DataBroker vppDataBroker) {
158         Preconditions.checkNotNull(hostName, "Hostname is null!");
159         Preconditions.checkNotNull(vppDataBroker, "Vpp DataBroker is null!");
160
161         String publicInterfaceName = HostIdToInterfaceInfoMapper.getInstance()
162                 .getInterfaceInfo(hostName, HostIdToInterfaceInfoMapper.InterfaceType.PUBLIC).getInterfaceName();
163
164         final Optional<InterfacesState> opInterfaceState = GbpNetconfTransaction.read(vppDataBroker,
165                 LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class),
166                 GbpNetconfTransaction.RETRY_COUNT);
167
168         if (!opInterfaceState.isPresent()) {
169             LOG.debug("There appear to be no interfaces on node {}.", hostName);
170             return Futures.immediateFailedFuture(new LispNotFoundException("No interfaces found"));
171         }
172
173         String interfaceName = null;
174         for(Interface intf: opInterfaceState.get().getInterface()) {
175             if(!ipAddressPresent(intf)) {
176                 continue;
177             }
178             interfaceName = intf.getName();
179         }
180
181         final Optional<Interfaces> opInterfaces =
182                 GbpNetconfTransaction.read(vppDataBroker, LogicalDatastoreType.CONFIGURATION,
183                         InstanceIdentifier.create(Interfaces.class), GbpNetconfTransaction.RETRY_COUNT);
184
185
186         if (opInterfaces.isPresent()) {
187
188             List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
189                     interfaces.Interface> hostInterfaceFromOpDS = opInterfaces.get().getInterface();
190
191             for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
192                     interfaces.Interface intf : hostInterfaceFromOpDS) {
193                 if (TENANT_INTERFACE.equals(intf.getDescription())
194                         && ipAddressPresent(intf)
195                         && intf.getType().equals(EthernetCsmacd.class)) {
196                     return Futures.immediateFuture(intf.getName());
197                 }
198             }
199
200             for (org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.
201                     interfaces.Interface intf : hostInterfaceFromOpDS) {
202                 if (ipAddressPresent(intf)
203                         && intf.getType().equals(EthernetCsmacd.class)
204                         && !intf.getName().equalsIgnoreCase(publicInterfaceName)) {
205                     return Futures.immediateFuture(intf.getName());
206                 }
207             }
208         }
209
210         if (interfaceName == null) {
211             LOG.warn("No interface with IP found for host {}", hostName);
212             return Futures.immediateFailedFuture(new LispNotFoundException("No interface with Ip address found!"));
213         }
214         return Futures.immediateFuture(interfaceName);
215     }
216
217     private boolean ipAddressPresent(Interface intf) {
218         Interface2 augIntf = intf.getAugmentation(Interface2.class);
219
220         if (augIntf == null) {
221             return false;
222         }
223
224         Ipv4 ipv4 = augIntf.getIpv4();
225
226         if (ipv4 == null) {
227             return false;
228         }
229
230         final List<Address> addresses = ipv4.getAddress();
231
232         if (addresses == null || addresses.isEmpty()) {
233             return false;
234         }
235
236         final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
237         return ip != null;
238     }
239
240     private boolean ipAddressPresent(final org.opendaylight.yang.gen.v1.urn.ietf.
241             params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intf) {
242         final Interface1 augIntf = intf.getAugmentation(Interface1.class);
243
244         if (augIntf == null) {
245             LOG.debug("Cannot get Interface1 augmentation for intf {}", intf);
246             return false;
247         }
248
249         final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4 ipv4 =
250                 augIntf.getIpv4();
251         if (ipv4 == null) {
252             return false;
253         }
254
255         final List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address> addresses =
256                 ipv4.getAddress();
257         if (addresses == null || addresses.isEmpty()) {
258             return false;
259         }
260
261         final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
262         return ip != null;
263     }
264
265     public String constructLocatorSetName(int locatorSetCount) {
266         return LispStateManager.DEFAULT_LOCATOR_SET_NAME_PREFIX + (locatorSetCount + 1);
267     }
268
269     public String constructMappingName(int presentMappingCount) {
270         return LispStateManager.DEFAULT_MAPPINGRECORD_NAME_PREFIX + (presentMappingCount + 1);
271     }
272
273     public String getSubnet(AddressEndpointWithLocation addressEp) {
274         String subnetUuid = null;
275         Containment containment = addressEp.getNetworkContainment().getContainment();
276         if (containment instanceof NetworkDomainContainment) {
277             NetworkDomainContainment networkDomainContainment = (NetworkDomainContainment) containment;
278             subnetUuid = networkDomainContainment.getNetworkDomainId().getValue();
279         }
280         return subnetUuid;
281     }
282
283     public Eid getEid(AddressEndpointWithLocation addressEp, long vni) {
284         String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
285         return LispUtil.toEid(LispUtil.toIpv4(ipPrefix), vni, Ipv4Afi.class);
286     }
287
288     public String getIpWithPrefixOfEndpoint(AddressEndpointWithLocation addressEp) {
289         String ipPrefix = null;
290         if (addressEp.getAddressType().equals(IpPrefixType.class)) {
291             ipPrefix = addressEp.getAddress();
292         } else if (addressEp.getAddressType().equals(MacAddressType.class)) {
293             ParentEndpointChoice parentEndpointChoice = addressEp.getParentEndpointChoice();
294             if (parentEndpointChoice instanceof ParentEndpointCase) {
295                 java.util.Optional<ParentEndpoint> endpointOptional =
296                     ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().stream()
297                         .filter(choice -> choice.getAddressType().equals(IpPrefixType.class))
298                         .filter(choice -> choice.getContextType().equals(L3Context.class)).findFirst();
299                 if (endpointOptional.isPresent()) {
300                     ipPrefix = endpointOptional.get().getAddress();
301                 }
302             }
303         }
304         return Preconditions.checkNotNull(ipPrefix, "No IP address found for Address Endpoint: {}", addressEp);
305     }
306
307     public Ipv4Address getInterfaceIp(AddressEndpointWithLocation addressEp) {
308         String ipPrefix = getIpWithPrefixOfEndpoint(addressEp);
309         return LispUtil.toIpv4(ipPrefix).getIpv4();
310     }
311
312     public Ipv4Prefix getInterfaceIpAsPrefix(AddressEndpointWithLocation addressEp) {
313         if (getInterfaceIp(addressEp).getValue().contains("/")) {
314             return new Ipv4Prefix(getInterfaceIp(addressEp).getValue());
315         }
316         else {
317             return new Ipv4Prefix(getInterfaceIp(addressEp).getValue() + "/32");
318         }
319     }
320
321     public String getFirstLocatorSetName(LispState lispState) {
322         Set<Map.Entry<String, String >> locatorSet = lispState.getLocatorSetEntry();
323         Preconditions.checkNotNull(locatorSet, "No locator set found!");
324         if (!locatorSet.iterator().hasNext()) {
325             return null;
326         }
327
328         return locatorSet.iterator().next().getValue();
329     }
330
331     public Optional<String> getInterfaceName(AddressEndpointWithLocation addedEp) {
332         ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp);
333         String interfacePath = epLoc.getExternalNodeConnector();
334
335         return VppPathMapper.interfacePathToInterfaceName(interfacePath);
336     }
337
338     public Optional<String> getInterfaceName(ExternalLocation externalLocation) {
339         String interfacePath = externalLocation.getExternalNodeConnector();
340         return VppPathMapper.interfacePathToInterfaceName(interfacePath);
341     }
342
343     public HmacKey getDefaultHmacKey() {
344         return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
345     }
346
347     public String getPhysicalAddress(AddressEndpointWithLocation addressEp) {
348         String physicalAddress = null;
349
350         if (addressEp.getAddressType().equals(MacAddressType.class)) {
351             physicalAddress = addressEp.getAddress();
352         } else {
353             List<ChildEndpoint> childEndpoints = addressEp.getChildEndpoint();
354             for (ChildEndpoint childEndpoint : childEndpoints) {
355                 if (childEndpoint.getAddressType().equals(MacAddressType.class)) {
356                     physicalAddress = childEndpoint.getAddress();
357                     break;
358                 }
359             }
360         }
361         return Preconditions.checkNotNull(physicalAddress, "Physical address not found " +
362                 "in address endpoint: " + addressEp);
363     }
364
365     public boolean isMetadataPort(AddressEndpointWithLocation addedEp) {
366         return addedEp.getRelativeLocations() != null && addedEp.getRelativeLocations().getExternalLocation() != null;
367     }
368
369     public Routing getRouting(long vrf) {
370         return new RoutingBuilder().setIpv4VrfId(vrf).build();
371     }
372 }