refactoring to support delete\update of servics.
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / NodeConnectorListener.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 import java.util.concurrent.ExecutionException;
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.controller.md.sal.common.api.data.TransactionCommitFailedException;
21 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
22 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
23 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
24 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
25 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayersBuilder;
26 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.LinksBuilder;
27 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
28 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkBuilder;
29 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.Interface;
30 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceBuilder;
31 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfigBuilder;
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 import com.google.common.util.concurrent.CheckedFuture;
45
46 public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapableNodeConnector> {
47
48     private static final Logger log = LoggerFactory.getLogger(NodeConnectorListener.class);
49     private static boolean generateMac = false;
50     private final UniPortManager uniPortManager;
51     private ListenerRegistration<NodeConnectorListener> nodeConnectorListenerRegistration;
52
53     public NodeConnectorListener(final DataBroker dataBroker, final UniPortManager uniPortManager, final boolean generateMac) {
54         super(dataBroker);
55         this.uniPortManager = uniPortManager;
56         NodeConnectorListener.generateMac = generateMac;
57         registerListener();
58     }
59
60     public void registerListener() {
61         try {
62             final DataTreeIdentifier<FlowCapableNodeConnector> dataTreeIid = new DataTreeIdentifier<>(
63                     LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
64             nodeConnectorListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
65             log.info("NodeConnectorListener created and registered");
66
67             configIntegrationBridge();
68         } catch (final Exception e) {
69             log.error("Node connector listener registration failed !", e);
70             throw new IllegalStateException("Node connector listener registration failed.", e);
71         }
72     }
73
74     @SuppressWarnings("deprecation")
75     private InstanceIdentifier<FlowCapableNodeConnector> getInstanceIdentifier() {
76         return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
77                 .augmentation(FlowCapableNodeConnector.class);
78     }
79
80     @Override
81     public void close() throws Exception {
82         nodeConnectorListenerRegistration.close();
83     }
84
85     @Override
86     public void add(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
87         if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
88             log.info("node connector {} created", newDataObject.getRootNode().getIdentifier());
89             addFlowCapableNodeConnector(newDataObject);
90         }
91     }
92
93     @Override
94     public void remove(DataTreeModification<FlowCapableNodeConnector> removedDataObject) {
95         if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
96             log.info("node connector {} deleted", removedDataObject.getRootNode().getIdentifier());
97             removeFlowCapableNodeConnector(removedDataObject);
98         }
99     }
100
101     @Override
102     public void update(DataTreeModification<FlowCapableNodeConnector> modifiedDataObject) {
103         if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
104             log.info("node connector {} updated", modifiedDataObject.getRootNode().getIdentifier());
105             updateFlowCapableNodeConnector(modifiedDataObject);
106         }
107     }
108
109     private void addFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
110         try {
111             FlowCapableNodeConnector data = newDataObject.getRootNode().getDataAfter();
112
113             String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(newDataObject);
114
115             handleNodeConnectorAdded(dataBroker, dpnFromNodeConnectorId, data);
116         } catch (final Exception e) {
117             log.error("Add node connector failed !", e);
118         }
119     }
120
121     private void removeFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> removedDataObject) {
122         try {
123             FlowCapableNodeConnector data = removedDataObject.getRootNode().getDataBefore();
124
125             String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(removedDataObject);
126
127             handleNodeConnectorRemoved(dataBroker, dpnFromNodeConnectorId, data);
128         } catch (final Exception e) {
129             log.error("Remove node connector failed !", e);
130         }
131     }
132
133     private void updateFlowCapableNodeConnector(DataTreeModification<FlowCapableNodeConnector> modifiedDataObject) {
134         try {
135             FlowCapableNodeConnector original = modifiedDataObject.getRootNode().getDataBefore();
136             FlowCapableNodeConnector update = modifiedDataObject.getRootNode().getDataAfter();
137
138             String dpnFromNodeConnectorId = getDpnIdFromNodeConnector(modifiedDataObject);
139
140             handleNodeConnectorUpdated(dataBroker, dpnFromNodeConnectorId, original, update);
141         } catch (final Exception e) {
142             log.error("Update node connector failed !", e);
143         }
144     }
145
146     @SuppressWarnings("deprecation")
147     private String getDpnIdFromNodeConnector(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
148         InstanceIdentifier<FlowCapableNodeConnector> key = newDataObject.getRootPath().getRootIdentifier();
149         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
150
151         String dpnFromNodeConnectorId = getDpnFromNodeConnectorId(nodeConnectorId);
152         return dpnFromNodeConnectorId;
153     }
154
155     @SuppressWarnings("deprecation")
156     private static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
157         /*
158          * NodeConnectorId is of form 'openflow:dpnid:portnum'
159          */
160         String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
161         return split[1];
162     }
163
164     private void handleNodeConnectorAdded(DataBroker dataBroker, String dpnId, FlowCapableNodeConnector nodeConnector) {
165
166         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
167
168         log.info("Adding mef uni/device interface {} with device {}", nodeConnector.getName(), dpnId);
169
170         String uniName = MefInterfaceUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
171         InstanceIdentifier<Interface> interfacePath = MefInterfaceUtils.getDeviceInterfaceInstanceIdentifier(dpnId,
172                 uniName);
173         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
174         interfaceBuilder.setPhy(new Identifier45(uniName));
175         Interface deviceInterface = interfaceBuilder.build();
176         tx.merge(LogicalDatastoreType.OPERATIONAL, interfacePath, deviceInterface, true);
177
178         InstanceIdentifier<Uni> uniPath = MefInterfaceUtils.getUniInstanceIdentifier(uniName);
179         UniBuilder uniBuilder = new UniBuilder();
180         uniBuilder.setUniId(new Identifier45(uniName));
181         uniBuilder.setMacAddress(nodeConnector.getHardwareAddress());
182
183         PhysicalLayersBuilder physicalLayersBuilder = new PhysicalLayersBuilder();
184         LinksBuilder linksBuilder = new LinksBuilder();
185         List<Link> links = new ArrayList<>();
186         LinkBuilder linkBuilder = new LinkBuilder();
187         linkBuilder.setDevice(new Identifier45(dpnId));
188         linkBuilder.setInterface(uniName);
189         links.add(linkBuilder.build());
190         linksBuilder.setLink(links);
191         physicalLayersBuilder.setLinks(linksBuilder.build());
192         uniBuilder.setPhysicalLayers(physicalLayersBuilder.build());
193         Uni uni = uniBuilder.build();
194         tx.merge(LogicalDatastoreType.OPERATIONAL, uniPath, uni, true);
195
196         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
197         try {
198             futures.get();
199         } catch (InterruptedException | ExecutionException e) {
200             log.error("Error writing to datastore (path, data) : ({}, {}), ({}, {})", interfacePath, deviceInterface,
201                     uniPath, uni);
202             throw new RuntimeException(e.getMessage());
203         }
204
205         // Reply UNI port configuration
206         uniPortManager.updateOperUni(uni.getUniId().getValue());
207     }
208
209     private void handleNodeConnectorRemoved(DataBroker dataBroker, String dpnId,
210             FlowCapableNodeConnector nodeConnector) {
211
212         String uniName = MefInterfaceUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
213         InstanceIdentifier<Interface> interfacePath = MefInterfaceUtils.getDeviceInterfaceInstanceIdentifier(dpnId,
214                 uniName);
215         if (MefInterfaceUtils.getInterface(dataBroker, dpnId, uniName, LogicalDatastoreType.OPERATIONAL) != null) {
216             MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, interfacePath);
217         }
218
219         // Reply UNI port configuration
220         uniPortManager.removeUniPorts(uniName);
221         InstanceIdentifier<Uni> uniPath = MefInterfaceUtils.getUniInstanceIdentifier(uniName);
222         if (MefInterfaceUtils.getUni(dataBroker, uniName, LogicalDatastoreType.OPERATIONAL) != null) {
223             MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, uniPath);
224         }
225     }
226
227     private void handleNodeConnectorUpdated(DataBroker dataBroker, String dpnFromNodeConnectorId,
228             FlowCapableNodeConnector original, FlowCapableNodeConnector update) {
229
230     }
231
232     private void configIntegrationBridge() {
233         if (generateMac == true) {// default for netvirt
234             return;
235         }
236
237         ElanConfigBuilder elanConfigBuilder = new ElanConfigBuilder();
238         elanConfigBuilder.setIntBridgeGenMac(false);
239         InstanceIdentifier<ElanConfig> id = InstanceIdentifier.builder(ElanConfig.class).build();
240
241         MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, id, elanConfigBuilder.build());
242     }
243 }