From f187ae2f6a363616442a8968db1450977ce69078 Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Wed, 4 May 2016 10:17:39 +0200 Subject: HONEYCOMB-10: Porting v3po2vpp to the new Java API Change-Id: Ic7166b0f578442165595aa44a587ebbc5db0e75c Signed-off-by: Marek Gradzki Signed-off-by: Maros Marsalek --- v3po/v3po2vpp/pom.xml | 17 +- v3po/v3po2vpp/src/main/config/default-config.xml | 89 ++++++-- .../v3po/interfaces/EthernetCustomizer.java | 7 +- .../v3po/interfaces/InterfaceCustomizer.java | 59 +++-- .../translate/v3po/interfaces/L2Customizer.java | 76 +++++-- .../v3po/interfaces/RoutingCustomizer.java | 37 ++-- .../translate/v3po/interfaces/VxlanCustomizer.java | 59 +++-- .../v3po/interfaces/ip/Interface1Customizer.java | 7 +- .../v3po/interfaces/ip/Ipv4Customizer.java | 46 ++-- .../v3po/interfaces/ip/Ipv6Customizer.java | 7 +- .../v3po/interfacesstate/InterfaceCustomizer.java | 95 ++++---- .../v3po/interfacesstate/InterfaceUtils.java | 73 ++++--- .../VppInterfaceStateCustomizer.java | 30 +-- .../v3po/translate/v3po/utils/V3poUtils.java | 55 ++--- .../translate/v3po/vpp/BridgeDomainCustomizer.java | 140 +++++++----- .../v3po/vppstate/BridgeDomainCustomizer.java | 195 +++++++++++------ .../translate/v3po/vppstate/VersionCustomizer.java | 33 ++- .../rev160406/InterfacesHoneycombWriterModule.java | 24 +-- .../InterfacesStateHoneycombReaderModule.java | 41 ++-- .../rev160406/VppHoneycombWriterModule.java | 10 +- .../rev160406/VppStateHoneycombReaderModule.java | 10 +- v3po/v3po2vpp/src/main/yang/v3po2vpp.yang | 89 +++++++- .../interfacesstate/InterfaceCustomizerTest.java | 200 ++++++++++------- .../v3po/test/ChildReaderCustomizerTest.java | 49 +++++ .../v3po/test/ListReaderCustomizerTest.java | 52 +++++ .../v3po/test/RootReaderCustomizerTest.java | 84 ++++++++ .../v3po/translate/v3po/utils/V3poUtilsTest.java | 32 +-- .../v3po/vpp/BridgeDomainCustomizerTest.java | 205 +++++++++--------- .../honeycomb/v3po/translate/v3po/vpp/VppTest.java | 185 ++++++++++------ .../v3po/translate/v3po/vpp/VppUtils.java | 9 +- .../v3po/vppstate/BridgeDomainCustomizerTest.java | 59 +++++ .../v3po/vppstate/VersionCustomizerTest.java | 73 +++++++ .../v3po/translate/v3po/vppstate/VppStateTest.java | 238 +++++++++++---------- .../translate/v3po/vppstate/VppStateTestUtils.java | 82 +++++++ .../translate/v3po/vppstate/VppStateUtils.java | 77 ------- 35 files changed, 1635 insertions(+), 909 deletions(-) create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ChildReaderCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ListReaderCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/RootReaderCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizerTest.java create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTestUtils.java delete mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateUtils.java (limited to 'v3po/v3po2vpp') diff --git a/v3po/v3po2vpp/pom.xml b/v3po/v3po2vpp/pom.xml index 6b57ca201..9fbaf0b3e 100644 --- a/v3po/v3po2vpp/pom.xml +++ b/v3po/v3po2vpp/pom.xml @@ -56,12 +56,12 @@ ${project.groupId} - vpp-japi-cfg + vpp-jvpp-cfg ${project.version} io.fd.vpp - vppjapi + jvpp 1.0.0-SNAPSHOT @@ -76,19 +76,6 @@ mockito-all test - - - org.powermock - powermock-api-mockito - 1.5.6 - test - - - org.powermock - powermock-module-junit4 - 1.5.6 - test - org.skinny-framework skinny-logback diff --git a/v3po/v3po2vpp/src/main/config/default-config.xml b/v3po/v3po2vpp/src/main/config/default-config.xml index 89c3c47a2..cd736eddc 100644 --- a/v3po/v3po2vpp/src/main/config/default-config.xml +++ b/v3po/v3po2vpp/src/main/config/default-config.xml @@ -19,46 +19,90 @@ - urn:honeycomb:params:xml:ns:yang:vpp:japi:cfg?module=vpp-japi-cfg&revision=2016-04-06 + urn:honeycomb:params:xml:ns:yang:vpp:jvpp:cfg?module=vpp-jvpp-cfg&revision=2016-04-06 urn:honeycomb:params:xml:ns:yang:v3po2vpp?module=v3po2vpp&revision=2016-04-06 + urn:honeycomb:params:xml:ns:yang:vpp:util?module=vpp-util&revision=2016-04-06 + + prefix:naming-context-impl + interface-context + interface- + + + prefix:naming-context-impl + bridge-domain-context + bridge-domain- + + prefix:vpp-state-honeycomb-reader vpp-state-honeycomb-reader - - prefix:vpp-japi - vpp-japi - + + prefix:vpp-jvpp + vpp-jvpp + + + prefix:naming-context + interface-context + + + prefix:naming-context + bridge-domain-context + prefix:interfaces-state-honeycomb-reader interfaces-state-honeycomb-reader - - prefix:vpp-japi - vpp-japi - + + prefix:vpp-jvpp + vpp-jvpp + + + prefix:naming-context + interface-context + + + prefix:naming-context + bridge-domain-context + prefix:vpp-honeycomb-writer vpp-honeycomb-writer - - prefix:vpp-japi - vpp-japi - + + prefix:vpp-jvpp + vpp-jvpp + + + prefix:naming-context + interface-context + + + prefix:naming-context + bridge-domain-context + prefix:interfaces-honeycomb-writer interfaces-honeycomb-writer - - prefix:vpp-japi - vpp-japi - + + prefix:vpp-jvpp + vpp-jvpp + + + prefix:naming-context + interface-context + + + prefix:naming-context + bridge-domain-context + @@ -101,6 +145,17 @@ /modules/module[type='interfaces-state-honeycomb-reader'][name='interfaces-state-honeycomb-reader'] + + prefix:naming-context + + interface-context + /modules/module[type='naming-context-impl'][name='interface-context'] + + + bridge-domain-context + /modules/module[type='naming-context-impl'][name='bridge-domain-context'] + + prefix: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 index 69ff63137..cdcea45f3 100644 --- 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 @@ -19,20 +19,21 @@ 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 io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class EthernetCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class EthernetCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class); - public EthernetCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public EthernetCustomizer(final FutureJVpp vppApi) { super(vppApi); } 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 index 30600d81e..5d5a6c08b 100644 --- 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 @@ -18,30 +18,36 @@ 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 io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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 java.util.List; +import java.util.concurrent.CompletionStage; 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; +import org.openvpp.jvpp.dto.SwInterfaceSetFlags; +import org.openvpp.jvpp.dto.SwInterfaceSetFlagsReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Ietf interface write customizer that only caches interface objects for child writers */ -public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterCustomizer { +public class InterfaceCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); + private final NamingContext interfaceContext; - public InterfaceCustomizer(final vppApi vppApi) { + public InterfaceCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Override @@ -94,20 +100,15 @@ public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterC LOG.info("Setting interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); LOG.debug("Setting interface {}", swIf); - String swIfName = swIf.getName(); - int swIfIndex = getVppApi().swIfIndexFromName(swIfName); - - setInterfaceAttributes(swIf, swIfName); + setInterfaceAttributes(swIf, swIf.getName()); } private void setInterfaceAttributes(final Interface swIf, final String swIfName) throws VppApiInvocationException { LOG.debug("Creating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); - setInterfaceFlags(swIfName, getVppApi().swIfIndexFromName(swIfName), + setInterfaceFlags(swIfName, interfaceContext.getIndex(swIfName), swIf.isEnabled() ? (byte) 1 : (byte) 0); - - setDescription(swIf); } private void updateInterface(final InstanceIdentifier id, @@ -116,35 +117,33 @@ public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterC LOG.info("Updating interface {}, type: {}", dataAfter.getName(), dataAfter.getType().getSimpleName()); LOG.debug("Updating interface {}", dataAfter); - String swIfName = dataAfter.getName(); - int swIfIndex = getVppApi().swIfIndexFromName(swIfName); - - setInterfaceAttributes(dataAfter, swIfName); + setInterfaceAttributes(dataAfter, dataAfter.getName()); } private void setInterfaceFlags(final String swIfName, final int swIfIndex, final byte enabled) throws VppApiInvocationException { - int ctxId = getVppApi().swInterfaceSetFlags(swIfIndex, enabled, enabled, (byte) 0 /* deleted */); + final CompletionStage swInterfaceSetFlagsReplyFuture = getFutureJVpp().swInterfaceSetFlags( + getSwInterfaceSetFlagsInput(swIfIndex, enabled, (byte) 0 /* deleted */)); - LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, - enabled, ctxId); + LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}", swIfName, swIfIndex, enabled); - 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); + SwInterfaceSetFlagsReply reply = V3poUtils.getReply(swInterfaceSetFlagsReplyFuture.toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Failed to update interface flags for: {}, index: {}, enabled: {}", swIfName, swIfIndex, + enabled); + throw new VppApiInvocationException("swInterfaceSetFlags", reply.context, reply.retval); } else { LOG.debug("Interface flags updated successfully for: {}, index: {}, enabled: {}, ctxId: {}", - swIfName, swIfIndex, enabled, ctxId); + swIfName, swIfIndex, enabled, reply.context); } } - private void setDescription(final Interface swIf) { - if (swIf.getDescription() != null) { - getVppApi().setInterfaceDescription(swIf.getName(), swIf.getDescription()); - } else { - getVppApi().setInterfaceDescription(swIf.getName(), ""); - } + private SwInterfaceSetFlags getSwInterfaceSetFlagsInput(final int swIfIndex, final byte enabled, final byte deleted) { + final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags(); + swInterfaceSetFlags.swIfIndex = swIfIndex; + swInterfaceSetFlags.adminUpDown = enabled; + swInterfaceSetFlags.linkUpDown = enabled; + swInterfaceSetFlags.deleted = deleted; + return swInterfaceSetFlags; } } 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 index b9296b481..3bc04f81d 100644 --- 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 @@ -21,10 +21,12 @@ 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.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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 java.util.concurrent.CompletionStage; 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; @@ -34,15 +36,25 @@ 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.interfaces._interface.l2.interconnection.XconnectBased; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceSetL2Bridge; +import org.openvpp.jvpp.dto.SwInterfaceSetL2BridgeReply; +import org.openvpp.jvpp.dto.SwInterfaceSetL2Xconnect; +import org.openvpp.jvpp.dto.SwInterfaceSetL2XconnectReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); + private final NamingContext interfaceContext; + private final NamingContext bridgeDomainContext; - public L2Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public L2Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext, + final NamingContext bridgeDomainContext) { super(vppApi); + this.interfaceContext = interfaceContext; + this.bridgeDomainContext = bridgeDomainContext; } @Nonnull @@ -57,7 +69,7 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = getSwIfc(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName); try { setL2(id, swIfc, ifcName, dataAfter); } catch (VppApiInvocationException e) { @@ -72,7 +84,7 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = getSwIfc(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName); // TODO handle update properly (if possible) try { setL2(id, swIfc, ifcName, dataAfter); @@ -82,12 +94,6 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi } } - private int getSwIfc(final String ifcName) { - int swIfcIndex = getVppApi().swIfIndexFromName(ifcName); - checkArgument(swIfcIndex != -1, "Interface %s does not exist", ifcName); - return swIfcIndex; - } - @Override public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2 dataBefore, @Nonnull final Context writeContext) { @@ -126,7 +132,9 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi bb.getBridgeDomain(), ifcName); String bdName = bb.getBridgeDomain(); - int bdId = getVppApi().bridgeDomainIdFromName(bdName); + + // FIXME need BridgeDomainContext here + int bdId = bridgeDomainContext.getIndex(bdName); checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", ifcName, bdName); @@ -135,19 +143,32 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi : (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()); + final CompletionStage swInterfaceSetL2BridgeReplyCompletionStage = getFutureJVpp() + .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */)); + final SwInterfaceSetL2BridgeReply reply = + V3poUtils.getReply(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture()); - if (rv < 0) { + if (reply.retval < 0) { LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifcName, bb); - throw new VppApiInvocationException("swInterfaceSetL2Bridge", ctxId, rv); + throw new VppApiInvocationException("swInterfaceSetL2Bridge", reply.context, reply.retval); } else { LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName, bb); } } + private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg, + final byte bvi, final byte enabled) { + final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge(); + swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex; + swInterfaceSetL2Bridge.bdId = bdId; + swInterfaceSetL2Bridge.shg = shg; + swInterfaceSetL2Bridge.bvi = bvi; + swInterfaceSetL2Bridge.enable = enabled; + return swInterfaceSetL2Bridge; + } + private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic) throws VppApiInvocationException { @@ -155,21 +176,34 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi LOG.debug("Setting xconnect based interconnection(outgoing ifc=%s) for interface: %s", outSwIfName, ifcName); - int outSwIfIndex = getVppApi().swIfIndexFromName(outSwIfName); + int outSwIfIndex = interfaceContext.getIndex(outSwIfName); checkArgument(outSwIfIndex > 0, "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", ifcName, outSwIfIndex); - int ctxId = getVppApi().swInterfaceSetL2Xconnect(swIfIndex, outSwIfIndex, (byte) 1 /* enable */); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + final CompletionStage swInterfaceSetL2XconnectReplyCompletionStage = + getFutureJVpp() + .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, (byte) 1 /* enable */)); + final SwInterfaceSetL2XconnectReply reply = + V3poUtils.getReply(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture()); - if (rv < 0) { + if (reply.retval < 0) { LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", ifcName, ic); - throw new VppApiInvocationException("swInterfaceSetL2Xconnect", ctxId, rv); + throw new VppApiInvocationException("swInterfaceSetL2Xconnect", reply.context, reply.retval); } else { LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName, ic); } } + + private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc, + final byte enabled) { + + final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect(); + swInterfaceSetL2Xconnect.enable = enabled; + swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc; + swInterfaceSetL2Xconnect.txSwIfIndex = txIfc; + return swInterfaceSetL2Xconnect; + } } 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 index 718afc0e1..b15050cd0 100644 --- 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 @@ -16,30 +16,35 @@ 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.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; 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 java.util.concurrent.CompletionStage; 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.openvpp.jvpp.dto.SwInterfaceSetTable; +import org.openvpp.jvpp.dto.SwInterfaceSetTableReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class RoutingCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class); + private final NamingContext interfaceContext; - public RoutingCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public RoutingCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Nonnull @@ -84,7 +89,7 @@ public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCu } private void setRouting(final String name, final Routing rt) throws VppApiInvocationException { - final int swIfc = getSwIfc(name); + final int swIfc = interfaceContext.getIndex(name); LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt); int vrfId = (rt != null) @@ -92,21 +97,25 @@ public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCu : 0; if (vrfId != 0) { - final int ctxId = getVppApi().swInterfaceSetTable(swIfc, (byte) 0, /* isIpv6 */ vrfId); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final CompletionStage swInterfaceSetTableReplyCompletionStage = + getFutureJVpp().swInterfaceSetTable(getInterfaceSetTableRequest(swIfc, (byte) 0, /* isIpv6 */ vrfId)); + final SwInterfaceSetTableReply reply = + V3poUtils.getReply(swInterfaceSetTableReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { LOG.debug("Failed to set routing for interface: {}, {}, vxlan: {}", name, swIfc, rt); - throw new VppApiInvocationException("swInterfaceSetTable", ctxId, rv); + throw new VppApiInvocationException("swInterfaceSetTable", reply.context, reply.retval); } 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; + private SwInterfaceSetTable getInterfaceSetTableRequest(final int swIfc, final byte isIpv6, final int vrfId) { + final SwInterfaceSetTable swInterfaceSetTable = new SwInterfaceSetTable(); + swInterfaceSetTable.isIpv6 = isIpv6; + swInterfaceSetTable.swIfIndex = swIfc; + swInterfaceSetTable.vrfId = vrfId; + return swInterfaceSetTable; } } 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 index 6e84c303a..2e532660e 100644 --- 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 @@ -17,30 +17,36 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import com.google.common.base.Optional; +import com.google.common.net.InetAddresses; 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.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; 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 java.net.InetAddress; +import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; -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.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.openvpp.jvpp.dto.VxlanAddDelTunnel; +import org.openvpp.jvpp.dto.VxlanAddDelTunnelReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); + private final NamingContext interfaceContext; - - public VxlanCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public VxlanCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Nonnull @@ -84,28 +90,39 @@ public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCust } private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { - Ipv4AddressNoZone srcAddress = V3poUtils.removeIpv4AddressNoZone(vxlan.getSrc()); - Ipv4AddressNoZone dstAddress = V3poUtils.removeIpv4AddressNoZone(vxlan.getDst()); - - byte[] srcAddr = V3poUtils.ipv4AddressNoZoneToArray(srcAddress); - byte[] dstAddr = V3poUtils.ipv4AddressNoZoneToArray(dstAddress); + final InetAddress srcAddress = InetAddresses.forString(vxlan.getSrc().getValue()); + final InetAddress dstAddress = InetAddresses.forString(vxlan.getDst().getValue()); int encapVrfId = vxlan.getEncapVrfId().intValue(); int vni = vxlan.getVni().getValue().intValue(); LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan); - int ctxId = 0; getVppApi().vxlanAddDelTunnel( - (byte) 1 /* is add */, - (byte) 0 /* is ipv6 */, - srcAddr, dstAddr, encapVrfId, -1, vni); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final CompletionStage vxlanAddDelTunnelReplyCompletionStage = + getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, srcAddress.getAddress(), + dstAddress.getAddress(), encapVrfId, -1, vni, (byte) 0 /* is IPV6 */)); + + final VxlanAddDelTunnelReply reply = + V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { LOG.debug("Failed to set vxlan tunnel for interface: {}, vxlan: {}", swIfName, vxlan); - throw new VppApiInvocationException("vxlanAddDelTunnel", ctxId, rv); + throw new VppApiInvocationException("vxlanAddDelTunnel", reply.context, reply.retval); } 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()); + // Add new interface to our interface context + interfaceContext.addName(reply.swIfIndex, swIfName); } } + + private VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final byte[] srcAddr, final byte[] dstAddr, + final int encapVrfId, + final int decapNextIndex, final int vni, final byte isIpv6) { + final VxlanAddDelTunnel vxlanAddDelTunnel = new VxlanAddDelTunnel(); + vxlanAddDelTunnel.isAdd = isAdd; + vxlanAddDelTunnel.srcAddress = srcAddr; + vxlanAddDelTunnel.dstAddress = dstAddr; + vxlanAddDelTunnel.encapVrfId = encapVrfId; + vxlanAddDelTunnel.vni = vni; + vxlanAddDelTunnel.decapNextIndex = decapNextIndex; + vxlanAddDelTunnel.isIpv6 = isIpv6; + return vxlanAddDelTunnel; + } } 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 index 9f3584908..e309294ef 100644 --- 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 @@ -19,16 +19,17 @@ 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 io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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; +import org.openvpp.jvpp.future.FutureJVpp; -public class Interface1Customizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class Interface1Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer { - public Interface1Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Interface1Customizer(final FutureJVpp vppApi) { super(vppApi); } 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 index 8349ebb9b..de2015c64 100644 --- 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 @@ -22,10 +22,12 @@ 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.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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 java.util.concurrent.CompletionStage; 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; @@ -36,17 +38,23 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061 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.openvpp.jvpp.dto.SwInterfaceAddDelAddress; +import org.openvpp.jvpp.dto.SwInterfaceAddDelAddressReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(Ipv4Customizer.class); + private final NamingContext interfaceContext; - public Ipv4Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Ipv4Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } + // TODO replace guava's Optionals with Java8 @Nonnull @Override public Optional extract(@Nonnull final InstanceIdentifier currentId, @@ -91,7 +99,7 @@ public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCusto private void setIpv4(final InstanceIdentifier id, final String name, final Ipv4 ipv4) throws WriteFailedException, VppApiInvocationException { - final int swIfc = getSwIfc(name); + final int swIfc = interfaceContext.getIndex(name); for (Address ipv4Addr : ipv4.getAddress()) { Subnet subnet = ipv4Addr.getSubnet(); @@ -127,24 +135,34 @@ public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCusto 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 CompletionStage swInterfaceAddDelAddressReplyCompletionStage = + getFutureJVpp().swInterfaceAddDelAddress(getSwInterfaceAddDelAddressRequest( + swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, (byte) 0 /* delAll */, plen.byteValue(), addr)); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final SwInterfaceAddDelAddressReply reply = + V3poUtils.getReply(swInterfaceAddDelAddressReplyCompletionStage.toCompletableFuture()); + + if (reply.retval < 0) { LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc, subnet, ipv4Addr); - throw new VppApiInvocationException("swInterfaceAddDelAddress", ctxId, rv); + throw new VppApiInvocationException("swInterfaceAddDelAddress", reply.context, reply.retval); } 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; + private SwInterfaceAddDelAddress getSwInterfaceAddDelAddressRequest(final int swIfc, final byte isAdd, final byte ipv6, + final byte deleteAll, + final byte length, final byte[] addr) { + final SwInterfaceAddDelAddress swInterfaceAddDelAddress = new SwInterfaceAddDelAddress(); + swInterfaceAddDelAddress.swIfIndex = swIfc; + swInterfaceAddDelAddress.isAdd = isAdd; + swInterfaceAddDelAddress.isIpv6 = ipv6; + swInterfaceAddDelAddress.delAll = deleteAll; + swInterfaceAddDelAddress.address = addr; + swInterfaceAddDelAddress.addressLength = length; + return swInterfaceAddDelAddress; } + } 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 index 3798f891a..e3ad3928e 100644 --- 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 @@ -19,20 +19,21 @@ 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 io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Ipv6Customizer extends VppApiCustomizer implements ChildWriterCustomizer { +public class Ipv6Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(Ipv6Customizer.class); - public Ipv6Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Ipv6Customizer(final FutureJVpp vppApi) { super(vppApi); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java index 718cef1b5..f7d473f73 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java @@ -19,6 +19,14 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +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.InterfacesStateBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; @@ -29,21 +37,23 @@ 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.yang.types.rev130715.PhysAddress; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceDump; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - -public class InterfaceCustomizer extends io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer +public class InterfaceCustomizer extends FutureJVppCustomizer implements ListReaderCustomizer { private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); + private final NamingContext interfaceContext; - public InterfaceCustomizer(org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public InterfaceCustomizer(@Nonnull final FutureJVpp jvpp, final NamingContext interfaceContext) { + super(jvpp); + this.interfaceContext = interfaceContext; } @Override @@ -54,56 +64,67 @@ public class InterfaceCustomizer extends io.fd.honeycomb.v3po.translate.v3po.uti @Override public void readCurrentAttributes(InstanceIdentifier id, InterfaceBuilder builder, Context ctx) throws ReadFailedException { - vppInterfaceDetails[] ifaces; - final InterfaceKey key = id.firstKeyOf(id.getTargetType()); - // Extract one interface detail from VPP - ifaces = getVppApi().swInterfaceDump((byte) 1, key.getName().getBytes()); - if (null == ifaces) { - LOG.warn("VPP returned null instead of interface by key {}", key.getName().getBytes()); - return; - } - if (1 != ifaces.length) { - LOG.error("Failed to extract interface {} details from VPP", key.getName()); - return; + final SwInterfaceDetails iface; + try { + iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key); + } catch (Exception e) { + throw new ReadFailedException(id, e); } - final vppInterfaceDetails iface = ifaces[0]; - builder.setName(iface.interfaceName); + builder.setName(key.getName()); // FIXME: report interface type based on name //Tunnel.class l2vlan(802.1q) bridge (transparent bridge?) builder.setType(EthernetCsmacd.class); - builder.setIfIndex(InterfaceUtils.vppIfIndexToYang(iface.ifIndex)); - builder.setAdminStatus(iface.adminUp == 1 ? AdminStatus.Up : AdminStatus.Down); - builder.setOperStatus(1 == iface.linkUp ? OperStatus.Up : OperStatus.Down); + builder.setIfIndex(InterfaceUtils.vppIfIndexToYang(iface.swIfIndex)); + builder.setAdminStatus(iface.adminUpDown == 1 + ? AdminStatus.Up + : AdminStatus.Down); + builder.setOperStatus(1 == iface.linkUpDown + ? OperStatus.Up + : OperStatus.Down); if (0 != iface.linkSpeed) { builder.setSpeed(InterfaceUtils.vppInterfaceSpeedToYang(iface.linkSpeed)); } - if (iface.physAddr.length == 6) { - builder.setPhysAddress(new PhysAddress(InterfaceUtils.vppPhysAddrToYang(iface.physAddr))); + if (iface.l2AddressLength == 6) { + builder.setPhysAddress(new PhysAddress(InterfaceUtils.vppPhysAddrToYang(iface.l2Address))); } } + @Nonnull @Override - public List getAllIds(InstanceIdentifier id, Context context) { - vppInterfaceDetails[] ifaces; - final ArrayList interfaceKeys = new ArrayList<>(); - - ifaces = getVppApi().swInterfaceDump((byte) 0, "".getBytes()); - if (null != ifaces) { - for (vppInterfaceDetails ifc : ifaces) { - interfaceKeys.add(new InterfaceKey(ifc.interfaceName)); - } + public List getAllIds(@Nonnull final InstanceIdentifier id, + @Nonnull final Context context) throws ReadFailedException { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture swInterfaceDetailsReplyDumpCompletableFuture = + getFutureJVpp().swInterfaceDump(request).toCompletableFuture(); + final SwInterfaceDetailsReplyDump ifaces = V3poUtils.getReply(swInterfaceDetailsReplyDumpCompletableFuture); + + // TODO can we get null here? + if (null == ifaces || null == ifaces.swInterfaceDetails) { + return Collections.emptyList(); } - return interfaceKeys; + return ifaces.swInterfaceDetails.stream() + .filter(elt -> elt != null) + .map((elt) -> { + // Store interface name from VPP in context if not yet present + if(!interfaceContext.containsName(elt.swIfIndex)){ + interfaceContext.addName(elt.swIfIndex, V3poUtils.toString(elt.interfaceName)); + } + return new InterfaceKey(interfaceContext.getName(elt.swIfIndex)); + }) + .collect(Collectors.toList()); } @Override - public void merge(org.opendaylight.yangtools.concepts.Builder builder, - List readData) { + public void merge(@Nonnull final org.opendaylight.yangtools.concepts.Builder builder, + @Nonnull final List readData) { ((InterfacesStateBuilder) builder).setInterface(readData); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java index d589c257f..979c9d6bd 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java @@ -16,15 +16,18 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; import java.math.BigInteger; - +import java.util.concurrent.ExecutionException; import javax.annotation.Nonnull; - +import javax.annotation.Nullable; +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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64; - -import com.google.common.base.Preconditions; -import org.openvpp.vppjapi.vppApi; -import org.openvpp.vppjapi.vppInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceDump; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,8 +45,7 @@ public class InterfaceUtils { private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray(); /** - * Convert VPP's link speed bitmask to Yang type. 1 = 10M, 2 = 100M, 4 = 1G, - * 8 = 10G, 16 = 40G, 32 = 100G + * Convert VPP's link speed bitmask to Yang type. 1 = 10M, 2 = 100M, 4 = 1G, 8 = 10G, 16 = 40G, 32 = 100G * * @param vppLinkSpeed Link speed in bitmask format from VPP. * @return Converted value from VPP link speed @@ -74,16 +76,11 @@ public class InterfaceUtils { } /** - * Convert VPP's physical address stored byte array format to string as Yang - * dictates - *

- * Replace later with - * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- - * util/src/main/ + * Convert VPP's physical address stored byte array format to string as Yang dictates

Replace later with + * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- util/src/main/ * java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java * - * @param vppPhysAddress byte array of bytes constructing the network IF physical - * address. + * @param vppPhysAddress byte array of bytes constructing the network IF physical address. * @return String like "aa:bb:cc:dd:ee:ff" */ public static String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) { @@ -102,8 +99,8 @@ public class InterfaceUtils { } /** - * VPP's interface index is counted from 0, whereas ietf-interface's - * if-index is from 1. This function converts from VPP's interface index to YANG's interface index. + * VPP's interface index is counted from 0, whereas ietf-interface's if-index is from 1. This function converts from + * VPP's interface index to YANG's interface index. * * @param vppIfIndex the sw interface index VPP reported. * @return VPP's interface index incremented by one @@ -115,7 +112,7 @@ public class InterfaceUtils { /** * This function does the opposite of what {@link #vppIfIndexToYang(int)} does. * - * @param yangIf if-index from ietf-interfaces. + * @param yangIfIndex if-index from ietf-interfaces. * @return VPP's representation of the if-index */ public static int YangIfIndexToVpp(int yangIfIndex) { @@ -124,25 +121,31 @@ public class InterfaceUtils { } - public static vppInterfaceDetails[] getVppInterfaceDetails(final vppApi api, - final boolean specificInterface, - String interfaceName) { - if (interfaceName == null) { - interfaceName = new String(); - } - vppInterfaceDetails[] ifaces = api.swInterfaceDump( - (byte) (specificInterface ? 1 : 0), - interfaceName.getBytes()); - if (null == ifaces) { - LOG.warn("VPP returned null instead of interface by key {}", interfaceName); + /** + * Queries VPP for interface description given interface key. + * + * @param futureJvpp VPP Java Future API + * @param key interface key + * @return SwInterfaceDetails DTO or null if interface was not found + * @throws ExecutionException if exception has been thrown while executing VPP query + * @throws InterruptedException if the current thread was interrupted + */ + @Nullable + public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp, + @Nonnull InterfaceKey key) + throws ExecutionException, InterruptedException { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = key.getName().getBytes(); + request.nameFilterValid = 1; + + // TODO should we use timeout? + SwInterfaceDetailsReplyDump ifaces = futureJvpp.swInterfaceDump(request).toCompletableFuture().get(); + if (null == ifaces) { // TODO can we get null here? + LOG.warn("VPP returned null instead of interface by key {}", key.getName().getBytes()); return null; } - if (1 != ifaces.length) { - LOG.error("Failed to extract interface {} details from VPP", interfaceName); - } - - return ifaces; + return Iterables.getOnlyElement(ifaces.swInterfaceDetails); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java index 8e5cc8932..2bc8beaaa 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java @@ -16,11 +16,10 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.getVppInterfaceDetails; - import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import javax.annotation.Nonnull; 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; @@ -32,28 +31,31 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VppInterfaceStateCustomizer extends io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer +public class VppInterfaceStateCustomizer extends FutureJVppCustomizer implements ChildReaderCustomizer { private static final Logger LOG = LoggerFactory.getLogger(VppInterfaceStateCustomizer.class); - public VppInterfaceStateCustomizer(org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public VppInterfaceStateCustomizer(@Nonnull final FutureJVpp jvpp) { + super(jvpp); } @Override - public void merge(@Nonnull Builder parentBuilder, @Nonnull VppInterfaceStateAugmentation readValue) { + public void merge(@Nonnull Builder parentBuilder, + @Nonnull VppInterfaceStateAugmentation readValue) { ((InterfaceBuilder) parentBuilder).addAugmentation(VppInterfaceStateAugmentation.class, readValue); } @Nonnull @Override - public VppInterfaceStateAugmentationBuilder getBuilder(@Nonnull InstanceIdentifier id) { + public VppInterfaceStateAugmentationBuilder getBuilder( + @Nonnull InstanceIdentifier id) { return new VppInterfaceStateAugmentationBuilder(); } @@ -63,15 +65,15 @@ public class VppInterfaceStateCustomizer extends io.fd.honeycomb.v3po.translate. @Nonnull final Context ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); - vppInterfaceDetails[] ifaces = getVppInterfaceDetails(getVppApi(), true, key.getName()); - if (null == ifaces || ifaces.length != 1) { - return; + final SwInterfaceDetails iface; + try { + iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key); + } catch (Exception e) { + throw new ReadFailedException(id, e); } - final vppInterfaceDetails iface = ifaces[0]; final EthernetBuilder ethernet = new EthernetBuilder(); - - ethernet.setMtu(iface.linkMtu); + ethernet.setMtu((int) iface.linkMtu); switch (iface.linkDuplex) { case 1: ethernet.setDuplex(Ethernet.Duplex.Half); 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 index 88626453e..b4217df46 100644 --- 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 @@ -16,18 +16,17 @@ package io.fd.honeycomb.v3po.translate.v3po.utils; -import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; -import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; 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.Ipv4Address; 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; +import org.openvpp.jvpp.dto.JVppReply; public final class V3poUtils { @@ -48,25 +47,17 @@ public final class V3poUtils { 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 + public static > REP getReply(Future future) { + try { + return future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("Interrupted", e); + } catch (ExecutionException e) { + // Execution exception should not occur, since we are using return codes for errors + // TODO fix when using exceptions instead of return codes + throw new IllegalArgumentException("Future " + " should not fail with an exception", e); } - 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) { @@ -80,22 +71,10 @@ public final class V3poUtils { } /** - * Removes zone index from Ipv4Address. - * @param ipv4Addr ipv4 address which can contain zone index - * @return ipv4 address without zone index + * Return (interned) string from byte array while removing \u0000. + * Strings represented as fixed length byte[] from vpp contain \u0000. */ - @Nonnull - public static Ipv4AddressNoZone removeIpv4AddressNoZone(@Nonnull final Ipv4Address ipv4Addr) { - Preconditions.checkNotNull(ipv4Addr, "ipv4Addr should not be null"); - if (ipv4Addr instanceof Ipv4AddressNoZone) { - return (Ipv4AddressNoZone)ipv4Addr; - } else { - String value = ipv4Addr.getValue(); - final int index = value.indexOf('%'); - if (index != -1) { - value = value.substring(0, index); - } - return new Ipv4AddressNoZone(value); - } + public static String toString(final byte[] cString) { + return new String(cString).replaceAll("\\u0000", "").intern(); } } 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 c69f2ef0a..4b4d7b3c1 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 @@ -18,12 +18,15 @@ package io.fd.honeycomb.v3po.translate.v3po.vpp; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -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 com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +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 java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -32,19 +35,24 @@ 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.bridge.domains.BridgeDomainKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.BridgeDomainAddDel; +import org.openvpp.jvpp.dto.BridgeDomainAddDelReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BridgeDomainCustomizer - extends VppApiCustomizer - implements ListWriterCustomizer { + extends FutureJVppCustomizer + implements ListWriterCustomizer { private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); private static final byte ADD_OR_UPDATE_BD = (byte) 1; + private final NamingContext bdContext; - public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi api) { - super(api); + public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext bdContext) { + super(futureJvpp); + this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null"); } @Nonnull @@ -54,76 +62,96 @@ public class BridgeDomainCustomizer return ((BridgeDomains) parentData).getBridgeDomain(); } - private int addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) { - byte flood = booleanToByte(bd.isFlood()); - byte forward = booleanToByte(bd.isForward()); - byte learn = booleanToByte(bd.isLearn()); - byte uuf = booleanToByte(bd.isUnknownUnicastFlood()); - byte arpTerm = booleanToByte(bd.isArpTermination()); - - int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); - return V3poUtils.waitForResponse(ctxId, getVppApi()); + private BridgeDomainAddDelReply addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) + throws VppApiInvocationException { + final BridgeDomainAddDel request = new BridgeDomainAddDel(); + request.bdId = bdId; + request.flood = booleanToByte(bd.isFlood()); + request.forward = booleanToByte(bd.isForward()); + request.learn = booleanToByte(bd.isLearn()); + request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood()); + request.arpTerm = booleanToByte(bd.isArpTermination()); + request.isAdd = ADD_OR_UPDATE_BD; + + final BridgeDomainAddDelReply reply = + V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Bridge domain {} (id={}) add/update failed", bd.getName(), bdId); + throw new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval); + } else { + LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId); + } + + return reply; } @Override public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final BridgeDomain current, - @Nonnull final Context ctx) { - LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, current, ctx); - final String bdName = current.getName(); - int bdId = getVppApi().findOrAddBridgeDomainId(bdName); - checkState(bdId > 0, "Unable to find or create bridge domain. Return code: %s", bdId); - - int rv = addOrUpdateBridgeDomain(bdId, current); - - checkState(rv >= 0, "Bridge domain %s(%s) write failed. Return code: %s", bdName, bdId, rv); - LOG.debug("Bridge domain {} written as {} successfully", bdName, bdId); + @Nonnull final BridgeDomain dataBefore, + @Nonnull final Context ctx) throws WriteFailedException.CreateFailedException { + LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx); + final String bdName = dataBefore.getName(); + + try { + // FIXME we need the bd index to be returned by VPP or we should have a counter field (maybe in context similar to artificial name) + // Here we assign the next available ID from bdContext's perspective + int index = 1; + while(bdContext.containsName(index)) { + index++; + } + addOrUpdateBridgeDomain(index, dataBefore); + bdContext.addName(index, bdName); + } catch (VppApiInvocationException e) { + LOG.warn("Failed to create bridge domain", e); + throw new WriteFailedException.CreateFailedException(id, dataBefore, e); + } } private byte booleanToByte(@Nullable final Boolean aBoolean) { - return aBoolean != null && aBoolean ? (byte) 1 : (byte) 0; + return aBoolean != null && aBoolean + ? (byte) 1 + : (byte) 0; } @Override public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final BridgeDomain dataBefore, - @Nonnull final Context ctx) { + @Nonnull final Context ctx) throws WriteFailedException.DeleteFailedException { LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx); - String bdName = id.firstKeyOf(BridgeDomain.class).getName(); - - int bdId = getVppApi().bridgeDomainIdFromName(bdName); - checkState(bdId > 0, "Unable to delete bridge domain. Does not exist. Return code: %s", bdId); - int ctxId = getVppApi().bridgeDomainAddDel(bdId, - (byte) 0 /* flood */, - (byte) 0 /* forward */, - (byte) 0 /* learn */, - (byte) 0 /* uuf */, - (byte) 0 /* arpTerm */, - (byte) 0 /* isAdd */); - - 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); + final String bdName = id.firstKeyOf(BridgeDomain.class).getName(); + int bdId = bdContext.getIndex(bdName); + final BridgeDomainAddDel request = new BridgeDomainAddDel(); + request.bdId = bdId; + + final BridgeDomainAddDelReply reply = + V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId); + throw new WriteFailedException.DeleteFailedException(id, + new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval)); + } else { + LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId); + } } @Override public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter, - @Nonnull final Context ctx) { - LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter, ctx); + @Nonnull final Context ctx) throws WriteFailedException.UpdateFailedException { + LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter, + ctx); final String bdName = checkNotNull(dataAfter.getName()); - checkArgument(bdName.equals(dataBefore.getName()), "BridgeDomain name changed. It should be deleted and then created."); - - int bdId = getVppApi().bridgeDomainIdFromName(bdName); - checkState(bdId > 0, "Unable to find bridge domain. Return code: %s", bdId); - - final int rv = addOrUpdateBridgeDomain(bdId, dataAfter); - - checkState(rv >= 0, "Bridge domain %s(%s) update failed. Return code: %s", bdName, bdId, rv); - LOG.debug("Bridge domain {}({}) updated successfully", bdName, bdId); + checkArgument(bdName.equals(dataBefore.getName()), + "BridgeDomain name changed. It should be deleted and then created."); + + try { + addOrUpdateBridgeDomain(bdContext.getIndex(bdName), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Failed to create bridge domain", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java index 61c345b44..addb425f6 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java @@ -16,10 +16,15 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import com.google.common.primitives.Longs; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -34,104 +39,150 @@ 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.bridge.domain.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2Fib; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibKey; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppBridgeDomainDetails; -import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails; -import org.openvpp.vppjapi.vppL2Fib; +import org.openvpp.jvpp.dto.BridgeDomainDetails; +import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; +import org.openvpp.jvpp.dto.BridgeDomainDump; +import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; +import org.openvpp.jvpp.dto.L2FibTableDump; +import org.openvpp.jvpp.dto.L2FibTableEntry; +import org.openvpp.jvpp.dto.L2FibTableEntryReplyDump; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class BridgeDomainCustomizer extends VppApiCustomizer - implements ListReaderCustomizer { +public final class BridgeDomainCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer { private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); - - public BridgeDomainCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + private final NamingContext bdContext; + private final NamingContext interfaceContext; + + public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJVpp, @Nonnull final NamingContext bdContext, + @Nonnull final NamingContext interfaceContext) { + super(futureJVpp); + this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null"); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");; } @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) { + @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) + throws ReadFailedException { LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: id={}, builderbuilder={}, context={}", id, builder, context); final BridgeDomainKey key = id.firstKeyOf(id.getTargetType()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: key={}", key); - final int bdId = getVppApi().bridgeDomainIdFromName(key.getName()); + final int bdId = bdContext.getIndex(key.getName()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: bdId={}", bdId); - final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bdId); - if(bridgeDomainDetails == null) { - LOG.debug("Bridge domain name={} does not exist", key.getName()); + BridgeDomainDetailsReplyDump reply; + BridgeDomainDetails bridgeDomainDetails; + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = bdContext.getIndex(key.getName()); + try { + reply = getFutureJVpp().bridgeDomainDump(request).toCompletableFuture().get(); + bridgeDomainDetails = Iterables.getOnlyElement(reply.bridgeDomainDetails); + } catch (Exception e) { + LOG.debug("Unable to read bridge domain: {}", key.getName(), e); return; } + logBridgeDomainDetails(bridgeDomainDetails); builder.setName(key.getName()); - // builder.setName(bridgeDomainDetails.name); - builder.setArpTermination(bridgeDomainDetails.arpTerm); - builder.setFlood(bridgeDomainDetails.flood); - builder.setForward(bridgeDomainDetails.forward); - builder.setLearn(bridgeDomainDetails.learn); - builder.setUnknownUnicastFlood(bridgeDomainDetails.uuFlood); - - builder.setInterface(getIfcs(bridgeDomainDetails)); - - final vppL2Fib[] vppL2Fibs = getVppApi().l2FibTableDump(bdId); - - final List l2Fibs = Lists.newArrayListWithCapacity(vppL2Fibs.length); - for (vppL2Fib vppL2Fib : vppL2Fibs) { - l2Fibs.add(new L2FibBuilder() - .setAction((vppL2Fib.filter - ? L2Fib.Action.Filter - : L2Fib.Action.Forward)) - .setBridgedVirtualInterface(vppL2Fib.bridgedVirtualInterface) - .setOutgoingInterface(vppL2Fib.outgoingInterface) - .setPhysAddress(new PhysAddress(getMacAddress(vppL2Fib.physAddress))) - .setStaticConfig(vppL2Fib.staticConfig) - .build()); + builder.setArpTermination(byteToBoolean(bridgeDomainDetails.arpTerm)); + builder.setFlood(byteToBoolean(bridgeDomainDetails.flood)); + builder.setForward(byteToBoolean(bridgeDomainDetails.forward)); + builder.setLearn(byteToBoolean(bridgeDomainDetails.learn)); + builder.setUnknownUnicastFlood(byteToBoolean(bridgeDomainDetails.uuFlood)); + + builder.setInterface(getIfcs(bridgeDomainDetails, reply.bridgeDomainSwIfDetails)); + + final L2FibTableDump l2FibRequest = new L2FibTableDump(); + l2FibRequest.bdId = bdId; + try { + final L2FibTableEntryReplyDump dump = + getFutureJVpp().l2FibTableDump(l2FibRequest).toCompletableFuture().get(); + final List l2Fibs = Lists.newArrayListWithCapacity(dump.l2FibTableEntry.size()); + for (L2FibTableEntry entry : dump.l2FibTableEntry) { + // entry.mac is a long value in the format 66:55:44:33:22:11:XX:XX + // where mac address is 11:22:33:44:55:66 + final PhysAddress address = new PhysAddress(getMacAddress(Longs.toByteArray(entry.mac))); + l2Fibs.add(new L2FibBuilder() + .setAction((byteToBoolean(entry.filterMac) + ? L2Fib.Action.Filter + : L2Fib.Action.Forward)) + .setBridgedVirtualInterface(byteToBoolean(entry.bviMac)) + .setOutgoingInterface(interfaceContext.getName(entry.swIfIndex)) + .setStaticConfig(byteToBoolean(entry.staticMac)) + .setPhysAddress(address) + .setKey(new L2FibKey(address)) + .build()); + } + builder.setL2Fib(l2Fibs); + + } catch (Exception e) { + LOG.warn("Failed to acquire l2FibTableDump for domain id={}", bdId, e); + } + } + + // TODO move to utils + private static Boolean byteToBoolean(final byte aByte) { + if (aByte == 0) { + return Boolean.FALSE; + } else if (aByte == 1) { + return Boolean.TRUE; } - builder.setL2Fib(l2Fibs); + throw new IllegalArgumentException(String.format("0 or 1 was expected but was %d", aByte)); } - private void logBridgeDomainDetails(final vppBridgeDomainDetails bridgeDomainDetails) { + private void logBridgeDomainDetails(final BridgeDomainDetails bridgeDomainDetails) { LOG.debug("bridgeDomainDetails={}", bridgeDomainDetails); if (bridgeDomainDetails != null) { LOG.debug("bridgeDomainDetails.arpTerm={}", bridgeDomainDetails.arpTerm); LOG.debug("bridgeDomainDetails.bdId={}", bridgeDomainDetails.bdId); - LOG.debug("bridgeDomainDetails.bviInterfaceName={}", bridgeDomainDetails.bviInterfaceName); + LOG.debug("bridgeDomainDetails.bviSwIfIndex={}", bridgeDomainDetails.bviSwIfIndex); LOG.debug("bridgeDomainDetails.flood={}", bridgeDomainDetails.flood); LOG.debug("bridgeDomainDetails.forward={}", bridgeDomainDetails.forward); LOG.debug("bridgeDomainDetails.learn={}", bridgeDomainDetails.learn); - LOG.debug("bridgeDomainDetails.name={}", bridgeDomainDetails.name); + LOG.debug("bridgeDomainDetails.nSwIfs={}", bridgeDomainDetails.nSwIfs); LOG.debug("bridgeDomainDetails.uuFlood={}", bridgeDomainDetails.uuFlood); } } - + // TODO move to some utility class private static String getMacAddress(byte[] mac) { StringBuilder sb = new StringBuilder(18); - for (byte b : mac) { + for (int i=5; i>=0; --i) { if (sb.length() > 0) { sb.append(':'); } - sb.append(String.format("%02x", b)); + sb.append(String.format("%02x", mac[i])); } return sb.toString(); } - private List getIfcs(final vppBridgeDomainDetails bridgeDomainDetails) { - final List ifcs = new ArrayList<>(bridgeDomainDetails.interfaces.length); - for (vppBridgeDomainInterfaceDetails anInterface : bridgeDomainDetails.interfaces) { - ifcs.add(new InterfaceBuilder() - .setBridgedVirtualInterface(bridgeDomainDetails.bviInterfaceName.equals(anInterface.interfaceName)) - .setName(anInterface.interfaceName) - .setKey(new InterfaceKey(anInterface.interfaceName)) - .build()); + private List getIfcs(final BridgeDomainDetails bridgeDomainDetails, + final List bridgeDomainSwIfDetails) { + final List ifcs = new ArrayList<>(bridgeDomainSwIfDetails.size()); + for (BridgeDomainSwIfDetails anInterface : bridgeDomainSwIfDetails) { + final String interfaceName = interfaceContext.getName(anInterface.swIfIndex); + if (anInterface.bdId == bridgeDomainDetails.bdId) { + ifcs.add(new InterfaceBuilder() + .setBridgedVirtualInterface(bridgeDomainDetails.bviSwIfIndex == anInterface.swIfIndex) + .setSplitHorizonGroup((short) anInterface.shg) + .setName(interfaceName) + .setKey(new InterfaceKey(interfaceName)) + .build()); + } + + } return ifcs; } @@ -144,25 +195,34 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer @Nonnull @Override - public List getAllIds(@Nonnull final InstanceIdentifier id, @Nonnull final Context context) { - final int[] bIds = getVppApi().bridgeDomainDump(-1); + public List getAllIds(@Nonnull final InstanceIdentifier id, + @Nonnull final Context context) { + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = -1; // dump call + + BridgeDomainDetailsReplyDump reply; + try { + reply = getFutureJVpp().bridgeDomainDump(request).toCompletableFuture().get(); + } catch (Exception e) { + throw new IllegalStateException("Bridge domain dump failed", e); // TODO ReadFailedException? + } - if(bIds == null) { + if(reply == null || reply.bridgeDomainDetails == null) { + return Collections.emptyList(); + } + + final int bIdsLength = reply.bridgeDomainDetails.size(); + LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bIds.length={}", bIdsLength); + if (bIdsLength == 0) { // No bridge domains return Collections.emptyList(); } - LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bIds.length={}", bIds.length); - final List allIds = new ArrayList<>(bIds.length); - for (int bId : bIds) { - LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bId={}", bId); - // FIXME this is highly inefficient having to dump all of the bridge domain details - // Use context to store already read information - // TODO Or just remove the getAllIds method and replace with a simple readAll - final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bId); - logBridgeDomainDetails(bridgeDomainDetails); - - final String bName = bridgeDomainDetails.name; + final List allIds = new ArrayList<>(bIdsLength); + for (BridgeDomainDetails detail : reply.bridgeDomainDetails) { + logBridgeDomainDetails(detail); + + final String bName = bdContext.getName(detail.bdId); LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bName={}", bName); allIds.add(new BridgeDomainKey(bName)); } @@ -171,7 +231,8 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer } @Override - public void merge(@Nonnull final Builder builder, @Nonnull final List readData) { + public void merge(@Nonnull final Builder builder, + @Nonnull final List readData) { ((BridgeDomainsBuilder) builder).setBridgeDomain(readData); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java index 31e3166bb..1db8217f9 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java @@ -17,8 +17,10 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; import io.fd.honeycomb.v3po.translate.Context; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import javax.annotation.Nonnull; 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.Version; @@ -26,14 +28,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppVersion; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; +import org.openvpp.jvpp.future.FutureJVpp; public final class VersionCustomizer - extends VppApiCustomizer + extends FutureJVppCustomizer implements ChildReaderCustomizer { - public VersionCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public VersionCustomizer(@Nonnull final FutureJVpp futureJVpp) { + super(futureJVpp); } @Override @@ -49,11 +53,18 @@ public final class VersionCustomizer @Override public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull final VersionBuilder builder, - @Nonnull final Context context) { - final vppVersion vppVersion = getVppApi().getVppVersion(); - builder.setBranch(vppVersion.gitBranch); - builder.setName(vppVersion.programName); - builder.setBuildDate(vppVersion.buildDate); - builder.setBuildDirectory(vppVersion.buildDirectory); + @Nonnull final Context context) throws ReadFailedException { + + ShowVersionReply reply; + try { + reply = getFutureJVpp().showVersion(new ShowVersion()).toCompletableFuture().get(); + } catch (Exception e) { + throw new ReadFailedException(id, e); + } + builder.setBranch(V3poUtils.toString(reply.version)); + builder.setName(V3poUtils.toString(reply.program)); + builder.setBuildDate(V3poUtils.toString(reply.buildDate)); + builder.setBuildDirectory(V3poUtils.toString(reply.buildDirectory)); } + } 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 index e906167fd..769589b3d 100644 --- 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 @@ -54,9 +54,9 @@ public class InterfacesHoneycombWriterModule extends org.opendaylight.yang.gen.v ifcAugmentations.add(getInterface1AugmentationWriter()); final ChildWriter interfaceWriter = new CompositeListWriter<>(Interface.class, - RWUtils.emptyChildWriterList(), + RWUtils.emptyChildWriterList(), ifcAugmentations, - new InterfaceCustomizer(getVppJapiIfcDependency()), + new InterfaceCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency()), // 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); @@ -68,36 +68,36 @@ public class InterfacesHoneycombWriterModule extends org.opendaylight.yang.gen.v // 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())); + childWriters, new NoopWriterCustomizer<>())); } private ChildWriter> getInterface1AugmentationWriter() { final ChildWriter ipv4Writer = new CompositeChildWriter<>(Ipv4.class, - new Ipv4Customizer(getVppJapiIfcDependency())); + new Ipv4Customizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); final ChildWriter ipv6Writer = new CompositeChildWriter<>(Ipv6.class, - new Ipv6Customizer(getVppJapiIfcDependency())); + new Ipv6Customizer(getVppJvppIfcDependency())); final List>> interface1ChildWriters = Lists.newArrayList(); interface1ChildWriters.add(ipv4Writer); interface1ChildWriters.add(ipv6Writer); return new CompositeChildWriter<>(Interface1.class, - interface1ChildWriters, new ReflexiveAugmentWriterCustomizer()); + interface1ChildWriters, new ReflexiveAugmentWriterCustomizer<>()); } private ChildWriter getVppIfcAugmentationWriter() { final ChildWriter ethernetWriter = new CompositeChildWriter<>(Ethernet.class, - new EthernetCustomizer(getVppJapiIfcDependency())); + new EthernetCustomizer(getVppJvppIfcDependency())); final ChildWriter routingWriter = new CompositeChildWriter<>(Routing.class, - new RoutingCustomizer(getVppJapiIfcDependency())); + new RoutingCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); final ChildWriter vxlanWriter = new CompositeChildWriter<>(Vxlan.class, - new VxlanCustomizer(getVppJapiIfcDependency())); + new VxlanCustomizer(getVppJvppIfcDependency(), getInterfaceContextDependency())); final ChildWriter l2Writer = new CompositeChildWriter<>(L2.class, - new L2Customizer(getVppJapiIfcDependency())); + new L2Customizer(getVppJvppIfcDependency(), getInterfaceContextDependency(), getBridgeDomainContextDependency())); final List>> vppIfcChildWriters = Lists.newArrayList(); // TODO what's the order here ? @@ -108,7 +108,7 @@ public class InterfacesHoneycombWriterModule extends org.opendaylight.yang.gen.v return new CompositeChildWriter<>(VppInterfaceAugmentation.class, vppIfcChildWriters, - RWUtils.emptyAugWriterList(), - new ReflexiveAugmentWriterCustomizer()); + RWUtils.emptyAugWriterList(), + new ReflexiveAugmentWriterCustomizer<>()); } } 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 aa72a29af..e753cf56e 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,10 +1,15 @@ package org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406; + +import static io.fd.honeycomb.v3po.translate.util.RWUtils.emptyAugReaderList; +import static io.fd.honeycomb.v3po.translate.util.RWUtils.emptyChildReaderList; +import static io.fd.honeycomb.v3po.translate.util.RWUtils.singletonAugReaderList; +import static io.fd.honeycomb.v3po.translate.util.RWUtils.singletonChildReaderList; + 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.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; @@ -15,14 +20,18 @@ 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.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.VppInterfaceStateAugmentation; -import org.openvpp.vppjapi.vppApi; -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) { +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); } - public InterfacesStateHoneycombReaderModule(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.InterfacesStateHoneycombReaderModule oldModule, java.lang.AutoCloseable oldInstance) { + public InterfacesStateHoneycombReaderModule(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.InterfacesStateHoneycombReaderModule oldModule, + java.lang.AutoCloseable oldInstance) { super(identifier, dependencyResolver, oldModule, oldInstance); } @@ -33,22 +42,22 @@ public class InterfacesStateHoneycombReaderModule extends org.opendaylight.yang. @Override public java.lang.AutoCloseable createInstance() { - final vppApi vppApi = getVppJapiDependency(); final ChildReader vppInterfaceStateAugmentationChildReader = - new CompositeChildReader<>(VppInterfaceStateAugmentation.class, - new VppInterfaceStateCustomizer(vppApi)); + new CompositeChildReader<>(VppInterfaceStateAugmentation.class, + new VppInterfaceStateCustomizer(getVppJvppDependency())); + final CompositeListReader interfaceReader = - new CompositeListReader<>(Interface.class, - RWUtils.emptyChildReaderList(), - RWUtils.singletonAugReaderList(vppInterfaceStateAugmentationChildReader), - new InterfaceCustomizer(vppApi)); + new CompositeListReader<>(Interface.class, + emptyChildReaderList(), + singletonAugReaderList(vppInterfaceStateAugmentationChildReader), + new InterfaceCustomizer(getVppJvppDependency(), getInterfaceContextIfcStateDependency())); return new CloseableReader<>(new CompositeRootReader<>( - InterfacesState.class, - RWUtils.singletonChildReaderList(interfaceReader), - RWUtils.emptyAugReaderList(), - new ReflexiveRootReaderCustomizer<>(InterfacesStateBuilder.class))); + InterfacesState.class, + singletonChildReaderList(interfaceReader), + emptyAugReaderList(), + new ReflexiveRootReaderCustomizer<>(InterfacesStateBuilder.class))); } } 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 a9eff593d..69c1bfc11 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 @@ -35,20 +35,20 @@ public class VppHoneycombWriterModule extends org.opendaylight.yang.gen.v1.urn.h public java.lang.AutoCloseable createInstance() { final CompositeListWriter bridgeDomainWriter = new CompositeListWriter<>( BridgeDomain.class, - new BridgeDomainCustomizer(getVppJapiWriterDependency())); + new BridgeDomainCustomizer(getVppJvppWriterDependency(), getBridgeDomainContextVppDependency())); - final ChildWriter bridgeDomainsReader = new CompositeChildWriter<>( + final ChildWriter bridgeDomainsWriter = new CompositeChildWriter<>( BridgeDomains.class, RWUtils.singletonChildWriterList(bridgeDomainWriter), - new ReflexiveChildWriterCustomizer()); + new ReflexiveChildWriterCustomizer<>()); final List>> childWriters = new ArrayList<>(); - childWriters.add(bridgeDomainsReader); + childWriters.add(bridgeDomainsWriter); return new CloseableWriter<>(new CompositeRootWriter<>( Vpp.class, childWriters, - new NoopWriterCustomizer())); + new NoopWriterCustomizer<>())); } } 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 0e1d48035..9a0165577 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 @@ -21,7 +21,7 @@ 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.openvpp.vppjapi.vppApi; +import org.openvpp.jvpp.future.FutureJVpp; public class VppStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.v3po2vpp.rev160406.AbstractVppStateHoneycombReaderModule { public VppStateHoneycombReaderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -39,12 +39,13 @@ public class VppStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1. @Override public java.lang.AutoCloseable createInstance() { - final vppApi vppApi = getVppJapiDependency(); + final FutureJVpp vppApi = getVppJvppDependency(); final ChildReader versionReader = new CompositeChildReader<>(Version.class, new VersionCustomizer(vppApi)); final CompositeListReader bridgeDomainReader = - new CompositeListReader<>(BridgeDomain.class, new BridgeDomainCustomizer(vppApi)); + new CompositeListReader<>(BridgeDomain.class, new BridgeDomainCustomizer(vppApi, + getBridgeDomainContextVppStateDependency(), getInterfaceContextVppStateDependency())); final ChildReader bridgeDomainsReader = new CompositeChildReader<>( BridgeDomains.class, @@ -58,8 +59,7 @@ public class VppStateHoneycombReaderModule extends org.opendaylight.yang.gen.v1. return new CloseableReader<>(new CompositeRootReader<>( VppState.class, childVppReaders, - RWUtils.emptyAugReaderList(), + RWUtils.emptyAugReaderList(), new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class))); } - } diff --git a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang index 286feb987..268739451 100644 --- a/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang +++ b/v3po/v3po2vpp/src/main/yang/v3po2vpp.yang @@ -5,7 +5,8 @@ module v3po2vpp { import config { prefix config; revision-date 2013-04-05; } import translate-api { prefix tapi; revision-date 2016-04-06; } - import vpp-japi-cfg { prefix vjc; revision-date 2016-04-06; } + import vpp-jvpp-cfg { prefix vjvppc; revision-date 2016-04-06; } + import vpp-util { prefix vpp-u; revision-date 2016-04-06; } description "This module contains reads and writers for v3po yang model"; @@ -24,15 +25,32 @@ module v3po2vpp { case vpp-state-honeycomb-reader { when "/config:modules/config:module/config:type = 'vpp-state-honeycomb-reader'"; - container vpp-japi { + container vpp-jvpp { uses config:service-ref { refine type { mandatory true; - config:required-identity vjc:vpp-japi; + config:required-identity vjvppc:vpp-jvpp; } } } + container interface-context-vpp-state { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } + + container bridge-domain-context-vpp-state { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } } } @@ -45,11 +63,29 @@ module v3po2vpp { case interfaces-state-honeycomb-reader { when "/config:modules/config:module/config:type = 'interfaces-state-honeycomb-reader'"; - container vpp-japi { + container vpp-jvpp { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vjvppc:vpp-jvpp; + } + } + } + + container interface-context-ifc-state { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } + + container bridge-domain-context-ifc-state { uses config:service-ref { refine type { mandatory true; - config:required-identity vjc:vpp-japi; + config:required-identity vpp-u:naming-context; } } } @@ -67,15 +103,32 @@ module v3po2vpp { case vpp-honeycomb-writer { when "/config:modules/config:module/config:type = 'vpp-honeycomb-writer'"; - container vpp-japi-writer { + container vpp-jvpp-writer { uses config:service-ref { refine type { mandatory true; - config:required-identity vjc:vpp-japi; + config:required-identity vjvppc:vpp-jvpp; } } } + container interface-context-vpp { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } + + container bridge-domain-context-vpp { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } } } @@ -88,11 +141,29 @@ module v3po2vpp { case interfaces-honeycomb-writer { when "/config:modules/config:module/config:type = 'interfaces-honeycomb-writer'"; - container vpp-japi-ifc { + container vpp-jvpp-ifc { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vjvppc:vpp-jvpp; + } + } + } + + container interface-context { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity vpp-u:naming-context; + } + } + } + + container bridge-domain-context { uses config:service-ref { refine type { mandatory true; - config:required-identity vjc:vpp-japi; + config:required-identity vpp-u:naming-context; } } } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizerTest.java index 111d813aa..7c88c3198 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizerTest.java @@ -16,112 +16,150 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import com.google.common.base.Optional; -import com.google.common.collect.Iterables; -import com.google.common.collect.Multimap; -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 static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.YangIfIndexToVpp; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + 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.DelegatingReaderRegistry; -import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer; -import org.junit.Before; +import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.test.ListReaderCustomizerTest; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; import org.junit.Test; -import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesStateBuilder; 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.yangtools.yang.binding.ChildOf; -import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppApi; -import org.openvpp.vppjapi.vppInterfaceDetails; -import org.openvpp.vppjapi.vppVersion; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; -import org.powermock.modules.junit4.PowerMockRunner; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceDump; -import static org.junit.Assert.assertTrue; -import static org.powermock.api.mockito.PowerMockito.mock; +public class InterfaceCustomizerTest extends + ListReaderCustomizerTest { -@RunWith(PowerMockRunner.class) -@SuppressStaticInitializationFor("org.openvpp.vppjapi.vppConn") -@PrepareForTest(vppApi.class) -public class InterfaceCustomizerTest { + private NamingContext interfacesContext; - public static final vppVersion VERSION = new vppVersion("test", "1", "2", "33"); + public InterfaceCustomizerTest() { + super(Interface.class); + } - private vppApi api; - private CompositeRootReader interfacesStateReader; - private DelegatingReaderRegistry readerRegistry; - private ReadContext ctx; + @Override + public void setUpBefore() { + interfacesContext = new NamingContext("generatedIfaceName"); + } - private CompositeRootReader getInterfacesStateReader( - final vppApi vppApi) { + @Override + protected RootReaderCustomizer initCustomizer() { + return new InterfaceCustomizer(api, interfacesContext); + } - final CompositeListReader interfacesReader = - new CompositeListReader<>(Interface.class, new InterfaceCustomizer(vppApi)); + // TODO use reflexion and move to ListReaderCustomizerTest + @Test + public void testMerge() throws Exception { + final InterfacesStateBuilder builder = mock(InterfacesStateBuilder.class); + final List value = Collections.emptyList(); + getCustomizer().merge(builder, value); + verify(builder).setInterface(value); + } - final List>> childReaders = new ArrayList<>(); - childReaders.add(interfacesReader); + private void verifyBridgeDomainDumpUpdateWasInvoked(final int nameFilterValid, final String ifaceName) { + // TODO adding equals methods for jvpp DTOs would make ArgumentCaptor usage obsolete + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(SwInterfaceDump.class); + verify(api).swInterfaceDump(argumentCaptor.capture()); + final SwInterfaceDump actual = argumentCaptor.getValue(); + assertEquals(nameFilterValid, actual.nameFilterValid); + assertArrayEquals(ifaceName.getBytes(), actual.nameFilter); + } - return new CompositeRootReader<>(InterfacesState.class, childReaders, - RWUtils.emptyAugReaderList(), - new ReflexiveRootReaderCustomizer<>(InterfacesStateBuilder.class)); + private static void assertIfacesAreEqual(final Interface iface, final SwInterfaceDetails details) { + assertEquals(iface.getName(), new String(details.interfaceName)); + assertEquals(YangIfIndexToVpp(iface.getIfIndex().intValue()), details.swIfIndex); + assertEquals(iface.getPhysAddress().getValue(), InterfaceUtils.vppPhysAddrToYang(details.l2Address)); } - public static vppInterfaceDetails createVppInterfaceDetails(int ifIndex, String name) { - return new vppInterfaceDetails( - ifIndex, name, 0, - new byte[]{ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}, - (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, 0, 0, - (byte) 0, (byte) 0, (byte) 0, (byte) 0, 0, 0, 0, 0, 0); + private void whenSwInterfaceDumpThenReturn(final List interfaceList) + throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final SwInterfaceDetailsReplyDump reply = new SwInterfaceDetailsReplyDump(); + reply.swInterfaceDetails = interfaceList; + when(replyFuture.get()).thenReturn(reply); + when(api.swInterfaceDump(any(SwInterfaceDump.class))).thenReturn(replyCS); } - @Before - public void setUp() throws Exception { - api = mock(vppApi.class); - // PowerMockito.doReturn(VERSION).when(api).getVppVersion(); - ctx = mock(ReadContext.class); - List ifaces = new ArrayList<>(); - ifaces.add(createVppInterfaceDetails(0, "loop0")); - vppInterfaceDetails[] ifArr = ifaces.toArray(new vppInterfaceDetails[ifaces.size()]); - - PowerMockito.when(api.swInterfaceDump((byte) 0, new byte[]{})). - thenReturn(ifArr); - PowerMockito.when(api.swInterfaceDump((byte) 1, ifArr[0].interfaceName.getBytes())).thenReturn(ifArr); - - interfacesStateReader = getInterfacesStateReader(api); - readerRegistry = new DelegatingReaderRegistry( - Collections.>singletonList(interfacesStateReader)); + @Test + public void testReadCurrentAttributes() throws Exception { + final String ifaceName = "eth0"; + final InstanceIdentifier id = InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class, new InterfaceKey(ifaceName)); + final InterfaceBuilder builder = getCustomizer().getBuilder(id); + + final SwInterfaceDetails iface = new SwInterfaceDetails(); + iface.interfaceName = ifaceName.getBytes(); + iface.swIfIndex = 0; + iface.linkSpeed = 1; + iface.l2AddressLength = 6; + iface.l2Address = new byte[iface.l2AddressLength]; + final List interfaceList = Collections.singletonList(iface); + whenSwInterfaceDumpThenReturn(interfaceList); + + getCustomizer().readCurrentAttributes(id, builder, ctx); + + verifyBridgeDomainDumpUpdateWasInvoked(1, ifaceName); + assertIfacesAreEqual(builder.build(), iface); } @Test - public void testReadAll() throws ReadFailedException { - final Multimap, ? extends DataObject> dataObjects = - readerRegistry.readAll(ctx); - - System.out.println(dataObjects.keys()); - final DataObject obj = Iterables.getOnlyElement( - dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet()))); - assertTrue(obj instanceof InterfacesState); + public void testReadCurrentAttributesFailed() throws Exception { + final String ifaceName = "eth0"; + final InstanceIdentifier id = InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class, new InterfaceKey(ifaceName)); + final InterfaceBuilder builder = getCustomizer().getBuilder(id); + + whenSwInterfaceDumpThenReturn(Collections.emptyList()); + + try { + getCustomizer().readCurrentAttributes(id, builder, ctx); + } catch (ReadFailedException e) { + verifyBridgeDomainDumpUpdateWasInvoked(1, ifaceName); + return; + } + + fail("ReadFailedException was expected"); } @Test - public void testReadId() throws ReadFailedException { - Optional read = - readerRegistry.read(InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey("Loofdsafdsap0")), ctx); - System.err.println(read); + public void testGetAllIds() throws Exception { + final InstanceIdentifier id = InstanceIdentifier.create(InterfacesState.class) + .child(Interface.class); + + final String swIf0Name = "eth0"; + final SwInterfaceDetails swIf0 = new SwInterfaceDetails(); + swIf0.interfaceName = swIf0Name.getBytes(); + final String swIf1Name = "eth0"; + final SwInterfaceDetails swIf1 = new SwInterfaceDetails(); + swIf1.interfaceName = swIf1Name.getBytes(); + whenSwInterfaceDumpThenReturn(Arrays.asList(swIf0, swIf1)); + + final List expectedIds = Arrays.asList(new InterfaceKey(swIf0Name), new InterfaceKey(swIf1Name)); + final List actualIds = getCustomizer().getAllIds(id, ctx); + + verifyBridgeDomainDumpUpdateWasInvoked(0, ""); + + assertEquals(expectedIds, actualIds); } } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ChildReaderCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ChildReaderCustomizerTest.java new file mode 100644 index 000000000..57369d665 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ChildReaderCustomizerTest.java @@ -0,0 +1,49 @@ +/* + * 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.test; + +import static org.junit.Assert.assertNotNull; + +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import org.junit.Test; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Generic test for classes implementing {@link ChildReaderCustomizer} interface. + * + * @param Specific DataObject derived type (Identifiable), that is handled by this customizer + * @param Specific Builder for handled type (D) + */ +public abstract class ChildReaderCustomizerTest> extends RootReaderCustomizerTest{ + + + protected ChildReaderCustomizerTest(Class dataObjectClass) { + super(dataObjectClass); + } + + @Override + protected ChildReaderCustomizer getCustomizer() { + return ChildReaderCustomizer.class.cast(super.getCustomizer()); + } + + @Test + public void testGetBuilder() throws Exception { + assertNotNull(getCustomizer().getBuilder(InstanceIdentifier.create(dataObjectClass))); + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ListReaderCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ListReaderCustomizerTest.java new file mode 100644 index 000000000..00cac2d5d --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/ListReaderCustomizerTest.java @@ -0,0 +1,52 @@ +/* + * 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.test; + +import static org.junit.Assert.assertNotNull; + +import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; +import org.junit.Test; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Generic test for classes implementing {@link ListReaderCustomizer} interface. + * + * @param Specific DataObject derived type (Identifiable), that is handled by this customizer + * @param Specific Identifier for handled type (D) + * @param Specific Builder for handled type (D) + */ +public abstract class ListReaderCustomizerTest, K extends Identifier, B extends Builder> extends RootReaderCustomizerTest{ + + + protected ListReaderCustomizerTest(Class dataObjectClass) { + super(dataObjectClass); + } + + @Override + protected ListReaderCustomizer getCustomizer() { + return ListReaderCustomizer.class.cast(super.getCustomizer()); + } + + @Test + public void testGetBuilder() throws Exception { + assertNotNull(getCustomizer().getBuilder(InstanceIdentifier.create(dataObjectClass))); + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/RootReaderCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/RootReaderCustomizerTest.java new file mode 100644 index 000000000..76eb0fb3f --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/test/RootReaderCustomizerTest.java @@ -0,0 +1,84 @@ +/* + * 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.test; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.MockitoAnnotations.initMocks; + +import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.future.FutureJVpp; + +/** + * Generic test for classes implementing {@link RootReaderCustomizer} interface. + * + * @param Specific DataObject derived type (Identifiable), that is handled by this customizer + * @param Specific Builder for handled type (D) + */ +public abstract class RootReaderCustomizerTest> { + + @Mock + protected FutureJVpp api; + @Mock + protected Context ctx; + + protected final Class dataObjectClass; + private RootReaderCustomizer customizer; + + protected RootReaderCustomizerTest(Class dataObjectClass) { + this.dataObjectClass = dataObjectClass; + } + + @Before + public void setUpParent() throws Exception { + initMocks(this); + setUpBefore(); + customizer = initCustomizer(); + setUpAfter(); + } + + /** + * Optional setup for subclasses. Invoked before customizer is initialized. + */ + protected void setUpBefore() { + + } + + /** + * Optional setup for subclasses. Invoked after customizer is initialized. + */ + protected void setUpAfter() { + + } + + protected abstract RootReaderCustomizer initCustomizer(); + + protected RootReaderCustomizer getCustomizer() { + return customizer; + } + + @Test + public void testGetBuilder() throws Exception { + assertNotNull(customizer.getBuilder(InstanceIdentifier.create(dataObjectClass))); + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtilsTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtilsTest.java index 3cb054ad4..115eb2b9c 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtilsTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtilsTest.java @@ -1,35 +1,17 @@ package io.fd.honeycomb.v3po.translate.v3po.utils; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; import org.junit.Test; -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.inet.types.rev130715.Ipv4AddressNoZone; public class V3poUtilsTest { @Test - public void testRemoveIpv4AddressNoZoneFromIpv4WithZone() throws Exception { - String ipWithZone = "1.2.3.4%20"; - String ipNoZone = "1.2.3.4"; - final Ipv4Address expectedIp = new Ipv4Address(ipNoZone); - final Ipv4AddressNoZone actualIp = V3poUtils.removeIpv4AddressNoZone(new Ipv4Address(ipWithZone)); - assertEquals(expectedIp.getValue(), actualIp.getValue()); - } - - @Test - public void testRemoveIpv4AddressNoZoneFromIpv4WithoutZone() throws Exception { - String ipNoZone = "1.2.3.4"; - final Ipv4Address expectedIp = new Ipv4Address(ipNoZone); - final Ipv4AddressNoZone actualIp = V3poUtils.removeIpv4AddressNoZone(expectedIp); - assertEquals(expectedIp.getValue(), actualIp.getValue()); - } - - @Test - public void testRemoveIpv4AddressNoZoneNop() throws Exception { - String ipNoZone = "1.2.3.4"; - final Ipv4Address expectedIp = new Ipv4AddressNoZone(ipNoZone); - final Ipv4AddressNoZone actualIp = V3poUtils.removeIpv4AddressNoZone(expectedIp); - assertEquals(expectedIp, actualIp); + public void testToString() { + final byte[] expected = "test".getBytes(); + final byte[] cString = new byte[expected.length+10]; + System.arraycopy(expected, 0, cString, 0, expected.length); + final String jString = V3poUtils.toString(cString); + assertArrayEquals(expected, jString.getBytes()); } } \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizerTest.java index f504918a8..5d5781adb 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizerTest.java @@ -13,57 +13,53 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package io.fd.honeycomb.v3po.translate.v3po.vpp; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; 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.BridgeDomainBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey; -import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; -import org.openvpp.vppjapi.vppApi; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@SuppressStaticInitializationFor("org.openvpp.vppjapi.vppConn") -@PrepareForTest(vppApi.class) +import org.openvpp.jvpp.dto.BridgeDomainAddDel; +import org.openvpp.jvpp.dto.BridgeDomainAddDelReply; +import org.openvpp.jvpp.future.FutureJVpp; + public class BridgeDomainCustomizerTest { - private static final int RESPONSE_NOT_READY = -77; private static final byte ADD_OR_UPDATE_BD = (byte) 1; private static final byte ZERO = 0; - private vppApi api; + + @Mock + private FutureJVpp api; @Mock private Context ctx; private BridgeDomainCustomizer customizer; + private NamingContext namingContext; @Before public void setUp() throws Exception { - // TODO create base class for tests using vppApi - api = PowerMockito.mock(vppApi.class); initMocks(this); - customizer = new BridgeDomainCustomizer(api); - - PowerMockito.doAnswer(BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER).when(api).findOrAddBridgeDomainId(anyString()); - PowerMockito.doAnswer(BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER).when(api).bridgeDomainIdFromName(anyString()); - PowerMockito.when(api.getRetval(anyInt(), anyInt())).thenReturn(RESPONSE_NOT_READY).thenReturn(0); - PowerMockito.doReturn(0).when(api).getRetval(anyInt(), anyInt()); + // TODO create base class for tests using vppApi + namingContext = new NamingContext("generatedBDName"); + customizer = new BridgeDomainCustomizer(api, namingContext); } private BridgeDomain generateBridgeDomain(final String bdName) { @@ -87,127 +83,140 @@ public class BridgeDomainCustomizerTest { .build(); } - private final int verifyBridgeDomainAddOrUpdateWasInvoked(final BridgeDomain bd) { - final int bdn1Id = BridgeDomainTestUtils.bdNameToID(bd.getName()); + private void verifyBridgeDomainAddOrUpdateWasInvoked(final BridgeDomain bd, final int bdId) { final byte arpTerm = BridgeDomainTestUtils.booleanToByte(bd.isArpTermination()); final byte flood = BridgeDomainTestUtils.booleanToByte(bd.isFlood()); final byte forward = BridgeDomainTestUtils.booleanToByte(bd.isForward()); final byte learn = BridgeDomainTestUtils.booleanToByte(bd.isLearn()); final byte uuf = BridgeDomainTestUtils.booleanToByte(bd.isUnknownUnicastFlood()); - return verify(api).bridgeDomainAddDel(bdn1Id, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); + + // TODO adding equals methods for jvpp DTOs would make ArgumentCaptor usage obsolete + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(BridgeDomainAddDel.class); + verify(api).bridgeDomainAddDel(argumentCaptor.capture()); + final BridgeDomainAddDel actual = argumentCaptor.getValue(); + assertEquals(arpTerm, actual.arpTerm); + assertEquals(flood, actual.flood); + assertEquals(forward, actual.forward); + assertEquals(learn, actual.learn); + assertEquals(uuf, actual.uuFlood); + assertEquals(ADD_OR_UPDATE_BD, actual.isAdd); + assertEquals(bdId, actual.bdId); } - private int verifyBridgeDomainAddOrUpdateWasNotInvoked(final BridgeDomain bd) { - final int bdn1Id = BridgeDomainTestUtils.bdNameToID(bd.getName()); - final byte arpTerm = BridgeDomainTestUtils.booleanToByte(bd.isArpTermination()); - final byte flood = BridgeDomainTestUtils.booleanToByte(bd.isFlood()); - final byte forward = BridgeDomainTestUtils.booleanToByte(bd.isForward()); - final byte learn = BridgeDomainTestUtils.booleanToByte(bd.isLearn()); - final byte uuf = BridgeDomainTestUtils.booleanToByte(bd.isUnknownUnicastFlood()); - return verify(api, never()).bridgeDomainAddDel(bdn1Id, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); + private void verifyBridgeDomainDeleteWasInvoked(final int bdId) { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(BridgeDomainAddDel.class); + verify(api).bridgeDomainAddDel(argumentCaptor.capture()); + final BridgeDomainAddDel actual = argumentCaptor.getValue(); + assertEquals(bdId, actual.bdId); + assertEquals(ZERO, actual.arpTerm); + assertEquals(ZERO, actual.flood); + assertEquals(ZERO, actual.forward); + assertEquals(ZERO, actual.learn); + assertEquals(ZERO, actual.uuFlood); + assertEquals(ZERO, actual.isAdd); + } + + private void whenBridgeDomainAddDelThen(final int retval) throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final BridgeDomainAddDelReply reply = new BridgeDomainAddDelReply(); + reply.retval = retval; + when(replyFuture.get()).thenReturn(reply); + when(api.bridgeDomainAddDel(any(BridgeDomainAddDel.class))).thenReturn(replyCS); } - private int verifyBridgeDomainDeletedWasInvoked(final BridgeDomain bd) { - final int bdn1Id = BridgeDomainTestUtils.bdNameToID(bd.getName()); - return verify(api).bridgeDomainAddDel(bdn1Id, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO); + private void whenBridgeDomainAddDelThenSuccess() throws ExecutionException, InterruptedException { + whenBridgeDomainAddDelThen(0); } - private int verifyBridgeDomainDeletedWasNotInvoked(final BridgeDomain bd) { - final int bdn1Id = BridgeDomainTestUtils.bdNameToID(bd.getName()); - return verify(api, never()).bridgeDomainAddDel(bdn1Id, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO); + private void whenBridgeDomainAddDelThenFailure() throws ExecutionException, InterruptedException { + whenBridgeDomainAddDelThen(-1); } @Test - public void testAddBridgeDomain() { + public void testAddBridgeDomain() throws Exception { + final int bdId = 1; final String bdName = "bd1"; - final BridgeDomain bd = generateBridgeDomain("bd1"); + final BridgeDomain bd = generateBridgeDomain(bdName); + + whenBridgeDomainAddDelThenSuccess(); customizer.writeCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - verifyBridgeDomainAddOrUpdateWasInvoked(bd); + verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId); } @Test - public void testBridgeDomainNameCreateFailed() { + public void testAddBridgeDomainFailed() throws Exception { + final int bdId = 1; final String bdName = "bd1"; - final BridgeDomain bd = generateBridgeDomain("bd1"); + final BridgeDomain bd = generateBridgeDomain(bdName); - // make vpp api fail to create id for our bd name - PowerMockito.doReturn(-1).when(api).findOrAddBridgeDomainId(bdName); + whenBridgeDomainAddDelThenFailure(); try { customizer.writeCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainAddOrUpdateWasNotInvoked(bd); + } catch (WriteFailedException.CreateFailedException e) { + verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId); return; } - fail("IllegalStateException was expected"); + fail("WriteFailedException.CreateFailedException was expected"); } @Test - public void testAddBridgeDomainFailed() { - // make any call to vpp fail - PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); - + public void testDeleteBridgeDomain() throws Exception { + final int bdId = 1; final String bdName = "bd1"; final BridgeDomain bd = generateBridgeDomain(bdName); + namingContext.addName(bdId, bdName); - try { - customizer.writeCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainAddOrUpdateWasInvoked(bd); - return; - } - fail("IllegalStateException was expected"); - } - - @Test - public void testDeleteBridgeDomain() { - final String bdName = "bd1"; - final BridgeDomain bd = generateBridgeDomain("bd1"); + whenBridgeDomainAddDelThenSuccess(); customizer.deleteCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - verifyBridgeDomainDeletedWasInvoked(bd); + verifyBridgeDomainDeleteWasInvoked(bdId); } @Test - public void testDeleteUnknownBridgeDomain() { + public void testDeleteUnknownBridgeDomain() throws Exception { final String bdName = "bd1"; final BridgeDomain bd = generateBridgeDomain("bd1"); - // make vpp api not find our bd - PowerMockito.doReturn(-1).when(api).bridgeDomainIdFromName(bdName); - try { customizer.deleteCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainDeletedWasNotInvoked(bd); + } catch (IllegalArgumentException e) { + verify(api, never()).bridgeDomainAddDel(any(BridgeDomainAddDel.class)); return; } - fail("IllegalStateException was expected"); + fail("IllegalArgumentException was expected"); } @Test - public void testDeleteBridgeDomainFailed() { - // make any call to vpp fail - PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); - + public void testDeleteBridgeDomainFailed() throws Exception { + final int bdId = 1; final String bdName = "bd1"; final BridgeDomain bd = generateBridgeDomain(bdName); + namingContext.addName(bdId, bdName); + + whenBridgeDomainAddDelThenFailure(); try { customizer.deleteCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainDeletedWasInvoked(bd); + } catch (WriteFailedException.DeleteFailedException e) { + verifyBridgeDomainDeleteWasInvoked(bdId); return; } - fail("IllegalStateException was expected"); + + fail("WriteFailedException.DeleteFailedException was expected"); } @Test public void testUpdateBridgeDomain() throws Exception { + final int bdId = 1; final String bdName = "bd1"; + namingContext.addName(bdId, bdName); + final byte arpTermBefore = 1; final byte floodBefore = 1; final byte forwardBefore = 0; @@ -220,11 +229,11 @@ public class BridgeDomainCustomizerTest { generateBridgeDomain(bdName, arpTermBefore ^ 1, floodBefore ^ 1, forwardBefore ^ 1, learnBefore ^ 1, uufBefore ^ 1); - final KeyedInstanceIdentifier id = BridgeDomainTestUtils.bdIdentifierForName(bdName); + whenBridgeDomainAddDelThenSuccess(); - customizer.updateCurrentAttributes(id, dataBefore, dataAfter, ctx); + customizer.updateCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), dataBefore, dataAfter, ctx); - verifyBridgeDomainAddOrUpdateWasInvoked(dataAfter); + verifyBridgeDomainAddOrUpdateWasInvoked(dataAfter, bdId); } @Test @@ -232,30 +241,28 @@ public class BridgeDomainCustomizerTest { final String bdName = "bd1"; final BridgeDomain bd = generateBridgeDomain("bd1"); - // make vpp api not find our bd - PowerMockito.doReturn(-1).when(api).bridgeDomainIdFromName(bdName); - try { customizer.updateCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainAddOrUpdateWasNotInvoked(bd); + } catch (IllegalArgumentException e) { + verify(api, never()).bridgeDomainAddDel(any(BridgeDomainAddDel.class)); return; } - fail("IllegalStateException was expected"); + fail("IllegalArgumentException was expected"); } @Test - public void testUpdateBridgeDomainFailed() { - // make any call to vpp fail - PowerMockito.doReturn(-1).when(api).getRetval(anyInt(), anyInt()); - + public void testUpdateBridgeDomainFailed() throws Exception { + final int bdId = 1; final String bdName = "bd1"; final BridgeDomain bd = generateBridgeDomain(bdName); + namingContext.addName(bdId, bdName); + + whenBridgeDomainAddDelThenFailure(); try { customizer.updateCurrentAttributes(BridgeDomainTestUtils.bdIdentifierForName(bdName), bd, bd, ctx); - } catch (IllegalStateException e) { - verifyBridgeDomainAddOrUpdateWasInvoked(bd); + } catch (WriteFailedException.UpdateFailedException e) { + verifyBridgeDomainAddOrUpdateWasInvoked(bd, bdId); return; } fail("IllegalStateException was expected"); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppTest.java index 0ff3ba16d..820cf0555 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppTest.java @@ -16,23 +16,28 @@ package io.fd.honeycomb.v3po.translate.v3po.vpp; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import com.google.common.collect.Iterators; import com.google.common.collect.Lists; import io.fd.honeycomb.v3po.translate.impl.write.CompositeRootWriter; -import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.util.write.DelegatingWriterRegistry; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.write.Writer; import java.util.Collections; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; 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.VppBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.BridgeDomains; @@ -41,98 +46,147 @@ 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.bridge.domains.BridgeDomainBuilder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppApi; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@SuppressStaticInitializationFor("org.openvpp.vppjapi.vppConn") -@PrepareForTest(vppApi.class) +import org.openvpp.jvpp.dto.BridgeDomainAddDel; +import org.openvpp.jvpp.dto.BridgeDomainAddDelReply; +import org.openvpp.jvpp.future.FutureJVpp; + public class VppTest { - private vppApi api; + private static final byte ADD_OR_UPDATE_BD = 1; + private static final byte ZERO = 0; + private FutureJVpp api; private DelegatingWriterRegistry rootRegistry; private CompositeRootWriter vppWriter; private WriteContext ctx; - - final byte zero = (byte) 0; - final byte flood = (byte) 1; - final byte forward = (byte) 0; - final byte learn = (byte) 1; - final byte uuf = (byte) 0; - final byte arpTerm = (byte) 0; - final byte add = (byte) 1; + private NamingContext bdContext; @Before public void setUp() throws Exception { - api = PowerMockito.mock(vppApi.class); + api = mock(FutureJVpp.class); ctx = mock(WriteContext.class); - PowerMockito.doAnswer(BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER).when(api).findOrAddBridgeDomainId(anyString()); - PowerMockito.doAnswer(BridgeDomainTestUtils.BD_NAME_TO_ID_ANSWER).when(api).bridgeDomainIdFromName(anyString()); - PowerMockito.doReturn(1).when(api).getRetval(anyInt(), anyInt()); - vppWriter = VppUtils.getVppWriter(api); + bdContext = new NamingContext("generatedBdName"); + vppWriter = VppUtils.getVppWriter(api, bdContext); rootRegistry = new DelegatingWriterRegistry( Collections.>singletonList(vppWriter)); } + private BridgeDomains getBridgeDomains(String... name) { + final List bdmns = Lists.newArrayList(); + for (String s : name) { + bdmns.add(new BridgeDomainBuilder() + .setName(s) + .setArpTermination(false) + .setFlood(true) + .setForward(false) + .setLearn(true) + .build()); + } + return new BridgeDomainsBuilder() + .setBridgeDomain(bdmns) + .build(); + } + + private void whenBridgeDomainAddDelThen(final int retval) throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final BridgeDomainAddDelReply reply = new BridgeDomainAddDelReply(); + reply.retval = retval; + when(replyFuture.get()).thenReturn(reply); + when(api.bridgeDomainAddDel(any(BridgeDomainAddDel.class))).thenReturn(replyCS); + } + + private void verifyBridgeDomainAddDel(final BridgeDomain bd, final int bdId) { + final byte arpTerm = BridgeDomainTestUtils.booleanToByte(bd.isArpTermination()); + final byte flood = BridgeDomainTestUtils.booleanToByte(bd.isFlood()); + final byte forward = BridgeDomainTestUtils.booleanToByte(bd.isForward()); + final byte learn = BridgeDomainTestUtils.booleanToByte(bd.isLearn()); + final byte uuf = BridgeDomainTestUtils.booleanToByte(bd.isUnknownUnicastFlood()); + + // TODO adding equals methods for jvpp DTOs would make ArgumentCaptor usage obsolete + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(BridgeDomainAddDel.class); + verify(api).bridgeDomainAddDel(argumentCaptor.capture()); + final BridgeDomainAddDel actual = argumentCaptor.getValue(); + assertEquals(arpTerm, actual.arpTerm); + assertEquals(flood, actual.flood); + assertEquals(forward, actual.forward); + assertEquals(learn, actual.learn); + assertEquals(uuf, actual.uuFlood); + assertEquals(ADD_OR_UPDATE_BD, actual.isAdd); + assertEquals(bdId, actual.bdId); + } + + private void verifyBridgeDomainDeleteWasInvoked(final int bdId) { + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(BridgeDomainAddDel.class); + verify(api).bridgeDomainAddDel(argumentCaptor.capture()); + final BridgeDomainAddDel actual = argumentCaptor.getValue(); + assertEquals(bdId, actual.bdId); + assertEquals(ZERO, actual.arpTerm); + assertEquals(ZERO, actual.flood); + assertEquals(ZERO, actual.forward); + assertEquals(ZERO, actual.learn); + assertEquals(ZERO, actual.uuFlood); + assertEquals(ZERO, actual.isAdd); + } + @Test - public void writeVpp() throws Exception { + public void writeVppUsingRootRegistry() throws Exception { + final int bdId = 1; + final BridgeDomains bdn1 = getBridgeDomains("bdn1"); + whenBridgeDomainAddDelThen(0); + rootRegistry.update( - InstanceIdentifier.create(Vpp.class), - null, - new VppBuilder().setBridgeDomains(getBridgeDomains("bdn1")).build(), - ctx); + InstanceIdentifier.create(Vpp.class), + null, + new VppBuilder().setBridgeDomains(bdn1).build(), + ctx); + + verifyBridgeDomainAddDel(Iterators.getOnlyElement(bdn1.getBridgeDomain().iterator()), bdId); + } - verify(api).bridgeDomainAddDel(1, flood, forward, learn, uuf, arpTerm, add); + @Test + public void writeVppUsingVppWriter() throws Exception { + final int bdId = 1; + final BridgeDomains bdn1 = getBridgeDomains("bdn1"); + whenBridgeDomainAddDelThen(0); vppWriter.update(InstanceIdentifier.create(Vpp.class), - null, - new VppBuilder().setBridgeDomains(getBridgeDomains("bdn1")).build(), - ctx); + null, + new VppBuilder().setBridgeDomains(bdn1).build(), + ctx); - verify(api, times(2)).bridgeDomainAddDel(1, flood, forward, learn, uuf, arpTerm, add); + verifyBridgeDomainAddDel(Iterators.getOnlyElement(bdn1.getBridgeDomain().iterator()), bdId); } @Test public void writeVppFromRoot() throws Exception { - final Vpp vpp = new VppBuilder().setBridgeDomains(getBridgeDomains("bdn1")).build(); + final BridgeDomains bdn1 = getBridgeDomains("bdn1"); + final int bdId = 1; + final Vpp vpp = new VppBuilder().setBridgeDomains(bdn1).build(); + whenBridgeDomainAddDelThen(0); rootRegistry.update(Collections., DataObject>emptyMap(), Collections., DataObject>singletonMap(InstanceIdentifier.create(Vpp.class), vpp), ctx); - verify(api).bridgeDomainAddDel(1, flood, forward, learn, uuf, arpTerm, add); - } - - private BridgeDomains getBridgeDomains(String... name) { - final List bdmns = Lists.newArrayList(); - for (String s : name) { - bdmns.add(new BridgeDomainBuilder() - .setName(s) - .setArpTermination(false) - .setFlood(true) - .setForward(false) - .setLearn(true) - .build()); - } - return new BridgeDomainsBuilder() - .setBridgeDomain(bdmns) - .build(); + verifyBridgeDomainAddDel(Iterators.getOnlyElement(bdn1.getBridgeDomain().iterator()), bdId); } @Test public void deleteVpp() throws Exception { + final String bdName = "bdn1"; + final BridgeDomains bdn1 = getBridgeDomains(bdName); + final int bdId = 1; + whenBridgeDomainAddDelThen(0); + bdContext.addName(bdId, bdName); + rootRegistry.update( InstanceIdentifier.create(Vpp.class), - new VppBuilder().setBridgeDomains(getBridgeDomains("bdn1")).build(), + new VppBuilder().setBridgeDomains(bdn1).build(), null, ctx); - final byte zero = (byte) 0; - - verify(api).bridgeDomainAddDel(1, zero, zero, zero, zero, zero, zero); + verifyBridgeDomainDeleteWasInvoked(bdId); } @Test @@ -148,7 +202,10 @@ public class VppTest { @Test public void writeUpdate() throws Exception { - final BridgeDomains domainsBefore = getBridgeDomains("bdn1"); + final String bdName = "bdn1"; + final int bdn1Id = 1; + bdContext.addName(bdn1Id, bdName); + final BridgeDomains domainsBefore = getBridgeDomains(bdName); final BridgeDomain bdn1Before = domainsBefore.getBridgeDomain().get(0); final BridgeDomain bdn1After = new BridgeDomainBuilder(bdn1Before).setFlood(!bdn1Before.isFlood()).build(); @@ -156,16 +213,16 @@ public class VppTest { .setBridgeDomain(Collections.singletonList(bdn1After)) .build(); + whenBridgeDomainAddDelThen(0); + rootRegistry.update( InstanceIdentifier.create(Vpp.class), new VppBuilder().setBridgeDomains(domainsBefore).build(), new VppBuilder().setBridgeDomains(domainsAfter).build(), ctx); - final int bdn1Id = 1; - // bdn1 is created with negated flood value - verify(api).bridgeDomainAddDel(bdn1Id, (byte) (flood ^ 1), forward, learn, uuf, arpTerm, add); + verifyBridgeDomainAddDel(bdn1After, bdn1Id); } // TODO test unkeyed list diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppUtils.java index cb74314e3..4b3eb5adc 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppUtils.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vpp/VppUtils.java @@ -19,10 +19,11 @@ package io.fd.honeycomb.v3po.translate.v3po.vpp; 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.NoopWriterCustomizer; import io.fd.honeycomb.v3po.translate.util.write.ReflexiveChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.write.ChildWriter; -import io.fd.honeycomb.v3po.translate.util.RWUtils; import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; @@ -31,7 +32,7 @@ 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.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.openvpp.vppjapi.vppApi; +import org.openvpp.jvpp.future.FutureJVpp; final class VppUtils { @@ -40,11 +41,11 @@ final class VppUtils { /** * Create root Vpp writer with all its children wired */ - static CompositeRootWriter getVppWriter(@Nonnull final vppApi vppApi) { + static CompositeRootWriter getVppWriter(@Nonnull final FutureJVpp vppApi, final NamingContext bdContext) { final CompositeListWriter bridgeDomainWriter = new CompositeListWriter<>( BridgeDomain.class, - new BridgeDomainCustomizer(vppApi)); + new BridgeDomainCustomizer(vppApi, bdContext)); final ChildWriter bridgeDomainsReader = new CompositeChildWriter<>( BridgeDomains.class, diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizerTest.java new file mode 100644 index 000000000..c482c4485 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizerTest.java @@ -0,0 +1,59 @@ +/* + * 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.vppstate; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.test.ListReaderCustomizerTest; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomainsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain; +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; + +public class BridgeDomainCustomizerTest extends ListReaderCustomizerTest { + + private NamingContext bdContext; + private NamingContext interfacesContext; + + public BridgeDomainCustomizerTest() { + super(BridgeDomain.class); + } + + @Override + public void setUpBefore() { + bdContext = new NamingContext("generatedBdName"); + interfacesContext = new NamingContext("generatedIfaceName"); + } + + @Test + public void testMerge() throws Exception { + final BridgeDomainsBuilder builder = mock(BridgeDomainsBuilder.class); + final List value = Collections.emptyList(); + getCustomizer().merge(builder, value); + verify(builder).setBridgeDomain(value); + } + + @Override + protected RootReaderCustomizer initCustomizer() { + return new BridgeDomainCustomizer(api, bdContext, interfacesContext); + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizerTest.java new file mode 100644 index 000000000..03b923102 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizerTest.java @@ -0,0 +1,73 @@ +/* + * 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.vppstate; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import org.junit.Test; +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.Version; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.VersionBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; + +public class VersionCustomizerTest extends ChildReaderCustomizerTest { + + public VersionCustomizerTest() { + super(Version.class); + } + + @Override + protected ChildReaderCustomizer initCustomizer() { + return new VersionCustomizer(api); + } + + @Test + public void testMerge() { + final VppStateBuilder builder = mock(VppStateBuilder.class); + final Version value = mock(Version.class); + getCustomizer().merge(builder, value); + verify(builder).setVersion(value); + } + + @Test + public void testReadCurrentAttributes() throws Exception { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final ShowVersionReply reply = new ShowVersionReply(); + reply.retval = 0; + reply.version = new byte[]{}; + reply.program = new byte[]{}; + reply.buildDate = new byte[]{}; + reply.buildDirectory = new byte[]{}; + when(replyFuture.get()).thenReturn(reply); + when(api.showVersion(any(ShowVersion.class))).thenReturn(replyCS); + + getCustomizer().readCurrentAttributes(InstanceIdentifier.create(Version.class), new VersionBuilder(), ctx); + + verify(api).showVersion(any(ShowVersion.class)); + } +} \ No newline at end of file diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTest.java index 6f53f6519..bf1d12152 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTest.java @@ -19,27 +19,30 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; import com.google.common.base.Optional; -import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import io.fd.honeycomb.v3po.translate.impl.read.CompositeListReader; import io.fd.honeycomb.v3po.translate.impl.read.CompositeRootReader; -import io.fd.honeycomb.v3po.translate.util.read.DelegatingReaderRegistry; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.Reader; +import io.fd.honeycomb.v3po.translate.util.read.DelegatingReaderRegistry; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Matchers; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; 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; @@ -53,131 +56,123 @@ 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.bridge.domain.L2FibKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppApi; -import org.openvpp.vppjapi.vppBridgeDomainDetails; -import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails; -import org.openvpp.vppjapi.vppL2Fib; -import org.openvpp.vppjapi.vppVersion; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; -import org.powermock.modules.junit4.PowerMockRunner; - -@RunWith(PowerMockRunner.class) -@SuppressStaticInitializationFor("org.openvpp.vppjapi.vppConn") -@PrepareForTest(vppApi.class) +import org.openvpp.jvpp.dto.BridgeDomainDetails; +import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; +import org.openvpp.jvpp.dto.BridgeDomainDump; +import org.openvpp.jvpp.dto.L2FibTableDump; +import org.openvpp.jvpp.dto.L2FibTableEntry; +import org.openvpp.jvpp.dto.L2FibTableEntryReplyDump; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; +import org.openvpp.jvpp.future.FutureJVpp; + public class VppStateTest { - public static final vppVersion VERSION = new vppVersion("test", "1", "2", "33"); + @Mock + private FutureJVpp api; + @Mock + private ReadContext ctx; + + private NamingContext bdContext; + private NamingContext interfaceContext; - private vppApi api; private CompositeRootReader vppStateReader; private DelegatingReaderRegistry readerRegistry; - private vppBridgeDomainDetails bdDetails; - private vppBridgeDomainDetails bdDetails2; - private ReadContext ctx; @Before public void setUp() throws Exception { - api = PowerMockito.mock(vppApi.class); - - ctx = mock(ReadContext.class); - - bdDetails = new vppBridgeDomainDetails(); - setIfcs(bdDetails); - setBaseAttrs(bdDetails, "bdn1", 1); - - bdDetails2 = new vppBridgeDomainDetails(); - setIfcs(bdDetails2); - setBaseAttrs(bdDetails2, "bdn2", 2); - - final vppL2Fib[] l2Fibs = getL2Fibs(); - PowerMockito.doReturn(l2Fibs).when(api).l2FibTableDump(Matchers.anyInt()); - PowerMockito.doAnswer(new Answer() { - - @Override - public vppBridgeDomainDetails answer(final InvocationOnMock invocationOnMock) throws Throwable { - final Integer idx = (Integer) invocationOnMock.getArguments()[0]; - switch (idx) { - case 1 : return bdDetails; - case 2 : return bdDetails2; - default: return null; - } - } - }).when(api).getBridgeDomainDetails(Matchers.anyInt()); - - PowerMockito.doAnswer(new Answer() { - @Override - public Object answer(final InvocationOnMock invocationOnMock) throws Throwable { - final String name = (String) invocationOnMock.getArguments()[0]; - switch (name) { - case "bdn1" : return 1; - case "bdn2" : return 2; - default: return null; - } - } - }).when(api).bridgeDomainIdFromName(anyString()); - PowerMockito.doReturn(new int[] {1, 2}).when(api).bridgeDomainDump(Matchers.anyInt()); - PowerMockito.doReturn(VERSION).when(api).getVppVersion(); - vppStateReader = VppStateUtils.getVppStateReader(api); + initMocks(this); + + bdContext = new NamingContext("generatedBdName"); + interfaceContext = new NamingContext("generatedInterfaceName"); + vppStateReader = VppStateTestUtils.getVppStateReader(api, bdContext, interfaceContext); readerRegistry = new DelegatingReaderRegistry(Collections.>singletonList(vppStateReader)); } - private vppL2Fib[] getL2Fibs() { - return new vppL2Fib[] { - new vppL2Fib(new byte[]{1,2,3,4,5,6}, true, "ifc1", true, true), - new vppL2Fib(new byte[]{2,2,3,4,5,6}, true, "ifc2", true, true), - }; + private static Version getVersion() { + return new VersionBuilder() + .setName("test") + .setBuildDirectory("1") + .setBranch("2") + .setBuildDate("3") + .build(); } - private void setIfcs(final vppBridgeDomainDetails bdDetails) { - final vppBridgeDomainInterfaceDetails ifcDetails = new vppBridgeDomainInterfaceDetails(); - ifcDetails.interfaceName = "ifc"; - ifcDetails.splitHorizonGroup = 2; - bdDetails.interfaces = new vppBridgeDomainInterfaceDetails[] {ifcDetails}; + private void whenShowVersionThenReturn(int retval, Version version) throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final ShowVersionReply reply = new ShowVersionReply(); + reply.retval = 0; // success + reply.buildDate = version.getBuildDate().getBytes(); + reply.program = version.getName().getBytes(); + reply.version = version.getBranch().getBytes(); + reply.buildDirectory = version.getBuildDirectory().getBytes(); + when(replyFuture.get()).thenReturn(reply); + when(api.showVersion(any(ShowVersion.class))).thenReturn(replyCS); } - private void setBaseAttrs(final vppBridgeDomainDetails bdDetails, final String bdn, final int i) { - bdDetails.name = bdn; - bdDetails.arpTerm = true; - bdDetails.bdId = i; - bdDetails.bviInterfaceName = "ifc"; - bdDetails.flood = true; - bdDetails.forward = true; - bdDetails.learn = true; - bdDetails.uuFlood = true; + private void whenL2FibTableDumpThenReturn(final List entryList) throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final L2FibTableEntryReplyDump reply = new L2FibTableEntryReplyDump(); + reply.l2FibTableEntry = entryList; + when(replyFuture.get()).thenReturn(reply); + when(api.l2FibTableDump(any(L2FibTableDump.class))).thenReturn(replyCS); + } + + private void whenBridgeDomainDumpThenReturn(final List bdList) throws ExecutionException, InterruptedException { + final CompletionStage replyCS = mock(CompletionStage.class); + final CompletableFuture replyFuture = mock(CompletableFuture.class); + when(replyCS.toCompletableFuture()).thenReturn(replyFuture); + final BridgeDomainDetailsReplyDump reply = new BridgeDomainDetailsReplyDump(); + reply.bridgeDomainDetails = bdList; + when(replyFuture.get()).thenReturn(reply); + + doAnswer(invocation -> { + BridgeDomainDump request = (BridgeDomainDump)invocation.getArguments()[0]; + if (request.bdId == -1) { + reply.bridgeDomainDetails = bdList; + } else { + reply.bridgeDomainDetails = Collections.singletonList(bdList.get(request.bdId)); + } + return replyCS; + }).when(api).bridgeDomainDump(any(BridgeDomainDump.class)); } @Test public void testReadAll() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(0, version); + + final List bdList = Arrays.asList(new BridgeDomainDetails(), new BridgeDomainDetails()); + whenBridgeDomainDumpThenReturn(bdList); + final Multimap, ? extends DataObject> dataObjects = readerRegistry.readAll(ctx); assertEquals(dataObjects.size(), 1); - final DataObject dataObject = Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet()))); - assertTrue(dataObject instanceof VppState); - assertVersion((VppState) dataObject); - assertEquals(2, ((VppState) dataObject).getBridgeDomains().getBridgeDomain().size()); - } - - private void assertVersion(final VppState dataObject) { - assertEquals( - new VersionBuilder() - .setName("test") - .setBuildDirectory("1") - .setBranch("2") - .setBuildDate("33") - .build(), - dataObject.getVersion()); + final VppState dataObject = (VppState)Iterables.getOnlyElement(dataObjects.get(Iterables.getOnlyElement(dataObjects.keySet()))); + assertEquals(version, dataObject.getVersion()); + assertEquals(2, dataObject.getBridgeDomains().getBridgeDomain().size()); } @Test public void testReadSpecific() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(0, version); + whenBridgeDomainDumpThenReturn(Collections.emptyList()); + final Optional read = readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx); assertTrue(read.isPresent()); - assertVersion((VppState) read.get()); + assertEquals(version, ((VppState) read.get()).getVersion()); } @Test public void testReadBridgeDomains() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(0, version); + whenBridgeDomainDumpThenReturn(Collections.singletonList(new BridgeDomainDetails())); + VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); Optional read = @@ -191,6 +186,16 @@ public class VppStateTest { */ @Test public void testReadL2Fib() throws Exception { + final BridgeDomainDetails bd = new BridgeDomainDetails(); + bd.bdId = 0; + final String bdName = "bdn1"; + bdContext.addName(bd.bdId, bdName); + whenBridgeDomainDumpThenReturn(Collections.singletonList(bd)); + final L2FibTableEntry l2FibEntry = new L2FibTableEntry(); + l2FibEntry.bdId = 0; + l2FibEntry.mac = 0x0605040302010000L; + whenL2FibTableDumpThenReturn(Collections.singletonList(l2FibEntry)); + // Deep child without a dedicated reader with specific l2fib key Optional read = readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( @@ -208,10 +213,14 @@ public class VppStateTest { @Test public void testReadBridgeDomainAll() throws Exception { + final Version version = getVersion(); + whenShowVersionThenReturn(0, version); + whenBridgeDomainDumpThenReturn(Collections.singletonList(new BridgeDomainDetails())); + VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); final CompositeListReader bridgeDomainReader = - VppStateUtils.getBridgeDomainReader(api); + VppStateTestUtils.getBridgeDomainReader(api, bdContext, interfaceContext); final List read = bridgeDomainReader.readList(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( @@ -222,24 +231,25 @@ public class VppStateTest { @Test public void testReadBridgeDomain() throws Exception { + final BridgeDomainDetails bd = new BridgeDomainDetails(); + bd.bdId = 0; + final String bdName = "bdn1"; + bdContext.addName(bd.bdId, bdName); + whenBridgeDomainDumpThenReturn(Collections.singletonList(bd)); + whenShowVersionThenReturn(0, getVersion()); + VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); final Optional read = readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( - BridgeDomain.class, new BridgeDomainKey("bdn1")), ctx); + BridgeDomain.class, new BridgeDomainKey(bdName)), ctx); assertTrue(read.isPresent()); - assertEquals(Iterables.find(readRoot.getBridgeDomains().getBridgeDomain(), new Predicate() { - @Override - public boolean apply(final BridgeDomain input) { - return input.getKey().getName().equals("bdn1"); - } - }), read.get()); + assertEquals(Iterables.find(readRoot.getBridgeDomains().getBridgeDomain(), + input -> input.getKey().getName().equals(bdName)), read.get()); } - // FIXME - @Ignore("Bridge domain customizer does not check whether the bd exists or not and fails with NPE, add it there") - @Test + @Test(expected = IllegalArgumentException.class) public void testReadBridgeDomainNotExisting() throws Exception { final Optional read = readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( @@ -249,6 +259,8 @@ public class VppStateTest { @Test public void testReadVersion() throws Exception { + whenShowVersionThenReturn(0, getVersion()); + whenBridgeDomainDumpThenReturn(Collections.emptyList()); VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); Optional read = diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTestUtils.java new file mode 100644 index 000000000..688f75911 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateTestUtils.java @@ -0,0 +1,82 @@ +/* + * 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.vppstate; + +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.util.RWUtils; +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.util.NamingContext; +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; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomainsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.Version; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain; +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.openvpp.jvpp.future.FutureJVpp; + +final class VppStateTestUtils { + + public VppStateTestUtils() { + } + + /** + * Create root VppState reader with all its children wired + */ + static CompositeRootReader getVppStateReader(@Nonnull final FutureJVpp futureJVpp, + @Nonnull final NamingContext bdContext, + @Nonnull final NamingContext interfaceContext) { + + final ChildReader versionReader = new CompositeChildReader<>( + Version.class, new VersionCustomizer(futureJVpp)); + + final CompositeListReader bridgeDomainReader = + getBridgeDomainReader(futureJVpp, bdContext, interfaceContext); + + final ChildReader bridgeDomainsReader = new CompositeChildReader<>( + BridgeDomains.class, + RWUtils.singletonChildReaderList(bridgeDomainReader), + new ReflexiveChildReaderCustomizer<>(BridgeDomainsBuilder.class)); + + final List>> childVppReaders = new ArrayList<>(); + childVppReaders.add(versionReader); + childVppReaders.add(bridgeDomainsReader); + + return new CompositeRootReader<>( + VppState.class, + childVppReaders, + RWUtils.emptyAugReaderList(), + new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class)); + } + + static CompositeListReader getBridgeDomainReader( + final @Nonnull FutureJVpp futureJVpp, @Nonnull final NamingContext bdContext, + @Nonnull final NamingContext interfaceContext) { + return new CompositeListReader<>( + BridgeDomain.class, + new BridgeDomainCustomizer(futureJVpp, bdContext, interfaceContext)); + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateUtils.java deleted file mode 100644 index 5c619d84d..000000000 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VppStateUtils.java +++ /dev/null @@ -1,77 +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.v3po.vppstate; - -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.util.read.ReflexiveChildReaderCustomizer; -import io.fd.honeycomb.v3po.translate.util.read.ReflexiveRootReaderCustomizer; -import io.fd.honeycomb.v3po.translate.util.RWUtils; -import io.fd.honeycomb.v3po.translate.read.ChildReader; -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; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.BridgeDomainsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.Version; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.BridgeDomain; -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.openvpp.vppjapi.vppApi; - -final class VppStateUtils { - - public VppStateUtils() {} - - /** - * Create root VppState reader with all its children wired - */ - static CompositeRootReader getVppStateReader(@Nonnull final vppApi vppApi) { - - final ChildReader versionReader = new CompositeChildReader<>( - Version.class, new VersionCustomizer(vppApi)); - - final CompositeListReader bridgeDomainReader = - getBridgeDomainReader(vppApi); - - final ChildReader bridgeDomainsReader = new CompositeChildReader<>( - BridgeDomains.class, - RWUtils.singletonChildReaderList(bridgeDomainReader), - new ReflexiveChildReaderCustomizer<>(BridgeDomainsBuilder.class)); - - final List>> childVppReaders = new ArrayList<>(); - childVppReaders.add(versionReader); - childVppReaders.add(bridgeDomainsReader); - - return new CompositeRootReader<>( - VppState.class, - childVppReaders, - RWUtils.emptyAugReaderList(), - new ReflexiveRootReaderCustomizer<>(VppStateBuilder.class)); - } - - static CompositeListReader getBridgeDomainReader( - final @Nonnull vppApi vppApi) { - return new CompositeListReader<>( - BridgeDomain.class, - new BridgeDomainCustomizer(vppApi)); - } -} -- cgit 1.2.3-korg