[lxc-devel] [lxd/master] client: Make Operation and RemoteOperation interfaces
stgraber on Github
lxc-bot at linuxcontainers.org
Wed Mar 21 18:09:55 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 354 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180321/377e3489/attachment.bin>
-------------- next part --------------
From ccf7bee7f3eb0300667e2216a7fb434d01c2bf47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 21 Mar 2018 13:48:53 -0400
Subject: [PATCH] client: Make Operation and RemoteOperation interfaces
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 | 69 ++++++++++++++++++----------
client/lxd.go | 6 +--
client/lxd_cluster.go | 2 +-
client/lxd_containers.go | 104 +++++++++++++++++++++++-------------------
client/lxd_images.go | 19 ++++----
client/lxd_storage_volumes.go | 8 ++--
client/operations.go | 40 +++++++++-------
lxc/config.go | 2 +-
lxc/copy.go | 2 +-
lxc/delete.go | 2 +-
lxc/exec.go | 3 +-
lxc/image.go | 6 ++-
lxc/publish.go | 3 +-
lxc/storage.go | 2 +-
lxc/utils/cancel.go | 2 +-
lxd-p2c/utils.go | 8 ++--
lxd/container_console.go | 5 +-
lxd/container_exec.go | 5 +-
lxd/containers_post.go | 5 +-
lxd/main_init.go | 2 +-
20 files changed, 172 insertions(+), 123 deletions(-)
diff --git a/client/interfaces.go b/client/interfaces.go
index d92096af3..051ef104f 100644
--- a/client/interfaces.go
+++ b/client/interfaces.go
@@ -11,6 +11,25 @@ import (
"github.com/lxc/lxd/shared/ioprogress"
)
+// The Operation type represents a currently running operation.
+type Operation interface {
+ AddHandler(function func(api.Operation)) (target *EventTarget, err error)
+ Cancel() (err error)
+ Get() (op api.Operation)
+ GetWebsocket(secret string) (conn *websocket.Conn, err error)
+ RemoveHandler(target *EventTarget) (err error)
+ Refresh() (err error)
+ Wait() (err error)
+}
+
+// The RemoteOperation type represents an Operation that may be using multiple servers.
+type RemoteOperation interface {
+ AddHandler(function func(api.Operation)) (target *EventTarget, err error)
+ CancelTarget() (err error)
+ GetTarget() (op *api.Operation, err error)
+ Wait() (err error)
+}
+
// The Server type represents a generic read-only server.
type Server interface {
GetConnectionInfo() (info *ConnectionInfo, err error)
@@ -63,16 +82,16 @@ type ContainerServer interface {
GetContainerNames() (names []string, err error)
GetContainers() (containers []api.Container, err error)
GetContainer(name string) (container *api.Container, ETag string, err error)
- CreateContainer(container api.ContainersPost) (op *Operation, err error)
- CreateContainerFromImage(source ImageServer, image api.Image, imgcontainer api.ContainersPost) (op *RemoteOperation, err error)
- CopyContainer(source ContainerServer, container api.Container, args *ContainerCopyArgs) (op *RemoteOperation, err error)
- UpdateContainer(name string, container api.ContainerPut, ETag string) (op *Operation, err error)
- RenameContainer(name string, container api.ContainerPost) (op *Operation, err error)
- MigrateContainer(name string, container api.ContainerPost) (op *Operation, err error)
- DeleteContainer(name string) (op *Operation, err error)
-
- ExecContainer(containerName string, exec api.ContainerExecPost, args *ContainerExecArgs) (op *Operation, err error)
- ConsoleContainer(containerName string, console api.ContainerConsolePost, args *ContainerConsoleArgs) (op *Operation, err error)
+ CreateContainer(container api.ContainersPost) (op Operation, err error)
+ CreateContainerFromImage(source ImageServer, image api.Image, imgcontainer api.ContainersPost) (op RemoteOperation, err error)
+ CopyContainer(source ContainerServer, container api.Container, args *ContainerCopyArgs) (op RemoteOperation, err error)
+ UpdateContainer(name string, container api.ContainerPut, ETag string) (op Operation, err error)
+ RenameContainer(name string, container api.ContainerPost) (op Operation, err error)
+ MigrateContainer(name string, container api.ContainerPost) (op Operation, err error)
+ DeleteContainer(name string) (op Operation, err error)
+
+ ExecContainer(containerName string, exec api.ContainerExecPost, args *ContainerExecArgs) (op Operation, err error)
+ ConsoleContainer(containerName string, console api.ContainerConsolePost, args *ContainerConsoleArgs) (op Operation, err error)
GetContainerConsoleLog(containerName string, args *ContainerConsoleLogArgs) (content io.ReadCloser, err error)
DeleteContainerConsoleLog(containerName string, args *ContainerConsoleLogArgs) (err error)
@@ -83,14 +102,14 @@ type ContainerServer interface {
GetContainerSnapshotNames(containerName string) (names []string, err error)
GetContainerSnapshots(containerName string) (snapshots []api.ContainerSnapshot, err error)
GetContainerSnapshot(containerName string, name string) (snapshot *api.ContainerSnapshot, ETag string, err error)
- CreateContainerSnapshot(containerName string, snapshot api.ContainerSnapshotsPost) (op *Operation, err error)
- CopyContainerSnapshot(source ContainerServer, snapshot api.ContainerSnapshot, args *ContainerSnapshotCopyArgs) (op *RemoteOperation, err error)
- RenameContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (op *Operation, err error)
- MigrateContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (op *Operation, err error)
- DeleteContainerSnapshot(containerName string, name string) (op *Operation, err error)
+ CreateContainerSnapshot(containerName string, snapshot api.ContainerSnapshotsPost) (op Operation, err error)
+ CopyContainerSnapshot(source ContainerServer, snapshot api.ContainerSnapshot, args *ContainerSnapshotCopyArgs) (op RemoteOperation, err error)
+ RenameContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (op Operation, err error)
+ MigrateContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (op Operation, err error)
+ DeleteContainerSnapshot(containerName string, name string) (op Operation, err error)
GetContainerState(name string) (state *api.ContainerState, ETag string, err error)
- UpdateContainerState(name string, state api.ContainerStatePut, ETag string) (op *Operation, err error)
+ UpdateContainerState(name string, state api.ContainerStatePut, ETag string) (op Operation, err error)
GetContainerLogfiles(name string) (logfiles []string, err error)
GetContainerLogfile(name string, filename string) (content io.ReadCloser, err error)
@@ -109,12 +128,12 @@ type ContainerServer interface {
GetEvents() (listener *EventListener, err error)
// Image functions
- CreateImage(image api.ImagesPost, args *ImageCreateArgs) (op *Operation, err error)
- CopyImage(source ImageServer, image api.Image, args *ImageCopyArgs) (op *RemoteOperation, err error)
+ CreateImage(image api.ImagesPost, args *ImageCreateArgs) (op Operation, err error)
+ CopyImage(source ImageServer, image api.Image, args *ImageCopyArgs) (op RemoteOperation, err error)
UpdateImage(fingerprint string, image api.ImagePut, ETag string) (err error)
- DeleteImage(fingerprint string) (op *Operation, err error)
- RefreshImage(fingerprint string) (op *Operation, err error)
- CreateImageSecret(fingerprint string) (op *Operation, err error)
+ DeleteImage(fingerprint string) (op Operation, err error)
+ RefreshImage(fingerprint string) (op Operation, err error)
+ CreateImageSecret(fingerprint string) (op Operation, err error)
CreateImageAlias(alias api.ImageAliasesPost) (err error)
UpdateImageAlias(name string, alias api.ImageAliasesEntryPut, ETag string) (err error)
RenameImageAlias(name string, alias api.ImageAliasesEntryPost) (err error)
@@ -163,12 +182,12 @@ type ContainerServer interface {
UpdateStoragePoolVolume(pool string, volType string, name string, volume api.StorageVolumePut, ETag string) (err error)
DeleteStoragePoolVolume(pool string, volType string, name string) (err error)
RenameStoragePoolVolume(pool string, volType string, name string, volume api.StorageVolumePost) (err error)
- CopyStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeCopyArgs) (op *RemoteOperation, err error)
- MoveStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeMoveArgs) (op *RemoteOperation, err error)
+ CopyStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeCopyArgs) (op RemoteOperation, err error)
+ MoveStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeMoveArgs) (op RemoteOperation, err error)
// Cluster functions ("cluster" API extensions)
GetCluster() (cluster *api.Cluster, ETag string, err error)
- UpdateCluster(cluster api.ClusterPut, ETag string) (op *Operation, err error)
+ UpdateCluster(cluster api.ClusterPut, ETag string) (op Operation, err error)
DeleteClusterMember(name string, force bool) (err error)
GetClusterMemberNames() (names []string, err error)
GetClusterMembers() (members []api.ClusterMember, err error)
@@ -178,7 +197,7 @@ type ContainerServer interface {
// Internal functions (for internal use)
RawQuery(method string, path string, data interface{}, queryETag string) (resp *api.Response, ETag string, err error)
RawWebsocket(path string) (conn *websocket.Conn, err error)
- RawOperation(method string, path string, data interface{}, queryETag string) (op *Operation, ETag string, err error)
+ RawOperation(method string, path string, data interface{}, queryETag string) (op Operation, ETag string, err error)
}
// The ConnectionInfo struct represents general information for a connection
diff --git a/client/lxd.go b/client/lxd.go
index 4218015d1..96458efed 100644
--- a/client/lxd.go
+++ b/client/lxd.go
@@ -114,7 +114,7 @@ func (r *ProtocolLXD) RawWebsocket(path string) (*websocket.Conn, error) {
// RawOperation allows direct querying of a LXD API endpoint returning
// background operations.
-func (r *ProtocolLXD) RawOperation(method string, path string, data interface{}, ETag string) (*Operation, string, error) {
+func (r *ProtocolLXD) RawOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
return r.queryOperation(method, path, data, ETag)
}
@@ -235,7 +235,7 @@ func (r *ProtocolLXD) queryStruct(method string, path string, data interface{},
return etag, nil
}
-func (r *ProtocolLXD) queryOperation(method string, path string, data interface{}, ETag string) (*Operation, string, error) {
+func (r *ProtocolLXD) queryOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
// Attempt to setup an early event listener
listener, err := r.GetEvents()
if err != nil {
@@ -263,7 +263,7 @@ func (r *ProtocolLXD) queryOperation(method string, path string, data interface{
}
// Setup an Operation wrapper
- op := Operation{
+ op := operation{
Operation: *respOperation,
r: r,
listener: listener,
diff --git a/client/lxd_cluster.go b/client/lxd_cluster.go
index 6a807af01..f21a5bb4b 100644
--- a/client/lxd_cluster.go
+++ b/client/lxd_cluster.go
@@ -24,7 +24,7 @@ func (r *ProtocolLXD) GetCluster() (*api.Cluster, string, error) {
}
// UpdateCluster requests to bootstrap a new cluster
-func (r *ProtocolLXD) UpdateCluster(cluster api.ClusterPut, ETag string) (*Operation, error) {
+func (r *ProtocolLXD) UpdateCluster(cluster api.ClusterPut, ETag string) (Operation, error) {
if !r.HasExtension("clustering") {
return nil, fmt.Errorf("The server is missing the required \"clustering\" API extension")
}
diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index 233f6c807..fddbf0ac0 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -63,7 +63,7 @@ func (r *ProtocolLXD) GetContainer(name string) (*api.Container, string, error)
}
// CreateContainer requests that LXD creates a new container
-func (r *ProtocolLXD) CreateContainer(container api.ContainersPost) (*Operation, error) {
+func (r *ProtocolLXD) CreateContainer(container api.ContainersPost) (Operation, error) {
if container.Source.ContainerOnly {
if !r.HasExtension("container_only_migration") {
return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension")
@@ -83,12 +83,12 @@ func (r *ProtocolLXD) CreateContainer(container api.ContainersPost) (*Operation,
return op, nil
}
-func (r *ProtocolLXD) tryCreateContainer(req api.ContainersPost, urls []string) (*RemoteOperation, error) {
+func (r *ProtocolLXD) tryCreateContainer(req api.ContainersPost, urls []string) (RemoteOperation, error) {
if len(urls) == 0 {
return nil, fmt.Errorf("The source server isn't listening on the network")
}
- rop := RemoteOperation{
+ rop := remoteOperation{
chDone: make(chan bool),
}
@@ -138,7 +138,7 @@ func (r *ProtocolLXD) tryCreateContainer(req api.ContainersPost, urls []string)
}
// CreateContainerFromImage is a convenience function to make it easier to create a container from an existing image
-func (r *ProtocolLXD) CreateContainerFromImage(source ImageServer, image api.Image, req api.ContainersPost) (*RemoteOperation, error) {
+func (r *ProtocolLXD) CreateContainerFromImage(source ImageServer, image api.Image, req api.ContainersPost) (RemoteOperation, error) {
// Set the minimal source fields
req.Source.Type = "image"
@@ -153,7 +153,7 @@ func (r *ProtocolLXD) CreateContainerFromImage(source ImageServer, image api.Ima
return nil, err
}
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: op,
chDone: make(chan bool),
}
@@ -201,7 +201,7 @@ func (r *ProtocolLXD) CreateContainerFromImage(source ImageServer, image api.Ima
}
// CopyContainer copies a container from a remote server. Additional options can be passed using ContainerCopyArgs
-func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Container, args *ContainerCopyArgs) (*RemoteOperation, error) {
+func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Container, args *ContainerCopyArgs) (RemoteOperation, error) {
// Base request
req := api.ContainersPost{
Name: container.Name,
@@ -261,7 +261,7 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
return nil, err
}
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: op,
chDone: make(chan bool),
}
@@ -298,15 +298,16 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
if err != nil {
return nil, err
}
+ opAPI := op.Get()
targetSecrets := map[string]string{}
- for k, v := range op.Metadata {
+ for k, v := range opAPI.Metadata {
targetSecrets[k] = v.(string)
}
// Prepare the source request
target := api.ContainerPostTarget{}
- target.Operation = op.ID
+ target.Operation = opAPI.ID
target.Websockets = targetSecrets
target.Certificate = info.Certificate
sourceReq.Target = &target
@@ -324,9 +325,10 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
if err != nil {
return nil, err
}
+ opAPI := op.Get()
sourceSecrets := map[string]string{}
- for k, v := range op.Metadata {
+ for k, v := range opAPI.Metadata {
sourceSecrets[k] = v.(string)
}
@@ -341,21 +343,22 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
if err != nil {
return nil, err
}
+ targetOpAPI := targetOp.Get()
// Extract the websockets
targetSecrets := map[string]string{}
- for k, v := range targetOp.Metadata {
+ for k, v := range targetOpAPI.Metadata {
targetSecrets[k] = v.(string)
}
// Launch the relay
- err = r.proxyMigration(targetOp, targetSecrets, source, op, sourceSecrets)
+ err = r.proxyMigration(targetOp.(*operation), targetSecrets, source, op.(*operation), sourceSecrets)
if err != nil {
return nil, err
}
// Prepare a tracking operation
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: targetOp,
chDone: make(chan bool),
}
@@ -372,14 +375,14 @@ func (r *ProtocolLXD) CopyContainer(source ContainerServer, container api.Contai
// Pull mode migration
req.Source.Type = "migration"
req.Source.Mode = "pull"
- req.Source.Operation = op.ID
+ req.Source.Operation = opAPI.ID
req.Source.Websockets = sourceSecrets
req.Source.Certificate = info.Certificate
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 {
+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]
@@ -465,7 +468,7 @@ func (r *ProtocolLXD) proxyMigration(targetOp *Operation, targetSecrets map[stri
}
// UpdateContainer updates the container definition
-func (r *ProtocolLXD) UpdateContainer(name string, container api.ContainerPut, ETag string) (*Operation, error) {
+func (r *ProtocolLXD) UpdateContainer(name string, container api.ContainerPut, ETag string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("PUT", fmt.Sprintf("/containers/%s", url.QueryEscape(name)), container, ETag)
if err != nil {
@@ -476,7 +479,7 @@ func (r *ProtocolLXD) UpdateContainer(name string, container api.ContainerPut, E
}
// RenameContainer requests that LXD renames the container
-func (r *ProtocolLXD) RenameContainer(name string, container api.ContainerPost) (*Operation, error) {
+func (r *ProtocolLXD) RenameContainer(name string, container api.ContainerPost) (Operation, error) {
// Sanity check
if container.Migration {
return nil, fmt.Errorf("Can't ask for a migration through RenameContainer")
@@ -491,12 +494,12 @@ 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) {
+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{
+ rop := remoteOperation{
chDone: make(chan bool),
}
@@ -542,7 +545,7 @@ func (r *ProtocolLXD) tryMigrateContainer(source ContainerServer, name string, r
}
// MigrateContainer requests that LXD prepares for a container migration
-func (r *ProtocolLXD) MigrateContainer(name string, container api.ContainerPost) (*Operation, error) {
+func (r *ProtocolLXD) MigrateContainer(name string, container api.ContainerPost) (Operation, error) {
if container.ContainerOnly {
if !r.HasExtension("container_only_migration") {
return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension")
@@ -569,7 +572,7 @@ func (r *ProtocolLXD) MigrateContainer(name string, container api.ContainerPost)
}
// DeleteContainer requests that LXD deletes the container
-func (r *ProtocolLXD) DeleteContainer(name string) (*Operation, error) {
+func (r *ProtocolLXD) DeleteContainer(name string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("DELETE", fmt.Sprintf("/containers/%s", url.QueryEscape(name)), nil, "")
if err != nil {
@@ -580,7 +583,7 @@ func (r *ProtocolLXD) DeleteContainer(name string) (*Operation, error) {
}
// ExecContainer requests that LXD spawns a command inside the container
-func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExecPost, args *ContainerExecArgs) (*Operation, error) {
+func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExecPost, args *ContainerExecArgs) (Operation, error) {
if exec.RecordOutput {
if !r.HasExtension("container_exec_recording") {
return nil, fmt.Errorf("The server is missing the required \"container_exec_recording\" API extension")
@@ -592,13 +595,14 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
if err != nil {
return nil, err
}
+ opAPI := op.Get()
// Process additional arguments
if args != nil {
// Parse the fds
fds := map[string]string{}
- value, ok := op.Metadata["fds"]
+ value, ok := opAPI.Metadata["fds"]
if ok {
values := value.(map[string]interface{})
for k, v := range values {
@@ -608,7 +612,7 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
// Call the control handler with a connection to the control socket
if args.Control != nil && fds["control"] != "" {
- conn, err := r.GetOperationWebsocket(op.ID, fds["control"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["control"])
if err != nil {
return nil, err
}
@@ -620,7 +624,7 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
// Handle interactive sections
if args.Stdin != nil && args.Stdout != nil {
// Connect to the websocket
- conn, err := r.GetOperationWebsocket(op.ID, fds["0"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["0"])
if err != nil {
return nil, err
}
@@ -647,7 +651,7 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
// Handle stdin
if fds["0"] != "" {
- conn, err := r.GetOperationWebsocket(op.ID, fds["0"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["0"])
if err != nil {
return nil, err
}
@@ -658,7 +662,7 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
// Handle stdout
if fds["1"] != "" {
- conn, err := r.GetOperationWebsocket(op.ID, fds["1"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["1"])
if err != nil {
return nil, err
}
@@ -669,7 +673,7 @@ func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExec
// Handle stderr
if fds["2"] != "" {
- conn, err := r.GetOperationWebsocket(op.ID, fds["2"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["2"])
if err != nil {
return nil, err
}
@@ -904,7 +908,7 @@ func (r *ProtocolLXD) GetContainerSnapshot(containerName string, name string) (*
}
// CreateContainerSnapshot requests that LXD creates a new snapshot for the container
-func (r *ProtocolLXD) CreateContainerSnapshot(containerName string, snapshot api.ContainerSnapshotsPost) (*Operation, error) {
+func (r *ProtocolLXD) CreateContainerSnapshot(containerName string, snapshot api.ContainerSnapshotsPost) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("POST", fmt.Sprintf("/containers/%s/snapshots", url.QueryEscape(containerName)), snapshot, "")
if err != nil {
@@ -915,7 +919,7 @@ func (r *ProtocolLXD) CreateContainerSnapshot(containerName string, snapshot api
}
// CopyContainerSnapshot copies a snapshot from a remote server into a new container. Additional options can be passed using ContainerCopyArgs
-func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api.ContainerSnapshot, args *ContainerSnapshotCopyArgs) (*RemoteOperation, error) {
+func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api.ContainerSnapshot, args *ContainerSnapshotCopyArgs) (RemoteOperation, error) {
// Base request
fields := strings.SplitN(snapshot.Name, shared.SnapshotDelimiter, 2)
cName := fields[0]
@@ -976,7 +980,7 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
return nil, err
}
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: op,
chDone: make(chan bool),
}
@@ -1015,15 +1019,16 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
if err != nil {
return nil, err
}
+ opAPI := op.Get()
targetSecrets := map[string]string{}
- for k, v := range op.Metadata {
+ for k, v := range opAPI.Metadata {
targetSecrets[k] = v.(string)
}
// Prepare the source request
target := api.ContainerPostTarget{}
- target.Operation = op.ID
+ target.Operation = opAPI.ID
target.Websockets = targetSecrets
target.Certificate = info.Certificate
sourceReq.Target = &target
@@ -1041,9 +1046,10 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
if err != nil {
return nil, err
}
+ opAPI := op.Get()
sourceSecrets := map[string]string{}
- for k, v := range op.Metadata {
+ for k, v := range opAPI.Metadata {
sourceSecrets[k] = v.(string)
}
@@ -1058,21 +1064,22 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
if err != nil {
return nil, err
}
+ targetOpAPI := targetOp.Get()
// Extract the websockets
targetSecrets := map[string]string{}
- for k, v := range targetOp.Metadata {
+ for k, v := range targetOpAPI.Metadata {
targetSecrets[k] = v.(string)
}
// Launch the relay
- err = r.proxyMigration(targetOp, targetSecrets, source, op, sourceSecrets)
+ err = r.proxyMigration(targetOp.(*operation), targetSecrets, source, op.(*operation), sourceSecrets)
if err != nil {
return nil, err
}
// Prepare a tracking operation
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: targetOp,
chDone: make(chan bool),
}
@@ -1089,7 +1096,7 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
// Pull mode migration
req.Source.Type = "migration"
req.Source.Mode = "pull"
- req.Source.Operation = op.ID
+ req.Source.Operation = opAPI.ID
req.Source.Websockets = sourceSecrets
req.Source.Certificate = info.Certificate
@@ -1097,7 +1104,7 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source ContainerServer, snapshot api
}
// RenameContainerSnapshot requests that LXD renames the snapshot
-func (r *ProtocolLXD) RenameContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (*Operation, error) {
+func (r *ProtocolLXD) RenameContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (Operation, error) {
// Sanity check
if container.Migration {
return nil, fmt.Errorf("Can't ask for a migration through RenameContainerSnapshot")
@@ -1112,12 +1119,12 @@ 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) {
+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{
+ rop := remoteOperation{
chDone: make(chan bool),
}
@@ -1163,7 +1170,7 @@ func (r *ProtocolLXD) tryMigrateContainerSnapshot(source ContainerServer, contai
}
// MigrateContainerSnapshot requests that LXD prepares for a snapshot migration
-func (r *ProtocolLXD) MigrateContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (*Operation, error) {
+func (r *ProtocolLXD) MigrateContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPost) (Operation, error) {
// Sanity check
if !container.Migration {
return nil, fmt.Errorf("Can't ask for a rename through MigrateContainerSnapshot")
@@ -1179,7 +1186,7 @@ func (r *ProtocolLXD) MigrateContainerSnapshot(containerName string, name string
}
// DeleteContainerSnapshot requests that LXD deletes the container snapshot
-func (r *ProtocolLXD) DeleteContainerSnapshot(containerName string, name string) (*Operation, error) {
+func (r *ProtocolLXD) DeleteContainerSnapshot(containerName string, name string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("DELETE", fmt.Sprintf("/containers/%s/snapshots/%s", url.QueryEscape(containerName), url.QueryEscape(name)), nil, "")
if err != nil {
@@ -1203,7 +1210,7 @@ func (r *ProtocolLXD) GetContainerState(name string) (*api.ContainerState, strin
}
// UpdateContainerState updates the container to match the requested state
-func (r *ProtocolLXD) UpdateContainerState(name string, state api.ContainerStatePut, ETag string) (*Operation, error) {
+func (r *ProtocolLXD) UpdateContainerState(name string, state api.ContainerStatePut, ETag string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("PUT", fmt.Sprintf("/containers/%s/state", url.QueryEscape(name)), state, ETag)
if err != nil {
@@ -1409,7 +1416,7 @@ func (r *ProtocolLXD) DeleteContainerTemplateFile(name string, templateName stri
}
// ConsoleContainer requests that LXD attaches to the console device of a container.
-func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.ContainerConsolePost, args *ContainerConsoleArgs) (*Operation, error) {
+func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.ContainerConsolePost, args *ContainerConsoleArgs) (Operation, error) {
if !r.HasExtension("console") {
return nil, fmt.Errorf("The server is missing the required \"console\" API extension")
}
@@ -1419,6 +1426,7 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain
if err != nil {
return nil, err
}
+ opAPI := op.Get()
if args == nil || args.Terminal == nil {
return nil, fmt.Errorf("A terminal must be set")
@@ -1431,7 +1439,7 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain
// Parse the fds
fds := map[string]string{}
- value, ok := op.Metadata["fds"]
+ value, ok := opAPI.Metadata["fds"]
if ok {
values := value.(map[string]interface{})
for k, v := range values {
@@ -1445,7 +1453,7 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain
return nil, fmt.Errorf("Did not receive a file descriptor for the control channel")
}
- controlConn, err = r.GetOperationWebsocket(op.ID, fds["control"])
+ controlConn, err = r.GetOperationWebsocket(opAPI.ID, fds["control"])
if err != nil {
return nil, err
}
@@ -1453,7 +1461,7 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain
go args.Control(controlConn)
// Connect to the websocket
- conn, err := r.GetOperationWebsocket(op.ID, fds["0"])
+ conn, err := r.GetOperationWebsocket(opAPI.ID, fds["0"])
if err != nil {
return nil, err
}
diff --git a/client/lxd_images.go b/client/lxd_images.go
index 51058b1d0..2f6f2e677 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -68,8 +68,9 @@ func (r *ProtocolLXD) GetImageSecret(fingerprint string) (string, error) {
if err != nil {
return "", err
}
+ opAPI := op.Get()
- return op.Metadata["secret"].(string), nil
+ return opAPI.Metadata["secret"].(string), nil
}
// GetPrivateImage is similar to GetImage but allows passing a secret download token
@@ -280,7 +281,7 @@ func (r *ProtocolLXD) GetImageAlias(name string) (*api.ImageAliasesEntry, string
}
// CreateImage requests that LXD creates, copies or import a new image
-func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (*Operation, error) {
+func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (Operation, error) {
if image.CompressionAlgorithm != "" {
if !r.HasExtension("image_compression_algorithm") {
return nil, fmt.Errorf("The server is missing the required \"image_compression_algorithm\" API extension")
@@ -423,7 +424,7 @@ func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (
}
// Setup an Operation wrapper
- op := Operation{
+ op := operation{
Operation: *respOperation,
r: r,
chActive: make(chan bool),
@@ -433,12 +434,12 @@ func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (
}
// tryCopyImage iterates through the source server URLs until one lets it download the image
-func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (*RemoteOperation, error) {
+func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (RemoteOperation, error) {
if len(urls) == 0 {
return nil, fmt.Errorf("The source server isn't listening on the network")
}
- rop := RemoteOperation{
+ rop := remoteOperation{
chDone: make(chan bool),
}
@@ -515,7 +516,7 @@ func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (*RemoteOp
}
// CopyImage copies an image from a remote server. Additional options can be passed using ImageCopyArgs
-func (r *ProtocolLXD) CopyImage(source ImageServer, image api.Image, args *ImageCopyArgs) (*RemoteOperation, error) {
+func (r *ProtocolLXD) CopyImage(source ImageServer, image api.Image, args *ImageCopyArgs) (RemoteOperation, error) {
// Sanity checks
if r == source {
return nil, fmt.Errorf("The source and target servers must be different")
@@ -579,7 +580,7 @@ func (r *ProtocolLXD) UpdateImage(fingerprint string, image api.ImagePut, ETag s
}
// DeleteImage requests that LXD removes an image from the store
-func (r *ProtocolLXD) DeleteImage(fingerprint string) (*Operation, error) {
+func (r *ProtocolLXD) DeleteImage(fingerprint string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("DELETE", fmt.Sprintf("/images/%s", url.QueryEscape(fingerprint)), nil, "")
if err != nil {
@@ -590,7 +591,7 @@ func (r *ProtocolLXD) DeleteImage(fingerprint string) (*Operation, error) {
}
// RefreshImage requests that LXD issues an image refresh
-func (r *ProtocolLXD) RefreshImage(fingerprint string) (*Operation, error) {
+func (r *ProtocolLXD) RefreshImage(fingerprint string) (Operation, error) {
if !r.HasExtension("image_force_refresh") {
return nil, fmt.Errorf("The server is missing the required \"image_force_refresh\" API extension")
}
@@ -605,7 +606,7 @@ func (r *ProtocolLXD) RefreshImage(fingerprint string) (*Operation, error) {
}
// CreateImageSecret requests that LXD issues a temporary image secret
-func (r *ProtocolLXD) CreateImageSecret(fingerprint string) (*Operation, error) {
+func (r *ProtocolLXD) CreateImageSecret(fingerprint string) (Operation, error) {
// Send the request
op, _, err := r.queryOperation("POST", fmt.Sprintf("/images/%s/secret", url.QueryEscape(fingerprint)), nil, "")
if err != nil {
diff --git a/client/lxd_storage_volumes.go b/client/lxd_storage_volumes.go
index eabeea5a1..c20c5e3f2 100644
--- a/client/lxd_storage_volumes.go
+++ b/client/lxd_storage_volumes.go
@@ -95,7 +95,7 @@ func (r *ProtocolLXD) CreateStoragePoolVolume(pool string, volume api.StorageVol
}
// CopyStoragePoolVolume copies an existing storage volume
-func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeCopyArgs) (*RemoteOperation, error) {
+func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeCopyArgs) (RemoteOperation, error) {
if !r.HasExtension("storage_api_local_volume_handling") {
return nil, fmt.Errorf("The server is missing the required \"storage_api_local_volume_handling\" API extension")
}
@@ -120,7 +120,7 @@ func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source ContainerServer,
return nil, err
}
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: op,
chDone: make(chan bool),
}
@@ -135,7 +135,7 @@ func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source ContainerServer,
}
// MoveStoragePoolVolume renames or moves an existing storage volume
-func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeMoveArgs) (*RemoteOperation, error) {
+func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source ContainerServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeMoveArgs) (RemoteOperation, error) {
if !r.HasExtension("storage_api_local_volume_handling") {
return nil, fmt.Errorf("The server is missing the required \"storage_api_local_volume_handling\" API extension")
}
@@ -155,7 +155,7 @@ func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source ContainerServer,
return nil, err
}
- rop := RemoteOperation{
+ rop := remoteOperation{
targetOp: op,
chDone: make(chan bool),
}
diff --git a/client/operations.go b/client/operations.go
index 90544ff96..fc015c220 100644
--- a/client/operations.go
+++ b/client/operations.go
@@ -11,7 +11,7 @@ import (
)
// The Operation type represents an ongoing LXD operation (asynchronous processing)
-type Operation struct {
+type operation struct {
api.Operation
r *ProtocolLXD
@@ -23,7 +23,7 @@ type Operation struct {
}
// AddHandler adds a function to be called whenever an event is received
-func (op *Operation) AddHandler(function func(api.Operation)) (*EventTarget, error) {
+func (op *operation) AddHandler(function func(api.Operation)) (*EventTarget, error) {
// Make sure we have a listener setup
err := op.setupListener()
if err != nil {
@@ -53,17 +53,22 @@ func (op *Operation) AddHandler(function func(api.Operation)) (*EventTarget, err
}
// Cancel will request that LXD cancels the operation (if supported)
-func (op *Operation) Cancel() error {
+func (op *operation) Cancel() error {
return op.r.DeleteOperation(op.ID)
}
+// Get returns the API operation struct
+func (op *operation) Get() api.Operation {
+ return op.Operation
+}
+
// GetWebsocket returns a raw websocket connection from the operation
-func (op *Operation) GetWebsocket(secret string) (*websocket.Conn, error) {
+func (op *operation) GetWebsocket(secret string) (*websocket.Conn, error) {
return op.r.GetOperationWebsocket(op.ID, secret)
}
// RemoveHandler removes a function to be called whenever an event is received
-func (op *Operation) RemoveHandler(target *EventTarget) error {
+func (op *operation) RemoveHandler(target *EventTarget) error {
// Make sure we're not racing with ourselves
op.handlerLock.Lock()
defer op.handlerLock.Unlock()
@@ -77,7 +82,7 @@ func (op *Operation) RemoveHandler(target *EventTarget) error {
}
// Refresh pulls the current version of the operation and updates the struct
-func (op *Operation) Refresh() error {
+func (op *operation) Refresh() error {
// Don't bother with a manual update if we are listening for events
if op.handlerReady {
return nil
@@ -96,7 +101,7 @@ func (op *Operation) Refresh() error {
}
// Wait lets you wait until the operation reaches a final state
-func (op *Operation) Wait() error {
+func (op *operation) Wait() error {
// Check if not done already
if op.StatusCode.IsFinal() {
if op.Err != "" {
@@ -122,7 +127,7 @@ func (op *Operation) Wait() error {
return nil
}
-func (op *Operation) setupListener() error {
+func (op *operation) setupListener() error {
// Make sure we're not racing with ourselves
op.handlerLock.Lock()
defer op.handlerLock.Unlock()
@@ -245,7 +250,7 @@ func (op *Operation) setupListener() error {
return nil
}
-func (op *Operation) extractOperation(data interface{}) *api.Operation {
+func (op *operation) extractOperation(data interface{}) *api.Operation {
// Extract the metadata
meta, ok := data.(map[string]interface{})["metadata"]
if !ok {
@@ -272,9 +277,9 @@ func (op *Operation) extractOperation(data interface{}) *api.Operation {
return &newOp
}
-// The RemoteOperation type represents an ongoing LXD operation between two servers
-type RemoteOperation struct {
- targetOp *Operation
+// The remoteOperation type represents an ongoing LXD operation between two servers
+type remoteOperation struct {
+ targetOp Operation
handlers []func(api.Operation)
@@ -284,7 +289,7 @@ type RemoteOperation struct {
}
// AddHandler adds a function to be called whenever an event is received
-func (op *RemoteOperation) AddHandler(function func(api.Operation)) (*EventTarget, error) {
+func (op *remoteOperation) AddHandler(function func(api.Operation)) (*EventTarget, error) {
var err error
var target *EventTarget
@@ -309,7 +314,7 @@ func (op *RemoteOperation) AddHandler(function func(api.Operation)) (*EventTarge
}
// CancelTarget attempts to cancel the target operation
-func (op *RemoteOperation) CancelTarget() error {
+func (op *remoteOperation) CancelTarget() error {
if op.targetOp == nil {
return fmt.Errorf("No associated target operation")
}
@@ -318,16 +323,17 @@ func (op *RemoteOperation) CancelTarget() error {
}
// GetTarget returns the target operation
-func (op *RemoteOperation) GetTarget() (*api.Operation, error) {
+func (op *remoteOperation) GetTarget() (*api.Operation, error) {
if op.targetOp == nil {
return nil, fmt.Errorf("No associated target operation")
}
- return &op.targetOp.Operation, nil
+ opAPI := op.targetOp.Get()
+ return &opAPI, nil
}
// Wait lets you wait until the operation reaches a final state
-func (op *RemoteOperation) Wait() error {
+func (op *remoteOperation) Wait() error {
<-op.chDone
if op.chPost != nil {
diff --git a/lxc/config.go b/lxc/config.go
index 68b7b604c..8a50fb921 100644
--- a/lxc/config.go
+++ b/lxc/config.go
@@ -809,7 +809,7 @@ func (c *configCmd) doContainerConfigEdit(client lxd.ContainerServer, cont strin
newdata := api.ContainerPut{}
err = yaml.Unmarshal(content, &newdata)
if err == nil {
- var op *lxd.Operation
+ var op lxd.Operation
op, err = client.UpdateContainer(cont, newdata, etag)
if err == nil {
err = op.Wait()
diff --git a/lxc/copy.go b/lxc/copy.go
index 3f9290506..89c0e932f 100644
--- a/lxc/copy.go
+++ b/lxc/copy.go
@@ -101,7 +101,7 @@ func (c *copyCmd) copyContainer(conf *config.Config, sourceResource string,
}
}
- var op *lxd.RemoteOperation
+ var op lxd.RemoteOperation
if shared.IsSnapshot(sourceName) {
// Prepare the container creation request
args := lxd.ContainerSnapshotCopyArgs{
diff --git a/lxc/delete.go b/lxc/delete.go
index 0863cf38f..12fed0d64 100644
--- a/lxc/delete.go
+++ b/lxc/delete.go
@@ -50,7 +50,7 @@ func (c *deleteCmd) promptDelete(name string) error {
}
func (c *deleteCmd) doDelete(d lxd.ContainerServer, name string) error {
- var op *lxd.Operation
+ var op lxd.Operation
var err error
if shared.IsSnapshot(name) {
diff --git a/lxc/exec.go b/lxc/exec.go
index 42b7a32fc..89f90654f 100644
--- a/lxc/exec.go
+++ b/lxc/exec.go
@@ -234,6 +234,7 @@ func (c *execCmd) run(conf *config.Config, args []string) error {
if err != nil {
return err
}
+ opAPI := op.Get()
// Wait for any remaining I/O to be flushed
<-execArgs.DataDone
@@ -249,6 +250,6 @@ func (c *execCmd) run(conf *config.Config, args []string) error {
termios.Restore(cfd, oldttystate)
}
- os.Exit(int(op.Metadata["return"].(float64)))
+ os.Exit(int(opAPI.Metadata["return"].(float64)))
return nil
}
diff --git a/lxc/image.go b/lxc/image.go
index eb104ec02..595ee72dc 100644
--- a/lxc/image.go
+++ b/lxc/image.go
@@ -543,10 +543,11 @@ func (c *imageCmd) run(conf *config.Config, args []string) error {
if err != nil {
return err
}
+ opAPI := op.Get()
// Check if refreshed
refreshed := false
- flag, ok := op.Metadata["refreshed"]
+ flag, ok := opAPI.Metadata["refreshed"]
if ok {
refreshed = flag.(bool)
}
@@ -772,9 +773,10 @@ func (c *imageCmd) run(conf *config.Config, args []string) error {
progress.Done("")
return err
}
+ opAPI := op.Get()
// Get the fingerprint
- fingerprint := op.Metadata["fingerprint"].(string)
+ fingerprint := opAPI.Metadata["fingerprint"].(string)
progress.Done(fmt.Sprintf(i18n.G("Image imported with fingerprint: %s"), fingerprint))
// Add the aliases
diff --git a/lxc/publish.go b/lxc/publish.go
index 5d2275e2e..cea9a50f4 100644
--- a/lxc/publish.go
+++ b/lxc/publish.go
@@ -212,9 +212,10 @@ func (c *publishCmd) run(conf *config.Config, args []string) error {
if err != nil {
return err
}
+ opAPI := op.Get()
// Grab the fingerprint
- fingerprint := op.Metadata["fingerprint"].(string)
+ fingerprint := opAPI.Metadata["fingerprint"].(string)
// For remote publish, copy to target now
if cRemote != iRemote {
diff --git a/lxc/storage.go b/lxc/storage.go
index b2497c509..1fe41eb79 100644
--- a/lxc/storage.go
+++ b/lxc/storage.go
@@ -1118,7 +1118,7 @@ func (c *storageCmd) doStoragePoolVolumeCopy(client lxd.ContainerServer, src str
return err
}
- op := &lxd.RemoteOperation{}
+ var op lxd.RemoteOperation
opMsg := ""
finalMsg := ""
if move {
diff --git a/lxc/utils/cancel.go b/lxc/utils/cancel.go
index f1b065cbd..4f936a044 100644
--- a/lxc/utils/cancel.go
+++ b/lxc/utils/cancel.go
@@ -11,7 +11,7 @@ import (
)
// CancelableWait waits for an operation and cancel it on SIGINT/SIGTERM
-func CancelableWait(op *lxd.RemoteOperation, progress *ProgressRenderer) error {
+func CancelableWait(op lxd.RemoteOperation, progress *ProgressRenderer) error {
// Signal handling
chSignal := make(chan os.Signal)
signal.Notify(chSignal, os.Interrupt)
diff --git a/lxd-p2c/utils.go b/lxd-p2c/utils.go
index dda9f2954..6a30bf36e 100644
--- a/lxd-p2c/utils.go
+++ b/lxd-p2c/utils.go
@@ -15,14 +15,16 @@ import (
"github.com/lxc/lxd/shared/api"
)
-func transferRootfs(dst lxd.ContainerServer, op *lxd.Operation, rootfs string) error {
+func transferRootfs(dst lxd.ContainerServer, op lxd.Operation, rootfs string) error {
+ opAPI := op.Get()
+
// Connect to the websockets
- wsControl, err := dst.GetOperationWebsocket(op.ID, op.Metadata["control"].(string))
+ wsControl, err := op.GetWebsocket(opAPI.Metadata["control"].(string))
if err != nil {
return err
}
- wsFs, err := dst.GetOperationWebsocket(op.ID, op.Metadata["fs"].(string))
+ wsFs, err := op.GetWebsocket(opAPI.Metadata["fs"].(string))
if err != nil {
return err
}
diff --git a/lxd/container_console.go b/lxd/container_console.go
index 300bbbf14..85af58799 100644
--- a/lxd/container_console.go
+++ b/lxd/container_console.go
@@ -271,13 +271,16 @@ func containerConsolePost(d *Daemon, r *http.Request) Response {
if err != nil {
return SmartError(err)
}
+
if client != nil {
url := fmt.Sprintf("/containers/%s/console", name)
op, _, err := client.RawOperation("POST", url, post, "")
if err != nil {
return SmartError(err)
}
- return ForwardedOperationResponse(&op.Operation)
+
+ opAPI := op.Get()
+ return ForwardedOperationResponse(&opAPI)
}
c, err := containerLoadByName(d.State(), name)
diff --git a/lxd/container_exec.go b/lxd/container_exec.go
index 3edcfc44f..0807c3cb7 100644
--- a/lxd/container_exec.go
+++ b/lxd/container_exec.go
@@ -349,13 +349,16 @@ func containerExecPost(d *Daemon, r *http.Request) Response {
if err != nil {
return SmartError(err)
}
+
if client != nil {
url := fmt.Sprintf("/containers/%s/exec", name)
op, _, err := client.RawOperation("POST", url, post, "")
if err != nil {
return SmartError(err)
}
- return ForwardedOperationResponse(&op.Operation)
+
+ opAPI := op.Get()
+ return ForwardedOperationResponse(&opAPI)
}
c, err := containerLoadByName(d.State(), name)
diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index ec5e664a4..9d2cb3f59 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -551,12 +551,15 @@ func containersPost(d *Daemon, r *http.Request) Response {
if err != nil {
return SmartError(err)
}
+
logger.Debugf("Forward container post request to %s", address)
op, err := client.UseTarget(targetNode).CreateContainer(req)
if err != nil {
return SmartError(err)
}
- return ForwardedOperationResponse(&op.Operation)
+
+ opAPI := op.Get()
+ return ForwardedOperationResponse(&opAPI)
}
}
diff --git a/lxd/main_init.go b/lxd/main_init.go
index 3c043e77a..28f63bbd4 100644
--- a/lxd/main_init.go
+++ b/lxd/main_init.go
@@ -572,7 +572,7 @@ func (cmd *CmdInit) initConfig(client lxd.ContainerServer, config map[string]int
// Turn on clustering.
func (cmd *CmdInit) initCluster(client lxd.ContainerServer, put api.ClusterPut, password string) (reverter, error) {
var reverter func() error
- var op *lxd.Operation
+ var op lxd.Operation
var err error
if put.ClusterAddress == "" {
op, err = client.UpdateCluster(put, "")
More information about the lxc-devel
mailing list