2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.iface;
11 import javax.annotation.Nonnull;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
15 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
16 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand;
17 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.VhostUserCommand.VhostUserCommandBuilder;
18 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent;
19 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
20 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General.Operations;
21 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint.InterfaceTypeChoice;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.vpp.endpoint._interface.type.choice.VhostUserCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import com.google.common.base.Optional;
31 import com.google.common.base.Preconditions;
32 import com.google.common.base.Strings;
33 import com.google.common.eventbus.Subscribe;
34 import com.google.common.util.concurrent.FutureCallback;
35 import com.google.common.util.concurrent.Futures;
37 public class InterfaceManager implements AutoCloseable {
39 private static final Logger LOG = LoggerFactory.getLogger(InterfaceManager.class);
40 private final MountedDataBrokerProvider mountDataProvider;
41 private final VppEndpointLocationProvider vppEndpointLocationProvider;
43 public InterfaceManager(@Nonnull MountedDataBrokerProvider mountDataProvider, @Nonnull DataBroker dataProvider) {
44 this.mountDataProvider = Preconditions.checkNotNull(mountDataProvider);
45 this.vppEndpointLocationProvider = new VppEndpointLocationProvider(dataProvider);
49 public void vppEndpointChanged(VppEndpointConfEvent event) {
50 switch (event.getDtoModificationType()) {
52 vppEndpointCreated(event.getAfter().get());
55 vppEndpointDeleted(event.getBefore().get());
56 vppEndpointCreated(event.getAfter().get());
59 vppEndpointDeleted(event.getBefore().get());
64 private void vppEndpointCreated(VppEndpoint vppEndpoint) {
65 Optional<ConfigCommand> potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
66 if (!potentialIfaceCommand.isPresent()) {
69 ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
70 InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
71 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
72 if (!potentialVppDataProvider.isPresent()) {
73 LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
76 DataBroker vppDataBroker = potentialVppDataProvider.get();
77 createIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
80 private void createIfaceOnVpp(ConfigCommand createIfaceWithoutBdCommand, DataBroker vppDataBroker,
81 VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
82 ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
83 createIfaceWithoutBdCommand.execute(rwTx);
84 Futures.addCallback(rwTx.submit(), new FutureCallback<Void>() {
87 public void onSuccess(Void result) {
88 LOG.debug("Create interface on VPP command was successful:\nVPP: {}\nCommand: {}", vppNodeIid,
89 createIfaceWithoutBdCommand);
90 vppEndpointLocationProvider.createLocationForVppEndpoint(vppEndpoint);
94 public void onFailure(Throwable t) {
95 LOG.error("Create interface on VPP command was NOT successful:\nVPP: {}\nCommand: {}", vppNodeIid,
96 createIfaceWithoutBdCommand, t);
101 private void vppEndpointDeleted(VppEndpoint vppEndpoint) {
102 Optional<ConfigCommand> potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
103 if (!potentialIfaceCommand.isPresent()) {
106 ConfigCommand ifaceWithoutBdCommand = potentialIfaceCommand.get();
107 InstanceIdentifier<?> vppNodeIid = vppEndpoint.getVppNodePath();
108 Optional<DataBroker> potentialVppDataProvider = mountDataProvider.getDataBrokerForMountPoint(vppNodeIid);
109 if (!potentialVppDataProvider.isPresent()) {
110 LOG.debug("Cannot get data broker for mount point {}", vppNodeIid);
113 DataBroker vppDataBroker = potentialVppDataProvider.get();
114 deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
117 private void deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand, DataBroker vppDataBroker,
118 VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
119 ReadWriteTransaction rwTx = vppDataBroker.newReadWriteTransaction();
120 deleteIfaceWithoutBdCommand.execute(rwTx);
121 Futures.addCallback(rwTx.submit(), new FutureCallback<Void>() {
124 public void onSuccess(Void result) {
125 LOG.debug("Delete interface on VPP command was successful:\nVPP: {}\nCommand: {}", vppNodeIid,
126 deleteIfaceWithoutBdCommand);
127 vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint);
131 public void onFailure(Throwable t) {
132 LOG.error("Delete interface on VPP command was NOT successful:\nVPP: {}\nCommand: {}", vppNodeIid,
133 deleteIfaceWithoutBdCommand, t);
139 public void vppNodeChanged(NodeOperEvent event) {
140 switch (event.getDtoModificationType()) {
142 if (event.isAfterConnected()) {
143 // TODO read VppEndpoints or cache them during vppEndpointChanged()
147 if (!event.isBeforeConnected() && event.isAfterConnected()) {
148 // TODO reconciliation - diff between disconnected snapshot and current snapshot
152 if (event.isBeforeConnected()) {
153 // TODO we could do snapshot of VppEndpoints
154 // which can be used for reconciliation
160 private static Optional<ConfigCommand> createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
161 @Nonnull Operations operations) {
162 if (!hasNodeAndInterface(vppEp)) {
163 LOG.debug("Interface command is not created for {}", vppEp);
164 return Optional.absent();
166 VhostUserCommandBuilder builder = VhostUserCommand.builder();
167 builder.setName(vppEp.getVppInterfaceName());
168 InterfaceTypeChoice interfaceTypeChoice = vppEp.getInterfaceTypeChoice();
169 if (interfaceTypeChoice instanceof VhostUserCase) {
170 VhostUserCase vhostUserIface = (VhostUserCase) interfaceTypeChoice;
171 String socket = vhostUserIface.getSocket();
172 if (Strings.isNullOrEmpty(socket)) {
173 LOG.debug("Vhost user interface command is not created because socket is missing. {}", vppEp);
174 return Optional.absent();
176 builder.setSocket(socket);
177 builder.setRole(VhostUserRole.Client);
179 VhostUserCommand vhostUserCommand =
180 builder.setOperation(operations).setDescription(vppEp.getDescription()).build();
181 return Optional.of(vhostUserCommand);
184 private static boolean hasNodeAndInterface(VppEndpoint vppEp) {
185 if (vppEp.getVppNodePath() == null) {
186 LOG.trace("vpp-node is missing. {}", vppEp);
189 if (Strings.isNullOrEmpty(vppEp.getVppInterfaceName())) {
190 LOG.trace("vpp-interface-name is missing. {}", vppEp);
197 public void close() throws Exception {
198 vppEndpointLocationProvider.close();