- for i, d in enumerate(requested_deploys, 1):
- # check if we want to punt due to --limit
- if d.location in seen:
- continue
- if is_root and not command.security_check_homedir(d):
- continue
- # XXX: we may be able to punt based on detected versions from d
- logging.info("Processing %s" % d.location)
- child_args = list(base_args)
- # calculate the log file, if a log dir was specified
- if options.log_dir:
- log_file = command.calculate_log_name(options.log_dir, i, d.location)
- child_args.append("--log-file=" + log_file)
- # actual meat
- def make_on_pair(d, i):
- # we need to make another stack frame so that d and i get specific bindings.
- def on_success(stdout, stderr):
- if stderr:
- warnings_log.write("%s\n" % d.location)
- logging.warning("Warnings [%04d] %s:\n%s" % (i, d.location, stderr))
- seen.add(d.location)
- def on_error(e):
- if e.name == "wizard.command.upgrade.AlreadyUpgradedError" or \
- e.name == "AlreadyUpgradedError":
- seen.add(d.location)
- logging.info("Skipped already upgraded %s" % d.location)
- elif e.name == "MergeFailed":
- seen.add(d.location)
- logging.warning("Merge failed: resolve at [%s], source at [%s]" % (e.stdout.rstrip(), d.location))
- merge_log.write("%s\n" % d.location)
- else:
- name = e.name
- if name not in errors: errors[name] = []
- errors[name].append(d)
- 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, i)
- sh.call("wizard", "upgrade", d.location, *child_args,
- on_success=on_success, on_error=on_error)
- sh.join()
- for name, deploys in errors.items():
- logging.warning("%s from %d installs" % (name, len(deploys)))
+ # clean up /dev/shm/wizard
+ if os.path.exists("/dev/shm/wizard"):
+ shutil.rmtree("/dev/shm/wizard")
+ os.mkdir("/dev/shm/wizard")
+ os.chmod("/dev/shm/wizard", 0o777)
+ try:
+ for i, d in enumerate(requested_deploys, 1):
+ runtime.write("lookup", i, d.location)
+ if not os.getuid() and not command.security_check_homedir(d.location):
+ continue
+ if not options.redo:
+ found = False
+ for r in status.reports.values():
+ if i in r.values:
+ found = True
+ break
+ if found:
+ continue
+ # XXX: we may be able to punt based on detected versions from d, which
+ # would be faster than spinning up a new process. On the other hand,
+ # our aggressive caching strategies using reports make this mostly not a problem
+ logging.info("[%04d] Processing %s", i, d.location)
+ child_args = list(base_args) # copy
+ # calculate the log file, if a log dir was specified
+ if options.log_dir:
+ log_file = command.calculate_log_name(options.log_dir, i)
+ child_args.append("--log-file=" + log_file)
+ # actual meat
+ def make_on_pair(d, i):
+ # we need to make another stack frame so that d and i get specific bindings.
+ def on_success(stdout, stderr):
+ if stderr:
+ runtime.write("warnings", i, d.location)
+ logging.warning("[%04d] Warnings at [%s]:\n%s", i, d.location, stderr)
+ runtime.write("success", i, d.location)
+ status.write("up_to_date", i, d.location)
+ def on_error(e):
+ if e.name == "AlreadyUpgraded":
+ logging.info("[%04d] Skipped already upgraded %s" % (i, d.location))
+ status.write("up_to_date", i, d.location)
+ elif e.name == "MergeFailed":
+ conflicts, _, tmpdir = e.stdout.rstrip().partition(" ")
+ logging.warning("[%04d] Conflicts in %s files: resolve at [%s], source at [%s]",
+ i, conflicts, tmpdir, d.location)
+ status.write("merge", i, tmpdir, conflicts, d.location)
+ elif e.name == "BlacklistedError":
+ reason = e.stdout.rstrip().replace("\n", " ")
+ logging.warning("[%04d] Blacklisted because of '%s' at %s", i, reason, d.location)
+ status.write("blacklisted", i, d.location, reason)
+ elif e.name == "WebVerificationError":
+ url = d.url.geturl()
+ # This should actually be a warning, but it's a really common error
+ logging.info("[%04d] Could not verify application at %s", i, url)
+ status.write("verify", i, url)
+ elif e.name == "DatabaseVerificationError":
+ logging.info("[%04d] Could not verify database ast %s", i, d.location)
+ status.write("db", i, d.location)
+ elif e.name == "NotMigratedError":
+ logging.info("[%04d] Application not migrated at %s", i, d.location)
+ status.write("not_migrated", i, d.location)
+ elif e.name == "BackupFailure":
+ logging.info("[%04d] Failed backups at %s", i, d.location)
+ status.write("backup_failure", i, d.location)
+ elif e.name == "QuotaTooLow":
+ logging.info("[%04d] Quota too low at %s", i, d.location)
+ status.write("quota", i, d.location)
+ elif e.name == "PermissionsError":
+ logging.info("[%04d] Insufficient permissions to upgrade %s", i, d.location)
+ status.write("permissions", i, d.location)
+ else:
+ errors.setdefault(e.name, []).append(d)
+ logging.error("[%04d] %s in %s", i, e.name, d.location)
+ runtime.write("errors", i, e.name, d.location)
+ # lack of status write means that we'll always retry
+ return (on_success, on_error)
+ on_success, on_error = make_on_pair(d, i)
+ sh.call("wizard", "upgrade", d.location, *child_args,
+ on_success=on_success, on_error=on_error)
+ sh.join()
+ finally:
+ sys.stderr.write("\n")
+ for name, deploys in errors.items():
+ logging.warning("%s from %d installs", name, len(deploys))
+ print
+ total = sum(len(x.values) for x in status.reports.values())
+ def printPercent(description, number):
+ print "% 4d out of % 4d installs (% 5.1f%%) %s" % (number, total, float(number)/total*100, description)
+ error_count = sum(len(e) for e in errors.values())
+ if error_count:
+ printPercent("had unusual errors", error_count)
+ for name, description in human_status.items():
+ values = status.reports[name].values
+ if values:
+ printPercent(description, len(values))
+ sys.stderr.write("\n")
+ print "%d installs were upgraded this run" % len(runtime.reports["success"].values)