Merge "Fixes bug 1006405-Additional test cases to be added to test_volumes_negative.py"
diff --git a/tempest/openstack.py b/tempest/openstack.py
index 18af647..e23373f 100644
--- a/tempest/openstack.py
+++ b/tempest/openstack.py
@@ -31,6 +31,8 @@
 from tempest.services.nova.json.floating_ips_client import FloatingIPsClient
 from tempest.services.nova.json.keypairs_client import KeyPairsClient
 from tempest.services.nova.json.volumes_client import VolumesClient
+from tempest.services.nova.json.console_output_client \
+import ConsoleOutputsClient
 from tempest.services.identity.json.admin_client import AdminClient
 from tempest.services.identity.json.admin_client import TokenClient
 
@@ -82,6 +84,7 @@
         self.security_groups_client = SecurityGroupsClient(*client_args)
         self.floating_ips_client = FloatingIPsClient(*client_args)
         self.volumes_client = VolumesClient(*client_args)
+        self.console_outputs_client = ConsoleOutputsClient(*client_args)
         self.admin_client = AdminClient(*client_args)
         self.token_client = TokenClient(self.config)
         self.network_client = NetworkClient(*client_args)
diff --git a/tempest/services/nova/json/console_output_client.py b/tempest/services/nova/json/console_output_client.py
new file mode 100644
index 0000000..4a8795b
--- /dev/null
+++ b/tempest/services/nova/json/console_output_client.py
@@ -0,0 +1,18 @@
+from tempest.common.rest_client import RestClient
+import json
+
+
+class ConsoleOutputsClient(RestClient):
+
+    def __init__(self, config, username, password, auth_url, tenant_name=None):
+        super(ConsoleOutputsClient, self).__init__(config, username, password,
+                                             auth_url, tenant_name)
+        self.service = self.config.compute.catalog_type
+
+    def get_console_output(self, server_id, length):
+        post_body = {'os-getConsoleOutput': {'length': length}}
+        url = "/servers/%s/action" % server_id
+        post_body = json.dumps(post_body)
+        resp, body = self.post(url, post_body, self.headers)
+        body = json.loads(body)
+        return resp, body['output']
diff --git a/tempest/tests/base_compute_test.py b/tempest/tests/base_compute_test.py
index 2b16d8c..d7dac10 100644
--- a/tempest/tests/base_compute_test.py
+++ b/tempest/tests/base_compute_test.py
@@ -15,6 +15,7 @@
     keypairs_client = os.keypairs_client
     floating_ips_client = os.floating_ips_client
     security_groups_client = os.security_groups_client
+    console_outputs_client = os.console_outputs_client
     limits_client = os.limits_client
     config = os.config
     build_interval = config.compute.build_interval
diff --git a/tempest/tests/network/base.py b/tempest/tests/network/base.py
new file mode 100644
index 0000000..1046cd6
--- /dev/null
+++ b/tempest/tests/network/base.py
@@ -0,0 +1,59 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack, LLC
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import nose
+import unittest2 as unittest
+
+from tempest import exceptions
+from tempest import openstack
+from tempest.common.utils.data_utils import rand_name
+
+
+class BaseNetworkTest(unittest.TestCase):
+
+    os = openstack.Manager()
+    client = os.network_client
+    config = os.config
+    networks = []
+    enabled = True
+
+    # Validate that there is even an endpoint configured
+    # for networks, and mark the attr for skipping if not
+    try:
+        client.list_networks()
+    except exceptions.EndpointNotFound:
+        enabled = False
+        skip_msg = "No network endpoint"
+
+    @classmethod
+    def setUpClass(cls):
+        if not cls.enabled:
+            raise nose.SkipTest(cls.skip_msg)
+
+    @classmethod
+    def tearDownClass(cls):
+        for network in cls.networks:
+            cls.client.delete_network(network['id'])
+
+    def create_network(self, network_name=None):
+        """Wrapper utility that returns a test network"""
+        network_name = network_name or rand_name('test-network')
+
+        resp, body = self.client.create_network(network_name)
+        network = body['network']
+        self.networks.append(network)
+        return network
diff --git a/tempest/tests/network/test_networks.py b/tempest/tests/network/test_networks.py
index 6adbb6b..5476551 100644
--- a/tempest/tests/network/test_networks.py
+++ b/tempest/tests/network/test_networks.py
@@ -1,23 +1,33 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack, LLC
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
 from nose.plugins.attrib import attr
-from tempest import openstack
+
 from tempest.common.utils.data_utils import rand_name
-import unittest2 as unittest
+from tempest.tests.network import base
 
 
-class NetworksTest(unittest.TestCase):
+class NetworksTest(base.BaseNetworkTest):
 
     @classmethod
     def setUpClass(cls):
-        cls.os = openstack.Manager()
-        cls.client = cls.os.network_client
-        cls.config = cls.os.config
-        cls.name = rand_name('network')
-        resp, body = cls.client.create_network(cls.name)
-        cls.network = body['network']
-
-    @classmethod
-    def tearDownClass(cls):
-        cls.client.delete_network(cls.network['id'])
+        super(NetworksTest, cls).setUpClass()
+        cls.network = cls.create_network()
+        cls.name = cls.network['name']
 
     @attr(type='positive')
     def test_create_delete_network(self):
diff --git a/tempest/tests/test_authorization.py b/tempest/tests/test_authorization.py
index b21e0d3..8a0cf1b 100644
--- a/tempest/tests/test_authorization.py
+++ b/tempest/tests/test_authorization.py
@@ -18,6 +18,7 @@
         cls.images_client = cls.os.images_client
         cls.keypairs_client = cls.os.keypairs_client
         cls.security_client = cls.os.security_groups_client
+        cls.console_outputs_client = cls.os.console_outputs_client
         cls.config = cls.os.config
         cls.image_ref = cls.config.compute.image_ref
         cls.flavor_ref = cls.config.compute.flavor_ref
@@ -42,6 +43,8 @@
                 cls.other_keypairs_client = cls.other_manager.keypairs_client
                 cls.other_security_client = \
                 cls.other_manager.security_groups_client
+                cls.other_console_outputs_client = \
+                cls.other_manager.console_outputs_client
             except exceptions.AuthenticationFailure:
                 # multi_user is already set to false, just fall through
                 pass
@@ -420,3 +423,13 @@
             resp, body = \
             self.images_client.delete_image_metadata_item(self.image['id'],
                                                             'meta1')
+
+    @raises(exceptions.NotFound)
+    @attr(type='negative')
+    @utils.skip_unless_attr('multi_user', 'Second user not configured')
+    def test_get_console_output_of_other_account_server_fails(self):
+        """
+        A Get Console Output for another user's server should fail
+        """
+        self.other_console_outputs_client.get_console_output(self.server['id'],
+                                                                    10)
diff --git a/tempest/tests/test_console_output.py b/tempest/tests/test_console_output.py
new file mode 100644
index 0000000..1aa4a1c
--- /dev/null
+++ b/tempest/tests/test_console_output.py
@@ -0,0 +1,59 @@
+from nose.plugins.attrib import attr
+from tempest import openstack
+from tempest import exceptions
+from base_compute_test import BaseComputeTest
+from tempest.common.utils.data_utils import rand_name
+
+
+class ConsoleOutputTest(BaseComputeTest):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.client = cls.console_outputs_client
+        cls.servers_client = cls.servers_client
+        cls.name = rand_name('server')
+        resp, server = cls.servers_client.create_server(cls.name,
+                                                 cls.image_ref,
+                                                 cls.flavor_ref)
+        cls.server_id = server['id']
+
+        cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.servers_client.delete_server(cls.server_id)
+
+    @attr(type='positive')
+    def test_get_console_output(self):
+            resp, output = self.client.get_console_output(self.server_id, 10)
+            self.assertEqual(200, resp.status)
+            self.assertNotEqual(output, None)
+            lines = len(output.split('\n'))
+            self.assertEqual(lines, 10)
+
+    @attr(type='negative')
+    def test_get_console_output_invalid_server_id(self):
+        try:
+            resp, output = self.client.get_console_output('!@#$%^&*()', 10)
+        except exceptions.NotFound:
+            pass
+
+    @attr(type='positive')
+    def test_get_console_output_server_id_in_reboot_status(self):
+        try:
+            resp, output = self.servers_client.reboot(self.server_id, 'SOFT')
+            self.servers_client.wait_for_server_status(self.server_id,
+                                                        'REBOOT')
+            resp, server = self.servers_client.get_server(self.server_id)
+            if (server['status'] == 'REBOOT'):
+                resp, output = self.client.get_console_output(self.server_id,
+                                                                10)
+                self.assertEqual(200, resp.status)
+                self.assertNotEqual(output, None)
+                lines = len(output.split('\n'))
+                self.assertEqual(lines, 10)
+            else:
+                self.fail("Could not capture instance in Reboot status")
+        finally:
+            self.servers_client.wait_for_server_status(self.server_id,
+                                                        'ACTIVE')
diff --git a/tempest/tests/test_flavors.py b/tempest/tests/test_flavors.py
index d5d598f..6a38e3b 100644
--- a/tempest/tests/test_flavors.py
+++ b/tempest/tests/test_flavors.py
@@ -4,6 +4,7 @@
 
 
 class FlavorsTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_images.py b/tempest/tests/test_images.py
index 65fd4be..c5ea509 100644
--- a/tempest/tests/test_images.py
+++ b/tempest/tests/test_images.py
@@ -7,6 +7,7 @@
 from tempest import openstack
 from tempest.common.utils import data_utils
 from tempest import exceptions
+from tempest.tests import utils
 
 
 class ImagesTest(BaseComputeTest):
@@ -18,7 +19,37 @@
     def setUpClass(cls):
         cls.client = cls.images_client
         cls.servers_client = cls.servers_client
-        cls.create_image_enabled = cls.config.compute.create_image_enabled
+
+        cls.user1 = cls.config.compute.username
+        cls.user2 = cls.config.compute.alt_username
+        cls.user2_password = cls.config.compute.alt_password
+        cls.user2_tenant_name = cls.config.compute.alt_tenant_name
+        cls.multi_user = False
+        cls.image_ids = []
+
+        if (cls.user2 and cls.user1 != cls.user2 and cls.user2_password \
+            and cls.user2_tenant_name):
+
+            try:
+                cls.alt_manager = openstack.AltManager()
+                cls.alt_client = cls.alt_manager.images_client
+            except exceptions.AuthenticationFailure:
+                # multi_user is already set to false, just fall through
+                pass
+            else:
+                cls.multi_user = True
+
+    def tearDown(self):
+        """Terminate test instances created after a test is executed"""
+        for server in self.servers:
+            resp, body = self.servers_client.delete_server(server['id'])
+            if resp['status'] == '204':
+                self.servers.remove(server)
+                self.servers_client.wait_for_server_termination(server['id'])
+
+        for image_id in self.image_ids:
+            self.client.delete_image(image_id)
+            self.image_ids.remove(image_id)
 
     @attr(type='smoke')
     @unittest.skipUnless(create_image_enabled,
@@ -103,6 +134,155 @@
                             " with invalid server id")
 
     @attr(type='negative')
+    @utils.skip_unless_attr('multi_user', 'Second user not configured')
+    def test_create_image_for_server_in_another_tenant(self):
+        """Creating image of another tenant's server should be return error"""
+        server = self.create_server()
+
+        snapshot_name = rand_name('test-snap-')
+        self.assertRaises(exceptions.NotFound, self.alt_client.create_image,
+                          server['id'], snapshot_name)
+
+    @attr(type='negative')
+    def test_create_image_when_server_is_building(self):
+        """Return error when creating an image of a server that is building"""
+        server_name = rand_name('test-vm-')
+        resp, server = self.servers_client.create_server(server_name,
+                                                       self.image_ref,
+                                                       self.flavor_ref)
+        self.servers.append(server)
+        snapshot_name = rand_name('test-snap-')
+        self.assertRaises(exceptions.Duplicate, self.client.create_image,
+                          server['id'], snapshot_name)
+
+    @attr(type='negative')
+    def test_create_image_when_server_is_rebooting(self):
+        """Return error when creating an image of server that is rebooting"""
+        server = self.create_server()
+        self.servers_client.reboot(server['id'], 'HARD')
+
+        snapshot_name = rand_name('test-snap-')
+        self.assertRaises(exceptions.Duplicate, self.client.create_image,
+                          server['id'], snapshot_name)
+
+    @attr(type='negative')
+    def test_create_image_when_server_is_terminating(self):
+        """Return an error when creating image of server that is terminating"""
+        server = self.create_server()
+        self.servers_client.delete_server(server['id'])
+
+        snapshot_name = rand_name('test-snap-')
+        self.assertRaises(exceptions.Duplicate, self.client.create_image,
+                         server['id'], snapshot_name)
+
+    @attr(type='negative')
+    def test_create_second_image_when_first_image_is_being_saved(self):
+        """Disallow creating another image when first image is being saved"""
+        server = self.create_server()
+
+        try:
+            # Create first snapshot
+            snapshot_name = rand_name('test-snap-')
+            resp, body = self.client.create_image(server['id'], snapshot_name)
+            image_id = data_utils.parse_image_id(resp['location'])
+            self.image_ids.append(image_id)
+
+            # Create second snapshot
+            alt_snapshot_name = rand_name('test-snap-')
+            self.client.create_image(server['id'], alt_snapshot_name)
+        except exceptions.Duplicate:
+            pass
+
+        else:
+            self.fail("Should allow creating an image when another image of"
+                      "the server is still being saved")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1004564 is fixed")
+    def test_create_image_specify_name_over_256_chars(self):
+        """Return an error if snapshot name over 256 characters is passed"""
+        server = self.create_server()
+
+        try:
+            snapshot_name = rand_name('a' * 260)
+            self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                          server['id'], snapshot_name)
+        except:
+            self.fail("Should return 400 Bad Request if image name is over 256"
+                      " characters")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1005397 is fixed")
+    def test_create_image_specify_uuid_35_characters_or_less(self):
+        """Return an error if Image ID passed is 35 characters or less"""
+        try:
+            snapshot_name = rand_name('test-snap-')
+            test_uuid = ('a' * 35)
+            self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                              test_uuid, snapshot_name)
+        except:
+            self.fail("Should return 400 Bad Request if server uuid is 35"
+                      " characters or less")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1005397 is fixed")
+    def test_create_image_specify_uuid_37_characters_or_more(self):
+        """Return an error if Image ID passed is 37 characters or more"""
+        try:
+            snapshot_name = rand_name('test-snap-')
+            test_uuid = ('a' * 37)
+            self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                              test_uuid, snapshot_name)
+        except:
+            self.fail("Should return 400 Bad Request if server uuid is 37"
+                      " characters or more")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1006725 is fixed")
+    def test_create_image_specify_multibyte_character_image_name(self):
+        """Return an error if the image name has multi-byte characters"""
+        server = self.create_server()
+
+        try:
+            snapshot_name = rand_name('\xef\xbb\xbf')
+            self.assertRaises(exceptions.BadRequest,
+                             self.client.create_image, server['id'],
+                             snapshot_name)
+        except:
+            self.fail("Should return 400 Bad Request if multi byte characters"
+                      " are used for image name")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1005423 is fixed")
+    def test_create_image_specify_invalid_metadata(self):
+        """Return an error when creating image with invalid metadata"""
+        server = self.create_server()
+
+        try:
+            snapshot_name = rand_name('test-snap-')
+            meta = {'': ''}
+            self.assertRaises(exceptions.BadRequest, self.client.create_image,
+                              server['id'], snapshot_name, meta)
+
+        except:
+            self.fail("Should raise 400 Bad Request if meta data is invalid")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1005423 is fixed")
+    def test_create_image_specify_metadata_over_limits(self):
+        """Return an error when creating image with meta data over 256 chars"""
+        server = self.create_server()
+
+        try:
+            snapshot_name = rand_name('test-snap-')
+            meta = {'a' * 260: 'b' * 260}
+            self.assertRaises(exceptions.OverLimit, self.client.create_image,
+                              server['id'], snapshot_name, meta)
+
+        except:
+            self.fail("Should raise 413 Over Limit if meta data was too long")
+
+    @attr(type='negative')
     def test_delete_image_with_invalid_image_id(self):
         """An image should not be deleted with invalid image id"""
         try:
@@ -115,3 +295,94 @@
         else:
             self.fail("DELETE image request should rasie NotFound exception"
                         "when requested with invalid image")
+
+    @attr(type='negative')
+    def test_delete_non_existent_image(self):
+        """Return an error while trying to delete a non-existent image"""
+
+        non_existent_image_id = '11a22b9-12a9-5555-cc11-00ab112223fa'
+        self.assertRaises(exceptions.NotFound, self.client.delete_image,
+                          non_existent_image_id)
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1006033 is fixed")
+    def test_delete_image_blank_id(self):
+        """Return an error while trying to delete an image with blank Id"""
+
+        try:
+            self.assertRaises(exceptions.BadRequest, self.client.delete_image,
+                              '')
+        except:
+            self.fail("Did not return HTTP 400 BadRequest for blank image id")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1006033 is fixed")
+    def test_delete_image_non_hex_string_id(self):
+        """Return an error while trying to delete an image with non hex id"""
+
+        image_id = '11a22b9-120q-5555-cc11-00ab112223gj'
+        try:
+            self.assertRaises(exceptions.BadRequest, self.client.delete_image,
+                             image_id)
+        except:
+            self.fail("Did not return HTTP 400 BadRequest for non hex image")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1006033 is fixed")
+    def test_delete_image_negative_image_id(self):
+        """Return an error while trying to delete an image with negative id"""
+
+        try:
+            self.assertRaises(exceptions.BadRequest, self.client.delete_image,
+                              -1)
+        except:
+            self.fail("Did not return HTTP 400 BadRequest for negative image "
+            "id")
+
+    @attr(type='negative')
+    @unittest.skip("Until Bug 1006033 is fixed")
+    def test_delete_image_id_is_over_35_character_limit(self):
+        """Return an error while trying to delete image with id over limit"""
+
+        try:
+            self.assertRaises(exceptions.OverLimit, self.client.delete_image,
+                              '11a22b9-120q-5555-cc11-00ab112223gj-3fac')
+        except:
+            self.fail("Did not return HTTP 413 OverLimit for image id that "
+                      "exceeds 35 character ID length limit")
+
+    @attr(type='negative')
+    @utils.skip_unless_attr('multi_user', 'Second user not configured')
+    def test_delete_image_of_another_tenant(self):
+        """Return an error while trying to delete another tenant's image"""
+
+        server = self.create_server()
+
+        snapshot_name = rand_name('test-snap-')
+        resp, body = self.client.create_image(server['id'], snapshot_name)
+        image_id = data_utils.parse_image_id(resp['location'])
+        self.image_ids.append(image_id)
+        self.client.wait_for_image_resp_code(image_id, 200)
+        self.client.wait_for_image_status(image_id, 'ACTIVE')
+
+        # Delete image
+        self.assertRaises(exceptions.NotFound,
+                         self.alt_client.delete_image, image_id)
+
+    @attr(type='negative')
+    def test_delete_image_that_is_not_yet_active(self):
+        """Return an error while trying to delete an active that is creating"""
+
+        server = self.create_server()
+
+        snapshot_name = rand_name('test-snap-')
+        resp, body = self.client.create_image(server['id'], snapshot_name)
+        image_id = data_utils.parse_image_id(resp['location'])
+        self.image_ids.append(image_id)
+
+        # Do not wait, attempt to delete the image, ensure it's successful
+        resp, body = self.client.delete_image(image_id)
+        self.assertEqual('204', resp['status'])
+        self.image_ids.remove(image_id)
+
+        self.assertRaises(exceptions.NotFound, self.client.get_image, image_id)
diff --git a/tempest/tests/test_keypairs.py b/tempest/tests/test_keypairs.py
index d3ba213..809aa8e 100644
--- a/tempest/tests/test_keypairs.py
+++ b/tempest/tests/test_keypairs.py
@@ -7,6 +7,7 @@
 
 
 class KeyPairsTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_list_images.py b/tempest/tests/test_list_images.py
index 810e933..098667c 100644
--- a/tempest/tests/test_list_images.py
+++ b/tempest/tests/test_list_images.py
@@ -6,6 +6,7 @@
 
 
 class ListImagesTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_list_servers.py b/tempest/tests/test_list_servers.py
index fbdce4b..eaca477 100644
--- a/tempest/tests/test_list_servers.py
+++ b/tempest/tests/test_list_servers.py
@@ -10,6 +10,7 @@
 
 
 class ServerDetailsTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_server_personality.py b/tempest/tests/test_server_personality.py
index c790a6c..d4a66ad 100644
--- a/tempest/tests/test_server_personality.py
+++ b/tempest/tests/test_server_personality.py
@@ -7,6 +7,7 @@
 
 
 class ServerPersonalityTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_servers.py b/tempest/tests/test_servers.py
index ec9911f..42e6f77 100644
--- a/tempest/tests/test_servers.py
+++ b/tempest/tests/test_servers.py
@@ -4,6 +4,7 @@
 
 
 class ServersTest(BaseComputeTest):
+    _multiprocess_shared_ = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/tests/test_servers_negative.py b/tempest/tests/test_servers_negative.py
index 87f184f..48c22d3 100644
--- a/tempest/tests/test_servers_negative.py
+++ b/tempest/tests/test_servers_negative.py
@@ -112,6 +112,7 @@
                                                  self.flavor_ref)
         self.server_id = create_server['id']
         self.client.delete_server(self.server_id)
+        self.client.wait_for_server_termination(self.server_id)
         try:
             resp1, reboot_server = self.client.reboot(self.server_id, 'SOFT')
         except exceptions.NotFound:
@@ -128,6 +129,7 @@
                                                  self.flavor_ref)
         self.server_id = create_server['id']
         self.client.delete_server(self.server_id)
+        self.client.wait_for_server_termination(self.server_id)
         try:
             resp1, rebuild_server = self.client.rebuild(self.server_id,
                                                 self.image_ref_alt)