Added the ability to reboot OpenStack server instances 47/48247/2
authorspisarski <s.pisarski@cablelabs.com>
Fri, 1 Dec 2017 18:06:23 +0000 (11:06 -0700)
committerspisarski <s.pisarski@cablelabs.com>
Tue, 5 Dec 2017 00:00:21 +0000 (16:00 -0800)
JIRA: SNAPS-243

Change-Id: I7232ee14cac81d39d86e7391a4e006b8276ed536
Signed-off-by: spisarski <s.pisarski@cablelabs.com>
docs/how-to-use/IntegrationTests.rst
snaps/openstack/create_instance.py
snaps/openstack/tests/create_instance_tests.py
snaps/openstack/utils/nova_utils.py

index a11afb9..df8859f 100644 (file)
@@ -548,6 +548,9 @@ create_instance_tests.py - CreateInstanceSingleNetworkTests
 | test_ssh_client_fip_reverse_engineer  | Nova 2        | Ensures that an instance can be reverse engineered and    |
 |                                       | Neutron 2     | allows for a floating IP to be added after initialization |
 +---------------------------------------+---------------+-----------------------------------------------------------+
+| test_ssh_client_fip_after_reboot      | Nova 2        | Ensures that an instance can be reached over SSH after    |
+|                                       | Neutron 2     | a reboot call has been issued                             |
++---------------------------------------+---------------+-----------------------------------------------------------+
 | test_ssh_client_fip_second_creator    | Nova 2        | Ensures that an instance can be reached over SSH via a    |
 |                                       | Neutron 2     | second identical creator object                           |
 +---------------------------------------+---------------+-----------------------------------------------------------+
index d7300e6..0105ef0 100644 (file)
@@ -23,6 +23,7 @@ from snaps.openstack.openstack_creator import OpenStackComputeObject
 from snaps.openstack.utils import glance_utils, cinder_utils, settings_utils
 from snaps.openstack.utils import neutron_utils
 from snaps.openstack.utils import nova_utils
+from snaps.openstack.utils.nova_utils import RebootType
 from snaps.provisioning import ansible_utils
 
 __author__ = 'spisarski'
@@ -787,6 +788,17 @@ class OpenStackVmInstance(OpenStackComputeObject):
             logger.warning('Security group not removed - ' + str(e))
             return False
 
+    def reboot(self, reboot_type=RebootType.soft):
+        """
+        Issues a reboot call
+        :param reboot_type: instance of
+                            snaps.openstack.utils.nova_utils.RebootType
+                            enumeration
+        :return:
+        """
+        nova_utils.reboot_server(
+            self._nova, self.__vm, reboot_type=reboot_type)
+
 
 def generate_creator(os_creds, vm_inst, image_config, keypair_config=None):
     """
index 1721ce3..6eb21b5 100644 (file)
@@ -48,6 +48,8 @@ from snaps.openstack.create_volume import OpenStackVolume
 from snaps.openstack.tests import openstack_tests, validation_utils
 from snaps.openstack.tests.os_source_file_test import (
     OSIntegrationTestCase, OSComponentTestCase)
+from snaps.openstack.utils import nova_utils
+from snaps.openstack.utils.nova_utils import RebootType
 from snaps.openstack.utils import nova_utils, settings_utils, neutron_utils
 
 __author__ = 'spisarski'
@@ -765,6 +767,62 @@ class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
 
         self.assertTrue(validate_ssh_client(inst_creator))
 
+    def test_ssh_client_fip_after_reboot(self):
+        """
+        Tests the ability to access a VM via SSH and a floating IP after it has
+        been rebooted.
+        """
+        port_settings = PortConfig(
+            name=self.port_1_name,
+            network_name=self.pub_net_config.network_settings.name)
+
+        instance_settings = VmInstanceConfig(
+            name=self.vm_inst_name,
+            flavor=self.flavor_creator.flavor_settings.name,
+            port_settings=[port_settings],
+            security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
+            floating_ip_settings=[FloatingIpConfig(
+                name=self.floating_ip_name, port_name=self.port_1_name,
+                router_name=self.pub_net_config.router_settings.name)])
+
+        inst_creator = OpenStackVmInstance(
+            self.os_creds, instance_settings,
+            self.image_creator.image_settings,
+            keypair_settings=self.keypair_creator.keypair_settings)
+        self.inst_creators.append(inst_creator)
+
+        # block=True will force the create() method to block until the
+        vm_inst = inst_creator.create(block=True)
+        self.assertIsNotNone(vm_inst)
+
+        self.assertTrue(inst_creator.vm_active(block=True))
+
+        ip = inst_creator.get_port_ip(port_settings.name)
+        self.assertTrue(check_dhcp_lease(inst_creator, ip))
+
+        self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
+
+        self.assertTrue(validate_ssh_client(inst_creator))
+
+        # Test default reboot which should be 'SOFT'
+        inst_creator.reboot()
+        # Lag time to allow for shutdown routine to take effect
+        time.sleep(10)
+        self.assertTrue(check_dhcp_lease(inst_creator, ip))
+        self.assertTrue(validate_ssh_client(inst_creator))
+
+        # Test 'SOFT' reboot
+        inst_creator.reboot(reboot_type=RebootType.soft)
+        time.sleep(10)
+        self.assertTrue(check_dhcp_lease(inst_creator, ip))
+        self.assertTrue(validate_ssh_client(inst_creator))
+
+        # Test 'HARD' reboot
+        inst_creator.reboot(reboot_type=RebootType.hard)
+        time.sleep(10)
+        self.assertTrue(check_dhcp_lease(inst_creator, ip))
+        self.assertTrue(validate_ssh_client(inst_creator))
+
     def test_ssh_client_fip_after_init(self):
         """
         Tests the ability to assign a floating IP to an already initialized
index b735ee2..2d569e6 100644 (file)
@@ -15,6 +15,7 @@
 
 import logging
 
+import enum
 import os
 import time
 from cryptography.hazmat.backends import default_backend
@@ -281,6 +282,21 @@ def get_server_info(nova, server):
         return vm._info
     return None
 
+def reboot_server(nova, server, reboot_type=None):
+    """
+    Returns a dictionary of a VMs info as returned by OpenStack
+    :param nova: the Nova client
+    :param server: the old server object
+    :param reboot_type: Acceptable values 'SOFT', 'HARD'
+                        (api uses SOFT as the default)
+    :return: a dict of the info if VM exists else None
+    """
+    vm = __get_latest_server_os_object(nova, server)
+    if vm:
+        vm.reboot(reboot_type=reboot_type.value)
+    else:
+        raise ServerNotFoundError('Cannot locate server')
+
 
 def create_keys(key_size=2048):
     """
@@ -730,7 +746,22 @@ def detach_volume(nova, server, volume, timeout=None):
         return get_server_object_by_id(nova, server.id)
 
 
+class RebootType(enum.Enum):
+    """
+    A rule's direction
+    """
+    soft = 'SOFT'
+    hard = 'HARD'
+
+
 class NovaException(Exception):
     """
     Exception when calls to the Keystone client cannot be served properly
     """
+
+
+class ServerNotFoundError(Exception):
+    """
+    Exception when operations to a VM/Server is requested and the OpenStack
+    Server instance cannot be located
+    """