Added range type to subject-feature-definition/parameter
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / integration / openstackgbp / OpenstackGbpEndpoint.java
1 package org.opendaylight.groupbasedpolicy.integration.openstackgbp;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.concurrent.ExecutionException;
6 import java.util.concurrent.Executors;
7 import java.util.concurrent.Future;
8 import java.util.concurrent.ScheduledExecutorService;
9
10 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
11 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
12 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
13 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
16 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
17 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
18 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.OpenstackEndpoints;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.OpenstackEndpointsBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.OpenstackEndpointService;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.RegisterEndpointInput;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.UnregisterEndpointInput;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.endpoint.fields.L3Address;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.Endpoint;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.EndpointBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.EndpointKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.EndpointL3;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.EndpointL3Builder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.openstack.endpoints.EndpointL3Key;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.unregister.endpoint.input.L2;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.openstackendpoint.rev141204.unregister.endpoint.input.L3;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.RpcResult;
46 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 import com.google.common.base.Function;
51 import com.google.common.base.Optional;
52 import com.google.common.util.concurrent.CheckedFuture;
53 import com.google.common.util.concurrent.FutureCallback;
54 import com.google.common.util.concurrent.Futures;
55 import com.google.common.util.concurrent.ListenableFuture;
56
57 public class OpenstackGbpEndpoint implements AutoCloseable,
58         OpenstackEndpointService {
59
60     public static final InstanceIdentifier<OpenstackEndpoints> OPENSTACKEP_IID = InstanceIdentifier
61             .builder(OpenstackEndpoints.class).build();
62
63     private static final Logger LOG = LoggerFactory
64             .getLogger(OpenstackGbpEndpoint.class);
65
66     private DataBroker dataProvider;
67     private final ScheduledExecutorService executor;
68
69     private final static InstanceIdentifier<Nodes> nodesIid = InstanceIdentifier
70             .builder(Nodes.class).build();
71     private final static InstanceIdentifier<Node> nodeIid = InstanceIdentifier
72             .builder(Nodes.class).child(Node.class).build();
73     private ListenerRegistration<DataChangeListener> nodesReg;
74
75     final BindingAwareBroker.RpcRegistration<OpenstackEndpointService> rpcRegistration;
76
77     public OpenstackGbpEndpoint(DataBroker dataProvider,
78             RpcProviderRegistry rpcRegistry) {
79         super();
80         this.dataProvider = dataProvider;
81         executor = Executors.newScheduledThreadPool(1);
82
83         if (rpcRegistry != null) {
84             rpcRegistration = rpcRegistry.addRpcImplementation(
85                     OpenstackEndpointService.class, this);
86         } else
87             rpcRegistration = null;
88
89         if (dataProvider != null) {
90             // XXX - This is a hack to avoid a bug in the data broker
91             // API where you have to write all the parents before you can write
92             // a child
93             InstanceIdentifier<OpenstackEndpoints> iid = InstanceIdentifier
94                     .builder(OpenstackEndpoints.class).build();
95             WriteTransaction t = this.dataProvider.newWriteOnlyTransaction();
96             t.put(LogicalDatastoreType.OPERATIONAL, iid,
97                     new OpenstackEndpointsBuilder().build());
98             CheckedFuture<Void, TransactionCommitFailedException> f = t
99                     .submit();
100             Futures.addCallback(f, new FutureCallback<Void>() {
101                 @Override
102                 public void onFailure(Throwable t) {
103                     LOG.error("Could not write endpoint base container", t);
104                 }
105
106                 @Override
107                 public void onSuccess(Void result) {
108                 }
109             });
110             nodesReg = dataProvider.registerDataChangeListener(
111                     LogicalDatastoreType.OPERATIONAL, nodeIid,
112                     new NodesListener(), DataChangeScope.SUBTREE);
113         }
114     }
115
116     // private OpenstackEndpoints buildOpenstackEndpoint(Name neutronPortId,
117     // TenantId tenant) {
118     // return new OpenstackEndpoints();
119     // }
120
121     public void setDataProvider(final DataBroker salDataProvider) {
122         this.dataProvider = salDataProvider;
123     }
124
125     @Override
126     public void close() throws Exception {
127         // When we close this service we need to shutdown our executor!
128         // executor.shutdown();
129
130         if (dataProvider != null) {
131             WriteTransaction tx = dataProvider.newWriteOnlyTransaction();
132             tx.delete(LogicalDatastoreType.OPERATIONAL, OPENSTACKEP_IID);
133             Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
134                 @Override
135                 public void onSuccess(final Void result) {
136                     LOG.debug("Delete OS EP commit result: " + result);
137                 }
138
139                 @Override
140                 public void onFailure(final Throwable t) {
141                     LOG.error("Delete of OS EP failed", t);
142                 }
143             });
144         }
145     }
146
147     // ******************************************************************/
148     /**
149      * Construct an endpoint with the appropriate augmentations from the
150      * endpoint input. This can be overridden by a concrete implementation.
151      *
152      * @param input
153      *            the input object
154      * @param timestamp
155      *            the current timestamp
156      */
157     protected EndpointBuilder buildEndpoint(RegisterEndpointInput input) {
158         return new EndpointBuilder(input);
159     }
160
161     /**
162      * Construct an L3 endpoint with the appropriate augmentations from the
163      * endpoint input. This can be overridden by a concrete implementation.
164      *
165      * @param input
166      *            the input object
167      * @param timestamp
168      *            the current timestamp
169      */
170     protected EndpointL3Builder buildEndpointL3(RegisterEndpointInput input) {
171         return new EndpointL3Builder(input);
172     }
173
174     @Override
175     public Future<RpcResult<Void>> unregisterEndpoint(
176             UnregisterEndpointInput input) {
177         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
178         if (input.getL2() != null) {
179             for (L2 l2a : input.getL2()) {
180                 EndpointKey key = new EndpointKey(l2a.getL2Context(),
181                         l2a.getMacAddress());
182                 InstanceIdentifier<Endpoint> iid = InstanceIdentifier
183                         .builder(OpenstackEndpoints.class)
184                         .child(Endpoint.class, key).build();
185                 t.delete(LogicalDatastoreType.OPERATIONAL, iid);
186             }
187         }
188         if (input.getL3() != null) {
189             for (L3 l3addr : input.getL3()) {
190                 EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(),
191                         l3addr.getL3Context());
192                 InstanceIdentifier<EndpointL3> iid_l3 = InstanceIdentifier
193                         .builder(OpenstackEndpoints.class)
194                         .child(EndpointL3.class, key3).build();
195                 t.delete(LogicalDatastoreType.OPERATIONAL, iid_l3);
196             }
197         }
198         unregisterStandardEndpoint(input);
199         ListenableFuture<Void> r = t.submit();
200         return Futures.transform(r, futureTrans, executor);
201     }
202
203     public Future<RpcResult<Void>> unregisterStandardEndpoint(
204             UnregisterEndpointInput input) {
205         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
206         if (input.getL2() != null) {
207             for (L2 l2a : input.getL2()) {
208                 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey key = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey(
209                         l2a.getL2Context(), l2a.getMacAddress());
210                 if (existsL2Endpoint(key)) {
211                     InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint> iid = InstanceIdentifier
212                             .builder(
213                                     org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints.class)
214                             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint.class,
215                                     key).build();
216                     t.delete(LogicalDatastoreType.OPERATIONAL, iid);
217                 }
218
219             }
220         }
221         if (input.getL3() != null) {
222             for (L3 l3addr : input.getL3()) {
223                 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key key3 = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key(
224                         l3addr.getIpAddress(), l3addr.getL3Context());
225                 if (existsL3Endpoint(key3)) {
226                     InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3> iid_l3 = InstanceIdentifier
227                             .builder(Endpoints.class)
228                             .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3.class,
229                                     key3).build();
230                     t.delete(LogicalDatastoreType.OPERATIONAL, iid_l3);
231                 }
232             }
233         }
234         ListenableFuture<Void> r = t.submit();
235         return Futures.transform(r, futureTrans, executor);
236     }
237
238     private Boolean existsL2Endpoint(
239             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey key) {
240         Boolean exists = false;
241         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint> iid = InstanceIdentifier
242                 .builder(Endpoints.class)
243                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint.class,
244                         key).build();
245
246         if (dataProvider != null) {
247             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint> result;
248             try {
249                 result = dataProvider.newReadOnlyTransaction()
250                         .read(LogicalDatastoreType.OPERATIONAL, iid).get();
251                 if (result.isPresent()) {
252                     exists = true;
253                 }
254             } catch (InterruptedException e) {
255                 // TODO Auto-generated catch block
256                 e.printStackTrace();
257             } catch (ExecutionException e) {
258                 // TODO Auto-generated catch block
259                 e.printStackTrace();
260             }
261         }
262         return exists;
263     }
264
265     private Boolean existsL3Endpoint(
266             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key keyL3) {
267         Boolean exists = false;
268         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3> iidL3 = InstanceIdentifier
269                 .builder(Endpoints.class)
270                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3.class,
271                         keyL3).build();
272         if (dataProvider != null) {
273             Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3> result;
274             try {
275                 result = dataProvider.newReadOnlyTransaction()
276                         .read(LogicalDatastoreType.OPERATIONAL, iidL3).get();
277                 if (result.isPresent()) {
278                     exists = true;
279                 }
280             } catch (InterruptedException e) {
281                 // TODO Auto-generated catch block
282                 e.printStackTrace();
283             } catch (ExecutionException e) {
284                 // TODO Auto-generated catch block
285                 e.printStackTrace();
286             }
287         }
288         return exists;
289     }
290
291     @Override
292     public Future<RpcResult<Void>> registerEndpoint(RegisterEndpointInput input) {
293         long timestamp = System.currentTimeMillis();
294
295         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
296
297         if (input.getL2Context() != null && input.getMacAddress() != null) {
298             Endpoint ep = buildEndpoint(input).setTimestamp(timestamp).build();
299
300             EndpointKey key = new EndpointKey(ep.getL2Context(),
301                     ep.getMacAddress());
302             InstanceIdentifier<Endpoint> iid = InstanceIdentifier
303                     .builder(OpenstackEndpoints.class)
304                     .child(Endpoint.class, key).build();
305             t.put(LogicalDatastoreType.OPERATIONAL, iid, ep);
306             NodeInfo nodeInfo = mapNeutronPortToNodeInfo(ep.getNeutronPortId()
307                     .getValue());
308             if (nodeInfo.getNode() != null
309                     && nodeInfo.getNodeConnector() != null) {
310                 writeNewEp(translateEndpoint(ep, nodeInfo.getNodeConnector()
311                         .getId(), nodeInfo.getNode().getId()));
312             }
313         }
314         if (input.getL3Address() != null) {
315             for (L3Address l3addr : input.getL3Address()) {
316                 EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(),
317                         l3addr.getL3Context());
318                 EndpointL3 ep3 = buildEndpointL3(input)
319                         .setIpAddress(key3.getIpAddress())
320                         .setL3Context(key3.getL3Context())
321                         .setTimestamp(timestamp).build();
322                 InstanceIdentifier<EndpointL3> iid_l3 = InstanceIdentifier
323                         .builder(OpenstackEndpoints.class)
324                         .child(EndpointL3.class, key3).build();
325                 t.put(LogicalDatastoreType.OPERATIONAL, iid_l3, ep3);
326                 NodeInfo nodeInfo = mapNeutronPortToNodeInfo(ep3
327                         .getNeutronPortId().toString());
328                 if (nodeInfo.getNode() != null
329                         && nodeInfo.getNodeConnector() != null) {
330                     writeNewEpL3(translateEndpointL3(ep3, nodeInfo
331                             .getNodeConnector().getId(), nodeInfo.getNode()
332                             .getId()));
333                 }
334             }
335         }
336         ListenableFuture<Void> r = t.submit();
337         return Futures.transform(r, futureTrans, executor);
338         // Now check for Nodes that match the neutron port id
339     }
340
341     // A wrapper class around node, noeConnector info so we can pass a final
342     // object inside OnSuccess anonymous inner class
343     private static class NodeInfo {
344         NodeConnector nodeConnector;
345         Node node;
346
347         private NodeInfo() {
348
349         }
350
351         private NodeInfo(NodeConnector nc, Node node) {
352             this.nodeConnector = nc;
353             this.node = node;
354         }
355
356         private Node getNode() {
357             return this.node;
358         }
359
360         private NodeConnector getNodeConnector() {
361             return this.nodeConnector;
362         }
363
364         public void setNodeConnector(NodeConnector nodeConnector) {
365             this.nodeConnector = nodeConnector;
366         }
367
368         public void setNode(Node node) {
369             this.node = node;
370         }
371     }
372
373     private NodeInfo mapNeutronPortToNodeInfo(final String neutronPortId) {
374         final NodeInfo nodeInfo = new NodeInfo();
375
376         if (dataProvider != null) {
377
378             ListenableFuture<Optional<Nodes>> future = dataProvider
379                     .newReadOnlyTransaction().read(
380                             LogicalDatastoreType.OPERATIONAL, nodesIid);
381
382             Futures.addCallback(future, new FutureCallback<Optional<Nodes>>() {
383                 @Override
384                 public void onSuccess(Optional<Nodes> result) {
385                     if (result.isPresent()) {
386                         Nodes nodes = result.get();
387                         for (Node node : nodes.getNode()) {
388                             if (node.getNodeConnector() != null) {
389                                 for (NodeConnector nc : node.getNodeConnector()) {
390                                     FlowCapableNodeConnector fcnc = nc
391                                             .getAugmentation(FlowCapableNodeConnector.class);
392                                     if (fcnc.getName().equals(neutronPortId)) {
393                                         nodeInfo.setNode(node);
394                                         nodeInfo.setNodeConnector(nc);
395                                     }
396                                 }
397                             }
398                         }
399
400                     }
401                 }
402
403                 @Override
404                 public void onFailure(Throwable t) {
405                     LOG.error("Count not read switch information", t);
406                 }
407             });
408         }
409         return nodeInfo;
410     }
411
412     private Future<RpcResult<Void>> writeNewEp(
413             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint ep) {
414         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
415         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint> iid = InstanceIdentifier
416                 .builder(
417                         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints.class)
418                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint.class,
419                         ep.getKey()).build();
420         t.put(LogicalDatastoreType.OPERATIONAL, iid, ep);
421         ListenableFuture<Void> r = t.submit();
422         return Futures.transform(r, futureTrans, executor);
423
424     }
425
426     private Future<RpcResult<Void>> writeNewEpL3(
427             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3 ep) {
428         WriteTransaction t = dataProvider.newWriteOnlyTransaction();
429         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3> iid = InstanceIdentifier
430                 .builder(
431                         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints.class)
432                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3.class,
433                         ep.getKey()).build();
434         t.put(LogicalDatastoreType.OPERATIONAL, iid, ep);
435         ListenableFuture<Void> r = t.submit();
436         return Futures.transform(r, futureTrans, executor);
437
438     }
439
440     private boolean validEp(Endpoint endpoint) {
441         return (endpoint != null && endpoint.getTenant() != null
442                 && endpoint.getEndpointGroup() != null
443                 && endpoint.getL2Context() != null && endpoint.getMacAddress() != null);
444     }
445
446     private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint translateEndpoint(
447             Endpoint ep, NodeConnectorId nodeConnectorId, NodeId nodeId) {
448         OfOverlayContextBuilder ofOverlayAugmentation = new OfOverlayContextBuilder();
449         ofOverlayAugmentation.setNodeId(nodeId);
450         ofOverlayAugmentation.setNodeConnectorId(nodeConnectorId);
451         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder newEpBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder();
452         newEpBuilder.addAugmentation(OfOverlayContext.class,
453                 ofOverlayAugmentation.build());
454         newEpBuilder.setCondition(ep.getCondition());
455         newEpBuilder.setEndpointGroup(ep.getEndpointGroup());
456         newEpBuilder.setL2Context(ep.getL2Context());
457         newEpBuilder.setMacAddress(ep.getMacAddress());
458         // TODO This is horrible, and a consequence of the
459         // openstackendpoint.yang not either including or importing
460         // groups from endpoint.yang ... cargo cult code again that needs to be
461         // cleaned up.
462         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey newEpKey = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey(
463                 ep.getL2Context(), ep.getMacAddress());
464         newEpBuilder.setKey(newEpKey);
465         // TODO As per above, horrible
466         List<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address> newL3AddressList = new ArrayList<>();
467         if (ep.getL3Address() != null) {
468             for (L3Address l3 : ep.getL3Address()) {
469                 LOG.debug(l3.toString());
470                 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder newL3AddressBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder();
471                 newL3AddressBuilder.setIpAddress(l3.getIpAddress());
472                 newL3AddressBuilder.setL3Context(l3.getL3Context());
473                 newL3AddressList.add(newL3AddressBuilder.build());
474             }
475         }
476         newEpBuilder.setL3Address(newL3AddressList);
477         newEpBuilder.setTenant(ep.getTenant());
478         newEpBuilder.setTimestamp(ep.getTimestamp());
479         return newEpBuilder.build();
480     }
481
482     private org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3 translateEndpointL3(
483             EndpointL3 ep, NodeConnectorId nodeConnectorId, NodeId nodeId) {
484         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder newEpL3Builder = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder();
485
486         newEpL3Builder.setCondition(ep.getCondition());
487         newEpL3Builder.setIpAddress(ep.getIpAddress());
488         newEpL3Builder.setL3Context(ep.getL3Context());
489         newEpL3Builder.setEndpointGroup(ep.getEndpointGroup());
490         newEpL3Builder.setL2Context(ep.getL2Context());
491         newEpL3Builder.setMacAddress(ep.getMacAddress());
492         // TODO This is horrible, and a consequence of the
493         // openstackendpoint.yang not either including or importing
494         // groups from endpoint.yang ... cargo cult code again that needs to be
495         // cleaned up.
496         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key newEpL3Key = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Key(
497                 ep.getIpAddress(), ep.getL3Context());
498         newEpL3Builder.setKey(newEpL3Key);
499         // TODO As per above, horrible
500         List<org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address> newL3AddressList = new ArrayList<>();
501         for (L3Address l3 : ep.getL3Address()) {
502             LOG.debug(l3.toString());
503             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder newL3AddressBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder();
504             newL3AddressBuilder.setIpAddress(l3.getIpAddress());
505             newL3AddressBuilder.setL3Context(l3.getL3Context());
506             newL3AddressList.add(newL3AddressBuilder.build());
507         }
508         newEpL3Builder.setL3Address(newL3AddressList);
509         newEpL3Builder.setTenant(ep.getTenant());
510         newEpL3Builder.setTimestamp(ep.getTimestamp());
511         return newEpL3Builder.build();
512     }
513
514     private void updateOfOverlayEndpoint(final String neutronPortId,
515             final NodeConnectorId nodeConnectorId, final NodeId nodeId) {
516
517         if (dataProvider != null) {
518             InstanceIdentifier<OpenstackEndpoints> iid = InstanceIdentifier
519                     .builder(OpenstackEndpoints.class).build();
520             ListenableFuture<Optional<OpenstackEndpoints>> future = dataProvider
521                     .newReadOnlyTransaction().read(
522                             LogicalDatastoreType.OPERATIONAL, iid);
523             Futures.addCallback(future,
524                     new FutureCallback<Optional<OpenstackEndpoints>>() {
525                         @Override
526                         public void onSuccess(
527                                 Optional<OpenstackEndpoints> result) {
528                             if (result.isPresent()) {
529                                 OpenstackEndpoints openstackEndpoints = result
530                                         .get();
531                                 if (openstackEndpoints.getEndpoint() != null) {
532                                     for (Endpoint ep : openstackEndpoints
533                                             .getEndpoint()) {
534                                         if (validEp(ep)
535                                                 && ep.getNeutronPortId()
536                                                         .getValue()
537                                                         .equals(neutronPortId)) {
538                                             LOG.debug("Match: " + ep.toString());
539                                             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint newEp = translateEndpoint(
540                                                     ep, nodeConnectorId, nodeId);
541                                             writeNewEp(newEp);
542                                             LOG.debug(newEp.toString());
543                                         }
544                                     }
545                                 }
546                                 if (openstackEndpoints.getEndpointL3() != null) {
547                                     for (EndpointL3 ep : openstackEndpoints
548                                             .getEndpointL3()) {
549                                         if (ep.getNeutronPortId().getValue()
550                                                 .equals(neutronPortId)) {
551                                             LOG.debug("L3 Match: "
552                                                     + ep.toString());
553                                             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3 newEpL3 = translateEndpointL3(
554                                                     ep, nodeConnectorId, nodeId);
555                                             writeNewEpL3(newEpL3);
556                                             LOG.debug(newEpL3.toString());
557                                         }
558                                     }
559                                 }
560                             }
561                         }
562
563                         @Override
564                         public void onFailure(Throwable t) {
565                             LOG.error("Count not read switch information", t);
566                         }
567                     });
568         }
569     }
570
571     private class NodesListener implements DataChangeListener {
572         @Override
573         public void onDataChanged(
574                 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
575             for (DataObject dao : change.getCreatedData().values()) {
576                 if (!(dao instanceof Node))
577                     continue;
578                 Node node = (Node) dao;
579                 if (node.getNodeConnector() != null) {
580                     for (NodeConnector nc : node.getNodeConnector()) {
581                         FlowCapableNodeConnector fcnc = nc
582                                 .getAugmentation(FlowCapableNodeConnector.class);
583                         if (fcnc.getName().matches(
584                                 "tap[a-f,0-9]{8}-[a-f,0-9]{2}")) {
585                             LOG.debug("Created Tap:" + fcnc.getName() + ": "
586                                     + nc.getId() + " : " + node.getId());
587                             updateOfOverlayEndpoint(fcnc.getName(), nc.getId(),
588                                     node.getId());
589                         }
590                     }
591                 }
592             }
593             for (DataObject dao : change.getUpdatedData().values()) {
594                 if (!(dao instanceof Node))
595                     continue;
596                 Node node = (Node) dao;
597                 if (node.getNodeConnector() != null) {
598                     for (NodeConnector nc : node.getNodeConnector()) {
599                         FlowCapableNodeConnector fcnc = nc
600                                 .getAugmentation(FlowCapableNodeConnector.class);
601                         if (fcnc.getName().matches(
602                                 "tap[a-f,0-9]{8}-[a-f,0-9]{2}")) {
603                             LOG.debug("Updated Tap:" + fcnc.getName() + ": "
604                                     + nc.getId() + " : " + node.getId());
605                             updateOfOverlayEndpoint(fcnc.getName(), nc.getId(),
606                                     node.getId());
607                         }
608                     }
609                 }
610             }
611         }
612     }
613
614     Function<Void, RpcResult<Void>> futureTrans = new Function<Void, RpcResult<Void>>() {
615         @Override
616         public RpcResult<Void> apply(Void input) {
617             return RpcResultBuilder.<Void> success().build();
618         }
619     };
620 }