Add python syntax check using OpenStack hacking rules

Change-Id: I42db1b87e216383009dbadc4fec4a1a7e580d898
This commit is contained in:
Swann Croiset 2016-02-11 16:19:41 +01:00
parent 1f54a530d1
commit 952fd4938d
13 changed files with 50 additions and 37 deletions

View File

@ -24,8 +24,7 @@ import collectd
class Base(object): class Base(object):
""" Base class for writing Python plugins. """Base class for writing Python plugins."""
"""
MAX_IDENTIFIER_LENGTH = 63 MAX_IDENTIFIER_LENGTH = 63
@ -54,8 +53,7 @@ class Base(object):
return return
def itermetrics(self): def itermetrics(self):
""" """Iterate over the collected metrics
Iterate over the collected metrics
This class must be implemented by the subclass and should yield dict This class must be implemented by the subclass and should yield dict
objects that represent the collected values. Each dict has 3 keys: objects that represent the collected values. Each dict has 3 keys:
@ -96,8 +94,7 @@ class Base(object):
v.dispatch() v.dispatch()
def execute(self, cmd, shell=True, cwd=None): def execute(self, cmd, shell=True, cwd=None):
""" """Executes a program with arguments.
Executes a program with arguments.
Args: Args:
cmd: a list of program arguments where the first item is the cmd: a list of program arguments where the first item is the
@ -150,8 +147,7 @@ class Base(object):
return (stdout, stderr) return (stdout, stderr)
def execute_to_json(self, *args, **kwargs): def execute_to_json(self, *args, **kwargs):
""" """Executes a program and decodes the output as a JSON string.
Executes a program and decodes the output as a JSON string.
See execute(). See execute().
@ -165,8 +161,7 @@ class Base(object):
@staticmethod @staticmethod
def restore_sigchld(): def restore_sigchld():
""" """Restores the SIGCHLD handler for Python <= v2.6.
Restores the SIGCHLD handler for Python <= v2.6.
This should be provided to collectd as the init callback by plugins This should be provided to collectd as the init callback by plugins
that execute external programs. that execute external programs.

View File

@ -49,7 +49,7 @@ class CephPerfSchema(object):
(stdout, stderr) = proc.communicate() (stdout, stderr) = proc.communicate()
stdout = stdout.rstrip('\n') stdout = stdout.rstrip('\n')
except Exception as e: except Exception as e:
print "Cannot execute command '%s': %s" % (cmd, str(e)) print("Cannot execute command '%s': %s" % (cmd, str(e)))
raise e raise e
return json.loads(stdout) return json.loads(stdout)
@ -69,15 +69,15 @@ class CephPerfSchema(object):
def main(): def main():
script_name = os.path.basename(sys.argv[0]) script_name = os.path.basename(sys.argv[0])
if len(sys.argv) < 2 or len(sys.argv) > 3: if len(sys.argv) < 2 or len(sys.argv) > 3:
print "usage: %s <Ceph OSD socket> [namespace]" % script_name print("usage: %s <Ceph OSD socket> [namespace]" % script_name)
else: else:
schema = CephPerfSchema(sys.argv[1]) schema = CephPerfSchema(sys.argv[1])
collection = sys.argv[2] if len(sys.argv) == 3 else None collection = sys.argv[2] if len(sys.argv) == 3 else None
print "# File generated automatically by the %s script" % script_name print("# File generated automatically by the %s script" % script_name)
print "# Ceph version: %s" % schema.ceph_version() print("# Ceph version: %s" % schema.ceph_version())
for item in schema.itertypes(): for item in schema.itertypes():
if collection is None or item.collection == collection: if collection is None or item.collection == collection:
print item print(item)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -24,8 +24,7 @@ RE_OSD_ID = re.compile(".*?osd\.(\d+)\.asok$")
class CephOSDPerfPlugin(base.CephBase): class CephOSDPerfPlugin(base.CephBase):
""" Collect OSD performance counters of all OSD daemons running on the host. """Collect OSD performance counters of OSD daemons running on the host."""
"""
# Collect only metrics from the 'osd' namespace # Collect only metrics from the 'osd' namespace
PREFIXES = ('osd') PREFIXES = ('osd')
@ -46,9 +45,10 @@ class CephOSDPerfPlugin(base.CephBase):
@staticmethod @staticmethod
def convert_to_collectd_value(value): def convert_to_collectd_value(value):
# See for details
# https://www.mail-archive.com/ceph-users@lists.ceph.com/msg18705.html
if isinstance(value, dict): if isinstance(value, dict):
if value['avgcount'] > 0: if value['avgcount'] > 0:
# See https://www.mail-archive.com/ceph-users@lists.ceph.com/msg18705.html
return value['sum'] / value['avgcount'] return value['sum'] / value['avgcount']
else: else:
return 0.0 return 0.0

View File

@ -26,8 +26,7 @@ HEALTH_MAP = {
class CephMonPlugin(base.CephBase): class CephMonPlugin(base.CephBase):
""" Collect states and information about ceph cluster and placement groups. """ Collect states and metrics about ceph cluster and placement groups."""
"""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CephMonPlugin, self).__init__(*args, **kwargs) super(CephMonPlugin, self).__init__(*args, **kwargs)

View File

@ -24,13 +24,13 @@ INTERVAL = openstack.INTERVAL
class APICheckPlugin(openstack.CollectdPlugin): class APICheckPlugin(openstack.CollectdPlugin):
""" Class to check the status of OpenStack API services. """Class to check the status of OpenStack API services."""
"""
FAIL = 0 FAIL = 0
OK = 1 OK = 1
UNKNOWN = 2 UNKNOWN = 2
# TODO: sahara, murano # TODO(all): sahara, murano
CHECK_MAP = { CHECK_MAP = {
'keystone': { 'keystone': {
'path': '/', 'expect': 300, 'name': 'keystone-public-api'}, 'path': '/', 'expect': 300, 'name': 'keystone-public-api'},
@ -67,7 +67,8 @@ class APICheckPlugin(openstack.CollectdPlugin):
for service in catalog: for service in catalog:
name = service['name'] name = service['name']
if name not in self.CHECK_MAP: if name not in self.CHECK_MAP:
self.logger.notice("No check found for service '%s', skipping it" % name) self.logger.notice(
"No check found for service '%s', skipping it" % name)
status = self.UNKNOWN status = self.UNKNOWN
else: else:
check = self.CHECK_MAP[name] check = self.CHECK_MAP[name]

View File

@ -30,6 +30,7 @@ METRICS = ['number_of_nodes', 'active_primary_shards', 'active_primary_shards',
HEALTH_ON_ERROR = {'type_instance': 'health', 'values': HEALTH_MAP['red']} HEALTH_ON_ERROR = {'type_instance': 'health', 'values': HEALTH_MAP['red']}
class ElasticsearchClusterHealthPlugin(base.Base): class ElasticsearchClusterHealthPlugin(base.Base):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ElasticsearchClusterHealthPlugin, self).__init__(*args, **kwargs) super(ElasticsearchClusterHealthPlugin, self).__init__(*args, **kwargs)

View File

@ -22,8 +22,7 @@ INTERVAL = openstack.INTERVAL
class HypervisorStatsPlugin(openstack.CollectdPlugin): class HypervisorStatsPlugin(openstack.CollectdPlugin):
""" Class to report the statistics on Nova hypervisors. """ Class to report the statistics on Nova hypervisors."""
"""
VALUE_MAP = { VALUE_MAP = {
'current_workload': 'running_tasks', 'current_workload': 'running_tasks',
'running_vms': 'running_instances', 'running_vms': 'running_instances',

View File

@ -21,7 +21,8 @@ import requests
NAME = 'influxdb' NAME = 'influxdb'
METRICS_BY_NAME = { METRICS_BY_NAME = {
'cluster': { 'cluster': {
'writeShardPointsReq': ('cluster_write_shard_points_requests', 'gauge'), 'writeShardPointsReq': ('cluster_write_shard_points_requests',
'gauge'),
'writeShardReq': ('cluster_write_shard_requests', 'gauge')}, 'writeShardReq': ('cluster_write_shard_requests', 'gauge')},
'httpd': { 'httpd': {

View File

@ -49,8 +49,10 @@ class OSClient(object):
# but not on timeout and backoff time is not supported. # but not on timeout and backoff time is not supported.
# (at this time we ship requests 2.2.1 and urllib3 1.6.1 or 1.7.1) # (at this time we ship requests 2.2.1 and urllib3 1.6.1 or 1.7.1)
self.session = requests.Session() self.session = requests.Session()
self.session.mount('http://', requests.adapters.HTTPAdapter(max_retries=max_retries)) self.session.mount(
self.session.mount('https://', requests.adapters.HTTPAdapter(max_retries=max_retries)) 'http://', requests.adapters.HTTPAdapter(max_retries=max_retries))
self.session.mount(
'https://', requests.adapters.HTTPAdapter(max_retries=max_retries))
self.get_token() self.get_token()
@ -72,10 +74,9 @@ class OSClient(object):
{ {
'username': self.username, 'username': self.username,
'password': self.password 'password': self.password
}
} }
} }
) })
self.logger.info("Trying to get token from '%s'" % self.keystone_url) self.logger.info("Trying to get token from '%s'" % self.keystone_url)
r = self.make_request('post', r = self.make_request('post',
'%s/tokens' % self.keystone_url, data=data, '%s/tokens' % self.keystone_url, data=data,

View File

@ -39,7 +39,7 @@ class CinderStatsPlugin(openstack.CollectdPlugin):
return d.get('status', 'unknown').lower() return d.get('status', 'unknown').lower()
def count_size_bytes(d): def count_size_bytes(d):
return d.get('size', 0) * 10**9 return d.get('size', 0) * 10 ** 9
status = self.count_objects_group_by(volumes_details, status = self.count_objects_group_by(volumes_details,
group_by_func=groupby) group_by_func=groupby)

View File

@ -92,7 +92,7 @@ class RabbitMqPlugin(base.Base):
mem_str = re.findall('{memory,\s+\[([^\]]+)\]\}', out) mem_str = re.findall('{memory,\s+\[([^\]]+)\]\}', out)
# We are only interested by the total of memory used # We are only interested by the total of memory used
# TODO: Get all informations about memory usage from mem_str # TODO(all): Get all informations about memory usage from mem_str
try: try:
stats['used_memory'] = int(re.findall('total,([0-9]+)', stats['used_memory'] = int(re.findall('total,([0-9]+)',
mem_str[0])[0]) mem_str[0])[0])
@ -101,9 +101,11 @@ class RabbitMqPlugin(base.Base):
self.rabbitmqctl_bin) self.rabbitmqctl_bin)
if 'vm_memory_limit' in stats and 'used_memory' in stats: if 'vm_memory_limit' in stats and 'used_memory' in stats:
stats['remaining_memory'] = stats['vm_memory_limit'] - stats['used_memory'] stats['remaining_memory'] = \
stats['vm_memory_limit'] - stats['used_memory']
if 'disk_free' in stats and 'disk_free_limit' in stats: if 'disk_free' in stats and 'disk_free_limit' in stats:
stats['remaining_disk'] = stats['disk_free'] - stats['disk_free_limit'] stats['remaining_disk'] = \
stats['disk_free'] - stats['disk_free_limit']
out, err = self.execute([self.rabbitmqctl_bin, '-q', 'cluster_status'], out, err = self.execute([self.rabbitmqctl_bin, '-q', 'cluster_status'],
shell=False) shell=False)
@ -112,7 +114,7 @@ class RabbitMqPlugin(base.Base):
self.rabbitmqctl_bin) self.rabbitmqctl_bin)
return return
# TODO: Need to be modified in case we are using RAM nodes. # TODO(all): Need to be modified in case we are using RAM nodes.
status = CLUSTER_STATUS.findall(out) status = CLUSTER_STATUS.findall(out)
if len(status) == 0: if len(status) == 0:
self.logger.error('%s: Failed to parse (%s)' % self.logger.error('%s: Failed to parse (%s)' %

View File

@ -1,2 +1,4 @@
Sphinx Sphinx
-e git+https://github.com/openstack/fuel-plugins.git#egg=fuel-plugin-builder -e git+https://github.com/openstack/fuel-plugins.git#egg=fuel-plugin-builder
# Hacking already pins down pep8, pyflakes and flake8
hacking<0.11,>=0.10.0

14
tox.ini
View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = manifests,heka,lma_collector,docs,qa_docs,build_plugin envlist = manifests,heka,lma_collector,docs,qa_docs,build_plugin,collectd_python
skipsdist = True skipsdist = True
[testenv] [testenv]
@ -39,6 +39,18 @@ commands =
bundle install --path {toxinidir}/.bundled_gems bundle install --path {toxinidir}/.bundled_gems
bundle exec rake test bundle exec rake test
[flake8]
ignore = H105,H201,E241,H401
exclude = haproxy.py
show-source = True
[testenv:collectd_python]
changedir = {toxinidir}/deployment_scripts/puppet/modules/lma_collector/files/collectd
whitelist_externals =
flake8
commands =
flake8 .
[testenv:docs] [testenv:docs]
changedir = {toxinidir}/doc changedir = {toxinidir}/doc
whitelist_externals = make whitelist_externals = make