From d54ea758da8dcf71d52727c4f01f87090c50bf2e Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Tue, 17 May 2016 09:10:39 +0200 Subject: HONEYCOMB-61: Add BA broker for context data tree With broker, context data can be accessed in a transactional manner, same as config data + Renamed data-api concepts to not include DataTree + Renamed context related concepts to better distinguish between them + Now passing full ReadContext to read customizers + Naming context is backed by context data broker Change-Id: I0b2876dd74a31a9ced7d9b5145672868e12f8b82 Signed-off-by: Maros Marsalek --- v3po/v3po2vpp/src/main/config/default-config.xml | 8 --- .../v3po/interfaces/InterfaceCustomizer.java | 18 ++--- .../translate/v3po/interfaces/L2Customizer.java | 29 ++++---- .../v3po/interfaces/RoutingCustomizer.java | 8 +-- .../v3po/interfaces/SubInterfaceCustomizer.java | 9 +-- .../translate/v3po/interfaces/TapCustomizer.java | 17 ++--- .../v3po/interfaces/VhostUserCustomizer.java | 20 +++--- .../v3po/interfaces/VlanTagRewriteCustomizer.java | 11 ++-- .../translate/v3po/interfaces/VxlanCustomizer.java | 12 ++-- .../v3po/interfaces/ip/Ipv4Customizer.java | 9 +-- .../v3po/interfacesstate/EthernetCustomizer.java | 8 ++- .../v3po/interfacesstate/InterfaceCustomizer.java | 21 +++--- .../v3po/interfacesstate/InterfaceUtils.java | 6 +- .../v3po/interfacesstate/L2Customizer.java | 10 +-- .../interfacesstate/SubInterfaceCustomizer.java | 12 ++-- .../v3po/interfacesstate/TapCustomizer.java | 12 ++-- .../v3po/interfacesstate/VhostUserCustomizer.java | 12 ++-- .../interfacesstate/VlanTagRewriteCustomizer.java | 6 +- .../v3po/interfacesstate/VxlanCustomizer.java | 8 +-- .../translate/v3po/vpp/BridgeDomainCustomizer.java | 8 +-- .../v3po/vppstate/BridgeDomainCustomizer.java | 21 +++--- .../translate/v3po/vppstate/VersionCustomizer.java | 4 +- .../v3po/translate/v3po/ContextTestUtils.java | 40 +++++++++++ .../v3po/interfaces/InterfaceTypeTestUtils.java | 12 +++- .../interfaces/SubInterfaceCustomizerTest.java | 20 ++++-- .../v3po/interfaces/TapCustomizerTest.java | 28 +++++--- .../v3po/interfaces/VhostUserCustomizerTest.java | 37 +++++++---- .../interfaces/VlanTagRewriteCustomizerTest.java | 10 ++- .../v3po/interfaces/VxlanCustomizerTest.java | 31 ++++++--- .../interfacesstate/InterfaceCustomizerTest.java | 26 +++++++- .../v3po/interfacesstate/L2CustomizerTest.java | 32 +++++++-- .../SubInterfaceCustomizerTest.java | 30 +++++++-- .../VlanTagRewriteCustomizerTest.java | 12 ++-- .../v3po/interfacesstate/VxlanCustomizerTest.java | 15 ++--- .../v3po/test/RootReaderCustomizerTest.java | 14 +++- .../v3po/vpp/BridgeDomainCustomizerTest.java | 32 +++++++-- .../honeycomb/v3po/translate/v3po/vpp/VppTest.java | 40 ++++++++--- .../v3po/vppstate/BridgeDomainCustomizerTest.java | 4 +- .../v3po/translate/v3po/vppstate/VppStateTest.java | 77 ++++++++++++++++++---- 39 files changed, 497 insertions(+), 232 deletions(-) create mode 100644 v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/ContextTestUtils.java (limited to 'v3po/v3po2vpp') diff --git a/v3po/v3po2vpp/src/main/config/default-config.xml b/v3po/v3po2vpp/src/main/config/default-config.xml index 02b0b7b89..be45a291b 100644 --- a/v3po/v3po2vpp/src/main/config/default-config.xml +++ b/v3po/v3po2vpp/src/main/config/default-config.xml @@ -32,19 +32,11 @@ prefix:naming-context-impl interface-context interface- - - prefix:data-tree - inmemory-persisted-context-data-tree - prefix:naming-context-impl bridge-domain-context bridge-domain- - - prefix:data-tree - inmemory-persisted-context-data-tree - 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 e6ed62acf..eb6426241 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 @@ -57,7 +57,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer implements ListWri throws WriteFailedException { try { - setInterface(id, dataAfter); + setInterface(id, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of VppInterfaceAugment failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -72,7 +72,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer implements ListWri throws WriteFailedException.UpdateFailedException { try { - updateInterface(id, dataBefore, dataAfter); + updateInterface(id, dataBefore, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of VppInterfaceAugment failed", e); throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); @@ -95,25 +95,25 @@ public class InterfaceCustomizer extends FutureJVppCustomizer implements ListWri } - private void setInterface(final InstanceIdentifier id, final Interface swIf) + private void setInterface(final InstanceIdentifier id, final Interface swIf, + final WriteContext writeContext) throws VppApiInvocationException, WriteFailedException { LOG.debug("Setting interface: {} to: {}", id, swIf); - setInterfaceAttributes(swIf, swIf.getName()); + setInterfaceAttributes(swIf, swIf.getName(), writeContext); } - private void setInterfaceAttributes(final Interface swIf, final String swIfName) + private void setInterfaceAttributes(final Interface swIf, final String swIfName, final WriteContext writeContext) throws VppApiInvocationException { - setInterfaceFlags(swIfName, interfaceContext.getIndex(swIfName), + setInterfaceFlags(swIfName, interfaceContext.getIndex(swIfName, writeContext.getMappingContext()), swIf.isEnabled() ? (byte) 1 : (byte) 0); } private void updateInterface(final InstanceIdentifier id, final Interface dataBefore, - final Interface dataAfter) throws VppApiInvocationException { + final Interface dataAfter, final WriteContext writeContext) throws VppApiInvocationException { LOG.debug("Updating interface:{} to: {}", id, dataAfter); - - setInterfaceAttributes(dataAfter, dataAfter.getName()); + setInterfaceAttributes(dataAfter, dataAfter.getName(), writeContext); } private void setInterfaceFlags(final String swIfName, final int swIfIndex, final byte enabled) 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 fc43cdb7e..5aea5de2b 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 @@ -69,9 +69,9 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = interfaceContext.getIndex(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext()); try { - setL2(id, swIfc, ifcName, dataAfter); + setL2(id, swIfc, ifcName, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Write of L2 failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -84,10 +84,10 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = interfaceContext.getIndex(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext()); // TODO handle update properly (if possible) try { - setL2(id, swIfc, ifcName, dataAfter); + setL2(id, swIfc, ifcName, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of L2 failed", e); throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); @@ -100,21 +100,22 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus // TODO implement delete (if possible) } - private void setL2(final InstanceIdentifier id, final int swIfIndex, final String ifcName, final L2 vppL2) + private void setL2(final InstanceIdentifier id, final int swIfIndex, final String ifcName, final L2 vppL2, + final WriteContext writeContext) throws VppApiInvocationException, WriteFailedException { LOG.debug("Setting L2 for interface: {}", ifcName); // Nothing besides interconnection here - setInterconnection(id, swIfIndex, ifcName, vppL2); + setInterconnection(id, swIfIndex, ifcName, vppL2, writeContext); } private void setInterconnection(final InstanceIdentifier id, final int swIfIndex, final String ifcName, - final L2 vppL2) + final L2 vppL2, final WriteContext writeContext) throws VppApiInvocationException, WriteFailedException { Interconnection ic = vppL2.getInterconnection(); if (ic instanceof XconnectBased) { - setXconnectBasedL2(swIfIndex, ifcName, (XconnectBased) ic); + setXconnectBasedL2(swIfIndex, ifcName, (XconnectBased) ic, writeContext); } else if (ic instanceof BridgeBased) { - setBridgeBasedL2(swIfIndex, ifcName, (BridgeBased) ic); + setBridgeBasedL2(swIfIndex, ifcName, (BridgeBased) ic, writeContext); } else { // FIXME how does choice extensibility work // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject @@ -125,7 +126,8 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus } } - private void setBridgeBasedL2(final int swIfIndex, final String ifcName, final BridgeBased bb) + private void setBridgeBasedL2(final int swIfIndex, final String ifcName, final BridgeBased bb, + final WriteContext writeContext) throws VppApiInvocationException { LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}", @@ -133,7 +135,7 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus String bdName = bb.getBridgeDomain(); - int bdId = bridgeDomainContext.getIndex(bdName); + int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext()); checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", ifcName, bdName); @@ -168,14 +170,15 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus return swInterfaceSetL2Bridge; } - private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic) + private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic, + final WriteContext writeContext) throws VppApiInvocationException { String outSwIfName = ic.getXconnectOutgoingInterface(); LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName, ifcName); - int outSwIfIndex = interfaceContext.getIndex(outSwIfName); + int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext()); checkArgument(outSwIfIndex > 0, "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", ifcName, outSwIfIndex); 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 4d17ba098..bf355e479 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 @@ -60,7 +60,7 @@ public class RoutingCustomizer extends FutureJVppCustomizer implements ChildWrit throws WriteFailedException.CreateFailedException { try { - setRouting(id.firstKeyOf(Interface.class).getName(), dataAfter); + setRouting(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of Routing failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -75,7 +75,7 @@ public class RoutingCustomizer extends FutureJVppCustomizer implements ChildWrit try { // TODO handle updates properly - setRouting(id.firstKeyOf(Interface.class).getName(), dataAfter); + setRouting(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of Routing failed", e); throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); @@ -88,8 +88,8 @@ public class RoutingCustomizer extends FutureJVppCustomizer implements ChildWrit // TODO implement delete } - private void setRouting(final String name, final Routing rt) throws VppApiInvocationException { - final int swIfc = interfaceContext.getIndex(name); + private void setRouting(final String name, final Routing rt, final WriteContext writeContext) throws VppApiInvocationException { + final int swIfc = interfaceContext.getIndex(name, writeContext.getMappingContext()); LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt); int vrfId = (rt != null) diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java index ecf2337e8..fb47b6a9f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java @@ -75,15 +75,16 @@ public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer createSubifReplyCompletionStage = getFutureJVpp().createSubif(getCreateSubifRequest(subInterface, swIfIndex)); @@ -96,7 +97,7 @@ public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer { @Nonnull final WriteContext writeContext) throws WriteFailedException.CreateFailedException { try { - createTap(id.firstKeyOf(Interface.class).getName(), dataAfter); + createTap(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Write of Tap failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -84,7 +84,7 @@ public class TapCustomizer extends AbstractInterfaceTypeCustomizer { final int index; try { - index = interfaceContext.getIndex(ifcName); + index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext()); } catch (IllegalArgumentException e) { throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); } @@ -105,20 +105,20 @@ public class TapCustomizer extends AbstractInterfaceTypeCustomizer { final int index; try { - index = interfaceContext.getIndex(ifcName); + index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext()); } catch (IllegalArgumentException e) { throw new WriteFailedException.DeleteFailedException(id, e); } try { - deleteTap(ifcName, index, dataBefore); + deleteTap(ifcName, index, dataBefore, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Delete of Tap failed", e); throw new WriteFailedException.DeleteFailedException(id, e); } } - private void createTap(final String swIfName, final Tap tap) throws VppApiInvocationException { + private void createTap(final String swIfName, final Tap tap, final WriteContext writeContext) throws VppApiInvocationException { LOG.debug("Setting tap interface: {}. Tap: {}", swIfName, tap); final CompletionStage tapConnectFuture = getFutureJVpp().tapConnect(getTapConnectRequest(tap.getTapName(), tap.getMac(), tap.getDeviceInstance())); @@ -130,7 +130,7 @@ public class TapCustomizer extends AbstractInterfaceTypeCustomizer { } else { LOG.debug("Tap set successfully for: {}, tap: {}", swIfName, tap); // Add new interface to our interface context - interfaceContext.addName(reply.swIfIndex, swIfName); + interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext()); } } @@ -148,7 +148,8 @@ public class TapCustomizer extends AbstractInterfaceTypeCustomizer { } } - private void deleteTap(final String swIfName, final int index, final Tap dataBefore) + private void deleteTap(final String swIfName, final int index, final Tap dataBefore, + final WriteContext writeContext) throws VppApiInvocationException { LOG.debug("Deleting tap interface: {}. Tap: {}", swIfName, dataBefore); final CompletionStage vxlanAddDelTunnelReplyCompletionStage = @@ -161,7 +162,7 @@ public class TapCustomizer extends AbstractInterfaceTypeCustomizer { } else { LOG.debug("Tap deleted successfully for: {}, tap: {}", swIfName, dataBefore); // Remove deleted interface from interface context - interfaceContext.removeName(swIfName); + interfaceContext.removeName(swIfName, writeContext.getMappingContext()); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java index ebefff34a..5f7d626e8 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizer.java @@ -73,13 +73,13 @@ public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer createVhostUserIfReplyCompletionStage = getFutureJVpp().createVhostUserIf(getCreateVhostUserIfRequest(vhostUser)); @@ -92,7 +92,7 @@ public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer modifyVhostUserIfReplyCompletionStage = getFutureJVpp() - .modifyVhostUserIf(getModifyVhostUserIfRequest(vhostUser, interfaceContext.getIndex(swIfName))); + .modifyVhostUserIf(getModifyVhostUserIfRequest(vhostUser, interfaceContext.getIndex(swIfName, writeContext.getMappingContext()))); final ModifyVhostUserIfReply reply = V3poUtils.getReply(modifyVhostUserIfReplyCompletionStage.toCompletableFuture()); @@ -155,16 +155,16 @@ public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer deleteVhostUserIfReplyCompletionStage = - getFutureJVpp().deleteVhostUserIf(getDeleteVhostUserIfRequest(interfaceContext.getIndex(swIfName))); + getFutureJVpp().deleteVhostUserIf(getDeleteVhostUserIfRequest(interfaceContext.getIndex(swIfName, writeContext.getMappingContext()))); final DeleteVhostUserIfReply reply = V3poUtils.getReply(deleteVhostUserIfReplyCompletionStage.toCompletableFuture()); @@ -174,7 +174,7 @@ public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer replyCompletionStage = @@ -121,7 +122,7 @@ public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements Ch return; } try { - setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter); + setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException e) { throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); } @@ -135,7 +136,7 @@ public class VlanTagRewriteCustomizer extends FutureJVppCustomizer implements Ch // disable tag rewrite final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); builder.setRewriteOperation(TagRewriteOperation.Disabled); - setTagRewrite(id.firstKeyOf(Interface.class).getName(), builder.build()); + setTagRewrite(id.firstKeyOf(Interface.class).getName(), builder.build(), writeContext); } catch (VppApiInvocationException e) { throw new WriteFailedException.DeleteFailedException(id, e); } 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 9d11b59b1..3edd531c6 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 @@ -71,7 +71,7 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { @Nonnull final WriteContext writeContext) throws WriteFailedException.CreateFailedException { try { - createVxlanTunnel(id.firstKeyOf(Interface.class).getName(), dataAfter); + createVxlanTunnel(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); } catch (VppApiInvocationException | IllegalInterfaceTypeException e) { LOG.warn("Write of Vxlan failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -95,14 +95,14 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { @Nonnull final WriteContext writeContext) throws WriteFailedException.DeleteFailedException { try { - deleteVxlanTunnel(id.firstKeyOf(Interface.class).getName(), dataBefore); + deleteVxlanTunnel(id.firstKeyOf(Interface.class).getName(), dataBefore, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Delete of Vxlan tunnel failed", e); throw new WriteFailedException.DeleteFailedException(id, e); } } - private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { + private void createVxlanTunnel(final String swIfName, final Vxlan vxlan, final WriteContext writeContext) throws VppApiInvocationException { final byte isIpv6 = (byte) (isIpv6(vxlan) ? 1 : 0); final InetAddress srcAddress = InetAddresses.forString(getAddressString(vxlan.getSrc())); final InetAddress dstAddress = InetAddresses.forString(getAddressString(vxlan.getDst())); @@ -123,7 +123,7 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { } else { LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan); // Add new interface to our interface context - interfaceContext.addName(reply.swIfIndex, swIfName); + interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext()); } } @@ -143,7 +143,7 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { return addr.getIpv4Address() == null ? addr.getIpv6Address().getValue() : addr.getIpv4Address().getValue(); } - private void deleteVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { + private void deleteVxlanTunnel(final String swIfName, final Vxlan vxlan, final WriteContext writeContext) throws VppApiInvocationException { final byte isIpv6 = (byte) (isIpv6(vxlan) ? 1 : 0); final InetAddress srcAddress = InetAddresses.forString(getAddressString(vxlan.getSrc())); final InetAddress dstAddress = InetAddresses.forString(getAddressString(vxlan.getDst())); @@ -164,7 +164,7 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer { } else { LOG.debug("Vxlan tunnel deleted successfully for: {}, vxlan: {}", swIfName, vxlan); // Remove interface from our interface context - interfaceContext.removeName(swIfName); + interfaceContext.removeName(swIfName, writeContext.getMappingContext()); } } 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 a54f6c5e3..4deb38f52 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 @@ -68,7 +68,7 @@ public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterC throws WriteFailedException { try { final String ifcName = id.firstKeyOf(Interface.class).getName(); - setIpv4(id, ifcName, dataAfter); + setIpv4(id, ifcName, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Create of Ipv4 failed", e); throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -84,7 +84,7 @@ public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterC // TODO handle update in a better way try { - setIpv4(id, ifcName, dataAfter); + setIpv4(id, ifcName, dataAfter, writeContext); } catch (VppApiInvocationException e) { LOG.warn("Update of Ipv4 failed", e); throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); @@ -97,9 +97,10 @@ public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterC // TODO implement delete } - private void setIpv4(final InstanceIdentifier id, final String name, final Ipv4 ipv4) + private void setIpv4(final InstanceIdentifier id, final String name, final Ipv4 ipv4, + final WriteContext writeContext) throws WriteFailedException, VppApiInvocationException { - final int swIfc = interfaceContext.getIndex(name); + final int swIfc = interfaceContext.getIndex(name, writeContext.getMappingContext()); for (Address ipv4Addr : ipv4.getAddress()) { Subnet subnet = ipv4Addr.getSubnet(); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java index 74ea45c11..8173b67ba 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java @@ -16,7 +16,9 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import io.fd.honeycomb.v3po.translate.Context; +import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump; + +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -64,11 +66,11 @@ public class EthernetCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final EthernetBuilder builder, - @Nonnull final Context ctx) throws ReadFailedException { + @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName()), ctx); + interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); builder.setMtu((int) iface.linkMtu); switch (iface.linkDuplex) { 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 51d4022d7..87c62f48f 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 @@ -16,7 +16,8 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.ModificationCache; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -69,13 +70,13 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull InterfaceBuilder builder, - @Nonnull Context ctx) throws ReadFailedException { + @Nonnull ReadContext ctx) throws ReadFailedException { LOG.debug("Reading attributes for interface: {}", id); final InterfaceKey key = id.firstKeyOf(id.getTargetType()); // Pass cached details from getAllIds to getDetails to avoid additional dumps final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName()), ctx); + interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); builder.setName(key.getName()); @@ -94,7 +95,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @Nonnull @SuppressWarnings("unchecked") - public static Map getCachedInterfaceDump(final @Nonnull Context ctx) { + public static Map getCachedInterfaceDump(final @Nonnull ModificationCache ctx) { return ctx.get(DUMPED_IFCS_CONTEXT_KEY) == null ? new HashMap<>() // allow customizers to update the cache : (Map) ctx.get(DUMPED_IFCS_CONTEXT_KEY); @@ -103,7 +104,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer @Nonnull @Override public List getAllIds(@Nonnull final InstanceIdentifier id, - @Nonnull final Context context) throws ReadFailedException { + @Nonnull final ReadContext context) throws ReadFailedException { LOG.trace("Dumping all interfaces to get all IDs"); final SwInterfaceDump request = new SwInterfaceDump(); @@ -120,20 +121,20 @@ public class InterfaceCustomizer extends FutureJVppCustomizer } // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes - context.put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream() + context.getModificationCache().put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream() .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails))); final List interfacesKeys = 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)); + if (!interfaceContext.containsName(elt.swIfIndex, context.getMappingContext())) { + interfaceContext.addName(elt.swIfIndex, V3poUtils.toString(elt.interfaceName), context.getMappingContext()); } LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP", - interfaceContext.getName(elt.swIfIndex), elt.interfaceName, elt.swIfIndex); + interfaceContext.getName(elt.swIfIndex, context.getMappingContext()), elt.interfaceName, elt.swIfIndex); - return new InterfaceKey(interfaceContext.getName(elt.swIfIndex)); + return new InterfaceKey(interfaceContext.getName(elt.swIfIndex, context.getMappingContext())); }) .collect(Collectors.toList()); 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 a6c887336..ee66aef1f 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 @@ -21,7 +21,7 @@ import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCusto import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.ModificationCache; import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import java.math.BigInteger; import java.util.Map; @@ -158,7 +158,7 @@ public final class InterfaceUtils { @Nonnull public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp, @Nonnull InterfaceKey key, final int index, - @Nonnull final Context ctx) { + @Nonnull final ModificationCache ctx) { final SwInterfaceDump request = new SwInterfaceDump(); request.nameFilter = key.getName().getBytes(); request.nameFilterValid = 1; @@ -225,7 +225,7 @@ public final class InterfaceUtils { return EthernetCsmacd.class; } - static boolean isInterfaceOfType(final Context ctx, final int index, + static boolean isInterfaceOfType(final ModificationCache ctx, final int index, final Class ifcType) { final SwInterfaceDetails cachedDetails = checkNotNull(getCachedInterfaceDump(ctx).get(index), diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java index 099d4c195..1bc9c2b3a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java @@ -17,7 +17,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -74,20 +74,20 @@ public class L2Customizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final L2Builder builder, - @Nonnull final Context ctx) throws ReadFailedException { + @Nonnull final ReadContext ctx) throws ReadFailedException { LOG.debug("Reading attributes for L2: {}", id); final InterfaceKey key = id.firstKeyOf(Interface.class); - final int ifaceId = interfaceContext.getIndex(key.getName()); + final int ifaceId = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - ifaceId, ctx); + ifaceId, ctx.getModificationCache()); LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); final Optional bdForInterface = getBridgeDomainForInterface(ifaceId); if (bdForInterface.isPresent()) { final BridgeDomainSwIfDetails bdSwIfDetails = bdForInterface.get(); final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); - bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId)); + bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId, ctx.getMappingContext())); // bbBuilder.setBridgedVirtualInterface // TODO where to find that value? if (bdSwIfDetails.shg != 0) { bbBuilder.setSplitHorizonGroup((short)bdSwIfDetails.shg); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java index b68acbfa3..ebd1cff40 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java @@ -19,7 +19,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -70,18 +70,18 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final SubInterfaceBuilder builder, @Nonnull final Context ctx) + @Nonnull final SubInterfaceBuilder builder, @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) // to fill in the context with initial ifc mapping - final int index = interfaceContext.getIndex(key.getName()); - if (!isInterfaceOfType(ctx, index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface.class)) { + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(ctx.getModificationCache(), index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface.class)) { return; } LOG.debug("Reading attributes for sub interface: {}", id); - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, index, ctx); + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, index, ctx.getModificationCache()); LOG.debug("VPP interface details: {}", ReflectionToStringBuilder.toString(iface)); if (iface.subId == 0) { @@ -90,7 +90,7 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer } builder.setIdentifier(Long.valueOf(iface.subId)); - builder.setSuperInterface(interfaceContext.getName(iface.supSwIfIndex)); + builder.setSuperInterface(interfaceContext.getName(iface.supSwIfIndex, ctx.getMappingContext())); builder.setNumberOfTags(Short.valueOf(iface.subNumberOfTags)); builder.setVlanType(iface.subDot1Ad == 1 ? VlanType._802dot1q : VlanType._802dot1ad); if (iface.subExactMatch == 1) { diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java index e7cd560bb..358e9149a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/TapCustomizer.java @@ -18,7 +18,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -72,12 +72,12 @@ public class TapCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final TapBuilder builder, - @Nonnull final Context ctx) throws ReadFailedException { + @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) // to fill in the context with initial ifc mapping - final int index = interfaceContext.getIndex(key.getName()); - if (!isInterfaceOfType(ctx, index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap.class)) { + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(ctx.getModificationCache(), index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap.class)) { return; } @@ -85,7 +85,7 @@ public class TapCustomizer extends FutureJVppCustomizer @SuppressWarnings("unchecked") Map mappedTaps = - (Map) ctx.get(DUMPED_TAPS_CONTEXT_KEY); + (Map) ctx.getModificationCache().get(DUMPED_TAPS_CONTEXT_KEY); if(mappedTaps == null) { // Full Tap dump has to be performed here, no filter or anything is here to help so at least we cache it @@ -104,7 +104,7 @@ public class TapCustomizer extends FutureJVppCustomizer .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)); } - ctx.put(DUMPED_TAPS_CONTEXT_KEY, mappedTaps); + ctx.getModificationCache().put(DUMPED_TAPS_CONTEXT_KEY, mappedTaps); } final SwInterfaceTapDetails swInterfaceTapDetails = mappedTaps.get(index); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java index 70a6da1cc..d5ae8faf3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VhostUserCustomizer.java @@ -18,7 +18,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -74,12 +74,12 @@ public class VhostUserCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final VhostUserBuilder builder, - @Nonnull final Context ctx) throws ReadFailedException { + @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) // to fill in the context with initial ifc mapping - final int index = interfaceContext.getIndex(key.getName()); - if (!isInterfaceOfType(ctx, index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)) { + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(ctx.getModificationCache(), index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)) { return; } @@ -87,7 +87,7 @@ public class VhostUserCustomizer extends FutureJVppCustomizer @SuppressWarnings("unchecked") Map mappedVhostUsers = - (Map) ctx.get(DUMPED_VHOST_USERS_CONTEXT_KEY); + (Map) ctx.getModificationCache().get(DUMPED_VHOST_USERS_CONTEXT_KEY); if(mappedVhostUsers == null) { // Full VhostUser dump has to be performed here, no filter or anything is here to help so at least we cache it @@ -106,7 +106,7 @@ public class VhostUserCustomizer extends FutureJVppCustomizer .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails)); } - ctx.put(DUMPED_VHOST_USERS_CONTEXT_KEY, mappedVhostUsers); + ctx.getModificationCache().put(DUMPED_VHOST_USERS_CONTEXT_KEY, mappedVhostUsers); } // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java index d7404e6d5..d05e089a2 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java @@ -17,7 +17,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -68,13 +68,13 @@ public class VlanTagRewriteCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final VlanTagRewriteBuilder builder, @Nonnull final Context ctx) + @Nonnull final VlanTagRewriteBuilder builder, @Nonnull final ReadContext ctx) throws ReadFailedException { LOG.debug("Reading attributes for sub interface: {}", id); final InterfaceKey key = id.firstKeyOf(Interface.class); final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName()), ctx); + interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); builder.setFirstPushed(iface.subDot1Ad == 1 ? VlanType._802dot1q : VlanType._802dot1ad); builder.setRewriteOperation(TagRewriteOperation.forValue(iface.vtrOp)); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java index 829416034..81ba34062 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizer.java @@ -18,7 +18,7 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkState; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -74,12 +74,12 @@ public class VxlanCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final VxlanBuilder builder, - @Nonnull final Context ctx) throws ReadFailedException { + @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) // to fill in the context with initial ifc mapping - final int index = interfaceContext.getIndex(key.getName()); - if (!InterfaceUtils.isInterfaceOfType(ctx, index, VxlanTunnel.class)) { + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!InterfaceUtils.isInterfaceOfType(ctx.getModificationCache(), index, VxlanTunnel.class)) { return; } 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 672a05f4e..6e94461a6 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 @@ -96,11 +96,11 @@ public class BridgeDomainCustomizer // 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)) { + while(bdContext.containsName(index, ctx.getMappingContext())) { index++; } addOrUpdateBridgeDomain(index, dataBefore); - bdContext.addName(index, bdName); + bdContext.addName(index, bdName, ctx.getMappingContext()); } catch (VppApiInvocationException e) { LOG.warn("Failed to create bridge domain", e); throw new WriteFailedException.CreateFailedException(id, dataBefore, e); @@ -120,7 +120,7 @@ public class BridgeDomainCustomizer LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx); final String bdName = id.firstKeyOf(BridgeDomain.class).getName(); - int bdId = bdContext.getIndex(bdName); + int bdId = bdContext.getIndex(bdName, ctx.getMappingContext()); final BridgeDomainAddDel request = new BridgeDomainAddDel(); request.bdId = bdId; @@ -154,7 +154,7 @@ public class BridgeDomainCustomizer "BridgeDomain name changed. It should be deleted and then created."); try { - addOrUpdateBridgeDomain(bdContext.getIndex(bdName), dataAfter); + addOrUpdateBridgeDomain(bdContext.getIndex(bdName, ctx.getMappingContext()), 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 1a3855ced..ac16c610f 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 @@ -20,7 +20,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.primitives.Longs; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -70,7 +70,7 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) + @Nonnull final BridgeDomainBuilder builder, @Nonnull final ReadContext context) throws ReadFailedException { LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: id={}, builderbuilder={}, context={}", id, builder, context); @@ -78,13 +78,13 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer final BridgeDomainKey key = id.firstKeyOf(id.getTargetType()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: key={}", key); - final int bdId = bdContext.getIndex(key.getName()); + final int bdId = bdContext.getIndex(key.getName(), context.getMappingContext()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: bdId={}", bdId); BridgeDomainDetailsReplyDump reply; BridgeDomainDetails bridgeDomainDetails; final BridgeDomainDump request = new BridgeDomainDump(); - request.bdId = bdContext.getIndex(key.getName()); + request.bdId = bdContext.getIndex(key.getName(), context.getMappingContext()); try { reply = getFutureJVpp().bridgeDomainDump(request).toCompletableFuture().get(); bridgeDomainDetails = Iterables.getOnlyElement(reply.bridgeDomainDetails); @@ -102,7 +102,7 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer builder.setLearn(byteToBoolean(bridgeDomainDetails.learn)); builder.setUnknownUnicastFlood(byteToBoolean(bridgeDomainDetails.uuFlood)); - builder.setInterface(getIfcs(bridgeDomainDetails, reply.bridgeDomainSwIfDetails)); + builder.setInterface(getIfcs(bridgeDomainDetails, reply.bridgeDomainSwIfDetails, context)); final L2FibTableDump l2FibRequest = new L2FibTableDump(); l2FibRequest.bdId = bdId; @@ -124,7 +124,7 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer ? L2Fib.Action.Filter : L2Fib.Action.Forward)) .setBridgedVirtualInterface(byteToBoolean(entry.bviMac)) - .setOutgoingInterface(interfaceContext.getName(entry.swIfIndex)) + .setOutgoingInterface(interfaceContext.getName(entry.swIfIndex, context.getMappingContext())) .setStaticConfig(byteToBoolean(entry.staticMac)) .setPhysAddress(address) .setKey(new L2FibKey(address)) @@ -175,10 +175,11 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer } private List getIfcs(final BridgeDomainDetails bridgeDomainDetails, - final List bridgeDomainSwIfDetails) { + final List bridgeDomainSwIfDetails, + final ReadContext context) { final List ifcs = new ArrayList<>(bridgeDomainSwIfDetails.size()); for (BridgeDomainSwIfDetails anInterface : bridgeDomainSwIfDetails) { - final String interfaceName = interfaceContext.getName(anInterface.swIfIndex); + final String interfaceName = interfaceContext.getName(anInterface.swIfIndex, context.getMappingContext()); if (anInterface.bdId == bridgeDomainDetails.bdId) { ifcs.add(new InterfaceBuilder() .setBridgedVirtualInterface(bridgeDomainDetails.bviSwIfIndex == anInterface.swIfIndex) @@ -202,7 +203,7 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer @Nonnull @Override public List getAllIds(@Nonnull final InstanceIdentifier id, - @Nonnull final Context context) { + @Nonnull final ReadContext context) { final BridgeDomainDump request = new BridgeDomainDump(); request.bdId = -1; // dump call @@ -228,7 +229,7 @@ public final class BridgeDomainCustomizer extends FutureJVppCustomizer for (BridgeDomainDetails detail : reply.bridgeDomainDetails) { logBridgeDomainDetails(detail); - final String bName = bdContext.getName(detail.bdId); + final String bName = bdContext.getName(detail.bdId, context.getMappingContext()); LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bName={}", bName); allIds.add(new BridgeDomainKey(bName)); } 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 1db8217f9..4ad4a6e91 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 @@ -16,7 +16,7 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadContext; 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; @@ -53,7 +53,7 @@ public final class VersionCustomizer @Override public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull final VersionBuilder builder, - @Nonnull final Context context) throws ReadFailedException { + @Nonnull final ReadContext context) throws ReadFailedException { ShowVersionReply reply; try { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/ContextTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/ContextTestUtils.java new file mode 100644 index 000000000..5c731bcb5 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/ContextTestUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po; + +import com.google.common.base.Optional; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContextKey; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +public class ContextTestUtils { + + public static Optional getMapping(final String name, final int index) { + return Optional.of(new MappingBuilder().setName(name).setIndex(index).build()); + } + + public static KeyedInstanceIdentifier getMappingIid(final String name, final String namingContextName) { + return InstanceIdentifier.create(Contexts.class).child( + org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContext.class, + new NamingContextKey(namingContextName)).child(Mappings.class).child(Mapping.class, new MappingKey(name)); + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceTypeTestUtils.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceTypeTestUtils.java index ff96131b1..fbb47b5d4 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceTypeTestUtils.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceTypeTestUtils.java @@ -19,21 +19,29 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import static org.mockito.Mockito.doReturn; import com.google.common.base.Optional; -import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.ModificationCache; import io.fd.honeycomb.v3po.translate.write.WriteContext; import org.mockito.Matchers; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.NamingContextKey; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; final class InterfaceTypeTestUtils { private InterfaceTypeTestUtils() {} static void setupWriteContext(final WriteContext writeContext, final Class ifcType) { - doReturn(new Context()).when(writeContext).getContext(); + doReturn(new ModificationCache()).when(writeContext).getModificationCache(); doReturn(Optional.of(new InterfaceBuilder() .setType(ifcType) .build())).when(writeContext).readAfter(Matchers.any(InstanceIdentifier.class)); } + } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizerTest.java index d70654655..31ab3aab5 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizerTest.java @@ -16,15 +16,18 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; +import io.fd.honeycomb.v3po.translate.MappingContext; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.write.WriteContext; @@ -54,6 +57,8 @@ public class SubInterfaceCustomizerTest { private FutureJVpp api; @Mock private WriteContext writeContext; + @Mock + private MappingContext mappingContext; private NamingContext namingContext; private SubInterfaceCustomizer customizer; @@ -65,10 +70,11 @@ public class SubInterfaceCustomizerTest { initMocks(this); InterfaceTypeTestUtils.setupWriteContext(writeContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface.class); - namingContext = new NamingContext("generatedSubInterfaceName"); + namingContext = new NamingContext("generatedSubInterfaceName", "test-instance"); + doReturn(mappingContext).when(writeContext).getMappingContext(); // TODO create base class for tests using vppApi customizer = new SubInterfaceCustomizer(api, namingContext); - namingContext.addName(SUPER_IF_ID, SUPER_IF_NAME); + doReturn(getMapping(SUPER_IF_NAME, SUPER_IF_ID)).when(mappingContext).read(getMappingIid(SUPER_IF_NAME, "test-instance")); } private SubInterface generateSubInterface(final String superIfName) { @@ -145,7 +151,7 @@ public class SubInterfaceCustomizerTest { customizer.writeCurrentAttributes(id, subInterface, writeContext); verifyCreateSubifWasInvoked(generateSubInterfaceRequest(SUPER_IF_ID)); - assertTrue(namingContext.containsIndex(subIfaceName)); + verify(mappingContext).put(eq(getMappingIid(subIfaceName, "test-instance")), eq(getMapping(subIfaceName, 0).get())); } @Test @@ -161,7 +167,9 @@ public class SubInterfaceCustomizerTest { } catch (WriteFailedException.CreateFailedException e) { assertEquals(VppApiInvocationException.class, e.getCause().getClass()); verifyCreateSubifWasInvoked(generateSubInterfaceRequest(SUPER_IF_ID)); - assertFalse(namingContext.containsIndex(subIfaceName)); + verify(mappingContext, times(0)).put( + eq(getMappingIid(subIfaceName, "test-instance")), + eq(getMapping(subIfaceName, 0).get())); return; } fail("WriteFailedException.CreateFailedException was expected"); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/TapCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/TapCustomizerTest.java index 8ae04f017..e717ec504 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/TapCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/TapCustomizerTest.java @@ -16,14 +16,17 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import io.fd.honeycomb.v3po.translate.MappingContext; +import io.fd.honeycomb.v3po.translate.ModificationCache; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.write.WriteContext; import java.util.concurrent.CompletableFuture; @@ -55,8 +58,9 @@ public class TapCustomizerTest { private FutureJVpp vppApi; @Mock private WriteContext writeContext; + @Mock + private MappingContext mappingContext; - private NamingContext ctx; private TapCustomizer tapCustomizer; @Before @@ -64,7 +68,11 @@ public class TapCustomizerTest { MockitoAnnotations.initMocks(this); InterfaceTypeTestUtils.setupWriteContext(writeContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap.class); - ctx = new NamingContext("ifcintest"); + final NamingContext ctx = new NamingContext("ifcintest", "test-instance"); + final ModificationCache toBeReturned = new ModificationCache(); + doReturn(toBeReturned).when(writeContext).getModificationCache(); + doReturn(mappingContext).when(writeContext).getMappingContext(); + tapCustomizer = new TapCustomizer(vppApi, ctx); } @@ -89,8 +97,8 @@ public class TapCustomizerTest { tapCustomizer.writeCurrentAttributes(getTapId("tap2"), getTapData("tap2", "ff:ff:ff:ff:ff:ff"), writeContext); verify(vppApi, times(2)).tapConnect(any(TapConnect.class)); - assertTrue(ctx.containsIndex("tap")); - assertTrue(ctx.containsIndex("tap2")); + verify(mappingContext).put(eq(getMappingIid("tap", "test-instance")), eq(getMapping("tap", 0).get())); + verify(mappingContext).put(eq(getMappingIid("tap2", "test-instance")), eq(getMapping("tap2", 1).get())); } @Test @@ -109,12 +117,13 @@ public class TapCustomizerTest { doReturn(replyModif).when(vppApi).tapModify(any(TapModify.class)); tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext); + doReturn(getMapping("tap", 1)).when(mappingContext).read(getMappingIid("tap", "test-instance")); tapCustomizer.updateCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), getTapData("tap", "ff:ff:ff:ff:ff:f1"), writeContext); verify(vppApi).tapConnect(any(TapConnect.class)); verify(vppApi).tapModify(any(TapModify.class)); - assertTrue(ctx.containsIndex("tap")); - assertFalse(ctx.containsIndex("tap2")); + + verify(mappingContext).put(eq(getMappingIid("tap", "test-instance")), eq(getMapping("tap", 0).get())); } @Test @@ -132,11 +141,12 @@ public class TapCustomizerTest { doReturn(replyDelete).when(vppApi).tapDelete(any(TapDelete.class)); tapCustomizer.writeCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext); + doReturn(getMapping("tap", 1)).when(mappingContext).read(getMappingIid("tap", "test-instance")); tapCustomizer.deleteCurrentAttributes(getTapId("tap"), getTapData("tap", "ff:ff:ff:ff:ff:ff"), writeContext); verify(vppApi).tapConnect(any(TapConnect.class)); verify(vppApi).tapDelete(any(TapDelete.class)); - assertFalse(ctx.containsIndex("tap")); + verify(mappingContext).delete(eq(getMappingIid("tap", "test-instance"))); } private InstanceIdentifier getTapId(final String tap) { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizerTest.java index 15b2a75c1..1015f24c0 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VhostUserCustomizerTest.java @@ -16,19 +16,25 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +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 static org.mockito.MockitoAnnotations.initMocks; +import io.fd.honeycomb.v3po.translate.MappingContext; +import io.fd.honeycomb.v3po.translate.ModificationCache; 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; @@ -63,8 +69,9 @@ public class VhostUserCustomizerTest { private FutureJVpp api; @Mock private WriteContext writeContext; + @Mock + private MappingContext mappingContext; - private NamingContext namingContext; private VhostUserCustomizer customizer; private static final int IFACE_ID = 1; private static final String IFACE_NAME = "eth0"; @@ -77,7 +84,11 @@ public class VhostUserCustomizerTest { initMocks(this); InterfaceTypeTestUtils.setupWriteContext(writeContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class); - namingContext = new NamingContext("generatedInterfaceName"); + final NamingContext namingContext = new NamingContext("generatedInterfaceName", "test-instance"); + final ModificationCache toBeReturned = new ModificationCache(); + doReturn(toBeReturned).when(writeContext).getModificationCache(); + doReturn(mappingContext).when(writeContext).getMappingContext(); + // TODO create base class for tests using vppApi customizer = new VhostUserCustomizer(api, namingContext); } @@ -186,7 +197,7 @@ public class VhostUserCustomizerTest { customizer.writeCurrentAttributes(ID, vhostUser, writeContext); verifyCreateVhostUserIfWasInvoked(vhostUser); - assertTrue(namingContext.containsIndex(IFACE_NAME)); + verify(mappingContext).put(eq(getMappingIid(IFACE_NAME, "test-instance")), eq(getMapping(IFACE_NAME, 0).get())); } @Test @@ -200,7 +211,7 @@ public class VhostUserCustomizerTest { } catch (WriteFailedException.CreateFailedException e) { assertEquals(VppApiInvocationException.class, e.getCause().getClass()); verifyCreateVhostUserIfWasInvoked(vhostUser); - assertFalse(namingContext.containsIndex(IFACE_NAME)); + verifyZeroInteractions(mappingContext); return; } fail("WriteFailedException.CreateFailedException was expected"); @@ -210,7 +221,7 @@ public class VhostUserCustomizerTest { public void testUpdateCurrentAttributes() throws Exception { final VhostUser vhostUserBefore = generateVhostUser(VhostUserRole.Client, "socketName0"); final VhostUser vhostUserAfter = generateVhostUser(VhostUserRole.Server, "socketName1"); - namingContext.addName(IFACE_ID, IFACE_NAME); + doReturn(getMapping(IFACE_NAME, IFACE_ID)).when(mappingContext).read(getMappingIid(IFACE_NAME, "test-instance")); whenModifyVhostUserIfThenSuccess(); @@ -230,7 +241,7 @@ public class VhostUserCustomizerTest { public void testUpdateCurrentAttributesFailed() throws Exception { final VhostUser vhostUserBefore = generateVhostUser(VhostUserRole.Client, "socketName0"); final VhostUser vhostUserAfter = generateVhostUser(VhostUserRole.Server, "socketName1"); - namingContext.addName(IFACE_ID, IFACE_NAME); + doReturn(getMapping(IFACE_NAME, IFACE_ID)).when(mappingContext).read(getMappingIid(IFACE_NAME, "test-instance")); whenModifyVhostUserIfThenFailure(); @@ -247,19 +258,19 @@ public class VhostUserCustomizerTest { @Test public void testDeleteCurrentAttributes() throws Exception { final VhostUser vhostUser = generateVhostUser(VhostUserRole.Client, "socketName"); - namingContext.addName(IFACE_ID, IFACE_NAME); + doReturn(getMapping(IFACE_NAME, IFACE_ID)).when(mappingContext).read(getMappingIid(IFACE_NAME, "test-instance")); whenDeleteVhostUserIfThenSuccess(); customizer.deleteCurrentAttributes(ID, vhostUser, writeContext); verifyDeleteVhostUserIfWasInvoked(IFACE_ID); - assertFalse(namingContext.containsIndex(IFACE_NAME)); + verify(mappingContext).delete(eq(getMappingIid(IFACE_NAME, "test-instance"))); } @Test public void testDeleteCurrentAttributesFailed() throws Exception { final VhostUser vhostUser = generateVhostUser(VhostUserRole.Client, "socketName"); - namingContext.addName(IFACE_ID, IFACE_NAME); + doReturn(getMapping(IFACE_NAME, IFACE_ID)).when(mappingContext).read(getMappingIid(IFACE_NAME, "test-instance")); whenDeleteVhostUserIfThenFailure(); @@ -268,7 +279,9 @@ public class VhostUserCustomizerTest { } catch (WriteFailedException.DeleteFailedException e) { assertEquals(VppApiInvocationException.class, e.getCause().getClass()); verifyDeleteVhostUserIfWasInvoked(IFACE_ID); - assertTrue(namingContext.containsIndex(IFACE_NAME)); + // Delete from context not invoked if delete from VPP failed + verify(mappingContext, times(0)).delete(eq(getMappingIid(IFACE_NAME, "test-instance"))); + verify(mappingContext).read(eq(getMappingIid(IFACE_NAME, "test-instance"))); return; } fail("WriteFailedException.DeleteFailedException was expected"); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java index ae768145a..39a9823b5 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizerTest.java @@ -16,6 +16,8 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; @@ -24,6 +26,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; +import io.fd.honeycomb.v3po.translate.MappingContext; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.write.WriteContext; @@ -55,6 +58,8 @@ public class VlanTagRewriteCustomizerTest { private FutureJVpp api; @Mock private WriteContext writeContext; + @Mock + private MappingContext mappingContext; private NamingContext namingContext; private VlanTagRewriteCustomizer customizer; @@ -65,9 +70,10 @@ public class VlanTagRewriteCustomizerTest { @Before public void setUp() throws Exception { initMocks(this); - namingContext = new NamingContext("generatedSubInterfaceName"); + namingContext = new NamingContext("generatedSubInterfaceName", "test-instance"); + doReturn(mappingContext).when(writeContext).getMappingContext(); customizer = new VlanTagRewriteCustomizer(api, namingContext); - namingContext.addName(VLAN_IF_ID, VLAN_IF_NAME); + doReturn(getMapping(VLAN_IF_NAME, VLAN_IF_ID)).when(mappingContext).read(getMappingIid(VLAN_IF_NAME, "test-instance")); } private InstanceIdentifier getVlanTagRewriteId(final String name) { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java index af7b4df17..a5103b178 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizerTest.java @@ -16,19 +16,24 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import com.google.common.net.InetAddresses; +import io.fd.honeycomb.v3po.translate.MappingContext; +import io.fd.honeycomb.v3po.translate.ModificationCache; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.write.WriteContext; @@ -63,9 +68,10 @@ public class VxlanCustomizerTest { private FutureJVpp api; @Mock private WriteContext writeContext; + @Mock + private MappingContext mappingContext; private VxlanCustomizer customizer; - private NamingContext namingContext; private String ifaceName; private InstanceIdentifier id; @@ -75,7 +81,11 @@ public class VxlanCustomizerTest { InterfaceTypeTestUtils.setupWriteContext(writeContext, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel.class); // TODO create base class for tests using vppApi - namingContext = new NamingContext("generateInterfaceNAme"); + NamingContext namingContext = new NamingContext("generateInterfaceNAme", "test-instance"); + final ModificationCache toBeReturned = new ModificationCache(); + doReturn(toBeReturned).when(writeContext).getModificationCache(); + doReturn(mappingContext).when(writeContext).getMappingContext(); + customizer = new VxlanCustomizer(api, namingContext); ifaceName = "eth0"; @@ -144,7 +154,7 @@ public class VxlanCustomizerTest { customizer.writeCurrentAttributes(id, vxlan, writeContext); verifyVxlanAddWasInvoked(vxlan); - assertTrue(namingContext.containsIndex(ifaceName)); + verify(mappingContext).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get())); } @Test @@ -158,7 +168,8 @@ public class VxlanCustomizerTest { } catch (WriteFailedException.CreateFailedException e) { assertEquals(VppApiInvocationException.class, e.getCause().getClass()); verifyVxlanAddWasInvoked(vxlan); - assertFalse(namingContext.containsIndex(ifaceName)); + // Mapping not stored due to failure + verify(mappingContext, times(0)).put(eq(getMappingIid(ifaceName, "test-instance")), eq(getMapping(ifaceName, 0).get())); return; } fail("WriteFailedException.CreateFailedException was expected"); @@ -186,11 +197,11 @@ public class VxlanCustomizerTest { final Vxlan vxlan = generateVxlan(); whenVxlanAddDelTunnelThenSuccess(); - namingContext.addName(1, ifaceName); + doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance")); customizer.deleteCurrentAttributes(id, vxlan, writeContext); verifyVxlanDeleteWasInvoked(vxlan); - assertFalse(namingContext.containsIndex(ifaceName)); + verify(mappingContext).delete(eq(getMappingIid(ifaceName, "test-instance"))); } @Test @@ -198,14 +209,14 @@ public class VxlanCustomizerTest { final Vxlan vxlan = generateVxlan(); whenVxlanAddDelTunnelThenFailure(); - namingContext.addName(1, ifaceName); + doReturn(getMapping(ifaceName, 1)).when(mappingContext).read(getMappingIid(ifaceName, "test-instance")); try { customizer.deleteCurrentAttributes(id, vxlan, writeContext); } catch (WriteFailedException.DeleteFailedException e) { assertEquals(VppApiInvocationException.class, e.getCause().getClass()); verifyVxlanDeleteWasInvoked(vxlan); - assertTrue(namingContext.containsIndex(ifaceName)); + verify(mappingContext, times(0)).delete(eq(getMappingIid(ifaceName, "test-instance"))); return; } fail("WriteFailedException.DeleteFailedException was expected"); 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 3f33d141f..822b16c2b 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,16 +16,21 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; 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.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Optional; +import com.google.common.collect.Lists; 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; @@ -37,12 +42,17 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import org.junit.Test; import org.mockito.ArgumentCaptor; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; 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.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.openvpp.jvpp.dto.SwInterfaceDetails; import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; import org.openvpp.jvpp.dto.SwInterfaceDump; @@ -58,13 +68,23 @@ public class InterfaceCustomizerTest extends @Override public void setUpBefore() { - interfacesContext = new NamingContext("generatedIfaceName"); + interfacesContext = new NamingContext("generatedIfaceName", "test-instance"); } @Override protected RootReaderCustomizer initCustomizer() { - interfacesContext.addName(0, "eth0"); - interfacesContext.addName(1, "eth1"); + final KeyedInstanceIdentifier eth0Id = getMappingIid("eth0", "test-instance"); + final KeyedInstanceIdentifier eth1Id = getMappingIid("eth1", "test-instance"); + final Optional eth0 = getMapping("eth0", 0); + final Optional eth1 = getMapping("eth1", 1); + + final List allMappings = Lists.newArrayList(getMapping("eth0", 0).get(), getMapping("eth1", 1).get()); + final Mappings allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build(); + doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(eth0Id.firstIdentifierOf(Mappings.class)); + + doReturn(eth0).when(mappingContext).read(eth0Id); + doReturn(eth1).when(mappingContext).read(eth1Id); + return new InterfaceCustomizer(api, interfacesContext); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java index b454446dc..b09381584 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2CustomizerTest.java @@ -16,12 +16,16 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import io.fd.honeycomb.v3po.translate.Context; +import com.google.common.base.Optional; +import com.google.common.collect.Lists; import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; @@ -33,6 +37,10 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ExecutionException; import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; 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.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -43,6 +51,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.interfaces.state._interface.l2.Interconnection; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.interconnection.BridgeBasedBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; import org.openvpp.jvpp.dto.BridgeDomainDump; import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; @@ -59,8 +68,8 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest { @Override public void setUpBefore() { - interfaceContext = new NamingContext("generatedIfaceName"); - bridgeDomainContext = new NamingContext("generatedBDName"); + interfaceContext = new NamingContext("generatedIfaceName", "ifc-test-instance"); + bridgeDomainContext = new NamingContext("generatedBDName", "bd-test-instance"); } @Override @@ -111,19 +120,28 @@ public class L2CustomizerTest extends ChildReaderCustomizerTest { @Test public void testRead() throws Exception { - final Context ctx = new Context(); final Map cachedInterfaceDump = new HashMap<>(); final int ifId = 1; final int bdId = 1; final String bdName = "bd001"; final String ifName = "eth0.sub0"; - interfaceContext.addName(ifId, ifName); - bridgeDomainContext.addName(bdId, bdName); + final KeyedInstanceIdentifier ifcIid = getMappingIid(ifName, "ifc-test-instance"); + doReturn(getMapping(ifName, ifId)).when(mappingContext).read(ifcIid); + final KeyedInstanceIdentifier bdIid = getMappingIid(bdName, "bd-test-instance"); + doReturn(getMapping(bdName, bdId)).when(mappingContext).read(bdIid); + + List allMappings = Lists.newArrayList(getMapping(ifName, ifId).get()); + Mappings allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build(); + doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(ifcIid.firstIdentifierOf(Mappings.class)); + + allMappings = Lists.newArrayList(getMapping(bdName, bdId).get()); + allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build(); + doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(bdIid.firstIdentifierOf(Mappings.class)); final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = ifId; cachedInterfaceDump.put(ifId, ifaceDetails); - ctx.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); + cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); whenBridgeDomainSwIfDumpThenReturn(Collections.singletonList(generateBdSwIfDetails(ifId, bdId))); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizerTest.java index 8ed35e01b..4f6857b47 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizerTest.java @@ -16,19 +16,29 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import io.fd.honeycomb.v3po.translate.Context; +import com.google.common.base.Optional; +import com.google.common.collect.Lists; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.Test; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; 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.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; @@ -38,6 +48,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.interfaces.state._interface.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterfaceBuilder; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.openvpp.jvpp.dto.SwInterfaceDetails; public class SubInterfaceCustomizerTest extends ChildReaderCustomizerTest { @@ -55,7 +66,7 @@ public class SubInterfaceCustomizerTest extends ChildReaderCustomizerTest getSubInterfaceId(final String name) { @@ -74,21 +85,30 @@ public class SubInterfaceCustomizerTest extends ChildReaderCustomizerTest cachedInterfaceDump = new HashMap<>(); final int ifId = 1; final String ifName = "eth0.sub0"; - interfacesContext.addName(ifId, ifName); + + final KeyedInstanceIdentifier ifcIid = getMappingIid(ifName, "test-instance"); + doReturn(getMapping(ifName, ifId)).when(mappingContext).read(ifcIid); + final KeyedInstanceIdentifier superIfcIid = getMappingIid("super", "test-instance"); + doReturn(getMapping("super", 0)).when(mappingContext).read(superIfcIid); + + final List allMappings = Lists.newArrayList(getMapping(ifName, ifId).get(), getMapping("super", 0).get()); + final Mappings allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build(); + doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(ifcIid.firstIdentifierOf(Mappings.class)); + final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = ifId; ifaceDetails.interfaceName = ifName.getBytes(); cachedInterfaceDump.put(ifId, ifaceDetails); - ctx.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); + cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); final SubInterfaceBuilder builder = mock(SubInterfaceBuilder.class); getCustomizer().readCurrentAttributes(getSubInterfaceId(ifName), builder, ctx); verify(builder).setIdentifier((long)ifId); + verify(builder).setSuperInterface(anyString()); verify(builder).setNumberOfTags((short)0); verify(builder).setVlanType(VlanType._802dot1ad); verify(builder, never()).setExactMatch(any()); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java index 2263160e3..d00745ec1 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizerTest.java @@ -16,12 +16,14 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; @@ -52,7 +54,7 @@ public class VlanTagRewriteCustomizerTest extends ChildReaderCustomizerTest cachedInterfaceDump = new HashMap<>(); final int ifId = 1; final String ifName = "eth0.sub0"; - interfacesContext.addName(ifId, ifName); + doReturn(getMapping(ifName, ifId)).when(mappingContext).read(getMappingIid(ifName, "test-instance")); + final SwInterfaceDetails ifaceDetails = new SwInterfaceDetails(); ifaceDetails.subId = ifId; cachedInterfaceDump.put(ifId, ifaceDetails); - ctx.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); + cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, cachedInterfaceDump); final VlanTagRewriteBuilder builder = mock(VlanTagRewriteBuilder.class); getCustomizer().readCurrentAttributes(getVlanTagRewriteId(ifName), builder, ctx); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizerTest.java index 760e85b26..db92ebf17 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VxlanCustomizerTest.java @@ -16,6 +16,8 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMapping; +import static io.fd.honeycomb.v3po.translate.v3po.ContextTestUtils.getMappingIid; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -25,7 +27,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import com.google.common.collect.Lists; -import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.read.RootReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.test.ChildReaderCustomizerTest; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; @@ -50,7 +51,6 @@ import org.openvpp.jvpp.dto.VxlanTunnelDump; public class VxlanCustomizerTest extends ChildReaderCustomizerTest { private NamingContext interfacesContext; - private Context ctx; static final InstanceIdentifier IID = InstanceIdentifier.create(InterfacesState.class).child(Interface.class, new InterfaceKey("ifc1")) .augmentation(VppInterfaceStateAugmentation.class).child(Vxlan.class); @@ -61,15 +61,14 @@ public class VxlanCustomizerTest extends ChildReaderCustomizerTest map = new HashMap<>(); map.put(0, v); - ctx.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map); + cache.put(InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY, map); } @Override @@ -114,7 +113,7 @@ public class VxlanCustomizerTest extends ChildReaderCustomizerTest dataObjectClass; private RootReaderCustomizer customizer; @@ -52,6 +58,10 @@ public abstract class RootReaderCustomizerTest vppWriter; - private WriteContext ctx; - private NamingContext bdContext; @Before public void setUp() throws Exception { - api = mock(FutureJVpp.class); - ctx = mock(WriteContext.class); - bdContext = new NamingContext("generatedBdName"); + MockitoAnnotations.initMocks(this); + NamingContext bdContext = new NamingContext("generatedBdName", "test-instance"); + final ModificationCache toBeReturned = new ModificationCache(); + doReturn(toBeReturned).when(ctx).getModificationCache(); + doReturn(mappingContext).when(ctx).getMappingContext(); + vppWriter = VppUtils.getVppWriter(api, bdContext); rootRegistry = new DelegatingWriterRegistry( Collections.>singletonList(vppWriter)); @@ -134,6 +150,8 @@ public class VppTest { final int bdId = 1; final BridgeDomains bdn1 = getBridgeDomains("bdn1"); whenBridgeDomainAddDelThen(0); + doReturn(Optional + .absent()).when(mappingContext).read(getMappingIid("bdn1", "test-instance").firstIdentifierOf(Mappings.class)); rootRegistry.update( InstanceIdentifier.create(Vpp.class), @@ -149,6 +167,8 @@ public class VppTest { final int bdId = 1; final BridgeDomains bdn1 = getBridgeDomains("bdn1"); whenBridgeDomainAddDelThen(0); + doReturn(Optional + .absent()).when(mappingContext).read(getMappingIid("bdn1", "test-instance").firstIdentifierOf(Mappings.class)); vppWriter.update(InstanceIdentifier.create(Vpp.class), null, @@ -156,6 +176,7 @@ public class VppTest { ctx); verifyBridgeDomainAddDel(Iterators.getOnlyElement(bdn1.getBridgeDomain().iterator()), bdId); + verify(mappingContext).put(getMappingIid("bdn1", "test-instance"), getMapping("bdn1", 1).get()); } @Test @@ -163,9 +184,11 @@ public class VppTest { final BridgeDomains bdn1 = getBridgeDomains("bdn1"); final int bdId = 1; final Vpp vpp = new VppBuilder().setBridgeDomains(bdn1).build(); + doReturn(Optional + .absent()).when(mappingContext).read(getMappingIid("bdn1", "test-instance").firstIdentifierOf(Mappings.class)); whenBridgeDomainAddDelThen(0); - rootRegistry.update(Collections., DataObject>emptyMap(), + rootRegistry.update(Collections.emptyMap(), Collections., DataObject>singletonMap(InstanceIdentifier.create(Vpp.class), vpp), ctx); @@ -178,7 +201,7 @@ public class VppTest { final BridgeDomains bdn1 = getBridgeDomains(bdName); final int bdId = 1; whenBridgeDomainAddDelThen(0); - bdContext.addName(bdId, bdName); + doReturn(getMapping(bdName, bdId)).when(mappingContext).read(getMappingIid(bdName, "test-instance")); rootRegistry.update( InstanceIdentifier.create(Vpp.class), @@ -204,7 +227,8 @@ public class VppTest { public void writeUpdate() throws Exception { final String bdName = "bdn1"; final int bdn1Id = 1; - bdContext.addName(bdn1Id, bdName); + doReturn(getMapping(bdName, bdn1Id)).when(mappingContext).read(getMappingIid(bdName, "test-instance")); + final BridgeDomains domainsBefore = getBridgeDomains(bdName); final BridgeDomain bdn1Before = domainsBefore.getBridgeDomain().get(0); 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 index c482c4485..369038687 100644 --- 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 @@ -40,8 +40,8 @@ public class BridgeDomainCustomizerTest extends ListReaderCustomizerTest>singletonList(vppStateReader)); } @@ -146,7 +160,14 @@ public class VppStateTest { final Version version = getVersion(); whenShowVersionThenReturn(0, version); - final List bdList = Arrays.asList(new BridgeDomainDetails(), new BridgeDomainDetails()); + final BridgeDomainDetails bridgeDomainDetails = new BridgeDomainDetails(); + final BridgeDomainDetails bridgeDomainDetails2 = new BridgeDomainDetails(); + bridgeDomainDetails2.bdId = 1; + + final List bdList = Arrays.asList(bridgeDomainDetails, bridgeDomainDetails2); + mockBdMapping(bridgeDomainDetails, "bd1"); + mockBdMapping(bridgeDomainDetails2, "bd2"); + whenBridgeDomainDumpThenReturn(bdList); final Multimap, ? extends DataObject> dataObjects = readerRegistry.readAll(ctx); @@ -171,8 +192,10 @@ public class VppStateTest { public void testReadBridgeDomains() throws Exception { final Version version = getVersion(); whenShowVersionThenReturn(0, version); - whenBridgeDomainDumpThenReturn(Collections.singletonList(new BridgeDomainDetails())); + final BridgeDomainDetails details = new BridgeDomainDetails(); + whenBridgeDomainDumpThenReturn(Collections.singletonList(details)); + mockBdMapping(details, "bdn1"); VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); Optional read = @@ -189,7 +212,9 @@ public class VppStateTest { final BridgeDomainDetails bd = new BridgeDomainDetails(); bd.bdId = 0; final String bdName = "bdn1"; - bdContext.addName(bd.bdId, bdName); + mockBdMapping(bd, bdName); + mockMapping("eth1", 0, "ifc-test-instance"); + whenBridgeDomainDumpThenReturn(Collections.singletonList(bd)); final L2FibTableEntry l2FibEntry = new L2FibTableEntry(); l2FibEntry.bdId = 0; @@ -204,18 +229,44 @@ public class VppStateTest { assertTrue(read.isPresent()); // non existing l2fib - read = - readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( + read = readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( BridgeDomain.class, new BridgeDomainKey("bdn1")) .child(L2Fib.class, new L2FibKey(new PhysAddress("FF:FF:FF:04:05:06"))), ctx); assertFalse(read.isPresent()); } + private void mockBdMapping(final BridgeDomainDetails bd, final String bdName) { + mockMapping(bdName, bd.bdId, "bd-test-instance"); + } + + private void mockMapping(final String name, final int id, final String namingContextName) { + final InstanceIdentifier mappingsIid = getMappingIid(name, namingContextName).firstIdentifierOf(Mappings.class); + + final Optional singleMapping = getMapping(name, id); + final Optional previousMappings = mappingContext.read(mappingsIid); + + final MappingsBuilder mappingsBuilder; + if(previousMappings != null && previousMappings.isPresent()) { + mappingsBuilder = new MappingsBuilder(previousMappings.get()); + } else { + mappingsBuilder = new MappingsBuilder(); + mappingsBuilder.setMapping(Lists.newArrayList()); + } + + final List mappingList = mappingsBuilder.getMapping(); + mappingList.add(singleMapping.get()); + doReturn(Optional.of(mappingsBuilder.setMapping(mappingList).build())) + .when(mappingContext).read(mappingsIid); + doReturn(singleMapping).when(mappingContext).read(getMappingIid(name, namingContextName)); + } + @Test public void testReadBridgeDomainAll() throws Exception { final Version version = getVersion(); whenShowVersionThenReturn(0, version); - whenBridgeDomainDumpThenReturn(Collections.singletonList(new BridgeDomainDetails())); + final BridgeDomainDetails details = new BridgeDomainDetails(); + whenBridgeDomainDumpThenReturn(Collections.singletonList(details)); + mockBdMapping(details, "bd2"); VppState readRoot = (VppState) readerRegistry.read(InstanceIdentifier.create(VppState.class), ctx).get(); @@ -234,7 +285,8 @@ public class VppStateTest { final BridgeDomainDetails bd = new BridgeDomainDetails(); bd.bdId = 0; final String bdName = "bdn1"; - bdContext.addName(bd.bdId, bdName); + mockBdMapping(bd, bdName); + whenBridgeDomainDumpThenReturn(Collections.singletonList(bd)); whenShowVersionThenReturn(0, getVersion()); @@ -245,12 +297,15 @@ public class VppStateTest { BridgeDomain.class, new BridgeDomainKey(bdName)), ctx); assertTrue(read.isPresent()); - assertEquals(Iterables.find(readRoot.getBridgeDomains().getBridgeDomain(), - input -> input.getKey().getName().equals(bdName)), read.get()); + assertEquals(readRoot.getBridgeDomains().getBridgeDomain().stream().filter( + input -> input.getKey().getName().equals(bdName)).findFirst().get(), + read.get()); } @Test(expected = IllegalArgumentException.class) public void testReadBridgeDomainNotExisting() throws Exception { + doReturn(Optional.absent()).when(mappingContext).read(getMappingIid("NOT EXISTING", "bd-test-instance")); + final Optional read = readerRegistry.read(InstanceIdentifier.create(VppState.class).child(BridgeDomains.class).child( BridgeDomain.class, new BridgeDomainKey("NOT EXISTING")), ctx); -- cgit 1.2.3-korg