From: Michal Cmarada Date: Wed, 18 May 2016 13:22:30 +0000 (+0200) Subject: Update of BaseEndpointRpcRegistry X-Git-Tag: release/boron~169 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=2e0f0354758cf387e4ec6966d71aa47dbdf7d773;p=groupbasedpolicy.git Update of BaseEndpointRpcRegistry - adding Verification of RPC Input - adding update of Endpoints in op DS - Unit tests Change-Id: Ic709f7a47f3aeed7e46201d17ed54d297c8031bc Signed-off-by: Michal Cmarada --- diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistry.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistry.java index d92edd196..899e29e8b 100644 --- a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistry.java +++ b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistry.java @@ -9,38 +9,55 @@ package org.opendaylight.groupbasedpolicy.base_endpoint; import com.google.common.base.Function; -import com.google.common.util.concurrent.CheckedFuture; -import com.google.common.util.concurrent.FutureCallback; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadTransaction; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentation; import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentationRegistry; +import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.groupbasedpolicy.util.IidFactory; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.BaseEndpointService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnreg; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg; import org.opendaylight.yangtools.yang.binding.Augmentation; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -48,10 +65,13 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Future; +import javax.annotation.Nullable; + public class BaseEndpointRpcRegistry - implements BaseEndpointService, BaseEndpointRendererAugmentationRegistry, AutoCloseable { + implements BaseEndpointService, BaseEndpointRendererAugmentationRegistry, AutoCloseable { - static final ConcurrentMap registeredRenderers = new ConcurrentHashMap<>(); + static final ConcurrentMap registeredRenderers = + new ConcurrentHashMap<>(); private static final Logger LOG = LoggerFactory.getLogger(BaseEndpointRpcRegistry.class); private final DataBroker dataProvider; private final BindingAwareBroker.RpcRegistration rpcRegistration; @@ -65,33 +85,11 @@ public class BaseEndpointRpcRegistry }; public BaseEndpointRpcRegistry(DataBroker dataProvider, RpcProviderRegistry rpcRegistry) { - this.dataProvider = dataProvider; - - if (rpcRegistry != null) { - rpcRegistration = rpcRegistry.addRpcImplementation(BaseEndpointService.class, this); - LOG.debug("Added Endpoints RPC Implementation Correctly"); - } else { - rpcRegistration = null; - } - - if (dataProvider != null) { - InstanceIdentifier iid = InstanceIdentifier.builder(Endpoints.class).build(); - WriteTransaction t = this.dataProvider.newWriteOnlyTransaction(); - t.put(LogicalDatastoreType.OPERATIONAL, iid, new EndpointsBuilder().build()); - CheckedFuture f = t.submit(); - Futures.addCallback(f, new FutureCallback() { - - @Override - public void onFailure(Throwable t) { - LOG.error("Could not write Endpoints base container", t); - } + Preconditions.checkNotNull(dataProvider); + Preconditions.checkNotNull(rpcRegistry); - @Override - public void onSuccess(Void result) { - LOG.info("Endpoints container write successful"); - } - }); - } + this.dataProvider = dataProvider; + this.rpcRegistration = rpcRegistry.addRpcImplementation(BaseEndpointService.class, this); } /** @@ -104,7 +102,7 @@ public class BaseEndpointRpcRegistry public void register(BaseEndpointRendererAugmentation baseEndpointRendererAugmentation) { if (baseEndpointRendererAugmentation != null) { registeredRenderers.putIfAbsent(baseEndpointRendererAugmentation.getClass().getName(), - baseEndpointRendererAugmentation); + baseEndpointRendererAugmentation); LOG.info("Registered {}", baseEndpointRendererAugmentation.getClass().getName()); } } @@ -138,25 +136,294 @@ public class BaseEndpointRpcRegistry WriteTransaction t = dataProvider.newWriteOnlyTransaction(); List endpoints = input.getContainmentEndpointReg(); - for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) { - long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp(); - ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build(); - t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint, - true); - } + ListenableFuture> failResult = verifyRegisterEndpointInput(input); + if (failResult == null) { + for (ContainmentEndpointReg ce : nullToEmpty(endpoints)) { + long stamp = (ce.getTimestamp() == null || ce.getTimestamp() == 0) ? timestamp : ce.getTimestamp(); + ContainmentEndpoint endpoint = buildContainmentEndpoint(ce).setTimestamp(stamp).build(); + t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(endpoint.getKey()), endpoint, + true); + + updateContainmentEndpointRegChilds(t, endpoint); + } + + List addressEndpoints = input.getAddressEndpointReg(); + for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) { + long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp(); + AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build(); + t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint, + true); + + updateAddressEndpointRegChilds(t, endpoint); - List addressEndpoints = input.getAddressEndpointReg(); - for (AddressEndpointReg ae : nullToEmpty(addressEndpoints)) { - long stamp = (ae.getTimestamp() == null || ae.getTimestamp() == 0) ? timestamp : ae.getTimestamp(); - AddressEndpoint endpoint = buildAddressEndpoint(ae).setTimestamp(stamp).build(); - t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(endpoint.getKey()), endpoint, true); + updateAddressEndpointRegParents(t, endpoint); + } + } else { + return failResult; } ListenableFuture r = t.submit(); return Futures.transform(r, futureTrans); } + private void updateContainmentEndpointRegChilds(WriteTransaction t, ContainmentEndpoint containmentEndpoint) { + ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + for (ChildEndpoint child : nullToEmpty(containmentEndpoint.getChildEndpoint())) { + AddressEndpointKey key = new AddressEndpointKey(child.getAddress(), child.getAddressType(), + child.getContextId(), child.getContextType()); + Optional addressEndpointOptional = DataStoreHelper + .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key), readTransaction); + + if (addressEndpointOptional.isPresent()) { + ParentEndpointChoice parentEndpointChoice = addressEndpointOptional.get().getParentEndpointChoice(); + List parentContainmentEndpoints = + getParentContainmentEndpoints(parentEndpointChoice); + + ParentContainmentEndpoint parentContainmentEndpoint = + new ParentContainmentEndpointBuilder().setContextId(containmentEndpoint.getContextId()) + .setContextType(containmentEndpoint.getContextType()) + .build(); + + if (!nullToEmpty(parentContainmentEndpoints).contains(parentContainmentEndpoint)) { + parentContainmentEndpoints.add(parentContainmentEndpoint); + AddressEndpoint updatedAddressEndpoint = new AddressEndpointBuilder(addressEndpointOptional.get()) + .setParentEndpointChoice(new ParentContainmentEndpointCaseBuilder() + .setParentContainmentEndpoint(parentContainmentEndpoints).build()) + .build(); + + t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key), updatedAddressEndpoint); + } + } + } + } + + private ListenableFuture> verifyRegisterEndpointInput(RegisterEndpointInput input) { + ListenableFuture> result; + List addressEndpointRegs = nullToEmpty(input.getAddressEndpointReg()); + List containmentEndpointRegs = nullToEmpty(input.getContainmentEndpointReg()); + + for (AddressEndpointReg addressEndpointReg : nullToEmpty(addressEndpointRegs)) { + result = verifyAddressEndpointChilds(addressEndpointRegs, addressEndpointReg); + if (result != null) { + return result; + } + + result = verifyAddressEndpointParents(addressEndpointRegs, addressEndpointReg); + if (result != null) { + return result; + } + } + + result = verifyContainmentEndpointChilds(addressEndpointRegs, containmentEndpointRegs); + if (result != null) { + return result; + } + + return null; + } + + private ListenableFuture> verifyContainmentEndpointChilds( + List addressEndpointRegs, List containmentEndpointRegs) { + for (ContainmentEndpointReg containmentEndpointReg : nullToEmpty(containmentEndpointRegs)) { + for (ChildEndpoint childEndpoint : nullToEmpty(containmentEndpointReg.getChildEndpoint())) { + AddressEndpointRegKey key = new AddressEndpointRegKey(childEndpoint.getAddress(), + childEndpoint.getAddressType(), childEndpoint.getContextId(), childEndpoint.getContextType()); + AddressEndpointReg addressEndpointRegChild = findAddressEndpointReg(key, addressEndpointRegs); + if (addressEndpointRegChild == null) { + // todo this can be optimized if we move this to + // updateContainmentEndpointRegChilds and verify child in one step with update. + Optional addressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(), + key.getAddressType(), key.getContextId(), key.getContextType())), + dataProvider.newReadOnlyTransaction()); + if (!addressEndpointOptional.isPresent()) { + LOG.debug("Child AddressEndpoint {} does not exist in RPC and DS.", childEndpoint); + return buildFailFeature( + String.format("Child AddressEndpoint %s does not exist in RPC and DS.", childEndpoint)); + } + } else { + + if (!containmentEndpointReg.getKey().equals(new ContainmentEndpointRegKey( + addressEndpointRegChild.getContextId(), addressEndpointRegChild.getContextType()))) { + LOG.debug( + "Child AddressEndpoint {} in ContainmentEndpoint->ChildEndpoints does not contain a valid ContainmentEndpointRegKey.", + addressEndpointRegChild); + return buildFailFeature(String + .format("AddressEndpoint in ContainmentEndpoint->ChildEndpoints does not contain a valid ContainmentEndpointRegKey." + + "\nChild element: %s", addressEndpointRegChild)); + } + } + } + } + return null; + } + + private ListenableFuture> verifyAddressEndpointParents(List addressEndpointRegs, + AddressEndpointReg addressEndpointReg) { + ParentEndpointChoice parentEndpointChoice = addressEndpointReg.getParentEndpointChoice(); + List parentEndpoints; + parentEndpoints = + (parentEndpointChoice instanceof ParentEndpointCase) ? ((ParentEndpointCase) parentEndpointChoice) + .getParentEndpoint() : null; + + for (ParentEndpoint parentEndpoint : nullToEmpty(parentEndpoints)) { + AddressEndpointRegKey key = new AddressEndpointRegKey(parentEndpoint.getAddress(), + parentEndpoint.getAddressType(), parentEndpoint.getContextId(), parentEndpoint.getContextType()); + AddressEndpointReg addressEndpointRegParent = findAddressEndpointReg(key, addressEndpointRegs); + + if (addressEndpointRegParent == null) { + // todo this can be optimized if we move this to updateAddressEndpointRegParents and + // verify child in one step with update. + Optional addressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(), + key.getAddressType(), key.getContextId(), key.getContextType())), + dataProvider.newReadOnlyTransaction()); + if (!addressEndpointOptional.isPresent()) { + LOG.debug("Parent AddressEndpoint {} does not exist in RPC and DS.", parentEndpoint); + return buildFailFeature( + String.format("Parent AddressEndpoint %s does not exist in RPC and DS.", parentEndpoint)); + } + } else { + + List childEndpoints = addressEndpointRegParent.getChildEndpoint(); + + if (!nullToEmpty(childEndpoints).contains(new ChildEndpointBuilder(addressEndpointReg).build())) { + LOG.debug("Parent AddressEndpoint {} does not contain a valid child AddressEndpoint.", + addressEndpointRegParent); + return buildFailFeature(String.format( + "Parent AddressEndpoint does not contain a valid child AddressEndpoint." + + "\nParent AddressEndpoint: %s" + "\nChild AddressEndpoint: %s", + addressEndpointRegParent, addressEndpointReg)); + } + } + } + return null; + } + + private ListenableFuture> verifyAddressEndpointChilds(List addressEndpointRegs, + AddressEndpointReg addressEndpointReg) { + for (ChildEndpoint childEndpoint : nullToEmpty(addressEndpointReg.getChildEndpoint())) { + AddressEndpointRegKey key = new AddressEndpointRegKey(childEndpoint.getAddress(), + childEndpoint.getAddressType(), childEndpoint.getContextId(), childEndpoint.getContextType()); + AddressEndpointReg addressEndpointRegChild = findAddressEndpointReg(key, addressEndpointRegs); + if (addressEndpointRegChild == null) { + // todo this can be optimized if we move this to updateAddressEndpointRegChilds and + // verify child in one step with update. + Optional addressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(key.getAddress(), + key.getAddressType(), key.getContextId(), key.getContextType())), + dataProvider.newReadOnlyTransaction()); + if (!addressEndpointOptional.isPresent()) { + LOG.debug("Child AddressEndpoint {} does not exist in RPC and DS.", childEndpoint); + return buildFailFeature( + String.format("Child AddressEndpoint %s does not exist in RPC and DS.", childEndpoint)); + } + } else { + + ParentEndpointChoice parentEndpointChoice = addressEndpointRegChild.getParentEndpointChoice(); + + if (!(parentEndpointChoice instanceof ParentEndpointCase)) { + LOG.debug("Child AddressEndpoint {} does not contain list of parent elements.", childEndpoint); + return buildFailFeature(String.format( + "Child AddressEndpoint does not contain list of parent elements." + "\nChild element: %s", + childEndpoint)); + } + + List parentEndpoints = + nullToEmpty(((ParentEndpointCase) parentEndpointChoice).getParentEndpoint()); + if (!parentEndpoints.contains(new ParentEndpointBuilder(addressEndpointReg).build())) { + LOG.debug("Child AddressEndpoint {} does not contain a valid parent AddressEndpoint.", + addressEndpointRegChild); + return buildFailFeature(String.format( + "Child AddressEndpoint does not contain a valid parent AddressEndpoint." + + "\nChild element: %s" + "\nparent AddressEndpoint: %s", + addressEndpointRegChild, addressEndpointReg)); + } + } + } + return null; + } + + private AddressEndpointReg findAddressEndpointReg(AddressEndpointRegKey key, List addressEndpointRegs) { + for (AddressEndpointReg addressEndpointReg : addressEndpointRegs) { + if (addressEndpointReg.getKey().equals(key)) { + return addressEndpointReg; + } + } + return null; + } + + private void updateAddressEndpointRegParents(WriteTransaction t, AddressEndpoint endpoint) { + ParentEndpointCase parentEndpointCase = (ParentEndpointCase) endpoint.getParentEndpointChoice(); + List parentEndpoints; + ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + parentEndpoints = getParentEndpoints(parentEndpointCase); + + for (ParentEndpoint parent : nullToEmpty(parentEndpoints)) { + Optional addressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(parent.getAddress(), + parent.getAddressType(), parent.getContextId(), parent.getContextType())), + readTransaction); + + if (addressEndpointOptional.isPresent()) { + + List childEndpoints; + + childEndpoints = (addressEndpointOptional.get() == null || addressEndpointOptional.get() + .getChildEndpoint() == null) ? new ArrayList<>() : addressEndpointOptional.get().getChildEndpoint(); + + ChildEndpoint childEndpoint = new ChildEndpointBuilder(endpoint).build(); + if (!childEndpoints.contains(childEndpoint)) { + childEndpoints.add(childEndpoint); + AddressEndpoint parentAddressEndpoint = new AddressEndpointBuilder(addressEndpointOptional.get()) + .setChildEndpoint(childEndpoints).build(); + t.put(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(parentAddressEndpoint.getKey()), parentAddressEndpoint); + } + } + } + } + + private void updateAddressEndpointRegChilds(WriteTransaction t, AddressEndpoint endpoint) { + ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + for (ChildEndpoint child : nullToEmpty(endpoint.getChildEndpoint())) { + Optional addressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(child.getAddress(), + child.getAddressType(), child.getContextId(), child.getContextType())), + readTransaction); + + if (addressEndpointOptional.isPresent()) { + ParentEndpointCase parentEndpointCase = + (ParentEndpointCase) addressEndpointOptional.get().getParentEndpointChoice(); + List parentEndpoints; + + parentEndpoints = getParentEndpoints(parentEndpointCase); + + ParentEndpoint parentEndpoint = new ParentEndpointBuilder(endpoint).build(); + if (!parentEndpoints.contains(parentEndpoint)) { + parentEndpoints.add(parentEndpoint); + AddressEndpoint childAddressEndpoint = + new AddressEndpointBuilder(addressEndpointOptional.get()) + .setParentEndpointChoice( + new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build()) + .build(); + t.put(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(childAddressEndpoint.getKey()), childAddressEndpoint); + } + } + } + } + private ContainmentEndpointBuilder buildContainmentEndpoint(ContainmentEndpointReg input) { + ContainmentEndpointBuilder eb = new ContainmentEndpointBuilder().setChildEndpoint(input.getChildEndpoint()) .setCondition(input.getCondition()) .setContextType(input.getContextType()) @@ -165,7 +432,8 @@ public class BaseEndpointRpcRegistry .setKey(new ContainmentEndpointKey(input.getContextId(), input.getContextType())) .setNetworkContainment(input.getNetworkContainment()) .setTenant(input.getTenant()) - .setTimestamp(input.getTimestamp()); + .setTimestamp(input.getTimestamp()) + .setChildEndpoint(input.getChildEndpoint()); for (Map.Entry entry : registeredRenderers.entrySet()) { try { @@ -225,18 +493,157 @@ public class BaseEndpointRpcRegistry AddressEndpointKey key = new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), ae.getContextId(), ae.getContextType()); t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(key)); + + updateAddressEndpointUnregChilds(t, ae); + + updateAddressEndpointUnregParents(t, ae); } List endpoints = input.getContainmentEndpointUnreg(); for (ContainmentEndpointUnreg ce : nullToEmpty(endpoints)) { ContainmentEndpointKey key = new ContainmentEndpointKey(ce.getContextId(), ce.getContextType()); t.delete(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(key)); + + updateContainmentEndpointUnregChilds(t, ce); } ListenableFuture r = t.submit(); return Futures.transform(r, futureTrans); } + private void updateAddressEndpointUnregParents(WriteTransaction t, AddressEndpointUnreg ae) { + ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + Optional addressEndpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), + ae.getContextId(), ae.getContextType())), + readTransaction); + + if (addressEndpointOptional.isPresent()) { + ParentEndpointCase parentEndpointCase = + (ParentEndpointCase) addressEndpointOptional.get().getParentEndpointChoice(); + List parentEndpoints; + + parentEndpoints = getParentEndpoints(parentEndpointCase); + + for (ParentEndpoint parentEndpoint : parentEndpoints) { + Optional parentAddressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(parentEndpoint.getAddress(), + parentEndpoint.getAddressType(), parentEndpoint.getContextId(), + parentEndpoint.getContextType())), + readTransaction); + + AddressEndpoint parent = + parentAddressEndpointOptional.isPresent() ? parentAddressEndpointOptional.get() : null; + + ChildEndpoint endpointToRemove = new ChildEndpointBuilder(addressEndpointOptional.get()).build(); + + if (parent != null && nullToEmpty(parent.getChildEndpoint()).contains(endpointToRemove)) { + parent.getChildEndpoint().remove(endpointToRemove); + t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(parent.getKey()), parent); + } + + } + } + } + + private void updateAddressEndpointUnregChilds(WriteTransaction t, AddressEndpointUnreg ae) { + ReadTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + Optional addressEndpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(ae.getAddress(), ae.getAddressType(), + ae.getContextId(), ae.getContextType())), + readTransaction); + + if (addressEndpointOptional.isPresent()) { + AddressEndpoint endpoint = addressEndpointOptional.get(); + List childEndpoints = endpoint.getChildEndpoint(); + + for (ChildEndpoint childEndpoint : nullToEmpty(childEndpoints)) { + Optional childAddressEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(new AddressEndpointKey(childEndpoint.getAddress(), + childEndpoint.getAddressType(), childEndpoint.getContextId(), + childEndpoint.getContextType())), + readTransaction); + + AddressEndpoint child = + childAddressEndpointOptional.isPresent() ? childAddressEndpointOptional.get() : null; + ParentEndpointCase parentEndpointCase = + (child != null) ? (ParentEndpointCase) child.getParentEndpointChoice() : null; + List parentEndpoints; + + parentEndpoints = getParentEndpoints(parentEndpointCase); + + ParentEndpoint endpointToRemove = new ParentEndpointBuilder(endpoint).build(); + + if (child != null && nullToEmpty(parentEndpoints).contains(endpointToRemove)) { + parentEndpoints.remove(endpointToRemove); + AddressEndpoint newChild = + new AddressEndpointBuilder(child) + .setParentEndpointChoice( + new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build()) + .build(); + + t.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(newChild.getKey()), newChild); + } + } + } + } + + private void updateContainmentEndpointUnregChilds(WriteTransaction t, + ContainmentEndpointUnreg containmentEndpointUnreg) { + ReadOnlyTransaction readTransaction = dataProvider.newReadOnlyTransaction(); + + ContainmentEndpointKey key = new ContainmentEndpointKey(containmentEndpointUnreg.getContextId(), + containmentEndpointUnreg.getContextType()); + Optional containmentEndpointOptional = DataStoreHelper + .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(key), readTransaction); + + if (!containmentEndpointOptional.isPresent()) { + return; + } + + for (ChildEndpoint child : nullToEmpty(containmentEndpointOptional.get().getChildEndpoint())) { + AddressEndpointKey aeKey = new AddressEndpointKey(child.getAddress(), child.getAddressType(), + child.getContextId(), child.getContextType()); + Optional addressEndpointOptional = DataStoreHelper + .readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aeKey), readTransaction); + + if (addressEndpointOptional.isPresent()) { + ParentEndpointChoice parentEndpointChoice = addressEndpointOptional.get().getParentEndpointChoice(); + List parentContainmentEndpoints; + parentContainmentEndpoints = getParentContainmentEndpoints(parentEndpointChoice); + + ParentContainmentEndpoint parentContainmentEndpoint = + new ParentContainmentEndpointBuilder().setContextId(containmentEndpointUnreg.getContextId()) + .setContextType(containmentEndpointUnreg.getContextType()) + .build(); + if (nullToEmpty(parentContainmentEndpoints).contains(parentContainmentEndpoint)) { + t.delete(LogicalDatastoreType.OPERATIONAL, + IidFactory.parentContainmentEndpointIid(aeKey, parentContainmentEndpoint.getKey())); + } + } + } + } + + private List getParentContainmentEndpoints(ParentEndpointChoice parentEndpointChoice) { + return (parentEndpointChoice instanceof ParentContainmentEndpointCase) ? ((ParentContainmentEndpointCase) parentEndpointChoice) + .getParentContainmentEndpoint() : new ArrayList<>(); + } + + private List getParentEndpoints(ParentEndpointCase parentEndpointCase) { + return (parentEndpointCase == null + || parentEndpointCase.getParentEndpoint() == null) ? new ArrayList<>() : parentEndpointCase + .getParentEndpoint(); + } + + private ListenableFuture> buildFailFeature(String message) { + return Futures + .immediateFuture(RpcResultBuilder.failed().withError(RpcError.ErrorType.PROTOCOL, message).build()); + } + @Override public void close() throws Exception { if (rpcRegistration != null) { diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java index 2116d12e1..a9f9e6c6b 100644 --- a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java +++ b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/IidFactory.java @@ -17,6 +17,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.containment.endpoint._case.ParentContainmentEndpointKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierDefinitionId; @@ -393,6 +395,17 @@ public class IidFactory { .build(); } + public static InstanceIdentifier parentContainmentEndpointIid( + AddressEndpointKey addressEndpointKey, ParentContainmentEndpointKey parentContainmentEndpointKey) { + return InstanceIdentifier + .builder( + org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints.class) + .child(AddressEndpoints.class) + .child(AddressEndpoint.class, addressEndpointKey) + .child(ParentContainmentEndpoint.class, parentContainmentEndpointKey) + .build(); + } + public static InstanceIdentifierBuilder providerAddressEndpointLocationIid(String provider, Class addrType, String addr, Class cType, ContextId containment) { diff --git a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistryTest.java b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistryTest.java index 875043dee..b83bcc541 100644 --- a/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistryTest.java +++ b/groupbasedpolicy/src/test/java/org/opendaylight/groupbasedpolicy/base_endpoint/BaseEndpointRpcRegistryTest.java @@ -8,65 +8,157 @@ package org.opendaylight.groupbasedpolicy.base_endpoint; -import com.google.common.util.concurrent.CheckedFuture; +import static org.mockito.Mockito.mock; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.groupbasedpolicy.api.BaseEndpointRendererAugmentation; -import org.opendaylight.groupbasedpolicy.base_endpoint.BaseEndpointRpcRegistry; +import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.*; +import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; +import org.opendaylight.groupbasedpolicy.util.IidFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.RegisterEndpointInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.ContainmentEndpoints; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentContainmentEndpointCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointReg; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.ContainmentEndpointRegBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.AddressEndpointUnregBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnreg; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.unregister.endpoint.input.ContainmentEndpointUnregBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.Subnet; -import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.AddressType; -import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Future; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; -import static org.mockito.internal.verification.VerificationModeFactory.times; +import javax.annotation.Nonnull; -public class BaseEndpointRpcRegistryTest { +public class BaseEndpointRpcRegistryTest extends CustomDataBrokerTest { private static final String MAC_ADDRESS = "01:23:45:67:89:AB"; + private static final String IP_ADDRESS = "192.168.100.1/24"; private static final String TENANT = "admin"; private static final String DOMAIN = "test.domain"; private static final String CONTEXT_ID = "testContext"; - private static final String FLOOD_DOMAIN = "testFloodDomain"; + private static final long timestamp = 1234567890L; + + private enum AddressEndpointRegistration { + CHILD, PARENT, BOTH, NONE + } + private enum AddressEndpointType { + L2, L3, BOTH, NONE + } private DataBroker dataProvider; private BaseEndpointRendererAugmentation baseEndpointRendererAugmentation; private BaseEndpointRpcRegistry baseEndpointRpcRegistry; + private AddressEndpoint basel2Ep; + private AddressEndpoint basel3Ep; + private ContainmentEndpoint baseContainmentEp; + private ParentEndpoint basel3Parent; + private ChildEndpoint basel2Child; + + @Nonnull + @Override + public Collection> getClassesFromModules() { + return ImmutableList.of(Endpoints.class, AddressEndpoints.class, ContainmentEndpoints.class, + MacAddressType.class, IpPrefixType.class); + } @Before public void init() { - dataProvider = mock(DataBroker.class); + dataProvider = getDataBroker(); baseEndpointRendererAugmentation = mock(BaseEndpointRendererAugmentation.class); - WriteTransaction wt = newWriteTransactionMock(); RpcProviderRegistry rpcRegistry = mock(RpcProviderRegistry.class); baseEndpointRpcRegistry = new BaseEndpointRpcRegistry(dataProvider, rpcRegistry); + + NetworkDomainContainment + networkDomainContainment = + new NetworkDomainContainmentBuilder().setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType( + Subnet.class).build(); + + basel3Parent = new ParentEndpointBuilder().setAddress(IP_ADDRESS) + .setAddressType(IpPrefixType.class) + .setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L3Context.class) + .build(); + + basel2Child = new ChildEndpointBuilder().setAddress(MAC_ADDRESS) + .setAddressType(MacAddressType.class) + .setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L2FloodDomain.class) + .build(); + + basel2Ep = new AddressEndpointBuilder().setTimestamp(timestamp) + .setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L2FloodDomain.class) + .setTenant(new TenantId(TENANT)) + .setAddress(MAC_ADDRESS) + .setAddressType(MacAddressType.class) + .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build()) + .setTimestamp(timestamp) + .setParentEndpointChoice( + new ParentEndpointCaseBuilder().setParentEndpoint(Collections.singletonList(basel3Parent)).build()) + .build(); + + basel3Ep = new AddressEndpointBuilder().setTimestamp(timestamp) + .setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L3Context.class) + .setTenant(new TenantId(TENANT)) + .setAddress(IP_ADDRESS) + .setAddressType(IpPrefixType.class) + .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build()) + .setTimestamp(timestamp) + .setChildEndpoint(Collections.singletonList(basel2Child)) + .build(); + + baseContainmentEp = new ContainmentEndpointBuilder().setTimestamp(timestamp) + .setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L2FloodDomain.class) + .setTenant(new TenantId(TENANT)) + .setNetworkContainment(new NetworkContainmentBuilder().setContainment(networkDomainContainment).build()) + .setChildEndpoint(Collections.singletonList(basel2Child)) + .build(); } @Test @@ -87,60 +179,357 @@ public class BaseEndpointRpcRegistryTest { @Test public void testRegisterEndpoint() throws Exception { - WriteTransaction wt = newWriteTransactionMock(); + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true); + + baseEndpointRpcRegistry.registerEndpoint(input); - baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest()); + ReadOnlyTransaction transaction = dataProvider.newReadOnlyTransaction(); - verify(wt, times(2)).put(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), - any(DataObject.class), eq(true)); + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), transaction); + + Assert.assertTrue(addressEndpointL2.isPresent()); + + if (addressEndpointL2.isPresent()) { + Assert.assertEquals(basel2Ep, addressEndpointL2.get()); + } + + key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class); + + Optional addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), transaction); + + Assert.assertTrue(addressEndpointL3.isPresent()); + + if (addressEndpointL3.isPresent()) { + Assert.assertEquals(basel3Ep, addressEndpointL3.get()); + } + + ContainmentEndpointKey containmentEndpointKey = + new ContainmentEndpointKey(new ContextId(CONTEXT_ID), L2FloodDomain.class); + + Optional ContainmentEndpoint = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.containmentEndpointIid(containmentEndpointKey), transaction); + + Assert.assertTrue(ContainmentEndpoint.isPresent()); + + if (ContainmentEndpoint.isPresent()) { + Assert.assertEquals(baseContainmentEp, ContainmentEndpoint.get()); + } } - private RegisterEndpointInput createRegisterEndpointInputVariablesForTest() throws Exception { - RegisterEndpointInputBuilder registerEndpointInputBuilder = new RegisterEndpointInputBuilder(); - long timestamp = System.currentTimeMillis(); + @Test + public void testRegisterEndpointWithParentUpdate() throws Exception { + setupBasicDataStore(); + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.L2, true); - registerEndpointInputBuilder.setAddressEndpointReg(new ArrayList<>()); - registerEndpointInputBuilder.setContainmentEndpointReg(new ArrayList<>()); + baseEndpointRpcRegistry.registerEndpoint(input); - registerEndpointInputBuilder.getAddressEndpointReg().add( - new AddressEndpointRegBuilder().setTimestamp(timestamp) - .setContextId(new ContextId(CONTEXT_ID)) - .setContextType(L2FloodDomain.class) - .setTenant(new TenantId(TENANT)) - .setAddress(MAC_ADDRESS) - .setAddressType(MacAddressType.class) - .setAddressType(AddressType.class) - .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder() - .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(Subnet.class).build()).build()) - .setKey(new AddressEndpointRegKey(MAC_ADDRESS,MacAddressType.class, new ContextId(CONTEXT_ID), L2FloodDomain.class)) - .setTimestamp(timestamp).build()); - - registerEndpointInputBuilder.getContainmentEndpointReg().add( - new ContainmentEndpointRegBuilder() - .setTimestamp(timestamp) - .setContextId(new L2FloodDomainId(FLOOD_DOMAIN)) - .setContextType(L2FloodDomain.class) - .setTenant(new TenantId(TENANT)) - .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder() - .setNetworkDomainId(new NetworkDomainId(DOMAIN)).setNetworkDomainType(Subnet.class).build()).build()) - .setKey(new ContainmentEndpointRegKey(new L2FloodDomainId(FLOOD_DOMAIN),L2FloodDomain.class)) - .build()); + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); - return registerEndpointInputBuilder.build(); + Assert.assertTrue(addressEndpointL2.isPresent()); + + if (addressEndpointL2.isPresent()) { + ParentEndpointCase parentEndpointCase = + (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice(); + List parentEndpoints = parentEndpointCase.getParentEndpoint(); + Assert.assertEquals(parentEndpoints.size(), 1); + } + + key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class); + + Optional addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL3.isPresent()); + + if (addressEndpointL3.isPresent()) { + Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 1); + } } @Test - public void testUnregisterEndpoint() throws Exception { - WriteTransaction wt = newWriteTransactionMock(); + public void testRegisterEndpointWithParentUpdateFail() throws Exception { + RegisterEndpointInput input = createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, + AddressEndpointType.L2, true); - UnregisterEndpointInput unregisterEndpointInput = unregisterEndpointInput(); + Future> rpcResultFuture = baseEndpointRpcRegistry.registerEndpoint(input); + + Assert.assertFalse(rpcResultFuture.get().isSuccessful()); + Assert.assertNotNull(rpcResultFuture.get().getErrors()); + Assert.assertEquals(rpcResultFuture.get().getErrors().size(), 1); + } + + @Test + public void testRegisterEndpointWithChildUpdate() throws Exception { + setupBasicDataStore(); + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.L3, true); - baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInput); + baseEndpointRpcRegistry.registerEndpoint(input); - verify(wt, times(2)).delete(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class)); + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + + if (addressEndpointL2.isPresent()) { + ParentEndpointCase parentEndpointCase = + (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice(); + List parentEndpoints = parentEndpointCase.getParentEndpoint(); + Assert.assertEquals(parentEndpoints.size(), 1); + } + + key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class); + + Optional addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL3.isPresent()); + + if (addressEndpointL3.isPresent()) { + Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 1); + } } - private UnregisterEndpointInput unregisterEndpointInput() { + @Test + public void testRegisterEndpointWithChildUpdateFail() throws Exception { + RegisterEndpointInput input = createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, + AddressEndpointType.L3, true); + + Future> rpcResultFuture = baseEndpointRpcRegistry.registerEndpoint(input); + + Assert.assertFalse(rpcResultFuture.get().isSuccessful()); + Assert.assertNotNull(rpcResultFuture.get().getErrors()); + Assert.assertEquals(rpcResultFuture.get().getErrors().size(), 1); + } + + private void setupBasicDataStore() throws Exception { + InstanceIdentifier id = InstanceIdentifier.builder(Endpoints.class).build(); + dataProvider.newWriteOnlyTransaction().delete(LogicalDatastoreType.OPERATIONAL, id); + + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.NONE, AddressEndpointType.BOTH, true); + + baseEndpointRpcRegistry.registerEndpoint(input); + + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + + if (addressEndpointL2.isPresent()) { + ParentEndpointCase parentEndpointCase = + (ParentEndpointCase) addressEndpointL2.get().getParentEndpointChoice(); + Assert.assertEquals(parentEndpointCase.getParentEndpoint().size(), 0); + } + + key = new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class); + + Optional addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL3.isPresent()); + + if (addressEndpointL3.isPresent()) { + Assert.assertEquals(addressEndpointL3.get().getChildEndpoint().size(), 0); + } + } + + @Test + public void testRegisterEndpointParentFail() throws Exception { + Future> rpcResultFuture = + baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest( + AddressEndpointRegistration.PARENT, AddressEndpointType.BOTH, true)); + + RpcResult rpcResult = rpcResultFuture.get(); + + Assert.assertFalse(rpcResult.isSuccessful()); + Assert.assertNull(rpcResult.getResult()); + Assert.assertEquals(rpcResult.getErrors().size(), 1); + + } + + @Test + public void testRegisterEndpointChildFail() throws Exception { + Future> rpcResultFuture = + baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest( + AddressEndpointRegistration.CHILD, AddressEndpointType.BOTH, true)); + + RpcResult rpcResult = rpcResultFuture.get(); + + Assert.assertFalse(rpcResult.isSuccessful()); + Assert.assertNull(rpcResult.getResult()); + Assert.assertEquals(rpcResult.getErrors().size(), 1); + } + + @Test + public void testUnregisterEndpointWithParent() throws Exception { + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true); + + baseEndpointRpcRegistry.registerEndpoint(input); + + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + ContainmentEndpointKey cKey = new ContainmentEndpointKey(new ContextId(CONTEXT_ID), L2FloodDomain.class); + + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + + if (addressEndpointL2.isPresent()) { + Assert.assertEquals(basel2Ep, addressEndpointL2.get()); + } + + Optional ContainmentEndpoint = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.containmentEndpointIid(cKey), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(ContainmentEndpoint.isPresent()); + + if (ContainmentEndpoint.isPresent()) { + Assert.assertEquals(baseContainmentEp, ContainmentEndpoint.get()); + } + + baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInputParent()); + Optional endpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertFalse(endpointOptional.isPresent()); + + Optional containmentEndpointOptional = + DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.containmentEndpointIid(cKey), + dataProvider.newReadOnlyTransaction()); + + Assert.assertFalse(containmentEndpointOptional.isPresent()); + } + + @Test + public void testUnregisterEndpointWithChild() throws Exception { + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.BOTH, AddressEndpointType.BOTH, true); + + baseEndpointRpcRegistry.registerEndpoint(input); + + AddressEndpointKey key = + new AddressEndpointKey(IP_ADDRESS, IpPrefixType.class, new ContextId(CONTEXT_ID), L3Context.class); + + Optional addressEndpointL3 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL3.isPresent()); + + if (addressEndpointL3.isPresent()) { + Assert.assertEquals(basel3Ep, addressEndpointL3.get()); + } + + baseEndpointRpcRegistry.unregisterEndpoint(unregisterEndpointInputChild()); + Optional endpointOptional = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertFalse(endpointOptional.isPresent()); + + } + + @Test + public void testRegisterContainmentEndpointWithChildFail() throws Exception { + Future> rpcResultFuture = + baseEndpointRpcRegistry.registerEndpoint(createRegisterEndpointInputVariablesForTest( + AddressEndpointRegistration.NONE, AddressEndpointType.NONE, true)); + + RpcResult rpcResult = rpcResultFuture.get(); + + Assert.assertFalse(rpcResult.isSuccessful()); + Assert.assertNull(rpcResult.getResult()); + Assert.assertEquals(rpcResult.getErrors().size(), 1); + } + + @Test + public void testUnregisterContainmentEndpointWithChild() throws Exception { + InstanceIdentifier id = InstanceIdentifier.builder(Endpoints.class).build(); + dataProvider.newWriteOnlyTransaction().delete(LogicalDatastoreType.OPERATIONAL, id); + + RegisterEndpointInput input = + createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration.NONE, AddressEndpointType.L2, false); + + baseEndpointRpcRegistry.registerEndpoint(input); + + AddressEndpointKey key = new AddressEndpointKey(MAC_ADDRESS, MacAddressType.class, new ContextId(CONTEXT_ID), + L2FloodDomain.class); + + Optional addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + if (addressEndpointL2.isPresent()){ + ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice(); + if(parentEndpointChoice instanceof ParentContainmentEndpointCase){ + ParentContainmentEndpointCase + parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice; + Assert.assertNull(parentEndpointCase.getParentContainmentEndpoint()); + } + } + + ContainmentEndpointReg containmentEndpointReg = new ContainmentEndpointRegBuilder().setTimestamp(baseContainmentEp.getTimestamp()) + .setContextId(baseContainmentEp.getContextId()) + .setContextType(baseContainmentEp.getContextType()) + .setTenant(baseContainmentEp.getTenant()) + .setNetworkContainment(baseContainmentEp.getNetworkContainment()) + .setChildEndpoint(Collections.singletonList(basel2Child)) + .build(); + + baseEndpointRpcRegistry.registerEndpoint(new RegisterEndpointInputBuilder().setContainmentEndpointReg(Collections.singletonList(containmentEndpointReg)).build()); + + addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + if (addressEndpointL2.isPresent()) { + ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice(); + if(parentEndpointChoice instanceof ParentContainmentEndpointCase){ + ParentContainmentEndpointCase + parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice; + Assert.assertNotNull(parentEndpointCase.getParentContainmentEndpoint()); + Assert.assertEquals(parentEndpointCase.getParentContainmentEndpoint().size(),1); + } + } + + ContainmentEndpointUnreg containmentEndpointUnreg = new ContainmentEndpointUnregBuilder() + .setContextId(baseContainmentEp.getContextId()) + .setContextType(baseContainmentEp.getContextType()) + .build(); + + baseEndpointRpcRegistry.unregisterEndpoint(new UnregisterEndpointInputBuilder().setContainmentEndpointUnreg(Collections.singletonList(containmentEndpointUnreg)).build()); + + addressEndpointL2 = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, + IidFactory.addressEndpointIid(key), dataProvider.newReadOnlyTransaction()); + + Assert.assertTrue(addressEndpointL2.isPresent()); + if (addressEndpointL2.isPresent()) { + ParentEndpointChoice parentEndpointChoice = addressEndpointL2.get().getParentEndpointChoice(); + if(parentEndpointChoice instanceof ParentContainmentEndpointCase){ + ParentContainmentEndpointCase + parentEndpointCase = (ParentContainmentEndpointCase) parentEndpointChoice; + Assert.assertNotNull(parentEndpointCase.getParentContainmentEndpoint()); + Assert.assertEquals(parentEndpointCase.getParentContainmentEndpoint().size(),0); + } + } + + } + + private UnregisterEndpointInput unregisterEndpointInputParent() { UnregisterEndpointInputBuilder builder = new UnregisterEndpointInputBuilder(); builder.setAddressEndpointUnreg(new ArrayList<>()); @@ -158,13 +547,77 @@ public class BaseEndpointRpcRegistryTest { return builder.build(); } - private WriteTransaction newWriteTransactionMock() { - WriteTransaction wt = mock(WriteTransaction.class); - CheckedFuture f = mock(CheckedFuture.class); + private UnregisterEndpointInput unregisterEndpointInputChild() { + UnregisterEndpointInputBuilder builder = new UnregisterEndpointInputBuilder(); + + builder.setAddressEndpointUnreg(new ArrayList<>()); + builder.setContainmentEndpointUnreg(new ArrayList<>()); - when(dataProvider.newWriteOnlyTransaction()).thenReturn(wt); - when(wt.submit()).thenReturn(f); - return wt; + builder.getAddressEndpointUnreg().add(new AddressEndpointUnregBuilder().setContextId(new ContextId(CONTEXT_ID)) + .setContextType(L3Context.class) + .setAddress(IP_ADDRESS) + .setAddressType(IpPrefixType.class) + .build()); + + return builder.build(); } + private RegisterEndpointInput createRegisterEndpointInputVariablesForTest(AddressEndpointRegistration registration, + AddressEndpointType type, boolean containmentEpPresent) throws Exception { + RegisterEndpointInputBuilder registerEndpointInputBuilder = new RegisterEndpointInputBuilder(); + long timestamp = System.currentTimeMillis(); + + List parentEndpoints = new ArrayList<>(); + if (registration == AddressEndpointRegistration.BOTH || registration == AddressEndpointRegistration.PARENT) { + parentEndpoints.add(basel3Parent); + } + + List childEndpoints = new ArrayList<>(); + if (registration == AddressEndpointRegistration.BOTH || registration == AddressEndpointRegistration.CHILD) { + childEndpoints.add(basel2Child); + } + + registerEndpointInputBuilder.setAddressEndpointReg(new ArrayList<>()); + registerEndpointInputBuilder.setContainmentEndpointReg(new ArrayList<>()); + + if (type == AddressEndpointType.BOTH || type == AddressEndpointType.L2) { + registerEndpointInputBuilder.getAddressEndpointReg() + .add(new AddressEndpointRegBuilder().setTimestamp(timestamp) + .setContextId(basel2Ep.getContextId()) + .setContextType(basel2Ep.getContextType()) + .setTenant(basel2Ep.getTenant()) + .setAddress(basel2Ep.getAddress()) + .setAddressType(basel2Ep.getAddressType()) + .setNetworkContainment(basel2Ep.getNetworkContainment()) + .setTimestamp(basel2Ep.getTimestamp()) + .setParentEndpointChoice(new ParentEndpointCaseBuilder().setParentEndpoint(parentEndpoints).build()) + .build()); + } + + if (type == AddressEndpointType.BOTH || type == AddressEndpointType.L3) { + registerEndpointInputBuilder.getAddressEndpointReg() + .add(new AddressEndpointRegBuilder().setContextId(basel3Ep.getContextId()) + .setContextType(basel3Ep.getContextType()) + .setTenant(basel3Ep.getTenant()) + .setAddress(basel3Ep.getAddress()) + .setAddressType(basel3Ep.getAddressType()) + .setNetworkContainment(basel3Ep.getNetworkContainment()) + .setTimestamp(basel3Ep.getTimestamp()) + .setChildEndpoint(childEndpoints) + .build()); + } + + if(containmentEpPresent) { + registerEndpointInputBuilder.getContainmentEndpointReg() + .add(new ContainmentEndpointRegBuilder().setTimestamp(baseContainmentEp.getTimestamp()) + .setContextId(baseContainmentEp.getContextId()) + .setContextType(baseContainmentEp.getContextType()) + .setTenant(baseContainmentEp.getTenant()) + .setNetworkContainment(baseContainmentEp.getNetworkContainment()) + .setChildEndpoint(Collections.singletonList(basel2Child)) + .build()); + } + + return registerEndpointInputBuilder.build(); + } }