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

Reply via email to