The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3196
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 0683675013503d82e97e0a50773422077389d9f5 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 20 Apr 2017 11:45:00 +0200 Subject: [PATCH 1/3] util_linux: add function to detect errno Closes #2494. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- shared/util_linux.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/shared/util_linux.go b/shared/util_linux.go index a01dbc1..519bb71 100644 --- a/shared/util_linux.go +++ b/shared/util_linux.go @@ -778,3 +778,23 @@ func LookupBlockDevByUUID(uuid string) (string, error) { return detectedPath, nil } + +// Detect whether err is an errno. +func GetErrno(err error) (errno error, iserrno bool) { + sysErr, ok := err.(*os.SyscallError) + if ok { + return sysErr.Err, true + } + + pathErr, ok := err.(*os.PathError) + if ok { + return pathErr.Err, true + } + + tmpErrno, ok := err.(syscall.Errno) + if ok { + return tmpErrno, true + } + + return nil, false +} From c8aed1e471e6116f38695db4492a88aa030dce09 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 20 Apr 2017 14:12:18 +0200 Subject: [PATCH 2/3] netcat: switch to new helper Closes #2494. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/main_netcat.go | 82 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/lxd/main_netcat.go b/lxd/main_netcat.go index 7de62f8..aa86780 100644 --- a/lxd/main_netcat.go +++ b/lxd/main_netcat.go @@ -5,8 +5,11 @@ import ( "io" "net" "os" + "strings" "sync" "syscall" + + "github.com/lxc/lxd/shared" ) // Netcat is called with: @@ -21,13 +24,47 @@ func cmdNetcat(args []string) error { return fmt.Errorf("Bad arguments %q", args) } + // The socket name on LXD instances prior to netcat log file is: + // /<some-tmp-path/lxd_rsync_<random-suffix> + // and on LXD instances with netcat log file: + // /<some-tmp-path/lxd_<ctName>_rsync_<random-suffix> + // Detect the latter case and create a netcat log + namestart := strings.LastIndex(args[1], "/lxd_") + nameend := strings.LastIndex(args[1], "_rsync_") + var logFile *os.File + var err error + if namestart > 0 && nameend > 0 { + namestart += len("/lxd_") - 1 + if namestart != nameend { + ctName := args[1][namestart+1 : nameend] + + logPath := shared.LogPath(ctName, "netcat.log") + if shared.PathExists(logPath) { + os.Remove(logPath) + } + + logFile, err := os.OpenFile(logPath, os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0644) + if err != nil { + logFile = nil + } else { + defer logFile.Close() + } + } + } + uAddr, err := net.ResolveUnixAddr("unix", args[1]) if err != nil { + if logFile != nil { + logFile.WriteString(fmt.Sprintf("Could not resolve unix domain socket \"%s\": %s.\n", args[1], err)) + } return err } conn, err := net.DialUnix("unix", nil, uAddr) if err != nil { + if logFile != nil { + logFile.WriteString(fmt.Sprintf("Could not dial unix domain socket \"%s\": %s.\n", args[1], err)) + } return err } @@ -35,13 +72,19 @@ func cmdNetcat(args []string) error { wg.Add(1) go func() { - io.Copy(eagainWriter{os.Stdout}, eagainReader{conn}) + _, err := io.Copy(eagainWriter{os.Stdout}, eagainReader{conn}) + if err != nil && logFile != nil { + logFile.WriteString(fmt.Sprintf("Error while copying from stdout to unix domain socket \"%s\": %s.\n", args[1], err)) + } conn.Close() wg.Done() }() go func() { - io.Copy(conn, os.Stdin) + _, err := io.Copy(eagainWriter{conn}, eagainReader{os.Stdin}) + if err != nil && logFile != nil { + logFile.WriteString(fmt.Sprintf("Error while copying from unix domain socket \"%s\" to stdin: %s.\n", args[1], err)) + } }() wg.Wait() @@ -54,27 +97,15 @@ type eagainReader struct { } func (er eagainReader) Read(p []byte) (int, error) { - // keep retrying on EAGAIN again: n, err := er.r.Read(p) if err == nil { return n, nil } - var errno error - // EAGAIN errors can hide in os.PathError. My best explanation for this - // weirdness is that os.Stdout refers to /dev/stdout which is a path. - sysErr, ok := err.(*os.PathError) - if ok { - errno = sysErr.Err - } else { - tmpErrno, ok := err.(syscall.Errno) - if ok { - errno = tmpErrno - } - } - - if errno == syscall.EAGAIN { + // keep retrying on EAGAIN + errno, ok := shared.GetErrno(err) + if ok && errno == syscall.EAGAIN { goto again } @@ -86,26 +117,15 @@ type eagainWriter struct { } func (ew eagainWriter) Write(p []byte) (int, error) { - // keep retrying on EAGAIN again: n, err := ew.w.Write(p) if err == nil { return n, nil } - var errno error - // EAGAIN errors can hide in os.PathError. My best explanation for this - // weirdness is that os.Stdout refers to /dev/stdout which is a path. - sysErr, ok := err.(*os.PathError) - if ok { - errno = sysErr.Err - } else { - tmpErrno, ok := err.(syscall.Errno) - if ok { - errno = tmpErrno - } - } - if errno == syscall.EAGAIN { + // keep retrying on EAGAIN + errno, ok := shared.GetErrno(err) + if ok && errno == syscall.EAGAIN { goto again } From 9ce1ac2c5faf8fee0f3ab7399b3f220f864320a3 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 20 Apr 2017 14:13:10 +0200 Subject: [PATCH 3/3] netcat: implement logging Closes #2494. Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/migrate.go | 3 ++- lxd/rsync.go | 9 +++++---- lxd/storage_migration.go | 8 +++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/lxd/migrate.go b/lxd/migrate.go index 1a8ad44..bba9a77 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -522,7 +522,8 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error { * no reason to do these in parallel. In the future when we're using * p.haul's protocol, it will make sense to do these in parallel. */ - err = RsyncSend(shared.AddSlash(checkpointDir), s.criuConn, nil, bwlimit) + ctName := s.container.Name() + err = RsyncSend(ctName, shared.AddSlash(checkpointDir), s.criuConn, nil, bwlimit) if err != nil { return abort(err) } diff --git a/lxd/rsync.go b/lxd/rsync.go index 44775f4..6d262fe 100644 --- a/lxd/rsync.go +++ b/lxd/rsync.go @@ -43,12 +43,13 @@ func rsyncLocalCopy(source string, dest string, bwlimit string) (string, error) dest) } -func rsyncSendSetup(path string, bwlimit string) (*exec.Cmd, net.Conn, io.ReadCloser, error) { +func rsyncSendSetup(name string, path string, bwlimit string) (*exec.Cmd, net.Conn, io.ReadCloser, error) { /* * It's sort of unfortunate, but there's no library call to get a * temporary name, so we get the file and close it and use its name. */ - f, err := ioutil.TempFile("", "lxd_rsync_") + tmp := fmt.Sprintf("lxd_%s_rsync_", name) + f, err := ioutil.TempFile("", tmp) if err != nil { return nil, nil, nil, err } @@ -124,8 +125,8 @@ func rsyncSendSetup(path string, bwlimit string) (*exec.Cmd, net.Conn, io.ReadCl // RsyncSend sets up the sending half of an rsync, to recursively send the // directory pointed to by path over the websocket. -func RsyncSend(path string, conn *websocket.Conn, readWrapper func(io.ReadCloser) io.ReadCloser, bwlimit string) error { - cmd, dataSocket, stderr, err := rsyncSendSetup(path, bwlimit) +func RsyncSend(name string, path string, conn *websocket.Conn, readWrapper func(io.ReadCloser) io.ReadCloser, bwlimit string) error { + cmd, dataSocket, stderr, err := rsyncSendSetup(name, path, bwlimit) if err != nil { return err } diff --git a/lxd/storage_migration.go b/lxd/storage_migration.go index b207374..ba0babd 100644 --- a/lxd/storage_migration.go +++ b/lxd/storage_migration.go @@ -41,6 +41,7 @@ func (s rsyncStorageSourceDriver) Snapshots() []container { } func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *operation, bwlimit string) error { + ctName := s.container.Name() for _, send := range s.snapshots { ourStart, err := send.StorageStart() if err != nil { @@ -52,19 +53,20 @@ func (s rsyncStorageSourceDriver) SendWhileRunning(conn *websocket.Conn, op *ope path := send.Path() wrapper := StorageProgressReader(op, "fs_progress", send.Name()) - err = RsyncSend(shared.AddSlash(path), conn, wrapper, bwlimit) + err = RsyncSend(ctName, shared.AddSlash(path), conn, wrapper, bwlimit) if err != nil { return err } } wrapper := StorageProgressReader(op, "fs_progress", s.container.Name()) - return RsyncSend(shared.AddSlash(s.container.Path()), conn, wrapper, bwlimit) + return RsyncSend(ctName, shared.AddSlash(s.container.Path()), conn, wrapper, bwlimit) } func (s rsyncStorageSourceDriver) SendAfterCheckpoint(conn *websocket.Conn, bwlimit string) error { + ctName := s.container.Name() // resync anything that changed between our first send and the checkpoint - return RsyncSend(shared.AddSlash(s.container.Path()), conn, nil, bwlimit) + return RsyncSend(ctName, shared.AddSlash(s.container.Path()), conn, nil, bwlimit) } func (s rsyncStorageSourceDriver) Cleanup() {
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel