Cleanup CRLF consistency
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / adapter / VppRpcServiceImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.adapter;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.Future;
14 import java.util.stream.Collectors;
15
16 import javax.annotation.Nonnull;
17
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.TapPortCommand;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand.VhostUserCommandBuilder;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
29 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
30 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.AddInterfaceToBridgeDomainInput;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateInterfaceOnNodeInput;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CreateVirtualBridgeDomainOnNodesInput;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DelInterfaceFromBridgeDomainInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteInterfaceFromNodeInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.DeleteVirtualBridgeDomainFromNodesInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.CloneVirtualBridgeDomainOnNodesInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.bridge.domain.attributes.tunnel.type.Vlan;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_adapter.rev161201.bridge.domain.attributes.tunnel.type.Vxlan;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes.InterfaceTypeChoice;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.TapCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCase;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VhostUserRole;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vlan.rev160429.network.topology.topology.tunnel.parameters.VlanNetworkParameters;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.network.topology.topology.tunnel.parameters.VxlanTunnelParameters;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
59 import org.opendaylight.yangtools.yang.common.RpcResult;
60 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.google.common.base.Optional;
65 import com.google.common.util.concurrent.AsyncFunction;
66 import com.google.common.util.concurrent.CheckedFuture;
67 import com.google.common.util.concurrent.Futures;
68 import com.google.common.util.concurrent.ListenableFuture;
69
70 public class VppRpcServiceImpl {
71
72     private static final Logger LOG = LoggerFactory.getLogger(VppRpcServiceImpl.class);
73
74     private final DataBroker dataBroker;
75     private final BridgeDomainManager bridgeDomainManager;
76     private final InterfaceManager interfaceManager;
77     private final MountedDataBrokerProvider mountDataProvider;
78
79     public VppRpcServiceImpl(@Nonnull DataBroker dataBroker, @Nonnull MountedDataBrokerProvider mountDataProvider,
80             BridgeDomainManager bridgeDomainManager, InterfaceManager interfaceManager) {
81         this.dataBroker = dataBroker;
82         this.bridgeDomainManager = bridgeDomainManager;
83         this.interfaceManager = interfaceManager;
84         this.mountDataProvider = mountDataProvider;
85     }
86
87     public Future<RpcResult<Void>> createVirtualBridgeDomain(CreateVirtualBridgeDomainOnNodesInput input) {
88         LOG.info("Processing a remote call for creating bridge domain {}", input.getId());
89         if (input.getTunnelType() == null) {
90             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
91                 .withError(ErrorType.RPC,
92                         "Failed to create bridge domain" + input.getId() + "." + "Tunnel type not specified")
93                 .build());
94         }
95         List<ListenableFuture<Void>> futures = new ArrayList<>();
96         List<NodeId> nodeIds = input.getPhysicalLocationRef()
97             .stream()
98             .map(locationRef -> locationRef.getNodeId())
99             .collect(Collectors.toList());
100         LOG.trace("Corresponding nodes for bridge-domain {}", input.getPhysicalLocationRef());
101         if (input.getTunnelType() instanceof Vxlan) {
102             LOG.trace("Detected VXLAN type for bridge domain {}", input.getId());
103             Vxlan tunnelType = (Vxlan) input.getTunnelType();
104             VxlanVni vxlanVni = new VxlanVni(tunnelType.getVni().getValue());
105             nodeIds.forEach(nodeId -> {
106                 futures.add(bridgeDomainManager.createVxlanBridgeDomainOnVppNode(input.getId(), vxlanVni, nodeId));
107             });
108         } else if (input.getTunnelType() instanceof Vlan) {
109             LOG.trace("Detected VLAN type for bridge domain {}", input.getId());
110             Vlan vlan = (Vlan) input.getTunnelType();
111             VlanId vlanId = new VlanId(vlan.getVlanId().getValue());
112             nodeIds.forEach(nodeId -> {
113                 futures.add(bridgeDomainManager.createVlanBridgeDomainOnVppNode(input.getId(), vlanId, nodeId));
114             });
115         }
116         return Futures.transform(Futures.allAsList(futures), voidsToRpcResult());
117     }
118
119     public Future<RpcResult<Void>> deleteVirtualBridgeDomain(DeleteVirtualBridgeDomainFromNodesInput input) {
120         LOG.info("Processing a remote call for removing bridge domain {}", input.getBridgeDomainId());
121         List<ListenableFuture<Void>> futures = new ArrayList<>();
122         input.getBridgeDomainNode().forEach(nodeId -> {
123             futures.add(bridgeDomainManager.removeBridgeDomainFromVppNode(input.getBridgeDomainId(), nodeId));
124         });
125         return Futures.transform(Futures.allAsList(futures), voidsToRpcResult());
126     }
127
128     public ListenableFuture<RpcResult<Void>> cloneVirtualBridgeDomainOnNode(CloneVirtualBridgeDomainOnNodesInput input) {
129         LOG.info("Processing a remote call for clonning  bridge domain {}", input.getBridgeDomainId());
130         List<ListenableFuture<Void>> futures = new ArrayList<>();
131         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
132         InstanceIdentifier<Topology> topologyIid = VppIidFactory.getTopologyIid(new TopologyKey(new TopologyId(
133                 input.getBridgeDomainId())));
134         return Futures.transform(rTx.read(LogicalDatastoreType.CONFIGURATION, topologyIid),
135                 new AsyncFunction<Optional<Topology>, RpcResult<Void>>() {
136
137                     @Override
138                     public ListenableFuture<RpcResult<Void>> apply(Optional<Topology> optTopology) throws Exception {
139                         if (!optTopology.isPresent()) {
140
141                             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
142                                 .withError(
143                                         ErrorType.RPC,
144                                         "Failed to clone bridge domain. Bridge domain " + input.getBridgeDomainId()
145                                                 + " does not exist.")
146                                 .build());
147                         }
148                         TopologyVbridgeAugment vBridgeAug = optTopology.get().getAugmentation(TopologyVbridgeAugment.class);
149                         if (vBridgeAug == null) {
150                             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
151                                 .withError(
152                                         ErrorType.RPC,
153                                         "Failed to clone bridge domain. Topology " + input.getBridgeDomainId()
154                                                 + " is not bridge domain type.")
155                                 .build());
156                         }
157                         if (vBridgeAug.getTunnelParameters() instanceof VxlanTunnelParameters) {
158                             LOG.debug("Clonning VXLAN type bridge domain {} on nodes {}", input.getBridgeDomainId(),
159                                     input.getBridgeDomainNode());
160                             VxlanTunnelParameters vxlanTunnelParams = (VxlanTunnelParameters) vBridgeAug.getTunnelParameters();
161                             VxlanVni vni = vxlanTunnelParams.getVni();
162                             input.getBridgeDomainNode().forEach(
163                                     nodeId -> {
164                                         futures.add(bridgeDomainManager.createVxlanBridgeDomainOnVppNode(
165                                                 input.getBridgeDomainId(), vni, nodeId));
166                                     });
167                         } else if (vBridgeAug.getTunnelParameters() instanceof VlanNetworkParameters) {
168                             LOG.debug("Clonning VLAN type bridge domain {} on nodes {}", input.getBridgeDomainId(),
169                                     input.getBridgeDomainNode());
170                             VlanNetworkParameters vlanTunnelParams = (VlanNetworkParameters) vBridgeAug.getTunnelParameters();
171                             VlanId vlanId = vlanTunnelParams.getVlanId();
172                             input.getBridgeDomainNode().forEach(
173                                     nodeId -> {
174                                         futures.add(bridgeDomainManager.createVlanBridgeDomainOnVppNode(
175                                                 input.getBridgeDomainId(), vlanId, nodeId));
176                                     });
177                         }
178                         return Futures.transform(Futures.allAsList(futures), voidsToRpcResult());
179                     }
180                 });
181     }
182
183     public ListenableFuture<RpcResult<Void>> createInterfaceOnNodes(CreateInterfaceOnNodeInput input) {
184         InterfaceTypeChoice interfaceType = input.getInterfaceTypeChoice();
185         ConfigCommand ifaceCommand = null;
186         if (interfaceType instanceof VhostUserCase) {
187             VhostUserCommandBuilder vhostBuilder = VhostUserCommand.builder();
188             vhostBuilder.setName(input.getVppInterfaceName());
189             VhostUserCase vhostCase = (VhostUserCase) input.getInterfaceTypeChoice();
190             vhostBuilder.setSocket(vhostCase.getSocket());
191             vhostBuilder.setRole(VhostUserRole.Client);
192             vhostBuilder.setDescription(input.getDescription());
193             vhostBuilder.setOperation(Operations.PUT);
194             ifaceCommand = vhostBuilder.build();
195         }
196         if (interfaceType instanceof TapCase) {
197             TapPortCommand.TapPortCommandBuilder tapBuilder = TapPortCommand.builder();
198             TapCase tapIface = (TapCase) input.getInterfaceTypeChoice();
199             tapBuilder.setTapName(tapIface.getName());
200             tapBuilder.setPhysAddress(tapIface.getPhysicalAddress());
201             tapBuilder.setInterfaceName(input.getVppInterfaceName());
202             tapBuilder.setDescription(input.getDescription());
203             tapBuilder.setOperation(Operations.PUT);
204             ifaceCommand = tapBuilder.build();
205         }
206         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(input.getVppNodeId());
207         Optional<DataBroker> optDataBroker = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
208         if (!optDataBroker.isPresent()) {
209             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
210                 .withError(ErrorType.RPC, "Cannot find data broker for mount point " + vppNodeIid)
211                 .build());
212         }
213         return Futures.transform(interfaceManager.createInterfaceOnVpp(ifaceCommand, optDataBroker.get()),
214                 voidToRpcResult());
215     }
216
217     public ListenableFuture<RpcResult<Void>> deleteInterfaceFromNodes(DeleteInterfaceFromNodeInput input) {
218         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(input.getVppNodeId());
219         return Futures.transform(readInterface(vppNodeIid, input.getVppInterfaceName()),
220                 new AsyncFunction<Optional<Interface>, RpcResult<Void>>() {
221
222                     @Override
223                     public ListenableFuture<RpcResult<Void>> apply(Optional<Interface> optIface) throws Exception {
224                         InterfaceKey iKey = new InterfaceKey(input.getVppInterfaceName());
225                         if (!optIface.isPresent()) {
226                             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
227                                 .withError(
228                                         ErrorType.RPC,
229                                         "Cannot delete interface " + iKey + " on node " + vppNodeIid
230                                                 + ". Not found or already deleted.")
231                                 .build());
232                         }
233                         Optional<DataBroker> dataBroker = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
234                         WriteTransaction wTx = dataBroker.get().newWriteOnlyTransaction();
235                         wTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(iKey));
236                         return Futures.transform(wTx.submit(), voidToRpcResult());
237                     }
238                 });
239     }
240
241     public ListenableFuture<RpcResult<Void>> addInterfaceToBridgeDomain(AddInterfaceToBridgeDomainInput input) {
242         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(input.getVppNodeId());
243         return Futures.transform(readInterface(vppNodeIid, input.getVppInterfaceName()),
244                 new AsyncFunction<Optional<Interface>, RpcResult<Void>>() {
245
246                     @Override
247                     public ListenableFuture<RpcResult<Void>> apply(Optional<Interface> optIface) throws Exception {
248                         InterfaceKey iKey = new InterfaceKey(input.getVppInterfaceName());
249                         if (!optIface.isPresent()) {
250                             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
251                                 .withError(
252                                         ErrorType.RPC,
253                                         "Cannot add interface " + iKey + " to bridge domain on node "
254                                                 + vppNodeIid + ". Not found or deleted.")
255                                 .build());
256                         }
257                         Optional<DataBroker> dataBroker = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
258                         return Futures.transform(interfaceManager.configureInterface(dataBroker.get(), iKey,
259                                 input.getBridgeDomainId(), null), voidToRpcResult());
260                     }
261                 });
262     }
263
264     public ListenableFuture<RpcResult<Void>> delInterfaceFromBridgeDomain(DelInterfaceFromBridgeDomainInput input) {
265         InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(input.getVppNodeId());
266         return Futures.transform(readInterface(vppNodeIid, input.getVppInterfaceName()),
267                 new AsyncFunction<Optional<Interface>, RpcResult<Void>>() {
268
269                     @Override
270                     public ListenableFuture<RpcResult<Void>> apply(Optional<Interface> optIface) throws Exception {
271                         if (!optIface.isPresent()) {
272                             return Futures.immediateFuture(RpcResultBuilder.<Void>failed()
273                                 .withError(
274                                         ErrorType.RPC,
275                                         "Cannot remove interface " + input.getVppInterfaceName()
276                                                 + " from bridge domain on node " + vppNodeIid
277                                                 + ". Not found or deleted.")
278                                 .build());
279                         }
280                         Optional<DataBroker> dataBroker = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
281                         return Futures.transform(interfaceManager.removeInterfaceFromBridgeDomain(dataBroker.get(),
282                                 optIface.get().getKey()), voidToRpcResult());
283                     }
284                 });
285     }
286
287     private CheckedFuture<Optional<Interface>, ReadFailedException> readInterface(InstanceIdentifier<?> nodeIid,
288             String interfaceName) {
289         Optional<DataBroker> optDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);
290         if (!optDataBroker.isPresent()) {
291             LOG.error("Cannot find data broker for node {}", nodeIid);
292             return Futures.immediateCheckedFuture(Optional.absent());
293         }
294         ReadOnlyTransaction rwTx = optDataBroker.get().newReadOnlyTransaction();
295         InterfaceKey iKey = new InterfaceKey(interfaceName);
296         InstanceIdentifier<Interface> interfaceIID = VppIidFactory.getInterfaceIID(iKey);
297         CheckedFuture<Optional<Interface>, ReadFailedException> readInterface = rwTx.read(
298                 LogicalDatastoreType.CONFIGURATION, interfaceIID);
299         rwTx.close();
300         return readInterface;
301     }
302
303     private AsyncFunction<Void, RpcResult<Void>> voidToRpcResult() {
304         return new AsyncFunction<Void, RpcResult<Void>>() {
305
306             @Override
307             public ListenableFuture<RpcResult<Void>> apply(Void input) throws Exception {
308                 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
309             }
310         };
311     }
312
313     private AsyncFunction<List<Void>, RpcResult<Void>> voidsToRpcResult() {
314         return new AsyncFunction<List<Void>, RpcResult<Void>>() {
315
316             @Override
317             public ListenableFuture<RpcResult<Void>> apply(List<Void> input) throws Exception {
318                 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
319             }
320         };
321     }
322 }