From 5041389b273212eb0c643cc071fd48ad1166d864 Mon Sep 17 00:00:00 2001 From: Tomas Cere Date: Wed, 3 Nov 2021 12:20:45 +0100 Subject: [PATCH] Fix eos entity lookups with YangInstanceIdentifier Caused by entity-name only being a string type which was inadvertently trying to lookup all entities as General. Fix this by changing entity-name to a union of instance-identifier and string. Also changed up the output of get-entities slightly: - if the entity is string based it will only contain the name in the output. - if, however, it is Instance-identifier based it will contain the entire identifier in the name field. JIRA: CONTROLLER-2009 Change-Id: I93e108bd54b14850b6bf276ec1eca4d7671d7d87 Signed-off-by: Tomas Cere Signed-off-by: Robert Varga --- opendaylight/md-sal/eos-dom-akka/pom.xml | 30 +++++++++++ .../eos/akka/AkkaEntityOwnershipService.java | 18 ++++--- .../eos/akka/bootstrap/EOSMain.java | 10 ++-- .../akka/owner/supervisor/IdleSupervisor.java | 15 ++++-- .../owner/supervisor/OwnerSupervisor.java | 26 +++++++--- .../akka/owner/supervisor/OwnerSyncer.java | 19 ++++--- .../supervisor/command/GetEntitiesReply.java | 23 ++++++-- .../owners/norev/EntityNameBuilder.java | 18 +++++++ .../src/main/yang/odl-akka-eos.yang | 7 ++- .../eos/akka/AbstractNativeEosTest.java | 15 ++++-- .../akka/AkkaEntityOwnershipServiceTest.java | 52 ++++++++++++++++++- .../owner/supervisor/OwnerSupervisorTest.java | 2 +- 12 files changed, 196 insertions(+), 39 deletions(-) create mode 100644 opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/entity/owners/norev/EntityNameBuilder.java diff --git a/opendaylight/md-sal/eos-dom-akka/pom.xml b/opendaylight/md-sal/eos-dom-akka/pom.xml index b9b50f5822..22268e215b 100644 --- a/opendaylight/md-sal/eos-dom-akka/pom.xml +++ b/opendaylight/md-sal/eos-dom-akka/pom.xml @@ -50,6 +50,14 @@ org.opendaylight.mdsal mdsal-binding-api + + org.opendaylight.mdsal + mdsal-binding-dom-codec-api + + + org.opendaylight.mdsal.model + general-entity + org.opendaylight.yangtools concepts @@ -91,6 +99,21 @@ awaitility + + org.opendaylight.mdsal + mdsal-binding-dom-codec + test + + + org.opendaylight.mdsal + mdsal-binding-generator + test + + + org.opendaylight.mdsal + mdsal-binding-runtime-spi + test + org.opendaylight.mdsal mdsal-singleton-common-api @@ -101,5 +124,12 @@ mdsal-singleton-dom-impl test + + + org.opendaylight.mdsal.model + ietf-topology + test + + diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipService.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipService.java index ce60f6f83d..e815c8a6a0 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipService.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipService.java @@ -38,7 +38,6 @@ import org.opendaylight.controller.eos.akka.owner.checker.command.GetOwnershipSt import org.opendaylight.controller.eos.akka.owner.checker.command.StateCheckerCommand; import org.opendaylight.controller.eos.akka.owner.supervisor.command.ActivateDataCenter; import org.opendaylight.controller.eos.akka.owner.supervisor.command.DeactivateDataCenter; -import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntitiesReply; import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntitiesRequest; import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityOwnerReply; import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityOwnerRequest; @@ -53,6 +52,8 @@ import org.opendaylight.controller.eos.akka.registry.listener.type.command.Regis import org.opendaylight.controller.eos.akka.registry.listener.type.command.TypeListenerRegistryCommand; import org.opendaylight.controller.eos.akka.registry.listener.type.command.UnregisterListener; import org.opendaylight.mdsal.binding.api.RpcProviderService; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException; import org.opendaylight.mdsal.eos.common.api.EntityOwnershipState; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; @@ -105,10 +106,12 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da private final ActorRef ownerStateChecker; protected final ActorRef ownerSupervisor; + private final BindingInstanceIdentifierCodec iidCodec; + private Registration reg; @VisibleForTesting - protected AkkaEntityOwnershipService(final ActorSystem actorSystem) + protected AkkaEntityOwnershipService(final ActorSystem actorSystem, final BindingCodecTree codecTree) throws ExecutionException, InterruptedException { final var typedActorSystem = Adapter.toTyped(actorSystem); scheduler = typedActorSystem.scheduler(); @@ -121,7 +124,9 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da .findFirst() .orElseThrow(() -> new IllegalArgumentException("No valid role found.")); - bootstrap = Adapter.spawn(actorSystem, Behaviors.setup(context -> EOSMain.create()), "EOSBootstrap"); + iidCodec = codecTree.getInstanceIdentifierCodec(); + bootstrap = Adapter.spawn(actorSystem, Behaviors.setup( + context -> EOSMain.create(iidCodec)), "EOSBootstrap"); final CompletionStage ask = AskPattern.ask(bootstrap, GetRunningContext::new, Duration.ofSeconds(5), scheduler); @@ -136,8 +141,9 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da @Inject @Activate public AkkaEntityOwnershipService(@Reference final ActorSystemProvider actorProvider, - @Reference final RpcProviderService rpcProvider) throws ExecutionException, InterruptedException { - this(actorProvider.getActorSystem()); + @Reference final RpcProviderService rpcProvider, @Reference final BindingCodecTree codecTree) + throws ExecutionException, InterruptedException { + this(actorProvider.getActorSystem(), codecTree); reg = rpcProvider.registerRpcImplementation(OdlEntityOwnersService.class, this); } @@ -219,7 +225,7 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da @Override public ListenableFuture> getEntities(final GetEntitiesInput input) { return toRpcFuture(AskPattern.ask(ownerSupervisor, GetEntitiesRequest::new, QUERY_TIMEOUT, scheduler), - GetEntitiesReply::toOutput); + reply -> reply.toOutput(iidCodec)); } @Override diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/bootstrap/EOSMain.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/bootstrap/EOSMain.java index 4fba4befb9..c0ffa29350 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/bootstrap/EOSMain.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/bootstrap/EOSMain.java @@ -28,6 +28,7 @@ import org.opendaylight.controller.eos.akka.registry.candidate.CandidateRegistry import org.opendaylight.controller.eos.akka.registry.candidate.command.CandidateRegistryCommand; import org.opendaylight.controller.eos.akka.registry.listener.type.EntityTypeListenerRegistry; import org.opendaylight.controller.eos.akka.registry.listener.type.command.TypeListenerRegistryCommand; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.yangtools.yang.common.Empty; public final class EOSMain extends AbstractBehavior { @@ -36,7 +37,7 @@ public final class EOSMain extends AbstractBehavior { private final ActorRef ownerSupervisor; private final ActorRef ownerStateChecker; - private EOSMain(final ActorContext context) { + private EOSMain(final ActorContext context, final BindingInstanceIdentifierCodec iidCodec) { super(context); final String role = Cluster.get(context.getSystem()).selfMember().getRoles().iterator().next(); @@ -47,11 +48,12 @@ public final class EOSMain extends AbstractBehavior { final ClusterSingleton clusterSingleton = ClusterSingleton.get(context.getSystem()); // start the initial sync behavior that switches to the regular one after syncing - ownerSupervisor = clusterSingleton.init(SingletonActor.of(IdleSupervisor.create(), "OwnerSupervisor")); + ownerSupervisor = clusterSingleton.init( + SingletonActor.of(IdleSupervisor.create(iidCodec), "OwnerSupervisor")); } - public static Behavior create() { - return Behaviors.setup(EOSMain::new); + public static Behavior create(final BindingInstanceIdentifierCodec iidCodec) { + return Behaviors.setup(context -> new EOSMain(context, iidCodec)); } @Override diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/IdleSupervisor.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/IdleSupervisor.java index 1abf6d6f12..7dcfb51218 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/IdleSupervisor.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/IdleSupervisor.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.eos.akka.owner.supervisor; +import static java.util.Objects.requireNonNull; + import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; import akka.actor.typed.javadsl.ActorContext; @@ -16,6 +18,7 @@ import akka.cluster.Member; import akka.cluster.typed.Cluster; import org.opendaylight.controller.eos.akka.owner.supervisor.command.ActivateDataCenter; import org.opendaylight.controller.eos.akka.owner.supervisor.command.OwnerSupervisorCommand; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,8 +33,12 @@ public final class IdleSupervisor extends AbstractBehavior context) { + private final BindingInstanceIdentifierCodec iidCodec; + + private IdleSupervisor(final ActorContext context, + final BindingInstanceIdentifierCodec iidCodec) { super(context); + this.iidCodec = requireNonNull(iidCodec); final Cluster cluster = Cluster.get(context.getSystem()); final String datacenterRole = extractDatacenterRole(cluster.selfMember()); @@ -43,9 +50,9 @@ public final class IdleSupervisor extends AbstractBehavior create() { + public static Behavior create(final BindingInstanceIdentifierCodec iidCodec) { - return Behaviors.setup(IdleSupervisor::new); + return Behaviors.setup(context -> new IdleSupervisor(context, iidCodec)); } @Override @@ -57,7 +64,7 @@ public final class IdleSupervisor extends AbstractBehavior onActivateDataCenter(final ActivateDataCenter message) { LOG.debug("Received ActivateDataCenter command switching to syncer behavior,"); - return OwnerSyncer.create(message.getReplyTo()); + return OwnerSyncer.create(message.getReplyTo(), iidCodec); } private String extractDatacenterRole(final Member selfMember) { diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisor.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisor.java index e56ed59f3c..f66f25aa82 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisor.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisor.java @@ -7,6 +7,9 @@ */ package org.opendaylight.controller.eos.akka.owner.supervisor; +import static com.google.common.base.Verify.verifyNotNull; +import static java.util.Objects.requireNonNull; + import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; @@ -58,6 +61,7 @@ import org.opendaylight.controller.eos.akka.owner.supervisor.command.MemberUpEve import org.opendaylight.controller.eos.akka.owner.supervisor.command.OwnerChanged; import org.opendaylight.controller.eos.akka.owner.supervisor.command.OwnerSupervisorCommand; import org.opendaylight.controller.eos.akka.registry.candidate.CandidateRegistry; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,10 +101,14 @@ public final class OwnerSupervisor extends AbstractBehavior reassignPredicate = (entity, candidate) -> !isActiveCandidate(candidate) || !isCandidateFor(entity, candidate); + private final BindingInstanceIdentifierCodec iidCodec; + private OwnerSupervisor(final ActorContext context, final Map> currentCandidates, - final Map currentOwners) { + final Map currentOwners, + final BindingInstanceIdentifierCodec iidCodec) { super(context); + this.iidCodec = requireNonNull(iidCodec); final DistributedData distributedData = DistributedData.get(context.getSystem()); final ActorRef replicator = distributedData.replicator(); @@ -150,8 +158,8 @@ public final class OwnerSupervisor extends AbstractBehavior create(final Map> currentCandidates, - final Map currentOwners) { - return Behaviors.setup(ctx -> new OwnerSupervisor(ctx, currentCandidates, currentOwners)); + final Map currentOwners, final BindingInstanceIdentifierCodec iidCodec) { + return Behaviors.setup(ctx -> new OwnerSupervisor(ctx, currentCandidates, currentOwners, iidCodec)); } @Override @@ -173,7 +181,7 @@ public final class OwnerSupervisor extends AbstractBehavior onDeactivateDatacenter(final DeactivateDataCenter command) { LOG.debug("Deactivating Owner Supervisor on {}", cluster.selfMember()); command.getReplyTo().tell(DataCenterDeactivated.INSTANCE); - return IdleSupervisor.create(); + return IdleSupervisor.create(iidCodec); } private Behavior onOwnerChanged(final OwnerChanged command) { @@ -431,8 +439,14 @@ public final class OwnerSupervisor extends AbstractBehavior request) { - return new DOMEntity(request.getType().getValue(), request.getName().getValue()); + private DOMEntity extractEntity(final AbstractEntityRequest request) { + final var name = request.getName(); + final var iid = name.getInstanceIdentifier(); + if (iid != null) { + return new DOMEntity(request.getType().getValue(), iidCodec.fromBinding(iid)); + } + final var str = verifyNotNull(name.getString(), "Unhandled entity name %s", name); + return new DOMEntity(request.getType().getValue(), str); } private static String extractRole(final Member member) { diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSyncer.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSyncer.java index a73a5620b3..04d27ee4dc 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSyncer.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSyncer.java @@ -7,6 +7,8 @@ */ package org.opendaylight.controller.eos.akka.owner.supervisor; +import static java.util.Objects.requireNonNull; + import akka.actor.typed.ActorRef; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.AbstractBehavior; @@ -32,6 +34,7 @@ import org.opendaylight.controller.eos.akka.owner.supervisor.command.InitialOwne import org.opendaylight.controller.eos.akka.owner.supervisor.command.OwnerSupervisorCommand; import org.opendaylight.controller.eos.akka.owner.supervisor.command.OwnerSupervisorReply; import org.opendaylight.controller.eos.akka.registry.candidate.CandidateRegistry; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,17 +52,20 @@ public final class OwnerSyncer extends AbstractBehavior // String representation of Entity to DOMEntity private final Map entityLookup = new HashMap<>(); + private final BindingInstanceIdentifierCodec iidCodec; private int toSync = -1; private OwnerSyncer(final ActorContext context, - @Nullable final ActorRef notifyDatacenterStarted) { + final @Nullable ActorRef notifyDatacenterStarted, + final BindingInstanceIdentifierCodec iidCodec) { super(context); + this.iidCodec = requireNonNull(iidCodec); LOG.debug("Starting candidate and owner sync"); final ActorRef replicator = DistributedData.get(context.getSystem()).replicator(); - this.ownerReplicator = new ReplicatorMessageAdapter<>(context, replicator, Duration.ofSeconds(5)); + ownerReplicator = new ReplicatorMessageAdapter<>(context, replicator, Duration.ofSeconds(5)); new ReplicatorMessageAdapter>>(context, replicator, Duration.ofSeconds(5)).askGet( @@ -71,9 +77,9 @@ public final class OwnerSyncer extends AbstractBehavior } } - public static Behavior create( - final ActorRef notifyDatacenterStarted) { - return Behaviors.setup(ctx -> new OwnerSyncer(ctx, notifyDatacenterStarted)); + public static Behavior create(final ActorRef notifyDatacenterStarted, + final BindingInstanceIdentifierCodec iidCodec) { + return Behaviors.setup(ctx -> new OwnerSyncer(ctx, notifyDatacenterStarted, iidCodec)); } @Override @@ -142,8 +148,7 @@ public final class OwnerSyncer extends AbstractBehavior private Behavior switchToSupervisor() { LOG.debug("Initial sync done, switching to supervisor. candidates: {}, owners: {}", currentCandidates, currentOwners); - return Behaviors.setup(ctx -> - OwnerSupervisor.create(currentCandidates, currentOwners)); + return Behaviors.setup(ctx -> OwnerSupervisor.create(currentCandidates, currentOwners, iidCodec)); } private void handleOwnerRsp(final Replicator.GetSuccess> rsp) { diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesReply.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesReply.java index ea8a5a8cc1..1cfa31ab00 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesReply.java +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesReply.java @@ -20,6 +20,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingInstanceIdentifierCodec; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityType; @@ -27,6 +28,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntitiesOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.NodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.get.entities.output.EntitiesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.core.general.entity.rev150930.Entity; import org.opendaylight.yangtools.yang.binding.util.BindingMap; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; @@ -46,7 +48,7 @@ public final class GetEntitiesReply extends OwnerSupervisorReply implements Seri this.owners = ImmutableMap.copyOf(owners); } - public @NonNull GetEntitiesOutput toOutput() { + public @NonNull GetEntitiesOutput toOutput(final BindingInstanceIdentifierCodec iidCodec) { final Set entities = new HashSet<>(); entities.addAll(owners.keySet()); entities.addAll(candidates.keySet()); @@ -56,7 +58,7 @@ public final class GetEntitiesReply extends OwnerSupervisorReply implements Seri .map(entity -> { final EntitiesBuilder eb = new EntitiesBuilder() .setType(new EntityType(entity.getType())) - .setName(extractName(entity)) + .setName(extractName(entity, iidCodec)) .setCandidateNodes(candidates.get(entity).stream() .map(NodeName::new).collect(Collectors.toUnmodifiableList())); @@ -70,8 +72,21 @@ public final class GetEntitiesReply extends OwnerSupervisorReply implements Seri .build(); } - private static EntityName extractName(final DOMEntity entity) { - final PathArgument last = entity.getIdentifier().getLastPathArgument(); + /** + * if the entity is general entity then shorthand the name to only the last path argument, otherwise return + * full YIID path encoded as string. + * + * @param entity Entity to extract the name from + * @param iidCodec codec to encode entity name back to InstanceIdentifier if needed + * @return Extracted name + */ + private static EntityName extractName(final DOMEntity entity, final BindingInstanceIdentifierCodec iidCodec) { + final var id = entity.getIdentifier(); + if (id.isEmpty() || !id.getPathArguments().get(0).getNodeType().equals(Entity.QNAME)) { + return new EntityName(iidCodec.toBinding(id)); + } + + final PathArgument last = id.getLastPathArgument(); verify(last instanceof NodeIdentifierWithPredicates, "Unexpected last argument %s", last); final Object value = Iterables.getOnlyElement(((NodeIdentifierWithPredicates) last).values()); verify(value instanceof String, "Unexpected predicate value %s", value); diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/entity/owners/norev/EntityNameBuilder.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/entity/owners/norev/EntityNameBuilder.java new file mode 100644 index 0000000000..f67d2ccd16 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/entity/owners/norev/EntityNameBuilder.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev; + +public final class EntityNameBuilder { + private EntityNameBuilder() { + // Hidden on purpose + } + + public static EntityName getDefaultInstance(final String defaultValue) { + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/yang/odl-akka-eos.yang b/opendaylight/md-sal/eos-dom-akka/src/main/yang/odl-akka-eos.yang index b4f16b9469..1aa2d41bbc 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/main/yang/odl-akka-eos.yang +++ b/opendaylight/md-sal/eos-dom-akka/src/main/yang/odl-akka-eos.yang @@ -19,8 +19,11 @@ module odl-entity-owners { } typedef entity-name { - type string { - length 1..max; + type union { + type instance-identifier; + type string { + length 1..max; + } } } diff --git a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AbstractNativeEosTest.java b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AbstractNativeEosTest.java index 5af0e2afdb..365ef85676 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AbstractNativeEosTest.java +++ b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AbstractNativeEosTest.java @@ -49,6 +49,10 @@ import org.opendaylight.controller.eos.akka.registry.candidate.command.RegisterC import org.opendaylight.controller.eos.akka.registry.candidate.command.UnregisterCandidate; import org.opendaylight.controller.eos.akka.registry.listener.type.command.RegisterListener; import org.opendaylight.controller.eos.akka.registry.listener.type.command.TypeListenerRegistryCommand; +import org.opendaylight.mdsal.binding.dom.codec.impl.BindingCodecContext; +import org.opendaylight.mdsal.binding.generator.impl.DefaultBindingRuntimeGenerator; +import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeGenerator; +import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipChange; import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipListener; @@ -77,6 +81,11 @@ public abstract class AbstractNativeEosTest { "akka://ClusterSystem@127.0.0.1:2552", "akka://ClusterSystem@127.0.0.1:2553"); + private static final BindingRuntimeGenerator BINDING_RUNTIME_GENERATOR = new DefaultBindingRuntimeGenerator(); + + protected static BindingCodecContext CODEC_CONTEXT + = new BindingCodecContext(BindingRuntimeHelpers.createRuntimeContext()); + private static final String REMOTE_PROTOCOL = "akka"; private static final String PORT_PARAM = "akka.remote.artery.canonical.port"; private static final String ROLE_PARAM = "akka.cluster.roles"; @@ -168,7 +177,7 @@ public abstract class AbstractNativeEosTest { // Create a classic Akka system since thats what we will have in osgi final akka.actor.ActorSystem system = akka.actor.ActorSystem.create("ClusterSystem", config); final ActorRef eosBootstrap = - Adapter.spawn(system, EOSMain.create(), "EOSBootstrap"); + Adapter.spawn(system, EOSMain.create(CODEC_CONTEXT.getInstanceIdentifierCodec()), "EOSBootstrap"); final CompletionStage ask = AskPattern.ask(eosBootstrap, GetRunningContext::new, @@ -181,7 +190,7 @@ public abstract class AbstractNativeEosTest { } private static Behavior rootBehavior() { - return Behaviors.setup(context -> EOSMain.create()); + return Behaviors.setup(context -> EOSMain.create(CODEC_CONTEXT.getInstanceIdentifierCodec())); } protected static void registerCandidates(final ClusterNode node, final DOMEntity entity, final String... members) { @@ -388,7 +397,7 @@ public abstract class AbstractNativeEosTest { protected MockNativeEntityOwnershipService(ActorSystem classicActorSystem) throws ExecutionException, InterruptedException { - super(classicActorSystem); + super(classicActorSystem, CODEC_CONTEXT); this.classicActorSystem = classicActorSystem; } diff --git a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipServiceTest.java b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipServiceTest.java index cf456fec75..b707b84f2e 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipServiceTest.java +++ b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/AkkaEntityOwnershipServiceTest.java @@ -11,6 +11,7 @@ import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -42,14 +43,23 @@ import org.opendaylight.mdsal.eos.dom.api.DOMEntity; import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipCandidateRegistration; import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipListenerRegistration; import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOutput; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; public class AkkaEntityOwnershipServiceTest extends AbstractNativeEosTest { static final String ENTITY_TYPE = "test"; static final String ENTITY_TYPE2 = "test2"; static final QName QNAME = QName.create("test", "2015-08-11", "foo"); - static int ID_COUNTER = 1; private ActorSystem system; private akka.actor.typed.ActorSystem typedSystem; @@ -62,7 +72,7 @@ public class AkkaEntityOwnershipServiceTest extends AbstractNativeEosTest { typedSystem = Adapter.toTyped(this.system); replicator = DistributedData.get(typedSystem).replicator(); - service = new AkkaEntityOwnershipService(system); + service = new AkkaEntityOwnershipService(system, CODEC_CONTEXT); } @After @@ -175,6 +185,44 @@ public class AkkaEntityOwnershipServiceTest extends AbstractNativeEosTest { assertTrue(service.isCandidateRegistered(test)); } + @Test + public void testEntityRetrievalWithYiid() throws Exception { + final YangInstanceIdentifier entityId = YangInstanceIdentifier.create(new NodeIdentifier(NetworkTopology.QNAME), + new NodeIdentifier(Topology.QNAME), + NodeIdentifierWithPredicates.of(Topology.QNAME, QName.create(Topology.QNAME, "topology-id"), "test"), + new NodeIdentifier(Node.QNAME), + NodeIdentifierWithPredicates.of(Node.QNAME, QName.create(Node.QNAME, "node-id"), "test://test-node")); + + final DOMEntity entity = new DOMEntity(ENTITY_TYPE, entityId); + + final DOMEntityOwnershipCandidateRegistration reg = service.registerCandidate(entity); + + verifyEntityOwnershipCandidateRegistration(entity, reg); + verifyEntityCandidateRegistered(ENTITY_TYPE, entityId, "member-1"); + + RpcResult getEntityResult = service.getEntity(new GetEntityInputBuilder() + .setName(new EntityName(CODEC_CONTEXT.fromYangInstanceIdentifier(entityId))) + .setType(new EntityType(ENTITY_TYPE)) + .build()) + .get(); + + assertEquals(getEntityResult.getResult().getOwnerNode().getValue(), "member-1"); + assertEquals(getEntityResult.getResult().getCandidateNodes().get(0).getValue(), "member-1"); + + // we should not be able to retrieve the entity when using string + final String entityPathEncoded = + "/network-topology:network-topology/topology[topology-id='test']/node[node-id='test://test-node']"; + + getEntityResult = service.getEntity(new GetEntityInputBuilder() + .setName(new EntityName(entityPathEncoded)) + .setType(new EntityType(ENTITY_TYPE)) + .build()) + .get(); + + assertNull(getEntityResult.getResult().getOwnerNode()); + assertTrue(getEntityResult.getResult().getCandidateNodes().isEmpty()); + } + private static void verifyGetOwnershipState(final DOMEntityOwnershipService service, final DOMEntity entity, final EntityOwnershipState expState) { await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> { diff --git a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisorTest.java b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisorTest.java index 8a088e3fdb..b396053e29 100644 --- a/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisorTest.java +++ b/opendaylight/md-sal/eos-dom-akka/src/test/java/org/opendaylight/controller/eos/akka/owner/supervisor/OwnerSupervisorTest.java @@ -139,7 +139,7 @@ public class OwnerSupervisorTest extends AbstractNativeEosTest { } private Behavior switchToSupervisor(final InitialCandidateSync message) { - return OwnerSupervisor.create(currentCandidates, currentOwners); + return OwnerSupervisor.create(currentCandidates, currentOwners, CODEC_CONTEXT.getInstanceIdentifierCodec()); } } -- 2.36.6