--- .../nodes/datagrepper01.phx2.fedoraproject.org.pp | 2 + modules/owner_changes/files/fedora-owner-change.py | 232 ++++++++++++++++++++ modules/owner_changes/manifests/init.pp | 23 ++ 3 files changed, 257 insertions(+), 0 deletions(-) create mode 100644 modules/owner_changes/files/fedora-owner-change.py create mode 100644 modules/owner_changes/manifests/init.pp diff --git a/manifests/nodes/datagrepper01.phx2.fedoraproject.org.pp b/manifests/nodes/datagrepper01.phx2.fedoraproject.org.pp index 41eba4c..63fea5d 100644 --- a/manifests/nodes/datagrepper01.phx2.fedoraproject.org.pp +++ b/manifests/nodes/datagrepper01.phx2.fedoraproject.org.pp @@ -10,6 +10,8 @@ node "datagrepper01.phx2.fedoraproject.org" { include datagrepper::app include openvpn::client + include owner_changes + iptables::firewall { 'ipv4': tcpPorts => [ 80, 443 ], custom => [ "-A INPUT -p tcp -m tcp -s 10.5.126.29 --dport 873 -j ACCEPT", diff --git a/modules/owner_changes/files/fedora-owner-change.py b/modules/owner_changes/files/fedora-owner-change.py new file mode 100644 index 0000000..662ed6c --- /dev/null +++ b/modules/owner_changes/files/fedora-owner-change.py @@ -0,0 +1,232 @@ +#!/usr/bin/python -tt +#-*- coding: utf-8 -*- + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +""" +This program checks and reports the packages owner change in pkgdb using +its messages catched by datanommer and available via datagrepper. + +Dependencies: +* python-requests +* python-argparse +""" + +import argparse +import json +import logging +import requests +import smtplib +import sys + +from email.mime.text import MIMEText + + +DATAGREPPER_URL = 'https://apps.fedoraproject.org/datagrepper/raw/' +DELTA = 1 * 24 * 60 * 60 # 1 day +TOPIC = 'org.fedoraproject.prod.pkgdb.owner.update' +EMAIL_TO = '' +EMAIL_FROM = '' +SMTP_SERVER = 'localhost' + +# Initial simple logging stuff +logging.basicConfig() +LOG = logging.getLogger("owner-change") + + +class PkgChange(object): + + def __init__(self, name, summary, branch, new_owner, user): + """ Constructor, fills in the basic information. + """ + self.name = name + self.summary = summary + self.branch = [branch] + self.new_owner = new_owner + self.user = user + + def add_branch(self, branch): + """ Add a branch to the current ones. """ + self.branch.append(branch) + + def unorphaned(self): + """ Returns a boolean specifying if the package has been + unorphaned or not. + """ + return self.new_owner == self.user + + def to_string(self): + """ String representation of the object adjusted for the + ownership change. + """ + if self.new_owner == self.user: + output = u'%s [%s] was unorphaned by %s' % ( + self.name, ','.join(sorted(self.branch)), + self.user) + elif self.new_owner == 'orphan': + output = u'%s [%s] was orphaned by %s' % ( + self.name, ','.join(sorted(self.branch)), + self.user) + else: + output = u'%s [%s] was changed to "%s" by %s' % ( + self.name, ','.join(sorted(self.branch)), + self.new_owner, self.user) + return output + + +def send_report(report): + """ This function sends the actual report. + :arg report: the content to send by email + """ + msg = MIMEText(report) + msg['Subject'] = '[Owner-change] Fedora packages ownership change' + msg['From'] = EMAIL_FROM + msg['To'] = EMAIL_TO + + # Send the message via our own SMTP server, but don't include the + # envelope header. + s = smtplib.SMTP(SMTP_SERVER) + s.sendmail(EMAIL_FROM, + EMAIL_TO, + msg.as_string()) + s.quit() + + +def retrieve_pkgdb_change(): + """ Query datagrepper to retrieve the list of change in ownership + on packages of pkgdb over the DELTA period of time. + """ + messages = [] + page = 1 + pages = 2 + while page <= pages: + LOG.debug('Retrieving page %s of %s' % (page, pages)) + data = {'delta': DELTA, + 'topic': TOPIC, + 'rows_per_page': 100, + 'page': page, + } + output = requests.get(DATAGREPPER_URL, params=data) + json_output = json.loads(output.text) + pages = json_output['pages'] + page += 1 + messages.extend(json_output['raw_messages']) + + LOG.debug('Should have retrieved %s' % json_output['total']) + return messages + + +def setup_parser(): + """ + Set the command line arguments. + """ + parser = argparse.ArgumentParser( + prog="fedora-owner-change") + parser.add_argument( + '--nomail', action='store_true', + help="Prints the report instead of sending it by email") + parser.add_argument( + '--debug', action='store_true', + help="Outputs debugging info") + return parser + + +def main(): + """ Retrieve all the change in ownership from pkgdb via datagrepper + and report the changes either as packages have been orphaned or + packages changed owner. + """ + parser = setup_parser() + args = parser.parse_args() + + global LOG + if args.debug: + LOG.setLevel(logging.DEBUG) + + changes = retrieve_pkgdb_change() + LOG.debug('%s changes retrieved' % len(changes)) + orphaned = {} + unorphaned = {} + changed = {} + for change in changes: + pkg_name = change['msg']['package_listing']['package']['name'] + owner = change['msg']['package_listing']['owner'] + branch = change['msg']['package_listing']['collection']['branchname'] + user = change['msg']['agent'] + LOG.debug('%s changed to %s by %s on %s' % ( + pkg_name, owner, user, branch)) + pkg = PkgChange( + name=pkg_name, + summary=change['msg']['package_listing']['package']['summary'], + branch=branch, + new_owner=owner, + user=user, + ) + + if owner == 'orphan': + if pkg_name in orphaned: + orphaned[pkg_name].add_branch(branch) + else: + orphaned[pkg_name] = pkg + elif owner == user: + if pkg_name in orphaned: + del(orphaned[pkg_name]) + + if pkg_name in changed: + unorphaned[pkg_name].add_branch(branch) + else: + unorphaned[pkg_name] = pkg + else: + if pkg_name in orphaned: + del(orphaned[pkg_name]) + + if pkg_name in changed: + changed[pkg_name].add_branch(branch) + else: + changed[pkg_name] = pkg + + hours = int(DELTA) / 3600 + report = 'Change in ownership over the last %s hours\n' % hours + report += '=' * (40 + len(str(hours))) + '\n' + + report += '\n%s packages were orphaned\n' % len(orphaned) + report += '-' * (len(str(len(orphaned))) + 23) + '\n' + for pkg in orphaned: + report += orphaned[pkg].to_string() + '\n' + report += ' ' * 5 + orphaned[pkg].summary + '\n' + report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\ + 'acls/name/%s\n' % orphaned[pkg].name + + report += '\n%s packages unorphaned\n' % len(unorphaned) + report += '-' * (len(str(len(unorphaned))) + 20) + '\n' + for pkg in unorphaned: + if unorphaned[pkg].unorphaned(): + report += unorphaned[pkg].to_string() + '\n' + + report += '\n%s packages changed owner\n' % len(changed) + report += '-' * (len(str(len(changed))) + 23) + '\n' + for pkg in changed: + if not changed[pkg].unorphaned(): + report += changed[pkg].to_string() + '\n' + + if args.nomail: + print report + else: + send_report(report) + + +if __name__ == '__main__': + import sys + sys.exit(main()) diff --git a/modules/owner_changes/manifests/init.pp b/modules/owner_changes/manifests/init.pp new file mode 100644 index 0000000..e507cc5 --- /dev/null +++ b/modules/owner_changes/manifests/init.pp @@ -0,0 +1,23 @@ +class owner_changes { + + package { "python-requests": + ensure => installed, + } + + file { "/usr/local/bin/fedora-owner-change.py": + owner => "root", + group => "root", + mode => 0755, + source => "puppet:///owner_changes/fedora-owner-change.py", + } + + cron { "gather-easyfix": + command => "/usr/bin/python /usr/local/bin/fedora-owner-change.py", + user => "pingou", + minute => 0, + hour => 12, + weekday => 1, + ensure => "present", + } + +} -- 1.7.2.1 _______________________________________________ infrastructure mailing list infrastructure@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/infrastructure