Add <relativePath/> for bgpmanager to ensure Maven pulls artifact from Nexus
[vpnservice.git] / vpnmanager-impl / src / main / java / org / opendaylight / vpnservice / VpnInterfaceManager.java
1 /*\r
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 package org.opendaylight.vpnservice;\r
9 \r
10 import java.util.List;\r
11 import java.util.ArrayList;\r
12 \r
13 import com.google.common.base.Optional;\r
14 import com.google.common.util.concurrent.Futures;\r
15 import com.google.common.util.concurrent.FutureCallback;\r
16 \r
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
18 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
19 import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
20 import org.opendaylight.yangtools.yang.binding.DataObject;\r
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
22 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;\r
23 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
26 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyList;\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;\r
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;\r
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;\r
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;\r
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;\r
39 import org.slf4j.Logger;\r
40 import org.slf4j.LoggerFactory;\r
41 \r
42 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {\r
43     private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);\r
44     private ListenerRegistration<DataChangeListener> listenerRegistration;\r
45     private final DataBroker broker;\r
46 \r
47     private static final FutureCallback<Void> DEFAULT_CALLBACK =\r
48             new FutureCallback<Void>() {\r
49                 public void onSuccess(Void result) {\r
50                     LOG.info("Success in Datastore write operation");\r
51                 }\r
52 \r
53                 public void onFailure(Throwable error) {\r
54                     LOG.error("Error in Datastore write operation", error);\r
55                 };\r
56             };\r
57 \r
58     /**\r
59      * Responsible for listening to data change related to VPN Interface\r
60      * Bind VPN Service on the interface and informs the BGP service\r
61      * \r
62      * @param db - dataBroker service reference\r
63      */\r
64     public VpnInterfaceManager(final DataBroker db) {\r
65         super(VpnInterface.class);\r
66         broker = db;\r
67         registerListener(db);\r
68     }\r
69 \r
70     @Override\r
71     public void close() throws Exception {\r
72         if (listenerRegistration != null) {\r
73             try {\r
74                 listenerRegistration.close();\r
75             } catch (final Exception e) {\r
76                 LOG.error("Error when cleaning up DataChangeListener.", e);\r
77             }\r
78             listenerRegistration = null;\r
79         }\r
80         LOG.info("VPN Interface Manager Closed");\r
81     }\r
82 \r
83     private void registerListener(final DataBroker db) {\r
84         try {\r
85             listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,\r
86                     getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);\r
87         } catch (final Exception e) {\r
88             LOG.error("VPN Service DataChange listener registration fail!", e);\r
89             throw new IllegalStateException("VPN Service registration Listener failed.", e);\r
90         }\r
91     }\r
92 \r
93     @Override\r
94     protected void add(final InstanceIdentifier<VpnInterface> identifier,\r
95             final VpnInterface vpnInterface) {\r
96         LOG.info("key: " + identifier + ", value=" + vpnInterface );\r
97         addInterface(identifier, vpnInterface);\r
98     }\r
99 \r
100     private void addInterface(final InstanceIdentifier<VpnInterface> identifier,\r
101                               final VpnInterface vpnInterface) {\r
102         final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);\r
103         String interfaceName = key.getName();\r
104         InstanceIdentifierBuilder<Interface> idBuilder = \r
105                 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));\r
106         InstanceIdentifier<Interface> id = idBuilder.build();\r
107         Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);\r
108         if (port.isPresent()) {\r
109             Interface interf = port.get();\r
110             bindServiceOnInterface(interf);\r
111             updateNextHops(identifier, vpnInterface);\r
112         }\r
113     }\r
114 \r
115     private void updateNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {\r
116         //Read NextHops\r
117         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);\r
118         Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);\r
119         String intfName = intf.getName();\r
120 \r
121         if (adjacencies.isPresent()) {\r
122             List<Adjacency> nextHops = adjacencies.get().getAdjacency();\r
123             List<Adjacency> value = new ArrayList<>();\r
124 \r
125             if (!nextHops.isEmpty()) {\r
126                 LOG.info("NextHops are " + nextHops);\r
127                 for (Adjacency nextHop : nextHops) {\r
128                     //TODO: Generate label for the prefix and store it in the next hop model\r
129                     long label = 200;\r
130 \r
131                     //TODO: Update BGP\r
132                     updatePrefixToBGP(nextHop);\r
133                     value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());\r
134                 }\r
135             }\r
136             Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);\r
137             VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);\r
138             InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);\r
139             asyncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);\r
140         }\r
141     }\r
142 \r
143     private void bindServiceOnInterface(Interface intf) {\r
144         //TODO: Create Ingress flow on the interface to bind the VPN service\r
145     }\r
146 \r
147     private void updatePrefixToBGP(Adjacency nextHop) {\r
148         //TODO: Update the Prefix to BGP\r
149     }\r
150 \r
151     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,\r
152             InstanceIdentifier<T> path) {\r
153 \r
154         ReadOnlyTransaction tx = broker.newReadOnlyTransaction();\r
155 \r
156         Optional<T> result = Optional.absent();\r
157         try {\r
158             result = tx.read(datastoreType, path).get();\r
159         } catch (Exception e) {\r
160             throw new RuntimeException(e);\r
161         }\r
162 \r
163         return result;\r
164     }\r
165 \r
166     private InstanceIdentifier<VpnInterface> getWildCardPath() {\r
167         return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);\r
168     }\r
169 \r
170     @Override\r
171     protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {\r
172         // TODO Auto-generated method stub\r
173 \r
174     }\r
175 \r
176     @Override\r
177     protected void update(InstanceIdentifier<VpnInterface> identifier, \r
178                                    VpnInterface original, VpnInterface update) {\r
179         // TODO Auto-generated method stub\r
180 \r
181     }\r
182 \r
183     private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,\r
184                         InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {\r
185         WriteTransaction tx = broker.newWriteOnlyTransaction();\r
186         tx.put(datastoreType, path, data, true);\r
187         Futures.addCallback(tx.submit(), callback);\r
188     }\r
189 }\r