You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
4.0 KiB
114 lines
4.0 KiB
#! /usr/bin/python
|
|
# Copyright 2012 Canonical Ltd.
|
|
#
|
|
# This script will write update metrics for a given Ubuntu release in CSV
|
|
# format. It will output a file with updates (broken in Security vs Updates)
|
|
# by month, as well as the number per package.
|
|
|
|
from collections import defaultdict
|
|
import csv
|
|
import logging
|
|
from optparse import OptionParser
|
|
import sys
|
|
|
|
from launchpadlib.launchpad import Launchpad
|
|
|
|
API_NAME = 'ubuntu-update-metrics'
|
|
|
|
|
|
def write_metrics_csv(filename, key_name, metrics):
|
|
"""Write the metrics to a CSV file.
|
|
|
|
:param filename: The CSV filename.
|
|
:param key_name: The name of the metrics key.
|
|
:param metrics: This should be a sequence of
|
|
[key, {'Updates': X, 'Security': X, 'Total': X}] record.
|
|
"""
|
|
logging.info('Writing metrics by %s to %s', key_name.lower(), filename)
|
|
writer = csv.writer(open(filename, 'wb'))
|
|
writer.writerow([key_name, 'Updates', 'Security', 'Total'])
|
|
for key, metrics in metrics:
|
|
writer.writerow(
|
|
[key, metrics['Updates'], metrics['Security'], metrics['Total']])
|
|
|
|
|
|
def main(argv):
|
|
parser = OptionParser(
|
|
usage="%prog [options] ubuntu-release-name")
|
|
parser.add_option(
|
|
'-l', '--launchpad', default='production', dest='lp_instance',
|
|
help="Select the Launchpad instance to run against. Defaults to "
|
|
"'production'")
|
|
parser.add_option(
|
|
'-v', '--verbose', default=0, action='count', dest='verbose',
|
|
help="Increase verbosity of the script. -v prints info messages, "
|
|
"-vv will print debug messages.")
|
|
parser.add_option(
|
|
'-c', '--credentials', default=None, action='store',
|
|
dest='credentials',
|
|
help="Use the OAuth credentials in FILE instead of the desktop "
|
|
"one.", metavar='FILE')
|
|
parser.add_option(
|
|
'-d', '--distribution', default='ubuntu', action='store',
|
|
dest='distribution',
|
|
help="The distribution to compute metrics for. Defaults to 'ubuntu'.")
|
|
options, args = parser.parse_args(argv[1:])
|
|
if len(args) != 1:
|
|
parser.error('Missing archive name.')
|
|
|
|
if options.verbose >= 2:
|
|
log_level = logging.DEBUG
|
|
elif options.verbose == 1:
|
|
log_level = logging.INFO
|
|
else:
|
|
log_level = logging.WARNING
|
|
logging.basicConfig(level=log_level)
|
|
|
|
lp = Launchpad.login_with(
|
|
API_NAME, options.lp_instance, credentials_file=options.credentials,
|
|
version='devel')
|
|
|
|
try:
|
|
distribution = lp.distributions[options.distribution]
|
|
except KeyError:
|
|
parser.error('unknown distribution: %s' % options.distribution)
|
|
|
|
series = distribution.getSeries(name_or_version=args[0])
|
|
if series is None:
|
|
parser.error('unknown series: %s' % args[0])
|
|
archive = series.main_archive
|
|
|
|
updates_by_package = defaultdict(lambda: defaultdict(int))
|
|
updates_by_month = defaultdict(lambda: defaultdict(int))
|
|
for pocket in ['Updates', 'Security']:
|
|
logging.info(
|
|
'Retrieving published %s sources for %s...', pocket, args[0])
|
|
published_history = archive.getPublishedSources(
|
|
component_name='main', created_since_date=series.datereleased,
|
|
distro_series=series, pocket=pocket)
|
|
for source in published_history:
|
|
package_metrics = updates_by_package[source.source_package_name]
|
|
package_metrics[source.pocket] += 1
|
|
package_metrics['Total'] += 1
|
|
|
|
month = source.date_published.strftime('%Y-%m')
|
|
month_metrics = updates_by_month[month]
|
|
month_metrics[source.pocket] += 1
|
|
month_metrics['Total'] += 1
|
|
|
|
by_month_filename = '%s-%s-updates-by-month.csv' % (
|
|
options.distribution, args[0])
|
|
write_metrics_csv(
|
|
by_month_filename, 'Month', sorted(updates_by_month.items()))
|
|
|
|
by_package_filename = '%s-%s-updates-by-package.csv' % (
|
|
options.distribution, args[0])
|
|
write_metrics_csv(
|
|
by_package_filename, 'Package', sorted(
|
|
updates_by_package.items(),
|
|
key=lambda m: m[1]['Total'], reverse=True))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv)
|