MRI version bumpup for Aluminium
[netvirt.git] / natservice / impl / src / main / java / org / opendaylight / netvirt / natservice / rpcservice / NatRpcServiceImpl.java
1 /*
2  * Copyright © 2017 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.netvirt.natservice.rpcservice;
9
10 import com.google.common.util.concurrent.Futures;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.ArrayList;
13 import java.util.List;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.genius.mdsalutil.NwConstants;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.netvirt.natservice.internal.NatConstants;
19 import org.opendaylight.netvirt.natservice.internal.NatUtil;
20 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.Ports;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.info.router.ports.ports.InternalToExternalPortMap;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.IpPortMapping;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutput;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsForNetworkAndIpaddressOutputBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterInput;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutput;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnRouterOutputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnInput;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.GetNatTranslationsOnVpnOutputBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.OdlNatRpcService;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMapping;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.dnat.configuration.DnatIpMappingBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNat;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.nat.output.RouterNatBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMapping;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rpc.rev170209.snat.state.SnatIpMappingBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
46 import org.opendaylight.yangtools.yang.common.RpcError;
47 import org.opendaylight.yangtools.yang.common.RpcResult;
48 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
49 import org.opendaylight.yangtools.yang.common.Uint32;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 @Singleton
54 public class NatRpcServiceImpl implements OdlNatRpcService {
55
56     private static final Logger LOG = LoggerFactory.getLogger(NatRpcServiceImpl.class);
57     private final DataBroker dataBroker;
58     private final INeutronVpnManager nvpnManager;
59
60     @Inject
61     public NatRpcServiceImpl(final DataBroker dataBroker, final INeutronVpnManager nvpnManager) {
62         this.dataBroker = dataBroker;
63         this.nvpnManager = nvpnManager;
64     }
65
66     @Override
67     public ListenableFuture<RpcResult<GetNatTranslationsOnVpnOutput>> getNatTranslationsOnVpn(
68             GetNatTranslationsOnVpnInput input) {
69         RpcResultBuilder<GetNatTranslationsOnVpnOutput> rpcResultBuilder = null;
70
71         List<Uuid> routerUuidList = NatUtil.getRouterUuIdsForVpn(dataBroker, input.getVpnUuid());
72         if (routerUuidList.isEmpty()) {
73             String errMsg = String.format("404 Not Found - Invalid external vpn {%s} provided",
74                     input.getVpnUuid().getValue());
75             rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsOnVpnOutput>failed()
76                     .withError(RpcError.ErrorType.APPLICATION, errMsg);
77             return rpcResultBuilder.buildFuture();
78         }
79         List<RouterNat> natRouterList = new ArrayList<>();
80         for (Uuid routerUuid : routerUuidList) {
81             Uint32 routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());
82             if (routerId == NatConstants.INVALID_ID) {
83                 LOG.warn("getNatTranslationsOnVpn : Invalid RouterID found {}", routerId);
84                 continue;
85             }
86             natRouterList.addAll(constructNatInformation(routerUuid, routerId));
87         }
88         GetNatTranslationsOnVpnOutputBuilder output = new GetNatTranslationsOnVpnOutputBuilder()
89                 .setRouterNat(natRouterList);
90         rpcResultBuilder = RpcResultBuilder.success();
91         rpcResultBuilder.withResult(output.build());
92         return Futures.immediateFuture(rpcResultBuilder.build());
93     }
94
95     @Override
96     public ListenableFuture<RpcResult<GetNatTranslationsOnRouterOutput>> getNatTranslationsOnRouter(
97             GetNatTranslationsOnRouterInput input) {
98         RpcResultBuilder<GetNatTranslationsOnRouterOutput> rpcResultBuilder = null;
99         Uint32 routerId = NatUtil.getVpnId(dataBroker, input.getRouterUuid().getValue());
100         if (routerId == NatConstants.INVALID_ID) {
101             String errMsg = String.format("404 Not Found - No Router found with UUID {%s}",
102                     input.getRouterUuid().getValue());
103             rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsOnRouterOutput>failed()
104                     .withError(RpcError.ErrorType.APPLICATION, errMsg);
105             return rpcResultBuilder.buildFuture();
106         }
107
108         List<RouterNat> routerNatList = constructNatInformation(input.getRouterUuid(), routerId);
109
110         GetNatTranslationsOnRouterOutputBuilder output = new GetNatTranslationsOnRouterOutputBuilder()
111                 .setRouterNat(routerNatList);
112         rpcResultBuilder = RpcResultBuilder.success();
113         rpcResultBuilder.withResult(output.build());
114         return rpcResultBuilder.buildFuture();
115     }
116
117     @Override
118     public ListenableFuture<RpcResult<GetNatTranslationsForNetworkAndIpaddressOutput>>
119             getNatTranslationsForNetworkAndIpaddress(GetNatTranslationsForNetworkAndIpaddressInput input) {
120
121         String ipAddress = input.getIpAddress().stringValue();
122         RpcResultBuilder<GetNatTranslationsForNetworkAndIpaddressOutput> rpcResultBuilder = null;
123         GetNatTranslationsForNetworkAndIpaddressOutputBuilder output = null;
124
125         List<Uuid> subnetUuidList = NatUtil.getSubnetIdsFromNetworkId(dataBroker, input.getNetworkUuid());
126         if (subnetUuidList.isEmpty()) {
127             String errMsg = String.format("404 Not Found - Invalid Network UUID {%s} provided as no Subnetworks found",
128                     input.getNetworkUuid().getValue());
129             rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
130                     .withError(RpcError.ErrorType.APPLICATION, errMsg);
131             return rpcResultBuilder.buildFuture();
132         }
133         Subnet subNet = null;
134         Boolean isIpInSubnet = Boolean.FALSE;
135         outerloop:
136         for (Uuid subnetUuid: subnetUuidList) {
137             subNet = nvpnManager.getNeutronSubnet(subnetUuid);
138             for (AllocationPools allocationPool : subNet.nonnullAllocationPools().values()) {
139                 if (NatUtil.isIpInSubnet(ipAddress,
140                         allocationPool.getStart().stringValue(),
141                         allocationPool.getEnd().stringValue())) {
142                     LOG.debug("getNatTranslationsForNetworkAndIpaddress : IP Adderess {} falls within the Subnet {}",
143                             ipAddress, subNet.getUuid().getValue());
144                     isIpInSubnet = Boolean.TRUE;
145                     break outerloop;
146                 }
147             }
148         }
149
150         if (!isIpInSubnet) {
151             String errMsg = String.format("404 Not Found - IP Adress {%s} does not fall within the Subnet IP range"
152                     + " of Network {%s}", ipAddress, input.getNetworkUuid().getValue());
153             rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
154                     .withError(RpcError.ErrorType.APPLICATION, errMsg);
155             return rpcResultBuilder.buildFuture();
156         }
157
158         Subnetmap subnetMap = NatUtil.getSubnetMap(dataBroker, subNet.getUuid());
159         Uint32 routerId = NatUtil.getVpnId(dataBroker, subnetMap.getRouterId().getValue());
160
161         List<Ports> fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, subnetMap.getRouterId());
162         if (fipPorts.isEmpty()) {
163             LOG.warn("getNatTranslationsForNetworkAndIpaddress : No DNAT IP Mapping found for IP {}", ipAddress);
164         } else {
165             for (Ports fipPort : fipPorts) {
166                 for (InternalToExternalPortMap fipMap : fipPort.nonnullInternalToExternalPortMap().values()) {
167                     if (fipMap.getInternalIp().equals(ipAddress)) {
168                         output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder()
169                                     .setExternalIp(fipMap.getExternalIp())
170                                     .setNatTranslation("DNAT");
171                         rpcResultBuilder = RpcResultBuilder.success();
172                         rpcResultBuilder.withResult(output.build());
173                         return rpcResultBuilder.buildFuture();
174                     }
175                 }
176             }
177         }
178
179         IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
180         if (ipPortMapping == null) {
181             LOG.warn("getNatTranslationsForNetworkAndIpaddress : No SNAT IP Mapping found for IP {}", ipAddress);
182         } else {
183             for (IntextIpProtocolType protocolType : ipPortMapping.nonnullIntextIpProtocolType().values()) {
184                 for (IpPortMap ipPortMap : protocolType.nonnullIpPortMap().values()) {
185                     String[] internalIpPort = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP);
186                     if (ipAddress.equals(internalIpPort[0])) {
187
188                         output = new GetNatTranslationsForNetworkAndIpaddressOutputBuilder()
189                                 .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress())
190                                 .setInternalIp(internalIpPort[0])
191                                 .setNatTranslation("SNAT")
192                                 .setInternalPort(internalIpPort[1])
193                                 .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString())
194                                 .setProtocol(protocolType.getProtocol().getName());
195                         rpcResultBuilder = RpcResultBuilder.success();
196                         rpcResultBuilder.withResult(output.build());
197                         return rpcResultBuilder.buildFuture();
198                     }
199                 }
200             }
201         }
202
203         String errMsg = String.format("404 Not Found - No NAT Translation found for IP {%s}", ipAddress);
204         rpcResultBuilder = RpcResultBuilder.<GetNatTranslationsForNetworkAndIpaddressOutput>failed()
205                 .withError(RpcError.ErrorType.APPLICATION, errMsg);
206         return rpcResultBuilder.buildFuture();
207     }
208
209     private List<RouterNat> constructNatInformation(Uuid routerUuid, Uint32 routerId) {
210
211         String neutronRouterName = NatUtil.getNeutronRouterNamebyUuid(dataBroker, routerUuid);
212
213         RouterNatBuilder natRouterBuilder = new RouterNatBuilder();
214         natRouterBuilder.setRouterUuid(routerUuid);
215         natRouterBuilder.setRouterName(neutronRouterName);
216
217         IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
218         if (ipPortMapping == null) {
219             LOG.warn("constructNatInformation : No SNAT IP Mapping found for router-uuid {}", routerUuid.getValue());
220         } else {
221
222             // Capturing SNAT information
223             List<SnatIpMapping> snatIpMapping = new ArrayList<>();
224
225             for (IntextIpProtocolType protocolType : ipPortMapping.nonnullIntextIpProtocolType().values()) {
226                 for (IpPortMap ipPortMap : protocolType.nonnullIpPortMap().values()) {
227                     String[] internalPortMap = ipPortMap.getIpPortInternal().split(NwConstants.MACADDR_SEP);
228                     SnatIpMappingBuilder natIpMappingBuilder = new SnatIpMappingBuilder()
229                             .setInternalIp(internalPortMap[0]).setInternalPort(internalPortMap[1])
230                             .setExternalIp(ipPortMap.getIpPortExternal().getIpAddress())
231                             .setExternalPort(ipPortMap.getIpPortExternal().getPortNum().toString())
232                             .setProtocol(protocolType.getProtocol().getName());
233                     snatIpMapping.add(natIpMappingBuilder.build());
234                 }
235             }
236             natRouterBuilder.setSnatIpMapping(snatIpMapping);
237         }
238
239         // Capturing DNAT information
240         List<DnatIpMapping> dnatIpMapping = new ArrayList<>();
241         List<Ports> fipPorts = NatUtil.getFloatingIpPortsForRouter(dataBroker, routerUuid);
242         if (fipPorts.isEmpty()) {
243             LOG.warn("constructNatInformation : No DNAT IP Mapping found for router-uuid {}", routerUuid.getValue());
244         } else {
245             for (Ports fipPort : fipPorts) {
246                 for (InternalToExternalPortMap fipMap : fipPort.nonnullInternalToExternalPortMap().values()) {
247                     DnatIpMappingBuilder natIpMappingBuilder = new DnatIpMappingBuilder()
248                             .setExternalIp(fipMap.getExternalIp()).setInternalIp(fipMap.getInternalIp());
249                     dnatIpMapping.add(natIpMappingBuilder.build());
250                 }
251             }
252             natRouterBuilder.setDnatIpMapping(dnatIpMapping);
253         }
254
255         List<RouterNat> natRouterList = new ArrayList<>();
256         natRouterList.add(natRouterBuilder.build());
257         return natRouterList;
258     }
259 }