[lxc-devel] [lxd/master] Bugfixes and tweaks to new client library
stgraber on Github
lxc-bot at linuxcontainers.org
Tue May 30 05:39:17 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/20170530/aba60fbb/attachment.bin>
-------------- next part --------------
From baf4204563d0095cb08b9cc64e913df4f7099b33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 26 May 2017 23:11:42 -0400
Subject: [PATCH 1/6] client: Improve error on image 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/lxd_images.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/lxd_images.go b/client/lxd_images.go
index 1abf5f7a4..641f000c2 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -467,7 +467,7 @@ func (r *ProtocolLXD) tryCopyImage(target ContainerServer, req api.ImagesPost, u
}
if !success {
- rop.err = fmt.Errorf("%s", strings.Join(errors, "\n"))
+ rop.err = fmt.Errorf("Failed remote image download:\n - %s", strings.Join(errors, "\n - "))
}
close(rop.chDone)
From 2e43489b4c149a9fef043e40d211e7492af2c4d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 29 May 2017 16:39:07 -0400
Subject: [PATCH 2/6] client: Add image_create_aliases backward compat
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_images.go | 33 +++++++++++++++++++++++++++++++++
client/operations.go | 27 +++++++++++++++++++++------
client/simplestreams_images.go | 36 +++++++++++++++++++++++++++++++++++-
3 files changed, 89 insertions(+), 7 deletions(-)
diff --git a/client/lxd_images.go b/client/lxd_images.go
index 641f000c2..eb67ee268 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -437,6 +437,39 @@ func (r *ProtocolLXD) tryCopyImage(target ContainerServer, req api.ImagesPost, u
chDone: make(chan bool),
}
+ // For older servers, apply the aliases after copy
+ if !target.HasExtension("image_create_aliases") && req.Aliases != nil {
+ rop.chPost = make(chan bool)
+
+ go func() {
+ defer close(rop.chPost)
+
+ // Wait for the main operation to finish
+ <-rop.chDone
+ if rop.err != nil {
+ return
+ }
+
+ // Get the operation data
+ op, err := rop.GetTarget()
+ if err != nil {
+ return
+ }
+
+ // Extract the fingerprint
+ fingerprint := op.Metadata["fingerprint"].(string)
+
+ // Add the aliases
+ for _, entry := range req.Aliases {
+ alias := api.ImageAliasesPost{}
+ alias.Name = entry.Name
+ alias.Target = fingerprint
+
+ target.CreateImageAlias(alias)
+ }
+ }()
+ }
+
// Forward targetOp to remote op
go func() {
success := false
diff --git a/client/operations.go b/client/operations.go
index 6520556cb..ec092644c 100644
--- a/client/operations.go
+++ b/client/operations.go
@@ -232,15 +232,10 @@ type RemoteOperation struct {
handlers []func(api.Operation)
chDone chan bool
+ chPost chan bool
err error
}
-// Wait lets you wait until the operation reaches a final state
-func (op *RemoteOperation) Wait() error {
- <-op.chDone
- return op.err
-}
-
// AddHandler adds a function to be called whenever an event is received
func (op *RemoteOperation) AddHandler(function func(api.Operation)) (*EventTarget, error) {
var err error
@@ -265,3 +260,23 @@ func (op *RemoteOperation) AddHandler(function func(api.Operation)) (*EventTarge
return target, nil
}
+
+// GetTarget returns the target operation
+func (op *RemoteOperation) GetTarget() (*api.Operation, error) {
+ if op.targetOp == nil {
+ return nil, fmt.Errorf("No associated target operation")
+ }
+
+ return &op.targetOp.Operation, nil
+}
+
+// Wait lets you wait until the operation reaches a final state
+func (op *RemoteOperation) Wait() error {
+ <-op.chDone
+
+ if op.chPost != nil {
+ <-op.chPost
+ }
+
+ return op.err
+}
diff --git a/client/simplestreams_images.go b/client/simplestreams_images.go
index 3d9b7ecef..970c308a0 100644
--- a/client/simplestreams_images.go
+++ b/client/simplestreams_images.go
@@ -2,8 +2,9 @@ package lxd
import (
"fmt"
- "github.com/lxc/lxd/shared/api"
"strings"
+
+ "github.com/lxc/lxd/shared/api"
)
// Image handling functions
@@ -183,6 +184,39 @@ func (r *ProtocolSimpleStreams) CopyImage(image api.Image, target ContainerServe
chDone: make(chan bool),
}
+ // For older servers, apply the aliases after copy
+ if !target.HasExtension("image_create_aliases") && req.Aliases != nil {
+ rop.chPost = make(chan bool)
+
+ go func() {
+ defer close(rop.chPost)
+
+ // Wait for the main operation to finish
+ <-rop.chDone
+ if rop.err != nil {
+ return
+ }
+
+ // Get the operation data
+ op, err := rop.GetTarget()
+ if err != nil {
+ return
+ }
+
+ // Extract the fingerprint
+ fingerprint := op.Metadata["fingerprint"].(string)
+
+ // Add the aliases
+ for _, entry := range req.Aliases {
+ alias := api.ImageAliasesPost{}
+ alias.Name = entry.Name
+ alias.Target = fingerprint
+
+ target.CreateImageAlias(alias)
+ }
+ }()
+ }
+
// Forward targetOp to remote op
go func() {
rop.err = rop.targetOp.Wait()
From 5b6010e06a34596e7a9f47bc78f415ac8f50279d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 29 May 2017 18:56:26 -0400
Subject: [PATCH 3/6] client: Move CopyImage to the target server
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This avoids a bunch of duplication and better aligns with what we'll do
for CreateFromImage and CopyContainer.
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
client/interfaces.go | 21 ++++++++--
client/lxd.go | 45 ++++++++++++----------
client/lxd_images.go | 36 ++++++++++-------
client/simplestreams.go | 10 +++++
client/simplestreams_images.go | 87 +++---------------------------------------
test/lxd-benchmark/main.go | 2 +-
6 files changed, 81 insertions(+), 120 deletions(-)
diff --git a/client/interfaces.go b/client/interfaces.go
index f11adce0e..9ddc6cc93 100644
--- a/client/interfaces.go
+++ b/client/interfaces.go
@@ -8,14 +8,22 @@ import (
"github.com/lxc/lxd/shared/api"
)
+// The Server type represents a generic read-only server.
+type Server interface {
+ GetConnectionInfo() (info *ConnectionInfo, err error)
+}
+
// The ImageServer type represents a read-only image server.
type ImageServer interface {
+ Server
+
// Image handling functions
GetImages() (images []api.Image, err error)
GetImageFingerprints() (fingerprints []string, err error)
GetImage(fingerprint string) (image *api.Image, ETag string, err error)
GetImageFile(fingerprint string, req ImageFileRequest) (resp *ImageFileResponse, err error)
+ GetImageSecret(fingerprint string) (secret string, err error)
GetPrivateImage(fingerprint string, secret string) (image *api.Image, ETag string, err error)
GetPrivateImageFile(fingerprint string, secret string, req ImageFileRequest) (resp *ImageFileResponse, err error)
@@ -24,12 +32,12 @@ type ImageServer interface {
GetImageAliasNames() (names []string, err error)
GetImageAlias(name string) (alias *api.ImageAliasesEntry, ETag string, err error)
-
- CopyImage(image api.Image, target ContainerServer, args *ImageCopyArgs) (op *RemoteOperation, err error)
}
// The ContainerServer type represents a full featured LXD server.
type ContainerServer interface {
+ ImageServer
+
// Server functions
GetServer() (server *api.Server, ETag string, err error)
UpdateServer(server api.ServerPut, ETag string) (err error)
@@ -78,8 +86,8 @@ type ContainerServer interface {
GetEvents() (listener *EventListener, err error)
// Image functions
- ImageServer
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)
@@ -133,6 +141,13 @@ type ContainerServer interface {
RawWebsocket(path string) (conn *websocket.Conn, err error)
}
+// The ConnectionInfo struct represents general information for a connection
+type ConnectionInfo struct {
+ Addresses []string
+ Certificate string
+ Protocol string
+}
+
// The ProgressData struct represents new progress information on an operation
type ProgressData struct {
// Preferred string repreentation of progress (always set)
diff --git a/client/lxd.go b/client/lxd.go
index 69bd4e8e9..4c02eabe4 100644
--- a/client/lxd.go
+++ b/client/lxd.go
@@ -29,6 +29,30 @@ type ProtocolLXD struct {
httpUserAgent string
}
+// GetConnectionInfo returns the basic connection information used to interact with the server
+func (r *ProtocolLXD) GetConnectionInfo() (*ConnectionInfo, error) {
+ info := ConnectionInfo{}
+ info.Certificate = r.httpCertificate
+ info.Protocol = "lxd"
+
+ urls := []string{}
+ if len(r.server.Environment.Addresses) > 0 {
+ if r.httpProtocol == "https" {
+ urls = append(urls, r.httpHost)
+ }
+
+ for _, addr := range r.server.Environment.Addresses {
+ url := fmt.Sprintf("https://%s", addr)
+ if !shared.StringInSlice(url, urls) {
+ urls = append(urls, url)
+ }
+ }
+ }
+ info.Addresses = urls
+
+ return &info, nil
+}
+
// RawQuery allows directly querying the LXD API
//
// This should only be used by internal LXD tools.
@@ -223,24 +247,3 @@ func (r *ProtocolLXD) websocket(path string) (*websocket.Conn, error) {
return r.rawWebsocket(url)
}
-
-// getServerUrls returns a prioritized list of potential URLs for the server
-func (r *ProtocolLXD) getServerUrls() ([]string, error) {
- if len(r.server.Environment.Addresses) == 0 {
- return nil, fmt.Errorf("Source server isn't reachable over the network")
- }
-
- urls := []string{}
- if r.httpProtocol == "https" {
- urls = append(urls, r.httpHost)
- }
-
- for _, addr := range r.server.Environment.Addresses {
- url := fmt.Sprintf("https://%s", addr)
- if !shared.StringInSlice(url, urls) {
- urls = append(urls, url)
- }
- }
-
- return urls, nil
-}
diff --git a/client/lxd_images.go b/client/lxd_images.go
index eb67ee268..90ddfc6fe 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -62,6 +62,16 @@ func (r *ProtocolLXD) GetImageFile(fingerprint string, req ImageFileRequest) (*I
return r.GetPrivateImageFile(fingerprint, "", req)
}
+// GetImageSecret is a helper around CreateImageSecret that returns a secret for the image
+func (r *ProtocolLXD) GetImageSecret(fingerprint string) (string, error) {
+ op, err := r.CreateImageSecret(fingerprint)
+ if err != nil {
+ return "", err
+ }
+
+ return op.Metadata["secret"].(string), nil
+}
+
// GetPrivateImage is similar to GetImage but allows passing a secret download token
func (r *ProtocolLXD) GetPrivateImage(fingerprint string, secret string) (*api.Image, string, error) {
image := api.Image{}
@@ -432,13 +442,13 @@ 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(target ContainerServer, req api.ImagesPost, urls []string) (*RemoteOperation, error) {
+func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (*RemoteOperation, error) {
rop := RemoteOperation{
chDone: make(chan bool),
}
// For older servers, apply the aliases after copy
- if !target.HasExtension("image_create_aliases") && req.Aliases != nil {
+ if !r.HasExtension("image_create_aliases") && req.Aliases != nil {
rop.chPost = make(chan bool)
go func() {
@@ -465,7 +475,7 @@ func (r *ProtocolLXD) tryCopyImage(target ContainerServer, req api.ImagesPost, u
alias.Name = entry.Name
alias.Target = fingerprint
- target.CreateImageAlias(alias)
+ r.CreateImageAlias(alias)
}
}()
}
@@ -477,7 +487,7 @@ func (r *ProtocolLXD) tryCopyImage(target ContainerServer, req api.ImagesPost, u
for _, serverURL := range urls {
req.Source.Server = serverURL
- op, err := target.CreateImage(req, nil)
+ op, err := r.CreateImage(req, nil)
if err != nil {
errors = append(errors, fmt.Sprintf("%s: %v", serverURL, err))
continue
@@ -509,15 +519,15 @@ func (r *ProtocolLXD) tryCopyImage(target ContainerServer, req api.ImagesPost, u
return &rop, nil
}
-// CopyImage copies an existing image to a remote server. Additional options can be passed using ImageCopyArgs
-func (r *ProtocolLXD) CopyImage(image api.Image, target ContainerServer, args *ImageCopyArgs) (*RemoteOperation, error) {
+// 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) {
// Sanity checks
- if r == target {
+ if r == source {
return nil, fmt.Errorf("The source and target servers must be different")
}
// Get a list of addresses for the source server
- urls, err := r.getServerUrls()
+ info, err := source.GetConnectionInfo()
if err != nil {
return nil, err
}
@@ -526,8 +536,8 @@ func (r *ProtocolLXD) CopyImage(image api.Image, target ContainerServer, args *I
req := api.ImagesPost{
Source: &api.ImagesPostSource{
ImageSource: api.ImageSource{
- Certificate: r.httpCertificate,
- Protocol: "lxd",
+ Certificate: info.Certificate,
+ Protocol: info.Protocol,
},
Fingerprint: image.Fingerprint,
Mode: "pull",
@@ -537,12 +547,12 @@ func (r *ProtocolLXD) CopyImage(image api.Image, target ContainerServer, args *I
// Generate secret token if needed
if !image.Public {
- op, err := r.CreateImageSecret(image.Fingerprint)
+ secret, err := source.GetImageSecret(image.Fingerprint)
if err != nil {
return nil, err
}
- req.Source.Secret = op.Metadata["secret"].(string)
+ req.Source.Secret = secret
}
// Process the arguments
@@ -559,7 +569,7 @@ func (r *ProtocolLXD) CopyImage(image api.Image, target ContainerServer, args *I
}
}
- return r.tryCopyImage(target, req, urls)
+ return r.tryCopyImage(req, info.Addresses)
}
// UpdateImage updates the image definition
diff --git a/client/simplestreams.go b/client/simplestreams.go
index a69a2ea8d..79fef42ae 100644
--- a/client/simplestreams.go
+++ b/client/simplestreams.go
@@ -15,3 +15,13 @@ type ProtocolSimpleStreams struct {
httpUserAgent string
httpCertificate string
}
+
+// GetConnectionInfo returns the basic connection information used to interact with the server
+func (r *ProtocolSimpleStreams) GetConnectionInfo() (*ConnectionInfo, error) {
+ info := ConnectionInfo{}
+ info.Addresses = []string{r.httpHost}
+ info.Certificate = r.httpCertificate
+ info.Protocol = "simplestreams"
+
+ return &info, nil
+}
diff --git a/client/simplestreams_images.go b/client/simplestreams_images.go
index 970c308a0..d84f8ed09 100644
--- a/client/simplestreams_images.go
+++ b/client/simplestreams_images.go
@@ -102,6 +102,11 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
return &resp, nil
}
+// GetImageSecret isn't relevant for the simplestreams protocol
+func (r *ProtocolSimpleStreams) GetImageSecret(fingerprint string) (string, error) {
+ return "", fmt.Errorf("Private images aren't supported by the simplestreams protocol")
+}
+
// GetPrivateImage isn't relevant for the simplestreams protocol
func (r *ProtocolSimpleStreams) GetPrivateImage(fingerprint string, secret string) (*api.Image, string, error) {
return nil, "", fmt.Errorf("Private images aren't supported by the simplestreams protocol")
@@ -143,85 +148,3 @@ func (r *ProtocolSimpleStreams) GetImageAlias(name string) (*api.ImageAliasesEnt
return alias, "", err
}
-
-// CopyImage copies an existing image to a remote server. Additional options can be passed using ImageCopyArgs
-func (r *ProtocolSimpleStreams) CopyImage(image api.Image, target ContainerServer, args *ImageCopyArgs) (*RemoteOperation, error) {
- // Prepare the copy request
- req := api.ImagesPost{
- Source: &api.ImagesPostSource{
- ImageSource: api.ImageSource{
- Certificate: r.httpCertificate,
- Protocol: "simplestreams",
- Server: r.httpHost,
- },
- Fingerprint: image.Fingerprint,
- Mode: "pull",
- Type: "image",
- },
- }
-
- // Process the arguments
- if args != nil {
- req.Aliases = args.Aliases
- req.AutoUpdate = args.AutoUpdate
- req.Public = args.Public
-
- if args.CopyAliases {
- req.Aliases = image.Aliases
- if args.Aliases != nil {
- req.Aliases = append(req.Aliases, args.Aliases...)
- }
- }
- }
-
- op, err := target.CreateImage(req, nil)
- if err != nil {
- return nil, err
- }
-
- rop := RemoteOperation{
- targetOp: op,
- chDone: make(chan bool),
- }
-
- // For older servers, apply the aliases after copy
- if !target.HasExtension("image_create_aliases") && req.Aliases != nil {
- rop.chPost = make(chan bool)
-
- go func() {
- defer close(rop.chPost)
-
- // Wait for the main operation to finish
- <-rop.chDone
- if rop.err != nil {
- return
- }
-
- // Get the operation data
- op, err := rop.GetTarget()
- if err != nil {
- return
- }
-
- // Extract the fingerprint
- fingerprint := op.Metadata["fingerprint"].(string)
-
- // Add the aliases
- for _, entry := range req.Aliases {
- alias := api.ImageAliasesPost{}
- alias.Name = entry.Name
- alias.Target = fingerprint
-
- target.CreateImageAlias(alias)
- }
- }()
- }
-
- // Forward targetOp to remote op
- go func() {
- rop.err = rop.targetOp.Wait()
- close(rop.chDone)
- }()
-
- return &rop, nil
-}
diff --git a/test/lxd-benchmark/main.go b/test/lxd-benchmark/main.go
index 686146249..9c8eb3c11 100644
--- a/test/lxd-benchmark/main.go
+++ b/test/lxd-benchmark/main.go
@@ -168,7 +168,7 @@ func spawnContainers(c lxd.ContainerServer, count int, image string, privileged
return err
}
- op, err := d.CopyImage(*image, c, nil)
+ op, err := c.CopyImage(d, *image, nil)
if err != nil {
logf(fmt.Sprintf("Failed to import image: %s", err))
return err
From a79b763480f0359076cda4362579185a877464fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 29 May 2017 23:58:57 -0400
Subject: [PATCH 4/6] client: Add CreateContainerFromImage function
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 | 1 +
client/lxd_containers.go | 107 +++++++++++++++++++++++++++++++++++++++++++++++
client/lxd_images.go | 2 +-
3 files changed, 109 insertions(+), 1 deletion(-)
diff --git a/client/interfaces.go b/client/interfaces.go
index 9ddc6cc93..e5541564d 100644
--- a/client/interfaces.go
+++ b/client/interfaces.go
@@ -56,6 +56,7 @@ type ContainerServer interface {
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)
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)
diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index 06b9add22..ead43a04a 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -78,6 +78,113 @@ func (r *ProtocolLXD) CreateContainer(container api.ContainersPost) (*Operation,
return op, nil
}
+func (r *ProtocolLXD) tryCreateContainerFromImage(req api.ContainersPost, urls []string) (*RemoteOperation, error) {
+ rop := RemoteOperation{
+ chDone: make(chan bool),
+ }
+
+ // Forward targetOp to remote op
+ go func() {
+ success := false
+ errors := []string{}
+ for _, serverURL := range urls {
+ req.Source.Server = serverURL
+
+ op, err := r.CreateContainer(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 creation:\n - %s", strings.Join(errors, "\n - "))
+ }
+
+ close(rop.chDone)
+ }()
+
+ return &rop, nil
+}
+
+// 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) {
+ // Set the minimal source fields
+ req.Source.Type = "image"
+
+ // Optimization for the local image case
+ if r == source {
+ // Always use fingerprints for local case
+ req.Source.Fingerprint = image.Fingerprint
+ req.Source.Alias = ""
+
+ op, err := r.CreateContainer(req)
+ if err != nil {
+ return nil, err
+ }
+
+ rop := RemoteOperation{
+ targetOp: op,
+ chDone: make(chan bool),
+ }
+
+ // Forward targetOp to remote op
+ go func() {
+ rop.err = rop.targetOp.Wait()
+ close(rop.chDone)
+ }()
+
+ return &rop, nil
+ }
+
+ // Minimal source fields for remote image
+ req.Source.Mode = "pull"
+
+ // If we have an alias and the image is public, use that
+ if req.Source.Alias != "" && image.Public {
+ req.Source.Fingerprint = ""
+ } else {
+ req.Source.Fingerprint = image.Fingerprint
+ req.Source.Alias = ""
+ }
+
+ // Get source server connection information
+ info, err := source.GetConnectionInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ req.Source.Protocol = info.Protocol
+ req.Source.Certificate = info.Certificate
+
+ // Generate secret token if needed
+ if !image.Public {
+ secret, err := source.GetImageSecret(image.Fingerprint)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Source.Secret = secret
+ }
+
+ return r.tryCreateContainerFromImage(req, info.Addresses)
+}
+
// UpdateContainer updates the container definition
func (r *ProtocolLXD) UpdateContainer(name string, container api.ContainerPut, ETag string) (*Operation, error) {
// Send the request
diff --git a/client/lxd_images.go b/client/lxd_images.go
index 90ddfc6fe..f9065e3e5 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -526,7 +526,7 @@ func (r *ProtocolLXD) CopyImage(source ImageServer, image api.Image, args *Image
return nil, fmt.Errorf("The source and target servers must be different")
}
- // Get a list of addresses for the source server
+ // Get source server connection information
info, err := source.GetConnectionInfo()
if err != nil {
return nil, err
From 76fadef65d8791894c640ecceb1275a496bda50b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 30 May 2017 00:27:40 -0400
Subject: [PATCH 5/6] tests: Test suites use space indent
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/image_auto_update.sh | 6 +++---
test/suites/init_preseed.sh | 16 ++++++++--------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/test/suites/image_auto_update.sh b/test/suites/image_auto_update.sh
index 6cfda3650..4e6007803 100644
--- a/test/suites/image_auto_update.sh
+++ b/test/suites/image_auto_update.sh
@@ -49,9 +49,9 @@ test_image_auto_update() {
retries=10
while [ "${retries}" != "0" ]; do
if lxc image info "${fp1}" > /dev/null 2>&1; then
- sleep 2
- retries=$((retries-1))
- continue
+ sleep 2
+ retries=$((retries-1))
+ continue
fi
break
done
diff --git a/test/suites/init_preseed.sh b/test/suites/init_preseed.sh
index b218050f7..b1499cf64 100644
--- a/test/suites/init_preseed.sh
+++ b/test/suites/init_preseed.sh
@@ -13,14 +13,14 @@ test_init_preseed() {
# In case we're running against the ZFS backend, let's test
# creating a zfs storage pool, otherwise just use dir.
if [ "$lxd_backend" = "zfs" ]; then
- configure_loop_device loop_file_4 loop_device_4
+ configure_loop_device loop_file_4 loop_device_4
# shellcheck disable=SC2154
- zpool create "lxdtest-$(basename "${LXD_DIR}")-preseed-pool" "${loop_device_4}" -f -m none -O compression=on
- driver="zfs"
- source="lxdtest-$(basename "${LXD_DIR}")-preseed-pool"
+ zpool create "lxdtest-$(basename "${LXD_DIR}")-preseed-pool" "${loop_device_4}" -f -m none -O compression=on
+ driver="zfs"
+ source="lxdtest-$(basename "${LXD_DIR}")-preseed-pool"
else
- driver="dir"
- source=""
+ driver="dir"
+ source=""
fi
cat <<EOF | lxd init --preseed
@@ -73,8 +73,8 @@ EOF
lxc storage delete data
if [ "$lxd_backend" = "zfs" ]; then
- # shellcheck disable=SC2154
- deconfigure_loop_device "${loop_file_4}" "${loop_device_4}"
+ # shellcheck disable=SC2154
+ deconfigure_loop_device "${loop_file_4}" "${loop_device_4}"
fi
)
kill_lxd "${LXD_INIT_DIR}"
From 6aaa1c8b6e3ebe14f2a952436d9cafe120d4debb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 30 May 2017 01:07:44 -0400
Subject: [PATCH 6/6] images: Fix potential double unlock
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>
---
lxd/daemon_images.go | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lxd/daemon_images.go b/lxd/daemon_images.go
index e5b223251..b2023d42f 100644
--- a/lxd/daemon_images.go
+++ b/lxd/daemon_images.go
@@ -296,9 +296,12 @@ func (d *Daemon) ImageDownload(op *operation, server string, protocol string, ce
// Other download succeeded, we're done
return imgInfo, nil
}
+ } else {
+ imagesDownloadingLock.Unlock()
}
// Add the download to the queue
+ imagesDownloadingLock.Lock()
imagesDownloading[fp] = make(chan bool)
imagesDownloadingLock.Unlock()
More information about the lxc-devel
mailing list