iData wait for elan tag 60/49960/2
authorKonsta Pozdeev <konsta.pozdeev@hpe.com>
Sun, 11 Dec 2016 12:13:14 +0000 (14:13 +0200)
committerDavid Goldberg <gdavid@hpe.com>
Tue, 3 Jan 2017 11:39:20 +0000 (13:39 +0200)
Change-Id: Iaf01d1837500ff1e9e56fb1839edcda6861a6226
Signed-off-by: Konsta Pozdeev <konsta.pozdeev@hpe.com>
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitGetter.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitListener.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MdsalUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtVpnUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/SubnetListener.java
netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml

diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitGetter.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitGetter.java
new file mode 100644 (file)
index 0000000..51a6e4f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public interface DataWaitGetter<D extends DataObject>  {
+  
+    public Object get(D object);
+   
+   
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/DataWaitListener.java
new file mode 100644 (file)
index 0000000..23b8ac4
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+@SuppressWarnings("rawtypes")
+public class DataWaitListener<D extends DataObject> extends UnimgrDataTreeChangeListener<D> {
+    private static final Logger Log = LoggerFactory.getLogger(DataWaitListener.class);
+    InstanceIdentifier<D> objectIdentifierId;
+    private ListenerRegistration<DataWaitListener> dataWaitListenerRegistration;
+    Boolean dataAvailable = false;
+    private int maxRetries;
+    LogicalDatastoreType logicalDatastoreType;
+    DataWaitGetter<D> getData;
+    private final long waitMillisec = 1000;
+    
+
+    public DataWaitListener(final DataBroker dataBroker, final InstanceIdentifier<D> objectIdentifierId,
+            int maxRetiries, LogicalDatastoreType logicalDatastoreType, final DataWaitGetter<D> getData) {
+        super(dataBroker);
+        this.objectIdentifierId = objectIdentifierId;
+        this.maxRetries = maxRetiries;
+        this.logicalDatastoreType = logicalDatastoreType; 
+        this.getData = getData;
+        registerListener();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void registerListener() {
+        try {
+            final DataTreeIdentifier<D> dataTreeIid = new DataTreeIdentifier<D>(
+                    LogicalDatastoreType.CONFIGURATION, objectIdentifierId);
+            dataWaitListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+            Log.info("DataWaitListener created and registered");
+        } catch (final Exception e) {
+            Log.error("DataWaitListener DataChange listener registration failed !", e);
+            throw new IllegalStateException("DataWaitListener registration Listener failed.", e);
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        dataWaitListenerRegistration.close();
+    }
+
+    @Override
+    public void add(DataTreeModification<D> newDataObject) {
+        if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+            Log.info("data {} created", newDataObject.getRootNode().getIdentifier());
+        }
+        synchronized (dataAvailable) {
+            dataAvailable.notifyAll();
+        }
+    }
+
+    @Override
+    public void remove(DataTreeModification<D> removedDataObject) {
+    }
+
+    @Override
+    public void update(DataTreeModification<D> modifiedDataObject) {
+        if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+            Log.info("data {} updated", modifiedDataObject.getRootNode().getIdentifier());
+        }
+        synchronized (dataAvailable) {
+            dataAvailable.notifyAll();
+        }
+    }
+
+    private boolean dataAvailable() {
+        Optional<D> objectInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                objectIdentifierId);
+        if (!objectInstance.isPresent()) {
+            Log.debug("Data for {} doesn't exist, waiting more", objectIdentifierId);
+            return false;
+        }  
+        if (getData.get(objectInstance.get()) != null) {
+            return true;
+        }
+        return false;
+    }
+
+    public boolean waitForData () {
+        return waitForData(maxRetries);
+    }
+    
+    
+    public boolean waitForData(int retry) {
+        synchronized (dataAvailable) {
+            dataAvailable = dataAvailable();
+            if (dataAvailable == true) {
+                return true;
+            } else if (retry <= 0) {
+                return false;
+            }
+            try {
+                dataAvailable.wait(waitMillisec);
+            } catch (InterruptedException e1) {
+            }
+        }
+        return waitForData(--retry);
+    }
+}
index 5b6b7deb98806a696f47adcfe5ce5e93358e629e..d4c87e014e03c5184f503973a717daaf91b4e7d9 100644 (file)
@@ -99,7 +99,6 @@ public class MdsalUtils {
         return result;
     }
 
-
     public static WriteTransaction createTransaction(DataBroker dataBroker) {
         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
         return tx;
index 158fc15b14d92b8d2ee56c1a43289c0ecb702569..e59c7818c6d332cfad78d82b99e0b26ee7595f75 100644 (file)
@@ -154,7 +154,7 @@ public class NetvirtUtils {
         return InstanceIdentifier.builder(ElanInterfaces.class).build();
     }
 
-    private static InstanceIdentifier<ElanInstance> getElanInstanceInstanceIdentifier(String instanceName) {
+    public static InstanceIdentifier<ElanInstance> getElanInstanceInstanceIdentifier(String instanceName) {
         return InstanceIdentifier.builder(ElanInstances.class)
                 .child(ElanInstance.class, new ElanInstanceKey(instanceName)).build();
     }
index 8059e745101a30a18f5aa2eb1eaf9fbbedd29daf..e8b6665daec50f75cb00601fb0bf79373e224462 100644 (file)
@@ -305,17 +305,16 @@ public class NetvirtVpnUtils {
 
     public static void addDirectSubnetToVpn(DataBroker dataBroker,
             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
-            IpPrefix subnetIpPrefix, String interfaceName) {
-        InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
-                .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
-        Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                elanIdentifierId);
-        if (!elanInstance.isPresent()) {
+            IpPrefix subnetIpPrefix, String interfaceName, int waitForElan) {
+        InstanceIdentifier<ElanInstance> elanIdentifierId = NetvirtUtils.getElanInstanceInstanceIdentifier(subnetName);
+
+        @SuppressWarnings("resource") // AutoCloseable
+        DataWaitListener<ElanInstance> elanTagWaiter = new DataWaitListener<ElanInstance>(
+                dataBroker, elanIdentifierId, 10, LogicalDatastoreType.CONFIGURATION, el -> el.getElanTag());
+        if ( !elanTagWaiter.waitForData()) {
             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
             return;
         }
-        Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
-                : elanInstance.get().getSegmentationId();
 
         Uuid subnetId = new Uuid(subnetName);
         logger.info("Adding subnet {} {} to elan map", subnetId, subnetId);
@@ -328,6 +327,10 @@ public class NetvirtVpnUtils {
         logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
         updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName), null);
 
+        Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                elanIdentifierId);
+        Long elanTag = elanInstance.get().getElanTag();
+
         logger.info("Publish subnet {}", subnetName);
         publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
         logger.info("Finished Working on subnet {}", subnetName);
index 2f98c3c19869273a4f421d815730cdc37373601c..c563746a7521e1294a32b98d1ede600c50e5a9a6 100644 (file)
@@ -42,13 +42,14 @@ public class SubnetListener extends UnimgrDataTreeChangeListener<Subnet> impleme
     private ListenerRegistration<SubnetListener> subnetListenerRegistration;
     private final NotificationPublishService notificationPublishService;
     private final IGwMacListener gwMacListener;
-
+    private final int waitForElanInterval;
 
     public SubnetListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
-             final IGwMacListener gwMacListener ) {
+             final IGwMacListener gwMacListener, int sleepInterval) {
         super(dataBroker);
         this.notificationPublishService = notPublishService;
         this.gwMacListener = gwMacListener;
+        this.waitForElanInterval = sleepInterval;
         registerListener();
     }
 
@@ -196,7 +197,7 @@ public class SubnetListener extends UnimgrDataTreeChangeListener<Subnet> impleme
         }
 
         NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
-                vpnElan.getElanId(), newSubnet.getSubnet(), vpnElan.getElanPort());
+                vpnElan.getElanId(), newSubnet.getSubnet(), vpnElan.getElanPort(), waitForElanInterval);
 
     }
 
index 451e65098015db28693211d2b60762d4f9097f74..281b315737931b3243ce5c0d1f10cd7775b776d8 100644 (file)
@@ -22,7 +22,7 @@
         class="org.opendaylight.unimgr.mef.netvirt.NodeConnectorListener">
         <argument ref="dataBroker" />
         <argument ref="uniPortManager" />
-            <argument value="false" />
+        <argument value="false" />
     </bean>
 
     <bean id="evcListener" class="org.opendaylight.unimgr.mef.netvirt.EvcListener">
@@ -40,6 +40,7 @@
         <argument ref="dataBroker" />
         <argument ref="notificationPublishService" />
         <argument ref="qwMacListener" />
+        <argument value="5" />                         
     </bean>
 
     <bean id="qwMacListener" class="org.opendaylight.unimgr.mef.netvirt.GwMacListener">