HONEYCOMB-267 - Reference check for Bridge domain in L2 59/4659/1
authorJan Srnicek <[email protected]>
Thu, 12 Jan 2017 09:05:46 +0000 (10:05 +0100)
committerJan Srnicek <[email protected]>
Thu, 12 Jan 2017 13:30:37 +0000 (14:30 +0100)
Eliminate attempts to remove bridge domain referenced in L2

Change-Id: Ia8ddafe68f87ef9fac0b091fb40d2142ce456cd4
Signed-off-by: Jan Srnicek <[email protected]>
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizer.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/vpp/BridgeDomainCustomizerTest.java

index b4b8626..2962ec5 100644 (file)
@@ -18,29 +18,37 @@ package io.fd.hc2vpp.v3po.vpp;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.stream.Collectors.toList;
 
 import com.google.common.base.Preconditions;
-import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.ReferenceCheck;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDelReply;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Collections;
+import java.util.Optional;
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.L2BaseAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BridgeDomainCustomizer
-        extends FutureJVppCustomizer
-        implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey>, ByteDataTranslator, JvppReplyConsumer {
+public class BridgeDomainCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey>, ByteDataTranslator, JvppReplyConsumer,
+        ReferenceCheck {
 
     private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
 
@@ -110,6 +118,24 @@ public class BridgeDomainCustomizer
             throws WriteFailedException {
         LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
         final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
+
+        final com.google.common.base.Optional<Interfaces> after =
+                ctx.readAfter(InstanceIdentifier.create(Interfaces.class));
+
+        if (after.isPresent()) {
+            checkReferenceExist(id, Optional.ofNullable(after.get().getInterface())
+                    .orElse(Collections.emptyList())
+                    .stream()
+                    .map(iface -> Optional.ofNullable(iface.getAugmentation(VppInterfaceAugmentation.class))
+                            .map(VppInterfaceAugmentation::getL2)
+                            .map(L2BaseAttributes::getInterconnection)
+                            .orElse(null))
+                    .filter(interconnection -> interconnection instanceof BridgeBased)
+                    .map(BridgeBased.class::cast)
+                    .filter(bridgeBased -> bdName.equals(bridgeBased.getBridgeDomain()))
+                    .collect(toList()));
+        }
+
         int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
 
         final BridgeDomainAddDel request = new BridgeDomainAddDel();
index 73106d8..25b398f 100644 (file)
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.base.Optional;
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
@@ -30,8 +31,17 @@ import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.vpp.jvpp.VppInvocationException;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel;
 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDelReply;
+import java.util.Arrays;
 import javax.annotation.Nullable;
 import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.l2.base.attributes.interconnection.BridgeBasedBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.BridgeDomains;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.vpp.bridge.domains.BridgeDomainBuilder;
@@ -168,6 +178,7 @@ public class BridgeDomainCustomizerTest extends WriterCustomizerTest implements
         final String bdName = "bd1";
         final BridgeDomain bd = generateBridgeDomain(bdName);
         defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+        when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.absent());
 
         whenBridgeDomainAddDelThenSuccess();
 
@@ -176,11 +187,61 @@ public class BridgeDomainCustomizerTest extends WriterCustomizerTest implements
         verifyBridgeDomainDeleteWasInvoked(bdId);
     }
 
+    @Test
+    public void testDeleteReferencedBridgeDomain() throws Exception {
+        final int bdId = 1;
+        final String bdName = "bd1";
+        final BridgeDomain bd = generateBridgeDomain(bdName);
+        defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+        when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.of(
+                new InterfacesBuilder().setInterface(Arrays.asList(l2ReferenceToBd("bd1"), l2ReferenceToBd("other-bd")))
+                        .build()
+        ));
+
+        try {
+            customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+        } catch (IllegalStateException e) {
+            verify(api, never()).bridgeDomainAddDel(any(BridgeDomainAddDel.class));
+            return;
+        }
+        fail("IllegalStateException was expected");
+    }
+
+    @Test
+    public void testDeleteReferencedPartialData() throws Exception {
+        final int bdId = 1;
+        final String bdName = "bd1";
+        final BridgeDomain bd = generateBridgeDomain(bdName);
+        defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+        whenBridgeDomainAddDelThenSuccess();
+        when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.of(
+                new InterfacesBuilder().setInterface(Arrays.asList(new InterfaceBuilder()
+                        .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder().build())
+                        .build())).build()
+        ));
+
+        customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
+        verifyBridgeDomainDeleteWasInvoked(bdId);
+    }
+
+    private static Interface l2ReferenceToBd(final String bridgeDomain) {
+        return new InterfaceBuilder()
+                .addAugmentation(VppInterfaceAugmentation.class, new VppInterfaceAugmentationBuilder()
+                        .setL2(new L2Builder()
+                                .setInterconnection(new BridgeBasedBuilder()
+                                        .setBridgeDomain(bridgeDomain)
+                                        .build())
+                                .build())
+                        .build())
+                .build();
+    }
+
     @Test
     public void testDeleteUnknownBridgeDomain() throws Exception {
         final String bdName = "bd1";
         final BridgeDomain bd = generateBridgeDomain("bd1");
         noMappingDefined(mappingContext, bdName, BD_CTX_NAME);
+        when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.absent());
 
         try {
             customizer.deleteCurrentAttributes(bdIdentifierForName(bdName), bd, writeContext);
@@ -197,6 +258,7 @@ public class BridgeDomainCustomizerTest extends WriterCustomizerTest implements
         final String bdName = "bd1";
         final BridgeDomain bd = generateBridgeDomain(bdName);
         defineMapping(mappingContext, bdName, bdId, BD_CTX_NAME);
+        when(writeContext.readAfter(InstanceIdentifier.create(Interfaces.class))).thenReturn(Optional.absent());
 
         whenBridgeDomainAddDelThenFailure();