Add helpers to detect OpenStack versions 67/60067/1
authorCédric Ollivier <cedric.ollivier@orange.com>
Sat, 21 Jul 2018 07:22:39 +0000 (09:22 +0200)
committerCédric Ollivier <cedric.ollivier@orange.com>
Sat, 21 Jul 2018 07:22:39 +0000 (09:22 +0200)
It leverages on Nova API Microversions [1].

[1] https://docs.openstack.org/nova/latest/reference/api-microversion-history.html

Change-Id: I60abf9089036e56fcbcd6c2b734666ea20875ceb
Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
functest/tests/unit/utils/test_functest_utils.py
functest/utils/functest_utils.py

index d35ed8c..2b98267 100644 (file)
@@ -20,7 +20,7 @@ from functest.utils import functest_utils
 
 
 class FunctestUtilsTesting(unittest.TestCase):
-    # pylint: disable=too-many-instance-attributes
+    # pylint: disable=too-many-instance-attributes,too-many-public-methods
 
     readline = 0
     test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
@@ -218,6 +218,126 @@ class FunctestUtilsTesting(unittest.TestCase):
                                                      self.test_file),
                              'test_image_name')
 
+    def test_nova_version_exc1(self):
+        # pylint: disable=protected-access
+        cloud = mock.Mock()
+        cloud._compute_client.request.return_value = None
+        self.assertEqual(functest_utils.get_nova_version(cloud), None)
+        cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+    def test_nova_version_exc2(self):
+        # pylint: disable=protected-access
+        cloud = mock.Mock()
+        cloud._compute_client.request.return_value = {"version": None}
+        self.assertEqual(functest_utils.get_nova_version(cloud), None)
+        cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+    def test_nova_version_exc3(self):
+        # pylint: disable=protected-access
+        cloud = mock.Mock()
+        cloud._compute_client.request.return_value = {
+            "version": {"version": None}}
+        self.assertEqual(functest_utils.get_nova_version(cloud), None)
+        cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+    def test_nova_version_exc4(self):
+        # pylint: disable=protected-access
+        cloud = mock.Mock()
+        cloud._compute_client.request.return_value = {
+            "version": {"version": "a.b"}}
+        self.assertEqual(functest_utils.get_nova_version(cloud), None)
+        cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+    def test_nova_version(self):
+        # pylint: disable=protected-access
+        cloud = mock.Mock()
+        cloud._compute_client.request.return_value = {
+            "version": {"version": "2.1"}}
+        self.assertEqual(functest_utils.get_nova_version(cloud), (2, 1))
+        cloud._compute_client.request.assert_called_once_with('/', 'GET')
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 61))
+    def test_openstack_version1(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(
+            cloud), "Rocky or newer")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 60))
+    def test_openstack_version2(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Queens")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 43))
+    def test_openstack_version3(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Pike")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 39))
+    def test_openstack_version4(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Ocata")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 26))
+    def test_openstack_version5(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Newton")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 13))
+    def test_openstack_version6(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Mitaka")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 4))
+    def test_openstack_version7(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(
+            functest_utils.get_openstack_version(cloud), "Liberty")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(2, 1))
+    def test_openstack_version8(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(functest_utils.get_openstack_version(cloud), "Kilo")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(1, 9))
+    def test_openstack_version9(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(
+            functest_utils.get_openstack_version(cloud), "Unknown")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=(3, 1))
+    def test_openstack_version10(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(
+            functest_utils.get_openstack_version(cloud), "Rocky or newer")
+        args[0].assert_called_once_with(cloud)
+
+    @mock.patch('functest.utils.functest_utils.get_nova_version',
+                return_value=None)
+    def test_openstack_version_exc(self, *args):
+        cloud = mock.Mock()
+        self.assertEqual(
+            functest_utils.get_openstack_version(cloud), "Unknown")
+        args[0].assert_called_once_with(cloud)
+
 
 if __name__ == "__main__":
     logging.disable(logging.CRITICAL)
index b614af3..c5950c9 100644 (file)
@@ -44,7 +44,7 @@ def execute_command(cmd, info=False, error_msg="",
             ofd.write(line)
         else:
             line = line.replace('\n', '')
-            print (line)
+            print(line)
             sys.stdout.flush()
     if output_file:
         ofd.close()
@@ -72,3 +72,65 @@ def get_parameter_from_yaml(parameter, yfile):
             raise ValueError("The parameter %s is not defined in"
                              " %s" % (parameter, yfile))
     return value
+
+
+def get_nova_version(cloud):
+    """ Get Nova API microversion
+
+    Returns:
+
+    - Nova API microversion
+    - None on operation error
+    """
+    # pylint: disable=protected-access
+    try:
+        request = cloud._compute_client.request("/", "GET")
+        LOGGER.debug('cloud._compute_client.request: %s', request)
+        version = request["version"]["version"]
+        major, minor = version.split('.')
+        LOGGER.debug('nova version: %s', (int(major), int(minor)))
+        return (int(major), int(minor))
+    except Exception:  # pylint: disable=broad-except
+        LOGGER.exception("Cannot detect Nova version")
+        return None
+
+
+def get_openstack_version(cloud):
+    """ Detect OpenStack version via Nova API microversion
+
+    It follows MicroversionHistory_.
+
+    Returns:
+
+    - OpenStack release
+    - Unknown on operation error
+
+    .. _MicroversionHistory:
+    https://docs.openstack.org/nova/latest/reference/api-microversion-history.html
+    """
+    version = get_nova_version(cloud)
+    try:
+        assert version
+        if version > (2, 60):
+            osversion = "Rocky or newer"
+        elif version > (2, 53):
+            osversion = "Queens"
+        elif version > (2, 42):
+            osversion = "Pike"
+        elif version > (2, 38):
+            osversion = "Ocata"
+        elif version > (2, 25):
+            osversion = "Newton"
+        elif version > (2, 12):
+            osversion = "Mitaka"
+        elif version > (2, 3):
+            osversion = "Liberty"
+        elif version >= (2, 1):
+            osversion = "Kilo"
+        else:
+            osversion = "Unknown"
+        LOGGER.info('Detect OpenStack version: %s', osversion)
+        return osversion
+    except AssertionError:
+        LOGGER.exception("Cannot detect OpenStack version")
+        return "Unknown"