Update profile listener
[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.Collections;
13 import java.util.List;
14 import java.util.stream.Collectors;
15
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
22 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.SubnetBuilder;
24 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
25 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
28 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;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
30 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
40 import org.opendaylight.yangtools.concepts.ListenerRegistration;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> implements IUniAwareService {
46     private static final Logger Log = LoggerFactory.getLogger(IpvcListener.class);
47     private final IUniPortManager uniPortManager;
48     private final ISubnetManager subnetManager;
49     private final UniQosManager uniQosManager;
50     private ListenerRegistration<IpvcListener> ipvcListenerRegistration;
51     @SuppressWarnings("unused")
52     private final UniAwareListener uniAwareListener;
53
54     public IpvcListener(final DataBroker dataBroker, final IUniPortManager uniPortManager,
55             final ISubnetManager subnetManager, final UniQosManager uniQosManager) {
56         super(dataBroker);
57         this.uniPortManager = uniPortManager;
58         this.subnetManager = subnetManager;
59         this.uniQosManager = uniQosManager;
60         this.uniAwareListener = new UniAwareListener(dataBroker, this);
61         registerListener();
62     }
63
64     public void registerListener() {
65         try {
66             final DataTreeIdentifier<Ipvc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
67                     MefServicesUtils.getIpvcsInstanceIdentifier());
68             ipvcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
69             Log.info("IpvcDataTreeChangeListener created and registered");
70         } catch (final Exception e) {
71             Log.error("Ipvc DataChange listener registration failed !", e);
72             throw new IllegalStateException("Ipvc registration Listener failed.", e);
73         }
74     }
75
76     @Override
77     public void close() throws Exception {
78         ipvcListenerRegistration.close();
79     }
80
81     @Override
82     public void add(DataTreeModification<Ipvc> newDataObject) {
83         if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
84             Log.info("ipvc {} created", newDataObject.getRootNode().getIdentifier());
85             addIpvc(newDataObject);
86         }
87     }
88
89     @Override
90     public void remove(DataTreeModification<Ipvc> removedDataObject) {
91         if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
92             Log.info("ipvc {} deleted", removedDataObject.getRootNode().getIdentifier());
93             removeIpvc(removedDataObject);
94         }
95     }
96
97     @Override
98     public void update(DataTreeModification<Ipvc> modifiedDataObject) {
99         if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
100             Log.info("ipvc {} updated", modifiedDataObject.getRootNode().getIdentifier());
101             updateIpvc(modifiedDataObject);
102         }
103     }
104
105     @Override
106     public void connectUni(String uniId) {
107         List<RetailSvcIdType> allIpvcs = MefServicesUtils.getAllIpvcsServiceIds(dataBroker);
108         allIpvcs = allIpvcs != null ? allIpvcs : Collections.emptyList();
109
110         for (RetailSvcIdType ipvcSerId : allIpvcs) {
111             InstanceIdentifier<Ipvc> ipvcId = MefServicesUtils.getIpvcInstanceIdentifier(ipvcSerId);
112             Ipvc ipvc = MefServicesUtils.getIpvc(dataBroker, ipvcId);
113             if (ipvc == null) {
114                 Log.error("Inconsistent data for svcId {}", ipvcSerId);
115                 continue;
116             }
117             List<Uni> toConnect = new ArrayList<>();
118
119             List<Uni> unis = ipvc.getUnis() != null ? ipvc.getUnis().getUni() : null;
120             unis = unis != null ? unis : Collections.emptyList();
121             for (Uni uni : unis) {
122                 if (uni.getUniId().getValue().equals(uniId)) {
123                     Log.info("Connecting Uni {} to svc id {}", uniId, ipvcSerId);
124                     toConnect.add(uni);
125                     break;
126                 }
127             }
128
129             IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
130             if (operIpvcVpn == null) {
131                 String instanceName = ipvc.getIpvcId().getValue();
132                 final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
133                 createVpnInstance(vpnName, ipvcId);
134                 operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
135                 if (operIpvcVpn == null) {
136                     Log.error("Ipvc {} hasn't been created as required, Nothing to reconnect", ipvcSerId);
137                     return;
138                 }
139             }
140             String vpnName = operIpvcVpn.getVpnId();
141             String rd = waitForRd(vpnName);
142             createUnis(vpnName, ipvcId, toConnect, rd);
143         }
144     }
145
146     @Override
147     public void disconnectUni(String uniId) {
148
149         List<RetailSvcIdType> allIpvcs = MefServicesUtils.getAllIpvcsServiceIds(dataBroker);
150         allIpvcs = allIpvcs != null ? allIpvcs : Collections.emptyList();
151
152         for (RetailSvcIdType ipvcSerId : allIpvcs) {
153             InstanceIdentifier<Ipvc> ipvcId = MefServicesUtils.getIpvcInstanceIdentifier(ipvcSerId);
154             Ipvc ipvc = MefServicesUtils.getIpvc(dataBroker, ipvcId);
155             if (ipvc == null) {
156                 Log.error("Inconsistent data for svcId {}", ipvcSerId);
157                 continue;
158             }
159             List<Uni> toRemove = new ArrayList<>();
160
161             List<Uni> unis = ipvc.getUnis() != null ? ipvc.getUnis().getUni() : null;
162             unis = unis != null ? unis : Collections.emptyList();
163             for (Uni uni : unis) {
164                 if (uni.getUniId().getValue().equals(uniId)) {
165                     Log.info("Disconnecting Uni {} from svc id {}", uniId, ipvcSerId);
166                     toRemove.add(uni);
167                     break;
168                 }
169             }
170
171             IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
172             if (operIpvcVpn == null) {
173                 Log.error("Ipvc {} hasn't been created as required, Nothing to disconnect", ipvcSerId);
174                 return;
175             }
176             String vpnName = operIpvcVpn.getVpnId();
177
178             synchronized (vpnName.intern()) {
179                 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
180                 removeUnis(ipvcId, operIpvcVpn, toRemove, tx);
181                 MdsalUtils.commitTransaction(tx);
182             }
183         }
184     }
185
186     private void addIpvc(DataTreeModification<Ipvc> newDataObject) {
187         try {
188             Ipvc ipvc = newDataObject.getRootNode().getDataAfter();
189             String instanceName = ipvc.getIpvcId().getValue();
190             final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
191             InstanceIdentifier<Ipvc> ipvcId = newDataObject.getRootPath().getRootIdentifier();
192             createVpnInstance(vpnName, ipvcId);
193             String rd = waitForRd(vpnName);
194
195             updateOperationalDataStoreWithVrfId(ipvcId, vpnName, rd);
196
197             List<Uni> unis = new ArrayList<>();
198             if (ipvc.getUnis() != null && ipvc.getUnis() != null) {
199                 unis = ipvc.getUnis().getUni();
200             }
201             Log.info("Number of UNI's: " + unis.size());
202
203             createUnis(vpnName, ipvcId, unis, rd);
204         } catch (final Exception e) {
205             Log.error("Add ipvc failed !", e);
206         }
207     }
208
209     private void updateOperationalDataStoreWithVrfId(InstanceIdentifier<Ipvc> ipvcId, String vpnName, String vrfId) {
210         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
211         MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, vrfId, tx);
212         MdsalUtils.commitTransaction(tx);
213     }
214
215     private void createVpnInstance(final String vpnName, InstanceIdentifier<Ipvc> ipvcId) {
216         synchronized (vpnName.intern()) {
217             WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
218             Log.info("Adding vpn instance: " + vpnName);
219             NetvirtVpnUtils.createVpnInstance(vpnName, tx);
220             MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, tx);
221             MdsalUtils.commitTransaction(tx);
222         }
223     }
224
225     private String waitForRd(final String vpnName) {
226         InstanceIdentifier<VpnInstance> vpnId = NetvirtVpnUtils.getVpnInstanceToVpnIdIdentifier(vpnName);
227         @SuppressWarnings("resource")
228         DataWaitListener<VpnInstance> vpnInstanceWaiter = new DataWaitListener<VpnInstance>(dataBroker, vpnId, 5,
229                 LogicalDatastoreType.CONFIGURATION, vpn -> vpn.getVrfId());
230         if (!vpnInstanceWaiter.waitForData()) {
231             String errorMessage = String.format("Fail to wait for vrfId for vpn %s", vpnName);
232             Log.error(errorMessage);
233             throw new UnsupportedOperationException(errorMessage);
234         }
235         String rd = (String) vpnInstanceWaiter.getData();
236         return rd;
237     }
238
239     private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
240         try {
241             Ipvc ipvc = removedDataObject.getRootNode().getDataBefore();
242             InstanceIdentifier<Ipvc> ipvcId = removedDataObject.getRootPath().getRootIdentifier();
243             IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
244             if (operIpvcVpn == null) {
245                 Log.error("Ipvc {} hasn't been created as required", ipvc.getIpvcId());
246                 return;
247             }
248             String vpnName = operIpvcVpn.getVpnId();
249
250             synchronized (vpnName.intern()) {
251                 // remove elan/vpn interfaces
252                 // must be in different transactios
253                 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
254                 removeUnis(ipvcId, operIpvcVpn, ipvc.getUnis().getUni(), tx);
255                 MdsalUtils.commitTransaction(tx);
256                 // Let to work for listeners
257                 // TODO : change to listener
258                 NetvirtUtils.safeSleep();
259
260                 WriteTransaction txvpn = MdsalUtils.createTransaction(dataBroker);
261                 NetvirtVpnUtils.removeVpnInstance(operIpvcVpn.getVpnId(), txvpn);
262                 MefServicesUtils.removeOperIpvcVpn(ipvcId, txvpn);
263                 MdsalUtils.commitTransaction(txvpn);
264             }
265         } catch (final Exception e) {
266             Log.error("Remove ipvc failed !", e);
267         }
268     }
269
270     private void removeUnis(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn operIpvcVpn, List<Uni> uniToRemove,
271             WriteTransaction tx) {
272         if (uniToRemove == null) {
273             Log.trace("No UNI's to remove");
274         }
275         for (Uni uni : uniToRemove) {
276             Identifier45 uniId = uni.getUniId();
277             Identifier45 ipUniId = uni.getIpUniId();
278             IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniId, ipUniId, LogicalDatastoreType.CONFIGURATION);
279             if (ipUni == null) {
280                 String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
281                 Log.error(errorMessage);
282                 throw new UnsupportedOperationException(errorMessage);
283             }
284
285             removeDirectSubnet(uni, ipUni);
286             subnetManager.unAssignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
287             removeInterfaces(ipvcId, operIpvcVpn, uni, ipUni, tx);
288         }
289         updateQos(uniToRemove);
290     }
291
292     private void createUnis(String vpnName, InstanceIdentifier<Ipvc> ipvcId, List<Uni> uniToCreate, String rd) {
293         // Create elan/vpn interfaces
294         for (Uni uni : uniToCreate) {
295             createInterfaces(vpnName, uni, ipvcId, rd);
296         }
297
298         for (Uni uni : uniToCreate) {
299             IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uni.getUniId(), uni.getIpUniId(),
300                     LogicalDatastoreType.CONFIGURATION);
301             createDirectSubnet(uni, ipUni);
302             subnetManager.assignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
303         }
304         updateQos(uniToCreate);
305     }
306
307     private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
308         try {
309             Ipvc origIpvc = modifiedDataObject.getRootNode().getDataBefore();
310             Ipvc updateIpvc = modifiedDataObject.getRootNode().getDataAfter();
311             InstanceIdentifier<Ipvc> ipvcId = modifiedDataObject.getRootPath().getRootIdentifier();
312             IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
313             if (operIpvcVpn == null) {
314                 Log.error("Ipvc {} hasn't been created as required", origIpvc.getIpvcId());
315                 return;
316             }
317             String vpnName = operIpvcVpn.getVpnId();
318             String rd = waitForRd(vpnName);
319             List<Uni> originalUni = origIpvc.getUnis() != null && origIpvc.getUnis().getUni() != null
320                     ? origIpvc.getUnis().getUni() : Collections.emptyList();
321             List<Identifier45> originalUniIds = originalUni.stream().map(u -> u.getUniId())
322                     .collect(Collectors.toList());
323             List<Uni> updateUni = updateIpvc.getUnis() != null && updateIpvc.getUnis().getUni() != null
324                     ? updateIpvc.getUnis().getUni() : Collections.emptyList();
325             List<Identifier45> updateUniIds = updateUni.stream().map(u -> u.getUniId()).collect(Collectors.toList());
326
327             synchronized (vpnName.intern()) {
328                 WriteTransaction txRemove = MdsalUtils.createTransaction(dataBroker);
329                 List<Uni> uniToRemove = new ArrayList<>(originalUni);
330                 uniToRemove.removeIf(u -> updateUniIds.contains(u.getUniId()));
331                 removeUnis(ipvcId, operIpvcVpn, uniToRemove, txRemove);
332                 MdsalUtils.commitTransaction(txRemove);
333             }
334             List<Uni> uniToCreate = new ArrayList<>(updateUni);
335             uniToCreate.removeIf(u -> originalUniIds.contains(u.getUniId()));
336             createUnis(vpnName, ipvcId, uniToCreate, rd);
337
338             List<Uni> uniToUpdate = new ArrayList<>(updateUni);
339             uniToUpdate.removeIf(u -> !originalUniIds.contains(u.getUniId()));
340             updateUnis(uniToUpdate);
341
342         } catch (final Exception e) {
343             Log.error("Update ipvc failed !", e);
344         }
345     }
346
347     private void createInterfaces(String vpnName, Uni uniInService, InstanceIdentifier<Ipvc> ipvcId, String rd) {
348         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
349         String uniId = uniInService.getUniId().getValue();
350         String ipUniId = uniInService.getIpUniId().getValue();
351         org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = MefInterfaceUtils
352                 .getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
353         if (uni == null) {
354             String errorMessage = String.format("Couldn't find uni %s for ipvc", uniId);
355             Log.error(errorMessage);
356             throw new UnsupportedOperationException(errorMessage);
357         }
358         IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniInService.getUniId(), uniInService.getIpUniId(),
359                 LogicalDatastoreType.CONFIGURATION);
360         if (ipUni == null) {
361             String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
362             Log.error(errorMessage);
363             throw new UnsupportedOperationException(errorMessage);
364         }
365
366         String interfaceName = null;
367         String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId, ipUniId);
368
369         String srcIpAddressStr = NetvirtVpnUtils
370                 .getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
371         IpAddress ipAddress = new IpAddress(srcIpAddressStr.toCharArray());
372         NetvirtVpnUtils.registerDirectSubnetForVpn(dataBroker, new Uuid(elanName), ipAddress);
373
374         synchronized (vpnName.intern()) {
375             Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : null;
376
377             interfaceName = createElanInterface(vpnName, ipvcId, uniId, elanName, vlan, ipAddress, tx,
378                     ipUni.getSegmentationId());
379             uniQosManager.mapUniPortBandwidthLimits(uniId, interfaceName, uniInService.getIngressBwProfile());
380             createVpnInterface(vpnName, uni, ipUni, interfaceName, elanName, tx);
381             NetvirtVpnUtils.createVpnPortFixedIp(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
382                     uni.getMacAddress(), tx);
383             MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, uniInService.getUniId(), uniInService.getIpUniId(),
384                     elanName, interfaceName, null, tx);
385             MdsalUtils.commitTransaction(tx);
386         }
387     }
388
389
390     private String createElanInterface(String vpnName, InstanceIdentifier<Ipvc> ipvcId, String uniId, String elanName,
391             Long vlan, IpAddress ipAddress, WriteTransaction tx, Long segmentationId) {
392         Log.info("Adding elan instance: " + elanName);
393         NetvirtUtils.updateElanInstance(elanName, tx, segmentationId);
394         NetvirtVpnUtils.registerDirectSubnetForVpn(dataBroker, new Uuid(elanName), ipAddress);
395
396         Log.info("Added trunk interface for uni {} vlan: {}", uniId, vlan);
397         if (vlan != null) {
398             uniPortManager.addCeVlan(uniId, vlan);
399         }
400         String interfaceName = uniPortManager.getUniVlanInterface(uniId, vlan);
401         if (interfaceName == null) {
402             String errorMessage = String.format("Couldn't create  uni %s vlan interface %s", uniId, vlan);
403             Log.error(errorMessage);
404             throw new UnsupportedOperationException(errorMessage);
405         }
406
407         Log.info("Adding elan interface: " + interfaceName);
408         NetvirtUtils.createElanInterface(elanName, interfaceName, EtreeInterfaceType.Root, false, tx);
409         return interfaceName;
410     }
411
412     private void createVpnInterface(String vpnName,
413             org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni,
414             IpUni ipUni, String interfaceName, String elanName, WriteTransaction tx) {
415
416         Log.info("Adding vpn interface: " + interfaceName);
417
418         NetvirtVpnUtils.createUpdateVpnInterface(vpnName, interfaceName, ipUni.getIpAddress(),
419                 uni.getMacAddress().getValue(), true, null, elanName, tx);
420
421         Log.info("Finished working on vpn instance {} interface () ", vpnName, interfaceName);
422     }
423
424     private void createDirectSubnet(Uni uni, IpUni ipUni) {
425         IpPrefix uniIpPrefix = ipUni.getIpAddress();
426         String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
427         IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
428         InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
429                 ipUni.getIpUniId(), subnetPrefix);
430         SubnetBuilder subnet = new SubnetBuilder();
431         subnet.setUniId(uni.getUniId());
432         subnet.setIpUniId(ipUni.getIpUniId());
433         subnet.setSubnet(subnetPrefix);
434         MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, subnet.build());
435     }
436
437     private void removeInterfaces(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn ipvcVpn, Uni uniInService, IpUni ipUni,
438             WriteTransaction tx) {
439         String uniId = uniInService.getUniId().getValue();
440         String vpnName = ipvcVpn.getVpnId();
441         VpnElans vpnElans = MefServicesUtils.findVpnElanForNetwork(new Identifier45(uniId), ipUni.getIpUniId(),
442                 ipvcVpn);
443         if (vpnElans == null) {
444             Log.error("Trying to remome non-operational vpn/elan for Uni {} Ip-UNi {}", uniId, ipUni.getIpUniId());
445             return;
446         }
447
448         NetvirtVpnUtils.removeVpnInterfaceAdjacencies(dataBroker, vpnName, vpnElans.getElanPort());
449         // TODO : change to listener
450         NetvirtUtils.safeSleep();
451         uniQosManager.unMapUniPortBandwidthLimits(uniId, vpnElans.getElanPort());
452         removeElan(vpnElans, uniId, ipUni, tx);
453         // record Uni bw limits
454         removeVpnInterface(vpnName, vpnElans, uniId, ipUni, tx);
455         MefServicesUtils.removeOperIpvcElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), uniInService.getUniId(),
456                 uniInService.getIpUniId(), vpnElans.getElanId(), vpnElans.getElanPort());
457     }
458
459     private void removeElan(VpnElans vpnElans, String uniId, IpUni ipUni, WriteTransaction tx) {
460         Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : 0;
461         Log.info("Removing trunk interface for uni {} vlan: {}", uniId, vlan);
462         uniPortManager.removeCeVlan(uniId, vlan);
463
464         String elanName = vpnElans.getElanId();
465         String interfaceName = vpnElans.getElanPort();
466
467         Log.info("Removing elan instance {} and interface {}: ", elanName, interfaceName);
468         NetvirtVpnUtils.unregisterDirectSubnetForVpn(dataBroker, new Uuid(elanName));
469         NetvirtUtils.deleteElanInterface(interfaceName, tx);
470         NetvirtUtils.deleteElanInstance(elanName, tx);
471     }
472
473     private void removeVpnInterface(String vpnName, VpnElans vpnElans, String uniId, IpUni ipUni, WriteTransaction tx) {
474         String interfaceName = vpnElans.getElanPort();
475         Log.info("Removing vpn interface: " + interfaceName);
476         NetvirtVpnUtils.removeVpnInterface(interfaceName, tx);
477         NetvirtVpnUtils.removeVpnPortFixedIp(vpnName, ipUni.getIpAddress(), tx);
478         Log.info("Finished working on vpn instance: " + vpnName);
479     }
480
481     private void removeDirectSubnet(Uni uni, IpUni ipUni) {
482         IpPrefix uniIpPrefix = ipUni.getIpAddress();
483         String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
484         IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
485         InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
486                 ipUni.getIpUniId(), subnetPrefix);
487         MdsalUtils.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
488     }
489
490     private void updateQos(List<Uni> uniToUpdate) {
491         uniToUpdate.forEach(u -> uniQosManager.setUniBandwidthLimits(u.getUniId()));
492     }
493
494     private void updateUnis(List<Uni> uniToUpdate) {
495         uniToUpdate.forEach(u -> uniQosManager.updateUni(u.getUniId(), u.getIngressBwProfile()));
496         updateQos(uniToUpdate);
497     }
498 }