From: Robert Varga Date: Mon, 9 Aug 2021 16:00:28 +0000 (+0200) Subject: Expose entity details in MDSAL X-Git-Tag: v4.0.2~2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=fd7bc3ff484b7b0bd72d425d59883f710e397c3f;hp=5b97f0fb5068bb3eb9b77b4509164707c5f35cd6 Expose entity details in MDSAL Our previous implementation was very open about it state, which was completely visible through RESTCONF (and from datastore). We have a number of tools which need information relating to where each entity lives -- and to that effect we want to expose a read-only API. This patch instroduces odl-akka-eos model, which exposes a few RPCs, which in turn provide information formerly visible from the datastore. JIRA: CONTROLLER-1992 Change-Id: I85da8941f84ca9e109c4dec61fb07a697e937639 Signed-off-by: Robert Varga --- diff --git a/opendaylight/md-sal/eos-dom-akka/pom.xml b/opendaylight/md-sal/eos-dom-akka/pom.xml index a6e68e8a25..7eda688b5f 100644 --- a/opendaylight/md-sal/eos-dom-akka/pom.xml +++ b/opendaylight/md-sal/eos-dom-akka/pom.xml @@ -13,9 +13,9 @@ 4.0.0 org.opendaylight.controller - bundle-parent + mdsal-parent 4.0.2-SNAPSHOT - ../../../bundle-parent + ../bundle-parent eos-dom-akka @@ -46,6 +46,10 @@ org.opendaylight.mdsal mdsal-eos-dom-api + + org.opendaylight.mdsal + mdsal-binding-api + org.opendaylight.yangtools concepts 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 fdb8a4d02f..ce60f6f83d 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 @@ -23,6 +23,7 @@ import java.util.Set; import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; +import java.util.function.Function; import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Singleton; @@ -37,13 +38,21 @@ 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; +import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityReply; +import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityRequest; 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.command.CandidateRegistryCommand; import org.opendaylight.controller.eos.akka.registry.candidate.command.RegisterCandidate; 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.controller.eos.akka.registry.listener.type.command.UnregisterListener; +import org.opendaylight.mdsal.binding.api.RpcProviderService; import org.opendaylight.mdsal.eos.common.api.CandidateAlreadyRegisteredException; import org.opendaylight.mdsal.eos.common.api.EntityOwnershipState; import org.opendaylight.mdsal.eos.dom.api.DOMEntity; @@ -51,7 +60,18 @@ import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipCandidateRegistratio import org.opendaylight.mdsal.eos.dom.api.DOMEntityOwnershipListener; 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.GetEntitiesInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntitiesOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOwnerInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOwnerOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.OdlEntityOwnersService; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.RpcOutput; import org.opendaylight.yangtools.yang.common.Empty; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; @@ -66,10 +86,12 @@ import org.slf4j.LoggerFactory; */ @Singleton @Component(immediate = true, service = { DOMEntityOwnershipService.class, DataCenterControl.class }) -public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, DataCenterControl, AutoCloseable { +public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, DataCenterControl, AutoCloseable, + OdlEntityOwnersService { private static final Logger LOG = LoggerFactory.getLogger(AkkaEntityOwnershipService.class); private static final String DATACENTER_PREFIX = "dc"; private static final Duration DATACENTER_OP_TIMEOUT = Duration.ofSeconds(20); + private static final Duration QUERY_TIMEOUT = Duration.ofSeconds(10); private final Set registeredEntities = ConcurrentHashMap.newKeySet(); private final String localCandidate; @@ -83,6 +105,8 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da private final ActorRef ownerStateChecker; protected final ActorRef ownerSupervisor; + private Registration reg; + @VisibleForTesting protected AkkaEntityOwnershipService(final ActorSystem actorSystem) throws ExecutionException, InterruptedException { @@ -111,15 +135,21 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da @Inject @Activate - public AkkaEntityOwnershipService(@Reference final ActorSystemProvider provider) - throws ExecutionException, InterruptedException { - this(provider.getActorSystem()); + public AkkaEntityOwnershipService(@Reference final ActorSystemProvider actorProvider, + @Reference final RpcProviderService rpcProvider) throws ExecutionException, InterruptedException { + this(actorProvider.getActorSystem()); + + reg = rpcProvider.registerRpcImplementation(OdlEntityOwnersService.class, this); } @PreDestroy @Deactivate @Override public void close() throws InterruptedException, ExecutionException { + if (reg != null) { + reg.close(); + reg = null; + } AskPattern.ask(bootstrap, Terminate::new, Duration.ofSeconds(5), scheduler).toCompletableFuture().get(); } @@ -185,6 +215,27 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da AskPattern.ask(ownerSupervisor, DeactivateDataCenter::new, DATACENTER_OP_TIMEOUT, scheduler)); } + + @Override + public ListenableFuture> getEntities(final GetEntitiesInput input) { + return toRpcFuture(AskPattern.ask(ownerSupervisor, GetEntitiesRequest::new, QUERY_TIMEOUT, scheduler), + GetEntitiesReply::toOutput); + } + + @Override + public ListenableFuture> getEntity(final GetEntityInput input) { + return toRpcFuture(AskPattern.ask(ownerSupervisor, + (final ActorRef replyTo) -> new GetEntityRequest(replyTo, input), QUERY_TIMEOUT, scheduler), + GetEntityReply::toOutput); + } + + @Override + public ListenableFuture> getEntityOwner(final GetEntityOwnerInput input) { + return toRpcFuture(AskPattern.ask(ownerSupervisor, + (final ActorRef replyTo) -> new GetEntityOwnerRequest(replyTo, input), QUERY_TIMEOUT, + scheduler), GetEntityOwnerReply::toOutput); + } + void unregisterCandidate(final DOMEntity entity) { LOG.debug("Unregistering candidate for {}", entity); @@ -204,11 +255,25 @@ public class AkkaEntityOwnershipService implements DOMEntityOwnershipService, Da return runningContext; } + private static ListenableFuture> toRpcFuture( + final CompletionStage stage, final Function outputFunction) { + + final SettableFuture> future = SettableFuture.create(); + stage.whenComplete((reply, failure) -> { + if (failure != null) { + future.setException(failure); + } else { + future.set(RpcResultBuilder.success(outputFunction.apply(reply)).build()); + } + }); + return future; + } + private static ListenableFuture toListenableFuture(final String op, final CompletionStage stage) { final SettableFuture future = SettableFuture.create(); stage.whenComplete((reply, failure) -> { if (failure != null) { - LOG.warn("{} DataCenter has failed", op, failure); + LOG.warn("{} DataCenter failed", op, failure); future.setException(failure); } else { LOG.debug("{} DataCenter successful", op); 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 047040a65d..5210f43dc6 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 @@ -40,9 +40,16 @@ import java.util.Map; import java.util.Set; import java.util.function.BiPredicate; import java.util.stream.Collectors; +import org.opendaylight.controller.eos.akka.owner.supervisor.command.AbstractEntityRequest; import org.opendaylight.controller.eos.akka.owner.supervisor.command.CandidatesChanged; import org.opendaylight.controller.eos.akka.owner.supervisor.command.DataCenterDeactivated; 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; +import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityReply; +import org.opendaylight.controller.eos.akka.owner.supervisor.command.GetEntityRequest; import org.opendaylight.controller.eos.akka.owner.supervisor.command.MemberDownEvent; import org.opendaylight.controller.eos.akka.owner.supervisor.command.MemberReachableEvent; import org.opendaylight.controller.eos.akka.owner.supervisor.command.MemberUnreachableEvent; @@ -156,6 +163,9 @@ public final class OwnerSupervisor extends AbstractBehavior predicate) { LOG.debug("Reassigning owners for {}", entities); for (final DOMEntity entity : entities) { - - if (predicate.test(entity, oldOwner)) { ownerToEntity.remove(oldOwner, entity); assignOwnerFor(entity); @@ -356,6 +364,22 @@ public final class OwnerSupervisor extends AbstractBehavior onGetEntities(final GetEntitiesRequest request) { + request.getReplyTo().tell(new GetEntitiesReply(currentOwners, currentCandidates)); + return this; + } + + private Behavior onGetEntity(final GetEntityRequest request) { + final DOMEntity entity = extractEntity(request); + request.getReplyTo().tell(new GetEntityReply(currentOwners.get(entity), currentCandidates.get(entity))); + return this; + } + + private Behavior onGetEntityOwner(final GetEntityOwnerRequest request) { + request.getReplyTo().tell(new GetEntityOwnerReply(currentOwners.get(extractEntity(request)))); + return this; + } + private void handleReachableEvent(final Set roles) { if (roles.contains(dataCenter)) { activeMembers.add(extractRole(roles)); @@ -406,6 +430,10 @@ public final class OwnerSupervisor extends AbstractBehavior request) { + return new DOMEntity(request.getType().getValue(), request.getName().getValue()); + } + private static String extractRole(final Member member) { return extractRole(member.getRoles()); } diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/AbstractEntityRequest.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/AbstractEntityRequest.java new file mode 100644 index 0000000000..b3b4c8cff8 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/AbstractEntityRequest.java @@ -0,0 +1,35 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import akka.actor.typed.ActorRef; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityId; +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; + +public abstract class AbstractEntityRequest extends OwnerSupervisorRequest { + private static final long serialVersionUID = 1L; + + private final @NonNull EntityType type; + private final @NonNull EntityName name; + + AbstractEntityRequest(final ActorRef replyTo, final EntityId entity) { + super(replyTo); + this.type = entity.requireType(); + this.name = entity.requireName(); + } + + public final @NonNull EntityType getType() { + return type; + } + + public final @NonNull EntityName getName() { + return name; + } +} 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 new file mode 100644 index 0000000000..ea8a5a8cc1 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesReply.java @@ -0,0 +1,80 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import static com.google.common.base.Verify.verify; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.ImmutableSetMultimap.Builder; +import com.google.common.collect.Iterables; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNull; +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; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntitiesOutput; +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.yangtools.yang.binding.util.BindingMap; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; + +public final class GetEntitiesReply extends OwnerSupervisorReply implements Serializable { + private static final long serialVersionUID = 1L; + + private final ImmutableSetMultimap candidates; + private final ImmutableMap owners; + + public GetEntitiesReply(final Map owners, final Map> candidates) { + final Builder builder = ImmutableSetMultimap.builder(); + for (Entry> entry : candidates.entrySet()) { + builder.putAll(entry.getKey(), entry.getValue()); + } + this.candidates = builder.build(); + this.owners = ImmutableMap.copyOf(owners); + } + + public @NonNull GetEntitiesOutput toOutput() { + final Set entities = new HashSet<>(); + entities.addAll(owners.keySet()); + entities.addAll(candidates.keySet()); + + return new GetEntitiesOutputBuilder() + .setEntities(entities.stream() + .map(entity -> { + final EntitiesBuilder eb = new EntitiesBuilder() + .setType(new EntityType(entity.getType())) + .setName(extractName(entity)) + .setCandidateNodes(candidates.get(entity).stream() + .map(NodeName::new).collect(Collectors.toUnmodifiableList())); + + final String owner = owners.get(entity); + if (owner != null) { + eb.setOwnerNode(new NodeName(owner)); + } + return eb.build(); + }) + .collect(BindingMap.toMap())) + .build(); + } + + private static EntityName extractName(final DOMEntity entity) { + final PathArgument last = entity.getIdentifier().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); + return new EntityName((String) value); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesRequest.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesRequest.java new file mode 100644 index 0000000000..fdea832798 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntitiesRequest.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.controller.eos.akka.owner.supervisor.command; + +import akka.actor.typed.ActorRef; + +public final class GetEntitiesRequest extends OwnerSupervisorRequest { + private static final long serialVersionUID = 1L; + + public GetEntitiesRequest(final ActorRef replyTo) { + super(replyTo); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerReply.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerReply.java new file mode 100644 index 0000000000..282fc4140d --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerReply.java @@ -0,0 +1,33 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import java.io.Serializable; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOwnerOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOwnerOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.NodeName; + +public final class GetEntityOwnerReply extends OwnerSupervisorReply implements Serializable { + private static final long serialVersionUID = 1L; + + private final String owner; + + public GetEntityOwnerReply(final @Nullable String owner) { + this.owner = owner; + } + + public @NonNull GetEntityOwnerOutput toOutput() { + final GetEntityOwnerOutputBuilder builder = new GetEntityOwnerOutputBuilder(); + if (owner != null) { + builder.setOwnerNode(new NodeName(owner)); + } + return builder.build(); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerRequest.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerRequest.java new file mode 100644 index 0000000000..6b341d3840 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityOwnerRequest.java @@ -0,0 +1,19 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import akka.actor.typed.ActorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityId; + +public final class GetEntityOwnerRequest extends AbstractEntityRequest { + private static final long serialVersionUID = 1L; + + public GetEntityOwnerRequest(final ActorRef replyTo, final EntityId entity) { + super(replyTo, entity); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityReply.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityReply.java new file mode 100644 index 0000000000..6fae25c5af --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityReply.java @@ -0,0 +1,40 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import com.google.common.collect.ImmutableSet; +import java.io.Serializable; +import java.util.Set; +import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.GetEntityOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.NodeName; + +public final class GetEntityReply extends OwnerSupervisorReply implements Serializable { + private static final long serialVersionUID = 1L; + + private final ImmutableSet candidates; + private final String owner; + + public GetEntityReply(final @Nullable String owner, final @Nullable Set candidates) { + this.owner = owner; + this.candidates = candidates == null ? ImmutableSet.of() : ImmutableSet.copyOf(candidates); + } + + public @NonNull GetEntityOutput toOutput() { + final GetEntityOutputBuilder builder = new GetEntityOutputBuilder(); + if (owner != null) { + builder.setOwnerNode(new NodeName(owner)); + } + return builder + .setCandidateNodes(candidates.stream().map(NodeName::new).collect(Collectors.toUnmodifiableList())) + .build(); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityRequest.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityRequest.java new file mode 100644 index 0000000000..91b73c8d60 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/GetEntityRequest.java @@ -0,0 +1,19 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import akka.actor.typed.ActorRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.entity.owners.norev.EntityId; + +public final class GetEntityRequest extends AbstractEntityRequest { + private static final long serialVersionUID = 1L; + + public GetEntityRequest(final ActorRef replyTo, final EntityId entity) { + super(replyTo, entity); + } +} diff --git a/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/OwnerSupervisorRequest.java b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/OwnerSupervisorRequest.java new file mode 100644 index 0000000000..ab822a7f02 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/java/org/opendaylight/controller/eos/akka/owner/supervisor/command/OwnerSupervisorRequest.java @@ -0,0 +1,29 @@ +/* + * 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.controller.eos.akka.owner.supervisor.command; + +import static java.util.Objects.requireNonNull; + +import akka.actor.typed.ActorRef; +import java.io.Serializable; +import org.eclipse.jdt.annotation.NonNull; + +abstract class OwnerSupervisorRequest extends OwnerSupervisorCommand + implements Serializable { + private static final long serialVersionUID = 1L; + + private final @NonNull ActorRef replyTo; + + OwnerSupervisorRequest(final ActorRef replyTo) { + this.replyTo = requireNonNull(replyTo); + } + + public final @NonNull ActorRef getReplyTo() { + return replyTo; + } +} 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 new file mode 100644 index 0000000000..b4f16b9469 --- /dev/null +++ b/opendaylight/md-sal/eos-dom-akka/src/main/yang/odl-akka-eos.yang @@ -0,0 +1,93 @@ +module odl-entity-owners { + namespace urn:opendaylight:params:xml:ns:yang:controller:entity-owners; + prefix entity-owners; + + organization 'OpenDaylight Project'; + description "An initial cut at modeling entity ownership status information + in a way which is not dependent on the datastore. + + This model is considered experimental and + implementation-specific. It can change incompatibly between + OpenDaylight releases."; + + typedef entity-type { + type string { + length 1..max; + // FIXME: it would be nice to have a pattern here, or even better + // if we turn this into an extensible enum (i.e. identityref) + } + } + + typedef entity-name { + type string { + length 1..max; + } + } + + typedef node-name { + type string { + length 1..max; + } + } + + grouping entity-id { + leaf type { + type entity-type; + mandatory true; + } + leaf name { + type entity-name; + mandatory true; + } + } + + grouping owner { + leaf owner-node { + type node-name; + } + } + + grouping candidates { + leaf-list candidate-nodes { + type node-name; + ordered-by user; + min-elements 1; + } + } + + grouping details { + uses owner; + uses candidates; + } + + rpc get-entities { + output { + list entities { + key 'type name'; + uses entity-id; + uses details; + } + } + } + + rpc get-entity { + input { + uses entity-id; + } + + output { + uses details; + } + } + + rpc get-entity-owner { + input { + uses entity-id; + } + + output { + uses owner; + } + } +} +