Fix test by waiting to lbaas entity delete

This fix prevents a scenario where an
lbaas entity is trying to be deleted while it still in use,
because an associate entity still didn't finished it's deletion.
Handling the DB before completing the back-end operations
can cause problems.
So waiting for back-end system response is crucial for
keeping the DB model consistent.

A new network timeout and time interval options were
added in configuration file. These were added to give control over
network resources wait periods without effecting other projects.

Added wait_for_resource_deletion and is_resource_deleted functions,
similar to the common rest_client functions but with resource type
as a parameter since network service has no rest_client for each resource.
calling the new function when deleting vips and pools.

Bug #1288326 was opened to address the fact that network rest client does
not fit common REST client framework approach where each resource
has its own implementation of the client.

This change is a replacement for the change below.
https://review.openstack.org/#/c/68190/3
Was replaced due to a development workstation crash.

Change-Id: Ie6468f0488ea2515ed8ccbe1a8c9c55b9ab4a3de
Closes-Bug: #1271214
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 2443399..2487d62 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -543,6 +543,14 @@
 # (string value)
 #public_router_id=
 
+# Timeout in seconds to wait for network operation to
+# complete. (integer value)
+#build_timeout=300
+
+# Time in seconds between network operation status checks.
+# (integer value)
+#build_interval=10
+
 
 [network-feature-enabled]
 
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index d5f2b5b..aa2c978 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -90,6 +90,7 @@
         # Verification of vip delete
         resp, body = self.client.delete_vip(vip['id'])
         self.assertEqual('204', resp['status'])
+        self.client.wait_for_resource_deletion('vip', vip['id'])
         # Verification of pool update
         new_name = "New_pool"
         resp, body = self.client.update_pool(pool['id'],
diff --git a/tempest/config.py b/tempest/config.py
index fa051d5..732b131 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -329,6 +329,14 @@
                default="",
                help="Id of the public router that provides external "
                     "connectivity"),
+    cfg.IntOpt('build_timeout',
+               default=300,
+               help="Timeout in seconds to wait for network operation to "
+                    "complete."),
+    cfg.IntOpt('build_interval',
+               default=10,
+               help="Time in seconds between network operation status "
+                    "checks."),
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
index 07716fa..f4b9364 100644
--- a/tempest/services/network/network_client_base.py
+++ b/tempest/services/network/network_client_base.py
@@ -10,9 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
 import urllib
 
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -52,6 +54,8 @@
         self.rest_client.service = CONF.network.catalog_type
         self.version = '2.0'
         self.uri_prefix = "v%s" % (self.version)
+        self.build_timeout = CONF.network.build_timeout
+        self.build_interval = CONF.network.build_interval
 
     def get_rest_client(self, auth_provider):
         raise NotImplementedError
@@ -191,3 +195,23 @@
         resp, body = self.post(uri, body)
         body = {'ports': self.deserialize_list(body)}
         return resp, body
+
+    def wait_for_resource_deletion(self, resource_type, id):
+        """Waits for a resource to be deleted."""
+        start_time = int(time.time())
+        while True:
+            if self.is_resource_deleted(resource_type, id):
+                return
+            if int(time.time()) - start_time >= self.build_timeout:
+                raise exceptions.TimeoutException
+            time.sleep(self.build_interval)
+
+    def is_resource_deleted(self, resource_type, id):
+        method = 'show_' + resource_type
+        try:
+            getattr(self, method)(id)
+        except AttributeError:
+            raise Exception("Unknown resource type %s " % resource_type)
+        except exceptions.NotFound:
+            return True
+        return False