Small fix to xsql dependencies
[controller.git] / opendaylight / md-sal / forwardingrules-manager / src / main / java / org / opendaylight / controller / frm / reconil / FlowNodeReconcilListener.java
1 /**
2  * Copyright (c) 2014 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.controller.frm.reconil;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import java.util.Set;
18 import java.util.concurrent.ExecutionException;
19 import org.opendaylight.controller.frm.AbstractChangeListener;
20 import org.opendaylight.controller.frm.FlowCookieProducer;
21 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupRef;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.AddMeterInputBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.MeterRef;
39 import org.opendaylight.yangtools.yang.binding.DataObject;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * forwardingrules-manager
46  * org.opendaylight.controller.frm
47  *
48  * FlowNode Reconciliation Listener
49  * Reconciliation for a new FlowNode
50  * Remove CookieMapKey for removed FlowNode
51  *
52  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
53  *
54  * Created: Jun 13, 2014
55  */
56 public class FlowNodeReconcilListener extends AbstractChangeListener {
57
58     private static final Logger LOG = LoggerFactory.getLogger(FlowNodeReconcilListener.class);
59
60     private final FlowNodeReconcilProvider provider;
61
62     public FlowNodeReconcilListener(final FlowNodeReconcilProvider provider) {
63         this.provider = Preconditions.checkNotNull(provider, "Flow Node Reconcil Provider can not be null!");
64     }
65
66     @Override
67     public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
68         /* FlowCapableNode DataObjects for reconciliation */
69         final Set<Entry<InstanceIdentifier<? extends DataObject>, DataObject>> createdEntries =
70                 changeEvent.getCreatedData().entrySet();
71         /* FlowCapableNode DataObjects for clean FlowCookieHolder */
72         final Set<InstanceIdentifier<? extends DataObject>> removeEntriesInstanceIdentifiers =
73                 changeEvent.getRemovedPaths();
74         for (final Entry<InstanceIdentifier<? extends DataObject>, DataObject> createdEntry : createdEntries) {
75             InstanceIdentifier<? extends DataObject> entryKey = createdEntry.getKey();
76             DataObject entryValue = createdEntry.getValue();
77             if (preconditionForChange(entryKey, entryValue, null)) {
78                 this.add(entryKey, entryValue);
79             }
80         }
81         for (final InstanceIdentifier<?> instanceId : removeEntriesInstanceIdentifiers) {
82             Map<InstanceIdentifier<? extends DataObject>, DataObject> origConfigData =
83                     changeEvent.getOriginalData();
84             final DataObject removeValue = origConfigData.get(instanceId);
85             if (preconditionForChange(instanceId, removeValue, null)) {
86                 this.remove(instanceId, removeValue);
87             }
88         }
89     }
90
91     @Override
92     /* Cleaning FlowCookieManager holder for all node tables */
93     protected void remove(final InstanceIdentifier<? extends DataObject> identifier,
94                           final DataObject removeDataObj) {
95
96         final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
97                 identifier.firstIdentifierOf(FlowCapableNode.class);
98         final FlowCapableNode flowNode = ((FlowCapableNode) removeDataObj);
99
100         for (Table flowTable : flowNode.getTable()) {
101             final InstanceIdentifier<Table> tableIdent =
102                     flowNodeIdent.child(Table.class, flowTable.getKey());
103             FlowCookieProducer.INSTANCE.clean(tableIdent);
104         }
105     }
106
107     @Override
108     /* Reconciliation by connect new FlowCapableNode */
109     protected void add(final InstanceIdentifier<? extends DataObject> identifier,
110                        final DataObject addDataObj) {
111
112         final InstanceIdentifier<FlowCapableNode> flowNodeIdent =
113                 identifier.firstIdentifierOf(FlowCapableNode.class);
114         final Optional<FlowCapableNode> flowCapNode = this.readFlowCapableNode(flowNodeIdent);
115
116         if (flowCapNode.isPresent()) {
117             final InstanceIdentifier<Node> nodeIdent = identifier.firstIdentifierOf(Node.class);
118             final NodeRef nodeRef = new NodeRef(nodeIdent);
119             /* Groups - have to be first */
120             List<Group> groups = flowCapNode.get().getGroup();
121             if(groups != null) {
122                 for (Group group : groups) {
123                     final GroupRef groupRef = new GroupRef(flowNodeIdent.child(Group.class, group.getKey()));
124                     final AddGroupInputBuilder groupBuilder = new AddGroupInputBuilder(group);
125                     groupBuilder.setGroupRef(groupRef);
126                     groupBuilder.setNode(nodeRef);
127                     this.provider.getSalGroupService().addGroup(groupBuilder.build());
128                 }
129             }
130             /* Meters */
131             List<Meter> meters = flowCapNode.get().getMeter();
132             if(meters != null) {
133                 for (Meter meter : meters) {
134                     final MeterRef meterRef = new MeterRef(flowNodeIdent.child(Meter.class, meter.getKey()));
135                     final AddMeterInputBuilder meterBuilder = new AddMeterInputBuilder(meter);
136                     meterBuilder.setMeterRef(meterRef);
137                     meterBuilder.setNode(nodeRef);
138                     this.provider.getSalMeterService().addMeter(meterBuilder.build());
139                 }
140             }
141             /* Flows */
142             List<Table> tables = flowCapNode.get().getTable();
143             if(tables != null) {
144                 for (Table flowTable : tables) {
145                     final InstanceIdentifier<Table> tableIdent = flowNodeIdent.child(Table.class, flowTable.getKey());
146                     List<Flow> flows = flowTable.getFlow();
147                     if(flows != null) {
148                         for (Flow flow : flows) {
149                             final FlowCookie flowCookie = new FlowCookie(FlowCookieProducer.INSTANCE.getNewCookie(tableIdent));
150                             final FlowRef flowRef = new FlowRef(tableIdent.child(Flow.class, flow.getKey()));
151                             final FlowTableRef flowTableRef = new FlowTableRef(tableIdent);
152                             final AddFlowInputBuilder flowBuilder = new AddFlowInputBuilder(flow);
153                             flowBuilder.setCookie(flowCookie);
154                             flowBuilder.setNode(nodeRef);
155                             flowBuilder.setFlowTable(flowTableRef);
156                             flowBuilder.setFlowRef(flowRef);
157                             this.provider.getSalFlowService().addFlow(flowBuilder.build());
158                         }
159                     }
160                 }
161             }
162         }
163     }
164
165     @Override
166     protected void update(final InstanceIdentifier<? extends DataObject> identifier,
167                           final DataObject original, final DataObject update) {
168         // NOOP - Listener is registered for DataChangeScope.BASE only
169     }
170
171     @Override
172     protected boolean preconditionForChange(final InstanceIdentifier<? extends DataObject> identifier,
173                                             final DataObject dataObj, final DataObject update) {
174         return (dataObj instanceof FlowCapableNode);
175     }
176
177     private Optional<FlowCapableNode> readFlowCapableNode(final InstanceIdentifier<FlowCapableNode> flowNodeIdent) {
178         ReadOnlyTransaction readTrans = this.provider.getDataService().newReadOnlyTransaction();
179         try {
180             ListenableFuture<Optional<FlowCapableNode>> confFlowNode =
181                     readTrans.read(LogicalDatastoreType.CONFIGURATION, flowNodeIdent);
182             if (confFlowNode.get().isPresent()) {
183                 return Optional.<FlowCapableNode> of(confFlowNode.get().get());
184             } else {
185                 return Optional.absent();
186             }
187         }
188         catch (InterruptedException | ExecutionException e) {
189             LOG.error("Unexpected exception by reading flow ".concat(flowNodeIdent.toString()), e);
190             return Optional.absent();
191         }
192         finally {
193             readTrans.close();
194         }
195     }
196 }