181c4a40104a0a6578aada874d8ed629479aa105
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / IpvcListener.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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.unimgr.mef.netvirt;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
17 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
20 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
21 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.ip.uni.subnets.Subnet;
22 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
27 import org.opendaylight.yangtools.concepts.ListenerRegistration;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> {
32     private static final Logger Log = LoggerFactory.getLogger(IpvcListener.class);
33     private ListenerRegistration<IpvcListener> ipvcListenerRegistration;
34     private final NotificationPublishService notificationPublishService;
35     private final OdlArputilService arpUtilService;
36
37     public IpvcListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
38             final OdlArputilService arputilService) {
39         super(dataBroker);
40         this.notificationPublishService = notPublishService;
41         this.arpUtilService = arputilService;
42         registerListener();
43     }
44
45     public void registerListener() {
46         try {
47             final DataTreeIdentifier<Ipvc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
48                     MefUtils.getIpvcInstanceIdentifier());
49             ipvcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
50             Log.info("IpvcDataTreeChangeListener created and registered");
51         } catch (final Exception e) {
52             Log.error("Ipvc DataChange listener registration failed !", e);
53             throw new IllegalStateException("Ipvc registration Listener failed.", e);
54         }
55     }
56
57     @Override
58     public void close() throws Exception {
59         ipvcListenerRegistration.close();
60     }
61
62     @Override
63     public void add(DataTreeModification<Ipvc> newDataObject) {
64         if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
65             Log.info("ipvc {} created", newDataObject.getRootNode().getIdentifier());
66             addIpvc(newDataObject);
67         }
68     }
69
70     @Override
71     public void remove(DataTreeModification<Ipvc> removedDataObject) {
72         if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
73             Log.info("ipvc {} deleted", removedDataObject.getRootNode().getIdentifier());
74             removeIpvc(removedDataObject);
75         }
76     }
77
78     @Override
79     public void update(DataTreeModification<Ipvc> modifiedDataObject) {
80         if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
81             Log.info("ipvc {} updated", modifiedDataObject.getRootNode().getIdentifier());
82             updateIpvc(modifiedDataObject);
83         }
84     }
85
86     private void addIpvc(DataTreeModification<Ipvc> newDataObject) {
87         try {
88             Ipvc data = newDataObject.getRootNode().getDataAfter();
89             String instanceName = data.getIpvcId().getValue();
90             final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
91
92             Log.info("Adding vpn instance: " + instanceName);
93             NetvirtVpnUtils.createVpnInstance(dataBroker, vpnName);
94             Log.info("Number of UNI's: " + data.getUnis().getUni().size());
95
96
97             // Create elan interfaces
98             for (Uni uni : data.getUnis().getUni()) {
99                 createInterfaces(vpnName, uni);
100             }
101         } catch (final Exception e) {
102             Log.error("Add ipvc failed !", e);
103         }
104     }
105
106     private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
107         try {
108             Ipvc original = modifiedDataObject.getRootNode().getDataBefore();
109             Ipvc update = modifiedDataObject.getRootNode().getDataAfter();
110
111             String instanceName = original.getIpvcId().getValue();
112             final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
113
114             Log.info("Updating elan instance: " + instanceName);
115
116             if (original == null || original.getUnis() == null || original.getUnis().getUni() == null) {
117                 addIpvc(modifiedDataObject);
118                 return;
119             }
120
121             List<Uni> originalUni = original.getUnis().getUni();
122             List<Uni> updateUni = update.getUnis().getUni();
123             if (updateUni != null && !updateUni.isEmpty()) {
124                 List<Uni> existingClonedUni = new ArrayList<>();
125                 if (originalUni != null && !originalUni.isEmpty()) {
126                     existingClonedUni.addAll(0, originalUni);
127                     originalUni.removeAll(updateUni);
128                     updateUni.removeAll(existingClonedUni);
129                     // removing the Uni which are not presented in the updated
130                     // List
131                     for (Uni uni : originalUni) {
132                         removeElanInterface(vpnName, uni);
133                     }
134                 }
135
136                 // Adding the new Uni which are presented in the updated List
137                 if (updateUni.size() > 0) {
138                     for (Uni uni : updateUni) {
139                         createInterfaces(vpnName, uni);
140                     }
141                 }
142             } else if (originalUni != null && !originalUni.isEmpty()) {
143                 for (Uni uni : originalUni) {
144                     removeElanInterface(vpnName, uni);
145                 }
146             }
147         } catch (final Exception e) {
148             Log.error("Update ipvc failed !", e);
149         }
150     }
151
152     private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
153         try {
154             Ipvc data = removedDataObject.getRootNode().getDataBefore();
155
156             String instanceName = data.getIpvcId().getValue();
157
158             for (Uni uni : data.getUnis().getUni()) {
159                 removeElanInterface(instanceName, uni);
160             }
161
162             Log.info("Removing elan instance: " + instanceName);
163             NetvirtUtils.deleteElanInstance(dataBroker, instanceName);
164         } catch (final Exception e) {
165             Log.error("Remove ipvc failed !", e);
166         }
167     }
168
169     private void createInterfaces(Ipvc ipvc, Uni uni) {
170         String instanceName = ipvc.getIpvcId().getValue();
171         createInterfaces(instanceName, uni);
172     }
173
174     private void createInterfaces(String vpnName, Uni uniInService) {
175         String uniId = uniInService.getUniId().getValue();
176         String ipUniId = uniInService.getIpUniId().getValue();
177
178         Log.info("Adding/updating elan instance: " + uniId);
179
180         org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = IpvcUniUtils
181                 .getUni(dataBroker, uniId);
182         if (uni == null) {
183             Log.error("Couldn't find uni {} for ipvc-uni", uniId);
184             throw new UnsupportedOperationException();
185         }
186         IpUni ipUni = IpvcUniUtils.getIpUni(dataBroker, uniId, ipUniId);
187         Integer vlan = ipUni.getVlan() != null ? ipUni.getVlan().getValue() : null;
188
189         String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId);
190         Log.info("Adding elan instance: " + elanName);
191         NetvirtUtils.updateElanInstance(dataBroker, elanName);
192
193         String interfaceName = NetvirtVpnUtils.getInterfaceNameForVlan(ipUniId, vlan);
194         Log.info("Adding trunk interface: " + interfaceName);
195         IpvcUniUtils.addUni(dataBroker, uniInService, interfaceName, vlan);
196
197         Log.info("Adding elan interface: " + interfaceName);
198         NetvirtUtils.createInterface(dataBroker, elanName, interfaceName, EtreeInterfaceType.Root, false);
199
200         Log.info("Adding vpn interface: " + interfaceName);
201         NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
202                 uni.getMacAddress(), true, null);
203         NetvirtVpnUtils.createVpnPortFixedIp(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
204                 uni.getMacAddress());
205
206         Log.info("Adding connected network for interface : " + interfaceName);
207         NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, vpnName, elanName,
208                 ipUni.getIpAddress(), interfaceName);
209
210         if (ipUni != null && ipUni.getSubnets() != null && ipUni.getSubnets().getSubnet() != null) {
211             for (Subnet subnet : ipUni.getSubnets().getSubnet()) {
212                 Log.info("Resolving MAC address for gateway: " + subnet.getGateway());
213                 MacAddress gwMacAddress = NetvirtVpnUtils.resolveGwMac(dataBroker, arpUtilService, vpnName,
214                         ipUni.getIpAddress(), subnet.getGateway(), interfaceName); // trunk
215                 if (gwMacAddress == null) {
216                     continue;
217                 }
218                 Log.info("update vpn interface: " + interfaceName);
219                 NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, subnet.getSubnet(),
220                         gwMacAddress, false, ipUni.getIpAddress());
221             }
222         }
223         Log.info("Finished working on elan instance: " + uniId);
224     }
225
226     private void removeElanInterface(String instanceName, Uni uni) {
227         String uniId = uni.getIpUniId().getValue();
228         String interfaceName = uniId;
229         Log.info("Removing elan interface: " + uniId);
230         NetvirtUtils.deleteElanInterface(dataBroker, instanceName, interfaceName);
231     }
232 }