add memory_load scenario 03/13703/5
authorJingLu5 <lvjing5@huawei.com>
Fri, 6 May 2016 01:58:41 +0000 (09:58 +0800)
committerJingLu5 <lvjing5@huawei.com>
Mon, 23 May 2016 00:22:33 +0000 (08:22 +0800)
JIRA: YARDSTICK-259

This scenario reads memory usage statistics on a Linux host.
memory usage statistics are read using the utility 'free'.

Signed-off-by: JingLu5 <lvjing5@huawei.com>
Change-Id: I677aa65ca264dc77a963bf8b6913a729fbf031be

samples/memload.yaml [new file with mode: 0644]
tests/unit/benchmark/scenarios/compute/memload_sample_output.txt [new file with mode: 0644]
tests/unit/benchmark/scenarios/compute/test_memload.py [new file with mode: 0644]
yardstick/benchmark/scenarios/compute/memload.py [new file with mode: 0644]

diff --git a/samples/memload.yaml b/samples/memload.yaml
new file mode 100644 (file)
index 0000000..0acba21
--- /dev/null
@@ -0,0 +1,32 @@
+---
+# Sample benchmark task config file
+# Reading memory load/statistics
+
+schema: "yardstick:task:0.1"
+
+scenarios:
+-
+  type: MEMORYload
+  options:
+    interval: 1
+    count: 1
+
+  host: kratos.demo
+
+  runner:
+    type: Duration
+    duration: 60
+
+context:
+  name: demo
+  image: yardstick-trusty-server
+  flavor: yardstick-flavor
+  user: ubuntu
+
+  servers:
+    kratos:
+      floating_ip: true
+
+  networks:
+    test:
+      cidr: '10.0.1.0/24'
diff --git a/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt b/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt
new file mode 100644 (file)
index 0000000..c23917f
--- /dev/null
@@ -0,0 +1,5 @@
+             total       used       free     shared    buffers     cached
+Mem:     263753976   76737332  187016644       2844     853528   67252400
+-/+ buffers/cache:    8631404  255122572
+Swap:    268029948          0  268029948
+
diff --git a/tests/unit/benchmark/scenarios/compute/test_memload.py b/tests/unit/benchmark/scenarios/compute/test_memload.py
new file mode 100644 (file)
index 0000000..cdf518d
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+
+##############################################################################
+# Copyright (c) 2016 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.memload.MEMLoad
+
+import mock
+import unittest
+import os
+
+from yardstick.benchmark.scenarios.compute import memload
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.memload.ssh')
+class MEMLoadTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.ctx = {
+            'host': {
+                'ip': '172.16.0.137',
+                'user': 'root',
+                'key_filename': "mykey.key"
+            }
+        }
+
+        self.result = {}
+
+    def test_memload_successful_setup(self, mock_ssh):
+        m = memload.MEMLoad({}, self.ctx)
+        mock_ssh.SSH().execute.return_value = (0, '', '')
+
+        m.setup()
+        self.assertIsNotNone(m.client)
+        self.assertTrue(m.setup_done)
+
+    def test_execute_command_success(self, mock_ssh):
+        m = memload.MEMLoad({}, self.ctx)
+        mock_ssh.SSH().execute.return_value = (0, '', '')
+        m.setup()
+
+        expected_result = 'abcdefg'
+        mock_ssh.SSH().execute.return_value = (0, expected_result, '')
+        result = m._execute_command("foo")
+        self.assertEqual(result, expected_result)
+
+    def test_execute_command_failed(self, mock_ssh):
+        m = memload.MEMLoad({}, self.ctx)
+        mock_ssh.SSH().execute.return_value = (0, '', '')
+        m.setup()
+
+        mock_ssh.SSH().execute.return_value = (127, '', 'Failed executing \
+                                               command')
+        self.assertRaises(RuntimeError, m._execute_command,
+                          "cat /proc/meminfo")
+
+    def test_get_mem_usage_successful(self, mock_ssh):
+        options = {
+            "interval": 1,
+            "count": 1
+        }
+        args = {"options": options}
+        m = memload.MEMLoad(args, self.ctx)
+        mock_ssh.SSH().execute.return_value = (0, '', '')
+        m.setup()
+
+        output = self._read_file("memload_sample_output.txt")
+        mock_ssh.SSH().execute.return_value = (0, output, '')
+        result = m._get_mem_usage()
+        expected_result = {"max": {"used": 76737332, "cached": 67252400,
+                           "free": 187016644, "shared": 2844,
+                           "total": 263753976, "buffers": 853528},
+                           "average": {"used": 76737332, "cached": 67252400,
+                           "free": 187016644, "shared": 2844,
+                           "total": 263753976, "buffers": 853528},
+                           "free": {"memory0": {"used": "76737332",
+                           "cached": "67252400", "free": "187016644",
+                           "shared": "2844", "total": "263753976",
+                           "buffers": "853528"}}}
+        self.assertEqual(result, expected_result)
+
+    def _read_file(self, filename):
+        curr_path = os.path.dirname(os.path.abspath(__file__))
+        output = os.path.join(curr_path, filename)
+        with open(output) as f:
+            sample_output = f.read()
+        return sample_output
+
diff --git a/yardstick/benchmark/scenarios/compute/memload.py b/yardstick/benchmark/scenarios/compute/memload.py
new file mode 100644 (file)
index 0000000..bafd896
--- /dev/null
@@ -0,0 +1,122 @@
+##############################################################################
+# Copyright (c) 2016 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
+##############################################################################
+
+"""Memory load and statistics."""
+
+import logging
+import yardstick.ssh as ssh
+
+from yardstick.benchmark.scenarios import base
+
+LOG = logging.getLogger(__name__)
+
+
+class MEMLoad(base.Scenario):
+    """Collect memory statistics and system load.
+
+    This scenario reads memory usage statistics on a Linux host.
+
+    memory usage statistics are read using the utility 'free'.
+
+    Parameters
+        interval - Time interval to measure memory usage.
+        Continuously display the result delay interval seconds apart.
+        type:       [int]
+        unit:       seconds
+        default:    1
+
+        count - specifies a # of measurments for each test
+        type:       [int]
+        unit:       N/A
+        default:    1
+    """
+    __scenario_type__ = "MEMORYload"
+
+    def __init__(self, scenario_cfg, context_cfg):
+        """Scenario construction."""
+        self.scenario_cfg = scenario_cfg
+        self.context_cfg = context_cfg
+        self.setup_done = False
+
+    def setup(self):
+        """Scenario setup."""
+        host = self.context_cfg['host']
+        user = host.get('user', 'ubuntu')
+        ip = host.get('ip', None)
+        key_filename = host.get('key_filename', '~/.ssh/id_rsa')
+
+        LOG.info("user:%s, host:%s", user, ip)
+        self.client = ssh.SSH(user, ip, key_filename=key_filename)
+        self.client.wait(timeout=600)
+
+        self.setup_done = True
+
+    def _execute_command(self, cmd):
+        """Execute a command on server."""
+        LOG.info("Executing: %s" % cmd)
+        status, stdout, stderr = self.client.execute(cmd)
+        if status:
+            raise RuntimeError("Failed executing command: ",
+                               cmd, stderr)
+        return stdout
+
+    def _filtrate_result(self, result):
+        fields = []
+        free = {}
+        ite = 0
+        average = {'total': 0, 'used': 0, 'free': 0, 'cached': 0, 'shared': 0,
+                   'buffers': 0}
+        maximum = {'total': 0, 'used': 0, 'free': 0, 'cached': 0, 'shared': 0,
+                   'buffers': 0}
+
+        for row in result.split('\n'):
+            line = row.split()
+
+            if line and line[0] == 'total':
+                # header fields
+                fields = line[:]
+            elif line and line[0] == 'Mem:':
+                memory = 'memory' + str(ite)
+                ite += 1
+                values = line[1:]
+                if values and len(values) == len(fields):
+                    free[memory] = dict(zip(fields, values))
+
+        for entry in free:
+            for item in average:
+                average[item] += int(free[entry][item])
+
+            for item in maximum:
+                if int(free[entry][item]) > maximum[item]:
+                    maximum[item] = int(free[entry][item])
+
+        for item in average:
+            average[item] = average[item] / len(free)
+
+        return {'free': free, 'average': average, 'max': maximum}
+
+    def _get_mem_usage(self):
+        """Get memory usage using free."""
+        options = self.scenario_cfg['options']
+        interval = options.get("interval", 1)
+        count = options.get("count", 1)
+
+        cmd = "free -s %s -c %s" % (interval, count)
+
+        result = self._execute_command(cmd)
+        filtrated_result = self._filtrate_result(result)
+
+        return filtrated_result
+
+    def run(self, result):
+        """Read processor statistics."""
+        if not self.setup_done:
+            self.setup()
+
+        result.update(self._get_mem_usage())