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