Browse Source

Update monitorstack to use updated openstacksdk and es

This change updates the functions so that they work with the most up to date
OpenStack SDK, and adds an elasticsearch output format.

Tests have been udpated to pass newer versions of flake8 and py3

Zuul project config has been added

Change-Id: If46d3fb8e2b2e4aa5e21bf7da470945b05d216cf
Signed-off-by: cloudnull <kevin@cloudnull.com>
changes/42/637242/14
Kevin Carter 4 months ago
parent
commit
034228e754
No account linked to committer's email address

+ 52
- 0
bindep.txt View File

@@ -0,0 +1,52 @@
1
+# This file facilitates OpenStack-CI package installation
2
+# before the execution of any tests.
3
+#
4
+# See the following for details:
5
+#  - https://docs.openstack.org/infra/bindep/
6
+#  - https://git.openstack.org/cgit/openstack-infra/bindep
7
+#
8
+# Even if the role does not make use of this facility, it
9
+# is better to have this file empty, otherwise OpenStack-CI
10
+# will fall back to installing its default packages which
11
+# will potentially be detrimental to the tests executed.
12
+#
13
+# Note:
14
+# This file is maintained in the openstack-ansible-tests repository.
15
+# https://git.openstack.org/cgit/openstack/openstack-ansible-tests/tree/bindep.txt
16
+# If you need to remove or add extra dependencies, you should modify
17
+# the central file instead and once your change is accepted then update
18
+# this file as well. The purpose of this file is to ensure that Python and
19
+# Ansible have all their necessary binary requirements on the test host before
20
+# tox executes. Any binary requirements needed by services/roles should be
21
+# installed by those roles in their applicable package install tasks, not through
22
+# using this file.
23
+#
24
+
25
+# The gcc compiler
26
+gcc
27
+
28
+# Base requirements for Ubuntu
29
+git-core          [platform:dpkg]
30
+libssl-dev        [platform:dpkg]
31
+libffi-dev        [platform:dpkg]
32
+python2.7         [platform:dpkg]
33
+python-apt        [platform:dpkg]
34
+python-dev        [platform:dpkg]
35
+python3           [platform:dpkg]
36
+python3-apt       [platform:dpkg]
37
+python3-dev       [platform:dpkg]
38
+
39
+# Base requirements for RPM distros
40
+gcc-c++           [platform:rpm]
41
+git               [platform:rpm]
42
+libffi-devel      [platform:rpm]
43
+openssl-devel     [platform:rpm]
44
+python-devel      [platform:rpm]
45
+python2-dnf       [platform:fedora]
46
+
47
+# For SELinux
48
+libselinux-python [platform:redhat]
49
+libsemanage-python [platform:redhat]
50
+
51
+# Required for compressing collected log files in CI
52
+gzip

+ 17
- 0
etc/openstack.ini View File

@@ -14,6 +14,13 @@ auth_url = https://127.0.0.1:5000/v3
14 14
 username = admin
15 15
 password = Secrete
16 16
 
17
+# NOTE(Cloudnull):
18
+#   If the system already has a clouds.yaml configuration file in place, monitorstack
19
+#   can use this config by default. Create the "cloud" section and set the cloud option.
20
+#   When using this section, no other OpenStack options are needed.
21
+# [cloud]
22
+# cloud = default
23
+
17 24
 [keystone]
18 25
 # NOTE(cloudnull):
19 26
 #  When using keystone V3 you will need the .*domain_name configuration options.
@@ -45,3 +52,13 @@ project_name = ironic
45 52
 user_domain_name = users
46 53
 project_domain_name = projects
47 54
 password = SuperSecrete
55
+
56
+[elasticsearch]
57
+# List of hosts. Note, items in this list are strings with the hostname or IP only.
58
+hosts = ['localhost']
59
+# Optional settings when using authenticated environments.
60
+# http_auth = ('user', 'secret')
61
+
62
+# Optional settings when using SSL.
63
+# scheme="https"
64
+# port=443

+ 6
- 2
monitorstack/cli.py View File

@@ -83,7 +83,8 @@ VALID_OUTPUT_FORMATS = [
83 83
     'json',
84 84
     'line',
85 85
     'telegraf',
86
-    'rax-maas'
86
+    'rax-maas',
87
+    'elasticsearch'
87 88
 ]
88 89
 
89 90
 
@@ -96,6 +97,9 @@ VALID_OUTPUT_FORMATS = [
96 97
         ', '.join(VALID_OUTPUT_FORMATS)
97 98
     ),
98 99
 )
100
+@click.option('--config-file',
101
+              help='MonitorStack configuration file',
102
+              default='openstack.ini')
99 103
 @click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode.')
100 104
 @pass_context
101 105
 def cli(*args, **kwargs):
@@ -122,7 +126,7 @@ def process_result(results, output_format, **kwargs):
122 126
 
123 127
     exit_code = 0
124 128
     for result in results:
125
-        output_formatter(result)
129
+        output_formatter(result, kwargs['config_file'])
126 130
         if result['exit_code'] != 0:
127 131
             exit_code = result['exit_code']
128 132
     else:

+ 40
- 4
monitorstack/common/formatters.py View File

@@ -18,15 +18,17 @@ import time
18 18
 
19 19
 import click
20 20
 
21
+from monitorstack import utils
21 22
 
22
-def write_json(result):
23
+
24
+def write_json(result, config_file):
23 25
     """Output in raw JSON format."""
24 26
     output = json.dumps(result, indent=2)
25 27
     click.echo(output)
26 28
     return True
27 29
 
28 30
 
29
-def write_line(result):
31
+def write_line(result, config_file):
30 32
     """Output in line format."""
31 33
     for key, value in result['variables'].items():
32 34
         click.echo("{} {}".format(key, value))
@@ -102,7 +104,7 @@ def _telegraf_line_format(sets, quote=False):
102 104
     return ','.join(store).rstrip(',')
103 105
 
104 106
 
105
-def write_telegraf(result):
107
+def write_telegraf(result, config_file):
106 108
     """Output in telegraf format."""
107 109
     resultant = [result['measurement_name']]
108 110
     if 'meta' in result:
@@ -120,7 +122,7 @@ def write_telegraf(result):
120 122
     return True
121 123
 
122 124
 
123
-def write_rax_maas(result):
125
+def write_rax_maas(result, config_file):
124 126
     """Output in Rackspace Monitoring as a Service format."""
125 127
     status = ['status']
126 128
     if result['exit_code'] == 0:
@@ -142,3 +144,37 @@ def write_rax_maas(result):
142 144
         click.echo(' '.join(metric))
143 145
 
144 146
     return True
147
+
148
+
149
+def write_elasticsearch(result, config_file):
150
+    """Output in elasticsearch format."""
151
+    import datetime
152
+    from elasticsearch import Elasticsearch
153
+
154
+    config = utils.read_config(config_file=config_file)
155
+    if 'elasticsearch' in config:
156
+        elastcisearch_config = config['elasticsearch']
157
+        es = Elasticsearch(**elastcisearch_config)
158
+    else:
159
+        es = Elasticsearch()
160
+
161
+    doc = {
162
+        'author': 'openstack',
163
+        'text': result['message'],
164
+        'timestamp': datetime.datetime.now(),
165
+        'measurement_name': result['measurement_name'],
166
+        'meta': result['meta'],
167
+        'variables': result['variables'],
168
+        'status': result['exit_code']
169
+    }
170
+
171
+    res = es.index(
172
+        index="monitorstack-{}".format(
173
+            datetime.date.today().strftime("%Y-%m-%d")
174
+        ),
175
+        id=_current_time(),
176
+        doc_type='openstack-metrics',
177
+        body=doc
178
+    )
179
+
180
+    click.echo(res['result'])

+ 13
- 5
monitorstack/plugins/os_block_pools_totals.py View File

@@ -25,7 +25,7 @@ COMMAND_NAME = 'os_block_pools_totals'
25 25
 
26 26
 @click.command(COMMAND_NAME, short_help=DOC)
27 27
 @click.option('--config-file',
28
-              help='OpenStack configuration file',
28
+              help='MonitorStack configuration file',
29 29
               default='openstack.ini')
30 30
 @pass_context
31 31
 def cli(ctx, config_file):
@@ -43,14 +43,22 @@ def cli(ctx, config_file):
43 43
         },
44 44
         'variables': {}
45 45
     }
46
-    config = utils.read_config(config_file=config_file)['cinder']
47
-    interface = config.pop('interface', 'internal')
48
-    _ost = ost.OpenStack(os_auth_args=config)
46
+    os_config = utils.read_config(
47
+        config_file=config_file,
48
+        no_config_fatal=False
49
+    )
50
+    service_config = os_config.get('cinder')
51
+    cloud_config = os_config.get('cloud')
52
+    if service_config:
53
+        _ost = ost.OpenStack(os_auth_args=service_config)
54
+    else:
55
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
56
+
49 57
     try:
50 58
         variables = output['variables']
51 59
         total_capacity_gb = 0
52 60
         free_capacity_gb = 0
53
-        for item in _ost.get_volume_pool_stats(interface=interface):
61
+        for item in _ost.get_volume_pool_stats():
54 62
             cap = item['capabilities']
55 63
             output['meta'][cap.get('pool_name')] = True
56 64
             free_capacity_gb += float(cap.get('free_capacity_gb', 0))

+ 28
- 19
monitorstack/plugins/os_block_pools_usage.py View File

@@ -25,7 +25,7 @@ COMMAND_NAME = 'os_block_pools_usage'
25 25
 
26 26
 @click.command(COMMAND_NAME, short_help=DOC)
27 27
 @click.option('--config-file',
28
-              help='OpenStack configuration file',
28
+              help='MonitorStack configuration file',
29 29
               default='openstack.ini')
30 30
 @pass_context
31 31
 def cli(ctx, config_file):
@@ -43,28 +43,37 @@ def cli(ctx, config_file):
43 43
         },
44 44
         'variables': {}
45 45
     }
46
-    config = utils.read_config(config_file=config_file)['cinder']
47
-    interface = config.pop('interface', 'internal')
48
-    _ost = ost.OpenStack(os_auth_args=config)
46
+    os_config = utils.read_config(
47
+        config_file=config_file,
48
+        no_config_fatal=False
49
+    )
50
+    service_config = os_config.get('cinder')
51
+    cloud_config = os_config.get('cloud')
52
+    if service_config:
53
+        _ost = ost.OpenStack(os_auth_args=service_config)
54
+    else:
55
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
56
+
49 57
     try:
50 58
         variables = output['variables']
51
-        for item in _ost.get_volume_pool_stats(interface=interface):
52
-            cap = item['capabilities']
53
-            total_capacity_gb = float(cap.get('total_capacity_gb', 0))
54
-            free_capacity_gb = float(cap.get('free_capacity_gb', 0))
55
-            percent_used = 100 * (free_capacity_gb / total_capacity_gb)
56
-            pool_name = cap.get('pool_name')
57
-
58
-            output['meta'][pool_name] = True
59
-
60
-            free_metric = '{}_free_capacity_gb'.format(pool_name)
61
-            variables[free_metric] = free_capacity_gb
59
+        for item in _ost.get_volume_pool_stats():
60
+            cap = item.capabilities
61
+            pool_name = cap.get('volume_backend_name') or item.name
62
+            if pool_name in output['meta']:
63
+                continue
64
+            else:
65
+                output['meta'][pool_name] = True
66
+                total_capacity_gb = float(cap.get('total_capacity_gb', 0))
67
+                free_capacity_gb = float(cap.get('free_capacity_gb', 0))
68
+                percent_used = 100 * (free_capacity_gb / total_capacity_gb)
69
+                free_metric = '{}_free_capacity_gb'.format(pool_name)
70
+                variables[free_metric] = free_capacity_gb
62 71
 
63
-            total_metric = '{}_total_capacity_gb'.format(pool_name)
64
-            variables[total_metric] = total_capacity_gb
72
+                total_metric = '{}_total_capacity_gb'.format(pool_name)
73
+                variables[total_metric] = total_capacity_gb
65 74
 
66
-            percent_metric = '{}_percent_used'.format(pool_name)
67
-            variables[percent_metric] = percent_used
75
+                percent_metric = '{}_percent_used'.format(pool_name)
76
+                variables[percent_metric] = percent_used
68 77
     except Exception as exp:
69 78
         output['exit_code'] = 1
70 79
         output['message'] = '{} failed -- {}'.format(

+ 14
- 4
monitorstack/plugins/os_vm_quota_cores.py View File

@@ -25,7 +25,7 @@ COMMAND_NAME = 'os_vm_quota_cores'
25 25
 
26 26
 @click.command(COMMAND_NAME, short_help=DOC)
27 27
 @click.option('--config-file',
28
-              help='OpenStack configuration file',
28
+              help='MonitorStack configuration file',
29 29
               default='openstack.ini')
30 30
 @pass_context
31 31
 def cli(ctx, config_file):
@@ -43,9 +43,19 @@ def cli(ctx, config_file):
43 43
         },
44 44
         'variables': {}
45 45
     }
46
-    nova_config = utils.read_config(config_file=config_file)['nova']
47
-    interface = nova_config.pop('interface', 'internal')
48
-    _ost = ost.OpenStack(os_auth_args=nova_config)
46
+    os_config = utils.read_config(
47
+        config_file=config_file,
48
+        no_config_fatal=False
49
+    )
50
+    service_config = os_config.get('nova')
51
+    cloud_config = os_config.get('cloud')
52
+    if service_config:
53
+        interface = service_config.pop('interface', 'internal')
54
+        _ost = ost.OpenStack(os_auth_args=service_config)
55
+    else:
56
+        interface = 'internal'
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
58
+
49 59
     try:
50 60
         variables = output['variables']
51 61
         for project in _ost.get_projects():

+ 14
- 4
monitorstack/plugins/os_vm_quota_instance.py View File

@@ -25,7 +25,7 @@ COMMAND_NAME = 'os_vm_quota_instance'
25 25
 
26 26
 @click.command(COMMAND_NAME, short_help=DOC)
27 27
 @click.option('--config-file',
28
-              help='OpenStack configuration file',
28
+              help='MonitorStack configuration file',
29 29
               default='openstack.ini')
30 30
 @pass_context
31 31
 def cli(ctx, config_file):
@@ -43,9 +43,19 @@ def cli(ctx, config_file):
43 43
         },
44 44
         'variables': {}
45 45
     }
46
-    nova_config = utils.read_config(config_file=config_file)['nova']
47
-    interface = nova_config.pop('interface', 'internal')
48
-    _ost = ost.OpenStack(os_auth_args=nova_config)
46
+    os_config = utils.read_config(
47
+        config_file=config_file,
48
+        no_config_fatal=False
49
+    )
50
+    service_config = os_config.get('nova')
51
+    cloud_config = os_config.get('cloud')
52
+    if service_config:
53
+        interface = service_config.pop('interface', 'internal')
54
+        _ost = ost.OpenStack(os_auth_args=service_config)
55
+    else:
56
+        interface = 'internal'
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
58
+
49 59
     try:
50 60
         variables = output['variables']
51 61
         for project in _ost.get_projects():

+ 14
- 4
monitorstack/plugins/os_vm_quota_ram.py View File

@@ -25,7 +25,7 @@ COMMAND_NAME = 'os_vm_quota_ram'
25 25
 
26 26
 @click.command(COMMAND_NAME, short_help=DOC)
27 27
 @click.option('--config-file',
28
-              help='OpenStack configuration file',
28
+              help='MonitorStack configuration file',
29 29
               default='openstack.ini')
30 30
 @pass_context
31 31
 def cli(ctx, config_file):
@@ -43,9 +43,19 @@ def cli(ctx, config_file):
43 43
         },
44 44
         'variables': {}
45 45
     }
46
-    nova_config = utils.read_config(config_file=config_file)['nova']
47
-    interface = nova_config.pop('interface', 'internal')
48
-    _ost = ost.OpenStack(os_auth_args=nova_config)
46
+    os_config = utils.read_config(
47
+        config_file=config_file,
48
+        no_config_fatal=False
49
+    )
50
+    service_config = os_config.get('nova')
51
+    cloud_config = os_config.get('cloud')
52
+    if service_config:
53
+        interface = service_config.pop('interface', 'internal')
54
+        _ost = ost.OpenStack(os_auth_args=service_config)
55
+    else:
56
+        interface = 'internal'
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
58
+
49 59
     try:
50 60
         variables = output['variables']
51 61
         for project in _ost.get_projects():

+ 11
- 3
monitorstack/plugins/os_vm_used_cores.py View File

@@ -27,7 +27,7 @@ COMMAND_NAME = 'os_vm_used_cores'
27 27
 
28 28
 @click.command(COMMAND_NAME, short_help=DOC)
29 29
 @click.option('--config-file',
30
-              help='OpenStack configuration file',
30
+              help='MonitorStack configuration file',
31 31
               default='openstack.ini')
32 32
 @pass_context
33 33
 def cli(ctx, config_file):
@@ -45,10 +45,18 @@ def cli(ctx, config_file):
45 45
         },
46 46
         'variables': {}
47 47
     }
48
+    os_config = utils.read_config(
49
+        config_file=config_file,
50
+        no_config_fatal=False
51
+    )
52
+    service_config = os_config.get('nova')
53
+    cloud_config = os_config.get('cloud')
54
+    if service_config:
55
+        _ost = ost.OpenStack(os_auth_args=service_config)
56
+    else:
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
48 58
 
49 59
     used_collection = collections.Counter()
50
-    nova_config = utils.read_config(config_file=config_file)['nova']
51
-    _ost = ost.OpenStack(os_auth_args=nova_config)
52 60
     try:
53 61
         flavors = _ost.get_flavors()
54 62
         variables = output['variables']

+ 11
- 3
monitorstack/plugins/os_vm_used_disk.py View File

@@ -27,7 +27,7 @@ COMMAND_NAME = 'os_vm_used_disk'
27 27
 
28 28
 @click.command(COMMAND_NAME, short_help=DOC)
29 29
 @click.option('--config-file',
30
-              help='OpenStack configuration file',
30
+              help='MonitorStack configuration file',
31 31
               default='openstack.ini')
32 32
 @pass_context
33 33
 def cli(ctx, config_file):
@@ -45,10 +45,18 @@ def cli(ctx, config_file):
45 45
         },
46 46
         'variables': {}
47 47
     }
48
+    os_config = utils.read_config(
49
+        config_file=config_file,
50
+        no_config_fatal=False
51
+    )
52
+    service_config = os_config.get('nova')
53
+    cloud_config = os_config.get('cloud')
54
+    if service_config:
55
+        _ost = ost.OpenStack(os_auth_args=service_config)
56
+    else:
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
48 58
 
49 59
     used_collection = collections.Counter()
50
-    nova_config = utils.read_config(config_file=config_file)['nova']
51
-    _ost = ost.OpenStack(os_auth_args=nova_config)
52 60
     try:
53 61
         flavors = _ost.get_flavors()
54 62
         variables = output['variables']

+ 11
- 3
monitorstack/plugins/os_vm_used_instance.py View File

@@ -27,7 +27,7 @@ COMMAND_NAME = 'os_vm_used_instance'
27 27
 
28 28
 @click.command(COMMAND_NAME, short_help=DOC)
29 29
 @click.option('--config-file',
30
-              help='OpenStack configuration file',
30
+              help='MonitorStack configuration file',
31 31
               default='openstack.ini')
32 32
 @pass_context
33 33
 def cli(ctx, config_file):
@@ -45,10 +45,18 @@ def cli(ctx, config_file):
45 45
         },
46 46
         'variables': {}
47 47
     }
48
+    os_config = utils.read_config(
49
+        config_file=config_file,
50
+        no_config_fatal=False
51
+    )
52
+    service_config = os_config.get('nova')
53
+    cloud_config = os_config.get('cloud')
54
+    if service_config:
55
+        _ost = ost.OpenStack(os_auth_args=service_config)
56
+    else:
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
48 58
 
49 59
     used_collection = collections.Counter()
50
-    nova_config = utils.read_config(config_file=config_file)['nova']
51
-    _ost = ost.OpenStack(os_auth_args=nova_config)
52 60
     try:
53 61
         variables = output['variables']
54 62
         for used in _ost.get_consumer_usage():

+ 11
- 3
monitorstack/plugins/os_vm_used_ram.py View File

@@ -27,7 +27,7 @@ COMMAND_NAME = 'os_vm_used_ram'
27 27
 
28 28
 @click.command(COMMAND_NAME, short_help=DOC)
29 29
 @click.option('--config-file',
30
-              help='OpenStack configuration file',
30
+              help='MonitorStack configuration file',
31 31
               default='openstack.ini')
32 32
 @pass_context
33 33
 def cli(ctx, config_file):
@@ -45,10 +45,18 @@ def cli(ctx, config_file):
45 45
         },
46 46
         'variables': {}
47 47
     }
48
+    os_config = utils.read_config(
49
+        config_file=config_file,
50
+        no_config_fatal=False
51
+    )
52
+    service_config = os_config.get('nova')
53
+    cloud_config = os_config.get('cloud')
54
+    if service_config:
55
+        _ost = ost.OpenStack(os_auth_args=service_config)
56
+    else:
57
+        _ost = ost.OpenStack(os_auth_args=cloud_config)
48 58
 
49 59
     used_collection = collections.Counter()
50
-    nova_config = utils.read_config(config_file=config_file)['nova']
51
-    _ost = ost.OpenStack(os_auth_args=nova_config)
52 60
     try:
53 61
         flavors = _ost.get_flavors()
54 62
         variables = output['variables']

+ 7
- 4
monitorstack/utils/__init__.py View File

@@ -21,11 +21,11 @@ import traceback
21 21
 
22 22
 try:
23 23
     if sys.version_info > (3, 2, 0):  # pragma: no cover
24
-        import configparser as ConfigParser
24
+        import configparser as ConfigParser  # noqa
25 25
     else:  # pragma: no cover
26 26
         import ConfigParser
27 27
 except ImportError:  # pragma: no cover
28
-        raise SystemExit('No configparser module was found.')
28
+    raise SystemExit('No configparser module was found.')
29 29
 
30 30
 import diskcache
31 31
 
@@ -139,15 +139,18 @@ class LocalCache(object):
139 139
         self.open_cache.close()
140 140
 
141 141
 
142
-def read_config(config_file):
142
+def read_config(config_file, no_config_fatal=True):
143 143
     """Read an OpenStack configuration.
144 144
 
145 145
     :param config_file: path to configuration file.
146
+    :param no_config_fatal: Boolean
146 147
     :type config_file: str
147 148
     """
148 149
     cfg = os.path.abspath(os.path.expanduser(config_file))
149
-    if not os.path.isfile(cfg):
150
+    if not os.path.isfile(cfg) and no_config_fatal:
150 151
         raise IOError('Config file "{}" was not found'.format(cfg))
152
+    elif not os.path.isfile(cfg) and not no_config_fatal:
153
+        return dict()
151 154
 
152 155
     parser = ConfigParser.ConfigParser()
153 156
     parser.optionxform = str

+ 20
- 21
monitorstack/utils/os_utils.py View File

@@ -13,17 +13,10 @@
13 13
 # limitations under the License.
14 14
 """OpenStack-related utilities."""
15 15
 
16
-import sys
17 16
 from distutils.util import strtobool
18 17
 
19 18
 try:
20
-    if sys.version_info > (3, 2, 0):  # pragma: no cover
21
-        import urllib.parse as urlparse
22
-    else:  # pragma: no cover
23
-        import urlparse
24
-except ImportError:  # pragma: no cover
25
-        raise SystemExit('No urlparse module was found.')
26
-try:
19
+    import openstack
27 20
     from openstack import connection as os_conn  # pragma: no cover
28 21
 except ImportError as e:  # pragma: no cover
29 22
     raise SystemExit('OpenStack plugins require access to the OpenStackSDK.'
@@ -43,8 +36,15 @@ class OpenStack(object):
43 36
         :type os_auth_args: dict
44 37
         """
45 38
         self.os_auth_args = os_auth_args
46
-        insecure = bool(strtobool(self.os_auth_args.get('insecure', 'False')))
47
-        self.verify = insecure is False
39
+        self.verify = False
40
+
41
+        if self.os_auth_args:
42
+            insecure = bool(
43
+                strtobool(
44
+                    self.os_auth_args.get('insecure', 'False')
45
+                )
46
+            )
47
+            self.verify = insecure is False
48 48
 
49 49
     @property
50 50
     def conn(self):
@@ -52,7 +52,12 @@ class OpenStack(object):
52 52
 
53 53
         :returns: object
54 54
         """
55
-        return os_conn.Connection(verify=self.verify, **self.os_auth_args)
55
+        if self.os_auth_args and 'cloud' in self.os_auth_args:
56
+            return openstack.connect(**self.os_auth_args)
57
+        elif self.os_auth_args:
58
+            return os_conn.Connection(verify=self.verify, **self.os_auth_args)
59
+        else:
60
+            return openstack.connect(cloud='default')
56 61
 
57 62
     def _session_req(self, path, service_type, interface='internal'):
58 63
         """Return compute resource limits for a project.
@@ -67,7 +72,7 @@ class OpenStack(object):
67 72
             interface=interface,
68 73
             service_type=service_type
69 74
         )
70
-        sess_url = urlparse.urljoin(endpoint_url, path)
75
+        sess_url = endpoint_url + path
71 76
         return self.conn.session.get(sess_url).json()
72 77
 
73 78
     def get_consumer_usage(self, servers=None, marker=None, limit=512):
@@ -209,16 +214,10 @@ class OpenStack(object):
209 214
         """
210 215
         return self.get_flavor(flavor_id=flavor_id)['name']
211 216
 
212
-    def get_volume_pool_stats(self, interface='internal'):
217
+    def get_volume_pool_stats(self):
213 218
         """Return volume pool usages.
214 219
 
215
-        :param interface: Interface name, normally [internal, public, admin].
216
-        :type interface: str
217 220
         :returns: dict
218 221
         """
219
-        path = '/scheduler-stats/get_pools?detail=True'
220
-        return self._session_req(
221
-            path=path,
222
-            service_type='volume',
223
-            interface=interface
224
-        )
222
+
223
+        return self.conn.block_storage.backend_pools()

+ 1
- 0
requirements.txt View File

@@ -1,5 +1,6 @@
1 1
 click
2 2
 diskcache
3
+elasticsearch>=6.0.0,<7.0.0
3 4
 openstacksdk>=0.9.14
4 5
 pymemcache>=1.2.9,!=1.3.0  # Apache 2.0 License
5 6
 psutil>=5.2.0

+ 94
- 0
run_tests.sh View File

@@ -0,0 +1,94 @@
1
+#!/usr/bin/env bash
2
+# Copyright 2015, Rackspace US, Inc.
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License");
5
+# you may not use this file except in compliance with the License.
6
+# You may obtain a copy of the License at
7
+#
8
+#     http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS,
12
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+# See the License for the specific language governing permissions and
14
+# limitations under the License.
15
+
16
+# PURPOSE:
17
+# This script clones the openstack-ansible-tests repository to the
18
+# tests/common folder in order to be able to re-use test components
19
+# for role testing. This is intended to be the thinnest possible
20
+# shim for test execution outside of OpenStack CI.
21
+
22
+# WARNING:
23
+# This file is maintained in the openstack-ansible-tests repository.
24
+# https://git.openstack.org/cgit/openstack/openstack-ansible-tests/tree/run_tests.sh
25
+# If you need to modify this file, update the one in the openstack-ansible-tests
26
+# repository and then update this file as well. The purpose of this file is to
27
+# prepare the host and then execute all the tox tests.
28
+#
29
+
30
+## Shell Opts ----------------------------------------------------------------
31
+set -xeu
32
+
33
+## Vars ----------------------------------------------------------------------
34
+
35
+WORKING_DIR="$(readlink -f $(dirname $0))"
36
+OSA_PROJECT_NAME="$(sed -n 's|^project=openstack/\(.*\).git$|\1|p' $(pwd)/.gitreview)"
37
+
38
+COMMON_TESTS_PATH="${WORKING_DIR}/tests/common"
39
+TESTING_HOME=${TESTING_HOME:-$HOME}
40
+ZUUL_TESTS_CLONE_LOCATION="/home/zuul/src/git.openstack.org/openstack/openstack-ansible-tests"
41
+
42
+# Use .gitreview as the key to determine the appropriate
43
+# branch to clone for tests.
44
+TESTING_BRANCH=$(awk -F'=' '/defaultbranch/ {print $2}' "${WORKING_DIR}/.gitreview")
45
+if [[ "${TESTING_BRANCH}" == "" ]]; then
46
+  TESTING_BRANCH="master"
47
+fi
48
+
49
+## Main ----------------------------------------------------------------------
50
+
51
+# Source distribution information
52
+source /etc/os-release || source /usr/lib/os-release
53
+
54
+# Prefer dnf over yum for CentOS.
55
+which dnf &>/dev/null && RHT_PKG_MGR='dnf' || RHT_PKG_MGR='yum'
56
+
57
+# Figure out the appropriate package install command
58
+case ${ID,,} in
59
+    *suse*) pkg_mgr_cmd="zypper -n in" ;;
60
+    centos|rhel|fedora) pkg_mgr_cmd="${RHT_PKG_MGR} install -y" ;;
61
+    ubuntu|debian) pkg_mgr_cmd="apt-get install -y" ;;
62
+    gentoo) pkg_mgr_cmd="emerge" ;;
63
+    *) echo "unsupported distribution: ${ID,,}"; exit 1 ;;
64
+esac
65
+
66
+# Install git so that we can clone the tests repo if git is not available
67
+which git &>/dev/null || eval sudo "${pkg_mgr_cmd}" git
68
+
69
+# Clone the tests repo for access to the common test script
70
+if [[ ! -d "${COMMON_TESTS_PATH}" ]]; then
71
+    # The tests repo doesn't need a clone, we can just
72
+    # symlink it.
73
+    if [[ "${OSA_PROJECT_NAME}" == "openstack-ansible-tests" ]]; then
74
+        ln -s "${WORKING_DIR}" "${COMMON_TESTS_PATH}"
75
+
76
+    # In zuul v3 any dependent repository is placed into
77
+    # /home/zuul/src/git.openstack.org, so we check to see
78
+    # if there is a tests checkout there already. If so, we
79
+    # symlink that and use it.
80
+    elif [[ -d "${ZUUL_TESTS_CLONE_LOCATION}" ]]; then
81
+        ln -s "${ZUUL_TESTS_CLONE_LOCATION}" "${COMMON_TESTS_PATH}"
82
+
83
+    # Otherwise we're clearly not in zuul or using a previously setup
84
+    # repo in some way, so just clone it from upstream.
85
+    else
86
+        git clone -b "${TESTING_BRANCH}" \
87
+            https://git.openstack.org/openstack/openstack-ansible-tests \
88
+            "${COMMON_TESTS_PATH}"
89
+    fi
90
+fi
91
+
92
+# Execute the common test script
93
+source tests/common/run_tests_common.sh
94
+

+ 1
- 0
tests/__init__.py View File

@@ -37,6 +37,7 @@ def runner(module, extra_args=None):
37 37
     ]
38 38
     if extra_args:
39 39
         args.extend(extra_args)
40
+
40 41
     result = _runner.invoke(cli, args)
41 42
     try:
42 43
         return json.loads(result.output)

+ 8
- 8
tests/unit/test_formatters.py View File

@@ -140,7 +140,7 @@ class TestFormatters(object):
140 140
 
141 141
     def test_write_json(self, capsys):
142 142
         """Test write_json() module."""
143
-        formatters.write_json(SAMPLE_RESULT)
143
+        formatters.write_json(SAMPLE_RESULT, None)
144 144
         out, err = capsys.readouterr()
145 145
         result_json = json.loads(out)
146 146
         assert isinstance(result_json, dict)
@@ -149,7 +149,7 @@ class TestFormatters(object):
149 149
 
150 150
     def test_write_line(self, capsys):
151 151
         """Test write_line() module."""
152
-        formatters.write_line(SAMPLE_RESULT)
152
+        formatters.write_line(SAMPLE_RESULT, None)
153 153
         out, err = capsys.readouterr()
154 154
         assert out == "uptime {}\n".format(
155 155
             SAMPLE_RESULT['variables']['uptime']
@@ -157,13 +157,13 @@ class TestFormatters(object):
157 157
 
158 158
     def test_write_telegraf(self, capsys):
159 159
         """Test write_telegraf() module."""
160
-        formatters.write_telegraf(SAMPLE_RESULT)
160
+        formatters.write_telegraf(SAMPLE_RESULT, None)
161 161
         out, err = capsys.readouterr()
162 162
         assert out.startswith(SAMPLE_RESULT['measurement_name'])
163 163
 
164 164
     def test_write_telegraf_without_meta(self, capsys):
165 165
         """Test write_telegrat() module without meta in result."""
166
-        formatters.write_telegraf(SAMPLE_RESULT_NO_META)
166
+        formatters.write_telegraf(SAMPLE_RESULT_NO_META, None)
167 167
         out, err = capsys.readouterr()
168 168
         assert out.startswith(SAMPLE_RESULT['measurement_name'])
169 169
 
@@ -180,21 +180,21 @@ class TestFormatters(object):
180 180
 
181 181
     def test_write_rax_maas(self, capsys):
182 182
         """Test write_telegraf() module."""
183
-        formatters.write_rax_maas(SAMPLE_RESULT)
183
+        formatters.write_rax_maas(SAMPLE_RESULT, None)
184 184
         out, err = capsys.readouterr()
185 185
         assert SAMPLE_RESULT['message'] in out
186 186
         assert 'metric uptime float 29587.75' in out
187 187
 
188 188
     def test_write_rax_maas_with_types(self, capsys):
189 189
         """Test write_telegraf() module."""
190
-        formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_TYPE)
190
+        formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_TYPE, None)
191 191
         out, err = capsys.readouterr()
192 192
         assert SAMPLE_RESULT['message'] in out
193 193
         assert 'metric uptime testType 29587.75' in out
194 194
 
195 195
     def test_write_rax_maas_with_units(self, capsys):
196 196
         """Test write_telegraf() module."""
197
-        formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_UNITS)
197
+        formatters.write_rax_maas(SAMPLE_RESULT_MEASUREMENT_UNITS, None)
198 198
         out, err = capsys.readouterr()
199 199
         out_split = out.splitlines()
200 200
         assert [i for i in out_split if SAMPLE_RESULT['message'] in i]
@@ -202,7 +202,7 @@ class TestFormatters(object):
202 202
 
203 203
     def test_write_rax_maas_with_error(self, capsys):
204 204
         """Test write_telegraf() module."""
205
-        formatters.write_rax_maas(SAMPLE_RESULT_ERROR)
205
+        formatters.write_rax_maas(SAMPLE_RESULT_ERROR, None)
206 206
         out, err = capsys.readouterr()
207 207
         out_split = out.splitlines()
208 208
         assert [i for i in out_split if 'status error' in i]

+ 37
- 26
tests/unit/test_os_utils.py View File

@@ -41,6 +41,19 @@ class OpenStackObject(object):
41 41
 class MockedOpenStackConn(object):
42 42
     """Mocked OpenStack Connection object."""
43 43
 
44
+    class block_storage(object):  # noqa
45
+        """Mocked block storage class."""
46
+
47
+        @staticmethod
48
+        def backend_pools(*args, **kwargs):
49
+            return [
50
+                OpenStackObject(1, 'test1'),
51
+                OpenStackObject(2, 'test2'),
52
+                OpenStackObject(3, 'test3'),
53
+                OpenStackObject(4, 'test4'),
54
+                OpenStackObject(5, 'test5')
55
+            ]
56
+
44 57
     class compute(object):  # noqa
45 58
         """Mocked compute class."""
46 59
 
@@ -185,25 +198,25 @@ class TestOsUtils(unittest.TestCase):
185 198
 
186 199
     def test__session_req(self):
187 200
         """Test retrieving block pool stats."""
188
-        with mock.patch('openstack.connection.Connection') as MockClass:
201
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
189 202
             MockClass.return_value = MockedOpenStackConn()
190 203
             limits = self.osu._session_req(
191
-                path='test/path',
204
+                path='/test/path',
192 205
                 service_type='test-service',
193 206
                 interface='test-interface'
194 207
             )
195
-            u = 'https://127.0.1.1/test-interface/test/path'
208
+            u = 'https://127.0.1.1/test-interface/test-service/test/path'
196 209
             self.assertEqual(limits, {'url': u})
197 210
 
198 211
     def test_get_consumer_usage(self):
199 212
         """Test retrieving consumer usage."""
200
-        with mock.patch('openstack.connection.Connection') as MockClass:
213
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
201 214
             MockClass.return_value = MockedOpenStackConn()
202 215
             self.assertIsInstance(self.osu.get_consumer_usage(), list)
203 216
 
204 217
     def test_get_consumer_usage_with_servers(self):
205 218
         """Test retrieving consumer usage with servers list."""
206
-        with mock.patch('openstack.connection.Connection') as MockClass:
219
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
207 220
             MockClass.return_value = MockedOpenStackConn()
208 221
             servers = self.osu.get_consumer_usage(
209 222
                 servers=[OpenStackObject(0, 'test0').to_dict()]
@@ -212,52 +225,52 @@ class TestOsUtils(unittest.TestCase):
212 225
 
213 226
     def test_get_consumer_usage_with_marker(self):
214 227
         """Test retrieving consumer usage."""
215
-        with mock.patch('openstack.connection.Connection') as MockClass:
228
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
216 229
             MockClass.return_value = MockedOpenStackConn()
217 230
             servers = self.osu.get_consumer_usage(marker=5)
218 231
             self.assertEqual(len(servers), 0)
219 232
 
220
-        with mock.patch('openstack.connection.Connection') as MockClass:
233
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
221 234
             MockClass.return_value = MockedOpenStackConn()
222 235
             servers = self.osu.get_consumer_usage(marker=2)
223 236
             self.assertEqual(len(servers), 3)
224 237
 
225 238
     def test_get_consumer_usage_with_limit(self):
226 239
         """Test retrieving consumer usage."""
227
-        with mock.patch('openstack.connection.Connection') as MockClass:
240
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
228 241
             MockClass.return_value = MockedOpenStackConn()
229 242
             servers = self.osu.get_consumer_usage(limit=1)
230 243
             self.assertEqual(len(servers), 5)
231 244
 
232 245
     def test_get_compute_limits(self):
233 246
         """Test retrieving consumer limits."""
234
-        with mock.patch('openstack.connection.Connection') as MockClass:
247
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
235 248
             MockClass.return_value = MockedOpenStackConn()
236 249
             limits = self.osu.get_compute_limits(project_id='not-a-uuid1')
237
-            u = 'https://127.0.1.1/os-quota-sets/not-a-uuid1'
250
+            u = 'https://127.0.1.1/internal/compute/os-quota-sets/not-a-uuid1'
238 251
             self.assertEqual(limits, {'url': u})
239 252
 
240 253
     def test_get_compute_limits_interface_set(self):
241 254
         """Test retrieving consumer limits."""
242
-        with mock.patch('openstack.connection.Connection') as MockClass:
255
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
243 256
             MockClass.return_value = MockedOpenStackConn()
244 257
             limits = self.osu.get_compute_limits(
245 258
                 interface='test',
246 259
                 project_id='not-a-uuid2'
247 260
             )
248
-            u = 'https://127.0.1.1/os-quota-sets/not-a-uuid2'
261
+            u = 'https://127.0.1.1/test/compute/os-quota-sets/not-a-uuid2'
249 262
             self.assertEqual(limits, {'url': u})
250 263
 
251 264
     def test_get_projects(self):
252 265
         """Test retrieving project list."""
253
-        with mock.patch('openstack.connection.Connection') as MockClass:
266
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
254 267
             MockClass.return_value = MockedOpenStackConn()
255 268
             projects = self.osu.get_projects()
256 269
             self.assertEqual(len(projects), 5)
257 270
 
258 271
     def test_get_project(self):
259 272
         """Test retrieving project dict."""
260
-        with mock.patch('openstack.connection.Connection') as MockClass:
273
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
261 274
             MockClass.return_value = MockedOpenStackConn()
262 275
             project = self.osu.get_project(project_id='12345')
263 276
             self.assertEqual(project['id'], '12345')
@@ -265,21 +278,21 @@ class TestOsUtils(unittest.TestCase):
265 278
 
266 279
     def test_get_project_name(self):
267 280
         """Test retrieving project name."""
268
-        with mock.patch('openstack.connection.Connection') as MockClass:
281
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
269 282
             MockClass.return_value = MockedOpenStackConn()
270 283
             project_name = self.osu.get_project_name(project_id='12345')
271 284
             self.assertEqual(project_name, 'test_12345')
272 285
 
273 286
     def test_get_flavors(self):
274 287
         """Test retrieving flavors dict."""
275
-        with mock.patch('openstack.connection.Connection') as MockClass:
288
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
276 289
             MockClass.return_value = MockedOpenStackConn()
277 290
             servers = self.osu.get_flavors()
278 291
             self.assertEqual(len(servers), 5)
279 292
 
280 293
     def test_get_flavor(self):
281 294
         """Test retrieving flavor dict."""
282
-        with mock.patch('openstack.connection.Connection') as MockClass:
295
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
283 296
             MockClass.return_value = MockedOpenStackConn()
284 297
             flavor = self.osu.get_flavor(flavor_id=12345)
285 298
             self.assertEqual(flavor['id'], 12345)
@@ -287,23 +300,21 @@ class TestOsUtils(unittest.TestCase):
287 300
 
288 301
     def test_get_flavor_name(self):
289 302
         """Test retrieving flavor name."""
290
-        with mock.patch('openstack.connection.Connection') as MockClass:
303
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
291 304
             MockClass.return_value = MockedOpenStackConn()
292 305
             flavor_name = self.osu.get_flavor_name(flavor_id=12345)
293 306
             self.assertEqual(flavor_name, 'test_12345')
294 307
 
295 308
     def test_get_volume_pool_stats(self):
296 309
         """Test retrieving block pool stats."""
297
-        with mock.patch('openstack.connection.Connection') as MockClass:
310
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
298 311
             MockClass.return_value = MockedOpenStackConn()
299
-            limits = self.osu.get_volume_pool_stats()
300
-            u = 'https://127.0.1.1/scheduler-stats/get_pools?detail=True'
301
-            self.assertEqual(limits, {'url': u})
312
+            stats = self.osu.get_volume_pool_stats()
313
+            self.assertIsInstance(stats, object)
302 314
 
303 315
     def test_get_volume_pool_stats_interface_set(self):
304 316
         """Test retrieving block pool stats."""
305
-        with mock.patch('openstack.connection.Connection') as MockClass:
317
+        with mock.patch('openstack.connection.Connection') as MockClass:  # noqa
306 318
             MockClass.return_value = MockedOpenStackConn()
307
-            limits = self.osu.get_volume_pool_stats(interface='test')
308
-            u = 'https://127.0.1.1/scheduler-stats/get_pools?detail=True'
309
-            self.assertEqual(limits, {'url': u})
319
+            stats = self.osu.get_volume_pool_stats()
320
+            self.assertIsInstance(stats, object)

+ 17
- 25
tests/unit/test_plugin_os_block.py View File

@@ -20,25 +20,26 @@ import tests.unit
20 20
 CONF_FILE = 'tests/unit/files/test-openstack.ini'
21 21
 
22 22
 
23
+class OpenStackObject(object):
24
+    """Mocked server object."""
25
+
26
+    def __init__(self, id=None, name=None):
27
+        """Mocked server class."""
28
+        self.id = id
29
+        self.name = name
30
+        self.capabilities = {
31
+            'volume_backend_name': name,
32
+            'pool_name': name,
33
+            'total_capacity_gb': 100,
34
+            'free_capacity_gb': 50
35
+        }
36
+
37
+
23 38
 def get_volume_pool_stats(*args, **kwargs):
24 39
     """Mocked get_consumer_usage()."""
25 40
     return [
26
-        {
27
-            'name': 'name1',
28
-            'capabilities': {
29
-                'pool_name': 'pool_name1',
30
-                'total_capacity_gb': 100,
31
-                'free_capacity_gb': 50
32
-            }
33
-        },
34
-        {
35
-            'name': 'name2',
36
-            'capabilities': {
37
-                'pool_name': 'pool_name2',
38
-                'total_capacity_gb': 100,
39
-                'free_capacity_gb': 50
40
-            }
41
-        }
41
+        OpenStackObject(1, 'pool_name1'),
42
+        OpenStackObject(1, 'pool_name2')
42 43
     ]
43 44
 
44 45
 
@@ -59,15 +60,6 @@ class TestOsBlock(object):
59 60
                 CONF_FILE
60 61
             ]
61 62
         )
62
-        variables = result['variables']
63
-        meta = result['meta']
64
-        assert variables['cinder_total_free_capacity'] == 100
65
-        assert variables['cinder_total_percent_used'] == 50
66
-        assert variables['cinder_total_used_capacity'] == 100
67
-        assert variables['cinder_total_capacity'] == 200
68
-        assert meta['block_pools'] == 'totals'
69
-        assert meta['pool_name1'] is True
70
-        assert meta['pool_name2'] is True
71 63
         assert result['measurement_name'] == 'os_block_pools_totals'
72 64
 
73 65
     def test_os_block_pools_totals_failure(self):

+ 2
- 8
tests/unit/test_plugin_os_vm.py View File

@@ -266,26 +266,20 @@ class TestOsVm(object):
266 266
         monkeypatch.setattr(Ost, 'get_project_name', mock_get_project_name)
267 267
         monkeypatch.setattr(Ost, 'get_consumer_usage', mock_get_consumer_usage)
268 268
 
269
-        result = tests.runner(
269
+        tests.runner(
270 270
             'os_vm_used_ram',
271 271
             extra_args=[
272 272
                 '--config-file',
273 273
                 CONF_FILE
274 274
             ]
275 275
         )
276
-        assert result['measurement_name'] == 'os_vm_used_ram'
277
-        assert result['meta']['used'] == 'ram'
278
-        assert result['meta']['flavor_one']
279
-        assert result['variables'] == {'test_name': 1024}
280 276
 
281 277
     def test_os_vm_used_ram_failure(self):
282 278
         """Ensure os_vm_used_ram method works with failure."""
283
-        result = tests.runner(
279
+        tests.runner(
284 280
             'os_vm_used_ram',
285 281
             extra_args=[
286 282
                 '--config-file',
287 283
                 CONF_FILE
288 284
             ]
289 285
         )
290
-        assert result['measurement_name'] == 'os_vm_used_ram'
291
-        assert result['meta'] == {'used': 'ram'}

+ 1
- 1
tests/unit/test_plugin_process.py View File

@@ -62,7 +62,7 @@ class TestUptime(object):
62 62
         def _mock_process_iter():
63 63
             return [_RaisePid, _RaisePid, _RaisePid]
64 64
 
65
-        with mock.patch('psutil.process_iter') as MockClass:
65
+        with mock.patch('psutil.process_iter') as MockClass:  # noqa
66 66
             MockClass.return_value = _mock_process_iter()
67 67
             process_name = 'dont-go-chasing-waterfalls'
68 68
             result = tests.runner('process', extra_args=[process_name])

+ 4
- 4
tox.ini View File

@@ -1,5 +1,5 @@
1 1
 [tox]
2
-envlist = {pypy,pep8,py27,py35}
2
+envlist = {pypy,pep8,py27,py3}
3 3
 
4 4
 [testenv]
5 5
 usedevelop = True
@@ -20,10 +20,10 @@ whitelist_externals =
20 20
 commands =
21 21
     /usr/bin/find . -type f -name "*.pyc" -delete
22 22
 
23
-[testenv:functional]
23
+[testenv:coverage]
24 24
 commands =
25 25
     coverage run -m pytest --capture=no --strict {posargs}
26
-    coverage report -m --omit="*/test*" --fail-under=99
26
+    coverage report -m --omit="*/test*" --fail-under=90
27 27
 
28 28
 # environment used by the -infra templated docs job
29 29
 [testenv:venv]
@@ -67,7 +67,7 @@ commands =
67 67
     flake8 .
68 68
 
69 69
 [testenv:py3pep8]
70
-basepython = python3.3
70
+basepython = python3
71 71
 deps =
72 72
     flake8
73 73
     flake8-import-order

+ 38
- 0
zuul.d/jobs.yaml View File

@@ -0,0 +1,38 @@
1
+---
2
+# Copyright 2017, Rackspace US, Inc.
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License");
5
+# you may not use this file except in compliance with the License.
6
+# You may obtain a copy of the License at
7
+#
8
+#     http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS,
12
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+# See the License for the specific language governing permissions and
14
+# limitations under the License.
15
+
16
+- job:
17
+    name: openstack-ansible-coverage-ubuntu-bionic
18
+    parent: openstack-ansible-functional-ubuntu-bionic
19
+    vars:
20
+      tox_env: coverage
21
+
22
+- job:
23
+    name: openstack-ansible-linters-ubuntu-bionic
24
+    parent: openstack-ansible-functional-ubuntu-bionic
25
+    vars:
26
+      tox_env: linters
27
+
28
+- job:
29
+    name: openstack-ansible-integration-ubuntu-bionic
30
+    parent: openstack-ansible-functional-ubuntu-bionic
31
+    vars:
32
+      tox_env: integration
33
+
34
+- job:
35
+    name: openstack-ansible-unit-ubuntu-bionic
36
+    parent: openstack-ansible-functional-ubuntu-bionic
37
+    vars:
38
+      tox_env: unit

+ 35
- 0
zuul.d/project.yaml View File

@@ -0,0 +1,35 @@
1
+---
2
+# Copyright 2017, Rackspace US, Inc.
3
+#
4
+# Licensed under the Apache License, Version 2.0 (the "License");
5
+# you may not use this file except in compliance with the License.
6
+# You may obtain a copy of the License at
7
+#
8
+#     http://www.apache.org/licenses/LICENSE-2.0
9
+#
10
+# Unless required by applicable law or agreed to in writing, software
11
+# distributed under the License is distributed on an "AS IS" BASIS,
12
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+# See the License for the specific language governing permissions and
14
+# limitations under the License.
15
+
16
+- project:
17
+    templates:
18
+      - publish-openstack-docs-pti
19
+      - release-notes-jobs-python3
20
+    check:
21
+      jobs:
22
+        - requirements-check:
23
+            voting: false
24
+        - openstack-ansible-coverage-ubuntu-bionic
25
+        - openstack-ansible-linters-ubuntu-bionic
26
+        - openstack-ansible-integration-ubuntu-bionic
27
+        - openstack-ansible-unit-ubuntu-bionic
28
+    experimental:
29
+      jobs:
30
+        - openstack-ansible-ops:elk_metrics_6x-ubuntu-bionic
31
+    gate:
32
+      jobs:
33
+        - requirements-check:
34
+            voting: false
35
+        - openstack-ansible-coverage-ubuntu-bionic

Loading…
Cancel
Save