From 28208ac2b1b9e068c51eee79cf1bfedc6a818195 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 12 Apr 2016 10:13:37 +0200 Subject: HONEYCOMB-9: Migrate Interface listener Change-Id: Iffde1ee21b749a8c8efa96c243f7f8bb0811b4c7 Signed-off-by: Maros Marsalek --- v3po/api/src/main/yang/v3po.yang | 5 + v3po/impl/pom.xml | 6 - .../v3po/translate/VppApiInvocationException.java | 76 -------- .../v3po/translate/write/ChildWriter.java | 6 +- .../v3po/translate/write/WriteFailedException.java | 154 +++++++++++++++ .../fd/honeycomb/v3po/translate/write/Writer.java | 7 +- .../v3po/translate/write/WriterRegistry.java | 17 +- .../translate/VppApiInvocationExceptionTest.java | 44 ----- .../v3po/translate/impl/TraversalType.java | 37 ++++ .../impl/read/AbstractCompositeReader.java | 41 ++-- .../translate/impl/read/CompositeChildReader.java | 21 ++- .../translate/impl/read/CompositeListReader.java | 20 +- .../translate/impl/read/CompositeRootReader.java | 21 ++- .../impl/write/AbstractCompositeWriter.java | 107 ++++++++--- .../translate/impl/write/CompositeChildWriter.java | 27 ++- .../translate/impl/write/CompositeListWriter.java | 33 +++- .../translate/impl/write/CompositeRootWriter.java | 24 ++- .../translate/spi/write/RootWriterCustomizer.java | 13 +- .../fd/honeycomb/v3po/translate/util/RWUtils.java | 5 + .../v3po/translate/util/read/CloseableReader.java | 60 ++++++ .../v3po/translate/util/write/CloseableWriter.java | 63 +++++++ .../util/write/DelegatingWriterRegistry.java | 10 +- .../rev160406/DelegatingWriterRegistryModule.java | 3 +- .../write/util/DelegatingWriterRegistryTest.java | 10 +- v3po/v3po2vpp/src/main/config/default-config.xml | 20 ++ .../v3po/interfaces/EthernetCustomizer.java | 70 +++++++ .../v3po/interfaces/InterfaceCustomizer.java | 72 +++++++ .../translate/v3po/interfaces/L2Customizer.java | 179 ++++++++++++++++++ .../v3po/interfaces/RoutingCustomizer.java | 115 +++++++++++ .../v3po/interfaces/VppInterfaceCustomizer.java | 210 +++++++++++++++++++++ .../translate/v3po/interfaces/VxlanCustomizer.java | 112 +++++++++++ .../v3po/interfaces/ip/Interface1Customizer.java | 60 ++++++ .../v3po/interfaces/ip/Ipv4Customizer.java | 153 +++++++++++++++ .../v3po/interfaces/ip/Ipv6Customizer.java | 66 +++++++ .../v3po/translate/v3po/utils/V3poUtils.java | 78 ++++++++ .../translate/v3po/vpp/BridgeDomainCustomizer.java | 15 +- .../rev160406/InterfacesHoneycombWriterModule.java | 114 +++++++++++ .../InterfacesHoneycombWriterModuleFactory.java | 13 ++ .../InterfacesStateHoneycombReaderModule.java | 46 +---- .../rev160406/VppHoneycombWriterModule.java | 46 +---- .../rev160406/VppStateHoneycombReaderModule.java | 43 +---- v3po/v3po2vpp/src/main/yang/v3po2vpp.yang | 21 +++ .../v3po/translate/v3po/util/VppApiCustomizer.java | 2 +- .../v3po/util/VppApiInvocationException.java | 75 ++++++++ .../v3po/util/VppApiInvocationExceptionTest.java | 44 +++++ 45 files changed, 1994 insertions(+), 370 deletions(-) delete mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java create mode 100644 v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteFailedException.java delete mode 100644 v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java create mode 100644 v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/TraversalType.java create mode 100644 v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/CloseableReader.java create mode 100644 v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/CloseableWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java create mode 100644 v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java create mode 100644 v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModuleFactory.java create mode 100644 v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationException.java create mode 100644 v3po/vpp-translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationExceptionTest.java diff --git a/v3po/api/src/main/yang/v3po.yang b/v3po/api/src/main/yang/v3po.yang index 43d318643..0ea54fa03 100644 --- a/v3po/api/src/main/yang/v3po.yang +++ b/v3po/api/src/main/yang/v3po.yang @@ -85,6 +85,11 @@ module v3po { augment /if:interfaces/if:interface { ext:augment-identifier "vpp-interface-augmentation"; + + // FIXME using ietf-interfaces model for vpp interfaces makes it hard to implement because: + // 1. The link between interface type and this augmentation is unclear + // 2. Only this augmentation with combination of ifc type is trigger to do something for vpp, what if user only configures base interface stuff ? + We need to get leaves defined by ietf-interfaces when we are processing this augment + container ethernet { when "../if:type = 'ianaift:ethernetCsmacd'"; leaf mtu { diff --git a/v3po/impl/pom.xml b/v3po/impl/pom.xml index ffa16aed2..63eb1f442 100644 --- a/v3po/impl/pom.xml +++ b/v3po/impl/pom.xml @@ -86,12 +86,6 @@ 1.5.6 test - - org.skinny-framework - skinny-logback - 1.0.8 - test - diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java deleted file mode 100644 index 298c698f7..000000000 --- a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/VppApiInvocationException.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.honeycomb.v3po.translate; - -import com.google.common.annotations.Beta; -import com.google.common.base.Preconditions; -import javax.annotation.Nonnull; - -/** - * Thrown when Vpp jAPI method invocation failed. - */ -@Beta -public class VppApiInvocationException extends TranslationException { - private final String methodName; - private final int ctxId; - private final int errorCode; - - /** - * Constructs an VppApiInvocationFailedException with the specified api method name and error code. - * - * @param methodName method name that failed to invoke - * @param ctxId api request context identifier - * @param errorCode negative error code value associated with this failure - * @throws NullPointerException if apiMethodName is null - * @throws IllegalArgumentException if errorCode is nonnegative - */ - public VppApiInvocationException(@Nonnull final String methodName, final int ctxId, final int errorCode) { - super(String.format("vppApi.%s failed with error code: %d (ctxId=%d) ", methodName, errorCode, ctxId)); - this.methodName = Preconditions.checkNotNull(methodName, "apiMethodName is null!"); - this.ctxId = ctxId; - Preconditions.checkArgument(errorCode < 0); - this.errorCode = errorCode; - } - - /** - * Returns method name that failed to invoke. - * - * @return method name - */ - public String getMethodName() { - return methodName; - } - - /** - * Returns api request context identifier. - * - * @return value of context identifier - */ - public int getCtxId() { - return ctxId; - } - - /** - * Returns the error code associated with this failure. - * - * @return a negative integer error code - */ - public int getErrorCode() { - return errorCode; - } -} - diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java index f933cfd4a..b38f26983 100644 --- a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/ChildWriter.java @@ -38,7 +38,7 @@ public interface ChildWriter extends Writer { */ void writeChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataAfter, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; /** * Extract data object managed by this writer(if necessary) from parent data and perform delete. @@ -49,7 +49,7 @@ public interface ChildWriter extends Writer { */ void deleteChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataBefore, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; /** * Extract data object managed by this writer(if necessary) from parent data and perform delete. @@ -62,5 +62,5 @@ public interface ChildWriter extends Writer { void updateChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataBefore, @Nonnull final DataObject parentDataAfter, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; } diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteFailedException.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteFailedException.java new file mode 100644 index 000000000..a924c7646 --- /dev/null +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriteFailedException.java @@ -0,0 +1,154 @@ +/* + * 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.honeycomb.v3po.translate.write; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.v3po.translate.TranslationException; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Thrown when a writer or customizer is not able to write/update/delete data . + */ +public class WriteFailedException extends TranslationException { + + private final InstanceIdentifier failedId; + + /** + * Constructs an WriteFailedException given data id and exception cause. + * + * @param failedId instance identifier of the data object that could not be read + * @param cause the cause of read failure + * @param message + */ + public WriteFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final String message, + @Nonnull final Throwable cause) { + super(message, cause); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + } + + /** + * Constructs an WriteFailedException given data id. + * + * @param failedId instance identifier of the data object that could not be written + */ + public WriteFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final String message) { + super(message); + this.failedId = checkNotNull(failedId, "failedId should not be null"); + } + + /** + * Returns id of the data object that could not be written. + * + * @return data object instance identifier + */ + @Nonnull + public InstanceIdentifier getFailedId() { + return failedId; + } + + + /** + * Delete specific write failed exception + */ + public static class DeleteFailedException extends WriteFailedException { + + public DeleteFailedException(@Nonnull final InstanceIdentifier failedId, @Nonnull final Throwable cause) { + super(failedId, getMsg(failedId), cause); + } + + private static String getMsg(@Nonnull final InstanceIdentifier failedId) { + return String.format("Failed to delete data at: %s", failedId); + } + + public DeleteFailedException(@Nonnull final InstanceIdentifier failedId) { + super(failedId, getMsg(failedId)); + } + } + + /** + * Create specific write failed exception + */ + public static class CreateFailedException extends WriteFailedException { + + private final DataObject data; + + public CreateFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final DataObject data, + @Nonnull final Throwable cause) { + super(failedId, getMsg(failedId, data), cause); + this.data = checkNotNull(data, "data"); + } + + private static String getMsg(final @Nonnull InstanceIdentifier failedId, final DataObject data) { + return String.format("Failed to create data: %s at: %s", data, failedId); + } + + public CreateFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final DataObject data) { + super(failedId, getMsg(failedId, data)); + this.data = checkNotNull(data, "data"); + } + + public DataObject getData() { + return data; + } + } + + /** + * Update specific write failed exception + */ + public static class UpdateFailedException extends WriteFailedException { + + private final DataObject dataBefore; + private final DataObject dataAfter; + + public UpdateFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final DataObject dataBefore, + @Nonnull final DataObject dataAfter, + @Nonnull final Throwable cause) { + super(failedId, getMsg(failedId, dataBefore, dataAfter), cause); + this.dataBefore = checkNotNull(dataBefore, "dataBefore"); + this.dataAfter = checkNotNull(dataAfter, "dataAfter"); + } + + private static String getMsg(final @Nonnull InstanceIdentifier failedId, final DataObject dataBefore, + final DataObject dataAfter) { + return String.format("Failed to update data from: %s to: %s, at: %s", dataBefore, dataAfter, failedId); + } + + public UpdateFailedException(@Nonnull final InstanceIdentifier failedId, + @Nonnull final DataObject dataBefore, + @Nonnull final DataObject dataAfter) { + super(failedId, getMsg(failedId, dataBefore, dataAfter)); + this.dataBefore = checkNotNull(dataBefore, "dataBefore"); + this.dataAfter = checkNotNull(dataAfter, "dataAfter"); + } + + public DataObject getDataBefore() { + return dataBefore; + } + + public DataObject getDataAfter() { + return dataAfter; + } + } +} diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java index 08465fdd7..77abe341c 100644 --- a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/Writer.java @@ -17,7 +17,6 @@ package io.fd.honeycomb.v3po.translate.write; import com.google.common.annotations.Beta; -import io.fd.honeycomb.v3po.translate.TranslationException; import io.fd.honeycomb.v3po.translate.SubtreeManager; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -36,14 +35,14 @@ public interface Writer extends SubtreeManager { /** * Handle update operation. U from CRUD. * - * @param id Identifier(from root) of data being written + * @param id Identifier of data being written * @param dataBefore Old data * @param dataAfter New, updated data * @param ctx Write context enabling writer to get information about candidate data as well as current data - * @throws TranslationException if update failed + * @throws WriteFailedException if update failed */ void update(@Nonnull final InstanceIdentifier id, @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter, - @Nonnull final WriteContext ctx) throws TranslationException; + @Nonnull final WriteContext ctx) throws WriteFailedException; } diff --git a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java index c5a8116c8..d30f06d13 100644 --- a/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java +++ b/v3po/translate-api/src/main/java/io/fd/honeycomb/v3po/translate/write/WriterRegistry.java @@ -47,10 +47,9 @@ public interface WriterRegistry extends Writer { * Thrown when bulk update failed. */ @Beta - class BulkUpdateException extends TranslationException { + class BulkUpdateException extends WriteFailedException { private final Reverter reverter; - private final InstanceIdentifier failedId; // TODO change to VppDataModification /** * Constructs an BulkUpdateException. @@ -60,8 +59,7 @@ public interface WriterRegistry extends Writer { */ public BulkUpdateException(@Nonnull final InstanceIdentifier failedId, @Nonnull final Reverter reverter, final Throwable cause) { - super("Bulk update failed at " + failedId, cause); - this.failedId = checkNotNull(failedId, "failedId should not be null"); + super(failedId, "Bulk update failed at " + failedId, cause); this.reverter = checkNotNull(reverter, "reverter should not be null"); } @@ -74,19 +72,10 @@ public interface WriterRegistry extends Writer { reverter.revert(); } - /** - * Returns instance identifier of the data object that caused bulk update to fail. - * - * @return data object's instance identifier - */ - @Nonnull - public InstanceIdentifier getFailedId() { - return failedId; - } } /** - * Abstraction over revert mechanism in cast of a bulk update failure + * Abstraction over revert mechanism in case of a bulk update failure */ @Beta interface Reverter { diff --git a/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java b/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java deleted file mode 100644 index b2cfbd216..000000000 --- a/v3po/translate-api/src/test/java/io/fd/honeycomb/v3po/translate/VppApiInvocationExceptionTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.honeycomb.v3po.translate; - -import java.util.Random; -import org.junit.Assert; -import org.junit.Test; - -public class VppApiInvocationExceptionTest { - - @Test - public void testInstantiation() { - final String apiMethodName = "methodName"; - final int ctxId = 1; - final int code = -1; - VppApiInvocationException e = new VppApiInvocationException(apiMethodName, ctxId, code); - Assert.assertEquals(apiMethodName, e.getMethodName()); - Assert.assertEquals(ctxId, e.getCtxId()); - Assert.assertEquals(code, e.getErrorCode()); - Assert.assertTrue(e.getMessage().contains(apiMethodName)); - Assert.assertTrue(e.getMessage().contains(String.valueOf(code))); - Assert.assertTrue(e.getMessage().contains(String.valueOf(ctxId))); - } - - @Test(expected = IllegalArgumentException.class) - public void testInstantiationFailed() { - final int code = new Random().nextInt(Integer.MAX_VALUE); - VppApiInvocationException e = new VppApiInvocationException("apiMethodName", 1, code); - } -} diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/TraversalType.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/TraversalType.java new file mode 100644 index 000000000..3fa0f8d24 --- /dev/null +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/TraversalType.java @@ -0,0 +1,37 @@ +/* + * 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.honeycomb.v3po.translate.impl; + +/** + * Type of traversal to be used by readers/writers in a tree + */ +public enum TraversalType { + + /** + * Read current attributes before reading from children + */ + PREORDER, + + /** + * Read from children before reading current attributes + */ + POSTORDER + + // TODO implement different traversal types as injectable iterators + // TODO implement above traversal types in readers + +} \ No newline at end of file diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java index f9fa0eeaa..e8d79c538 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/AbstractCompositeReader.java @@ -22,6 +22,7 @@ import com.google.common.annotations.Beta; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.util.ReflectionUtils; import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.read.ChildReader; @@ -52,10 +53,13 @@ abstract class AbstractCompositeReader, ChildReader>> childReaders; private final Map, ChildReader>> augReaders; private final InstanceIdentifier instanceIdentifier; + private final TraversalType traversalType; AbstractCompositeReader(final Class managedDataObjectType, final List>> childReaders, - final List>> augReaders) { + final List>> augReaders, + final TraversalType traversalType) { + this.traversalType = traversalType; this.childReaders = RWUtils.uniqueLinkedIndex(childReaders, RWUtils.MANAGER_CLASS_FUNCTION); this.augReaders = RWUtils.uniqueLinkedIndex(augReaders, RWUtils.MANAGER_CLASS_AUG_FUNCTION); this.instanceIdentifier = InstanceIdentifier.create(managedDataObjectType); @@ -78,9 +82,31 @@ abstract class AbstractCompositeReader read = built.equals(emptyValue) + ? Optional.absent() + : Optional.of(built); + + LOG.debug("{}: Current node read successfully. Result: {}", this, read); + return read; + } + private void readChildren(final InstanceIdentifier id, final @Nonnull ReadContext ctx, final B builder) + throws ReadFailedException { // TODO expect exceptions from reader for (ChildReader> child : childReaders.values()) { LOG.debug("{}: Reading child from: {}", this, child); @@ -91,15 +117,6 @@ abstract class AbstractCompositeReader read = built.equals(emptyValue) - ? Optional.absent() - : Optional.of(built); - - LOG.debug("{}: Current node read successfully. Result: {}", this, read); - return read; } @Nonnull diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeChildReader.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeChildReader.java index 46a59bb90..1984cd86d 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeChildReader.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeChildReader.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.translate.impl.read; import com.google.common.annotations.Beta; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.util.RWUtils; @@ -56,7 +57,25 @@ public final class CompositeChildReader>> childReaders, @Nonnull final List>> augReaders, @Nonnull final ChildReaderCustomizer customizer) { - super(managedDataObjectType, childReaders, augReaders); + this(managedDataObjectType, childReaders, augReaders, customizer, TraversalType.PREORDER); + } + + /** + * Create new {@link CompositeChildReader} + * + * @param managedDataObjectType Class object for managed data type + * @param childReaders Child nodes(container, list) readers + * @param augReaders Child augmentations readers + * @param customizer Customizer instance to customize this generic reader + * @param traversalType Type of traversal to use in the tree of readers + * + */ + public CompositeChildReader(@Nonnull final Class managedDataObjectType, + @Nonnull final List>> childReaders, + @Nonnull final List>> augReaders, + @Nonnull final ChildReaderCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(managedDataObjectType, childReaders, augReaders, traversalType); this.customizer = customizer; } diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeListReader.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeListReader.java index fd7b279ca..de32ee723 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeListReader.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeListReader.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.annotations.Beta; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.read.ChildReader; @@ -68,7 +69,24 @@ public final class CompositeListReader, K @Nonnull final List>> childReaders, @Nonnull final List>> augReaders, @Nonnull final ListReaderCustomizer customizer) { - super(managedDataObjectType, childReaders, augReaders); + this(managedDataObjectType, childReaders, augReaders, customizer, TraversalType.PREORDER); + } + + /** + * Create new {@link CompositeListReader} + * + * @param managedDataObjectType Class object for managed data type. Must come from a list node type. + * @param childReaders Child nodes(container, list) readers + * @param augReaders Child augmentations readers + * @param customizer Customizer instance to customize this generic reader + * @param traversalType Type of traversal to use in the tree of readers + */ + public CompositeListReader(@Nonnull final Class managedDataObjectType, + @Nonnull final List>> childReaders, + @Nonnull final List>> augReaders, + @Nonnull final ListReaderCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(managedDataObjectType, childReaders, augReaders, traversalType); this.customizer = customizer; } diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeRootReader.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeRootReader.java index f297abb76..0abae70be 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeRootReader.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/read/CompositeRootReader.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.v3po.translate.impl.read; import com.google.common.annotations.Beta; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.read.ChildReader; @@ -55,7 +56,25 @@ public final class CompositeRootReader>> childReaders, @Nonnull final List>> augReaders, @Nonnull final RootReaderCustomizer customizer) { - super(managedDataObjectType, childReaders, augReaders); + this(managedDataObjectType, childReaders, augReaders, customizer, TraversalType.PREORDER); + } + + /** + * Create new {@link CompositeRootReader} + * + * @param managedDataObjectType Class object for managed data type + * @param childReaders Child nodes(container, list) readers + * @param augReaders Child augmentations readers + * @param customizer Customizer instance to customize this generic reader + * @param traversalType Type of traversal to use in the tree of readers + * + */ + public CompositeRootReader(@Nonnull final Class managedDataObjectType, + @Nonnull final List>> childReaders, + @Nonnull final List>> augReaders, + @Nonnull final RootReaderCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(managedDataObjectType, childReaders, augReaders, traversalType); this.customizer = customizer; } diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/AbstractCompositeWriter.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/AbstractCompositeWriter.java index e971fbeff..1e4d1361a 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/AbstractCompositeWriter.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/AbstractCompositeWriter.java @@ -20,10 +20,11 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.base.Optional; import com.google.common.collect.Lists; -import io.fd.honeycomb.v3po.translate.TranslationException; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; +import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.write.ChildWriter; import io.fd.honeycomb.v3po.translate.write.WriteContext; -import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import io.fd.honeycomb.v3po.translate.write.Writer; import java.util.ArrayList; import java.util.Collection; @@ -46,21 +47,42 @@ public abstract class AbstractCompositeWriter implements W private final Map, ChildWriter>> childWriters; private final Map, ChildWriter>> augWriters; private final InstanceIdentifier instanceIdentifier; + private TraversalType traversalType; public AbstractCompositeWriter(final Class type, final List>> childWriters, - final List>> augWriters) { + final List>> augWriters, + final TraversalType traversalType) { + this.traversalType = traversalType; this.instanceIdentifier = InstanceIdentifier.create(type); this.childWriters = RWUtils.uniqueLinkedIndex(childWriters, RWUtils.MANAGER_CLASS_FUNCTION); this.augWriters = RWUtils.uniqueLinkedIndex(augWriters, RWUtils.MANAGER_CLASS_AUG_FUNCTION); } - protected void writeCurrent(final InstanceIdentifier id, final D data, final WriteContext ctx) { + protected void writeCurrent(final InstanceIdentifier id, final D data, final WriteContext ctx) + throws WriteFailedException { LOG.debug("{}: Writing current: {} data: {}", this, id, data); - LOG.trace("{}: Writing current attributes", this); - writeCurrentAttributes(id, data, ctx); + switch (traversalType) { + case PREORDER: { + LOG.trace("{}: Writing current attributes", this); + writeCurrentAttributes(id, data, ctx); + writeChildren(id, data, ctx); + break; + } + case POSTORDER: { + writeChildren(id, data, ctx); + LOG.trace("{}: Writing current attributes", this); + writeCurrentAttributes(id, data, ctx); + break; + } + } + LOG.debug("{}: Current node written successfully", this); + } + + private void writeChildren(final InstanceIdentifier id, final D data, final WriteContext ctx) + throws WriteFailedException { for (ChildWriter> child : childWriters.values()) { LOG.debug("{}: Writing child in: {}", this, child); child.writeChild(id, data, ctx); @@ -70,23 +92,38 @@ public abstract class AbstractCompositeWriter implements W LOG.debug("{}: Writing augment in: {}", this, child); child.writeChild(id, data, ctx); } - - LOG.debug("{}: Current node written successfully", this); } protected void updateCurrent(final InstanceIdentifier id, final D dataBefore, final D dataAfter, - final WriteContext ctx) { + final WriteContext ctx) throws WriteFailedException { LOG.debug("{}: Updating current: {} dataBefore: {}, datAfter: {}", this, id, dataBefore, dataAfter); - if(dataBefore.equals(dataAfter)) { + if (dataBefore.equals(dataAfter)) { LOG.debug("{}: Skipping current(no update): {}", this, id); // No change, ignore return; } - LOG.trace("{}: Updating current attributes", this); - updateCurrentAttributes(id, dataBefore, dataAfter, ctx); + switch (traversalType) { + case PREORDER: { + LOG.trace("{}: Updating current attributes", this); + updateCurrentAttributes(id, dataBefore, dataAfter, ctx); + updateChildren(id, dataBefore, dataAfter, ctx); + break; + } + case POSTORDER: { + updateChildren(id, dataBefore, dataAfter, ctx); + LOG.trace("{}: Updating current attributes", this); + updateCurrentAttributes(id, dataBefore, dataAfter, ctx); + break; + } + } + + LOG.debug("{}: Current node updated successfully", this); + } + private void updateChildren(final InstanceIdentifier id, final D dataBefore, final D dataAfter, + final WriteContext ctx) throws WriteFailedException { for (ChildWriter> child : childWriters.values()) { LOG.debug("{}: Updating child in: {}", this, child); child.updateChild(id, dataBefore, dataAfter, ctx); @@ -96,14 +133,30 @@ public abstract class AbstractCompositeWriter implements W LOG.debug("{}: Updating augment in: {}", this, child); child.updateChild(id, dataBefore, dataAfter, ctx); } - - LOG.debug("{}: Current node updated successfully", this); } - protected void deleteCurrent(final InstanceIdentifier id, final D dataBefore, final WriteContext ctx) { + protected void deleteCurrent(final InstanceIdentifier id, final D dataBefore, final WriteContext ctx) + throws WriteFailedException { LOG.debug("{}: Deleting current: {} dataBefore: {}", this, id, dataBefore); - // delete in reversed order + switch (traversalType) { + case PREORDER: { + deleteChildren(id, dataBefore, ctx); + LOG.trace("{}: Deleting current attributes", this); + deleteCurrentAttributes(id, dataBefore, ctx); + break; + } + case POSTORDER: { + LOG.trace("{}: Deleting current attributes", this); + deleteCurrentAttributes(id, dataBefore, ctx); + deleteChildren(id, dataBefore, ctx); + break; + } + } + } + + private void deleteChildren(final InstanceIdentifier id, final D dataBefore, final WriteContext ctx) + throws WriteFailedException { for (ChildWriter> child : reverseCollection(augWriters.values())) { LOG.debug("{}: Deleting augment in: {}", this, child); child.deleteChild(id, dataBefore, ctx); @@ -113,9 +166,6 @@ public abstract class AbstractCompositeWriter implements W LOG.debug("{}: Deleting child in: {}", this, child); child.deleteChild(id, dataBefore, ctx); } - - LOG.trace("{}: Deleting current attributes", this); - deleteCurrentAttributes(id, dataBefore, ctx); } @SuppressWarnings("unchecked") @@ -123,7 +173,7 @@ public abstract class AbstractCompositeWriter implements W public void update(@Nonnull final InstanceIdentifier id, @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter, - @Nonnull final WriteContext ctx) throws TranslationException { + @Nonnull final WriteContext ctx) throws WriteFailedException { LOG.debug("{}: Updating : {}", this, id); LOG.trace("{}: Updating : {}, from: {} to: {}", this, id, dataBefore, dataAfter); @@ -168,7 +218,7 @@ public abstract class AbstractCompositeWriter implements W } private void writeSubtree(final InstanceIdentifier id, - final DataObject dataAfter, final WriteContext ctx) throws TranslationException { + final DataObject dataAfter, final WriteContext ctx) throws WriteFailedException { LOG.debug("{}: Writing subtree: {}", this, id); final Writer> writer = getNextWriter(id); @@ -190,9 +240,8 @@ public abstract class AbstractCompositeWriter implements W return id.getTargetType().equals(getManagedDataObjectType().getTargetType()); } - @SuppressWarnings("unchecked") private void deleteSubtree(final InstanceIdentifier id, - final DataObject dataBefore, final WriteContext ctx) throws TranslationException { + final DataObject dataBefore, final WriteContext ctx) throws WriteFailedException { LOG.debug("{}: Deleting subtree: {}", this, id); final Writer> writer = getNextWriter(id); @@ -205,7 +254,8 @@ public abstract class AbstractCompositeWriter implements W } @SuppressWarnings("unchecked") - private void updateSubtreeFromCurrent(final InstanceIdentifier id, final WriteContext ctx) { + private void updateSubtreeFromCurrent(final InstanceIdentifier id, final WriteContext ctx) + throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.cutId(id, getManagedDataObjectType()); Optional currentDataBefore = ctx.readBefore(currentId); Optional currentDataAfter = ctx.readAfter(currentId); @@ -215,11 +265,10 @@ public abstract class AbstractCompositeWriter implements W castToManaged(currentDataAfter.orNull()), ctx); } - @SuppressWarnings("unchecked") private void updateSubtree(final InstanceIdentifier id, final DataObject dataBefore, final DataObject dataAfter, - final WriteContext ctx) throws TranslationException { + final WriteContext ctx) throws WriteFailedException { LOG.debug("{}: Updating subtree: {}", this, id); final Writer> writer = getNextWriter(id); @@ -245,16 +294,16 @@ public abstract class AbstractCompositeWriter implements W protected abstract void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D data, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; protected abstract void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; protected abstract void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, @Nonnull final D dataAfter, - @Nonnull final WriteContext ctx); + @Nonnull final WriteContext ctx) throws WriteFailedException; @Nonnull @Override diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeChildWriter.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeChildWriter.java index fbfeffbdb..512eb44d9 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeChildWriter.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeChildWriter.java @@ -17,10 +17,12 @@ package io.fd.honeycomb.v3po.translate.impl.write; import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.write.ChildWriter; import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import java.util.List; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.Augmentation; @@ -37,7 +39,16 @@ public class CompositeChildWriter extends AbstractComposit @Nonnull final List>> childWriters, @Nonnull final List>> augWriters, @Nonnull final ChildWriterCustomizer customizer) { - super(type, childWriters, augWriters); + this(type, childWriters, augWriters, customizer, TraversalType.PREORDER); + } + + + public CompositeChildWriter(@Nonnull final Class type, + @Nonnull final List>> childWriters, + @Nonnull final List>> augWriters, + @Nonnull final ChildWriterCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(type, childWriters, augWriters, traversalType); this.customizer = customizer; } @@ -54,25 +65,27 @@ public class CompositeChildWriter extends AbstractComposit @Override protected void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D data, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { customizer.writeCurrentAttributes(id, data, ctx.getContext()); } @Override protected void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull WriteContext ctx) { + @Nonnull WriteContext ctx) throws WriteFailedException { customizer.deleteCurrentAttributes(id, dataBefore, ctx.getContext()); } @Override protected void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final D dataAfter, @Nonnull WriteContext ctx) { + @Nonnull final D dataAfter, @Nonnull WriteContext ctx) + throws WriteFailedException { customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx.getContext()); } @Override public void writeChild(@Nonnull final InstanceIdentifier parentId, - @Nonnull final DataObject parentData, @Nonnull WriteContext ctx) { + @Nonnull final DataObject parentData, @Nonnull WriteContext ctx) + throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final Optional currentData = customizer.extract(currentId, parentData); if(currentData.isPresent()) { @@ -83,7 +96,7 @@ public class CompositeChildWriter extends AbstractComposit @Override public void deleteChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentData, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final Optional currentData = customizer.extract(currentId, parentData); if(currentData.isPresent()) { @@ -94,7 +107,7 @@ public class CompositeChildWriter extends AbstractComposit @Override public void updateChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataBefore, @Nonnull final DataObject parentDataAfter, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final Optional before = customizer.extract(currentId, parentDataBefore); final Optional after = customizer.extract(currentId, parentDataAfter); diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeListWriter.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeListWriter.java index dc924fe39..967edb6a9 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeListWriter.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeListWriter.java @@ -20,10 +20,12 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; import io.fd.honeycomb.v3po.translate.write.ChildWriter; import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import java.util.List; import java.util.Map; import javax.annotation.Nonnull; @@ -54,7 +56,15 @@ public class CompositeListWriter, K exten @Nonnull final List>> childWriters, @Nonnull final List>> augWriters, @Nonnull final ListWriterCustomizer customizer) { - super(type, childWriters, augWriters); + this(type, childWriters, augWriters, customizer, TraversalType.PREORDER); + } + + public CompositeListWriter(@Nonnull final Class type, + @Nonnull final List>> childWriters, + @Nonnull final List>> augWriters, + @Nonnull final ListWriterCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(type, childWriters, augWriters, traversalType); this.customizer = customizer; } @@ -72,26 +82,27 @@ public class CompositeListWriter, K exten @Override protected void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D data, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { customizer.writeCurrentAttributes(id, data, ctx.getContext()); } @Override protected void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { customizer.deleteCurrentAttributes(id, dataBefore, ctx.getContext()); } @Override protected void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final D dataAfter, @Nonnull final WriteContext ctx) { + @Nonnull final D dataAfter, @Nonnull final WriteContext ctx) + throws WriteFailedException { customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx.getContext()); } @Override public void writeChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentData, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final List currentData = customizer.extract(currentId, parentData); for (D entry : currentData) { @@ -102,7 +113,7 @@ public class CompositeListWriter, K exten @Override public void deleteChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataBefore, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final List dataBefore = customizer.extract(currentId, parentDataBefore); for (D entry : dataBefore) { @@ -113,7 +124,7 @@ public class CompositeListWriter, K exten @Override public void updateChild(@Nonnull final InstanceIdentifier parentId, @Nonnull final DataObject parentDataBefore, @Nonnull final DataObject parentDataAfter, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier currentId = RWUtils.appendTypeToId(parentId, getManagedDataObjectType()); final ImmutableMap dataBefore = Maps.uniqueIndex(customizer.extract(currentId, parentDataBefore), INDEX_FUNCTION); @@ -138,7 +149,8 @@ public class CompositeListWriter, K exten } @Override - protected void writeCurrent(final InstanceIdentifier id, final D data, final WriteContext ctx) { + protected void writeCurrent(final InstanceIdentifier id, final D data, final WriteContext ctx) + throws WriteFailedException { // Make sure the key is present if(isWildcarded(id)) { super.writeCurrent(getSpecificId(id, data), data, ctx); @@ -149,7 +161,7 @@ public class CompositeListWriter, K exten @Override protected void updateCurrent(final InstanceIdentifier id, final D dataBefore, final D dataAfter, - final WriteContext ctx) { + final WriteContext ctx) throws WriteFailedException { // Make sure the key is present if(isWildcarded(id)) { super.updateCurrent(getSpecificId(id, dataBefore), dataBefore, dataAfter, ctx); @@ -159,7 +171,8 @@ public class CompositeListWriter, K exten } @Override - protected void deleteCurrent(final InstanceIdentifier id, final D dataBefore, final WriteContext ctx) { + protected void deleteCurrent(final InstanceIdentifier id, final D dataBefore, final WriteContext ctx) + throws WriteFailedException { // Make sure the key is present if(isWildcarded(id)) { super.deleteCurrent(getSpecificId(id, dataBefore), dataBefore, ctx); diff --git a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeRootWriter.java b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeRootWriter.java index acf2cfd2e..5e4ff86ad 100644 --- a/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeRootWriter.java +++ b/v3po/translate-impl/src/main/java/io/fd/honeycomb/v3po/translate/impl/write/CompositeRootWriter.java @@ -16,10 +16,12 @@ package io.fd.honeycomb.v3po.translate.impl.write; -import io.fd.honeycomb.v3po.translate.write.WriteContext; -import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; import io.fd.honeycomb.v3po.translate.spi.write.RootWriterCustomizer; +import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.write.ChildWriter; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import java.util.List; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.Augmentation; @@ -35,7 +37,15 @@ public class CompositeRootWriter extends AbstractComposite @Nonnull final List>> childWriters, @Nonnull final List>> augWriters, @Nonnull final RootWriterCustomizer customizer) { - super(type, childWriters, augWriters); + this(type, childWriters, augWriters, customizer, TraversalType.PREORDER); + } + + public CompositeRootWriter(@Nonnull final Class type, + @Nonnull final List>> childWriters, + @Nonnull final List>> augWriters, + @Nonnull final RootWriterCustomizer customizer, + @Nonnull final TraversalType traversalType) { + super(type, childWriters, augWriters, traversalType); this.customizer = customizer; } @@ -52,13 +62,15 @@ public class CompositeRootWriter extends AbstractComposite @Override protected void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D data, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { + // TODO wrap all customizer invocations in try catch, and wrap runtime exceptions in ReadFailed + // TODO same for readers customizer.writeCurrentAttributes(id, data, ctx.getContext()); } @Override protected void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { customizer.deleteCurrentAttributes(id, dataBefore, ctx.getContext()); } @@ -66,7 +78,7 @@ public class CompositeRootWriter extends AbstractComposite protected void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, @Nonnull final D dataAfter, - @Nonnull final WriteContext ctx) { + @Nonnull final WriteContext ctx) throws WriteFailedException { customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx.getContext()); } } diff --git a/v3po/translate-spi/src/main/java/io/fd/honeycomb/v3po/translate/spi/write/RootWriterCustomizer.java b/v3po/translate-spi/src/main/java/io/fd/honeycomb/v3po/translate/spi/write/RootWriterCustomizer.java index ca4f02dce..2cdcff3fd 100644 --- a/v3po/translate-spi/src/main/java/io/fd/honeycomb/v3po/translate/spi/write/RootWriterCustomizer.java +++ b/v3po/translate-spi/src/main/java/io/fd/honeycomb/v3po/translate/spi/write/RootWriterCustomizer.java @@ -18,6 +18,7 @@ package io.fd.honeycomb.v3po.translate.spi.write; import com.google.common.annotations.Beta; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import javax.annotation.Nonnull; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -36,10 +37,12 @@ public interface RootWriterCustomizer { * @param id Identifier(from root) of data being written * @param dataAfter New data to be written * @param writeContext Write context can be used to store any useful information and then utilized by other customizers + * + * @throws WriteFailedException if write was unsuccessful */ void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataAfter, - @Nonnull final Context writeContext); + @Nonnull final Context writeContext) throws WriteFailedException; /** * Handle update operation. U from CRUD. @@ -48,11 +51,13 @@ public interface RootWriterCustomizer { * @param dataBefore Old data * @param dataAfter New, updated data * @param writeContext Write context can be used to store any useful information and then utilized by other customizers + * + * @throws WriteFailedException if update was unsuccessful */ void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, @Nonnull final D dataAfter, - @Nonnull final Context writeContext); + @Nonnull final Context writeContext) throws WriteFailedException; /** * Handle delete operation. D from CRUD. @@ -60,8 +65,10 @@ public interface RootWriterCustomizer { * @param id Identifier(from root) of data being written * @param dataBefore Old data being deleted * @param writeContext Write context can be used to store any useful information and then utilized by other customizers + * + * @throws WriteFailedException if delete was unsuccessful */ void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final D dataBefore, - @Nonnull final Context writeContext); + @Nonnull final Context writeContext) throws WriteFailedException; } diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java index 027d9bbb7..dbfed04b0 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/RWUtils.java @@ -89,6 +89,11 @@ public final class RWUtils { return Collections.>>singletonList(item); } + public static List>> singletonAugWriterList( + ChildWriter> item) { + return Collections.>>singletonList(item); + } + /** * Replace last item in ID with a provided IdentifiableItem of the same type */ diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/CloseableReader.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/CloseableReader.java new file mode 100644 index 000000000..5492062e3 --- /dev/null +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/read/CloseableReader.java @@ -0,0 +1,60 @@ +/* + * 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.honeycomb.v3po.translate.util.read; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.read.ReadContext; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.read.Reader; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Closeable wrapper for a reader + */ +public final class CloseableReader implements Reader, AutoCloseable { + + private Reader compositeRootReader; + + public CloseableReader(@Nonnull final Reader compositeRootReader) { + this.compositeRootReader = compositeRootReader; + } + + @Nonnull + @Override + public Optional read(@Nonnull InstanceIdentifier id, + @Nonnull ReadContext ctx) throws ReadFailedException { + return compositeRootReader.read(id, ctx); + } + + @Nonnull + @Override + public InstanceIdentifier getManagedDataObjectType() { + return compositeRootReader.getManagedDataObjectType(); + } + + @Override + public String toString() { + return compositeRootReader.toString(); + } + + @Override + public void close() throws Exception { + //NOOP + } +} diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/CloseableWriter.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/CloseableWriter.java new file mode 100644 index 000000000..3442f8370 --- /dev/null +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/CloseableWriter.java @@ -0,0 +1,63 @@ +/* + * 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.honeycomb.v3po.translate.util.write; + +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import io.fd.honeycomb.v3po.translate.write.Writer; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Closeable wrapper for a writer + */ +public final class CloseableWriter implements Writer, AutoCloseable { + + private Writer vppCompositeRootWriter; + + public CloseableWriter( + final Writer vppCompositeRootWriter) { + this.vppCompositeRootWriter = vppCompositeRootWriter; + } + + @Override + public void update( + @Nonnull final InstanceIdentifier id, + @Nullable final DataObject dataBefore, + @Nullable final DataObject dataAfter, + @Nonnull final WriteContext ctx) throws WriteFailedException { + vppCompositeRootWriter.update(id, dataBefore, dataAfter, ctx); + } + + @Nonnull + @Override + public InstanceIdentifier getManagedDataObjectType() { + return vppCompositeRootWriter.getManagedDataObjectType(); + } + + @Override + public String toString() { + return vppCompositeRootWriter.toString(); + } + + @Override + public void close() throws Exception { + + } +} diff --git a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/DelegatingWriterRegistry.java b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/DelegatingWriterRegistry.java index fda289e2b..f25ba5336 100644 --- a/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/DelegatingWriterRegistry.java +++ b/v3po/translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/util/write/DelegatingWriterRegistry.java @@ -24,9 +24,9 @@ import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import io.fd.honeycomb.v3po.translate.TranslationException; import io.fd.honeycomb.v3po.translate.util.RWUtils; import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import io.fd.honeycomb.v3po.translate.write.Writer; import io.fd.honeycomb.v3po.translate.write.WriterRegistry; import java.util.LinkedList; @@ -40,8 +40,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Simple writer registry able to perform and aggregated read (ROOT write) on top of all provided writers. Also able to - * delegate a specific read to one of the delegate writers. + * Simple writer registry able to perform and aggregated write (ROOT write) on top of all provided writers. Also able to + * delegate a specific write to one of the delegate writers. * * This could serve as a utility to hold & hide all available writers in upper layers. */ @@ -82,7 +82,7 @@ public final class DelegatingWriterRegistry implements WriterRegistry { public void update(@Nonnull final InstanceIdentifier id, @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter, - @Nonnull final WriteContext ctx) throws TranslationException { + @Nonnull final WriteContext ctx) throws WriteFailedException { final InstanceIdentifier.PathArgument first = checkNotNull( Iterables.getFirst(id.getPathArguments(), null), "Empty id"); final Writer writer = rootWriters.get(first.getType()); @@ -94,7 +94,7 @@ public final class DelegatingWriterRegistry implements WriterRegistry { @Override public void update(@Nonnull final Map, DataObject> nodesBefore, @Nonnull final Map, DataObject> nodesAfter, - @Nonnull final WriteContext ctx) throws TranslationException { + @Nonnull final WriteContext ctx) throws WriteFailedException { checkAllWritersPresent(nodesBefore); checkAllWritersPresent(nodesAfter); diff --git a/v3po/translate-utils/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/translate/utils/rev160406/DelegatingWriterRegistryModule.java b/v3po/translate-utils/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/translate/utils/rev160406/DelegatingWriterRegistryModule.java index a629a294f..72ec87691 100644 --- a/v3po/translate-utils/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/translate/utils/rev160406/DelegatingWriterRegistryModule.java +++ b/v3po/translate-utils/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/translate/utils/rev160406/DelegatingWriterRegistryModule.java @@ -5,6 +5,7 @@ import com.google.common.collect.Lists; import io.fd.honeycomb.v3po.translate.TranslationException; import io.fd.honeycomb.v3po.translate.util.write.DelegatingWriterRegistry; import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import io.fd.honeycomb.v3po.translate.write.Writer; import io.fd.honeycomb.v3po.translate.write.WriterRegistry; import java.util.List; @@ -63,7 +64,7 @@ public class DelegatingWriterRegistryModule extends org.opendaylight.yang.gen.v1 public void update( @Nonnull final InstanceIdentifier id, @Nullable final DataObject dataBefore, @Nullable final DataObject dataAfter, - @Nonnull final WriteContext ctx) throws TranslationException { + @Nonnull final WriteContext ctx) throws WriteFailedException { delegatingWriterRegistry.update(id, dataBefore, dataAfter, ctx); } diff --git a/v3po/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/DelegatingWriterRegistryTest.java b/v3po/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/DelegatingWriterRegistryTest.java index e201890b5..f51e49db5 100644 --- a/v3po/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/DelegatingWriterRegistryTest.java +++ b/v3po/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/DelegatingWriterRegistryTest.java @@ -24,9 +24,9 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import io.fd.honeycomb.v3po.translate.TranslationException; import io.fd.honeycomb.v3po.translate.util.write.DelegatingWriterRegistry; import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import io.fd.honeycomb.v3po.translate.write.Writer; import io.fd.honeycomb.v3po.translate.write.WriterRegistry; import java.util.ArrayList; @@ -117,8 +117,8 @@ public class DelegatingWriterRegistryTest { final DataObject dataAfter2 = mockDataObject("VppState after", VppState.class); // Fail on update - Mockito.doThrow(new TranslationException("vpp failed")).when(vppStateWriter) - .update(vppStateId, dataBefore2, dataAfter2, ctx); + Mockito.doThrow(new WriteFailedException(InstanceIdentifier.create(Vpp.class), "vpp failed")) + .when(vppStateWriter).update(vppStateId, dataBefore2, dataAfter2, ctx); // Run the test try { @@ -154,11 +154,11 @@ public class DelegatingWriterRegistryTest { final DataObject dataAfter3 = mockDataObject("Interfaces after", Interfaces.class); // Fail on the third update - doThrow(new TranslationException("vpp failed")).when(interfacesWriter) + doThrow(new WriteFailedException(InstanceIdentifier.create(Vpp.class), "vpp failed")).when(interfacesWriter) .update(interfaceId, dataBefore3, dataAfter3, ctx); // Fail on the second revert - doThrow(new TranslationException("vpp failed again")).when(writer) + doThrow(new WriteFailedException(InstanceIdentifier.create(Vpp.class), "vpp failed")).when(writer) .update(vppId, dataAfter1, dataBefore1, ctx); // Run the test diff --git a/v3po/v3po2vpp/src/main/config/default-config.xml b/v3po/v3po2vpp/src/main/config/default-config.xml index 1a1e6a8f5..89c3c47a2 100644 --- a/v3po/v3po2vpp/src/main/config/default-config.xml +++ b/v3po/v3po2vpp/src/main/config/default-config.xml @@ -52,6 +52,15 @@ + + prefix:interfaces-honeycomb-writer + interfaces-honeycomb-writer + + prefix:vpp-japi + vpp-japi + + + prefix:delegating-reader-registry read-registry @@ -64,6 +73,7 @@ interfaces-state-honeycomb-reader + prefix:delegating-writer-registry write-registry @@ -71,8 +81,13 @@ prefix:honeycomb-writer vpp-honeycomb-writer + + prefix:honeycomb-writer + interfaces-honeycomb-writer + + prefix:honeycomb-reader @@ -93,6 +108,11 @@ /modules/module[type='vpp-honeycomb-writer'][name='vpp-honeycomb-writer'] + + interfaces-honeycomb-writer + /modules/module[type='interfaces-honeycomb-writer'][name='interfaces-honeycomb-writer'] + + diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java new file mode 100644 index 000000000..69ff63137 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java @@ -0,0 +1,70 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Ethernet; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EthernetCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class); + + public EthernetCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getEthernet()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataAfter, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataBefore, @Nonnull final Ethernet dataAfter, + @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ethernet dataBefore, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration delete {}", id); + + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java new file mode 100644 index 000000000..6b91e2e0a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java @@ -0,0 +1,72 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import java.util.List; +import javax.annotation.Nonnull; +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.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.vppjapi.vppApi; + +/** + * Ietf interface write customizer that only caches interface objects for child writers + */ +public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterCustomizer { + + public static final String IFC_AFTER_CTX = InterfaceCustomizer.class.toString() + "ifcAfter"; + public static final String IFC_BEFORE_CTX = InterfaceCustomizer.class.toString() + "ifcBefore"; + + public InterfaceCustomizer(final vppApi vppApi) { + super(vppApi); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataAfter, + @Nonnull final Context writeContext) { + writeContext.put(IFC_AFTER_CTX, dataAfter); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataBefore, + @Nonnull final Interface dataAfter, + @Nonnull final Context writeContext) { + writeContext.put(IFC_BEFORE_CTX, dataBefore); + writeContext.put(IFC_AFTER_CTX, dataAfter); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface dataBefore, + @Nonnull final Context writeContext) { + writeContext.put(IFC_BEFORE_CTX, dataBefore); + } + + @Nonnull + @Override + public List extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return ((Interfaces) parentData).getInterface(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java new file mode 100644 index 000000000..e596f8fbf --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java @@ -0,0 +1,179 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.Interconnection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.XconnectBased; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); + + public L2Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getL2()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + final int swIfc = getSwIfc(ifc); + try { + setL2(id, swIfc, ifc, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Write of L2 failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataBefore, + @Nonnull final L2 dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + final int swIfc = getSwIfc(ifcBefore); + // TODO handle update properly (if possible) + try { + setL2(id, swIfc, ifcAfter, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of L2 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + private int getSwIfc(final Interface ifcBefore) { + int swIfcIndex = getVppApi().swIfIndexFromName(ifcBefore.getName()); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", ifcBefore.getName()); + return swIfcIndex; + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + final int swIfc = getSwIfc(ifcBefore); + // TODO implement delete (if possible) + } + + private void setL2(final InstanceIdentifier id, final int swIfIndex, final Interface ifc, final L2 vppL2) + throws VppApiInvocationException, WriteFailedException { + LOG.debug("Setting L2 for interface: %s", ifc.getName()); + // Nothing besides interconnection here + setInterconnection(id, swIfIndex, ifc, vppL2); + } + + private void setInterconnection(final InstanceIdentifier id, final int swIfIndex, final Interface ifc, + final L2 vppL2) + throws VppApiInvocationException, WriteFailedException { + Interconnection ic = vppL2.getInterconnection(); + if (ic instanceof XconnectBased) { + setXconnectBasedL2(swIfIndex, ifc, (XconnectBased) ic); + } else if (ic instanceof BridgeBased) { + setBridgeBasedL2(swIfIndex, ifc, (BridgeBased) ic); + } else { + // FIXME how does choice extensibility work + // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject + // FIXME we might need a choice customizer + // THis choice is already from augment, so its probably not possible to augment augmented choice + LOG.error("Unable to handle Interconnection of type {}", ic.getClass()); + throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass()); + } + } + + private void setBridgeBasedL2(final int swIfIndex, final Interface ifc, final BridgeBased bb) + throws VppApiInvocationException { + + LOG.debug("Setting bridge based interconnection(bridge-domain=%s) for interface: %s", + bb.getBridgeDomain(), ifc.getName()); + + String bdName = bb.getBridgeDomain(); + int bdId = getVppApi().bridgeDomainIdFromName(bdName); + checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", + ifc.getName(), bdName); + + byte bvi = bb.isBridgedVirtualInterface() + ? (byte) 1 + : (byte) 0; + byte shg = bb.getSplitHorizonGroup().byteValue(); + + final int ctxId = getVppApi().swInterfaceSetL2Bridge(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + + if (rv < 0) { + LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifc.getName(), + bb); + throw new VppApiInvocationException("swInterfaceSetL2Bridge", ctxId, rv); + } else { + LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifc.getName(), + bb); + } + } + + private void setXconnectBasedL2(final int swIfIndex, final Interface ifc, final XconnectBased ic) + throws VppApiInvocationException { + + String outSwIfName = ic.getXconnectOutgoingInterface(); + LOG.debug("Setting xconnect based interconnection(outgoing ifc=%s) for interface: %s", outSwIfName, + ifc.getName()); + + int outSwIfIndex = getVppApi().swIfIndexFromName(outSwIfName); + checkArgument(outSwIfIndex > 0, + "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", + ifc.getName(), outSwIfIndex); + + int ctxId = getVppApi().swInterfaceSetL2Xconnect(swIfIndex, outSwIfIndex, (byte) 1 /* enable */); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + + if (rv < 0) { + LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", + ifc.getName(), ic); + throw new VppApiInvocationException("swInterfaceSetL2Xconnect", ctxId, rv); + } else { + LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifc.getName(), + ic); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java new file mode 100644 index 000000000..8d930d80c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java @@ -0,0 +1,115 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class); + + public RoutingCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getRouting()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException.CreateFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + try { + setRouting(ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Routing failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataBefore, @Nonnull final Routing dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + try { + // TODO handle updates properly + setRouting(ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Routing failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Routing dataBefore, @Nonnull final Context writeContext) { + // TODO implement delete + } + + private void setRouting(final String name, final Routing rt) throws VppApiInvocationException { + final int swIfc = getSwIfc(name); + LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt); + + int vrfId = (rt != null) + ? rt.getVrfId().intValue() + : 0; + + if (vrfId != 0) { + final int ctxId = getVppApi().swInterfaceSetTable(swIfc, (byte) 0, /* isIpv6 */ vrfId); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.debug("Failed to set routing for interface: {}, {}, vxlan: {}", name, swIfc, rt); + throw new VppApiInvocationException("swInterfaceSetTable", ctxId, rv); + } else { + LOG.debug("Routing set successfully for interface: {}, {}, routing: {}", name, swIfc, rt); + } + } + } + + private int getSwIfc(final String name) { + int swIfcIndex = getVppApi().swIfIndexFromName(name); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); + return swIfcIndex; + } + +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java new file mode 100644 index 000000000..3ea3f9743 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VppInterfaceCustomizer.java @@ -0,0 +1,210 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VppInterfaceCustomizer extends VppApiCustomizer + implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(VppInterfaceCustomizer.class); + + public VppInterfaceCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract( + @Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface) parentData).getAugmentation(VppInterfaceAugmentation.class)); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + setInterface(id, ifc, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of VppInterfaceAugment failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataBefore, + @Nonnull final VppInterfaceAugmentation dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + updateInterface(id, ifc, dataBefore, dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of VppInterfaceAugment failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final VppInterfaceAugmentation dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + LOG.info("Deleting interface: {}, type: {}", ifcBefore.getName(), ifcBefore.getType().getSimpleName()); + + if (ifcBefore.getType().isAssignableFrom(EthernetCsmacd.class)) { + LOG.error("Interface {}, type: {} cannot be deleted", + ifcBefore.getName(), ifcBefore.getType().getSimpleName()); + + /* FIXME: Add additional interface types here. + * + * } else if (swIf.getType().isAssignableFrom(*.class)) { + */ + + } + } + + + private void updateInterface(final InstanceIdentifier id, final Interface swIf, + final VppInterfaceAugmentation dataBefore, + final VppInterfaceAugmentation dataAfter) throws VppApiInvocationException { + LOG.info("Updating interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); + LOG.debug("Updating interface {}", swIf); + + Class ifType = checkNotNull(swIf.getType(), "Interface type missing for %s", swIf); + String swIfName = swIf.getName(); + int swIfIndex = getVppApi().swIfIndexFromName(swIfName); + checkArgument(swIfIndex != -1, "Updating non-existing vpp interface: %s", swIfName); + + // TODO handle updates properly + + if (VxlanTunnel.class.isAssignableFrom(ifType)) { + updateVxlanTunnelInterface(swIf); + } else if (EthernetCsmacd.class.isAssignableFrom(ifType)) { + updateEthernetCsmacdInterface(swIf, swIfName, swIfIndex); + } + } + + + private void setInterface(final InstanceIdentifier id, final Interface swIf, + final VppInterfaceAugmentation dataAfter) + throws VppApiInvocationException, WriteFailedException { + LOG.info("Setting interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); + LOG.debug("Setting interface {}", swIf); + + Class ifType = checkNotNull(swIf.getType(), "Interface type missing for %s", swIf); + String swIfName = swIf.getName(); + int swIfIndex = getVppApi().swIfIndexFromName(swIfName); + checkArgument(swIfIndex == -1, "Creating already-existing vpp interface: %s", swIfName); + + if (VxlanTunnel.class.isAssignableFrom(ifType)) { + createVxlanTunnelInterface(swIf, swIfName); + } else if (EthernetCsmacd.class.isAssignableFrom(ifType)) { + createEthernetCsmacdInterface(id, swIfName, dataAfter); + } + } + + private void createVxlanTunnelInterface(final Interface swIf, final String swIfName) + throws VppApiInvocationException { + LOG.debug("Creating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + + // FIXME, Vxlan child writer needs to be handled before this is + int newSwIfIndex = getVppApi().swIfIndexFromName(swIfName); + + setInterfaceFlags(swIfName, newSwIfIndex, swIf.isEnabled() + ? (byte) 1 + : (byte) 0); + setDescription(swIf); + } + + private void updateVxlanTunnelInterface(final Interface swIf) { + LOG.debug("Updating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + + // TODO handle + } + + private void createEthernetCsmacdInterface(final InstanceIdentifier id, + final String swIfName, final VppInterfaceAugmentation dataAfter) throws WriteFailedException { + LOG.warn("Unable to create interface: {}, type: {}", swIfName, EthernetCsmacd.class); + throw new WriteFailedException.CreateFailedException(id, dataAfter); + } + + private void updateEthernetCsmacdInterface(final Interface swIf, + final String swIfName, final int swIfIndex) + throws VppApiInvocationException { + LOG.debug("Updating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); + byte enabled = swIf.isEnabled() + ? (byte) 1 + : (byte) 0; + setInterfaceFlags(swIfName, swIfIndex, enabled); + setDescription(swIf); + } + + private void setInterfaceFlags(final String swIfName, final int swIfIndex, final byte enabled) + throws VppApiInvocationException { + int ctxId = getVppApi().swInterfaceSetFlags(swIfIndex, enabled, enabled, (byte) 0 /* deleted */); + + LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, + enabled, ctxId); + + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.warn("Failed to update interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, + enabled, ctxId); + throw new VppApiInvocationException("swInterfaceSetFlags", ctxId, rv); + } else { + LOG.debug("Interface flags updated successfully for: {}, index: {}, enabled: {}, ctxId: {}", + swIfName, swIfIndex, enabled, ctxId); + } + } + + private void setDescription(final Interface swIf) { + if (swIf.getDescription() != null) { + getVppApi().setInterfaceDescription(swIf.getName(), swIf.getDescription()); + } else { + getVppApi().setInterfaceDescription(swIf.getName(), ""); + } + } + +} + diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java new file mode 100644 index 000000000..2b2774ece --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java @@ -0,0 +1,112 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); + + + public VxlanCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getVxlan()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException.CreateFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + try { + createVxlanTunnel(ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Write of Vxlan failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataBefore, + @Nonnull final Vxlan dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException.UpdateFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle update in a better way + try { + createVxlanTunnel(ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of L2 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Vxlan dataBefore, + @Nonnull final Context writeContext) { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle delete + } + + private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { + Ipv4Address srcAddress = vxlan.getSrc(); + Ipv4Address dstAddress = vxlan.getDst(); + + int srcAddr = V3poUtils.parseIp(srcAddress.getValue()); + int dstAddr = V3poUtils.parseIp(dstAddress.getValue()); + int encapVrfId = vxlan.getEncapVrfId().intValue(); + int vni = vxlan.getVni().getValue().intValue(); + + LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan); + int ctxId = getVppApi().vxlanAddDelTunnel((byte) 1 /* is add */, srcAddr, dstAddr, encapVrfId, -1, vni); + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.debug("Failed to set vxlan tunnel for interface: {}, vxlan: {}", swIfName, vxlan); + throw new VppApiInvocationException("vxlanAddDelTunnel", ctxId, rv); + } else { + LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan); + // FIXME avoid this dump just to fill cache in vpp-japi + // refresh interfaces to be able to get ifIndex + getVppApi().swInterfaceDump((byte) 1, V3poUtils.IFC_TYPES.inverse().get(VxlanTunnel.class).getBytes()); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java new file mode 100644 index 000000000..9f3584908 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java @@ -0,0 +1,60 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces.ip; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +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.ip.rev140616.Interface1; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Interface1Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + public Interface1Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface) parentData).getAugmentation(Interface1.class)); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataAfter, @Nonnull final Context writeContext) { + + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataBefore, @Nonnull final Interface1 dataAfter, + @Nonnull final Context writeContext) { + + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Interface1 dataBefore, @Nonnull final Context writeContext) { + + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java new file mode 100644 index 000000000..08974fe68 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java @@ -0,0 +1,153 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces.ip; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.InterfaceCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +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.ip.rev140616.Interface1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.Subnet; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(Ipv4Customizer.class); + + public Ipv4Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface1) parentData).getIpv4()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataAfter, @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifc = (Interface) writeContext.get(InterfaceCustomizer.IFC_AFTER_CTX); + + try { + setIpv4(id, ifc.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Create of Ipv4 failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataBefore, @Nonnull final Ipv4 dataAfter, + @Nonnull final Context writeContext) + throws WriteFailedException { + final Interface ifcBefore = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + final Interface ifcAfter = (Interface) writeContext.get(InterfaceCustomizer.IFC_BEFORE_CTX); + + // TODO handle update in a better way + try { + setIpv4(id, ifcAfter.getName(), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Update of Ipv4 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv4 dataBefore, @Nonnull final Context writeContext) { + // TODO implement delete + } + + private void setIpv4(final InstanceIdentifier id, final String name, final Ipv4 ipv4) + throws WriteFailedException, VppApiInvocationException { + final int swIfc = getSwIfc(name); + + for (Address ipv4Addr : ipv4.getAddress()) { + Subnet subnet = ipv4Addr.getSubnet(); + + if (subnet instanceof PrefixLength) { + setPrefixLengthSubnet(name, swIfc, ipv4Addr, (PrefixLength) subnet); + } else if (subnet instanceof Netmask) { + setNetmaskSubnet(); + } else { + // FIXME how does choice extensibility work + // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject + // FIXME we might need a choice customizer + // THis choice is already from augment, so its probably not possible to augment augmented choice + LOG.error("Unable to handle subnet of type {}", subnet.getClass()); + throw new WriteFailedException(id, "Unable to handle subnet of type " + subnet.getClass()); + } + } + } + + private void setNetmaskSubnet() { + // FIXME + throw new UnsupportedOperationException("Unimplemented"); + } + + private void setPrefixLengthSubnet(final String name, final int swIfc, final Address ipv4Addr, + final PrefixLength subnet) throws VppApiInvocationException { + Short plen = subnet.getPrefixLength(); + LOG.debug("Setting Subnet(prefix-length) for interface: {}, {}. Subnet: {}, Ipv4: {}", name, swIfc, subnet, + ipv4Addr); + + byte[] addr = V3poUtils.ipv4AddressNoZoneToArray(ipv4Addr.getIp()); + + checkArgument(plen > 0, "Invalid length"); + checkNotNull(addr, "Null address"); + + final int ctxId = getVppApi().swInterfaceAddDelAddress(swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, + (byte) 0 /* delAll */, plen.byteValue(), addr); + + final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + if (rv < 0) { + LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc, + subnet, ipv4Addr); + throw new VppApiInvocationException("swInterfaceAddDelAddress", ctxId, rv); + } else { + LOG.debug("Subnet(prefix-length) set successfully for interface: {}, {}, Subnet: {}, Ipv4: {}", name, + swIfc, subnet, ipv4Addr); + } + } + + + private int getSwIfc(final String name) { + int swIfcIndex = getVppApi().swIfIndexFromName(name); + checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); + return swIfcIndex; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java new file mode 100644 index 000000000..3798f891a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java @@ -0,0 +1,66 @@ +/* + * 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.honeycomb.v3po.translate.v3po.interfaces.ip; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Ipv6Customizer extends VppApiCustomizer implements ChildWriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(Ipv6Customizer.class); + + public Ipv6Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + super(vppApi); + } + + @Nonnull + @Override + public Optional extract(@Nonnull final InstanceIdentifier currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((Interface1) parentData).getIpv6()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataAfter, @Nonnull final Context writeContext) { + // TODO + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataBefore, @Nonnull final Ipv6 dataAfter, + @Nonnull final Context writeContext) { + LOG.warn("Unsupported, ignoring configuration {}", dataAfter); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ipv6 dataBefore, @Nonnull final Context writeContext) { + LOG.warn("Unsupported, ignoring configuration delete {}", id); + // TODO + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java new file mode 100644 index 000000000..18a8103cc --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java @@ -0,0 +1,78 @@ +/* + * 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.honeycomb.v3po.translate.v3po.utils; + +import com.google.common.base.Splitter; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.SoftwareLoopback; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; +import org.openvpp.vppjapi.vppApi; + +public final class V3poUtils { + + // TODO move to vpp-translate-utils + + public static final int RESPONSE_NOT_READY = -77; + public static final int RELEASE = 1; + public static final Splitter DOT_SPLITTER = Splitter.on('.'); + public static final BiMap> IFC_TYPES = HashBiMap.create(); + static { + V3poUtils.IFC_TYPES.put("vxlan", VxlanTunnel.class); + V3poUtils.IFC_TYPES.put("lo", SoftwareLoopback.class); + V3poUtils.IFC_TYPES.put("Ether", EthernetCsmacd.class); + // TODO missing types below +// V3poUtils.IFC_TYPES.put("l2tpv3_tunnel", EthernetCsmacd.class); +// V3poUtils.IFC_TYPES.put("tap", EthernetCsmacd.class); + } + + private V3poUtils() {} + + public static int waitForResponse(final int ctxId, final vppApi vppApi) { + int rv; + while ((rv = vppApi.getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) { + // TODO limit attempts + } + return rv; + } + + public static int parseIp(final String address) { + int result = 0; + + // iterate over each octet + for (String part : DOT_SPLITTER.split(address)) { + // shift the previously parsed bits over by 1 byte + result = result << 8; + // set the low order bits to the current octet + result |= Integer.parseInt(part); + } + return result; + } + + public static byte[] ipv4AddressNoZoneToArray(final Ipv4AddressNoZone ipv4Addr) { + byte[] retval = new byte[4]; + String[] dots = ipv4Addr.getValue().split("\\."); + + for (int d = 3; d >= 0; d--) { + retval[d] = (byte) (Short.parseShort(dots[3 - d]) & 0xff); + } + return retval; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java index ffbc95beb..c69f2ef0a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java @@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkState; import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -41,8 +42,6 @@ public class BridgeDomainCustomizer private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); private static final byte ADD_OR_UPDATE_BD = (byte) 1; - private static final int RESPONSE_NOT_READY = -77; - private static final int RELEASE = 1; public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi api) { super(api); @@ -55,14 +54,6 @@ public class BridgeDomainCustomizer return ((BridgeDomains) parentData).getBridgeDomain(); } - private int waitForResponse(final int ctxId) { - int rv; - while ((rv = getVppApi().getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) { - // TODO limit attempts - } - return rv; - } - private int addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) { byte flood = booleanToByte(bd.isFlood()); byte forward = booleanToByte(bd.isForward()); @@ -71,7 +62,7 @@ public class BridgeDomainCustomizer byte arpTerm = booleanToByte(bd.isArpTermination()); int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); - return waitForResponse(ctxId); + return V3poUtils.waitForResponse(ctxId, getVppApi()); } @Override @@ -111,7 +102,7 @@ public class BridgeDomainCustomizer (byte) 0 /* arpTerm */, (byte) 0 /* isAdd */); - int rv = waitForResponse(ctxId); + int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); checkState(rv >= 0, "Bridge domain delete failed. Return code: %s", rv); LOG.debug("Bridge domain {} deleted as {} successfully", bdName, bdId); diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java new file mode 100644 index 000000000..4710d9e1a --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModule.java @@ -0,0 +1,114 @@ +package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; + +import com.google.common.collect.Lists; +import io.fd.honeycomb.v3po.translate.impl.TraversalType; +import io.fd.honeycomb.v3po.translate.impl.write.CompositeChildWriter; +import io.fd.honeycomb.v3po.translate.impl.write.CompositeListWriter; +import io.fd.honeycomb.v3po.translate.impl.write.CompositeRootWriter; +import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.util.write.CloseableWriter; +import io.fd.honeycomb.v3po.translate.util.write.NoopWriterCustomizer; +import io.fd.honeycomb.v3po.translate.util.write.ReflexiveChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.EthernetCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.InterfaceCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.L2Customizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.RoutingCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.VppInterfaceCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.VxlanCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.ip.Ipv4Customizer; +import io.fd.honeycomb.v3po.translate.v3po.interfaces.ip.Ipv6Customizer; +import io.fd.honeycomb.v3po.translate.write.ChildWriter; +import java.util.ArrayList; +import java.util.List; +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.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Ethernet; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Routing; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.ChildOf; + +public class InterfacesHoneycombWriterModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesHoneycombWriterModule { + public InterfacesHoneycombWriterModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public InterfacesHoneycombWriterModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.InterfacesHoneycombWriterModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + + final List>> ifcAugmentations = Lists.newArrayList(); + ifcAugmentations.add(getVppIfcAugmentationWriter()); + + final ChildWriter interfaceWriter = new CompositeListWriter<>(Interface.class, + RWUtils.emptyChildWriterList(), + ifcAugmentations, + new InterfaceCustomizer(getVppJapiIfcDependency())); + + final List>> childWriters = new ArrayList<>(); + childWriters.add(interfaceWriter); + + // FIXME if we just return the root writer and cfg subsystem takes care to set it into reader registry, + // we loose the ordering information for root writers + // Or can we rely to the order in which readers are configured ? + return new CloseableWriter<>(new CompositeRootWriter<>(Interfaces.class, + childWriters, new NoopWriterCustomizer())); + } + + private ChildWriter> getInterface1AugmentationWriter() { + final ChildWriter ipv4Writer = new CompositeChildWriter<>(Ipv4.class, + new Ipv4Customizer(getVppJapiIfcDependency())); + final ChildWriter ipv6Writer = new CompositeChildWriter<>(Ipv6.class, + new Ipv6Customizer(getVppJapiIfcDependency())); + + final List>> interface1ChildWriters = Lists.newArrayList(); + interface1ChildWriters.add(ipv4Writer); + interface1ChildWriters.add(ipv6Writer); + + return new CompositeChildWriter<>(Interface1.class, + interface1ChildWriters, new ReflexiveChildWriterCustomizer()); + } + + private ChildWriter getVppIfcAugmentationWriter() { + + final ChildWriter ethernetWriter = new CompositeChildWriter<>(Ethernet.class, + new EthernetCustomizer(getVppJapiIfcDependency())); + + final ChildWriter routingWriter = new CompositeChildWriter<>(Routing.class, + new RoutingCustomizer(getVppJapiIfcDependency())); + + final ChildWriter vxlanWriter = new CompositeChildWriter<>(Vxlan.class, + new VxlanCustomizer(getVppJapiIfcDependency())); + + final ChildWriter l2Writer = new CompositeChildWriter<>(L2.class, + new L2Customizer(getVppJapiIfcDependency())); + + final List>> vppIfcChildWriters = Lists.newArrayList(); + // TODO what's the order here ? + vppIfcChildWriters.add(ethernetWriter); + vppIfcChildWriters.add(vxlanWriter); + vppIfcChildWriters.add(l2Writer); + vppIfcChildWriters.add(routingWriter); + + return new CompositeChildWriter<>(VppInterfaceAugmentation.class, + vppIfcChildWriters, + RWUtils.emptyAugWriterList(), + new VppInterfaceCustomizer(getVppJapiIfcDependency()), + // It's important that this customizer is handled in a postorder way, because you first have to handle child nodes + // e.g. Vxlan before setting other interface or vppInterfaceAugmentation leaves + TraversalType.POSTORDER); + } +} diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModuleFactory.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModuleFactory.java new file mode 100644 index 000000000..9332d3017 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesHoneycombWriterModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: v3po2vpp yang module local name: interfaces-honeycomb-writer +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Apr 08 13:28:05 CEST 2016 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; +public class InterfacesHoneycombWriterModuleFactory extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesHoneycombWriterModuleFactory { + +} diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java index 5b79ff0d3..aa72a29af 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/InterfacesStateHoneycombReaderModule.java @@ -1,14 +1,11 @@ package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; -import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.impl.read.CompositeChildReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeListReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeRootReader; import io.fd.honeycomb.v3po.translate.read.ChildReader; -import io.fd.honeycomb.v3po.translate.read.ReadContext; -import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.read.Reader; import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.util.read.CloseableReader; import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer; import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.VppInterfaceStateCustomizer; @@ -17,14 +14,9 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentation; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.openvpp.vppjapi.vppApi; -import javax.annotation.Nonnull; - public class InterfacesStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractInterfacesStateHoneycombReaderModule { public InterfacesStateHoneycombReaderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { super(identifier, dependencyResolver); @@ -53,44 +45,10 @@ public class InterfacesStateHoneycombReaderModule extends org.opendaylight.yang. RWUtils.singletonAugReaderList(vppInterfaceStateAugmentationChildReader), new InterfaceCustomizer(vppApi)); - return new CloseableReader(new CompositeRootReader<>( + return new CloseableReader<>(new CompositeRootReader<>( InterfacesState.class, RWUtils.singletonChildReaderList(interfaceReader), RWUtils.emptyAugReaderList(), new ReflexiveRootReaderCustomizer<>(InterfacesStateBuilder.class))); } - - - private static final class CloseableReader implements Reader, AutoCloseable { - - private CompositeRootReader compositeRootReader; - - public CloseableReader( - final CompositeRootReader compositeRootReader) { - this.compositeRootReader = compositeRootReader; - } - - @Nonnull - @Override - public Optional read(@Nonnull InstanceIdentifier id, - @Nonnull ReadContext ctx) throws ReadFailedException { - return compositeRootReader.read(id, ctx); - } - - @Nonnull - @Override - public InstanceIdentifier getManagedDataObjectType() { - return compositeRootReader.getManagedDataObjectType(); - } - - @Override - public String toString() { - return compositeRootReader.toString(); - } - - @Override - public void close() throws Exception { - //NOOP - } - } } diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppHoneycombWriterModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppHoneycombWriterModule.java index 5694bc139..a9eff593d 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppHoneycombWriterModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppHoneycombWriterModule.java @@ -1,27 +1,21 @@ package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; -import io.fd.honeycomb.v3po.translate.TranslationException; import io.fd.honeycomb.v3po.translate.impl.write.CompositeChildWriter; import io.fd.honeycomb.v3po.translate.impl.write.CompositeListWriter; import io.fd.honeycomb.v3po.translate.impl.write.CompositeRootWriter; import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.util.write.CloseableWriter; import io.fd.honeycomb.v3po.translate.util.write.NoopWriterCustomizer; import io.fd.honeycomb.v3po.translate.util.write.ReflexiveChildWriterCustomizer; import io.fd.honeycomb.v3po.translate.v3po.vpp.BridgeDomainCustomizer; import io.fd.honeycomb.v3po.translate.write.ChildWriter; -import io.fd.honeycomb.v3po.translate.write.WriteContext; -import io.fd.honeycomb.v3po.translate.write.Writer; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Vpp; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; import org.opendaylight.yangtools.yang.binding.ChildOf; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; public class VppHoneycombWriterModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractVppHoneycombWriterModule { public VppHoneycombWriterModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -51,46 +45,10 @@ public class VppHoneycombWriterModule extends org.opendaylight.yang.gen.v1.urn.h final List>> childWriters = new ArrayList<>(); childWriters.add(bridgeDomainsReader); - return new CloseableWriter(new CompositeRootWriter<>( + return new CloseableWriter<>(new CompositeRootWriter<>( Vpp.class, childWriters, new NoopWriterCustomizer())); } - // TODO move to translate-utils - private static final class CloseableWriter implements Writer, AutoCloseable { - - private CompositeRootWriter vppCompositeRootWriter; - - public CloseableWriter( - final CompositeRootWriter vppCompositeRootWriter) { - this.vppCompositeRootWriter = vppCompositeRootWriter; - } - - @Override - public void update( - @Nonnull final InstanceIdentifier id, - @Nullable final DataObject dataBefore, - @Nullable final DataObject dataAfter, - @Nonnull final WriteContext ctx) throws TranslationException { - vppCompositeRootWriter.update(id, dataBefore, dataAfter, ctx); - } - - @Nonnull - @Override - public InstanceIdentifier getManagedDataObjectType() { - return vppCompositeRootWriter.getManagedDataObjectType(); - } - - @Override - public String toString() { - return vppCompositeRootWriter.toString(); - } - - @Override - public void close() throws Exception { - - } - } - } diff --git a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppStateHoneycombReaderModule.java b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppStateHoneycombReaderModule.java index 8da7dad1c..0e1d48035 100644 --- a/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppStateHoneycombReaderModule.java +++ b/v3po/v3po2vpp/src/main/java/org/opendaylight/yang/gen/v1/urn/honeycomb/params/xml/ns/yang/v3po2vpp/rev160406/VppStateHoneycombReaderModule.java @@ -1,21 +1,17 @@ package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; -import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.impl.read.CompositeChildReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeListReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeRootReader; import io.fd.honeycomb.v3po.translate.read.ChildReader; -import io.fd.honeycomb.v3po.translate.read.ReadContext; -import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.read.Reader; import io.fd.honeycomb.v3po.translate.util.RWUtils; +import io.fd.honeycomb.v3po.translate.util.read.CloseableReader; import io.fd.honeycomb.v3po.translate.util.read.ReflexiveChildReaderCustomizer; import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.vppstate.BridgeDomainCustomizer; import io.fd.honeycomb.v3po.translate.v3po.vppstate.VersionCustomizer; import java.util.ArrayList; import java.util.List; -import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomains; @@ -25,8 +21,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomainBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomainKey; import org.opendaylight.yangtools.yang.binding.ChildOf; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.openvpp.vppjapi.vppApi; public class VppStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractVppStateHoneycombReaderModule { @@ -61,44 +55,11 @@ public class VppStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1. childVppReaders.add(versionReader); childVppReaders.add(bridgeDomainsReader); - return new CloseableReader(new CompositeRootReader<>( + return new CloseableReader<>(new CompositeRootReader<>( VppState.class, childVppReaders, RWUtils.emptyAugReaderList(), new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class))); } - // TODO move to utils - private static final class CloseableReader implements Reader, AutoCloseable { - - private CompositeRootReader vppStateVppStateBuilderCompositeRootReader; - - public CloseableReader( - final CompositeRootReader vppStateVppStateBuilderCompositeRootReader) { - this.vppStateVppStateBuilderCompositeRootReader = vppStateVppStateBuilderCompositeRootReader; - } - - @Nonnull - @Override - public Optional read(@Nonnull final InstanceIdentifier id, - @Nonnull final ReadContext ctx) throws ReadFailedException { - return vppStateVppStateBuilderCompositeRootReader.read(id, ctx); - } - - @Nonnull - @Override - public InstanceIdentifier getManagedDataObjectType() { - return vppStateVppStateBuilderCompositeRootReader.getManagedDataObjectType(); - } - - @Override - public String toString() { - return vppStateVppStateBuilderCompositeRootReader.toString(); - } - - @Override - public void close() throws Exception { - //NOOP - } - } } diff --git a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang index 9d3199970..286feb987 100644 --- a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang +++ b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang @@ -79,4 +79,25 @@ module v3po2vpp { } } + identity interfaces-honeycomb-writer { + base config:module-type; + config:provided-service tapi:honeycomb-writer; + } + + augment "/config:modules/config:module/config:configuration" { + case interfaces-honeycomb-writer { + when "/config:modules/config:module/config:type = 'interfaces-honeycomb-writer'"; + + container vpp-japi-ifc { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vjc:vpp-japi; + } + } + } + + } + } + } \ No newline at end of file diff --git a/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiCustomizer.java b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiCustomizer.java index de4602456..c9351cdc4 100644 --- a/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiCustomizer.java +++ b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiCustomizer.java @@ -26,7 +26,7 @@ public abstract class VppApiCustomizer { private final org.openvpp.vppjapi.vppApi vppApi; - protected VppApiCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public VppApiCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { this.vppApi = vppApi; } diff --git a/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationException.java b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationException.java new file mode 100644 index 000000000..4c50304c6 --- /dev/null +++ b/v3po/vpp-translate-utils/src/main/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationException.java @@ -0,0 +1,75 @@ +/* + * 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.honeycomb.v3po.translate.v3po.util; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import javax.annotation.Nonnull; + +/** + * Thrown when Vpp jAPI method invocation failed. + */ +@Beta +public class VppApiInvocationException extends Exception { + private final String methodName; + private final int ctxId; + private final int errorCode; + + /** + * Constructs an VppApiInvocationFailedException with the specified api method name and error code. + * + * @param methodName method name that failed to invoke + * @param ctxId api request context identifier + * @param errorCode negative error code value associated with this failure + * @throws NullPointerException if apiMethodName is null + * @throws IllegalArgumentException if errorCode is nonnegative + */ + public VppApiInvocationException(@Nonnull final String methodName, final int ctxId, final int errorCode) { + super(String.format("vppApi.%s failed with error code: %d (ctxId=%d) ", methodName, errorCode, ctxId)); + this.methodName = Preconditions.checkNotNull(methodName, "apiMethodName is null!"); + this.ctxId = ctxId; + Preconditions.checkArgument(errorCode < 0); + this.errorCode = errorCode; + } + + /** + * Returns method name that failed to invoke. + * + * @return method name + */ + public String getMethodName() { + return methodName; + } + + /** + * Returns api request context identifier. + * + * @return value of context identifier + */ + public int getCtxId() { + return ctxId; + } + + /** + * Returns the error code associated with this failure. + * + * @return a negative integer error code + */ + public int getErrorCode() { + return errorCode; + } +} diff --git a/v3po/vpp-translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationExceptionTest.java b/v3po/vpp-translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationExceptionTest.java new file mode 100644 index 000000000..184beceef --- /dev/null +++ b/v3po/vpp-translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/v3po/util/VppApiInvocationExceptionTest.java @@ -0,0 +1,44 @@ +/* + * 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.honeycomb.v3po.translate.v3po.util; + +import java.util.Random; +import org.junit.Assert; +import org.junit.Test; + +public class VppApiInvocationExceptionTest { + + @Test + public void testInstantiation() { + final String apiMethodName = "methodName"; + final int ctxId = 1; + final int code = -1; + VppApiInvocationException e = new VppApiInvocationException(apiMethodName, ctxId, code); + Assert.assertEquals(apiMethodName, e.getMethodName()); + Assert.assertEquals(ctxId, e.getCtxId()); + Assert.assertEquals(code, e.getErrorCode()); + Assert.assertTrue(e.getMessage().contains(apiMethodName)); + Assert.assertTrue(e.getMessage().contains(String.valueOf(code))); + Assert.assertTrue(e.getMessage().contains(String.valueOf(ctxId))); + } + + @Test(expected = IllegalArgumentException.class) + public void testInstantiationFailed() { + final int code = new Random().nextInt(Integer.MAX_VALUE); + VppApiInvocationException e = new VppApiInvocationException("apiMethodName", 1, code); + } +} -- cgit 1.2.3-korg