Browse Source

Add Cinder block pool metrics (#25)

The PR adds the cinder block pool metrics so that we can now retrieve
insights into the environment on the capacity all active storage pools.
This PR also creates tests for the new plugins and reduces duplication
across plugins by centralizing the runner method into the init of the
tests module.

This should now bring total code coverage to 100%

Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
Kevin Carter 2 years ago
parent
commit
e808ba1f7d

+ 4
- 0
.coveragerc View File

@@ -1,3 +1,7 @@
1 1
 [run]
2 2
 branch = True
3 3
 source = monitorstack
4
+
5
+[report]
6
+exclude_lines =
7
+    pragma: no cover

+ 1
- 1
monitorstack/cli.py View File

@@ -129,7 +129,7 @@ def process_result(results, output_format, **kwargs):
129 129
         sys.exit(exit_code)
130 130
 
131 131
 
132
-if __name__ == '__main__':
132
+if __name__ == '__main__':  # pragma: no cover
133 133
     topdir = os.path.normpath(
134 134
         os.path.join(
135 135
             os.path.abspath(

+ 72
- 0
monitorstack/plugins/os_block_pools_totals.py View File

@@ -0,0 +1,72 @@
1
+# Copyright 2017, Kevin Carter <kevin@cloudnull.com>
2
+#
3
+# Licensed under the Apache License, Version 2.0 (the "License");
4
+# you may not use this file except in compliance with the License.
5
+# You may obtain a copy of the License at
6
+#
7
+#     http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS,
11
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+"""Get block storage usage from the available pools."""
15
+
16
+import click
17
+
18
+from monitorstack import utils
19
+from monitorstack.cli import pass_context
20
+from monitorstack.utils import os_utils as ost
21
+
22
+
23
+DOC = """Get block storage totals from the available pools."""
24
+COMMAND_NAME = 'os_block_pools_totals'
25
+
26
+
27
+@click.command(COMMAND_NAME, short_help=DOC)
28
+@click.option('--config-file',
29
+              help='OpenStack configuration file',
30
+              default='openstack.ini')
31
+@pass_context
32
+def cli(ctx, config_file):
33
+    """Get nova cores quotas."""
34
+    setattr(cli, '__doc__', DOC)
35
+
36
+    output = {
37
+        'measurement_name': COMMAND_NAME,
38
+        'meta': {
39
+            'block_pools': 'totals'
40
+        },
41
+        'variables': {}
42
+    }
43
+    config = utils.read_config(config_file=config_file)['cinder']
44
+    interface = config.pop('interface', 'internal')
45
+    _ost = ost.OpenStack(os_auth_args=config)
46
+    try:
47
+        variables = output['variables']
48
+        total_capacity_gb = 0
49
+        free_capacity_gb = 0
50
+        for item in _ost.get_volume_pool_stats(interface=interface):
51
+            cap = item['capabilities']
52
+            output['meta'][cap.get('pool_name')] = True
53
+            free_capacity_gb += float(cap.get('free_capacity_gb', 0))
54
+            total_capacity_gb += float(cap.get('total_capacity_gb', 0))
55
+        else:
56
+            used_capacity = total_capacity_gb - free_capacity_gb
57
+            total_percent = 100 * (free_capacity_gb / total_capacity_gb)
58
+            variables['cinder_total_percent_used'] = total_percent
59
+            variables['cinder_total_free_capacity'] = free_capacity_gb
60
+            variables['cinder_total_used_capacity'] = used_capacity
61
+            variables['cinder_total_capacity'] = total_capacity_gb
62
+    except Exception as exp:
63
+        output['exit_code'] = 1
64
+        output['message'] = '{} failed -- {}'.format(
65
+            COMMAND_NAME,
66
+            utils.log_exception(exp=exp)
67
+        )
68
+    else:
69
+        output['exit_code'] = 0
70
+        output['message'] = '{} is ok'.format(COMMAND_NAME)
71
+    finally:
72
+        return output

+ 75
- 0
monitorstack/plugins/os_block_pools_usage.py View File

@@ -0,0 +1,75 @@
1
+# Copyright 2017, Kevin Carter <kevin@cloudnull.com>
2
+#
3
+# Licensed under the Apache License, Version 2.0 (the "License");
4
+# you may not use this file except in compliance with the License.
5
+# You may obtain a copy of the License at
6
+#
7
+#     http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS,
11
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+"""Get block storage usage from the available pools."""
15
+
16
+import click
17
+
18
+from monitorstack import utils
19
+from monitorstack.cli import pass_context
20
+from monitorstack.utils import os_utils as ost
21
+
22
+
23
+DOC = """Get block storage usage from the available pools."""
24
+COMMAND_NAME = 'os_block_pools_usage'
25
+
26
+
27
+@click.command(COMMAND_NAME, short_help=DOC)
28
+@click.option('--config-file',
29
+              help='OpenStack configuration file',
30
+              default='openstack.ini')
31
+@pass_context
32
+def cli(ctx, config_file):
33
+    """Get nova cores quotas."""
34
+    setattr(cli, '__doc__', DOC)
35
+
36
+    output = {
37
+        'measurement_name': COMMAND_NAME,
38
+        'meta': {
39
+            'block_pools': 'usage'
40
+        },
41
+        'variables': {}
42
+    }
43
+    config = utils.read_config(config_file=config_file)['cinder']
44
+    interface = config.pop('interface', 'internal')
45
+    _ost = ost.OpenStack(os_auth_args=config)
46
+    try:
47
+        variables = output['variables']
48
+        for item in _ost.get_volume_pool_stats(interface=interface):
49
+            cap = item['capabilities']
50
+            total_capacity_gb = float(cap.get('total_capacity_gb', 0))
51
+            free_capacity_gb = float(cap.get('free_capacity_gb', 0))
52
+            percent_used = 100 * (free_capacity_gb / total_capacity_gb)
53
+            pool_name = cap.get('pool_name')
54
+
55
+            output['meta'][pool_name] = True
56
+
57
+            free_metric = '{}_free_capacity_gb'.format(pool_name)
58
+            variables[free_metric] = free_capacity_gb
59
+
60
+            total_metric = '{}_total_capacity_gb'.format(pool_name)
61
+            variables[total_metric] = total_capacity_gb
62
+
63
+            percent_metric = '{}_percent_used'.format(pool_name)
64
+            variables[percent_metric] = percent_used
65
+    except Exception as exp:
66
+        output['exit_code'] = 1
67
+        output['message'] = '{} failed -- {}'.format(
68
+            COMMAND_NAME,
69
+            utils.log_exception(exp=exp)
70
+        )
71
+    else:
72
+        output['exit_code'] = 0
73
+        output['message'] = '{} is ok'.format(COMMAND_NAME)
74
+    finally:
75
+        return output

+ 3
- 3
monitorstack/utils/__init__.py View File

@@ -20,11 +20,11 @@ import time
20 20
 import traceback
21 21
 
22 22
 try:
23
-    if sys.version_info > (3, 2, 0):
23
+    if sys.version_info > (3, 2, 0):  # pragma: no cover
24 24
         import configparser as ConfigParser
25
-    else:
25
+    else:  # pragma: no cover
26 26
         import ConfigParser
27
-except ImportError:
27
+except ImportError:  # pragma: no cover
28 28
         raise SystemExit('No configparser module was found.')
29 29
 
30 30
 import diskcache

+ 47
- 9
monitorstack/utils/os_utils.py View File

@@ -13,9 +13,19 @@
13 13
 # limitations under the License.
14 14
 """OpenStack-related utilities."""
15 15
 
16
+import sys
17
+
18
+try:
19
+    if sys.version_info > (3, 2, 0):  # pragma: no cover
20
+        import urllib.parse as urlparse
21
+    else:  # pragma: no cover
22
+        import urlparse
23
+except ImportError:  # pragma: no cover
24
+        raise SystemExit('No urlparse module was found.')
25
+
16 26
 try:
17
-    from openstack import connection as os_conn
18
-except ImportError as e:
27
+    from openstack import connection as os_conn  # pragma: no cover
28
+except ImportError as e:  # pragma: no cover
19 29
     raise SystemExit('OpenStack plugins require access to the OpenStackSDK.'
20 30
                      ' Please install "python-openstacksdk".'
21 31
                      ' ERROR: %s' % str(e))
@@ -42,6 +52,22 @@ class OpenStack(object):
42 52
         """
43 53
         return os_conn.Connection(**self.os_auth_args)
44 54
 
55
+    def _session_req(self, path, service_type, interface='internal'):
56
+        """Return compute resource limits for a project.
57
+
58
+        :param path: URL path to make a request against.
59
+        :type path: str
60
+        :param interface: Interface name, normally [internal, public, admin].
61
+        :type interface: str
62
+        :returns: dict
63
+        """
64
+        endpoint_url = self.conn.session.get_endpoint(
65
+            interface=interface,
66
+            service_type=service_type
67
+        )
68
+        sess_url = urlparse.urljoin(endpoint_url, path)
69
+        return self.conn.session.get(sess_url).json()
70
+
45 71
     def get_consumer_usage(self, servers=None, marker=None, limit=512):
46 72
         """Retrieve current usage by an OpenStack cloud consumer.
47 73
 
@@ -81,14 +107,12 @@ class OpenStack(object):
81 107
         :type interface: str
82 108
         :returns: dict
83 109
         """
84
-        url = self.conn.session.get_endpoint(
85
-            interface=interface,
86
-            service_type='compute'
87
-        )
88
-        quota_data = self.conn.session.get(
89
-            url + '/os-quota-sets/' + project_id
110
+        path = '/os-quota-sets/' + project_id
111
+        return self._session_req(
112
+            path=path,
113
+            service_type='compute',
114
+            interface=interface
90 115
         )
91
-        return quota_data.json()
92 116
 
93 117
     def get_projects(self):
94 118
         """Retrieve a list of projects.
@@ -182,3 +206,17 @@ class OpenStack(object):
182 206
         :returns: str
183 207
         """
184 208
         return self.get_flavor(flavor_id=flavor_id)['name']
209
+
210
+    def get_volume_pool_stats(self, interface='internal'):
211
+        """Return volume pool usages.
212
+
213
+        :param interface: Interface name, normally [internal, public, admin].
214
+        :type interface: str
215
+        :returns: dict
216
+        """
217
+        path = '/scheduler-stats/get_pools?detail=True'
218
+        return self._session_req(
219
+            path=path,
220
+            service_type='volume',
221
+            interface=interface
222
+        )

+ 36
- 1
tests/__init__.py View File

@@ -14,16 +14,51 @@
14 14
 # limitations under the License.
15 15
 """This an __init__.py."""
16 16
 
17
+import json
17 18
 import os
18 19
 
20
+from click.testing import CliRunner
21
+
19 22
 from monitorstack import utils
23
+from monitorstack.cli import cli
20 24
 
21 25
 
22 26
 def read_config():
23
-    """Load the test config file."""
27
+    """Load the test config file.
28
+
29
+    :returns: dict
30
+    """
24 31
     os_config_file = os.path.expanduser(
25 32
         os.path.abspath(
26 33
             os.path.dirname(__file__) + '/files/test-openstack.ini'
27 34
         )
28 35
     )
29 36
     return utils.read_config(os_config_file)
37
+
38
+
39
+def runner(module, extra_args=None):
40
+    """Run click CLI tests.
41
+
42
+    :param module: Name of module to run.
43
+    :type module: str
44
+    :param extra_args: List of extra arguments to pass to the CLI.
45
+    :type extra_args: list
46
+    :returns: dict || object
47
+    """
48
+    _runner = CliRunner()
49
+    args = [
50
+        '-f', 'json',
51
+        module
52
+    ]
53
+    if extra_args:
54
+        args.extend(extra_args)
55
+    result = _runner.invoke(cli, args)
56
+    try:
57
+        return json.loads(result.output)
58
+    except ValueError:
59
+        return result
60
+
61
+
62
+def fake_version_info(major, minor, serial):
63
+    """Return tuple for fake python version info."""
64
+    return major, minor, serial

+ 41
- 2
tests/test_os_utils.py View File

@@ -159,6 +159,18 @@ class TestOsUtils(unittest.TestCase):
159 159
         """Tear down the test."""
160 160
         pass
161 161
 
162
+    def test__session_req(self):
163
+        """Test retrieving block pool stats."""
164
+        with mock.patch('openstack.connection.Connection') as MockClass:
165
+            MockClass.return_value = MockedOpenStackConn()
166
+            limits = self.osu._session_req(
167
+                path='test/path',
168
+                service_type='test-service',
169
+                interface='test-interface'
170
+            )
171
+            u = 'https://127.0.1.1/test-interface/test/path'
172
+            self.assertEquals(limits, {'url': u})
173
+
162 174
     def test_get_consumer_usage(self):
163 175
         """Test retrieving consumer usage."""
164 176
         with mock.patch('openstack.connection.Connection') as MockClass:
@@ -197,8 +209,19 @@ class TestOsUtils(unittest.TestCase):
197 209
         """Test retrieving consumer limits."""
198 210
         with mock.patch('openstack.connection.Connection') as MockClass:
199 211
             MockClass.return_value = MockedOpenStackConn()
200
-            limits = self.osu.get_compute_limits(project_id='not-a-uuid')
201
-            u = 'https://127.0.1.1/internal/compute/os-quota-sets/not-a-uuid'
212
+            limits = self.osu.get_compute_limits(project_id='not-a-uuid1')
213
+            u = 'https://127.0.1.1/os-quota-sets/not-a-uuid1'
214
+            self.assertEquals(limits, {'url': u})
215
+
216
+    def test_get_compute_limits_interface_set(self):
217
+        """Test retrieving consumer limits."""
218
+        with mock.patch('openstack.connection.Connection') as MockClass:
219
+            MockClass.return_value = MockedOpenStackConn()
220
+            limits = self.osu.get_compute_limits(
221
+                interface='test',
222
+                project_id='not-a-uuid2'
223
+            )
224
+            u = 'https://127.0.1.1/os-quota-sets/not-a-uuid2'
202 225
             self.assertEquals(limits, {'url': u})
203 226
 
204 227
     def test_get_projects(self):
@@ -244,3 +267,19 @@ class TestOsUtils(unittest.TestCase):
244 267
             MockClass.return_value = MockedOpenStackConn()
245 268
             flavor_name = self.osu.get_flavor_name(flavor_id=12345)
246 269
             self.assertEquals(flavor_name, 'test_12345')
270
+
271
+    def test_get_volume_pool_stats(self):
272
+        """Test retrieving block pool stats."""
273
+        with mock.patch('openstack.connection.Connection') as MockClass:
274
+            MockClass.return_value = MockedOpenStackConn()
275
+            limits = self.osu.get_volume_pool_stats()
276
+            u = 'https://127.0.1.1/scheduler-stats/get_pools?detail=True'
277
+            self.assertEquals(limits, {'url': u})
278
+
279
+    def test_get_volume_pool_stats_interface_set(self):
280
+        """Test retrieving block pool stats."""
281
+        with mock.patch('openstack.connection.Connection') as MockClass:
282
+            MockClass.return_value = MockedOpenStackConn()
283
+            limits = self.osu.get_volume_pool_stats(interface='test')
284
+            u = 'https://127.0.1.1/scheduler-stats/get_pools?detail=True'
285
+            self.assertEquals(limits, {'url': u})

+ 5
- 3
tests/test_plugin_kvm.py View File

@@ -21,6 +21,8 @@ from click.testing import CliRunner
21 21
 
22 22
 from monitorstack.cli import cli
23 23
 
24
+import tests  # Import the test base module
25
+
24 26
 
25 27
 def _runner(module):
26 28
     runner = CliRunner()
@@ -99,12 +101,12 @@ class TestKvm(unittest.TestCase):
99 101
     def test_run_failure_no_libvirt(self):
100 102
         """Ensure the run() method works."""
101 103
         sys.modules.pop('libvirt', None)
102
-        result = _runner('kvm')
103
-        self.assertTrue(isinstance(result, SystemExit))
104
+        result = tests.runner('kvm')
105
+        self.assertTrue(isinstance(result.exception, SystemExit))
104 106
 
105 107
     def test_run_failure(self):
106 108
         """Ensure the run() method works."""
107 109
         sys.modules['libvirt'] = LibvirtStubFailed()
108
-        result = _runner('kvm')
110
+        result = tests.runner('kvm')
109 111
         assert result['measurement_name'] == 'kvm'
110 112
         assert result['exit_code'] == 1

+ 120
- 0
tests/test_plugin_os_block.py View File

@@ -0,0 +1,120 @@
1
+# Copyright 2017, Kevin Carter <kevin@cloudnull.com>
2
+#
3
+# Licensed under the Apache License, Version 2.0 (the "License");
4
+# you may not use this file except in compliance with the License.
5
+# You may obtain a copy of the License at
6
+#
7
+#     http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS,
11
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+# See the License for the specific language governing permissions and
13
+# limitations under the License.
14
+"""Tests for the KVM plugin."""
15
+
16
+from monitorstack.utils.os_utils import OpenStack as Ost
17
+
18
+import tests  # Import the test base module
19
+
20
+
21
+def get_volume_pool_stats(*args, **kwargs):
22
+    """Mocked get_consumer_usage()."""
23
+    return [
24
+        {
25
+            'name': 'name1',
26
+            'capabilities': {
27
+                'pool_name': 'pool_name1',
28
+                'total_capacity_gb': 100,
29
+                'free_capacity_gb': 50
30
+            }
31
+        },
32
+        {
33
+            'name': 'name2',
34
+            'capabilities': {
35
+                'pool_name': 'pool_name2',
36
+                'total_capacity_gb': 100,
37
+                'free_capacity_gb': 50
38
+            }
39
+        }
40
+    ]
41
+
42
+
43
+class TestOsBlock(object):
44
+    """Tests for the os_vm.* monitors."""
45
+
46
+    def test_os_block_pools_totals_success(self, monkeypatch):
47
+        """Ensure os_block_pools_totals method works with success."""
48
+        monkeypatch.setattr(
49
+            Ost,
50
+            'get_volume_pool_stats',
51
+            get_volume_pool_stats
52
+        )
53
+        result = tests.runner(
54
+            'os_block_pools_totals',
55
+            extra_args=[
56
+                '--config-file',
57
+                'tests/files/test-openstack.ini'
58
+            ]
59
+        )
60
+        variables = result['variables']
61
+        meta = result['meta']
62
+        assert variables['cinder_total_free_capacity'] == 100
63
+        assert variables['cinder_total_percent_used'] == 50
64
+        assert variables['cinder_total_used_capacity'] == 100
65
+        assert variables['cinder_total_capacity'] == 200
66
+        assert meta['block_pools'] == 'totals'
67
+        assert meta['pool_name1'] is True
68
+        assert meta['pool_name2'] is True
69
+        assert result['measurement_name'] == 'os_block_pools_totals'
70
+
71
+    def test_os_block_pools_totals_failure(self):
72
+        """Ensure os_block_pools_totals method works with success."""
73
+        result = tests.runner(
74
+            'os_block_pools_totals',
75
+            extra_args=[
76
+                '--config-file',
77
+                'tests/files/test-openstack.ini'
78
+            ]
79
+        )
80
+        assert result['measurement_name'] == 'os_block_pools_totals'
81
+        assert result['exit_code'] == 1
82
+
83
+    def test_os_block_pools_usage_success(self, monkeypatch):
84
+        """Ensure os_block_pools_totals method works with success."""
85
+        monkeypatch.setattr(
86
+            Ost,
87
+            'get_volume_pool_stats',
88
+            get_volume_pool_stats
89
+        )
90
+        result = tests.runner(
91
+            'os_block_pools_usage',
92
+            extra_args=[
93
+                '--config-file',
94
+                'tests/files/test-openstack.ini'
95
+            ]
96
+        )
97
+        variables = result['variables']
98
+        meta = result['meta']
99
+        assert variables['pool_name1_free_capacity_gb'] == 50
100
+        assert variables['pool_name2_total_capacity_gb'] == 100
101
+        assert variables['pool_name1_percent_used'] == 50
102
+        assert variables['pool_name1_total_capacity_gb'] == 100
103
+        assert variables['pool_name2_free_capacity_gb'] == 50
104
+        assert variables['pool_name2_percent_used'] == 50
105
+        assert meta['block_pools'] == 'usage'
106
+        assert meta['pool_name1'] is True
107
+        assert meta['pool_name2'] is True
108
+        assert result['measurement_name'] == 'os_block_pools_usage'
109
+
110
+    def test_os_block_pools_usage_failure(self):
111
+        """Ensure os_block_pools_totals method works with success."""
112
+        result = tests.runner(
113
+            'os_block_pools_usage',
114
+            extra_args=[
115
+                '--config-file',
116
+                'tests/files/test-openstack.ini'
117
+            ]
118
+        )
119
+        assert result['measurement_name'] == 'os_block_pools_usage'
120
+        assert result['exit_code'] == 1

+ 100
- 30
tests/test_plugin_os_vm.py View File

@@ -13,22 +13,9 @@
13 13
 # limitations under the License.
14 14
 """Tests for the KVM plugin."""
15 15
 
16
-import json
17
-
18
-from click.testing import CliRunner
19
-
20
-from monitorstack.cli import cli
21 16
 from monitorstack.utils.os_utils import OpenStack as Ost
22 17
 
23
-
24
-def _runner(module):
25
-    runner = CliRunner()
26
-    result = runner.invoke(cli, [
27
-        '-f', 'json',
28
-        module,
29
-        '--config-file', 'tests/files/test-openstack.ini',
30
-    ])
31
-    return json.loads(result.output)
18
+import tests  # Import the test base module
32 19
 
33 20
 
34 21
 class MockProject(object):
@@ -96,21 +83,32 @@ def mock_get_compute_limits(*args, **kwargs):
96 83
     }
97 84
 
98 85
 
99
-class TestOs(object):
86
+class TestOsVm(object):
100 87
     """Tests for the os_vm.* monitors."""
101 88
 
102 89
     def test_os_vm_quota_cores_success(self, monkeypatch):
103 90
         """Ensure os_vm_quota_cores method works with success."""
104 91
         monkeypatch.setattr(Ost, 'get_projects', mock_get_projects)
105 92
         monkeypatch.setattr(Ost, 'get_compute_limits', mock_get_compute_limits)
106
-
107
-        result = _runner('os_vm_quota_cores')
93
+        result = tests.runner(
94
+            'os_vm_quota_cores',
95
+            extra_args=[
96
+                '--config-file',
97
+                'tests/files/test-openstack.ini'
98
+            ]
99
+        )
108 100
         assert result['measurement_name'] == 'os_vm_quota_cores'
109 101
         assert result['meta'] == {'quotas': 'cores'}
110 102
 
111 103
     def test_os_vm_quota_cores_failure(self):
112 104
         """Ensure os_vm_quota_cores method works with failure."""
113
-        result = _runner('os_vm_quota_cores')
105
+        result = tests.runner(
106
+            'os_vm_quota_cores',
107
+            extra_args=[
108
+                '--config-file',
109
+                'tests/files/test-openstack.ini'
110
+            ]
111
+        )
114 112
         assert result['measurement_name'] == 'os_vm_quota_cores'
115 113
         assert result['meta'] == {'quotas': 'cores'}
116 114
 
@@ -119,13 +117,25 @@ class TestOs(object):
119 117
         monkeypatch.setattr(Ost, 'get_projects', mock_get_projects)
120 118
         monkeypatch.setattr(Ost, 'get_compute_limits', mock_get_compute_limits)
121 119
 
122
-        result = _runner('os_vm_quota_instance')
120
+        result = tests.runner(
121
+            'os_vm_quota_instance',
122
+            extra_args=[
123
+                '--config-file',
124
+                'tests/files/test-openstack.ini'
125
+            ]
126
+        )
123 127
         assert result['measurement_name'] == 'os_vm_quota_instance'
124 128
         assert result['meta'] == {'quotas': 'instances'}
125 129
 
126 130
     def test_os_vm_quota_instance_failure(self):
127 131
         """Ensure os_vm_quota_cores method works with failure."""
128
-        result = _runner('os_vm_quota_instance')
132
+        result = tests.runner(
133
+            'os_vm_quota_instance',
134
+            extra_args=[
135
+                '--config-file',
136
+                'tests/files/test-openstack.ini'
137
+            ]
138
+        )
129 139
         assert result['measurement_name'] == 'os_vm_quota_instance'
130 140
         assert result['meta'] == {'quotas': 'instances'}
131 141
 
@@ -134,13 +144,25 @@ class TestOs(object):
134 144
         monkeypatch.setattr(Ost, 'get_projects', mock_get_projects)
135 145
         monkeypatch.setattr(Ost, 'get_compute_limits', mock_get_compute_limits)
136 146
 
137
-        result = _runner('os_vm_quota_ram')
147
+        result = tests.runner(
148
+            'os_vm_quota_ram',
149
+            extra_args=[
150
+                '--config-file',
151
+                'tests/files/test-openstack.ini'
152
+            ]
153
+        )
138 154
         assert result['measurement_name'] == 'os_vm_quota_ram'
139 155
         assert result['meta'] == {'quotas': 'ram'}
140 156
 
141 157
     def test_os_vm_quota_ram_failure(self):
142 158
         """Ensure os_vm_quota_ram method works with failure."""
143
-        result = _runner('os_vm_quota_ram')
159
+        result = tests.runner(
160
+            'os_vm_quota_ram',
161
+            extra_args=[
162
+                '--config-file',
163
+                'tests/files/test-openstack.ini'
164
+            ]
165
+        )
144 166
         assert result['measurement_name'] == 'os_vm_quota_ram'
145 167
         assert result['meta'] == {'quotas': 'ram'}
146 168
 
@@ -151,14 +173,26 @@ class TestOs(object):
151 173
         monkeypatch.setattr(Ost, 'get_project_name', mock_get_project_name)
152 174
         monkeypatch.setattr(Ost, 'get_consumer_usage', mock_get_consumer_usage)
153 175
 
154
-        result = _runner('os_vm_used_cores')
176
+        result = tests.runner(
177
+            'os_vm_used_cores',
178
+            extra_args=[
179
+                '--config-file',
180
+                'tests/files/test-openstack.ini'
181
+            ]
182
+        )
155 183
         assert result['measurement_name'] == 'os_vm_used_cores'
156 184
         assert result['meta']['used'] == 'cores'
157 185
         assert result['meta']['flavor_one']
158 186
 
159 187
     def test_os_vm_used_cores_failure(self):
160 188
         """Ensure os_vm_used_cores method works with failure."""
161
-        result = _runner('os_vm_used_cores')
189
+        result = tests.runner(
190
+            'os_vm_used_cores',
191
+            extra_args=[
192
+                '--config-file',
193
+                'tests/files/test-openstack.ini'
194
+            ]
195
+        )
162 196
         assert result['measurement_name'] == 'os_vm_used_cores'
163 197
         assert result['meta'] == {'used': 'cores'}
164 198
 
@@ -169,14 +203,26 @@ class TestOs(object):
169 203
         monkeypatch.setattr(Ost, 'get_project_name', mock_get_project_name)
170 204
         monkeypatch.setattr(Ost, 'get_consumer_usage', mock_get_consumer_usage)
171 205
 
172
-        result = _runner('os_vm_used_disk')
206
+        result = tests.runner(
207
+            'os_vm_used_disk',
208
+            extra_args=[
209
+                '--config-file',
210
+                'tests/files/test-openstack.ini'
211
+            ]
212
+        )
173 213
         assert result['measurement_name'] == 'os_vm_used_disk'
174 214
         assert result['meta']['used'] == 'disk'
175 215
         assert result['meta']['flavor_one']
176 216
 
177 217
     def test_os_vm_used_disk_failure(self):
178 218
         """Ensure os_vm_used_disk method works with failure."""
179
-        result = _runner('os_vm_used_disk')
219
+        result = tests.runner(
220
+            'os_vm_used_disk',
221
+            extra_args=[
222
+                '--config-file',
223
+                'tests/files/test-openstack.ini'
224
+            ]
225
+        )
180 226
         assert result['measurement_name'] == 'os_vm_used_disk'
181 227
         assert result['meta'] == {'used': 'disk'}
182 228
 
@@ -187,14 +233,26 @@ class TestOs(object):
187 233
         monkeypatch.setattr(Ost, 'get_project_name', mock_get_project_name)
188 234
         monkeypatch.setattr(Ost, 'get_consumer_usage', mock_get_consumer_usage)
189 235
 
190
-        result = _runner('os_vm_used_instance')
236
+        result = tests.runner(
237
+            'os_vm_used_instance',
238
+            extra_args=[
239
+                '--config-file',
240
+                'tests/files/test-openstack.ini'
241
+            ]
242
+        )
191 243
         assert result['measurement_name'] == 'os_vm_used_instance'
192 244
         assert result['meta']['used'] == 'instances'
193 245
         assert result['variables'] == {'test_name': 1}
194 246
 
195 247
     def test_os_vm_used_instance_failure(self):
196 248
         """Ensure os_vm_used_instance method works with failure."""
197
-        result = _runner('os_vm_used_instance')
249
+        result = tests.runner(
250
+            'os_vm_used_instance',
251
+            extra_args=[
252
+                '--config-file',
253
+                'tests/files/test-openstack.ini'
254
+            ]
255
+        )
198 256
         assert result['measurement_name'] == 'os_vm_used_instance'
199 257
         assert result['meta'] == {'used': 'instances'}
200 258
 
@@ -205,7 +263,13 @@ class TestOs(object):
205 263
         monkeypatch.setattr(Ost, 'get_project_name', mock_get_project_name)
206 264
         monkeypatch.setattr(Ost, 'get_consumer_usage', mock_get_consumer_usage)
207 265
 
208
-        result = _runner('os_vm_used_ram')
266
+        result = tests.runner(
267
+            'os_vm_used_ram',
268
+            extra_args=[
269
+                '--config-file',
270
+                'tests/files/test-openstack.ini'
271
+            ]
272
+        )
209 273
         assert result['measurement_name'] == 'os_vm_used_ram'
210 274
         assert result['meta']['used'] == 'ram'
211 275
         assert result['meta']['flavor_one']
@@ -213,6 +277,12 @@ class TestOs(object):
213 277
 
214 278
     def test_os_vm_used_ram_failure(self):
215 279
         """Ensure os_vm_used_ram method works with failure."""
216
-        result = _runner('os_vm_used_ram')
280
+        result = tests.runner(
281
+            'os_vm_used_ram',
282
+            extra_args=[
283
+                '--config-file',
284
+                'tests/files/test-openstack.ini'
285
+            ]
286
+        )
217 287
         assert result['measurement_name'] == 'os_vm_used_ram'
218 288
         assert result['meta'] == {'used': 'ram'}

+ 29
- 20
tests/test_plugin_process.py View File

@@ -13,38 +13,29 @@
13 13
 # limitations under the License.
14 14
 """Tests for the process plugin."""
15 15
 
16
-import json
16
+import mock
17 17
 
18
-from click.testing import CliRunner
19
-
20
-from monitorstack.cli import cli
21 18
 from monitorstack.plugins import process
22 19
 
20
+import tests  # Import the test base module
21
+
23 22
 
24 23
 class TestUptime(object):
25 24
     """Tests for the uptime monitor class."""
26 25
 
27 26
     def test_run_failure(self):
28 27
         """Ensure the run() method works."""
29
-        runner = CliRunner()
30 28
         process_name = 'dont-go-chasing-waterfalls'
31
-        result = runner.invoke(cli, [
32
-            '-f', 'json',
33
-            'process', process_name])
34
-        result_json = json.loads(result.output)
35
-        assert result_json['variables'] == {process_name: 0}
36
-        assert result.exit_code == 1
29
+        result = tests.runner('process', extra_args=[process_name])
30
+        assert result['variables'] == {process_name: 0}
31
+        assert result['exit_code'] == 1
37 32
 
38 33
     def test_run_success(self):
39 34
         """Ensure the run() method works."""
40
-        runner = CliRunner()
41 35
         process_name = '/'
42
-        result = runner.invoke(cli, [
43
-            '-f', 'json',
44
-            'process', process_name])
45
-        result_json = json.loads(result.output)
46
-        assert result_json['variables'] == {process_name: 1}
47
-        assert result.exit_code == 0
36
+        result = tests.runner('process', extra_args=[process_name])
37
+        assert result['variables'] == {process_name: 1}
38
+        assert result['exit_code'] == 0
48 39
 
49 40
     def test_check_process_success(self, monkeypatch):
50 41
         """Ensure the check_process() method works."""
@@ -57,5 +48,23 @@ class TestUptime(object):
57 48
 
58 49
     def test_get_cmdlines(self):
59 50
         """Ensure the get_cmdlines() method works."""
60
-        cmdlines = process.get_cmdlines()
61
-        assert isinstance(cmdlines, list)
51
+        assert isinstance(process.get_cmdlines(), list)
52
+
53
+    def test_get_cmdlines_exception(self, monkeypatch):
54
+        """Ensure the get_cmdlines() method works."""
55
+        class _RaisePid(object):
56
+            pid = 'not-a-pid'
57
+
58
+            @staticmethod
59
+            def cmdline():
60
+                raise process.psutil.NoSuchProcess('not-a-pid')
61
+
62
+        def _mock_process_iter():
63
+            return [_RaisePid, _RaisePid, _RaisePid]
64
+
65
+        with mock.patch('psutil.process_iter') as MockClass:
66
+            MockClass.return_value = _mock_process_iter()
67
+            process_name = 'dont-go-chasing-waterfalls'
68
+            result = tests.runner('process', extra_args=[process_name])
69
+            assert result['variables'] == {process_name: 0}
70
+            assert result['exit_code'] == 1

+ 5
- 10
tests/test_plugin_uptime.py View File

@@ -13,24 +13,19 @@
13 13
 # limitations under the License.
14 14
 """Tests for the uptime plugin."""
15 15
 
16
-import json
17
-
18
-from click.testing import CliRunner
19
-
20
-from monitorstack.cli import cli
21 16
 from monitorstack.plugins.uptime import get_uptime
22 17
 
18
+import tests  # Import the test base module
19
+
23 20
 
24 21
 class TestUptime(object):
25 22
     """Tests for the uptime monitor class."""
26 23
 
27 24
     def test_run(self):
28 25
         """Ensure the run() method works."""
29
-        runner = CliRunner()
30
-        result = runner.invoke(cli, ['-f', 'json', 'uptime'])
31
-        result_json = json.loads(result.output)
32
-        assert 'uptime' in result_json['variables']
33
-        assert result.exit_code == 0
26
+        result = tests.runner('uptime')
27
+        assert 'uptime' in result['variables']
28
+        assert result['exit_code'] == 0
34 29
 
35 30
     def test_get_uptime(self):
36 31
         """Ensure the cli() method works."""

Loading…
Cancel
Save