Add  another scenario testcase  test_minimum_basic

Current test used as a basic check for multiple services

- Changed the nova reboot to HARD in order to refresh connection for
  attahced devices
- Created a volume snapshot and delete it before reboot instance
- Write data to the attached volume and read post instance reboot.

Related-Bug: #1860913

Change-Id: I4151715954b3a12e6c790836d4b7bd50c0407720
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 7aa96b2..801bb5c 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -471,7 +471,8 @@
 
         self.addCleanup(self.snapshots_client.wait_for_resource_deletion,
                         snapshot['id'])
-        self.addCleanup(self.snapshots_client.delete_snapshot, snapshot['id'])
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.snapshots_client.delete_snapshot, snapshot['id'])
         waiters.wait_for_volume_resource_status(self.snapshots_client,
                                                 snapshot['id'], 'available')
         snapshot = self.snapshots_client.show_snapshot(
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 5aac19c..8cafd1f 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.common import custom_matchers
 from tempest.common import utils
 from tempest.common import waiters
@@ -29,24 +31,11 @@
 
     """This is a basic minimum scenario test.
 
-    This test below:
+    These tests below:
     * across the multiple components
     * as a regular user
     * with and without optional parameters
     * check command outputs
-
-    Steps:
-    1. Create image
-    2. Create keypair
-    3. Boot instance with keypair and get list of instances
-    4. Create volume and show list of volumes
-    5. Attach volume to instance and getlist of volumes
-    6. Add IP to instance
-    7. Create and add security group to instance
-    8. Check SSH connection to instance
-    9. Reboot instance
-    10. Check SSH connection to instance after reboot
-
     """
 
     def nova_show(self, server):
@@ -67,8 +56,9 @@
             volume, custom_matchers.MatchesDictExceptForKeys(
                 got_volume, excluded_keys=excluded_keys))
 
-    def nova_reboot(self, server):
-        self.servers_client.reboot_server(server['id'], type='SOFT')
+    def nova_reboot(self, server, hard=False):
+        self.servers_client.reboot_server(server['id'],
+                                          type="HARD" if hard else "SOFT")
         waiters.wait_for_server_status(self.servers_client,
                                        server['id'], 'ACTIVE')
 
@@ -96,9 +86,37 @@
                    '%s' % (secgroup['id'], server['id']))
             raise exceptions.TimeoutException(msg)
 
+    def _get_floating_ip_in_server_addresses(self, floating_ip, server):
+        for addresses in server['addresses'].values():
+            for address in addresses:
+                if (address['OS-EXT-IPS:type'] == 'floating' and
+                        address['addr'] == floating_ip['floating_ip_address']):
+                    return address
+
+    def _is_floating_ip_detached_from_server(self, server, floating_ip):
+        server_info = self.servers_client.show_server(
+            server['id'])['server']
+        address = self._get_floating_ip_in_server_addresses(
+            floating_ip, server_info)
+        return (not address)
+
     @decorators.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
     @utils.services('compute', 'volume', 'image', 'network')
     def test_minimum_basic_scenario(self):
+        """This is a basic minimum scenario with multiple components
+
+        Steps:
+        1. Create image
+        2. Create keypair
+        3. Boot instance with keypair and get list of instances
+        4. Create volume and show list of volumes
+        5. Attach volume to instance and getlist of volumes
+        6. Add IP to instance
+        7. Create and add security group to instance
+        8. Check SSH connection to instance
+        9. Reboot instance
+        10. Check SSH connection to instance after reboot
+        """
         image = self.image_create()
         keypair = self.create_keypair()
 
@@ -121,7 +139,7 @@
         floating_ip = None
         server = self.servers_client.show_server(server['id'])['server']
         if (CONF.network_feature_enabled.floating_ips and
-            CONF.network.floating_network_name):
+                CONF.network.floating_network_name):
             fip = self.create_floating_ip(server)
             floating_ip = self.associate_floating_ip(
                 fip, server)
@@ -154,3 +172,116 @@
             waiters.wait_for_server_floating_ip(
                 self.servers_client, server, floating_ip,
                 wait_for_disassociate=True)
+
+            if not test_utils.call_until_true(
+                    self._is_floating_ip_detached_from_server,
+                    CONF.compute.build_timeout,
+                    CONF.compute.build_interval, server, floating_ip):
+                msg = ("Floating IP '%s' should not be in server addresses: %s"
+                       % (floating_ip['floating_ip_address'],
+                          server['addresses']))
+                raise exceptions.TimeoutException(msg)
+
+    @decorators.idempotent_id('a8fd48ec-1d01-4895-b932-02321661ec1e')
+    @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+                          "Cinder volume snapshots are disabled")
+    @utils.services('compute', 'volume', 'image', 'network')
+    def test_minimum_basic_instance_hard_reboot_after_vol_snap_deletion(self):
+        """Test compute hard reboot after volume snapshot deleted
+
+        Steps:
+        1. Create image
+        2. Create keypair
+        3. Boot instance with keypair and get list of instances
+        4. Create volume and show list of volumes
+        5. Attach volume to instance and getlist of volumes
+        6. Create a snapshot from volume
+        7. Add IP to instance
+        8. Create and add security group to instance
+        9. Check SSH connection to instance
+        10. Write data timestamp to the attached volume
+        11. Delete volume snapshot before reboot instance
+        12. Reboot instance (HARD)
+        13. Check SSH connection to instance after reboot
+        14. Verify attached disk data timestamp post instance reboot
+        """
+        image = self.image_create()
+        keypair = self.create_keypair()
+
+        server = self.create_server(image_id=image, key_name=keypair['name'])
+        servers = self.servers_client.list_servers()['servers']
+        self.assertIn(server['id'], [x['id'] for x in servers])
+
+        self.nova_show(server)
+
+        volume = self.create_volume()
+        volumes = self.volumes_client.list_volumes()['volumes']
+        self.assertIn(volume['id'], [x['id'] for x in volumes])
+
+        self.cinder_show(volume)
+
+        volume = self.nova_volume_attach(server, volume)
+        self.addCleanup(self.nova_volume_detach, server, volume)
+        snapshot = self.create_volume_snapshot(volume['id'], force=True)
+        self.cinder_show(volume)
+
+        floating_ip = None
+        server = self.servers_client.show_server(server['id'])['server']
+        if (CONF.network_feature_enabled.floating_ips and
+                CONF.network.floating_network_name):
+            fip = self.create_floating_ip(server)
+            floating_ip = self.associate_floating_ip(
+                fip, server)
+            # fetch the server again to make sure the addresses were refreshed
+            # after associating the floating IP
+            server = self.servers_client.show_server(server['id'])['server']
+            address = self._get_floating_ip_in_server_addresses(
+                floating_ip, server)
+            self.assertIsNotNone(
+                address,
+                "Failed to find floating IP '%s' in server addresses: %s" %
+                (floating_ip['floating_ip_address'], server['addresses']))
+            ssh_ip = floating_ip['floating_ip_address']
+        else:
+            ssh_ip = self.get_server_ip(server)
+
+        self.create_and_add_security_group_to_server(server)
+
+        # check that we can SSH to the server before reboot
+        self.linux_client = self.get_remote_client(
+            ssh_ip, private_key=keypair['private_key'],
+            server=server)
+
+        # write data to the volume before reboot instance
+        timestamp_before = self.create_timestamp(
+            ssh_ip, private_key=keypair['private_key'], server=server)
+        # delete the snapshot before rebooting the instance
+        self.snapshots_client.delete_snapshot(snapshot['id'])
+        self.snapshots_client.wait_for_resource_deletion(snapshot['id'])
+        self.nova_reboot(server, hard=True)
+
+        # check that we can SSH to the server after reboot
+        # (both connections are part of the scenario)
+        self.linux_client = self.get_remote_client(
+            ssh_ip, private_key=keypair['private_key'],
+            server=server)
+
+        self.check_disks()
+        timestamp_after = self.get_timestamp(
+            ssh_ip, private_key=keypair['private_key'], server=server)
+        self.assertEqual(timestamp_before, timestamp_after)
+        if floating_ip:
+            # delete the floating IP, this should refresh the server addresses
+            self.disassociate_floating_ip(floating_ip)
+            waiters.wait_for_server_floating_ip(
+                self.servers_client, server, floating_ip,
+                wait_for_disassociate=True)
+
+            if not test_utils.call_until_true(
+                self._is_floating_ip_detached_from_server,
+                    CONF.compute.build_timeout, CONF.compute.build_interval,
+                    server, floating_ip):
+                msg = ("Floating IP '%s' should not be in server addresses: %s"
+                       % (floating_ip['floating_ip_address'],
+                          server['addresses']))
+                raise exceptions.TimeoutException(msg)