1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
package main
import (
"fmt"
"reflect"
"github.com/canonical/lxd/client"
"github.com/canonical/lxd/lxd/migration"
"github.com/canonical/lxd/shared/api"
)
func transferRootfs(dst lxd.ContainerServer, op lxd.Operation, rootfs string, rsyncArgs string) error {
opAPI := op.Get()
// Connect to the websockets
wsControl, err := op.GetWebsocket(opAPI.Metadata[api.SecretNameControl].(string))
if err != nil {
return err
}
abort := func(err error) error {
protoSendError(wsControl, err)
return err
}
wsFs, err := op.GetWebsocket(opAPI.Metadata[api.SecretNameFilesystem].(string))
if err != nil {
return abort(err)
}
// Setup control struct
fs := migration.MigrationFSType_RSYNC
rsyncHasFeature := true
offerHeader := migration.MigrationHeader{
Fs: &fs,
RsyncFeatures: &migration.RsyncFeatures{
Xattrs: &rsyncHasFeature,
Delete: &rsyncHasFeature,
Compress: &rsyncHasFeature,
},
}
err = migration.ProtoSend(wsControl, &offerHeader)
if err != nil {
return abort(err)
}
var respHeader migration.MigrationHeader
err = migration.ProtoRecv(wsControl, &respHeader)
if err != nil {
return abort(err)
}
rsyncFeaturesOffered := offerHeader.GetRsyncFeaturesSlice()
rsyncFeaturesResponse := respHeader.GetRsyncFeaturesSlice()
if !reflect.DeepEqual(rsyncFeaturesOffered, rsyncFeaturesResponse) {
return abort(fmt.Errorf("Offered rsync features (%v) differ from those in the migration response (%v)", rsyncFeaturesOffered, rsyncFeaturesResponse))
}
// Send the filesystem
err = rsyncSend(wsFs, rootfs, rsyncArgs)
if err != nil {
return abort(err)
}
// Check the result
msg := migration.MigrationControl{}
err = migration.ProtoRecv(wsControl, &msg)
if err != nil {
_ = wsControl.Close()
return err
}
if !msg.GetSuccess() {
return fmt.Errorf(msg.GetMessage())
}
return nil
}
|