2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.subscription;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.MoreExecutors;
15 import java.time.Instant;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.mdsal.common.api.CommitInfo;
19 import org.opendaylight.restconf.notifications.mdsal.MdsalNotificationService;
20 import org.opendaylight.restconf.notifications.mdsal.SubscriptionStateService;
21 import org.opendaylight.restconf.server.api.ServerException;
22 import org.opendaylight.restconf.server.api.ServerRequest;
23 import org.opendaylight.restconf.server.spi.OperationInput;
24 import org.opendaylight.restconf.server.spi.RpcImplementation;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.subscribed.notifications.rev190909.KillSubscription;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.subscribed.notifications.rev190909.KillSubscriptionInput;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.subscribed.notifications.rev190909.KillSubscriptionOutput;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.subscribed.notifications.rev190909.NoSuchSubscription;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.subscribed.notifications.rev190909.subscriptions.Subscription;
30 import org.opendaylight.yangtools.yang.common.ErrorTag;
31 import org.opendaylight.yangtools.yang.common.ErrorType;
32 import org.opendaylight.yangtools.yang.common.QName;
33 import org.opendaylight.yangtools.yang.common.Uint32;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
36 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
37 import org.osgi.service.component.annotations.Activate;
38 import org.osgi.service.component.annotations.Component;
39 import org.osgi.service.component.annotations.Reference;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
44 * RESTCONF implementation of {@link KillSubscription}.
47 @Component(service = RpcImplementation.class)
48 public final class KillSubscriptionRpc extends RpcImplementation {
49 private static final YangInstanceIdentifier.NodeIdentifier SUBSCRIPTION_ID =
50 YangInstanceIdentifier.NodeIdentifier.create(QName.create(KillSubscriptionInput.QNAME, "id").intern());
52 private static final Logger LOG = LoggerFactory.getLogger(KillSubscriptionRpc.class);
54 private final MdsalNotificationService mdsalService;
55 private final SubscriptionStateService subscriptionStateService;
56 private final SubscriptionStateMachine stateMachine;
60 public KillSubscriptionRpc(@Reference final MdsalNotificationService mdsalService,
61 @Reference final SubscriptionStateService subscriptionStateService,
62 @Reference final SubscriptionStateMachine stateMachine) {
63 super(KillSubscription.QNAME);
64 this.mdsalService = requireNonNull(mdsalService);
65 this.subscriptionStateService = requireNonNull(subscriptionStateService);
66 this.stateMachine = requireNonNull(stateMachine);
70 public void invoke(final ServerRequest<ContainerNode> request, final URI restconfURI, final OperationInput input) {
71 final var body = input.input();
74 id = leaf(body, SUBSCRIPTION_ID, Uint32.class);
75 } catch (IllegalArgumentException e) {
76 request.completeWith(new ServerException(ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT, e));
80 request.completeWith(new ServerException(ErrorType.APPLICATION, ErrorTag.MISSING_ELEMENT,
84 final var state = stateMachine.getSubscriptionState(id);
86 request.completeWith(new ServerException(ErrorType.APPLICATION, ErrorTag.MISSING_ELEMENT,
87 "No subscription with given ID."));
90 if (state != SubscriptionState.ACTIVE && state != SubscriptionState.SUSPENDED) {
91 request.completeWith(new ServerException(ErrorType.APPLICATION, ErrorTag.BAD_ELEMENT,
92 "There is no active or suspended subscription with given ID."));
96 mdsalService.deleteSubscription(SubscriptionUtil.SUBSCRIPTIONS.node(YangInstanceIdentifier
97 .NodeIdentifierWithPredicates.of(Subscription.QNAME, SubscriptionUtil.QNAME_ID, id)))
98 .addCallback(new FutureCallback<CommitInfo>() {
100 public void onSuccess(final CommitInfo result) {
101 request.completeWith(ImmutableNodes.newContainerBuilder()
102 .withNodeIdentifier(YangInstanceIdentifier.NodeIdentifier.create(KillSubscriptionOutput.QNAME))
104 stateMachine.moveTo(id, SubscriptionState.END);
106 subscriptionStateService.subscriptionTerminated(Instant.now(), id, NoSuchSubscription.QNAME);
107 } catch (InterruptedException e) {
108 LOG.warn("Could not send subscription terminated notification", e);
113 public void onFailure(final Throwable throwable) {
114 request.completeWith(new ServerException(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED,
115 throwable.getMessage()));
117 }, MoreExecutors.directExecutor());