
* E122 continuation line missing indentation or outdented * E126 continuation line over-indented for hanging indent * E127 continuation line over-indented for visual indent * E128 continuation line under-indented for visual indent * E131 continuation line unaligned for hanging indent * E303 too many blank lines * W601 .has_key() is deprecated, use 'in' * H234 assertEquals is deprecated, use assertEqual * H401 docstring should not start with a space * H402 one line docstring needs punctuation. Change-Id: I1c264dba19bfe7cb9173e8999429827bd026b930
110 lines
3.9 KiB
Python
110 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
import logging
|
|
import os
|
|
import re
|
|
|
|
from packstack.installer.exceptions import PuppetError
|
|
|
|
|
|
# TODO: Fill logger name when logging system will be refactored
|
|
logger = logging.getLogger()
|
|
|
|
re_color = re.compile('\x1b.*?\d\dm')
|
|
re_error = re.compile(
|
|
'err:|Syntax error at|^Duplicate definition:|^Invalid tag|'
|
|
'^No matching value for selector param|^Parameter name failed:|Error:|'
|
|
'^Invalid parameter|^Duplicate declaration:|^Could not find resource|'
|
|
'^Could not parse for|^/usr/bin/puppet:\d+: .+|.+\(LoadError\)|'
|
|
'^Could not autoload|'
|
|
'^\/usr\/bin\/env\: jruby\: No such file or directory|'
|
|
'failed to execute puppet'
|
|
)
|
|
re_ignore = re.compile(
|
|
# Puppet preloads a provider using the mysql command before it is installed
|
|
'Command mysql is missing|'
|
|
# Puppet preloads a database_grant provider which fails if /root/.my.cnf
|
|
# is missing, this is ok because it will be retried later if needed
|
|
'Could not prefetch database_grant provider.*?\\.my\\.cnf|'
|
|
# Swift Puppet module tries to install swift-plugin-s3, there is no such
|
|
# package on RHEL, fixed in the upstream puppet module
|
|
'yum.*?install swift-plugin-s3|'
|
|
# facter gives a weird NM error when it's disabled, due to
|
|
# https://tickets.puppetlabs.com/browse/FACT-697
|
|
'NetworkManager is not running'
|
|
)
|
|
re_notice = re.compile(r"notice: .*Notify\[packstack_info\]"
|
|
"\/message: defined \'message\' as "
|
|
"\'(?P<message>.*)\'")
|
|
|
|
surrogates = [
|
|
# Value in /etc/sysctl.conf cannot be changed
|
|
('Sysctl::Value\[.*\]\/Sysctl\[(?P<arg1>.*)\].*Field \'val\' is required',
|
|
'Cannot change value of %(arg1)s in /etc/sysctl.conf'),
|
|
# Package is not found in yum repos
|
|
('Package\[.*\]\/ensure.*yum.*install (?P<arg1>.*)\'.*Nothing to do',
|
|
'Package %(arg1)s has not been found in enabled Yum repos.'),
|
|
('Execution of \'.*yum.*install (?P<arg1>.*)\'.*Nothing to do',
|
|
'Package %(arg1)s has not been found in enabled Yum repos.'),
|
|
# Packstack does not cooperate with jruby
|
|
('jruby', 'Your Puppet installation uses jruby instead of ruby. Package '
|
|
'jruby does not cooperate with Packstack well. You will have to '
|
|
'fix this manually.'),
|
|
]
|
|
|
|
|
|
def validate_logfile(logpath):
|
|
"""
|
|
Check given Puppet log file for errors and raise PuppetError if there is
|
|
any error
|
|
"""
|
|
manifestpath = os.path.splitext(logpath)[0]
|
|
manifestfile = os.path.basename(manifestpath)
|
|
with open(logpath) as logfile:
|
|
for line in logfile:
|
|
line = line.strip()
|
|
|
|
if re_error.search(line) is None:
|
|
continue
|
|
|
|
error = re_color.sub('', line) # remove colors
|
|
if re_ignore.search(line):
|
|
msg = ('Ignoring expected error during Puppet run %s: %s' %
|
|
(manifestfile, error))
|
|
logger.debug(msg)
|
|
continue
|
|
|
|
for regex, surrogate in surrogates:
|
|
match = re.search(regex, error)
|
|
if match is None:
|
|
continue
|
|
|
|
args = {}
|
|
num = 1
|
|
while True:
|
|
try:
|
|
args['arg%d' % num] = match.group(num)
|
|
num += 1
|
|
except IndexError:
|
|
break
|
|
error = surrogate % args
|
|
|
|
message = ('Error appeared during Puppet run: %s\n%s\n'
|
|
'You will find full trace in log %s' %
|
|
(manifestfile, error, logpath))
|
|
raise PuppetError(message)
|
|
|
|
|
|
def scan_logfile(logpath):
|
|
"""
|
|
Returns list of packstack_info/packstack_warn notices parsed from
|
|
given puppet log file.
|
|
"""
|
|
output = []
|
|
with open(logpath) as logfile:
|
|
for line in logfile:
|
|
match = re_notice.search(line)
|
|
if match:
|
|
output.append(match.group('message'))
|
|
return output
|