Merge "BUG-4099: Groups pointing to ports"
[openflowplugin.git] / applications / forwardingrules-manager / src / main / java / org / opendaylight / openflowplugin / applications / frm / impl / ForwardingRulesManagerImpl.java
1 /**
2  * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.applications.frm.impl;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Sets;
14 import java.util.Collections;
15 import java.util.Set;
16 import java.util.concurrent.atomic.AtomicLong;
17
18 import com.google.common.util.concurrent.CheckedFuture;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
22 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
23 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
27 import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation;
28 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesCommiter;
29 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * forwardingrules-manager
47  * org.opendaylight.openflowplugin.applications.frm.impl
48  *
49  * Manager and middle point for whole module.
50  * It contains ActiveNodeHolder and provide all RPC services.
51  *
52  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
53  *
54  * Created: Aug 25, 2014
55  */
56 public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
57
58     private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
59     public static final int STARTUP_LOOP_TICK = 500;
60     public static final int STARTUP_LOOP_MAX_RETRIES = 8;
61
62     private final AtomicLong txNum = new AtomicLong();
63     private final Object lockObj = new Object();
64     private Set<InstanceIdentifier<FlowCapableNode>> activeNodes = Collections.emptySet();
65
66     private final DataBroker dataService;
67     private final SalFlowService salFlowService;
68     private final SalGroupService salGroupService;
69     private final SalMeterService salMeterService;
70     private final SalTableService salTableService;
71
72     private ForwardingRulesCommiter<Flow> flowListener;
73     private ForwardingRulesCommiter<Group> groupListener;
74     private ForwardingRulesCommiter<Meter> meterListener;
75     private ForwardingRulesCommiter<TableFeatures> tableListener;
76     private FlowNodeReconciliation nodeListener;
77
78     private final ForwardingRulesManagerConfig forwardingRulesManagerConfig;
79     private FlowNodeConnectorInventoryTranslatorImpl flowNodeConnectorInventoryTranslatorImpl;
80     private final EntityOwnershipService entityOwnershipService;
81
82     public ForwardingRulesManagerImpl(final DataBroker dataBroker,
83                                       final RpcConsumerRegistry rpcRegistry,
84                                       final ForwardingRulesManagerConfig config,
85                                       final EntityOwnershipService eos) {
86         this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
87         this.forwardingRulesManagerConfig = Preconditions.checkNotNull(config, "Configuration for FRM cannot be null");
88         this.entityOwnershipService = Preconditions.checkNotNull(eos, "EntityOwnership service can not be null");
89
90         Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
91
92         this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
93                 "RPC SalFlowService not found.");
94         this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
95                 "RPC SalGroupService not found.");
96         this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
97                 "RPC SalMeterService not found.");
98         this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
99                 "RPC SalTableService not found.");
100     }
101
102     @Override
103     public void start() {
104
105         this.flowListener = new FlowForwarder(this, dataService);
106
107         this.groupListener = new GroupForwarder(this, dataService);
108         this.meterListener = new MeterForwarder(this, dataService);
109
110         this.tableListener = new TableForwarder(this, dataService);
111         this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
112         flowNodeConnectorInventoryTranslatorImpl = 
113                             new FlowNodeConnectorInventoryTranslatorImpl(this,dataService);
114         LOG.info("ForwardingRulesManager has started successfully.");
115
116     }
117
118     @Override
119     public void close() throws Exception {
120         if (this.flowListener != null) {
121             this.flowListener.close();
122             this.flowListener = null;
123         }
124         if (this.groupListener != null) {
125             this.groupListener.close();
126             this.groupListener = null;
127         }
128         if (this.meterListener != null) {
129             this.meterListener.close();
130             this.meterListener = null;
131         }
132         if (this.tableListener != null) {
133             this.tableListener.close();
134             this.tableListener = null;
135         }
136         if (this.nodeListener != null) {
137             this.nodeListener.close();
138             this.nodeListener = null;
139         }
140     }
141
142     @Override
143     public ReadOnlyTransaction getReadTranaction() {
144         return dataService.newReadOnlyTransaction();
145     }
146
147     @Override
148     public String getNewTransactionId() {
149         return "DOM-" + txNum.getAndIncrement();
150     }
151
152     @Override
153     public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident) {
154         return activeNodes.contains(ident);
155     }
156
157     @Override
158     public boolean checkNodeInOperationalDataStore(InstanceIdentifier<FlowCapableNode> ident) {
159         boolean result = false;
160         InstanceIdentifier<Node> nodeIid = ident.firstIdentifierOf(Node.class);
161         final ReadOnlyTransaction transaction = dataService.newReadOnlyTransaction();
162         Optional<Node> optionalDataObject;
163         CheckedFuture<Optional<Node>, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid);
164         try {
165             optionalDataObject = future.checkedGet();
166             if (optionalDataObject.isPresent()) {
167                 result = true;
168             } else {
169                 LOG.debug("{}: Failed to read {}",
170                         Thread.currentThread().getStackTrace()[1], nodeIid);
171             }
172         } catch (ReadFailedException e) {
173             LOG.warn("Failed to read {} ", nodeIid, e);
174         }
175         transaction.close();
176
177         return result;
178     }
179
180     @Override
181     public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident) {
182         if (!activeNodes.contains(ident)) {
183             synchronized (lockObj) {
184                 if (!activeNodes.contains(ident)) {
185                     Set<InstanceIdentifier<FlowCapableNode>> set =
186                             Sets.newHashSet(activeNodes);
187                     set.add(ident);
188                     activeNodes = Collections.unmodifiableSet(set);
189                 }
190             }
191         }
192     }
193
194     @Override
195     public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident) {
196         if (activeNodes.contains(ident)) {
197             synchronized (lockObj) {
198                 if (activeNodes.contains(ident)) {
199                     Set<InstanceIdentifier<FlowCapableNode>> set =
200                             Sets.newHashSet(activeNodes);
201                     set.remove(ident);
202                     activeNodes = Collections.unmodifiableSet(set);
203                 }
204             }
205         }
206     }
207
208     @Override
209     public SalFlowService getSalFlowService() {
210         return salFlowService;
211     }
212
213     @Override
214     public SalGroupService getSalGroupService() {
215         return salGroupService;
216     }
217
218     @Override
219     public SalMeterService getSalMeterService() {
220         return salMeterService;
221     }
222
223     @Override
224     public SalTableService getSalTableService() {
225         return salTableService;
226     }
227
228     @Override
229     public ForwardingRulesCommiter<Flow> getFlowCommiter() {
230         return flowListener;
231     }
232
233     @Override
234     public ForwardingRulesCommiter<Group> getGroupCommiter() {
235         return groupListener;
236     }
237
238     @Override
239     public ForwardingRulesCommiter<Meter> getMeterCommiter() {
240         return meterListener;
241     }
242
243     @Override
244     public ForwardingRulesCommiter<TableFeatures> getTableFeaturesCommiter() {
245         return tableListener;
246     }
247
248     @Override
249     public FlowNodeReconciliation getFlowNodeReconciliation() {
250         return nodeListener;
251     }
252
253     @Override
254     public ForwardingRulesManagerConfig getConfiguration() {
255         return forwardingRulesManagerConfig;
256     }
257
258     @Override
259     public FlowNodeConnectorInventoryTranslatorImpl getFlowNodeConnectorInventoryTranslatorImpl() {
260         return flowNodeConnectorInventoryTranslatorImpl;
261     }
262
263     @Override
264     public boolean isNodeOwner(InstanceIdentifier<FlowCapableNode> ident) {
265         NodeId nodeId = ident.firstKeyOf(Node.class).getId();
266         Entity entity = new Entity("openflow", nodeId.getValue());
267         Optional<EntityOwnershipState> eState = this.entityOwnershipService.getOwnershipState(entity);
268         if(eState.isPresent()) {
269             return eState.get().isOwner();
270         }
271         return false;
272     }
273 }
274