14fd503aaa
Manage nodepool configurations using the common-ci solution in puppet-openstackci Remove nodepool.yaml.erb from this repo as openstackci::nodepool will pull it in from project-config/nodepool/nodepool.yaml Remove the tox nodepool environment and test dependency as it has been migrated to project-config The nodepool logging template file and associated tool that generates the file will remain in this repo. In the short term, updates to nodepool.yaml in project-config repo may require a related change in this repo to update the logging configuration. In the longer term, nodepool will be updated to automatically log image creations without needing a customized logging configuration. Depends-on: I89207d100eb4b6bbb502a6ed38831f49e4b29096 Depends-on: I473a1b78acdb035eb379394a7ed5f771434dc942 Depends-on: I6b01ab7260a41927fff34b9b81b631ea2c933f22 Change-Id: I2b45a7145805368b1598d3a3e8a94f0e4eb8cf2d
257 lines
7.0 KiB
Python
Executable File
257 lines
7.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
|
|
"""Generate a sample logging configuration file
|
|
|
|
use log_config_generator.generate_log_config() to generate a sample
|
|
logging configuration file.
|
|
|
|
The sample splits up the log output for general logging and image
|
|
builds and applys some sensible rotation defaults.
|
|
"""
|
|
|
|
import argparse
|
|
import logging
|
|
import yaml
|
|
|
|
# default paths and outputs
|
|
MODULES_PATH = '../modules/openstack_project/templates/nodepool'
|
|
# default the project-config repo path to the same folder as this repo
|
|
CONFIG_FILE = '../../project-config/nodepool/nodepool.yaml'
|
|
LOGGING_CONFIG_FILE = MODULES_PATH + '/nodepool.logging.conf.erb'
|
|
LOG_DIR = '/var/log/nodepool'
|
|
IMAGE_LOG_DIR = '<%= @image_log_document_root %>'
|
|
|
|
|
|
_BASIC_FILE = """
|
|
|
|
#
|
|
# THIS FILE HAS BEEN AUTOGENERATED
|
|
# Regenerate it with tools/nodepool_log_config.py
|
|
#
|
|
|
|
[loggers]
|
|
keys=root,nodepool,requests,image,%(logger_titles)s
|
|
|
|
[handlers]
|
|
keys=console,debug,normal,image,%(handler_titles)s
|
|
|
|
[formatters]
|
|
keys=simple
|
|
|
|
[logger_root]
|
|
level=WARNING
|
|
handlers=console
|
|
|
|
[logger_requests]
|
|
level=WARNING
|
|
handlers=debug,normal
|
|
qualname=requests
|
|
|
|
[logger_nodepool]
|
|
level=DEBUG
|
|
handlers=debug,normal
|
|
qualname=nodepool
|
|
|
|
[logger_image]
|
|
level=DEBUG
|
|
handlers=image
|
|
qualname=nodepool.image.build
|
|
propagate=0
|
|
|
|
[handler_console]
|
|
level=WARNING
|
|
class=StreamHandler
|
|
formatter=simple
|
|
args=(sys.stdout,)
|
|
|
|
[handler_debug]
|
|
level=DEBUG
|
|
class=logging.handlers.TimedRotatingFileHandler
|
|
formatter=simple
|
|
args=('%(log_dir)s/debug.log', 'H', 8, 30,)
|
|
|
|
[handler_normal]
|
|
level=INFO
|
|
class=logging.handlers.TimedRotatingFileHandler
|
|
formatter=simple
|
|
args=('%(log_dir)s/nodepool.log', 'H', 8, 30,)
|
|
|
|
[handler_image]
|
|
level=DEBUG
|
|
class=logging.handlers.TimedRotatingFileHandler
|
|
formatter=simple
|
|
args=('%(image_log_dir)s/image.log', 'H', 8, 30,)
|
|
|
|
[formatter_simple]
|
|
format=%%(asctime)s %%(levelname)s %%(name)s: %%(message)s
|
|
datefmt=
|
|
|
|
# ==== individual image loggers ====
|
|
|
|
%(image_loggers_and_handlers)s"""
|
|
|
|
_IMAGE_HANDLER = """
|
|
[handler_%(title)s]
|
|
level=DEBUG
|
|
class=logging.handlers.TimedRotatingFileHandler
|
|
formatter=simple
|
|
args=('%(image_log_dir)s/%(filename)s', 'H', 8, 30,)
|
|
"""
|
|
|
|
_IMAGE_LOGGER = """
|
|
[logger_%(title)s]
|
|
level=DEBUG
|
|
handlers=%(handler)s
|
|
qualname=nodepool.image.build.%(qualname)s
|
|
propagate=0
|
|
"""
|
|
|
|
|
|
def _get_providers_and_images(config_file):
|
|
ret = []
|
|
config = yaml.load(config_file)
|
|
for provider in config['providers']:
|
|
for image in provider['images']:
|
|
if 'diskimage' not in image:
|
|
ret.append((provider['name'], image['name']))
|
|
logging.debug("Added %d providers & images" % len(ret))
|
|
|
|
# diskimages have a special provider
|
|
if 'diskimages' in config:
|
|
for diskimage in config['diskimages']:
|
|
ret.append(('dib', diskimage['name']))
|
|
|
|
return ret
|
|
|
|
|
|
def _generate_logger_and_handler(image_log_dir, provider, image):
|
|
handler = _IMAGE_HANDLER % {
|
|
'image_log_dir': image_log_dir,
|
|
'title': '%s_%s' % (provider, image),
|
|
'filename': '%s.%s.log' % (provider, image),
|
|
}
|
|
|
|
logger = _IMAGE_LOGGER % {
|
|
'title': '%s_%s' % (provider, image),
|
|
'handler': '%s_%s' % (provider, image),
|
|
'qualname': '%s%s' % (provider + "." if provider != 'dib' else '',
|
|
image),
|
|
}
|
|
|
|
return {
|
|
'handler_title': '%s_%s' % (provider, image),
|
|
'logger_title': '%s_%s' % (provider, image),
|
|
'handler': handler,
|
|
'logger': logger,
|
|
}
|
|
|
|
|
|
def generate_log_config(config, log_dir, image_log_dir, output):
|
|
|
|
"""Generate a sample logging file
|
|
|
|
The logging output will have the correct formatters and handlers
|
|
to split all image-build logs out into separate files grouped by
|
|
provider. e.g.
|
|
|
|
providers:
|
|
- name: foo
|
|
...
|
|
- images:
|
|
- name: image1
|
|
...
|
|
- name: image2
|
|
...
|
|
- name: moo
|
|
...
|
|
- images:
|
|
- name: image1
|
|
...
|
|
- name: image2
|
|
...
|
|
|
|
Will result in log files (in `image_log_dir`) of foo.image1.log,
|
|
foo.image2.log, moo.image1.log, moo.image2.log
|
|
|
|
diskimage-builder built images will have special provider "dib"
|
|
|
|
:param config: input config file
|
|
:param log_dir: directory for main log file
|
|
:param image_log_dir: directory for image build logs
|
|
:param output: open file handle to output sample configuration to
|
|
|
|
"""
|
|
|
|
loggers_and_handlers = []
|
|
logging.debug("Reading config file %s" % config.name)
|
|
for (provider, image) in _get_providers_and_images(config):
|
|
loggers_and_handlers.append(
|
|
_generate_logger_and_handler(image_log_dir, provider, image))
|
|
|
|
logger_titles = []
|
|
handler_titles = []
|
|
image_loggers_and_handlers = ""
|
|
for item in loggers_and_handlers:
|
|
logger_titles.append(item['logger_title'])
|
|
handler_titles.append(item['handler_title'])
|
|
image_loggers_and_handlers += item['logger'] + item['handler']
|
|
|
|
final_output = _BASIC_FILE % {
|
|
'log_dir': log_dir,
|
|
'image_log_dir': image_log_dir,
|
|
'logger_titles': ','.join(logger_titles),
|
|
'handler_titles': ','.join(handler_titles),
|
|
'image_loggers_and_handlers': image_loggers_and_handlers,
|
|
}
|
|
|
|
logging.debug("Writing output to %s" % output.name)
|
|
output.write(final_output)
|
|
output.flush()
|
|
logging.debug("Done!")
|
|
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('-d', '--debug', action='store_true',
|
|
help="Enable debugging")
|
|
parser.add_argument('-c', '--config', default=CONFIG_FILE,
|
|
help="Config file to read in "
|
|
"(default: %s)" % CONFIG_FILE,
|
|
type=argparse.FileType('r'))
|
|
parser.add_argument('-o', '--output', default=LOGGING_CONFIG_FILE,
|
|
help="Output file "
|
|
"(default: %s)" % LOGGING_CONFIG_FILE,
|
|
type=argparse.FileType('w'))
|
|
parser.add_argument('-l', '--log-dir', default=LOG_DIR,
|
|
help="Output directory for logs "
|
|
"(default: %s)" % LOG_DIR)
|
|
parser.add_argument('-i', '--image-log-dir', default=IMAGE_LOG_DIR,
|
|
help="Output directory for image logs "
|
|
"(default: %s)" % IMAGE_LOG_DIR)
|
|
args = parser.parse_args()
|
|
|
|
logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO)
|
|
|
|
generate_log_config(args.config,
|
|
args.log_dir,
|
|
args.image_log_dir,
|
|
args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|