MD SAL Util API exposed as a Service
[vpnservice.git] / mdsalutil / mdsalutil-impl / src / main / java / org / opendaylight / vpnservice / mdsalutil / internal / MDSALManager.java
1 /*
2  * Copyright (c) 2013 Ericsson AB.  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
10 package org.opendaylight.vpnservice.mdsalutil.internal;
11
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.concurrent.atomic.AtomicInteger;
16
17 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
18 //import org.opendaylight.controller.md.sal.common.api.data.DataModification;
19 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
20 import org.opendaylight.vpnservice.mdsalutil.ActionType;
21 import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
22 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
23 import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
24 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
25 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
26 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
27 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
28 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
29 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
30 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
31 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
32 import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
33 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowTableRef;
43 // Missing constraint
44 //import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
53 //import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.OpendaylightInventoryService;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
60 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
62 import org.opendaylight.yangtools.yang.common.RpcResult;
63 import org.slf4j.Logger;
64 import org.slf4j.LoggerFactory;
65
66 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
67 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
68 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
69 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
70 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
71
72 import com.google.common.util.concurrent.CheckedFuture;
73 import com.google.common.util.concurrent.FutureCallback;
74 import com.google.common.util.concurrent.Futures;
75 import com.google.common.util.concurrent.ListenableFuture;
76
77 public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, AutoCloseable {
78
79     private static final Logger s_logger = LoggerFactory.getLogger(MDSALManager.class);
80
81     private DataBroker m_dataBroker;
82
83     private ConsumerContext m_consumerContext = null;
84        
85     private PacketProcessingService m_packetProcessingService;
86       
87     private final AtomicInteger m_atomicInteger = new AtomicInteger();
88
89     //TODO : IF ID MANAGER IS RQD
90     
91     @Override
92     public void onSessionInitialized(ConsumerContext session) {
93         
94         s_logger.info( " Session Initiated for MD SAL Manager") ;
95         
96         m_consumerContext = session;
97         
98        m_dataBroker = session.getSALService(DataBroker.class);
99               
100         // TODO - Verify this.
101        m_packetProcessingService = session.getRpcService(PacketProcessingService.class);
102             
103     }
104     
105     
106     @Override
107     public void close() throws Exception {
108         s_logger.info("MDSAL Manager Closed");
109     }
110     
111     @Override
112     public void printTest() {
113         
114         s_logger.info(" INTER MODULECOMMUNICATION IS WORKING!!!!");
115     }
116     @Override
117     public void installFlow(FlowEntity flowEntity) {
118         try {
119             s_logger.info("within installFlowX {}", flowEntity.getDpnId());
120             System.out.println( " Insie installFlow -- ") ;
121
122             if (flowEntity.getCookie() == null) {
123                 s_logger.info("Helium_sync: Cookie is null");
124                 flowEntity.setCookie(new BigInteger("0110000", 16));
125             }
126
127             Flow flow = flowEntity.getFlowBuilder().build();
128
129             Node nodeDpn = buildDpnNode(flowEntity.getDpnId());
130             InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
131                     .child(Node.class, nodeDpn.getKey()).build();
132             InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
133                     .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
134                     .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flow.getKey()).build();
135
136             String sTransactionUri = generateTransactionUri();
137             // Helium Way
138                        
139             WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
140             
141             modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn, true);
142             
143             modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow);
144             
145             ListenableFuture<RpcResult<TransactionStatus>> commitFuture = modification.commit();
146             
147             Futures.addCallback(commitFuture, new FutureCallback<RpcResult<TransactionStatus>>() {
148                 @Override
149                 public void onSuccess(RpcResult<TransactionStatus> result) {
150                         if( result.getResult() != TransactionStatus.COMMITED ) {
151                                 s_logger.debug("Failed to commit the Flow Data " + result.getErrors());
152                         
153                     }
154                 
155                 }
156
157                 @Override
158                 public void onFailure(Throwable throwable) {
159                         s_logger.error(throwable.getMessage(), throwable);
160                     s_logger.debug(String.format("Status of Flow Data Loaded Transaction : failure. Reason : %s", throwable));
161                     
162                 }
163             });
164         } catch (Exception e) {
165             s_logger.error("Could not install flow: {}, exception: {}", flowEntity, e.getMessage());
166         }
167
168     }
169     @Override
170     public void installGroup(GroupEntity groupEntity) {
171         try {
172             Group group = groupEntity.getGroupBuilder().build();
173
174             Node nodeDpn = buildDpnNode(groupEntity.getDpnId());
175             InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
176                     .child(Node.class, nodeDpn.getKey()).build();
177             InstanceIdentifier<Group> groupInstanceId = InstanceIdentifier.builder(Nodes.class)
178                     .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
179                     .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build();
180
181                        
182          // Helium
183             WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
184             
185             modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn);
186             modification.put(LogicalDatastoreType.CONFIGURATION, groupInstanceId, group);
187                               
188             ListenableFuture<RpcResult<TransactionStatus>> commitFuture = modification.commit();
189             
190             Futures.addCallback(commitFuture, new FutureCallback<RpcResult<TransactionStatus>>() {
191                 @Override
192                 public void onSuccess(RpcResult<TransactionStatus> result) {
193                         if( result.getResult() != TransactionStatus.COMMITED ) {
194                                 s_logger.debug("Failed to commit the group Data " + result.getErrors());
195                         
196                     }
197                 
198                 }
199
200                 @Override
201                 public void onFailure(Throwable throwable) {
202                         s_logger.error(throwable.getMessage(), throwable);
203                     s_logger.debug(String.format("Status of Group Data Loaded Transaction : failure. Reason : %s", throwable));
204                     
205                 }
206             });
207                         
208         } catch (Exception e) {
209             s_logger.error("Could not install Group: {}, exception: {}", groupEntity, e.getMessage());
210             throw e;
211         }
212     }
213
214     @Override
215     public void removeFlow(FlowEntity flowEntity) {
216         try {
217             Node nodeDpn = buildDpnNode(flowEntity.getDpnId());
218             FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getFlowId()));
219             InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
220                     .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
221                     .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build();
222
223
224                 WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
225                 modification.delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId );
226
227                 ListenableFuture<RpcResult<TransactionStatus>> commitFuture = modification.commit();
228                 
229                 Futures.addCallback(commitFuture, new FutureCallback<RpcResult<TransactionStatus>>() {
230                     @Override
231                     public void onSuccess(RpcResult<TransactionStatus> result) {
232                         if( result.getResult() != TransactionStatus.COMMITED ) {
233                                 s_logger.debug("Failed to remove the Flow Data " + result.getErrors());
234                                 
235                         }
236                     
237                     }
238
239                     @Override
240                     public void onFailure(Throwable throwable) {
241                         s_logger.error(throwable.getMessage(), throwable);
242                         s_logger.debug(String.format("Status of Flow Data remove Transaction : failure. Reason : %s", throwable));
243                         
244                     }
245                 });
246         } catch (Exception e) {
247             s_logger.error("Could not remove Flow: {}, exception: {}", flowEntity, e.getMessage());
248         }
249     }
250
251     @Override
252     public void removeGroup(GroupEntity groupEntity) {
253         try {
254             Node nodeDpn = buildDpnNode(groupEntity.getDpnId());
255             InstanceIdentifier<Group> groupInstanceId = InstanceIdentifier.builder(Nodes.class)
256                     .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
257                     .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build();
258
259
260             WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
261             
262             modification.delete(LogicalDatastoreType.CONFIGURATION,groupInstanceId );
263
264             ListenableFuture<RpcResult<TransactionStatus>> commitFuture = modification.commit();
265             
266             Futures.addCallback(commitFuture, new FutureCallback<RpcResult<TransactionStatus>>() {
267                 @Override
268                 public void onSuccess(RpcResult<TransactionStatus> result) {
269                         if( result.getResult() != TransactionStatus.COMMITED ) {
270                                 s_logger.debug("Failed to remove the group Data " + result.getErrors());
271                         
272                     }
273                 
274                 }
275
276                 @Override
277                 public void onFailure(Throwable throwable) {
278                         s_logger.error(throwable.getMessage(), throwable);
279                     s_logger.debug(String.format("Status of group Data remove Transaction : failure. Reason : %s", throwable));
280                     
281                 }
282             });
283
284                 
285
286         } catch (Exception e) {
287             s_logger.error("Could not remove Group: {}, exception: {}", groupEntity, e.getMessage());
288         }
289     }
290
291     @Override
292     public void modifyGroup(GroupEntity groupEntity) {
293
294         installGroup(groupEntity);
295     }
296
297     private String generateTransactionUri() {
298         long lTransactionIdOut = m_atomicInteger.incrementAndGet();
299
300         // TO DO Introduce this later
301       //  return "" + (lTransactionIdOut | m_lTransactionIdPrefix);
302         return "" + (lTransactionIdOut );
303     }
304 /*
305     private String generateTransactionUriForFlow(long nTransactionId) {
306         long lTransactionIdOut = m_atomicInteger.incrementAndGet();
307         return Long.toString((lTransactionIdOut | m_lTransactionIdPrefix)) + EUtil.TRANSACTION_ID_SEPARATOR
308                 + Long.toString(nTransactionId);
309     }
310 */
311     
312     @Override
313     public void sendPacketOut(long lDpnId, int groupId, byte[] payload) {
314
315         List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
316         actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
317
318         sendPacketOutWithActions(lDpnId, groupId, payload, actionInfos);
319     }
320
321     @Override
322     public void sendPacketOutWithActions(long lDpnId, long groupId, byte[] payload, List<ActionInfo> actionInfos) {
323
324         m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actionInfos, payload, lDpnId,
325                 getNodeConnRef("openflow:" + lDpnId, "0xfffffffd")));
326     }
327
328     @Override
329     public void sendARPPacketOutWithActions(long lDpnId, byte[] payload, List<ActionInfo> actions) {
330
331         m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actions, payload, lDpnId,
332                 getNodeConnRef("openflow:" + lDpnId, "0xfffffffd")));
333     }
334
335     private NodeKey getNodeKey(long dpId) {
336         String nodeId = "openflow:" + dpId;
337         NodeKey nodeKey = new NodeKey(new NodeId(nodeId));
338         return nodeKey;
339     }
340
341     public InstanceIdentifier<Node> nodeToInstanceId(Node node) {
342         return InstanceIdentifier.builder(Nodes.class).child(Node.class, node.getKey()).toInstance();
343     }
344
345     private static NodeConnectorRef getNodeConnRef(final String nodeId, final String port) {
346         StringBuilder _stringBuilder = new StringBuilder(nodeId);
347         StringBuilder _append = _stringBuilder.append(":");
348         StringBuilder sBuild = _append.append(port);
349         String _string = sBuild.toString();
350         NodeConnectorId _nodeConnectorId = new NodeConnectorId(_string);
351         NodeConnectorKey _nodeConnectorKey = new NodeConnectorKey(_nodeConnectorId);
352         NodeConnectorKey nConKey = _nodeConnectorKey;
353         InstanceIdentifierBuilder<Nodes> _builder = InstanceIdentifier.<Nodes> builder(Nodes.class);
354         NodeId _nodeId = new NodeId(nodeId);
355         NodeKey _nodeKey = new NodeKey(_nodeId);
356         InstanceIdentifierBuilder<Node> _child = _builder.<Node, NodeKey> child(Node.class, _nodeKey);
357         InstanceIdentifierBuilder<NodeConnector> _child_1 = _child.<NodeConnector, NodeConnectorKey> child(
358                 NodeConnector.class, nConKey);
359         InstanceIdentifier<NodeConnector> path = _child_1.toInstance();
360         NodeConnectorRef _nodeConnectorRef = new NodeConnectorRef(path);
361         return _nodeConnectorRef;
362     }
363
364     private long getDpnIdFromNodeName(String nodeName) {
365         String dpId = nodeName.substring(nodeName.lastIndexOf(":") + 1);
366         return Long.parseLong(dpId);
367     }
368
369     private Node buildDpnNode(long lDpnId) {
370         NodeId nodeId = new NodeId("openflow:" + lDpnId);
371         Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
372
373         return nodeDpn;
374     }
375 }