summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Srnicek <jsrnicek@cisco.com>2017-01-12 09:59:30 +0100
committerJan Srnicek <jsrnicek@cisco.com>2017-01-12 14:30:19 +0100
commit4f8dbff5c3a94f5ea8db32a3601fc704b95250f7 (patch)
tree0a2e98be55b3cc8a38667b09a2326e8fc07e21ab
parente0b4359b39acfe8a583089117a0c2485b85ff7e4 (diff)
HONEYCOMB-296 - Reference checking in Locator set
Reference must be checked while removing to prevent dead references Change-Id: I37cb426f73a3fa64d4e6795062d8d7affc0cbb2b Signed-off-by: Jan Srnicek <jsrnicek@cisco.com>
-rwxr-xr-xlisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizer.java55
-rwxr-xr-xlisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizerTest.java89
-rw-r--r--vpp-common/vpp-translate-utils/src/main/java/io/fd/hc2vpp/common/translate/util/ReferenceCheck.java40
3 files changed, 178 insertions, 6 deletions
diff --git a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizer.java b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizer.java
index b125d4038..8c41372e1 100755
--- a/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizer.java
+++ b/lisp/lisp2vpp/src/main/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizer.java
@@ -20,17 +20,29 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;
-import io.fd.hc2vpp.lisp.translate.read.trait.LocatorSetReader;
-import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import com.google.common.base.Optional;
import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.common.translate.util.ReferenceCheck;
+import io.fd.hc2vpp.lisp.translate.read.trait.LocatorSetReader;
+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.LispAddDelLocatorSet;
import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.DpSubtableGrouping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.Lisp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.dp.subtable.grouping.LocalMappings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.dp.subtable.grouping.local.mappings.LocalMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.EidTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.eid.table.VniTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.lisp.feature.data.grouping.LispFeatureData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.locator.sets.LocatorSet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.locator.sets.LocatorSetKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.locator.sets.locator.set.Interface;
@@ -44,7 +56,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
*/
public class LocatorSetCustomizer extends FutureJVppCustomizer
implements ListWriterCustomizer<LocatorSet, LocatorSetKey>, ByteDataTranslator,
- LocatorSetReader {
+ LocatorSetReader, ReferenceCheck {
private final NamingContext locatorSetContext;
@@ -85,11 +97,48 @@ public class LocatorSetCustomizer extends FutureJVppCustomizer
@Nonnull LocatorSet dataBefore,
@Nonnull WriteContext writeContext) throws WriteFailedException {
final String locatorSetName = dataBefore.getName();
+
+ final Optional<EidTable> eidTableData = writeContext.readAfter(InstanceIdentifier.create(Lisp.class)
+ .child(LispFeatureData.class)
+ .child(EidTable.class));
+
+ if (eidTableData.isPresent()) {
+ // due to non-functional LeafRefValidation, it must be checked like this
+ final List<VniTable> vniTables =
+ Optional.fromNullable(eidTableData.get().getVniTable()).or(Collections.emptyList());
+ checkReferenceExist(id, vrfReferences(vniTables, locatorSetName));
+ checkReferenceExist(id, bdReferences(vniTables, locatorSetName));
+ }
+
addDelLocatorSetAndReply(false, dataBefore.getName(), id);
//removes mapping after successful delete
locatorSetContext.removeName(locatorSetName, writeContext.getMappingContext());
}
+ private Collection<LocalMapping> bdReferences(final List<VniTable> vniTables,
+ final String locatorSetName) {
+ return vniTables.stream()
+ .map(vniTable -> java.util.Optional.ofNullable(vniTable.getBridgeDomainSubtable())
+ .map(DpSubtableGrouping::getLocalMappings)
+ .map(LocalMappings::getLocalMapping)
+ .orElse(Collections.emptyList()))
+ .flatMap(Collection::stream)
+ .filter(localMapping -> locatorSetName.equals(localMapping.getLocatorSet()))
+ .collect(Collectors.toSet());
+ }
+
+ private static Collection<LocalMapping> vrfReferences(final List<VniTable> vniTables,
+ final String locatorSetName) {
+ return vniTables.stream()
+ .map(vniTable -> java.util.Optional.ofNullable(vniTable.getVrfSubtable())
+ .map(DpSubtableGrouping::getLocalMappings)
+ .map(LocalMappings::getLocalMapping)
+ .orElse(Collections.emptyList()))
+ .flatMap(Collection::stream)
+ .filter(localMapping -> locatorSetName.equals(localMapping.getLocatorSet()))
+ .collect(Collectors.toSet());
+ }
+
private int addDelLocatorSetAndReply(final boolean add, final String name, final InstanceIdentifier<LocatorSet> id)
throws WriteFailedException {
diff --git a/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizerTest.java b/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizerTest.java
index b29e1a018..734dddd6c 100755
--- a/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizerTest.java
+++ b/lisp/lisp2vpp/src/test/java/io/fd/hc2vpp/lisp/translate/write/LocatorSetCustomizerTest.java
@@ -40,6 +40,14 @@ import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.Lisp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.dp.subtable.grouping.LocalMappingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.dp.subtable.grouping.local.mappings.LocalMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.EidTable;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.EidTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.eid.table.VniTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.eid.table.grouping.eid.table.vni.table.VrfSubtableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.lisp.feature.data.grouping.LispFeatureData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.LocatorSets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.locator.sets.LocatorSet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev161214.locator.sets.grouping.locator.sets.LocatorSetBuilder;
@@ -49,6 +57,15 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
public class LocatorSetCustomizerTest extends WriterCustomizerTest {
+ private static final InstanceIdentifier<EidTable>
+ EID_TABLE_ID = InstanceIdentifier.create(Lisp.class)
+ .child(LispFeatureData.class)
+ .child(EidTable.class);
+
+ private static final LocatorSet LOCATOR_SET_TO_DELETE = new LocatorSetBuilder()
+ .setName("Locator")
+ .build();
+
private LocatorSetCustomizer customizer;
@Override
@@ -126,10 +143,25 @@ public class LocatorSetCustomizerTest extends WriterCustomizerTest {
@Test
public void testDeleteCurrentAttributes() throws InterruptedException, ExecutionException, WriteFailedException {
- LocatorSet locatorSet = new LocatorSetBuilder()
- .setName("Locator")
- .build();
+ when(writeContext.readAfter(EID_TABLE_ID)).thenReturn(Optional.absent());
+ verifySuccessfullDelete(LOCATOR_SET_TO_DELETE);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesWithoutLocalMappingContainer()
+ throws InterruptedException, ExecutionException, WriteFailedException {
+ when(writeContext.readAfter(EID_TABLE_ID)).thenReturn(eidTableDataWithoutLocalMappingContainer());
+ verifySuccessfullDelete(LOCATOR_SET_TO_DELETE);
+ }
+
+ @Test
+ public void testDeleteCurrentAttributesWithoutLocalMappingValues()
+ throws InterruptedException, ExecutionException, WriteFailedException {
+ when(writeContext.readAfter(EID_TABLE_ID)).thenReturn(eidTableDataWithoutLocalMappingValues());
+ verifySuccessfullDelete(LOCATOR_SET_TO_DELETE);
+ }
+ private void verifySuccessfullDelete(final LocatorSet locatorSet) throws WriteFailedException {
ArgumentCaptor<LispAddDelLocatorSet> locatorSetCaptor = ArgumentCaptor.forClass(LispAddDelLocatorSet.class);
when(api.lispAddDelLocatorSet(any(LispAddDelLocatorSet.class)))
@@ -145,4 +177,55 @@ public class LocatorSetCustomizerTest extends WriterCustomizerTest {
assertEquals("Locator", new String(request.locatorSetName));
assertEquals(0, request.isAdd);
}
+
+ @Test
+ public void testDeleteReferenced() throws InterruptedException, ExecutionException, WriteFailedException {
+ when(writeContext.readAfter(EID_TABLE_ID))
+ .thenReturn(eidTableData());
+
+ ArgumentCaptor<LispAddDelLocatorSet> locatorSetCaptor = ArgumentCaptor.forClass(LispAddDelLocatorSet.class);
+
+ when(api.lispAddDelLocatorSet(any(LispAddDelLocatorSet.class)))
+ .thenReturn(future(new LispAddDelLocatorSetReply()));
+
+ try {
+ customizer.deleteCurrentAttributes(null, LOCATOR_SET_TO_DELETE, writeContext);
+ } catch (IllegalStateException e) {
+ verify(api, times(0)).lispAddDelLocatorSet(locatorSetCaptor.capture());
+ return;
+ }
+ fail("testDeleteReferenced should have failed");
+ }
+
+ private static Optional<EidTable> eidTableData() {
+ return Optional.of(new EidTableBuilder()
+ .setVniTable(
+ Arrays.asList(new VniTableBuilder()
+ .setVrfSubtable(new VrfSubtableBuilder()
+ .setLocalMappings(new LocalMappingsBuilder()
+ .setLocalMapping(Arrays.asList(
+ new LocalMappingBuilder().setLocatorSet("Locator")
+ .build(),
+ new LocalMappingBuilder()
+ .setLocatorSet("OtherLocatorSet").build()
+ )).build()).build()).build())).build());
+ }
+
+ private static Optional<EidTable> eidTableDataWithoutLocalMappingValues() {
+ return Optional.of(new EidTableBuilder()
+ .setVniTable(
+ Arrays.asList(new VniTableBuilder()
+ .setVrfSubtable(new VrfSubtableBuilder()
+ .setLocalMappings(new LocalMappingsBuilder().build()).build()).build()))
+ .build());
+ }
+
+ private static Optional<EidTable> eidTableDataWithoutLocalMappingContainer() {
+ return Optional.of(new EidTableBuilder()
+ .setVniTable(
+ Arrays.asList(new VniTableBuilder().setVrfSubtable(new VrfSubtableBuilder().build()).build()))
+ .build());
+ }
+
+
}
diff --git a/vpp-common/vpp-translate-utils/src/main/java/io/fd/hc2vpp/common/translate/util/ReferenceCheck.java b/vpp-common/vpp-translate-utils/src/main/java/io/fd/hc2vpp/common/translate/util/ReferenceCheck.java
new file mode 100644
index 000000000..847f28aed
--- /dev/null
+++ b/vpp-common/vpp-translate-utils/src/main/java/io/fd/hc2vpp/common/translate/util/ReferenceCheck.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.common.translate.util;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Checks references exist, and throws if present
+ */
+public interface ReferenceCheck {
+
+ /**
+ * Checks if references are present, and throw if so
+ *
+ * @throws IllegalStateException if any references present
+ */
+ default <T extends DataObject> void checkReferenceExist(@Nonnull final InstanceIdentifier<?> locSetId,
+ final Collection<T> references) {
+ checkState(references == null || references.isEmpty(), "%s is referenced in %s", locSetId, references);
+ }
+}