[lxc-devel] [lxd/master] push and relay mode for container copy/move
stgraber on Github
lxc-bot at linuxcontainers.org
Mon Jul 3 05:37:50 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170703/d001a23a/attachment.bin>
-------------- next part --------------
From 5134b57faa22827e4272c96e08dbaec5a9124b2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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?= <stgraber at ubuntu.com>
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 <stgraber at ubuntu.com>
---
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: lxc-devel at lists.linuxcontainers.org\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 <tim at netlope.de>\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: lxc-devel at lists.linuxcontainers.org\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 <simos.65 at gmail.com>\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: lxc-devel at lists.linuxcontainers.org\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 <stgraber at stgraber.org>\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: lxc-devel at lists.linuxcontainers.org\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 <alberto.donato at gmail.com>\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: lxc-devel at lists.linuxcontainers.org\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 <karma at jazz.email.ne.jp>\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: lxc-devel at lists.linuxcontainers.org\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 at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at li.org>\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: lxc-devel at lists.linuxcontainers.org\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: lxc-devel at lists.linuxcontainers.org\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: Александр Киль <shorrey at gmail.com>\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: lxc-devel at lists.linuxcontainers.org\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: lxc-devel at lists.linuxcontainers.org\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: lxc-devel at lists.linuxcontainers.org\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 ""
More information about the lxc-devel
mailing list