|
|
|
@ -1,50 +1,51 @@ |
|
|
|
|
package common |
|
|
|
|
package sync |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"fmt" |
|
|
|
|
"math/rand" |
|
|
|
|
"os" |
|
|
|
|
"strconv" |
|
|
|
|
|
|
|
|
|
"git.csclub.uwaterloo.ca/public/merlin/config" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func (repo *Repo) buildRsyncHost() string { |
|
|
|
|
func buildRsyncHost(repo *config.Repo) string { |
|
|
|
|
if repo.RsyncUser != "" { |
|
|
|
|
repo.RsyncHost = repo.RsyncUser + "@" + repo.RsyncHost |
|
|
|
|
} |
|
|
|
|
return "rsync://" + repo.RsyncHost + "/" + repo.RsyncDir |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) buildRsyncDaemonHost() string { |
|
|
|
|
func buildRsyncDaemonHost(repo *config.Repo) string { |
|
|
|
|
if repo.RsyncUser != "" { |
|
|
|
|
repo.RsyncHost = repo.RsyncUser + "@" + repo.RsyncHost |
|
|
|
|
} |
|
|
|
|
return repo.RsyncHost + "::" + repo.RsyncDir |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) buildRsyncSSHHost() string { |
|
|
|
|
func buildRsyncSSHHost(repo *config.Repo) string { |
|
|
|
|
if repo.RsyncUser != "" { |
|
|
|
|
repo.RsyncHost = repo.RsyncUser + "@" + repo.RsyncHost |
|
|
|
|
} |
|
|
|
|
return repo.RsyncHost + ":" + repo.RsyncDir |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) buildDownloadDir() string { |
|
|
|
|
return repo.cfg.DownloadDir + "/" + repo.LocalDir |
|
|
|
|
func buildDownloadDir(repo *config.Repo) string { |
|
|
|
|
return config.Conf.DownloadDir + "/" + repo.LocalDir |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncApache() []string { |
|
|
|
|
func cscSyncApache(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-az", "--no-owner", "--no-group", "--delete", "--safe-links", |
|
|
|
|
"--timeout=3600", "-4", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--timeout=3600", "-4", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".~tmp~/", |
|
|
|
|
"--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncDaemonHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncDaemonHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncArchLinux() []string { |
|
|
|
|
func cscSyncArchLinux(repo *config.Repo) []string { |
|
|
|
|
|
|
|
|
|
tempDir := "" // is this option even needed?
|
|
|
|
|
|
|
|
|
@ -52,83 +53,83 @@ func (repo *Repo) CSCSyncArchLinux() []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"rsync", "-rtlH", "--safe-links", "--delete-after", "--timeout=600", |
|
|
|
|
"--contimeout=60", "-p", "--delay-updates", "--no-motd", |
|
|
|
|
"--temp-dir=" + tempDir, "--log-file=" + repo.RsyncLogFile, "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--temp-dir=" + tempDir, "--log-file=" + repo.RsyncLogFile, "--address=" + config.Conf.IPv4Address, |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncBadPerms() []string { |
|
|
|
|
func cscSyncBadPerms(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-aH", "--no-owner", "--no-group", "--chmod=o=rX", "--delete", |
|
|
|
|
"--timeout=3600", "-4", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--timeout=3600", "-4", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".~tmp~/", |
|
|
|
|
"--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncDaemonHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncDaemonHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO ceph
|
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncCDImage() []string { |
|
|
|
|
func cscSyncCDImage(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-aH", "--no-owner", "--no-group", "--delete", |
|
|
|
|
"--timeout=3600", "-4", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--timeout=3600", "-4", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".*/", "--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncDaemonHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncDaemonHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncChmod() []string { |
|
|
|
|
func cscSyncChmod(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-aH", "--no-owner", "--no-group", "--delete-after", "--delay-updates", "--safe-links", |
|
|
|
|
"--timeout=3600", "-4", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--timeout=3600", "-4", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".~tmp~/", "--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
"--chmod=u=rwX,go=rX", |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncDebian() []string { |
|
|
|
|
func cscSyncDebian(repo *config.Repo) []string { |
|
|
|
|
|
|
|
|
|
// sync /pool
|
|
|
|
|
args := []string{"nice", "rsync", "-rlHtvp", |
|
|
|
|
"--exclude", ".~tmp~/", "--timeout=3600", "-4", |
|
|
|
|
"--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--address=" + config.Conf.IPv4Address, |
|
|
|
|
} |
|
|
|
|
// $RSYNC_HOST::$RSYNC_DIR/pool/ $TO/pool/ >> $LOGFILE 2>&1
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncDebianCD() []string { |
|
|
|
|
func cscSyncDebianCD(repo *config.Repo) []string { |
|
|
|
|
|
|
|
|
|
// this is basically the same as CSCSyncDebian, except it has an extra --exclude
|
|
|
|
|
args := []string{"nice", "rsync", "-rlHtvp", "--delete", |
|
|
|
|
"--exclude", ".~tmp~/", "--timeout=3600", "-4", |
|
|
|
|
"--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--address=" + config.Conf.IPv4Address, |
|
|
|
|
// "--exclude", "Archive-Update-in-Progress-${HOSTNAME}"
|
|
|
|
|
} |
|
|
|
|
// $RSYNC_HOST::$RSYNC_DIR $TO >> $LOGFILE 2>&1
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncGentoo() []string { |
|
|
|
|
func cscSyncGentoo(repo *config.Repo) []string { |
|
|
|
|
repo.RsyncUser = "gentoo" |
|
|
|
|
repo.PasswordFile = "gentoo-distfiles" |
|
|
|
|
return repo.CSCSyncStandard() |
|
|
|
|
return cscSyncStandard(repo) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO s3
|
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncSSH() []string { |
|
|
|
|
func cscSyncSSH(repo *config.Repo) []string { |
|
|
|
|
|
|
|
|
|
args := []string{ |
|
|
|
|
"rsync", "-aH", "--no-owner", "--no-group", "--delete", |
|
|
|
@ -138,39 +139,39 @@ func (repo *Repo) CSCSyncSSH() []string { |
|
|
|
|
} |
|
|
|
|
// not sure if we should be assuming ssh identity file is the password file
|
|
|
|
|
args = append(args, "-e", fmt.Sprintf("'ssh -i %s'", repo.PasswordFile)) |
|
|
|
|
args = append(args, repo.buildRsyncSSHHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncSSHHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncStandard() []string { |
|
|
|
|
func cscSyncStandard(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-aH", "--no-owner", "--no-group", "--delete-after", |
|
|
|
|
"--delay-updates", "--safe-links", "--timeout=3600", "-4", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--delay-updates", "--safe-links", "--timeout=3600", "-4", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".~tmp~/", "--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
} |
|
|
|
|
if repo.PasswordFile != "" { |
|
|
|
|
filename := repo.cfg.PasswordDir + "/" + repo.PasswordFile |
|
|
|
|
filename := config.Conf.PasswordDir + "/" + repo.PasswordFile |
|
|
|
|
args = append(args, "--password-file", filename) |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) CSCSyncStandardIPV6() []string { |
|
|
|
|
func cscSyncStandardIPV6(repo *config.Repo) []string { |
|
|
|
|
args := []string{ |
|
|
|
|
"nice", "rsync", "-aH", "--no-owner", "--no-group", "--delete-after", |
|
|
|
|
"--delay-updates", "--safe-links", "--timeout=3600", "-6", "--address=" + repo.cfg.IPv4Address, |
|
|
|
|
"--delay-updates", "--safe-links", "--timeout=3600", "-6", "--address=" + config.Conf.IPv4Address, |
|
|
|
|
"--exclude", ".~tmp~/", "--quiet", "--stats", "--log-file=" + repo.RsyncLogFile, |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncDaemonHost(), repo.buildDownloadDir()) |
|
|
|
|
args = append(args, buildRsyncDaemonHost(repo), buildDownloadDir(repo)) |
|
|
|
|
|
|
|
|
|
return args |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// for testing, to be removed later
|
|
|
|
|
func (repo *Repo) CSCSyncDummy() []string { |
|
|
|
|
func cscSyncDummy(repo *config.Repo) []string { |
|
|
|
|
|
|
|
|
|
sleepDur := strconv.FormatInt(rand.Int63n(10)+5, 10) |
|
|
|
|
args := []string{"sleep", sleepDur} |
|
|
|
@ -179,7 +180,7 @@ func (repo *Repo) CSCSyncDummy() []string { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// executes a particular sync job depending on repo.SyncType.
|
|
|
|
|
func (repo *Repo) getSyncCommand() []string { |
|
|
|
|
func getSyncCommand(repo *config.Repo) []string { |
|
|
|
|
/* |
|
|
|
|
# scripts used by merlin.py |
|
|
|
|
csc-sync-debian |
|
|
|
@ -208,78 +209,38 @@ func (repo *Repo) getSyncCommand() []string { |
|
|
|
|
switch repo.SyncType { |
|
|
|
|
|
|
|
|
|
case "csc-sync-apache": |
|
|
|
|
return repo.CSCSyncApache() |
|
|
|
|
return cscSyncApache(repo) |
|
|
|
|
case "csc-sync-archlinux": |
|
|
|
|
return repo.CSCSyncArchLinux() |
|
|
|
|
return cscSyncArchLinux(repo) |
|
|
|
|
case "csc-sync-badperms": |
|
|
|
|
return repo.CSCSyncBadPerms() |
|
|
|
|
return cscSyncBadPerms(repo) |
|
|
|
|
case "csc-sync-cdimage": |
|
|
|
|
return repo.CSCSyncCDImage() |
|
|
|
|
return cscSyncCDImage(repo) |
|
|
|
|
// case "csc-sync-ceph":
|
|
|
|
|
// return repo.CSCSyncCeph()
|
|
|
|
|
// return cscSyncCeph(repo)
|
|
|
|
|
case "csc-sync-chmod": |
|
|
|
|
return repo.CSCSyncChmod() |
|
|
|
|
return cscSyncChmod(repo) |
|
|
|
|
case "csc-sync-debian": |
|
|
|
|
return repo.CSCSyncDebian() |
|
|
|
|
return cscSyncDebian(repo) |
|
|
|
|
case "csc-sync-debian-cd": |
|
|
|
|
return repo.CSCSyncDebianCD() |
|
|
|
|
return cscSyncDebianCD(repo) |
|
|
|
|
case "csc-sync-gentoo": |
|
|
|
|
return repo.CSCSyncGentoo() |
|
|
|
|
return cscSyncGentoo(repo) |
|
|
|
|
// case "csc-sync-s3":
|
|
|
|
|
// return repo.CSCSyncS3()
|
|
|
|
|
// return cscSyncS3(repo)
|
|
|
|
|
case "csc-sync-ssh": |
|
|
|
|
return repo.CSCSyncSSH() |
|
|
|
|
return cscSyncSSH(repo) |
|
|
|
|
case "csc-sync-standard": |
|
|
|
|
return repo.CSCSyncStandard() |
|
|
|
|
return cscSyncStandard(repo) |
|
|
|
|
case "csc-sync-standard-ipv6": |
|
|
|
|
return repo.CSCSyncStandardIPV6() |
|
|
|
|
return cscSyncStandardIPV6(repo) |
|
|
|
|
// case "csc-sync-wget":
|
|
|
|
|
// return repo.CSCSyncWget()
|
|
|
|
|
// return cscSyncWget(repo)
|
|
|
|
|
case "csc-sync-dummy": |
|
|
|
|
return repo.CSCSyncDummy() |
|
|
|
|
return cscSyncDummy(repo) |
|
|
|
|
default: |
|
|
|
|
repo.Logger.Error("Unrecognized sync type", "'"+repo.SyncType+"'") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return []string{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (repo *Repo) StartSyncJob() { |
|
|
|
|
status := FAILURE |
|
|
|
|
defer func() { |
|
|
|
|
repo.DoneChan <- Result{ |
|
|
|
|
Name: repo.Name, |
|
|
|
|
Exit: status, |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
localDir := repo.buildDownloadDir() |
|
|
|
|
err := os.MkdirAll(localDir, 0775) |
|
|
|
|
if err != nil { |
|
|
|
|
err = fmt.Errorf("Could not create directory %s: %w", localDir, err) |
|
|
|
|
// I'm not sure if logger can handle error so just use the string?
|
|
|
|
|
repo.Logger.Error(err.Error()) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
args := repo.getSyncCommand() |
|
|
|
|
if repo.PasswordFile != "" { |
|
|
|
|
filename := repo.cfg.PasswordDir + "/" + repo.PasswordFile |
|
|
|
|
args = append(args, "--password-file", filename) |
|
|
|
|
} |
|
|
|
|
args = append(args, repo.buildRsyncHost(), localDir) |
|
|
|
|
|
|
|
|
|
ch := SpawnProcess(repo, args) |
|
|
|
|
if ch == nil { |
|
|
|
|
// SpawnProcess will have already logged error
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
cmd := <-ch |
|
|
|
|
switch cmd.ProcessState.ExitCode() { |
|
|
|
|
case 0: |
|
|
|
|
status = SUCCESS |
|
|
|
|
case -1: |
|
|
|
|
status = TERMINATED |
|
|
|
|
// default is already FAILURE
|
|
|
|
|
} |
|
|
|
|
} |