#!/usr/bin/env python import os import sys import subprocess import pickle from optparse import OptionParser def call(command): print "PYTHONPATH=%s" % os.environ["PYTHONPATH"], " ".join(command) subprocess.check_call(command, env=os.environ) def cmdget(command): print "PYTHONPATH=%s" % os.environ["PYTHONPATH"], " ".join(command) out = subprocess.check_output(command, env=os.environ) return out.strip() class Importer(object): def __init__(self, opts, config): self.opts = opts self.config = config self.existing_lists = cmdget( ["sudo", "-u", "mailman", "mailman3", "lists", "-q"]) self.index_path = self._get_index_path() def _get_index_path(self): sys.path.append(self.config["confdir"]) settings = __import__("settings") sys.path.pop() return settings.KITTYSTORE_SEARCH_INDEX def import_dir(self, mm2libdir): all_listnames = [ d for d in os.listdir( os.path.join(mm2libdir, 'lists')) if not d.startswith(".") ] all_listnames.sort() for index, listname in enumerate(all_listnames): listaddr = "%s@%s" % (listname, self.config["domain"]) print listaddr, "(%d/%d)" % (index+1, len(all_listnames)) confpickle = os.path.join(mm2libdir, 'lists', listname, 'config.pck') if not os.path.exists(confpickle): print "Missing configuration pickle:", confpickle continue list_is_new = bool(listaddr not in self.existing_lists) if list_is_new: call(["sudo", "-u", "mailman", "mailman3", "create", "-d", listaddr]) call(["sudo", "-u", "mailman", "mailman3", "import21", listaddr, confpickle]) if not self.opts.no_archives: archivefile = os.path.join( mm2libdir, "archives", "private", "%s.mbox" % listname, "%s.mbox" % listname) archive_policy = bool(pickle.load( open(confpickle)).get('archive')) if not archive_policy: print "List %s wants no archiving" % listname continue if os.path.exists(archivefile) and \ (list_is_new or not self.opts.new_only): call(["sudo", "kittystore-import", "-p", self.config["confdir"], "-s", "settings_admin", "-l", listaddr, "--continue", archivefile]) if self.index_path: call(["sudo", "chown", "mailman:", "-R", self.index_path]) def main(): parser = OptionParser() parser.add_option("-n", "--new-only", action="store_true", help="Only import the archives when the list is new") parser.add_option("-A", "--no-archives", action="store_true", help="Don't import the archives, only import the list config") parser.add_option("-c", "--config", default="/etc/mailman-migration.conf", help="Configuration file (default: %defaults)") opts, args = parser.parse_args() if len(args) != 1: parser.error("Only one arg: the Mailman 2.1 lib dir to import") mm2libdir = args[0] if not os.path.exists(mm2libdir): parser.error("No such directory: %s" % mm2libdir) with open(opts.config) as conffile: config = yaml.safe_load(conffile) sys.path.append(config["mm21codedir"]) # set the env var to propagate to subprocesses os.environ["PYTHONPATH"] = config["mm21codedir"] importer = Importer(opts, config) importer.import_dir(mm2libdir) if __name__ == "__main__": main()