Add a flow by adding the flow data into the datastore
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / FlowProgrammerAdapter.xtend
1 package org.opendaylight.controller.sal.compatibility
2
3 import java.util.concurrent.ExecutionException
4 import org.opendaylight.controller.sal.core.Node
5 import org.opendaylight.controller.sal.flowprogrammer.Flow
6 import org.opendaylight.controller.sal.flowprogrammer.IPluginInFlowProgrammerService
7 import org.opendaylight.controller.sal.flowprogrammer.IPluginOutFlowProgrammerService
8 import org.opendaylight.controller.sal.utils.Status
9 import org.opendaylight.controller.sal.utils.StatusCode
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved
13 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification
18 import org.opendaylight.yangtools.yang.common.RpcResult
19 import org.slf4j.LoggerFactory
20
21 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService
22 import org.opendaylight.controller.md.sal.common.api.TransactionStatus
23 import org.opendaylight.controller.md.sal.common.api.data.DataModification
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.tables.Table
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
30 import org.opendaylight.yangtools.yang.binding.DataObject
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId
36
37
38 import static org.opendaylight.controller.sal.compatibility.MDFlowMapping.*
39
40 import static extension org.opendaylight.controller.sal.compatibility.NodeMapping.*
41 import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*
42
43 class FlowProgrammerAdapter implements IPluginInFlowProgrammerService, SalFlowListener {
44
45     private static val LOG = LoggerFactory.getLogger(FlowProgrammerAdapter);
46
47     @Property
48     private SalFlowService delegate;
49
50     @Property
51     private DataBrokerService dataBrokerService;
52     
53     @Property
54     private IPluginOutFlowProgrammerService flowProgrammerPublisher;
55
56     override addFlow(Node node, Flow flow) {
57         val input = addFlowInput(node, flow);
58         writeFlow(input, new NodeKey(new NodeId(node.getNodeIDString())), new FlowKey(new FlowId(flow.getId())));
59         return toStatus(true);
60     }
61
62     override modifyFlow(Node node, Flow oldFlow, Flow newFlow) {
63         val input = updateFlowInput(node, oldFlow, newFlow);
64         val future = delegate.updateFlow(input);
65         try {
66             val result = future.get();
67             return toStatus(result);
68         } catch (Exception e) {
69             return processException(e);
70         }
71     }
72
73     override removeFlow(Node node, Flow flow) {
74         val input = removeFlowInput(node, flow);
75         val future = delegate.removeFlow(input);
76
77         try {
78             val result = future.get();
79             return toStatus(result);
80         } catch (Exception e) {
81             return processException(e);
82         }
83     }
84
85     override addFlowAsync(Node node, Flow flow, long rid) {
86         val input = addFlowInput(node, flow);
87         delegate.addFlow(input);
88         return new Status(StatusCode.SUCCESS);
89     }
90
91     override modifyFlowAsync(Node node, Flow oldFlow, Flow newFlow, long rid) {
92         val input = updateFlowInput(node, oldFlow, newFlow);
93         delegate.updateFlow(input);
94         return new Status(StatusCode.SUCCESS);
95     }
96
97     override removeFlowAsync(Node node, Flow flow, long rid) {
98         val input = removeFlowInput(node, flow);
99         delegate.removeFlow(input);
100         return new Status(StatusCode.SUCCESS);
101     }
102
103     override removeAllFlows(Node node) {
104         throw new UnsupportedOperationException("Not present in MD-SAL");
105     }
106
107     override syncSendBarrierMessage(Node node) {
108
109         // FIXME: Update YANG model
110         return null;
111     }
112
113     override asyncSendBarrierMessage(Node node) {
114
115         // FIXME: Update YANG model
116         return null;
117     }
118
119     private static def toStatus(boolean successful) {
120         if (successful) {
121             return new Status(StatusCode.SUCCESS);
122         } else {
123             return new Status(StatusCode.INTERNALERROR);
124         }
125     }
126
127
128     private def writeFlow(AddFlowInput flow, NodeKey nodeKey, FlowKey flowKey) {
129         val modification = this._dataBrokerService.beginTransaction();
130         val flowPath = InstanceIdentifier.builder(Nodes)
131                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, nodeKey).augmentation(FlowCapableNode)
132                 .child(Table, new TableKey(flow.getTableId())).child(org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow, flowKey).build();
133         modification.putOperationalData(flowPath, flow);
134         modification.putConfigurationData(flowPath, flow);
135         val commitFuture = modification.commit();
136         try {
137             val result = commitFuture.get();
138             val status = result.getResult();
139         } catch (InterruptedException e) {
140             LOG.error(e.getMessage(), e);
141         } catch (ExecutionException e) {
142             LOG.error(e.getMessage(), e);
143         }
144     }
145
146     public static def toStatus(RpcResult<?> result) {
147         return toStatus(result.isSuccessful());
148     }
149     
150     private static dispatch def Status processException(InterruptedException e) {
151         LOG.error("Interruption occured during processing flow",e);
152         return new Status(StatusCode.INTERNALERROR);
153     }
154     
155     private static dispatch def Status processException(ExecutionException e) {
156         LOG.error("Execution exception occured during processing flow",e.cause);
157         return new Status(StatusCode.INTERNALERROR);
158     }
159     
160     private static dispatch def Status processException(Exception e) {
161         throw new RuntimeException(e);
162     }
163     
164     override onFlowAdded(FlowAdded notification) {
165         // NOOP : Not supported by AD SAL
166     }
167     
168     override onFlowRemoved(FlowRemoved notification) {
169         flowProgrammerPublisher.flowRemoved(notification.node.toADNode,notification.toFlow());
170     }
171     
172     override onFlowUpdated(FlowUpdated notification) {
173         // NOOP : Not supported by AD SAL
174     }
175     
176     override onSwitchFlowRemoved(SwitchFlowRemoved notification) {
177         // NOOP : Not supported by AD SAL
178     }
179     
180      override onNodeErrorNotification(NodeErrorNotification notification) {
181         // NOOP : Not supported by AD SAL
182     }
183     
184      override onNodeExperimenterErrorNotification(
185                 NodeExperimenterErrorNotification notification) {
186         // NOOP : Not supported by AD SAL
187     }
188 }