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