Add common openstack opertation scenarios: flavor & server 37/39037/19
authorJingLu5 <lvjing5@huawei.com>
Thu, 10 Aug 2017 06:00:58 +0000 (06:00 +0000)
committerJingLu5 <lvjing5@huawei.com>
Fri, 11 Aug 2017 01:13:24 +0000 (01:13 +0000)
JIRA: YARDSTICK-781

This patch adds some common openstack opertation scenarios

Change-Id: I9e84a8894fe9b9c1754a45a0ddfdf93739164b9a
Signed-off-by: JingLu5 <lvjing5@huawei.com>
tests/unit/benchmark/scenarios/lib/test_create_flavor.py [new file with mode: 0644]
tests/unit/benchmark/scenarios/lib/test_create_server.py [new file with mode: 0644]
tests/unit/benchmark/scenarios/lib/test_delete_flavor.py [new file with mode: 0644]
tests/unit/benchmark/scenarios/lib/test_get_flavor.py [new file with mode: 0644]
yardstick/benchmark/scenarios/lib/create_flavor.py [new file with mode: 0644]
yardstick/benchmark/scenarios/lib/create_server.py [new file with mode: 0644]
yardstick/benchmark/scenarios/lib/delete_flavor.py [new file with mode: 0644]
yardstick/benchmark/scenarios/lib/get_flavor.py [new file with mode: 0644]
yardstick/common/openstack_utils.py

diff --git a/tests/unit/benchmark/scenarios/lib/test_create_flavor.py b/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
new file mode 100644 (file)
index 0000000..036ae95
--- /dev/null
@@ -0,0 +1,37 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+import mock
+
+from yardstick.benchmark.scenarios.lib.create_flavor import CreateFlavor
+
+
+class CreateFlavorTestCase(unittest.TestCase):
+
+    @mock.patch('yardstick.common.openstack_utils.create_flavor')
+    def test_create_flavor(self, mock_create_flavor):
+        options = {
+            'flavor_name': 'yardstick_test_flavor',
+            'vcpus': '2',
+            'ram': '1024',
+            'disk': '100',
+            'is_public': 'True'
+        }
+        args = {"options": options}
+        obj = CreateFlavor(args, {})
+        obj.run({})
+        self.assertTrue(mock_create_flavor.called)
+
+
+def main():
+    unittest.main()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/unit/benchmark/scenarios/lib/test_create_server.py b/tests/unit/benchmark/scenarios/lib/test_create_server.py
new file mode 100644 (file)
index 0000000..7c41931
--- /dev/null
@@ -0,0 +1,42 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+import mock
+
+from yardstick.benchmark.scenarios.lib.create_server import CreateServer
+
+
+class CreateServerTestCase(unittest.TestCase):
+
+    @mock.patch('yardstick.common.openstack_utils.create_instance_and_wait_for_active')
+    @mock.patch('yardstick.common.openstack_utils.get_nova_client')
+    @mock.patch('yardstick.common.openstack_utils.get_glance_client')
+    @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
+    def test_create_server(self, mock_get_nova_client, mock_get_neutron_client,
+                           mock_get_glance_client, mock_create_instance_and_wait_for_active):
+        scenario_cfg = {
+            'options' : {
+                 'openstack_paras': 'example'
+             },
+             'output': 'server'
+        }
+        obj = CreateServer(scenario_cfg, {})
+        obj.run({})
+        self.assertTrue(mock_get_nova_client.called)
+        self.assertTrue(mock_get_glance_client.called)
+        self.assertTrue(mock_get_neutron_client.called)
+        self.assertTrue(mock_create_instance_and_wait_for_active.called)
+
+
+def main():
+    unittest.main()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py b/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
new file mode 100644 (file)
index 0000000..4a91b89
--- /dev/null
@@ -0,0 +1,35 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+import mock
+
+from yardstick.benchmark.scenarios.lib.delete_flavor import DeleteFlavor
+
+
+class DeleteFlavorTestCase(unittest.TestCase):
+
+    @mock.patch('yardstick.common.openstack_utils.delete_flavor')
+    @mock.patch('yardstick.common.openstack_utils.get_nova_client')
+    def test_delete_flavor(self, mock_get_nova_client, mock_delete_flavor):
+        options = {
+            'flavor_name': 'yardstick_test_flavor'
+        }
+        args = {"options": options}
+        obj = DeleteFlavor(args, {})
+        obj.run({})
+        self.assertTrue(mock_get_nova_client.called)
+        self.assertTrue(mock_delete_flavor.called)
+
+
+def main():
+    unittest.main()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/unit/benchmark/scenarios/lib/test_get_flavor.py b/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
new file mode 100644 (file)
index 0000000..bf12e0a
--- /dev/null
@@ -0,0 +1,33 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+import mock
+
+from yardstick.benchmark.scenarios.lib.get_flavor import GetFlavor
+
+
+class GetFlavorTestCase(unittest.TestCase):
+
+    @mock.patch('yardstick.common.openstack_utils.get_flavor_by_name')
+    def test_get_flavor(self, mock_get_flavor_by_name):
+        options = {
+            'flavor_name': 'yardstick_test_flavor'
+        }
+        args = {"options": options}
+        obj = GetFlavor(args, {})
+        obj.run({})
+        self.assertTrue(mock_get_flavor_by_name.called)
+
+
+def main():
+    unittest.main()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/yardstick/benchmark/scenarios/lib/create_flavor.py b/yardstick/benchmark/scenarios/lib/create_flavor.py
new file mode 100644 (file)
index 0000000..05c7099
--- /dev/null
@@ -0,0 +1,65 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+import yardstick.common.openstack_utils as op_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateFlavor(base.Scenario):
+    """Create an OpenStack flavor"""
+
+    __scenario_type__ = "CreateFlavor"
+
+    def __init__(self, scenario_cfg, context_cfg):
+        self.scenario_cfg = scenario_cfg
+        self.context_cfg = context_cfg
+        self.options = self.scenario_cfg['options']
+
+        self.flavor_name = self.options.get("flavor_name", "TestFlavor")
+        self.vcpus = self.options.get("vcpus", 2)
+        self.ram = self.options.get("ram", 1024)
+        self.disk = self.options.get("disk", 100)
+        self.public = self.options.get("is_public", True)
+
+        self.setup_done = False
+
+    def setup(self):
+        """scenario setup"""
+
+        self.setup_done = True
+
+    def run(self, result):
+        """execute the test"""
+
+        if not self.setup_done:
+            self.setup()
+
+        LOG.info("Creating flavor %s with %s vcpus, %sMB ram and %sGB disk",
+                 self.flavor_name, self.vcpus, self.ram, self.disk)
+        paras = {'is_public': self.public}
+        flavor = op_utils.create_flavor(self.flavor_name,
+                                        self.ram, self.vcpus, self.disk,
+                                        **paras)
+
+        if flavor:
+            LOG.info("Create flavor successful!")
+            values = [flavor.id]
+        else:
+            LOG.info("Create flavor failed!")
+            values = []
+
+        keys = self.scenario_cfg.get('output', '').split()
+        return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/create_server.py b/yardstick/benchmark/scenarios/lib/create_server.py
new file mode 100644 (file)
index 0000000..45c0bfd
--- /dev/null
@@ -0,0 +1,72 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+import yardstick.common.openstack_utils as op_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class CreateServer(base.Scenario):
+    """Create an OpenStack server"""
+
+    __scenario_type__ = "CreateSever"
+
+    def __init__(self, scenario_cfg, context_cfg):
+        self.scenario_cfg = scenario_cfg
+        self.context_cfg = context_cfg
+        self.options = self.scenario_cfg['options']
+
+        self.image_name = self.options.get("image_name", None)
+        self.flavor_name = self.options.get("flavor_name", None)
+        self.openstack = self.options.get("openstack_paras", None)
+
+        self.glance_client = op_utils.get_glance_client()
+        self.neutron_client = op_utils.get_neutron_client()
+        self.nova_client = op_utils.get_nova_client()
+
+        self.setup_done = False
+
+    def setup(self):
+        """scenario setup"""
+
+        self.setup_done = True
+
+    def run(self, result):
+        """execute the test"""
+
+        if not self.setup_done:
+            self.setup()
+
+        if self.image_name is not None:
+            self.openstack['image'] = op_utils.get_image_id(self.glance_client,
+                                                            self.image_name)
+        if self.flavor_name is not None:
+            self.openstack['flavor'] = op_utils.get_flavor_id(self.nova_client,
+                                                              self.flavor_name)
+
+        vm = op_utils.create_instance_and_wait_for_active(self.openstack)
+
+        if vm:
+            LOG.info("Create server successful!")
+        else:
+            LOG.error("Create server failed!")
+
+        try:
+            keys = self.scenario_cfg.get('output', '').split()
+        except KeyError:
+            pass
+        else:
+            values = [vm.id]
+            return self._push_to_outputs(keys, values)
diff --git a/yardstick/benchmark/scenarios/lib/delete_flavor.py b/yardstick/benchmark/scenarios/lib/delete_flavor.py
new file mode 100644 (file)
index 0000000..b30c374
--- /dev/null
@@ -0,0 +1,56 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+import yardstick.common.openstack_utils as op_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class DeleteFlavor(base.Scenario):
+    """Delete an OpenStack flavor by name"""
+
+    __scenario_type__ = "DeleteFlavor"
+
+    def __init__(self, scenario_cfg, context_cfg):
+        self.scenario_cfg = scenario_cfg
+        self.context_cfg = context_cfg
+        self.options = self.scenario_cfg['options']
+
+        self.flavor_name = self.options.get("flavor_name", "TestFlavor")
+        self.flavor_id = None
+
+        self.nova_client = op_utils.get_nova_client()
+
+        self.setup_done = False
+
+    def setup(self):
+        """scenario setup"""
+
+        self.setup_done = True
+
+    def run(self, result):
+        """execute the test"""
+
+        if not self.setup_done:
+            self.setup()
+
+        self.flavor_id = op_utils.get_flavor_id(self.nova_client, self.flavor_name)
+        LOG.info("Deleting flavor: %s", self.flavor_name)
+        status = op_utils.delete_flavor(self.flavor_id)
+
+        if status:
+            LOG.info("Delete flavor successful!")
+        else:
+            LOG.info("Delete flavor failed!")
diff --git a/yardstick/benchmark/scenarios/lib/get_flavor.py b/yardstick/benchmark/scenarios/lib/get_flavor.py
new file mode 100644 (file)
index 0000000..d5e3394
--- /dev/null
@@ -0,0 +1,54 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from __future__ import print_function
+from __future__ import absolute_import
+
+import logging
+
+from yardstick.benchmark.scenarios import base
+import yardstick.common.openstack_utils as op_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class GetFlavor(base.Scenario):
+    """Get an OpenStack flavor by name"""
+
+    __scenario_type__ = "GetFlavor"
+
+    def __init__(self, scenario_cfg, context_cfg):
+        self.scenario_cfg = scenario_cfg
+        self.context_cfg = context_cfg
+        self.options = self.scenario_cfg['options']
+        self.flavor_name = self.options.get("flavor_name", "TestFlavor")
+        self.setup_done = False
+
+    def setup(self):
+        """scenario setup"""
+
+        self.setup_done = True
+
+    def run(self, result):
+        """execute the test"""
+
+        if not self.setup_done:
+            self.setup()
+
+        LOG.info("Querying flavor: %s", self.flavor_name)
+        flavor = op_utils.get_flavor_by_name(self.flavor_name)
+        if flavor:
+            LOG.info("Get flavor successful!")
+            values = [self._change_obj_to_dict(flavor)]
+        else:
+            LOG.info("Get flavor: no flavor matched!")
+            values = []
+
+        keys = self.scenario_cfg.get('output', '').split()
+        return self._push_to_outputs(keys, values)
index f027b79..51be688 100644 (file)
@@ -264,81 +264,29 @@ def create_aggregate_with_host(nova_client, aggregate_name, av_zone,
         return True
 
 
-def create_instance(flavor_name,
-                    image_id,
-                    network_id,
-                    instance_name="instance-vm",
-                    confdrive=True,
-                    userdata=None,
-                    av_zone='',
-                    fixed_ip=None,
-                    files=None):    # pragma: no cover
-    nova_client = get_nova_client()
+def create_instance(json_body):    # pragma: no cover
     try:
-        flavor = nova_client.flavors.find(name=flavor_name)
-    except:
-        flavors = nova_client.flavors.list()
-        log.exception("Error: Flavor '%s' not found. Available flavors are: "
-                      "\n%s", flavor_name, flavors)
+        return get_nova_client().servers.create(**json_body)
+    except Exception:
+        log.exception("Error create instance failed")
         return None
-    if fixed_ip is not None:
-        nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
-    else:
-        nics = {"net-id": network_id}
-    if userdata is None:
-        instance = nova_client.servers.create(
-            name=instance_name,
-            flavor=flavor,
-            image=image_id,
-            nics=[nics],
-            availability_zone=av_zone,
-            files=files
-        )
-    else:
-        instance = nova_client.servers.create(
-            name=instance_name,
-            flavor=flavor,
-            image=image_id,
-            nics=[nics],
-            config_drive=confdrive,
-            userdata=userdata,
-            availability_zone=av_zone,
-            files=files
-        )
-    return instance
-
-
-def create_instance_and_wait_for_active(flavor_name,
-                                        image_id,
-                                        network_id,
-                                        instance_name="instance-vm",
-                                        config_drive=False,
-                                        userdata="",
-                                        av_zone='',
-                                        fixed_ip=None,
-                                        files=None):    # pragma: no cover
+
+
+def create_instance_and_wait_for_active(json_body):    # pragma: no cover
     SLEEP = 3
     VM_BOOT_TIMEOUT = 180
     nova_client = get_nova_client()
-    instance = create_instance(flavor_name,
-                               image_id,
-                               network_id,
-                               instance_name,
-                               config_drive,
-                               userdata,
-                               av_zone=av_zone,
-                               fixed_ip=fixed_ip,
-                               files=files)
+    instance = create_instance(json_body)
     count = VM_BOOT_TIMEOUT / SLEEP
     for n in range(count, -1, -1):
         status = get_instance_status(nova_client, instance)
         if status.lower() == "active":
             return instance
         elif status.lower() == "error":
-            log.error("The instance %s went to ERROR status.", instance_name)
+            log.error("The instance went to ERROR status.")
             return None
         time.sleep(SLEEP)
-    log.error("Timeout booting the instance %s.", instance_name)
+    log.error("Timeout booting the instance.")
     return None
 
 
@@ -395,6 +343,15 @@ def get_server_by_name(name):   # pragma: no cover
         raise
 
 
+def create_flavor(name, ram, vcpus, disk, **kwargs):   # pragma: no cover
+    try:
+        return get_nova_client().flavors.create(name, ram, vcpus, disk, **kwargs)
+    except Exception:
+        log.exception("Error [create_flavor(nova_client, %s, %s, %s, %s, %s)]",
+                      name, ram, disk, vcpus, kwargs['is_public'])
+        return None
+
+
 def get_image_by_name(name):    # pragma: no cover
     images = get_nova_client().images.list()
     try:
@@ -403,6 +360,16 @@ def get_image_by_name(name):    # pragma: no cover
         log.exception('No image matched')
 
 
+def get_flavor_id(nova_client, flavor_name):    # pragma: no cover
+    flavors = nova_client.flavors.list(detailed=True)
+    flavor_id = ''
+    for f in flavors:
+        if f.name == flavor_name:
+            flavor_id = f.id
+            break
+    return flavor_id
+
+
 def get_flavor_by_name(name):   # pragma: no cover
     flavors = get_nova_client().flavors.list()
     try:
@@ -426,6 +393,16 @@ def check_status(status, name, iterations, interval):   # pragma: no cover
     return False
 
 
+def delete_flavor(flavor_id):    # pragma: no cover
+    try:
+        get_nova_client().flavors.delete(flavor_id)
+    except Exception:
+        log.exception("Error [delete_flavor(nova_client, %s)]", flavor_id)
+        return False
+    else:
+        return True
+
+
 # *********************************************
 #   NEUTRON
 # *********************************************