The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3486

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) ===

From 5134b57faa22827e4272c96e08dbaec5a9124b2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Mon, 3 Jul 2017 01:25:39 -0400
Subject: [PATCH 1/6] client: Don't live migrate stopped containers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <[email protected]>
---
 client/lxd_containers.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index 24a7f2d11..0e102d213 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -203,7 +203,6 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, 
container api.Contai
                ContainerPut: container.Writable(),
        }
        req.Source.BaseImage = container.Config["volatile.base_image"]
-       req.Source.Live = container.StatusCode == api.Running
 
        // Process the copy arguments
        if args != nil {
@@ -221,6 +220,10 @@ func (r *ProtocolLXD) CopyContainer(source 
ContainerServer, container api.Contai
                req.Source.ContainerOnly = args.ContainerOnly
        }
 
+       if req.Source.Live {
+               req.Source.Live = container.StatusCode == api.Running
+       }
+
        // Optimization for the local copy case
        if r == source {
                // Local copy source fields

From 665f9013f70ae99a92c6c8c8bd08892b5dfd6cbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Sun, 2 Jul 2017 20:42:33 -0400
Subject: [PATCH 2/6] Implement complete push migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <[email protected]>
---
 doc/api-extensions.md            |  4 +++
 lxd/api_1.0.go                   |  1 +
 lxd/container_post.go            | 16 +++++++++++
 lxd/container_snapshot.go        | 34 +++++++++++++++++++++-
 lxd/migrate.go                   | 61 ++++++++++++++++++++++++++++++++++++++++
 shared/api/container.go          | 12 ++++++++
 shared/api/container_snapshot.go |  5 ++--
 7 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 4590b3eab..bc3dd2d61 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -288,3 +288,7 @@ uid/gid to use as the base.
 ## file\_symlinks
 This adds support for transfering symlinks through the file API.
 X-LXD-type can now be "symlink" with the request content being the target path.
+
+## container\_push\_target
+This adds the "target" field to POST /1.0/containers/NAME which can be
+used to have the source LXD host connect to the target during migration.
diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index 0c0ad691b..46f7b5459 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -111,6 +111,7 @@ func api10Get(d *Daemon, r *http.Request) Response {
                        "storage_lvm_lv_resizing",
                        "id_map_base",
                        "file_symlinks",
+                       "container_push_target",
                },
                APIStatus:  "stable",
                APIVersion: version.APIVersion,
diff --git a/lxd/container_post.go b/lxd/container_post.go
index ca884e3cd..69a697824 100644
--- a/lxd/container_post.go
+++ b/lxd/container_post.go
@@ -55,6 +55,22 @@ func containerPost(d *Daemon, r *http.Request) Response {
                resources := map[string][]string{}
                resources["containers"] = []string{name}
 
+               if req.Target != nil {
+                       // Push mode
+                       err := ws.ConnectTarget(*req.Target)
+                       if err != nil {
+                               return InternalError(err)
+                       }
+
+                       op, err := operationCreate(operationClassTask, 
resources, nil, ws.Do, nil, nil)
+                       if err != nil {
+                               return InternalError(err)
+                       }
+
+                       return OperationResponse(op)
+               }
+
+               // Pull mode
                op, err := operationCreate(operationClassWebsocket, resources, 
ws.Metadata(), ws.Do, nil, ws.Connect)
                if err != nil {
                        return InternalError(err)
diff --git a/lxd/container_snapshot.go b/lxd/container_snapshot.go
index a4d2ace26..359d6c4cd 100644
--- a/lxd/container_snapshot.go
+++ b/lxd/container_snapshot.go
@@ -1,8 +1,10 @@
 package main
 
 import (
+       "bytes"
        "encoding/json"
        "fmt"
+       "io/ioutil"
        "net/http"
        "strconv"
 
@@ -196,13 +198,27 @@ func snapshotGet(sc container, name string) Response {
 }
 
 func snapshotPost(d *Daemon, r *http.Request, sc container, containerName 
string) Response {
+       body, err := ioutil.ReadAll(r.Body)
+       if err != nil {
+               return InternalError(err)
+       }
+
+       rdr1 := ioutil.NopCloser(bytes.NewBuffer(body))
+       rdr2 := ioutil.NopCloser(bytes.NewBuffer(body))
+
        raw := shared.Jmap{}
-       if err := json.NewDecoder(r.Body).Decode(&raw); err != nil {
+       if err := json.NewDecoder(rdr1).Decode(&raw); err != nil {
                return BadRequest(err)
        }
 
        migration, err := raw.GetBool("migration")
        if err == nil && migration {
+               req := api.ContainerPost{}
+               err = json.NewDecoder(rdr2).Decode(&req)
+               if err != nil {
+                       return BadRequest(err)
+               }
+
                ws, err := NewMigrationSource(sc, false, true)
                if err != nil {
                        return SmartError(err)
@@ -211,6 +227,22 @@ func snapshotPost(d *Daemon, r *http.Request, sc 
container, containerName string
                resources := map[string][]string{}
                resources["containers"] = []string{containerName}
 
+               if req.Target != nil {
+                       // Push mode
+                       err := ws.ConnectTarget(*req.Target)
+                       if err != nil {
+                               return InternalError(err)
+                       }
+
+                       op, err := operationCreate(operationClassTask, 
resources, nil, ws.Do, nil, nil)
+                       if err != nil {
+                               return InternalError(err)
+                       }
+
+                       return OperationResponse(op)
+               }
+
+               // Pull mode
                op, err := operationCreate(operationClassWebsocket, resources, 
ws.Metadata(), ws.Do, nil, ws.Connect)
                if err != nil {
                        return InternalError(err)
diff --git a/lxd/migrate.go b/lxd/migrate.go
index 244ee1d73..16bcc6fa3 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -6,6 +6,8 @@
 package main
 
 import (
+       "crypto/x509"
+       "encoding/pem"
        "fmt"
        "io/ioutil"
        "net/http"
@@ -21,6 +23,7 @@ import (
        "gopkg.in/lxc/go-lxc.v2"
 
        "github.com/lxc/lxd/shared"
+       "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
 )
 
@@ -234,6 +237,64 @@ func (s *migrationSourceWs) Connect(op *operation, r 
*http.Request, w http.Respo
        return nil
 }
 
+func (s *migrationSourceWs) ConnectTarget(target api.ContainerPostTarget) 
error {
+       var err error
+       var cert *x509.Certificate
+
+       if target.Certificate != "" {
+               certBlock, _ := pem.Decode([]byte(target.Certificate))
+               if certBlock == nil {
+                       return fmt.Errorf("Invalid certificate")
+               }
+
+               cert, err = x509.ParseCertificate(certBlock.Bytes)
+               if err != nil {
+                       return err
+               }
+       }
+
+       config, err := shared.GetTLSConfig("", "", "", cert)
+       if err != nil {
+               return err
+       }
+
+       dialer := websocket.Dialer{
+               TLSClientConfig: config,
+               NetDial:         shared.RFC3493Dialer,
+       }
+
+       for name, secret := range target.Websockets {
+               var conn **websocket.Conn
+
+               switch name {
+               case "control":
+                       conn = &s.controlConn
+               case "fs":
+                       conn = &s.fsConn
+               case "criu":
+                       conn = &s.criuConn
+               default:
+                       return fmt.Errorf("Unknown secret provided: %s", name)
+               }
+
+               query := url.Values{"secret": []string{secret}}
+
+               // The URL is a https URL to the operation, mangle to be a wss 
URL to the secret
+               wsUrl := fmt.Sprintf("wss://%s/websocket?%s", 
strings.TrimPrefix(target.Operation, "https://";), query.Encode())
+
+               wsConn, _, err := dialer.Dial(wsUrl, http.Header{})
+               if err != nil {
+                       return err
+               }
+
+               *conn = wsConn
+       }
+
+       s.allConnected <- true
+
+       return nil
+}
+
 func writeActionScript(directory string, operation string, secret string) 
error {
        script := fmt.Sprintf(`#!/bin/sh -e
 if [ "$CRTOOLS_SCRIPT_ACTION" = "post-dump" ]; then
diff --git a/shared/api/container.go b/shared/api/container.go
index a300a0731..58cac56cf 100644
--- a/shared/api/container.go
+++ b/shared/api/container.go
@@ -25,6 +25,18 @@ type ContainerPost struct {
 
        // API extension: container_only_migration
        ContainerOnly bool `json:"container_only" yaml:"container_only"`
+
+       // API extension: container_push_target
+       Target *ContainerPostTarget `json:"target" yaml:"target"`
+}
+
+// ContainerPostTarget represents the migration target host and operation
+//
+// API extension: container_push_target
+type ContainerPostTarget struct {
+       Certificate string            `json:"certificate" yaml:"certificate"`
+       Operation   string            `json:"operation,omitempty" 
yaml:"operation,omitempty"`
+       Websockets  map[string]string `json:"secrets,omitempty" 
yaml:"secrets,omitempty"`
 }
 
 // ContainerPut represents the modifiable fields of a LXD container
diff --git a/shared/api/container_snapshot.go b/shared/api/container_snapshot.go
index 17e5d3a8d..3f9b0fd6c 100644
--- a/shared/api/container_snapshot.go
+++ b/shared/api/container_snapshot.go
@@ -12,8 +12,9 @@ type ContainerSnapshotsPost struct {
 
 // ContainerSnapshotPost represents the fields required to rename/move a LXD 
container snapshot
 type ContainerSnapshotPost struct {
-       Name      string `json:"name" yaml:"name"`
-       Migration bool   `json:"migration" yaml:"migration"`
+       Name      string               `json:"name" yaml:"name"`
+       Migration bool                 `json:"migration" yaml:"migration"`
+       Target    *ContainerPostTarget `json:"target" yaml:"target"`
 }
 
 // ContainerSnapshot represents a LXD conainer snapshot

From e4bd65bbff29675a8e0e24c623c7038ab89e0bbe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Sun, 2 Jul 2017 01:57:01 -0400
Subject: [PATCH 3/6] client: Implement push and relay container copy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <[email protected]>
---
 client/interfaces.go     |   6 +
 client/lxd_containers.go | 359 ++++++++++++++++++++++++++++++++++++++++++++---
 shared/network.go        |  54 +++++++
 3 files changed, 403 insertions(+), 16 deletions(-)

diff --git a/client/interfaces.go b/client/interfaces.go
index 410c4f726..d146c1ddf 100644
--- a/client/interfaces.go
+++ b/client/interfaces.go
@@ -240,12 +240,18 @@ type ContainerCopyArgs struct {
 
        // If set, only the container will copied, its snapshots won't
        ContainerOnly bool
+
+       // The transfer mode, can be "pull" (default), "push" or "relay"
+       Mode string
 }
 
 // The ContainerSnapshotCopyArgs struct is used to pass additional options 
during container copy
 type ContainerSnapshotCopyArgs struct {
        // If set, the container will be renamed on copy
        Name string
+
+       // The transfer mode, can be "pull" (default), "push" or "relay"
+       Mode string
 }
 
 // The ContainerExecArgs struct is used to pass additional options during 
container exec
diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index 0e102d213..1cc305cf9 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -207,8 +207,28 @@ func (r *ProtocolLXD) CopyContainer(source 
ContainerServer, container api.Contai
        // Process the copy arguments
        if args != nil {
                // Sanity checks
-               if args.ContainerOnly && 
!r.HasExtension("container_only_migration") {
-                       return nil, fmt.Errorf("The server is missing the 
required \"container_only_migration\" API extension")
+               if args.ContainerOnly {
+                       if !r.HasExtension("container_only_migration") {
+                               return nil, fmt.Errorf("The target server is 
missing the required \"container_only_migration\" API extension")
+                       }
+
+                       if !source.HasExtension("container_only_migration") {
+                               return nil, fmt.Errorf("The source server is 
missing the required \"container_only_migration\" API extension")
+                       }
+               }
+
+               if shared.StringInSlice(args.Mode, []string{"push", "relay"}) {
+                       if !r.HasExtension("container_push") {
+                               return nil, fmt.Errorf("The target server is 
missing the required \"container_push\" API extension")
+                       }
+
+                       if !source.HasExtension("container_push") {
+                               return nil, fmt.Errorf("The source server is 
missing the required \"container_push\" API extension")
+                       }
+               }
+
+               if args.Mode == "push" && 
!source.HasExtension("container_push_target") {
+                       return nil, fmt.Errorf("The source server is missing 
the required \"container_push_target\" API extension")
                }
 
                // Allow overriding the target name
@@ -250,19 +270,51 @@ func (r *ProtocolLXD) CopyContainer(source 
ContainerServer, container api.Contai
                return &rop, nil
        }
 
-       // Get source server connection information
-       info, err := source.GetConnectionInfo()
-       if err != nil {
-               return nil, err
-       }
-
-       // Get a source operation
+       // Source request
        sourceReq := api.ContainerPost{
                Migration:     true,
                Live:          req.Source.Live,
                ContainerOnly: req.Source.ContainerOnly,
        }
 
+       // Push mode migration
+       if args != nil && args.Mode == "push" {
+               // Get target server connection information
+               info, err := r.GetConnectionInfo()
+               if err != nil {
+                       return nil, err
+               }
+
+               // Create the container
+               req.Source.Type = "migration"
+               req.Source.Mode = "push"
+
+               op, err := r.CreateContainer(req)
+               if err != nil {
+                       return nil, err
+               }
+
+               targetSecrets := map[string]string{}
+               for k, v := range op.Metadata {
+                       targetSecrets[k] = v.(string)
+               }
+
+               // Prepare the source request
+               target := api.ContainerPostTarget{}
+               target.Operation = op.ID
+               target.Websockets = targetSecrets
+               target.Certificate = info.Certificate
+               sourceReq.Target = &target
+
+               return r.tryMigrateContainer(source, container.Name, sourceReq, 
info.Addresses)
+       }
+
+       // Get source server connection information
+       info, err := source.GetConnectionInfo()
+       if err != nil {
+               return nil, err
+       }
+
        op, err := source.MigrateContainer(container.Name, sourceReq)
        if err != nil {
                return nil, err
@@ -273,7 +325,71 @@ func (r *ProtocolLXD) CopyContainer(source 
ContainerServer, container api.Contai
                sourceSecrets[k] = v.(string)
        }
 
-       // Migration source fields
+       // Relay mode migration
+       if args != nil && args.Mode == "relay" {
+               // Push copy source fields
+               req.Source.Type = "migration"
+               req.Source.Mode = "push"
+
+               // Start the process
+               targetOp, err := r.CreateContainer(req)
+               if err != nil {
+                       return nil, err
+               }
+
+               // Extract the websockets
+               targetSecrets := map[string]string{}
+               for k, v := range targetOp.Metadata {
+                       targetSecrets[k] = v.(string)
+               }
+
+               // Launch the relay
+               dones := []chan bool{}
+               conns := []*websocket.Conn{}
+
+               for name := range sourceSecrets {
+                       sourceConn, err := source.GetOperationWebsocket(op.ID, 
sourceSecrets[name])
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       targetConn, err := r.GetOperationWebsocket(targetOp.ID, 
targetSecrets[name])
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       conns = append(conns, sourceConn)
+                       conns = append(conns, targetConn)
+                       dones = append(dones, shared.WebsocketProxy(sourceConn, 
targetConn))
+               }
+
+               // Wait for everything to be done
+               go func() {
+                       for _, chDone := range dones {
+                               <-chDone
+                       }
+
+                       for _, conn := range conns {
+                               conn.Close()
+                       }
+               }()
+
+               // Prepare a tracking operation
+               rop := RemoteOperation{
+                       targetOp: targetOp,
+                       chDone:   make(chan bool),
+               }
+
+               // Forward targetOp to remote op
+               go func() {
+                       rop.err = rop.targetOp.Wait()
+                       close(rop.chDone)
+               }()
+
+               return &rop, nil
+       }
+
+       // Pull mode migration
        req.Source.Type = "migration"
        req.Source.Mode = "pull"
        req.Source.Operation = op.ID
@@ -310,6 +426,56 @@ func (r *ProtocolLXD) RenameContainer(name string, 
container api.ContainerPost)
        return op, nil
 }
 
+func (r *ProtocolLXD) tryMigrateContainer(source ContainerServer, name string, 
req api.ContainerPost, urls []string) (*RemoteOperation, error) {
+       if len(urls) == 0 {
+               return nil, fmt.Errorf("The target server isn't listening on 
the network")
+       }
+
+       rop := RemoteOperation{
+               chDone: make(chan bool),
+       }
+
+       operation := req.Target.Operation
+
+       // Forward targetOp to remote op
+       go func() {
+               success := false
+               errors := []string{}
+               for _, serverURL := range urls {
+                       req.Target.Operation = 
fmt.Sprintf("%s/1.0/operations/%s", serverURL, operation)
+
+                       op, err := source.MigrateContainer(name, req)
+                       if err != nil {
+                               errors = append(errors, fmt.Sprintf("%s: %v", 
serverURL, err))
+                               continue
+                       }
+
+                       rop.targetOp = op
+
+                       for _, handler := range rop.handlers {
+                               rop.targetOp.AddHandler(handler)
+                       }
+
+                       err = rop.targetOp.Wait()
+                       if err != nil {
+                               errors = append(errors, fmt.Sprintf("%s: %v", 
serverURL, err))
+                               continue
+                       }
+
+                       success = true
+                       break
+               }
+
+               if !success {
+                       rop.err = fmt.Errorf("Failed container migration:\n - 
%s", strings.Join(errors, "\n - "))
+               }
+
+               close(rop.chDone)
+       }()
+
+       return &rop, nil
+}
+
 // MigrateContainer requests that LXD prepares for a container migration
 func (r *ProtocolLXD) MigrateContainer(name string, container 
api.ContainerPost) (*Operation, error) {
        if container.ContainerOnly {
@@ -695,6 +861,21 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source 
ContainerServer, snapshot api
 
        // Process the copy arguments
        if args != nil {
+               // Sanity checks
+               if shared.StringInSlice(args.Mode, []string{"push", "relay"}) {
+                       if !r.HasExtension("container_push") {
+                               return nil, fmt.Errorf("The target server is 
missing the required \"container_push\" API extension")
+                       }
+
+                       if !source.HasExtension("container_push") {
+                               return nil, fmt.Errorf("The source server is 
missing the required \"container_push\" API extension")
+                       }
+               }
+
+               if args.Mode == "push" && 
!source.HasExtension("container_push_target") {
+                       return nil, fmt.Errorf("The source server is missing 
the required \"container_push_target\" API extension")
+               }
+
                // Allow overriding the target name
                if args.Name != "" {
                        req.Name = args.Name
@@ -727,17 +908,49 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source 
ContainerServer, snapshot api
                return &rop, nil
        }
 
+       // Source request
+       sourceReq := api.ContainerSnapshotPost{
+               Migration: true,
+       }
+
+       // Push mode migration
+       if args != nil && args.Mode == "push" {
+               // Get target server connection information
+               info, err := r.GetConnectionInfo()
+               if err != nil {
+                       return nil, err
+               }
+
+               // Create the container
+               req.Source.Type = "migration"
+               req.Source.Mode = "push"
+
+               op, err := r.CreateContainer(req)
+               if err != nil {
+                       return nil, err
+               }
+
+               targetSecrets := map[string]string{}
+               for k, v := range op.Metadata {
+                       targetSecrets[k] = v.(string)
+               }
+
+               // Prepare the source request
+               target := api.ContainerPostTarget{}
+               target.Operation = op.ID
+               target.Websockets = targetSecrets
+               target.Certificate = info.Certificate
+               sourceReq.Target = &target
+
+               return r.tryMigrateContainerSnapshot(source, cName, sName, 
sourceReq, info.Addresses)
+       }
+
        // Get source server connection information
        info, err := source.GetConnectionInfo()
        if err != nil {
                return nil, err
        }
 
-       // Get a source operation
-       sourceReq := api.ContainerSnapshotPost{
-               Migration: true,
-       }
-
        op, err := source.MigrateContainerSnapshot(cName, sName, sourceReq)
        if err != nil {
                return nil, err
@@ -748,7 +961,71 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source 
ContainerServer, snapshot api
                sourceSecrets[k] = v.(string)
        }
 
-       // Migration source fields
+       // Relay mode migration
+       if args != nil && args.Mode == "relay" {
+               // Push copy source fields
+               req.Source.Type = "migration"
+               req.Source.Mode = "push"
+
+               // Start the process
+               targetOp, err := r.CreateContainer(req)
+               if err != nil {
+                       return nil, err
+               }
+
+               // Extract the websockets
+               targetSecrets := map[string]string{}
+               for k, v := range targetOp.Metadata {
+                       targetSecrets[k] = v.(string)
+               }
+
+               // Launch the relay
+               dones := []chan bool{}
+               conns := []*websocket.Conn{}
+
+               for name := range sourceSecrets {
+                       sourceConn, err := source.GetOperationWebsocket(op.ID, 
sourceSecrets[name])
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       targetConn, err := r.GetOperationWebsocket(targetOp.ID, 
targetSecrets[name])
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       conns = append(conns, sourceConn)
+                       conns = append(conns, targetConn)
+                       dones = append(dones, shared.WebsocketProxy(sourceConn, 
targetConn))
+               }
+
+               // Wait for everything to be done
+               go func() {
+                       for _, chDone := range dones {
+                               <-chDone
+                       }
+
+                       for _, conn := range conns {
+                               conn.Close()
+                       }
+               }()
+
+               // Prepare a tracking operation
+               rop := RemoteOperation{
+                       targetOp: targetOp,
+                       chDone:   make(chan bool),
+               }
+
+               // Forward targetOp to remote op
+               go func() {
+                       rop.err = rop.targetOp.Wait()
+                       close(rop.chDone)
+               }()
+
+               return &rop, nil
+       }
+
+       // Pull mode migration
        req.Source.Type = "migration"
        req.Source.Mode = "pull"
        req.Source.Operation = op.ID
@@ -774,6 +1051,56 @@ func (r *ProtocolLXD) 
RenameContainerSnapshot(containerName string, name string,
        return op, nil
 }
 
+func (r *ProtocolLXD) tryMigrateContainerSnapshot(source ContainerServer, 
containerName string, name string, req api.ContainerSnapshotPost, urls 
[]string) (*RemoteOperation, error) {
+       if len(urls) == 0 {
+               return nil, fmt.Errorf("The target server isn't listening on 
the network")
+       }
+
+       rop := RemoteOperation{
+               chDone: make(chan bool),
+       }
+
+       operation := req.Target.Operation
+
+       // Forward targetOp to remote op
+       go func() {
+               success := false
+               errors := []string{}
+               for _, serverURL := range urls {
+                       req.Target.Operation = 
fmt.Sprintf("%s/1.0/operations/%s", serverURL, operation)
+
+                       op, err := 
source.MigrateContainerSnapshot(containerName, name, req)
+                       if err != nil {
+                               errors = append(errors, fmt.Sprintf("%s: %v", 
serverURL, err))
+                               continue
+                       }
+
+                       rop.targetOp = op
+
+                       for _, handler := range rop.handlers {
+                               rop.targetOp.AddHandler(handler)
+                       }
+
+                       err = rop.targetOp.Wait()
+                       if err != nil {
+                               errors = append(errors, fmt.Sprintf("%s: %v", 
serverURL, err))
+                               continue
+                       }
+
+                       success = true
+                       break
+               }
+
+               if !success {
+                       rop.err = fmt.Errorf("Failed container migration:\n - 
%s", strings.Join(errors, "\n - "))
+               }
+
+               close(rop.chDone)
+       }()
+
+       return &rop, nil
+}
+
 // MigrateContainerSnapshot requests that LXD prepares for a snapshot migration
 func (r *ProtocolLXD) MigrateContainerSnapshot(containerName string, name 
string, container api.ContainerSnapshotPost) (*Operation, error) {
        // Sanity check
diff --git a/shared/network.go b/shared/network.go
index 51f1d796a..4cf7af81b 100644
--- a/shared/network.go
+++ b/shared/network.go
@@ -230,6 +230,60 @@ func WebsocketRecvStream(w io.Writer, conn 
*websocket.Conn) chan bool {
        return ch
 }
 
+func WebsocketProxy(source *websocket.Conn, target *websocket.Conn) chan bool {
+       forward := func(in *websocket.Conn, out *websocket.Conn, ch chan bool) {
+               for {
+                       mt, r, err := in.NextReader()
+                       if mt == websocket.CloseMessage {
+                               logger.Debugf("Got close message for reader")
+                               break
+                       }
+
+                       if mt == websocket.TextMessage {
+                               logger.Debugf("got message barrier")
+                               break
+                       }
+
+                       if err != nil {
+                               logger.Debugf("Got error getting next reader 
%s", err)
+                               break
+                       }
+
+                       w, err := out.NextWriter(websocket.BinaryMessage)
+                       if err != nil {
+                               logger.Debugf("Got error getting next writer 
%s", err)
+                               break
+                       }
+
+                       _, err = io.Copy(w, r)
+                       w.Close()
+                       if err != nil {
+                               logger.Debugf("Got err writing %s", err)
+                               break
+                       }
+               }
+               out.WriteMessage(websocket.TextMessage, []byte{})
+
+               ch <- true
+       }
+
+       chSend := make(chan bool)
+       go forward(source, target, chSend)
+
+       chRecv := make(chan bool)
+       go forward(target, source, chRecv)
+
+       ch := make(chan bool)
+       go func() {
+               <-chSend
+               <-chRecv
+
+               ch <- true
+       }()
+
+       return ch
+}
+
 func defaultReader(conn *websocket.Conn, r io.ReadCloser, readDone chan<- 
bool) {
        /* For now, we don't need to adjust buffer sizes in
        * WebsocketMirror, since it's used for interactive things like

From cb33006b3f23c54b93a605ec8821e11613432882 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Sun, 2 Jul 2017 19:32:40 -0400
Subject: [PATCH 4/6] lxc/copy: Make transfer mode configurable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #553

Signed-off-by: Stéphane Graber <[email protected]>
---
 lxc/copy.go | 16 +++++++++++++---
 lxc/move.go | 10 +++++++++-
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/lxc/copy.go b/lxc/copy.go
index f5388051b..befcfc15a 100644
--- a/lxc/copy.go
+++ b/lxc/copy.go
@@ -16,6 +16,7 @@ type copyCmd struct {
        confArgs      configList
        ephem         bool
        containerOnly bool
+       mode          string
 }
 
 func (c *copyCmd) showByDefault() bool {
@@ -36,10 +37,11 @@ func (c *copyCmd) flags() {
        gnuflag.Var(&c.profArgs, "p", i18n.G("Profile to apply to the new 
container"))
        gnuflag.BoolVar(&c.ephem, "ephemeral", false, i18n.G("Ephemeral 
container"))
        gnuflag.BoolVar(&c.ephem, "e", false, i18n.G("Ephemeral container"))
+       gnuflag.StringVar(&c.mode, "mode", "pull", i18n.G("Transfer mode. One 
of pull (default), push or relay."))
        gnuflag.BoolVar(&c.containerOnly, "container-only", false, i18n.G("Copy 
the container without its snapshots"))
 }
 
-func (c *copyCmd) copyContainer(conf *config.Config, sourceResource string, 
destResource string, keepVolatile bool, ephemeral int, stateful bool, 
containerOnly bool) error {
+func (c *copyCmd) copyContainer(conf *config.Config, sourceResource string, 
destResource string, keepVolatile bool, ephemeral int, stateful bool, 
containerOnly bool, mode string) error {
        // Parse the source
        sourceRemote, sourceName, err := conf.ParseRemote(sourceResource)
        if err != nil {
@@ -86,6 +88,7 @@ func (c *copyCmd) copyContainer(conf *config.Config, 
sourceResource string, dest
                // Prepare the container creation request
                args := lxd.ContainerSnapshotCopyArgs{
                        Name: destName,
+                       Mode: mode,
                }
 
                // Copy of a snapshot into a new container
@@ -138,6 +141,7 @@ func (c *copyCmd) copyContainer(conf *config.Config, 
sourceResource string, dest
                        Name:          destName,
                        Live:          stateful,
                        ContainerOnly: containerOnly,
+                       Mode:          mode,
                }
 
                // Copy of a container into a new container
@@ -235,11 +239,17 @@ func (c *copyCmd) run(conf *config.Config, args []string) 
error {
                ephem = 1
        }
 
+       // Parse the mode
+       mode := "pull"
+       if c.mode != "" {
+               mode = c.mode
+       }
+
        // If not target name is specified, one will be chosed by the server
        if len(args) < 2 {
-               return c.copyContainer(conf, args[0], "", false, ephem, false, 
c.containerOnly)
+               return c.copyContainer(conf, args[0], "", false, ephem, false, 
c.containerOnly, mode)
        }
 
        // Normal copy with a pre-determined name
-       return c.copyContainer(conf, args[0], args[1], false, ephem, false, 
c.containerOnly)
+       return c.copyContainer(conf, args[0], args[1], false, ephem, false, 
c.containerOnly, mode)
 }
diff --git a/lxc/move.go b/lxc/move.go
index 9fcb3d229..6d867070d 100644
--- a/lxc/move.go
+++ b/lxc/move.go
@@ -12,6 +12,7 @@ import (
 
 type moveCmd struct {
        containerOnly bool
+       mode          string
 }
 
 func (c *moveCmd) showByDefault() bool {
@@ -36,6 +37,7 @@ lxc move <container>/<old snapshot name> <container>/<new 
snapshot name>
 
 func (c *moveCmd) flags() {
        gnuflag.BoolVar(&c.containerOnly, "container-only", false, i18n.G("Move 
the container without its snapshots"))
+       gnuflag.StringVar(&c.mode, "mode", "pull", i18n.G("Transfer mode. One 
of pull (default), push or relay."))
 }
 
 func (c *moveCmd) run(conf *config.Config, args []string) error {
@@ -43,6 +45,12 @@ func (c *moveCmd) run(conf *config.Config, args []string) 
error {
                return errArgs
        }
 
+       // Parse the mode
+       mode := "pull"
+       if c.mode != "" {
+               mode = c.mode
+       }
+
        sourceRemote, sourceName, err := conf.ParseRemote(args[0])
        if err != nil {
                return err
@@ -90,7 +98,7 @@ func (c *moveCmd) run(conf *config.Config, args []string) 
error {
 
        // A move is just a copy followed by a delete; however, we want to
        // keep the volatile entries around since we are moving the container.
-       err = cpy.copyContainer(conf, args[0], args[1], true, -1, true, 
c.containerOnly)
+       err = cpy.copyContainer(conf, args[0], args[1], true, -1, true, 
c.containerOnly, mode)
        if err != nil {
                return err
        }

From 9e10964fabad07c7a2bd28efaef745734925d087 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Mon, 3 Jul 2017 01:27:20 -0400
Subject: [PATCH 5/6] tests: Add test for push and relay mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <[email protected]>
---
 test/suites/migration.sh | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/test/suites/migration.sh b/test/suites/migration.sh
index 6a75cf4ec..afd1859cb 100644
--- a/test/suites/migration.sh
+++ b/test/suites/migration.sh
@@ -85,7 +85,7 @@ migration() {
     [ -d "${lxd2_dir}/snapshots/nonlive/snap0/rootfs/bin" ]
   fi
 
-  lxc_remote copy l2:nonlive l1:nonlive2
+  lxc_remote copy l2:nonlive l1:nonlive2 --mode=push
   # This line exists so that the container's storage volume is mounted when we
   # perform existence check for various files.
   lxc_remote start l2:nonlive
@@ -100,7 +100,7 @@ migration() {
     [ -d "${LXD_DIR}/snapshots/nonlive2/snap0/rootfs/bin" ]
   fi
 
-  lxc_remote copy l1:nonlive2/snap0 l2:nonlive3
+  lxc_remote copy l1:nonlive2/snap0 l2:nonlive3 --mode=relay
   # FIXME: make this backend agnostic
   if [ "$lxd2_backend" != "lvm" ]; then
     [ -d "${lxd2_dir}/containers/nonlive3/rootfs/bin" ]
@@ -108,7 +108,7 @@ migration() {
   lxc_remote delete l2:nonlive3 --force
 
   lxc_remote stop l2:nonlive
-  lxc_remote copy l2:nonlive l2:nonlive2
+  lxc_remote copy l2:nonlive l2:nonlive2 --mode=push
   # should have the same base image tag
   [ "$(lxc_remote config get l2:nonlive volatile.base_image)" = "$(lxc_remote 
config get l2:nonlive2 volatile.base_image)" ]
   # check that nonlive2 has a new addr in volatile
@@ -158,7 +158,8 @@ migration() {
   lxc_remote delete l2:udssr
 
   # Remote container only move.
-  lxc_remote move l1:cccp l2:udssr --container-only
+  lxc_remote list l1:cccp
+  lxc_remote move l1:cccp l2:udssr --container-only --mode=relay
   ! lxc_remote info l1:cccp
   [ "$(lxc_remote info l2:udssr | grep -c snap)" -eq 0 ]
   lxc_remote delete l2:udssr
@@ -168,7 +169,7 @@ migration() {
   lxc_remote snapshot l1:cccp
 
   # Remote container with snapshots move.
-  lxc_remote move l1:cccp l2:udssr
+  lxc_remote move l1:cccp l2:udssr --mode=push
   ! lxc_remote info l1:cccp
   [ "$(lxc_remote info l2:udssr | grep -c snap)" -eq 2 ]
   lxc_remote delete l2:udssr
@@ -179,7 +180,7 @@ migration() {
   lxc snapshot cccp
 
   # Local container with snapshots move.
-  lxc move cccp udssr
+  lxc move cccp udssr --mode=pull
   ! lxc info cccp
   [ "$(lxc info udssr | grep -c snap)" -eq 2 ]
   lxc delete udssr

From edc99c229e475e2f7edd2a15bb7ef822fe18f871 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <[email protected]>
Date: Mon, 3 Jul 2017 01:12:12 -0400
Subject: [PATCH 6/6] i18n: Update templates
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <[email protected]>
---
 po/de.po   | 28 ++++++++++++++++------------
 po/el.po   | 28 ++++++++++++++++------------
 po/fr.po   | 28 ++++++++++++++++------------
 po/it.po   | 28 ++++++++++++++++------------
 po/ja.po   | 28 ++++++++++++++++------------
 po/lxd.pot | 28 ++++++++++++++++------------
 po/nl.po   | 28 ++++++++++++++++------------
 po/ru.po   | 28 ++++++++++++++++------------
 po/sr.po   | 28 ++++++++++++++++------------
 po/sv.po   | 28 ++++++++++++++++------------
 po/tr.po   | 28 ++++++++++++++++------------
 11 files changed, 176 insertions(+), 132 deletions(-)

diff --git a/po/de.po b/po/de.po
index d5f1a1714..50bdb872e 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: LXD\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-02-14 17:11+0000\n"
 "Last-Translator: Tim Rose <[email protected]>\n"
 "Language-Team: German <https://hosted.weblate.org/projects/linux-containers/";
@@ -347,7 +347,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 #, fuzzy
 msgid "Config key/value to apply to the new container"
 msgstr "kann nicht zum selben Container Namen kopieren"
@@ -366,7 +366,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -380,7 +380,7 @@ msgstr "Abbild mit Fingerabdruck %s importiert\n"
 msgid "Copy aliases from source"
 msgstr "Kopiere Aliasse von der Quelle"
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 #, fuzzy
 msgid "Copy the container without its snapshots"
 msgstr "Herunterfahren des Containers erzwingen."
@@ -480,7 +480,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr "Flüchtiger Container"
 
@@ -516,7 +516,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 #, fuzzy
 msgid "Failed to get the new container name"
 msgstr "kann nicht zum selben Container Namen kopieren"
@@ -703,7 +703,7 @@ msgid "More than one file to download, but target is not a 
directory"
 msgstr ""
 "Mehr als eine Datei herunterzuladen, aber das Ziel ist kein Verzeichnis"
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 #, fuzzy
 msgid "Move the container without its snapshots"
 msgstr "Herunterfahren des Containers erzwingen."
@@ -890,7 +890,7 @@ msgstr "Profil %s gelöscht\n"
 msgid "Profile %s removed from %s"
 msgstr "Gerät %s wurde von %s entfernt\n"
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 #, fuzzy
 msgid "Profile to apply to the new container"
 msgstr "kann nicht zum selben Container Namen kopieren"
@@ -1201,7 +1201,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, fuzzy, c-format
 msgid "Transfering container: %s"
 msgstr "kann nicht zum selben Container Namen kopieren"
@@ -1382,7 +1386,7 @@ msgstr ""
 "Um das Server Passwort zur authentifizierung zu setzen:\n"
 "\tlxc config set core.trust_password blah\n"
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 #, fuzzy
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
@@ -1777,7 +1781,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 #, fuzzy
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
@@ -2192,7 +2196,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr "kann nicht zum selben Container Namen kopieren"
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 #, fuzzy
 msgid "You must specify a source container name"
 msgstr "der Name des Ursprung Containers muss angegeben werden"
diff --git a/po/el.po b/po/el.po
index 221369446..00845b4c0 100644
--- a/po/el.po
+++ b/po/el.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-02-14 08:00+0000\n"
 "Last-Translator: Simos Xenitellis <[email protected]>\n"
 "Language-Team: Greek <https://hosted.weblate.org/projects/linux-containers/";
@@ -259,7 +259,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -277,7 +277,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -291,7 +291,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -387,7 +387,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -423,7 +423,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -604,7 +604,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -783,7 +783,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1079,7 +1079,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1221,7 +1225,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1555,7 +1559,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1908,7 +1912,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
diff --git a/po/fr.po b/po/fr.po
index dc131c398..17426e804 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: LXD\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-06-07 15:24+0000\n"
 "Last-Translator: Stéphane Graber <[email protected]>\n"
 "Language-Team: French <https://hosted.weblate.org/projects/linux-containers/";
@@ -339,7 +339,7 @@ msgstr "Colonnes"
 msgid "Commands:"
 msgstr "Commandes:"
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr "Clé/valeur de configuration à appliquer au nouveau conteneur"
 
@@ -357,7 +357,7 @@ msgstr "Connexion refusée ; LXD est-il actif ?"
 msgid "Container name is mandatory"
 msgstr "Le nom du conteneur est obligatoire"
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr "Le nom du conteneur est : %s"
@@ -371,7 +371,7 @@ msgstr "Conteneur publié avec l'empreinte : %s"
 msgid "Copy aliases from source"
 msgstr "Copier les alias depuis la source"
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 #, fuzzy
 msgid "Copy the container without its snapshots"
 msgstr "Forcer le conteneur à s'arrêter"
@@ -468,7 +468,7 @@ msgstr "Variable d'environnement (de la forme 
HOME=/home/foo) à positionner"
 msgid "Environment:"
 msgstr "Environnement :"
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr "Conteneur éphémère"
 
@@ -504,7 +504,7 @@ msgstr "Échec lors de la génération de 'lxc.%s.1': %v"
 msgid "Failed to generate 'lxc.1': %v"
 msgstr "Échec lors de la génération de 'lxc.1': %v"
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 #, fuzzy
 msgid "Failed to get the new container name"
 msgstr "Profil à appliquer au nouveau conteneur"
@@ -693,7 +693,7 @@ msgid "More than one file to download, but target is not a 
directory"
 msgstr ""
 "Plusieurs fichiers à télécharger, mais la destination n'est pas un dossier"
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 #, fuzzy
 msgid "Move the container without its snapshots"
 msgstr "Forcer le conteneur à s'arrêter"
@@ -875,7 +875,7 @@ msgstr "Profil %s supprimé"
 msgid "Profile %s removed from %s"
 msgstr "Profil %s supprimé de %s"
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr "Profil à appliquer au nouveau conteneur"
 
@@ -1188,7 +1188,11 @@ msgid "To start your first container, try: lxc launch 
ubuntu:16.04"
 msgstr ""
 "Pour démarrer votre premier conteneur, essayer : lxc launch ubuntu:16.04"
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, fuzzy, c-format
 msgid "Transfering container: %s"
 msgstr "Transfert de l'image : %s"
@@ -1390,7 +1394,7 @@ msgstr ""
 "Pour positionner le mot de passe de confiance du serveur :\n"
 "    lxc config set core.trust_password blah"
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 #, fuzzy
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
@@ -1959,7 +1963,7 @@ msgstr ""
 "Exemple :\n"
 "lxc monitor --type=logging"
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 #, fuzzy
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
@@ -2472,7 +2476,7 @@ msgstr "Il est impossible de passer -t et -T 
simultanément"
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr "impossible de copier vers le même nom de conteneur"
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 #, fuzzy
 msgid "You must specify a source container name"
 msgstr "vous devez spécifier un nom de conteneur source"
diff --git a/po/it.po b/po/it.po
index 15c5805fc..5d6371441 100644
--- a/po/it.po
+++ b/po/it.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-06-15 22:46+0000\n"
 "Last-Translator: Alberto Donato <[email protected]>\n"
 "Language-Team: Italian <https://hosted.weblate.org/projects/linux-containers/";
@@ -279,7 +279,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -297,7 +297,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -311,7 +311,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -406,7 +406,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -442,7 +442,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -622,7 +622,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -800,7 +800,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1097,7 +1097,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1239,7 +1243,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1573,7 +1577,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1926,7 +1930,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 #, fuzzy
 msgid "You must specify a source container name"
 msgstr "occorre specificare un nome di container come origine"
diff --git a/po/ja.po b/po/ja.po
index 87ac6d6c1..a90bbf211 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: LXD\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-03-23 12:03+0000\n"
 "Last-Translator: KATOH Yasufumi <[email protected]>\n"
 "Language-Team: Japanese <https://hosted.weblate.org/projects/linux-";
@@ -260,7 +260,7 @@ msgstr "カラムレイアウト"
 msgid "Commands:"
 msgstr "コマンド:"
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr "新しいコンテナに適用するキー/値の設定"
 
@@ -278,7 +278,7 @@ msgstr "接続が拒否されました。LXDが実行されていますか?"
 msgid "Container name is mandatory"
 msgstr "コンテナ名を指定する必要があります"
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr "コンテナ名: %s"
@@ -292,7 +292,7 @@ msgstr "コンテナは以下のフィンガープリントで publish されま
 msgid "Copy aliases from source"
 msgstr "ソースからエイリアスをコピーしました"
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 #, fuzzy
 msgid "Copy the container without its snapshots"
 msgstr "コンテナを強制シャットダウンします"
@@ -388,7 +388,7 @@ msgstr "環境変数を設定します (例: HOME=/home/foo)"
 msgid "Environment:"
 msgstr "環境変数:"
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr "Ephemeral コンテナ"
 
@@ -424,7 +424,7 @@ msgstr "'lxc.%s.1' の生成が失敗しました: %v"
 msgid "Failed to generate 'lxc.1': %v"
 msgstr "'lxc.1' の生成が失敗しました: %v"
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 #, fuzzy
 msgid "Failed to get the new container name"
 msgstr "新しいコンテナに適用するプロファイル"
@@ -610,7 +610,7 @@ msgstr ""
 "ダウンロード対象のファイルが複数ありますが、コピー先がディレクトリではありま"
 "せん"
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 #, fuzzy
 msgid "Move the container without its snapshots"
 msgstr "コンテナを強制シャットダウンします"
@@ -789,7 +789,7 @@ msgstr "プロファイル %s を削除しました"
 msgid "Profile %s removed from %s"
 msgstr "プロファイル %s が %s から削除されました"
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr "新しいコンテナに適用するプロファイル"
 
@@ -1100,7 +1100,11 @@ msgstr ""
 "初めてコンテナを起動するには、\"lxc launch ubuntu:16.04\" と実行してみてくだ"
 "さい"
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, fuzzy, c-format
 msgid "Transfering container: %s"
 msgstr "イメージを転送中: %s"
@@ -1307,7 +1311,7 @@ msgstr ""
 "lxc config set core.trust_password blah\n"
 "    サーバのパスワードを blah に設定する。"
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1896,7 +1900,7 @@ msgstr ""
 "lxc monitor --type=logging\n"
 "    ログメッセージのみ表示します。"
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -2535,7 +2539,7 @@ msgstr "-t と -T は同時に指定できません"
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr "--mode と同時に -t または -T は指定できません"
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 #, fuzzy
 msgid "You must specify a source container name"
 msgstr "コピー元のコンテナ名を指定してください"
diff --git a/po/lxd.pot b/po/lxd.pot
index 00d40eb7b..ff1275036 100644
--- a/po/lxd.pot
+++ b/po/lxd.pot
@@ -7,7 +7,7 @@
 msgid   ""
 msgstr  "Project-Id-Version: lxd\n"
         "Report-Msgid-Bugs-To: [email protected]\n"
-        "POT-Creation-Date: 2017-07-02 01:58-0400\n"
+        "POT-Creation-Date: 2017-07-03 01:12-0400\n"
         "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
         "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
         "Language-Team: LANGUAGE <[email protected]>\n"
@@ -249,7 +249,7 @@ msgstr  ""
 msgid   "Commands:"
 msgstr  ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid   "Config key/value to apply to the new container"
 msgstr  ""
 
@@ -266,7 +266,7 @@ msgstr  ""
 msgid   "Container name is mandatory"
 msgstr  ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid   "Container name is: %s"
 msgstr  ""
@@ -280,7 +280,7 @@ msgstr  ""
 msgid   "Copy aliases from source"
 msgstr  ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid   "Copy the container without its snapshots"
 msgstr  ""
 
@@ -374,7 +374,7 @@ msgstr  ""
 msgid   "Environment:"
 msgstr  ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid   "Ephemeral container"
 msgstr  ""
 
@@ -410,7 +410,7 @@ msgstr  ""
 msgid   "Failed to generate 'lxc.1': %v"
 msgstr  ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid   "Failed to get the new container name"
 msgstr  ""
 
@@ -590,7 +590,7 @@ msgstr  ""
 msgid   "More than one file to download, but target is not a directory"
 msgstr  ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid   "Move the container without its snapshots"
 msgstr  ""
 
@@ -767,7 +767,7 @@ msgstr  ""
 msgid   "Profile %s removed from %s"
 msgstr  ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid   "Profile to apply to the new container"
 msgstr  ""
 
@@ -1059,7 +1059,11 @@ msgstr  ""
 msgid   "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr  ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid   "Transfer mode. One of pull (default), push or relay."
+msgstr  ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid   "Transfering container: %s"
 msgstr  ""
@@ -1197,7 +1201,7 @@ msgid   "Usage: lxc config <subcommand> [options]\n"
         "    Will set the server's trust password to blah."
 msgstr  ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid   "Usage: lxc copy [<remote>:]<source>[/<snapshot>] 
[[<remote>:]<destination>] [--ephemeral|e] [--profile|-p <profile>...] 
[--config|-c <key=value>...] [--container-only]\n"
         "\n"
         "Copy containers within or in between LXD instances."
@@ -1490,7 +1494,7 @@ msgid   "Usage: lxc monitor [<remote>:] 
[--type=TYPE...]\n"
         "    Only show log message."
 msgstr  ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid   "Usage: lxc move [<remote>:]<container>[/<snapshot>] 
[<remote>:][<container>[/<snapshot>]] [--container-only]\n"
         "\n"
         "Move containers within or in between LXD instances.\n"
@@ -1808,7 +1812,7 @@ msgstr  ""
 msgid   "You can't pass -t or -T at the same time as --mode"
 msgstr  ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid   "You must specify a source container name"
 msgstr  ""
 
diff --git a/po/nl.po b/po/nl.po
index b82157709..2ab523c82 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -255,7 +255,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -273,7 +273,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -287,7 +287,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -382,7 +382,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -418,7 +418,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -598,7 +598,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -776,7 +776,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1072,7 +1072,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1214,7 +1218,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1548,7 +1552,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1901,7 +1905,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
diff --git a/po/ru.po b/po/ru.po
index 32f32062c..bcd2eebc7 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: 2017-06-06 13:55+0000\n"
 "Last-Translator: Александр Киль <[email protected]>\n"
 "Language-Team: Russian <https://hosted.weblate.org/projects/linux-containers/";
@@ -328,7 +328,7 @@ msgstr "Столбцы"
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -346,7 +346,7 @@ msgstr "В соединении отказано; LXD запущен?"
 msgid "Container name is mandatory"
 msgstr "Имя контейнера является обязательным"
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr "Имя контейнера: %s"
@@ -360,7 +360,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr "Копировать псевдонимы из источника"
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -456,7 +456,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -492,7 +492,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -673,7 +673,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -852,7 +852,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1148,7 +1148,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1293,7 +1297,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 #, fuzzy
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
@@ -1632,7 +1636,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1985,7 +1989,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
diff --git a/po/sr.po b/po/sr.po
index dea2fe71d..8ea7c9d44 100644
--- a/po/sr.po
+++ b/po/sr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -255,7 +255,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -273,7 +273,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -287,7 +287,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -382,7 +382,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -418,7 +418,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -598,7 +598,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -776,7 +776,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1072,7 +1072,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1214,7 +1218,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1548,7 +1552,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1901,7 +1905,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
diff --git a/po/sv.po b/po/sv.po
index c7f4aaf3e..ded933497 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -255,7 +255,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -273,7 +273,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -287,7 +287,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -382,7 +382,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -418,7 +418,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -598,7 +598,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -776,7 +776,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1072,7 +1072,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1214,7 +1218,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1548,7 +1552,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1901,7 +1905,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
diff --git a/po/tr.po b/po/tr.po
index c5d085ac0..8daa56623 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: lxd\n"
 "Report-Msgid-Bugs-To: [email protected]\n"
-"POT-Creation-Date: 2017-07-02 01:58-0400\n"
+"POT-Creation-Date: 2017-07-03 01:12-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: Automatically generated\n"
 "Language-Team: none\n"
@@ -255,7 +255,7 @@ msgstr ""
 msgid "Commands:"
 msgstr ""
 
-#: lxc/copy.go:33 lxc/copy.go:34 lxc/init.go:136 lxc/init.go:137
+#: lxc/copy.go:34 lxc/copy.go:35 lxc/init.go:136 lxc/init.go:137
 msgid "Config key/value to apply to the new container"
 msgstr ""
 
@@ -273,7 +273,7 @@ msgstr ""
 msgid "Container name is mandatory"
 msgstr ""
 
-#: lxc/copy.go:220 lxc/init.go:314
+#: lxc/copy.go:224 lxc/init.go:314
 #, c-format
 msgid "Container name is: %s"
 msgstr ""
@@ -287,7 +287,7 @@ msgstr ""
 msgid "Copy aliases from source"
 msgstr ""
 
-#: lxc/copy.go:39
+#: lxc/copy.go:41
 msgid "Copy the container without its snapshots"
 msgstr ""
 
@@ -382,7 +382,7 @@ msgstr ""
 msgid "Environment:"
 msgstr ""
 
-#: lxc/copy.go:37 lxc/copy.go:38 lxc/init.go:140 lxc/init.go:141
+#: lxc/copy.go:38 lxc/copy.go:39 lxc/init.go:140 lxc/init.go:141
 msgid "Ephemeral container"
 msgstr ""
 
@@ -418,7 +418,7 @@ msgstr ""
 msgid "Failed to generate 'lxc.1': %v"
 msgstr ""
 
-#: lxc/copy.go:215
+#: lxc/copy.go:219
 msgid "Failed to get the new container name"
 msgstr ""
 
@@ -598,7 +598,7 @@ msgstr ""
 msgid "More than one file to download, but target is not a directory"
 msgstr ""
 
-#: lxc/move.go:38
+#: lxc/move.go:39
 msgid "Move the container without its snapshots"
 msgstr ""
 
@@ -776,7 +776,7 @@ msgstr ""
 msgid "Profile %s removed from %s"
 msgstr ""
 
-#: lxc/copy.go:35 lxc/copy.go:36 lxc/init.go:138 lxc/init.go:139
+#: lxc/copy.go:36 lxc/copy.go:37 lxc/init.go:138 lxc/init.go:139
 msgid "Profile to apply to the new container"
 msgstr ""
 
@@ -1072,7 +1072,11 @@ msgstr ""
 msgid "To start your first container, try: lxc launch ubuntu:16.04"
 msgstr ""
 
-#: lxc/copy.go:189
+#: lxc/copy.go:40 lxc/move.go:40
+msgid "Transfer mode. One of pull (default), push or relay."
+msgstr ""
+
+#: lxc/copy.go:193
 #, c-format
 msgid "Transfering container: %s"
 msgstr ""
@@ -1214,7 +1218,7 @@ msgid ""
 "    Will set the server's trust password to blah."
 msgstr ""
 
-#: lxc/copy.go:26
+#: lxc/copy.go:27
 msgid ""
 "Usage: lxc copy [<remote>:]<source>[/<snapshot>] [[<remote>:]<destination>] "
 "[--ephemeral|e] [--profile|-p <profile>...] [--config|-c <key=value>...] [--"
@@ -1548,7 +1552,7 @@ msgid ""
 "    Only show log message."
 msgstr ""
 
-#: lxc/move.go:22
+#: lxc/move.go:23
 msgid ""
 "Usage: lxc move [<remote>:]<container>[/<snapshot>] [<remote>:][<container>[/"
 "<snapshot>]] [--container-only]\n"
@@ -1901,7 +1905,7 @@ msgstr ""
 msgid "You can't pass -t or -T at the same time as --mode"
 msgstr ""
 
-#: lxc/copy.go:57
+#: lxc/copy.go:59
 msgid "You must specify a source container name"
 msgstr ""
 
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to