import static org.opendaylight.netvirt.neutronvpn.NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier;
-import com.google.common.base.Optional;
+import edu.umd.cs.findbugs.annotations.CheckReturnValue;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.infrautils.utils.concurrent.KeyedLocks;
+import org.opendaylight.infrautils.utils.concurrent.Executors;
+import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
+import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
+import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.FloatingIpInfo;
import org.slf4j.LoggerFactory;
@Singleton
-public class NeutronFloatingToFixedIpMappingChangeListener extends AsyncDataTreeChangeListenerBase<Floatingip,
- NeutronFloatingToFixedIpMappingChangeListener> {
+public class NeutronFloatingToFixedIpMappingChangeListener extends AbstractAsyncDataTreeChangeListener<Floatingip> {
private static final Logger LOG = LoggerFactory.getLogger(NeutronFloatingToFixedIpMappingChangeListener.class);
- private static long LOCK_WAIT_TIME = 10L;
+ private static final long LOCK_WAIT_TIME = 10L;
private final DataBroker dataBroker;
- private final KeyedLocks<String> routerLock = new KeyedLocks<>();
+ private final NamedLocks<String> routerLock = new NamedLocks<>();
@Inject
public NeutronFloatingToFixedIpMappingChangeListener(final DataBroker dataBroker) {
- super(Floatingip.class, NeutronFloatingToFixedIpMappingChangeListener.class);
+ super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Neutron.class)
+ .child(Floatingips.class).child(Floatingip.class),
+ Executors.newSingleThreadExecutor("NeutronFloatingToFixedIpMappingChangeListener", LOG));
this.dataBroker = dataBroker;
}
- @Override
- @PostConstruct
public void init() {
LOG.info("{} init", getClass().getSimpleName());
- registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
- }
-
- @Override
- protected InstanceIdentifier<Floatingip> getWildCardPath() {
- return InstanceIdentifier.create(Neutron.class).child(Floatingips.class).child(Floatingip.class);
}
@Override
- protected NeutronFloatingToFixedIpMappingChangeListener getDataTreeChangeListener() {
- return NeutronFloatingToFixedIpMappingChangeListener.this;
+ @PreDestroy
+ public void close() {
+ super.close();
+ Executors.shutdownAndAwaitTermination(getExecutorService());
}
@Override
- protected void add(InstanceIdentifier<Floatingip> identifier, Floatingip input) {
+ public void add(InstanceIdentifier<Floatingip> identifier, Floatingip input) {
LOG.trace("Neutron Floating IP created: key: {}, value={}", identifier, input);
IpAddress fixedIp = input.getFixedIpAddress();
String floatingIp = input.getFloatingIpAddress().getIpv4Address().getValue();
}
@Override
- protected void remove(InstanceIdentifier<Floatingip> identifier, Floatingip input) {
+ public void remove(InstanceIdentifier<Floatingip> identifier, Floatingip input) {
LOG.trace("Neutron Floating IP deleted : key: {}, value={}", identifier, input);
IpAddress fixedIp = input.getFixedIpAddress();
if (fixedIp != null) {
// populate the floating to fixed ip map upon association/dissociation from fixed ip
@Override
- protected void update(InstanceIdentifier<Floatingip> identifier, Floatingip original, Floatingip update) {
+ public void update(InstanceIdentifier<Floatingip> identifier, Floatingip original, Floatingip update) {
LOG.trace("Handling FloatingIptoFixedIp mapping : key: {}, original value={}, update value={}", identifier,
original, update);
IpAddress oldFixedIp = original.getFixedIpAddress();
private void addToFloatingIpInfo(String routerName, Uuid extNetworkId, String fixedNeutronPortName, String
fixedIpAddress, String floatingIpAddress, Uuid floatingIpId) {
RouterPortsBuilder routerPortsBuilder;
- boolean isLockAcquired = false;
InstanceIdentifier<RouterPorts> routerPortsIdentifier = InstanceIdentifier.builder(FloatingIpInfo.class)
.child(RouterPorts.class, new RouterPortsKey(routerName)).build();
try {
SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
routerPortsIdentifier);
if (optionalRouterPorts.isPresent()) {
- LOG.debug("Updating routerPorts node {} in floatingIpInfo DS for floating IP () on fixed "
+ LOG.debug("Updating routerPorts node {} in floatingIpInfo DS for floating IP {} on fixed "
+ "neutron port {} : ", routerName, floatingIpAddress, fixedNeutronPortName);
routerPortsBuilder = new RouterPortsBuilder(optionalRouterPorts.get());
} else {
- LOG.debug("Creating new routerPorts node {} in floatingIpInfo DS for floating IP () on fixed "
+ LOG.debug("Creating new routerPorts node {} in floatingIpInfo DS for floating IP {} on fixed "
+ "neutron port {} : ", routerName, floatingIpAddress, fixedNeutronPortName);
routerPortsBuilder =
- new RouterPortsBuilder().setKey(new RouterPortsKey(routerName)).setRouterId(routerName);
+ new RouterPortsBuilder().withKey(new RouterPortsKey(routerName)).setRouterId(routerName);
}
if (extNetworkId != null) {
routerPortsBuilder.setExternalNetworkId(extNetworkId);
}
if (fixedNeutronPortName != null) {
- List<Ports> portsList = routerPortsBuilder.getPorts();
- if (portsList == null) {
- portsList = new ArrayList<>();
- }
+ List<Ports> portsList = routerPortsBuilder.getPorts() != null
+ ? new ArrayList<>(routerPortsBuilder.getPorts()) : new ArrayList<>();
PortsBuilder fixedNeutronPortBuilder = null;
for (Ports neutronPort : portsList) {
if (neutronPort.getPortName().equals(fixedNeutronPortName)) {
}
}
if (fixedNeutronPortBuilder == null) {
- fixedNeutronPortBuilder = new PortsBuilder().setKey(new PortsKey(fixedNeutronPortName))
+ fixedNeutronPortBuilder = new PortsBuilder().withKey(new PortsKey(fixedNeutronPortName))
.setPortName(fixedNeutronPortName);
}
if (fixedIpAddress != null) {
if (intExtPortMapList == null) {
intExtPortMapList = new ArrayList<>();
}
- InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().setKey(new
+ InternalToExternalPortMap intExtPortMap = new InternalToExternalPortMapBuilder().withKey(new
InternalToExternalPortMapKey(fixedIpAddress)).setInternalIp(fixedIpAddress)
- .setExternalIp(floatingIpAddress).setExternalId(floatingIpId).setLabel(null).build();
+ .setExternalIp(floatingIpAddress).setExternalId(floatingIpId).build();
intExtPortMapList.add(intExtPortMap);
fixedNeutronPortBuilder.setInternalToExternalPortMap(intExtPortMapList);
}
portsList.add(fixedNeutronPortBuilder.build());
routerPortsBuilder.setPorts(portsList);
}
- isLockAcquired = routerLock.tryLock(routerName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
- LOG.debug("Creating/Updating routerPorts node {} in floatingIpInfo DS for floating IP () on fixed "
- + "neutron port {} : ", routerName, floatingIpAddress, fixedNeutronPortName);
- MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsIdentifier,
- routerPortsBuilder.build());
- LOG.debug("FloatingIpInfo DS updated for floating IP {} ", floatingIpAddress);
- } catch (ReadFailedException | RuntimeException e) {
- LOG.error("addToFloatingIpInfo failed for floating IP: {} ", floatingIpAddress, e);
- } finally {
- if (isLockAcquired) {
- routerLock.unlock(routerName);
+
+ try (AcquireResult lock = tryRouterLock(routerName)) {
+ if (!lock.wasAcquired()) {
+ // FIXME: why do we even bother with locking if we do not honor it?!
+ logTryLockFailure(routerName);
+ }
+
+ LOG.debug("Creating/Updating routerPorts node {} in floatingIpInfo DS for floating IP {} on fixed "
+ + "neutron port {} : ", routerName, floatingIpAddress, fixedNeutronPortName);
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsIdentifier,
+ routerPortsBuilder.build());
+ LOG.debug("FloatingIpInfo DS updated for floating IP {} ", floatingIpAddress);
}
+ } catch (RuntimeException | ExecutionException | InterruptedException e) {
+ LOG.error("addToFloatingIpInfo failed for floating IP: {} ", floatingIpAddress, e);
}
}
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
private void clearFromFloatingIpInfo(String routerName, String fixedNeutronPortName, String fixedIpAddress) {
- boolean isLockAcquired = false;
InstanceIdentifier.InstanceIdentifierBuilder<RouterPorts> routerPortsIdentifierBuilder = InstanceIdentifier
.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerName));
try {
routerPortsIdentifierBuilder.build());
if (optionalRouterPorts.isPresent()) {
RouterPorts routerPorts = optionalRouterPorts.get();
- List<Ports> portsList = routerPorts.getPorts();
+ List<Ports> portsList = routerPorts.nonnullPorts();
List<InternalToExternalPortMap> intExtPortMap = new ArrayList<>();
for (Ports ports : portsList) {
- if (ports.getPortName().equals(fixedNeutronPortName)) {
- intExtPortMap = ports.getInternalToExternalPortMap();
+ if (Objects.equals(ports.getPortName(), fixedNeutronPortName)) {
+ intExtPortMap = ports.nonnullInternalToExternalPortMap();
break;
}
}
if (intExtPortMap.size() == 1) {
removeRouterPortsOrPortsNode(routerName, routerPortsIdentifierBuilder, portsList,
- fixedNeutronPortName, isLockAcquired);
+ fixedNeutronPortName);
} else {
for (InternalToExternalPortMap intToExtMap : intExtPortMap) {
- if (intToExtMap.getInternalIp().equals(fixedIpAddress)) {
+ if (Objects.equals(intToExtMap.getInternalIp(), fixedIpAddress)) {
InstanceIdentifier<InternalToExternalPortMap> intExtPortMapIdentifier =
routerPortsIdentifierBuilder.child(Ports
.class, new PortsKey(fixedNeutronPortName)).child(InternalToExternalPortMap.class,
new InternalToExternalPortMapKey(fixedIpAddress)).build();
- try {
+ try (AcquireResult lock = tryRouterLock(fixedIpAddress)) {
+ if (!lock.wasAcquired()) {
+ // FIXME: why do we even bother with locking if we do not honor it?!
+ logTryLockFailure(fixedIpAddress);
+ }
+
// remove particular internal-to-external-port-map
- isLockAcquired = routerLock.tryLock(fixedIpAddress, LOCK_WAIT_TIME, TimeUnit.SECONDS);
LOG.debug("removing particular internal-to-external-port-map {}", intExtPortMap);
- MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ try {
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
intExtPortMapIdentifier);
- } catch (Exception e) {
- LOG.error("Failure in deletion of internal-to-external-port-map {}", intExtPortMap, e);
- } finally {
- if (isLockAcquired) {
- routerLock.unlock(fixedIpAddress);
+ } catch (Exception e) {
+ LOG.error("Failure in deletion of internal-to-external-port-map {}", intExtPortMap,
+ e);
}
}
}
} else {
LOG.warn("routerPorts for router {} - fixedIp {} not found", routerName, fixedIpAddress);
}
- } catch (RuntimeException | ReadFailedException e) {
+ } catch (RuntimeException | ExecutionException | InterruptedException e) {
LOG.error("Failed to delete internal-to-external-port-map from FloatingIpInfo DS for fixed Ip {}",
fixedIpAddress, e);
}
}
protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
- boolean isLockAcquired = false;
InstanceIdentifier.InstanceIdentifierBuilder<FloatingIpInfo> floatingIpInfoIdentifierBuilder =
InstanceIdentifier.builder(FloatingIpInfo.class);
try {
List<Ports> portsList = routerPorts.getPorts();
if (portsList != null && !portsList.isEmpty()) {
for (Ports ports : portsList) {
- if (ports.getPortName().equals(fixedNeutronPortName)) {
+ if (Objects.equals(ports.getPortName(), fixedNeutronPortName)) {
String routerName = routerPorts.getRouterId();
InstanceIdentifier.InstanceIdentifierBuilder<RouterPorts>
routerPortsIdentifierBuilder = floatingIpInfoIdentifierBuilder
.child(RouterPorts.class, new RouterPortsKey(routerName));
removeRouterPortsOrPortsNode(routerName, routerPortsIdentifierBuilder, portsList,
- fixedNeutronPortName, isLockAcquired);
+ fixedNeutronPortName);
LOG.debug("Deletion from FloatingIpInfo DS successful for fixedIP neutron port {} ",
fixedNeutronPortName);
break;
LOG.debug("FloatingIPInfo DS empty. Hence, no router present containing fixed to floating IP "
+ "association(s)");
}
- } catch (ReadFailedException e) {
+ } catch (ExecutionException | InterruptedException e) {
LOG.error("Failed to dissociate fixedIP from FloatingIpInfo DS for neutron port {}",
fixedNeutronPortName, e);
}
}
- // TODO Clean up the exception handling
- @SuppressWarnings("checkstyle:IllegalCatch")
- private void removeRouterPortsOrPortsNode(String routerName, InstanceIdentifier
- .InstanceIdentifierBuilder<RouterPorts> routerPortsIdentifierBuilder, List<Ports> portsList,
- String fixedNeutronPortName, boolean isLockAcquired) {
- String lockName = null;
- try {
- if (portsList.size() == 1) {
- // remove entire routerPorts node
- lockName = routerName;
- isLockAcquired = routerLock.tryLock(lockName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+ private void removeRouterPortsOrPortsNode(String routerName,
+ InstanceIdentifier.InstanceIdentifierBuilder<RouterPorts> routerPortsIdentifierBuilder,
+ List<Ports> portsList, String fixedNeutronPortName) {
+ if (portsList.size() == 1) {
+ // remove entire routerPorts node
+ try (AcquireResult lock = tryRouterLock(routerName)) {
+ if (!lock.wasAcquired()) {
+ // FIXME: why do we even bother with locking if we do not honor it?!
+ logTryLockFailure(routerName);
+ }
+
LOG.debug("removing routerPorts node: {} ", routerName);
MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsIdentifierBuilder
- .build());
- } else {
- // remove entire ports node under this routerPorts node
- lockName = fixedNeutronPortName;
- isLockAcquired = routerLock.tryLock(lockName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
- LOG.debug("removing ports node {} under routerPorts node {}", fixedNeutronPortName, routerName);
- InstanceIdentifier.InstanceIdentifierBuilder<Ports> portsIdentifierBuilder =
- routerPortsIdentifierBuilder.child(Ports.class, new PortsKey(fixedNeutronPortName));
- MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, portsIdentifierBuilder.build());
+ .build());
}
- } catch (Exception e) {
- LOG.error("Failure in deletion of routerPorts node {}", routerName, e);
- } finally {
- if (isLockAcquired) {
- routerLock.unlock(lockName);
+ } else {
+ // remove entire ports node under this routerPorts node
+ try (AcquireResult lock = tryRouterLock(fixedNeutronPortName)) {
+ if (!lock.wasAcquired()) {
+ // FIXME: why do we even bother with locking if we do not honor it?!
+ logTryLockFailure(fixedNeutronPortName);
+ }
+
+ LOG.debug("removing ports node {} under routerPorts node {}", fixedNeutronPortName, routerName);
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
+ routerPortsIdentifierBuilder.child(Ports.class, new PortsKey(fixedNeutronPortName)).build());
}
}
}
+ "IP Port Info Config DS failed", floatingIpId.getValue(), e);
}
}
+
+ @CheckReturnValue
+ private AcquireResult tryRouterLock(final String lockName) {
+ return routerLock.tryAcquire(lockName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
+ }
+
+ private static void logTryLockFailure(String lockName) {
+ LOG.warn("Lock for {} was not acquired, continuing anyway", lockName, new Throwable());
+ }
}