2 * Copyright (c) 2016 Cisco Systems Inc 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
9 package org.opendaylight.unimgr.impl;
11 import java.util.List;
12 import java.util.Optional;
13 import java.util.concurrent.locks.ReentrantReadWriteLock;
15 import javax.annotation.Nonnull;
17 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriver;
18 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriverAmbiguousException;
19 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriverBuilder;
20 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriverNotFoundException;
21 import org.opendaylight.unimgr.mef.nrp.api.ActivationDriverRepoService;
22 import org.opendaylight.unimgr.mef.nrp.impl.ActivationTransaction;
23 import org.opendaylight.yang.gen.v1.urn.onf.core.network.module.rev160630.forwarding.constructs.ForwardingConstruct;
24 import org.opendaylight.yang.gen.v1.urn.onf.core.network.module.rev160630.g_forwardingconstruct.FcPort;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
28 import static org.opendaylight.unimgr.mef.nrp.impl.ActivationTransaction.Result;
31 * @author bartosz.michalik@amartus.com
32 * @author krzysztof.bijakowski@amartus.com [modifications]
34 public class ForwardingConstructActivatorService {
35 private static final Logger LOG = LoggerFactory.getLogger(ForwardingConstructActivatorService.class);
36 private ActivationDriverRepoService activationRepoService;
37 private final ReentrantReadWriteLock lock;
39 public ForwardingConstructActivatorService(ActivationDriverRepoService activationRepoService) {
40 this.activationRepoService = activationRepoService;
41 lock = new ReentrantReadWriteLock();
45 * Activate a MEF ForwardingConstruct.
46 * @param forwardingConstruct the new route to activate
48 public void activate(@Nonnull ForwardingConstruct forwardingConstruct, @Nonnull ForwardingConstructActivationStateTracker stateTracker) {
49 if(stateTracker.isActivatable()) {
50 Optional<ActivationTransaction> tx = prepareTransaction(forwardingConstruct);
52 Result result = tx.get().activate();
54 if(result.isSuccessful()) {
55 stateTracker.activated(forwardingConstruct);
56 LOG.info("Forwarding construct activated successfully, request = {} ", forwardingConstruct);
58 stateTracker.activationFailed(forwardingConstruct);
59 LOG.warn("Forwarding construct activation failed, reason = {}, request = {}", result.getMessage(), forwardingConstruct);
62 LOG.warn("No transaction for this activation request {}", forwardingConstruct);
63 stateTracker.activationFailed(forwardingConstruct);
69 * Deactivate a MEF ForwardingConstruct.
70 * @param forwardingConstruct the existing route to deactivate
72 public void deactivate(@Nonnull ForwardingConstruct forwardingConstruct, @Nonnull ForwardingConstructActivationStateTracker stateTracker) {
73 if(stateTracker.isDeactivatable()) {
74 Optional<ActivationTransaction> tx = prepareTransaction(forwardingConstruct);
76 Result result = tx.get().deactivate();
78 if(result.isSuccessful()) {
79 stateTracker.deactivated();
80 LOG.info("Forwarding construct deactivated successfully, request = {}", forwardingConstruct);
82 stateTracker.deactivationFailed();
83 LOG.warn("Forwarding construct deactivation failed, reason = {}, request = {}", result.getMessage(), forwardingConstruct);
86 LOG.warn("No transaction for this deactivation request {}", forwardingConstruct);
87 stateTracker.deactivationFailed();
92 private Optional<ActivationTransaction> prepareTransaction(ForwardingConstruct fwdC) {
93 final List<FcPort> list = fwdC.getFcPort();
94 //TODO validate pre-condition
95 final FcPort a = list.get(0);
96 final FcPort z = list.get(1);
98 return isTheSameNode(fwdC)
99 ? getTxForNode(a,z, fwdC) : getTxForMultiNode(a,z, fwdC);
102 private boolean isTheSameNode(ForwardingConstruct forwardingConstruct) {
103 final FcPort p1 = forwardingConstruct.getFcPort().get(0);
104 final FcPort p2 = forwardingConstruct.getFcPort().get(1);
105 return p1.getNode().equals(p2.getNode());
108 private Optional<ActivationTransaction> getTxForNode(FcPort portA, FcPort portZ, ForwardingConstruct fwdC) {
109 lock.readLock().lock();
111 final ActivationDriverBuilder.BuilderContext ctx = new ActivationDriverBuilder.BuilderContext();
112 ActivationDriver activator = activationRepoService.getDriver(portA, portZ, ctx);
114 activator.initialize(portA, portZ, fwdC);
115 ActivationTransaction tx = new ActivationTransaction();
116 tx.addDriver(activator);
117 return Optional.of(tx);
118 } catch (ActivationDriverNotFoundException e) {
119 LOG.warn("No unique activation driver found for {} <-> {}", portA, portZ);
120 return Optional.empty();
121 } catch (ActivationDriverAmbiguousException e) {
122 LOG.warn("Multiple activation driver found for {} <-> {}", portZ, portA);
123 return Optional.empty();
124 } catch (Exception e) {
125 LOG.error("driver initialization exception", e);
126 return Optional.empty();
128 lock.readLock().unlock();
132 private Optional<ActivationTransaction> getTxForMultiNode(FcPort portA, FcPort portZ, ForwardingConstruct fwdC) {
133 //1. find and initialize drivers
134 lock.readLock().lock();
137 final ActivationDriverBuilder.BuilderContext ctx = new ActivationDriverBuilder.BuilderContext();
138 ctx.put(ForwardingConstruct.class.getName(), fwdC);
140 Optional<ActivationDriver> aendActivator = findDriver(portA, ctx);
141 Optional<ActivationDriver> zendActivator = findDriver(portZ, ctx);
143 if (aendActivator.isPresent() && zendActivator.isPresent()) {
144 aendActivator.get().initialize(portA, portZ, fwdC);
145 zendActivator.get().initialize(portZ, portA, fwdC);
147 final ActivationTransaction tx = new ActivationTransaction();
148 tx.addDriver(aendActivator.get());
149 tx.addDriver(zendActivator.get());
151 return Optional.of(tx);
153 // ??? TODO improve comment for better traceability
154 LOG.error("drivers for both ends needed");
155 return Optional.empty();
158 } catch (Exception e) {
159 LOG.error("driver initialization exception",e);
160 return Optional.empty();
162 lock.readLock().unlock();
166 protected Optional<ActivationDriver> findDriver(FcPort port, ActivationDriverBuilder.BuilderContext fwdC) {
167 if (activationRepoService == null) {
168 LOG.warn("Activation Driver repo is not initialized");
169 return Optional.empty();
172 return Optional.ofNullable(activationRepoService.getDriver(port, fwdC));
173 } catch (ActivationDriverNotFoundException e) {
174 LOG.warn("No activation driver found for {}", port);
175 return Optional.empty();
176 } catch (ActivationDriverAmbiguousException e) {
177 LOG.warn("Multiple activation driver found for {}", port);
178 return Optional.empty();
185 * Set the activation driver repository service.
186 * @param activationRepoService service to use
188 public void setActivationRepoService(ActivationDriverRepoService activationRepoService) {
189 lock.writeLock().lock();
190 this.activationRepoService = activationRepoService;
191 lock.writeLock().unlock();
195 * Unset the activation driver repository service.
197 public void unsetActivationRepoService() {
198 lock.writeLock().lock();
199 this.activationRepoService = null;
200 lock.writeLock().unlock();
203 static final class Context {
206 final ForwardingConstruct fwC;
208 public Context(FcPort portA, FcPort portZ, ForwardingConstruct fwC) {