[lxc-devel] [lxd/master] Bugfixes
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Jul 6 04:36:27 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/20170706/6d604262/attachment.bin>
-------------- next part --------------
From 441f13699411106ad27c5e24d0e691c9b86047c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 6 Jul 2017 00:24:17 -0400
Subject: [PATCH 1/2] client: Improve migration relay code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This removes code duplication by adding a new function for migration
proxying and makes it more robust by validating things before starting
the proxy.
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
client/lxd_containers.go | 147 +++++++++++++++++++++++++++++------------------
1 file changed, 91 insertions(+), 56 deletions(-)
diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index b627169db..9d4cb6bce 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -344,36 +344,11 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
}
// 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))
+ err = r.proxyMigration(targetOp, targetSecrets, source, op, sourceSecrets)
+ if err != nil {
+ return nil, err
}
- // 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,
@@ -399,6 +374,91 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
return r.tryCreateContainer(req, info.Addresses)
}
+func (r *ProtocolLXD) proxyMigration(targetOp *Operation, targetSecrets map[string]string, source ContainerServer, sourceOp *Operation, sourceSecrets map[string]string) error {
+ // Sanity checks
+ for n := range targetSecrets {
+ _, ok := sourceSecrets[n]
+ if !ok {
+ return fmt.Errorf("Migration target expects the \"%s\" socket but source isn't providing it", n)
+ }
+ }
+
+ if targetSecrets["control"] == "" {
+ return fmt.Errorf("Migration target didn't setup the required \"control\" socket")
+ }
+
+ // Struct used to hold everything together
+ type proxy struct {
+ done chan bool
+ sourceConn *websocket.Conn
+ targetConn *websocket.Conn
+ }
+
+ proxies := map[string]*proxy{}
+
+ // Connect the control socket
+ sourceConn, err := source.GetOperationWebsocket(sourceOp.ID, sourceSecrets["control"])
+ if err != nil {
+ return err
+ }
+
+ targetConn, err := r.GetOperationWebsocket(targetOp.ID, targetSecrets["control"])
+ if err != nil {
+ return err
+ }
+
+ proxies["control"] = &proxy{
+ done: shared.WebsocketProxy(sourceConn, targetConn),
+ sourceConn: sourceConn,
+ targetConn: targetConn,
+ }
+
+ // Connect the data sockets
+ for name := range sourceSecrets {
+ if name == "control" {
+ continue
+ }
+
+ // Handle resets (used for multiple objects)
+ sourceConn, err := source.GetOperationWebsocket(sourceOp.ID, sourceSecrets[name])
+ if err != nil {
+ break
+ }
+
+ targetConn, err := r.GetOperationWebsocket(targetOp.ID, targetSecrets[name])
+ if err != nil {
+ break
+ }
+
+ proxies[name] = &proxy{
+ sourceConn: sourceConn,
+ targetConn: targetConn,
+ done: shared.WebsocketProxy(sourceConn, targetConn),
+ }
+ }
+
+ // Cleanup once everything is done
+ go func() {
+ // Wait for control socket
+ <-proxies["control"].done
+ proxies["control"].sourceConn.Close()
+ proxies["control"].targetConn.Close()
+
+ // Then deal with the others
+ for name, proxy := range proxies {
+ if name == "control" {
+ continue
+ }
+
+ <-proxy.done
+ proxy.sourceConn.Close()
+ proxy.targetConn.Close()
+ }
+ }()
+
+ return nil
+}
+
// UpdateContainer updates the container definition
func (r *ProtocolLXD) UpdateContainer(name string, container api.ContainerPut, ETag string) (*Operation, error) {
// Send the request
@@ -991,36 +1051,11 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
}
// 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))
+ err = r.proxyMigration(targetOp, targetSecrets, source, op, sourceSecrets)
+ if err != nil {
+ return nil, err
}
- // 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,
From 5eeaa93fe5430d0110420ff44aec49298177d875 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 6 Jul 2017 00:25:41 -0400
Subject: [PATCH 2/2] shared: Websocket proxy should proxy everything
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>
---
shared/network.go | 25 ++++++++-----------------
1 file changed, 8 insertions(+), 17 deletions(-)
diff --git a/shared/network.go b/shared/network.go
index 4cf7af81b..a2ee54740 100644
--- a/shared/network.go
+++ b/shared/network.go
@@ -234,35 +234,21 @@ 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)
+ w, err := out.NextWriter(mt)
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
}
@@ -275,8 +261,13 @@ func WebsocketProxy(source *websocket.Conn, target *websocket.Conn) chan bool {
ch := make(chan bool)
go func() {
- <-chSend
- <-chRecv
+ select {
+ case <-chSend:
+ case <-chRecv:
+ }
+
+ source.Close()
+ target.Close()
ch <- true
}()
More information about the lxc-devel
mailing list