Reconnect port support
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / SubnetListener.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.Collections;
12 import java.util.List;
13 import java.util.stream.Collectors;
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.NotificationPublishService;
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;
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.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.MefServices;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.IpvcChoice;
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;
29 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;
30 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;
31 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
33 import org.opendaylight.yangtools.concepts.ListenerRegistration;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.common.base.Optional;
39
40 public class SubnetListener extends UnimgrDataTreeChangeListener<Subnet> implements ISubnetManager {
41     private static final Logger Log = LoggerFactory.getLogger(SubnetListener.class);
42     private ListenerRegistration<SubnetListener> subnetListenerRegistration;
43     private final NotificationPublishService notificationPublishService;
44     private final IGwMacListener gwMacListener;
45     private final int waitForElanInterval;
46
47     public SubnetListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
48             final IGwMacListener gwMacListener, int sleepInterval) {
49         super(dataBroker);
50         this.notificationPublishService = notPublishService;
51         this.gwMacListener = gwMacListener;
52         this.waitForElanInterval = sleepInterval;
53         registerListener();
54     }
55
56     public void registerListener() {
57         try {
58             final DataTreeIdentifier<Subnet> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
59                     MefInterfaceUtils.getSubnetsInstanceIdentifier());
60             subnetListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
61             Log.info("IpvcDataTreeChangeListener created and registered");
62         } catch (final Exception e) {
63             Log.error("Ipvc DataChange listener registration failed !", e);
64             throw new IllegalStateException("Ipvc registration Listener failed.", e);
65         }
66     }
67
68     @Override
69     public void close() throws Exception {
70         subnetListenerRegistration.close();
71     }
72
73     @Override
74     public void add(DataTreeModification<Subnet> newDataObject) {
75         if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
76             Log.info("subnet {} created", newDataObject.getRootNode().getIdentifier());
77         }
78
79         createNetwork(newDataObject);
80     }
81
82     @Override
83     public void remove(DataTreeModification<Subnet> removedDataObject) {
84         if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
85             Log.info("subnet {} deleted", removedDataObject.getRootNode().getIdentifier());
86         }
87         removeNetwork(removedDataObject);
88     }
89
90     @Override
91     public void update(DataTreeModification<Subnet> modifiedDataObject) {
92         if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
93             Log.info("subnet {} updated", modifiedDataObject.getRootNode().getIdentifier());
94             Log.info("process as delete / create");
95             removeNetwork(modifiedDataObject);
96             createNetwork(modifiedDataObject);
97         }
98     }
99
100     @Override
101     public void assignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
102         InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
103         Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
104         Subnets allSubnets = allList.isPresent() ? allList.get() : null;
105         List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
106                 : Collections.emptyList();
107         List<Subnet> ipUniSubnets = allSubnet.stream()
108                 .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
109         // recreate networks on restart
110         ipUniSubnets.forEach(s -> createNetwork(s, uniId, ipUniId));
111     }
112
113     @Override
114     public void unAssignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
115         InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
116         Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
117         Subnets allSubnets = allList.isPresent() ? allList.get() : null;
118         List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
119                 : Collections.emptyList();
120         List<Subnet> ipUniSubnets = allSubnet.stream()
121                 .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
122         ipUniSubnets.forEach(s -> removeNetwork(s, uniId, ipUniId, ipvcId));
123     }
124
125     private void createNetwork(DataTreeModification<Subnet> newDataObject) {
126         Subnet newSubnet = newDataObject.getRootNode().getDataAfter();
127
128         Identifier45 nwUniId = newSubnet.getUniId();
129         Identifier45 nwIpUniId = newSubnet.getIpUniId();
130
131         createNetwork(newSubnet, nwUniId, nwIpUniId);
132     }
133
134     private void createNetwork(Subnet newSubnet, Identifier45 nwUniId, Identifier45 nwIpUniId) {
135         String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
136
137         InstanceIdentifier<Ipvc> ipvcId = findService(nwUniId, nwIpUniId);
138         if (ipvcId == null) {
139             Log.info("Subnet Uni {} IpUNI {} is not assosiated to service", nwUniId, nwIpUniId);
140             return;
141         }
142         IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
143         if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
144             Log.error("Subnet Uni {} IpUNI {} is not operational", nwUniId, nwIpUniId);
145             return;
146         }
147         VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(newSubnet, ipvcVpn);
148         if (vpnElan == null) {
149             Log.error("Subnet Uni {} IpUNI {} for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
150             return;
151         }
152         if (MefServicesUtils.findNetwork(newSubnet, vpnElan) != null) {
153             Log.info("Network {} exists already", subnetStr);
154             return;
155         }
156
157         String vpnId = ipvcVpn.getVpnId();
158         synchronized (vpnId.intern()) {
159             if (newSubnet.getGateway() == null) {
160                 checkCreateDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
161             } else {
162                 createNonDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
163             }
164         }
165         MefServicesUtils.addOperIpvcVpnElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), nwUniId, nwIpUniId,
166                 vpnElan.getElanId(), vpnElan.getElanPort(), Collections.singletonList(subnetStr));
167
168     }
169
170     private void createNonDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
171             VpnElans vpnElan) {
172         if (newSubnet.getGateway() == null) {
173             return;
174         }
175
176         Identifier45 nwUniId = newSubnet.getUniId();
177         Identifier45 nwIpUniId = newSubnet.getIpUniId();
178         String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
179
180         IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
181         if (ipUni == null) {
182             Log.error("Uni {} IpUni {}  for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
183             return;
184         }
185
186         String srcTpAddressStr = NetvirtVpnUtils
187                 .getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
188         IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
189         String subnet = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
190         gwMacListener.resolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress, newSubnet.getGateway(),
191                 subnet);
192     }
193
194     private void checkCreateDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
195             VpnElans vpnElan) {
196         if (newSubnet.getGateway() != null) {
197             return;
198         }
199
200         org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni operUni = MefInterfaceUtils
201                 .getUni(dataBroker, newSubnet.getUniId().getValue(), LogicalDatastoreType.OPERATIONAL);
202         if (operUni == null) {
203             Log.error("Uni {} for network {} is not operational", newSubnet.getUniId(), newSubnet.getSubnet());
204             return;
205         }
206         String portMacAddress = operUni.getMacAddress().getValue();
207
208         NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
209                 vpnElan.getElanId(), newSubnet.getSubnet(), vpnElan.getElanPort(), portMacAddress, waitForElanInterval);
210
211     }
212
213     private void removeNetwork(DataTreeModification<Subnet> deletedDataObject) {
214         Subnet deletedSubnet = deletedDataObject.getRootNode().getDataBefore();
215         Identifier45 dlUniId = deletedSubnet.getUniId();
216         Identifier45 dlIpUniId = deletedSubnet.getIpUniId();
217         InstanceIdentifier<Ipvc> ipvcId = findService(dlUniId, dlIpUniId);
218         if (ipvcId == null) {
219             Log.info("Subnet Uni {} IpUNI {} for deleted network is not assosiated to service", dlUniId, dlIpUniId);
220             return;
221         }
222         removeNetwork(deletedSubnet, dlUniId, dlIpUniId, ipvcId);
223     }
224
225     private void removeNetwork(Subnet dlSubnet, Identifier45 dlUniId, Identifier45 dlIpUniId,
226             InstanceIdentifier<Ipvc> ipvcId) {
227         String subnetStr = NetvirtVpnUtils.ipPrefixToString(dlSubnet.getSubnet());
228         IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
229         if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
230             Log.error("Subnet Uni {} IpUNI {} is not operational", dlUniId, dlIpUniId);
231             return;
232         }
233         VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(dlSubnet, ipvcVpn);
234         if (vpnElan == null) {
235             Log.error("Trying to remove non-operational network {}", subnetStr);
236             return;
237         }
238         if (MefServicesUtils.findNetwork(dlSubnet, vpnElan) == null) {
239             Log.error("Trying to remove non-operational network {}", subnetStr);
240             return;
241         }
242
243         String vpnId = ipvcVpn.getVpnId();
244         synchronized (vpnId.intern()) {
245             if (dlSubnet.getGateway() == null) {
246                 removeDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
247             } else {
248                 removeNonDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
249             }
250         }
251         MefServicesUtils.removeOperIpvcSubnet(dataBroker, ipvcId, ipvcVpn.getVpnId(), dlUniId, dlIpUniId,
252                 vpnElan.getElanId(), vpnElan.getElanPort(), subnetStr);
253     }
254
255     private void removeDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
256         if (deletedSubnet.getGateway() != null) {
257             return;
258         }
259
260         String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
261         VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
262         if (vpnElan == null) {
263             Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
264             return;
265         }
266
267         NetvirtVpnUtils.removeDirectSubnetFromVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
268                 vpnElan.getElanId(), vpnElan.getElanPort());
269
270     }
271
272     private void removeNonDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
273         if (deletedSubnet.getGateway() == null) {
274             return;
275         }
276
277         Identifier45 nwUniId = deletedSubnet.getUniId();
278         Identifier45 nwIpUniId = deletedSubnet.getIpUniId();
279         String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
280         VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
281         if (vpnElan == null) {
282             Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
283             return;
284         }
285
286         IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
287         if (ipUni == null) {
288             Log.error("Uni {} IpUni {}  for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
289             return;
290         }
291
292         String srcTpAddressStr = NetvirtVpnUtils
293                 .getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
294         IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
295         String subnet = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
296         gwMacListener.unResolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress,
297                 deletedSubnet.getGateway(), subnet);
298
299         NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getSubnet());
300         NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getGateway());
301     }
302
303     private InstanceIdentifier<Ipvc> findService(Identifier45 uniId, Identifier45 ipUniId) {
304         InstanceIdentifier<MefServices> path = MefServicesUtils.getMefServicesInstanceIdentifier();
305         Optional<MefServices> mefServices = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
306         if (!mefServices.isPresent() || mefServices.get() == null) {
307             Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);
308             return null;
309         }
310         for (MefService service : mefServices.get().getMefService()) {
311             if (service.getMefServiceChoice() instanceof IpvcChoice) {
312                 Ipvc ipvc = ((IpvcChoice) service.getMefServiceChoice()).getIpvc();
313                 if (ipvc.getUnis() == null || ipvc.getUnis().getUni() == null) {
314                     continue;
315                 }
316                 List<Uni> unis = ipvc.getUnis().getUni();
317                 for (Uni uni : unis) {
318                     if (uni.getUniId().equals(uniId) && uni.getIpUniId().equals(ipUniId)) {
319                         Log.info("Find service {} for uni {} ipuni {}", service.getSvcId(), uniId, ipUniId);
320                         return MefServicesUtils.getIpvcInstanceIdentifier(service.getSvcId());
321                     }
322                 }
323             }
324         }
325         Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);
326         return null;
327     }
328 }