TODO NOW:
-- Genericize callAsUser and drop_priviledges in shell
- Remove "already migrated" cruft that will accumulate if we do small
--limit and then increase.
-- Make sure to generate reports about what errored and what had warnings.
- Same goes for our output
-- Allow to migrate just one user (user filtering of installs)
-- Make sure MediaWiki upgrade script does not give proper exit code
- if it fails, so be sure to check for "Done" in the last 10 characters.
+- Allow to migrate just one user (user filtering of installs, also
+ has userland capabilities, although it means we need some way of
+ selectively publishing the versions directory)
- Make parallel-find.pl use `sudo -u username git describe --tags`
to determine version. Make parallel-find.pl have this have greater
- Better error message if daemon/scripts-security-upd
is not on scripts-security-upd list
+- MediaWiki upgrade script does not give proper exit code;
+ if it fails, so be sure to check for "Done" in the last 10 characters.
- Custom merge algo: absolute php.ini symlinks to relative symlinks
- Custom merge algo: re-constitute AdminSettings.php if missing. It looks
like this is the case for most 1.5.8 installs (check what the merges
- Redo Wordpress conversion, with an eye for automating everything
possible (such as downloading the tarball and unpacking)
+- Genericize callAsUser and drop_priviledges in shell
- Summary script should be more machine friendly, and should not
output summary charts when I increase specificity
logger.setLevel(logging.DEBUG)
else:
stderr.setLevel(logging.WARNING)
- if options.verbose or hasattr(options, "dry_run"):
+ if options.verbose or hasattr(options, "dry_run") and options.dry_run:
stderr.setLevel(logging.INFO)
if options.log_file:
file.setLevel(logging.INFO)
sh = make_shell(options)
seen = make_serialized_set(options)
my_uid = os.getuid() # to see if we have root
+ warnings_logname = "/tmp/wizard-migrate-warnings.log"
+ errors_logname = "/tmp/wizard-migrate-errors.log"
if options.log_dir:
# must not be on AFS
try:
options.log_dir = os.path.join(options.log_dir, str(int(time.time())))
os.mkdir(options.log_dir) # if fails, be fatal
os.chmod(options.log_dir, 0o777)
+ warnings_logname = os.path.join(options.log_dir, "warnings.log")
+ errors_logname = os.path.join(options.log_dir, "errors.log")
+ warnings_log = open(warnings_logname, "a")
+ errors_log = open(errors_logname, "a")
# loop stuff
errors = {}
i = 0
log_file = os.path.join(options.log_dir, shorten(i, d.location))
child_args.append("--log-file=" + log_file)
# actual meat
- def make_on_pair(d):
+ def make_on_pair(d, i):
def on_success(stdout, stderr):
+ if stderr:
+ warnings_log.write("%s\n" % d.location)
+ logging.warning("Warnings [%04d] %s:\n%s" % (d.location, i, stderr))
seen.add(d.location)
def on_error(e):
if e.name == "wizard.command.migrate.AlreadyMigratedError" or \
name = e.name
if name not in errors: errors[name] = []
errors[name].append(d)
- logging.error("%s in %s" % (name, d.location))
+ logging.error("%s in [%04d] %s" % (name, i, d.location))
+ errors_log.write("%s\n" % d.location)
return (on_success, on_error)
- on_success, on_error = make_on_pair(d)
+ on_success, on_error = make_on_pair(d, i)
sh.wait() # wait for a parallel processing slot to be available
sh.call("wizard", "migrate", d.location, *child_args,
on_success=on_success, on_error=on_error)
def calculate_base_args(options):
base_args = command.makeBaseArgs(options, dry_run="--dry-run", srv_path="--srv-path", force="--force")
- base_args += '--quiet'
return base_args
def shorten(i, dir):
os.unsetenv("GIT_DIR") # prevent some perverse errors
- make_repository(sh, options, repo, tag)
- check_variables(deployment, options)
+ try:
+ try:
+ os.fdopen(os.open(".scripts-migrate-lock", os.O_CREAT | os.O_EXCL)).write(str(os.getpid()))
+ except OSError as e:
+ if e.errno == errno.EEXIST:
+ raise DirectoryLockedError
+ elif e.errno == errno.EACCES:
+ raise command.PermissionsError(dir)
+ make_repository(sh, options, repo, tag)
+ check_variables(deployment, options)
+ finally:
+ try:
+ os.unlink(".scripts-migrate-lock")
+ except OSError:
+ pass
def parse_args(argv, baton):
usage = """usage: %prog migrate [ARGS] DIR
this is an autoinstalled application?
"""
+class DirectoryLockedError(Error):
+ def __init__(self, dir):
+ self.dir = dir
+ def __str__(self):
+ return """
+
+ERROR: Could not acquire lock on directory. Maybe there is
+another migration process running?
+"""
+
class NoTagError(Error):
def __init__(self, version):
self.version = version
self.stdout = stdout
self.stderr = stderr
def __str__(self):
- return "CallError [%d]" % self.code
+ return "CallError [%d]\n%s" % (self.code, self.stderr)
class PythonCallError(CallError):
"""
CallError.__init__(self, code, args, stdout, stderr)
def __str__(self):
if self.name:
- return "PythonCallError [%s]" % self.name
+ return "PythonCallError [%s]\n%s" % (self.name, self.stderr)
else:
- return "PythonCallError"
+ return "PythonCallError\n%s" % self.stderr