Federation plugin
[netvirt.git] / vpnservice / federation-plugin / impl / src / main / java / org / opendaylight / netvirt / federation / plugin / FederationPluginUtils.java
1 /*
2  * Copyright (c) 2017 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.netvirt.federation.plugin;
10
11 import com.google.common.collect.ImmutableList;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.UncheckedExecutionException;
14
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.apache.commons.lang3.tuple.Pair;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
24 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
25 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
29 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
30 import org.opendaylight.federation.service.api.message.BindingAwareJsonConverter;
31 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
32 import org.opendaylight.genius.itm.globals.ITMConstants;
33 import org.opendaylight.netvirt.federation.plugin.creators.FederationPluginCreatorRegistry;
34 import org.opendaylight.netvirt.federation.plugin.creators.FederationPluginModificationCreator;
35 import org.opendaylight.netvirt.federation.plugin.filters.FederationPluginFilter;
36 import org.opendaylight.netvirt.federation.plugin.filters.FederationPluginFilterRegistry;
37 import org.opendaylight.netvirt.federation.plugin.filters.FilterResult;
38 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationPluginIdentifier;
39 import org.opendaylight.netvirt.federation.plugin.identifiers.FederationPluginIdentifierRegistry;
40 import org.opendaylight.netvirt.federation.plugin.transformers.FederationPluginTransformer;
41 import org.opendaylight.netvirt.federation.plugin.transformers.FederationPluginTransformerRegistry;
42 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
43 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
44 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfacesBuilder;
45 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
46 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
47 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableStatisticsGatheringStatus;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableStatisticsGatheringStatusBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternalBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfStackedVlan;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfStackedVlanBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeatures;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupFeaturesBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeatures;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.NodeMeterFeaturesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTag;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagNameBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstancesBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfacesBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMapBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.FederationGenerations;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfo;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfoBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.manager.rev170219.federation.generations.RemoteSiteGenerationInfoKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.ElanShadowProperties;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.ElanShadowPropertiesBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.IfShadowProperties;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.IfShadowPropertiesBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.InventoryNodeShadowProperties;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.InventoryNodeShadowPropertiesBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.TopologyNodeShadowProperties;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.TopologyNodeShadowPropertiesBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.VpnShadowProperties;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.federation.plugin.rev170219.VpnShadowPropertiesBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OpState;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OpStateBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
130 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
131 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
132 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
133 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
134 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
135 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
136 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
137 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
138 import org.opendaylight.yangtools.yang.binding.DataObject;
139 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
140 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
141 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
142 import org.slf4j.Logger;
143 import org.slf4j.LoggerFactory;
144
145 public class FederationPluginUtils {
146     private static final Logger LOG = LoggerFactory.getLogger(FederationPluginUtils.class);
147
148     private static final List<String> SORTED_LISTENER_KEYS =
149
150             ImmutableList.of(FederationPluginConstants.TOPOLOGY_NODE_CONFIG_KEY, //
151                     FederationPluginConstants.TOPOLOGY_NODE_OPER_KEY, //
152                     FederationPluginConstants.INVENTORY_NODE_CONFIG_KEY, //
153                     FederationPluginConstants.INVENTORY_NODE_OPER_KEY, //
154                     FederationPluginConstants.IETF_INTERFACE_KEY, //
155                     FederationPluginConstants.ELAN_INTERFACE_KEY, //
156                     FederationPluginConstants.VPN_INTERFACE_KEY);
157
158
159     private static volatile boolean yangModulesInitialized = false;
160
161     private FederationPluginUtils() {
162
163     }
164
165     @SuppressWarnings("checkstyle:IllegalCatch")
166     public static synchronized void initYangModules() {
167         if (yangModulesInitialized) {
168             return;
169         }
170
171         ArrayList<YangModuleInfo> moduleInfos = new ArrayList<>();
172         try {
173             moduleInfos.add(BindingReflections.getModuleInfo(Topology.class));
174             moduleInfos.add(BindingReflections.getModuleInfo(OvsdbNodeAugmentation.class));
175             moduleInfos.add(BindingReflections.getModuleInfo(Nodes.class));
176             moduleInfos.add(BindingReflections.getModuleInfo(FlowCapableNodeConnector.class));
177             moduleInfos.add(BindingReflections.getModuleInfo(FlowCapableNodeConnectorStatisticsData.class));
178             moduleInfos.add(BindingReflections.getModuleInfo(NodeMeterFeatures.class));
179             moduleInfos.add(BindingReflections.getModuleInfo(NodeGroupFeatures.class));
180             moduleInfos.add(BindingReflections.getModuleInfo(Interfaces.class));
181             moduleInfos.add(BindingReflections.getModuleInfo(IfExternal.class));
182             moduleInfos.add(BindingReflections.getModuleInfo(InterfaceAcl.class));
183             moduleInfos.add(BindingReflections.getModuleInfo(ParentRefs.class));
184             moduleInfos.add(BindingReflections.getModuleInfo(IfL2vlan.class));
185             moduleInfos.add(BindingReflections.getModuleInfo(IfStackedVlan.class));
186             moduleInfos.add(BindingReflections.getModuleInfo(ElanInterfaces.class));
187             moduleInfos.add(BindingReflections.getModuleInfo(EtreeInterface.class));
188             moduleInfos.add(BindingReflections.getModuleInfo(EtreeInstance.class));
189             moduleInfos.add(BindingReflections.getModuleInfo(EtreeLeafTagName.class));
190             moduleInfos.add(BindingReflections.getModuleInfo(VpnInterfaces.class));
191             moduleInfos.add(BindingReflections.getModuleInfo(Adjacencies.class));
192             moduleInfos.add(BindingReflections.getModuleInfo(SubnetRoute.class));
193             moduleInfos.add(BindingReflections.getModuleInfo(OpState.class));
194             moduleInfos.add(BindingReflections.getModuleInfo(TopologyNodeShadowProperties.class));
195             moduleInfos.add(BindingReflections.getModuleInfo(ElanShadowProperties.class));
196             moduleInfos.add(BindingReflections.getModuleInfo(IfShadowProperties.class));
197             moduleInfos.add(BindingReflections.getModuleInfo(InventoryNodeShadowProperties.class));
198             moduleInfos.add(BindingReflections.getModuleInfo(VpnShadowProperties.class));
199             BindingAwareJsonConverter.init(moduleInfos);
200             bug7420Workaround(5);
201             yangModulesInitialized = true;
202             LOG.info("Finished initializing BindingReflections modules");
203         } catch (Exception e) {
204             LOG.error("Failed to initialized MessageSeralizationUtils", e);
205         }
206     }
207
208     public static List<String> getOrderedListenerKeys() {
209         return SORTED_LISTENER_KEYS;
210     }
211
212     public static LogicalDatastoreType getListenerDatastoreType(String listenerKey) {
213         return FederationPluginIdentifierRegistry.getDatastoreType(listenerKey);
214     }
215
216     public static InstanceIdentifier<? extends DataObject> getInstanceIdentifier(String listenerKey) {
217         FederationPluginIdentifier<? extends DataObject, ? extends DataObject, ? extends DataObject>
218             identifierHandler = FederationPluginIdentifierRegistry.getIdentifier(listenerKey);
219         if (identifierHandler == null) {
220             LOG.error("Failed to get identifier for {}", listenerKey);
221             return null;
222         }
223
224         return identifierHandler.getInstanceIdentifier();
225     }
226
227     public static InstanceIdentifier<? extends DataObject> getParentInstanceIdentifier(String listenerKey) {
228         FederationPluginIdentifier<? extends DataObject, ? extends DataObject, ? extends DataObject>
229             identifierHandler = FederationPluginIdentifierRegistry.getIdentifier(listenerKey);
230         if (identifierHandler == null) {
231             LOG.error("Failed to get identifier for {}", listenerKey);
232             return null;
233         }
234
235         return identifierHandler.getParentInstanceIdentifier();
236     }
237
238     public static InstanceIdentifier<? extends DataObject> getSubtreeInstanceIdentifier(String listenerKey) {
239         FederationPluginIdentifier<? extends DataObject, ? extends DataObject, ? extends DataObject>
240             identifierHandler = FederationPluginIdentifierRegistry.getIdentifier(listenerKey);
241         if (identifierHandler == null) {
242             LOG.error("Failed to get identifier for {}", listenerKey);
243             return null;
244         }
245
246         return identifierHandler.getSubtreeInstanceIdentifier();
247     }
248
249     public static <T extends DataObject> String getClassListener(Class<T> clazz, LogicalDatastoreType datastoreType) {
250         return FederationPluginIdentifierRegistry.getListenerKey(datastoreType, clazz);
251     }
252
253     @SuppressWarnings("unchecked")
254     public static <T extends DataObject, S extends DataObject> FilterResult applyEgressFilter(String listenerKey,
255             T dataObject, FederatedMappings federatedMappings,
256             PendingModificationCache<DataTreeModification<?>> pendingModifications,
257             DataTreeModification<T> dataTreeModification) {
258         FederationPluginFilter<T, S> filter = (FederationPluginFilter<T, S>) FederationPluginFilterRegistry
259                 .getFilter(listenerKey);
260         if (filter == null) {
261             LOG.error("Filter not found for key {}", listenerKey);
262             return FilterResult.DENY;
263         }
264
265         return filter.applyEgressFilter(dataObject, federatedMappings, pendingModifications, dataTreeModification);
266     }
267
268     @SuppressWarnings("unchecked")
269     public static <T extends DataObject, R extends DataObject> FilterResult applyIngressFilter(String listenerKey,
270             R dataObject) {
271         FederationPluginFilter<T, R> filter = (FederationPluginFilter<T, R>) FederationPluginFilterRegistry
272                 .getFilter(listenerKey);
273         if (filter == null) {
274             LOG.error("Filter not found for key {}", listenerKey);
275             return FilterResult.DENY;
276         }
277
278         return filter.applyIngressFilter(listenerKey, dataObject);
279     }
280
281     @SuppressWarnings("unchecked")
282     public static <T extends DataObject, S extends DataObject> Pair<InstanceIdentifier<T>, T>
283             applyIngressTransformation(String listenerKey, S dataObject, ModificationType modificationType,
284                     int generationNumber, String remoteIp) {
285         FederationPluginTransformer<T, S> transformer =
286                 (FederationPluginTransformer<T, S>) FederationPluginTransformerRegistry.getTransformer(listenerKey);
287         if (transformer == null) {
288             LOG.error("Transformer not found for key {}", listenerKey);
289             return null;
290         }
291
292         return transformer.applyIngressTransformation(dataObject, modificationType, generationNumber, remoteIp);
293     }
294
295     @SuppressWarnings("unchecked")
296     public static <T extends DataObject, S extends DataObject> S applyEgressTransformation(String listenerKey,
297             T dataObject, FederatedMappings federatedMappings,
298             PendingModificationCache<DataTreeModification<?>> pendingModifications) {
299         FederationPluginTransformer<T, S> transformer =
300                 (FederationPluginTransformer<T, S>) FederationPluginTransformerRegistry.getTransformer(listenerKey);
301         if (transformer == null) {
302             LOG.error("Transformer not found for key {} ", listenerKey);
303             return null;
304         }
305
306         return transformer.applyEgressTransformation(dataObject, federatedMappings, pendingModifications);
307     }
308
309     @SuppressWarnings("unchecked")
310     public static <T extends DataObject, S extends DataObject> Collection<DataTreeModification<T>> createModifications(
311             String listenerKey, S parentDataObject) {
312         FederationPluginModificationCreator<T, S> creator =
313                 (FederationPluginModificationCreator<T, S>) FederationPluginCreatorRegistry.getCreator(listenerKey);
314         if (creator == null) {
315             LOG.error("Modification creator not found for key {} ", listenerKey);
316             return null;
317         }
318
319         return creator.createDataTreeModifications(parentDataObject);
320     }
321
322     public static <T extends DataObject> T getDataObjectFromModification(DataTreeModification<T> dataTreeModification) {
323         DataObjectModification<T> dataObjectModification = dataTreeModification.getRootNode();
324         switch (dataObjectModification.getModificationType()) {
325             case WRITE:
326             case SUBTREE_MODIFIED:
327                 return dataObjectModification.getDataAfter();
328             case DELETE:
329                 return dataObjectModification.getDataBefore();
330             default:
331                 break;
332         }
333
334         return null;
335     }
336
337     /**
338      * Discover if interface is a DHCP port. Should be replaced with type
339      * definition in ietf-model
340      *
341      * @param dataBroker
342      *            - the databroker.
343      * @param interfaceName
344      *            - the interface name .
345      * @return if true
346      */
347     public static boolean isDhcpInterface(DataBroker dataBroker, String interfaceName) {
348         Uuid portId;
349
350         try {
351             portId = new Uuid(interfaceName);
352         } catch (IllegalArgumentException e) {
353             return false;
354         }
355
356         InstanceIdentifier<Port> inst = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class,
357                 new PortKey(portId));
358         Port port;
359         try {
360             port = SingleTransactionDataBroker.syncRead(dataBroker, LogicalDatastoreType.CONFIGURATION, inst);
361             return port != null && NeutronConstants.DEVICE_OWNER_DHCP.equals(port.getDeviceOwner());
362         } catch (ReadFailedException e) {
363             LOG.debug("Interface {} is not associated with any neutron port", interfaceName);
364             return false;
365         }
366     }
367
368     public static RemoteSiteGenerationInfo getGenerationInfoForRemoteSite(DataBroker broker, String remoteIp) {
369         InstanceIdentifier<RemoteSiteGenerationInfo> remoteSiteGenerationNumber = InstanceIdentifier
370                 .create(FederationGenerations.class)
371                 .child(RemoteSiteGenerationInfo.class, new RemoteSiteGenerationInfoKey(remoteIp));
372         try {
373             return SingleTransactionDataBroker.syncRead(broker,
374                     LogicalDatastoreType.CONFIGURATION, remoteSiteGenerationNumber);
375         } catch (ReadFailedException e) {
376             LOG.debug("No generation info found for remote site {}", remoteIp);
377             return null;
378         }
379     }
380
381     public static String getSubnetIdFromVpnInterface(VpnInterface vpnInterface) {
382         Adjacencies adjacencies = vpnInterface.getAugmentation(Adjacencies.class);
383         if (adjacencies == null) {
384             return null;
385         }
386
387         for (Adjacency adjacency : adjacencies.getAdjacency()) {
388             if (adjacency.isPrimaryAdjacency() != null && adjacency.isPrimaryAdjacency()) {
389                 Uuid subnetId = adjacency.getSubnetId();
390                 return subnetId != null ? subnetId.getValue() : null;
391             }
392         }
393
394         return null;
395     }
396
397     @SuppressWarnings("unchecked")
398     public static <T extends DataObject, S extends DataObject> S getAssociatedDataObjectFromPending(String listenerKey,
399             T dataObject, PendingModificationCache<DataTreeModification<?>> pendingModifications) {
400         S associatedObject = null;
401         Map<String, Collection<DataTreeModification<?>>> modifications = pendingModifications.get(dataObject);
402
403         if (modifications != null) {
404             Collection<DataTreeModification<?>> listenerModifications = modifications.get(listenerKey);
405             if (listenerModifications != null && !listenerModifications.isEmpty()) {
406                 DataTreeModification<S> modification = (DataTreeModification<S>) listenerModifications.iterator()
407                         .next();
408                 associatedObject = modification.getRootNode().getDataAfter();
409                 if (associatedObject == null) {
410                     associatedObject = modification.getRootNode().getDataBefore();
411                 }
412             }
413         }
414
415         return associatedObject;
416     }
417
418     public static boolean isPortNameFiltered(String portName) {
419         return portName.startsWith(FederationPluginConstants.TUNNEL_PREFIX)
420                 || portName.startsWith(ITMConstants.DEFAULT_BRIDGE_NAME);
421     }
422
423     public static boolean updateGenerationInfo(DataBroker broker, String remoteIp, int generationNumber) {
424         if (remoteIp == null) {
425             LOG.error("Cannot write generation number - remote IP is null");
426             return false;
427         }
428
429         LOG.info("Writing generation number {} for remote site {}", remoteIp, generationNumber);
430         WriteTransaction putTx = broker.newWriteOnlyTransaction();
431         RemoteSiteGenerationInfoBuilder builder = new RemoteSiteGenerationInfoBuilder();
432         builder.setRemoteIp(remoteIp);
433         builder.setGenerationNumber(generationNumber);
434         InstanceIdentifier<RemoteSiteGenerationInfo> path = InstanceIdentifier.create(FederationGenerations.class)
435                 .child(RemoteSiteGenerationInfo.class, new RemoteSiteGenerationInfoKey(remoteIp));
436         putTx.put(LogicalDatastoreType.CONFIGURATION, path, builder.build());
437         CheckedFuture<Void, TransactionCommitFailedException> future1 = putTx.submit();
438
439         try {
440             future1.checkedGet();
441         } catch (org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException e) {
442             return false;
443         }
444
445         return true;
446     }
447
448     public static void deleteGenerationInfo(DataBroker broker, String remoteIp) {
449         if (remoteIp == null) {
450             LOG.error("Cannot remove generation number - remote IP is null");
451             return;
452         }
453
454         LOG.info("Deleting generation number for remote site {}", remoteIp);
455         WriteTransaction deleteTx = broker.newWriteOnlyTransaction();
456         InstanceIdentifier<RemoteSiteGenerationInfo> path = InstanceIdentifier.create(FederationGenerations.class)
457                 .child(RemoteSiteGenerationInfo.class, new RemoteSiteGenerationInfoKey(remoteIp));
458         deleteTx.delete(LogicalDatastoreType.CONFIGURATION, path);
459         deleteTx.submit();
460     }
461
462     // https://bugs.opendaylight.org/show_bug.cgi?id=7420
463     // SubnetRoute.class; allegedly not federated
464     @SuppressWarnings({ "checkstyle:emptyblock", "deprecation" })
465     private static void bug7420Workaround(int moreRetries) {
466
467         if (moreRetries == 0) {
468             return;
469         }
470         try {
471
472             TopologyBuilder topologyBuilder = new TopologyBuilder();
473             topologyBuilder.setKey(new TopologyKey(new TopologyId(new Uri("ovsdb:1"))));
474             String nodeName = "aaa";
475             NodeBuilder nodeBuilder = new NodeBuilder();
476             nodeBuilder.setNodeId(new NodeId(nodeName));
477             nodeBuilder.addAugmentation(TopologyNodeShadowProperties.class,
478                     new TopologyNodeShadowPropertiesBuilder().setShadow(true).build());
479             nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, new OvsdbNodeAugmentationBuilder().build());
480             topologyBuilder.setNode(Collections.singletonList(nodeBuilder.build()));
481             NetworkTopology networkTopology = new NetworkTopologyBuilder()
482                     .setTopology(Collections.singletonList(topologyBuilder.build())).build();
483             InstanceIdentifier<NetworkTopology> iid = InstanceIdentifier.create(NetworkTopology.class);
484             BindingAwareJsonConverter.jsonStringFromDataObject(iid, networkTopology);
485
486             ElanInterfaceBuilder eeib = new ElanInterfaceBuilder();
487             eeib.setElanInstanceName("aaa");
488             eeib.setKey(new ElanInterfaceKey("vvv"));
489             eeib.addAugmentation(ElanShadowProperties.class, new ElanShadowPropertiesBuilder().setShadow(true).build());
490             ElanInterfacesBuilder eib = new ElanInterfacesBuilder();
491             eib.setElanInterface(Collections.singletonList(eeib.build()));
492             InstanceIdentifier<ElanInterfaces> iid2 = InstanceIdentifier.create(ElanInterfaces.class);
493             BindingAwareJsonConverter.jsonStringFromDataObject(iid2, eib.build());
494
495             InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey("sad"));
496             interfaceBuilder.addAugmentation(IfShadowProperties.class,
497                     new IfShadowPropertiesBuilder().setShadow(true).build());
498             interfaceBuilder.addAugmentation(IfL2vlan.class, new IfL2vlanBuilder().build());
499             interfaceBuilder.addAugmentation(IfExternal.class, new IfExternalBuilder().build());
500             interfaceBuilder.addAugmentation(InterfaceAcl.class, new InterfaceAclBuilder().build());
501             interfaceBuilder.addAugmentation(IfStackedVlan.class, new IfStackedVlanBuilder().build());
502             interfaceBuilder.addAugmentation(ParentRefs.class, new ParentRefsBuilder().build());
503
504             Interfaces interfaces = new InterfacesBuilder()
505                     .setInterface(Collections.singletonList(interfaceBuilder.build())).build();
506             InstanceIdentifier<Interfaces> iid4 = InstanceIdentifier.create(Interfaces.class);
507             BindingAwareJsonConverter.jsonStringFromDataObject(iid4, interfaces);
508
509             org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder inventoryNodeBuilder
510                     = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder().setKey(
511                             new NodeKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId(
512                                     "asd")));
513             inventoryNodeBuilder.addAugmentation(FlowCapableNode.class, new FlowCapableNodeBuilder().build());
514             inventoryNodeBuilder.addAugmentation(NodeMeterFeatures.class, new NodeMeterFeaturesBuilder().build());
515             inventoryNodeBuilder.addAugmentation(FlowCapableStatisticsGatheringStatus.class,
516                     new FlowCapableStatisticsGatheringStatusBuilder().build());
517             inventoryNodeBuilder.addAugmentation(NodeGroupFeatures.class, new NodeGroupFeaturesBuilder().build());
518
519             List<NodeConnector> newNcList = new ArrayList<>();
520             NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder()
521                     .setKey(new NodeConnectorKey(new NodeConnectorId("asd")));
522             ncBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class,
523                     new FlowCapableNodeConnectorStatisticsDataBuilder().build());
524             ncBuilder.addAugmentation(FlowCapableNodeConnector.class, new FlowCapableNodeConnectorBuilder().build());
525             newNcList.add(ncBuilder.build());
526             inventoryNodeBuilder.setNodeConnector(newNcList);
527             inventoryNodeBuilder.addAugmentation(InventoryNodeShadowProperties.class,
528                     new InventoryNodeShadowPropertiesBuilder().setShadow(true).build());
529             Nodes nodes = new NodesBuilder().setNode(Collections.singletonList(inventoryNodeBuilder.build())).build();
530             InstanceIdentifier<Nodes> iid5 = InstanceIdentifier.create(Nodes.class);
531             BindingAwareJsonConverter.jsonStringFromDataObject(iid5, nodes);
532
533             List<Adjacency> federatedAdjacencies = Collections
534                     .singletonList(new AdjacencyBuilder().setKey(new AdjacencyKey("asd")).build());
535             VpnInterfaceBuilder vpnInterfaceBuilder = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey("asd"));
536             vpnInterfaceBuilder.addAugmentation(Adjacencies.class,
537                     new AdjacenciesBuilder().setAdjacency(federatedAdjacencies).build());
538             vpnInterfaceBuilder.addAugmentation(VpnShadowProperties.class,
539                     new VpnShadowPropertiesBuilder().setShadow(true).build());
540             vpnInterfaceBuilder.addAugmentation(OpState.class, new OpStateBuilder().build());
541             VpnInterfaces vpnInterfaces = new VpnInterfacesBuilder()
542                     .setVpnInterface(Collections.singletonList(vpnInterfaceBuilder.build())).build();
543             InstanceIdentifier<VpnInterfaces> iid6 = InstanceIdentifier.create(VpnInterfaces.class);
544             BindingAwareJsonConverter.jsonStringFromDataObject(iid6, vpnInterfaces);
545
546             InstanceIdentifier<ElanInstances> iid7 = InstanceIdentifier.create(ElanInstances.class);
547             ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().addAugmentation(EtreeInstance.class,
548                     new EtreeInstanceBuilder().build());
549             ElanInstancesBuilder instancesBuilder = new ElanInstancesBuilder().setElanInstance(
550                     Collections.singletonList(elanInstanceBuilder.setKey(new ElanInstanceKey("asd")).build()));
551             BindingAwareJsonConverter.jsonStringFromDataObject(iid7, instancesBuilder.build());
552
553             InstanceIdentifier<ElanTagNameMap> iid8 = InstanceIdentifier.create(ElanTagNameMap.class);
554             ElanTagName tagName = new ElanTagNameBuilder().setKey(new ElanTagNameKey(123L))
555                     .addAugmentation(EtreeLeafTagName.class,
556                             new EtreeLeafTagNameBuilder().setEtreeLeafTag(new EtreeLeafTag(23L)).build())
557                     .build();
558             ElanTagNameMapBuilder mapBuilder = new ElanTagNameMapBuilder()
559                     .setElanTagName(Collections.singletonList(tagName));
560             BindingAwareJsonConverter.jsonStringFromDataObject(iid8, mapBuilder.build());
561         } catch (UncheckedExecutionException t) {
562             LOG.info("Frozen issue occured in workaround - this is acceptable, retrying it", t);
563             try {
564                 Thread.sleep(200);
565             } catch (InterruptedException e) {
566             }
567             bug7420Workaround(--moreRetries);
568         }
569     }
570
571 }