[lxc-devel] [lxd/master] Support downloading through host LXD

stgraber on Github lxc-bot at linuxcontainers.org
Wed Jul 25 22:25:29 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 716 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180725/77ddb28f/attachment.bin>
-------------- next part --------------
From 4b99727e9175a9cbd1f9523fc9c494a9eae94074 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 25 Jul 2018 18:06:49 -0400
Subject: [PATCH 1/2] client: Split LXD download code into own 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/lxd.go            |  4 ++--
 client/lxd_containers.go | 14 +++++++-------
 client/lxd_images.go     | 20 ++++++++++++--------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/client/lxd.go b/client/lxd.go
index 4b386cd30..3f61c84f7 100644
--- a/client/lxd.go
+++ b/client/lxd.go
@@ -121,7 +121,7 @@ func (r *ProtocolLXD) RawOperation(method string, path string, data interface{},
 }
 
 // Internal functions
-func (r *ProtocolLXD) parseResponse(resp *http.Response) (*api.Response, string, error) {
+func lxdParseResponse(resp *http.Response) (*api.Response, string, error) {
 	// Get the ETag
 	etag := resp.Header.Get("ETag")
 
@@ -221,7 +221,7 @@ func (r *ProtocolLXD) rawQuery(method string, url string, data interface{}, ETag
 	}
 	defer resp.Body.Close()
 
-	return r.parseResponse(resp)
+	return lxdParseResponse(resp)
 }
 
 func (r *ProtocolLXD) query(method string, path string, data interface{}, ETag string) (*api.Response, string, error) {
diff --git a/client/lxd_containers.go b/client/lxd_containers.go
index 3eaa2d998..a7df5ba4c 100644
--- a/client/lxd_containers.go
+++ b/client/lxd_containers.go
@@ -762,7 +762,7 @@ func (r *ProtocolLXD) GetContainerFile(containerName string, path string) (io.Re
 
 	// Check the return value for a cleaner error
 	if resp.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(resp)
+		_, _, err := lxdParseResponse(resp)
 		if err != nil {
 			return nil, nil, err
 		}
@@ -861,7 +861,7 @@ func (r *ProtocolLXD) CreateContainerFile(containerName string, path string, arg
 	}
 
 	// Check the return value for a cleaner error
-	_, _, err = r.parseResponse(resp)
+	_, _, err = lxdParseResponse(resp)
 	if err != nil {
 		return err
 	}
@@ -1287,7 +1287,7 @@ func (r *ProtocolLXD) GetContainerLogfile(name string, filename string) (io.Read
 
 	// Check the return value for a cleaner error
 	if resp.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(resp)
+		_, _, err := lxdParseResponse(resp)
 		if err != nil {
 			return nil, err
 		}
@@ -1381,7 +1381,7 @@ func (r *ProtocolLXD) GetContainerTemplateFile(containerName string, templateNam
 
 	// Check the return value for a cleaner error
 	if resp.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(resp)
+		_, _, err := lxdParseResponse(resp)
 		if err != nil {
 			return nil, err
 		}
@@ -1421,7 +1421,7 @@ func (r *ProtocolLXD) setContainerTemplateFile(containerName string, templateNam
 	resp, err := r.http.Do(req)
 	// Check the return value for a cleaner error
 	if resp.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(resp)
+		_, _, err := lxdParseResponse(resp)
 		if err != nil {
 			return err
 		}
@@ -1536,7 +1536,7 @@ func (r *ProtocolLXD) GetContainerConsoleLog(containerName string, args *Contain
 
 	// Check the return value for a cleaner error
 	if resp.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(resp)
+		_, _, err := lxdParseResponse(resp)
 		if err != nil {
 			return nil, err
 		}
@@ -1695,7 +1695,7 @@ func (r *ProtocolLXD) GetContainerBackupFile(containerName string, name string,
 	defer close(doneCh)
 
 	if response.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(response)
+		_, _, err := lxdParseResponse(response)
 		if err != nil {
 			return nil, err
 		}
diff --git a/client/lxd_images.go b/client/lxd_images.go
index 9eb7928c5..e3c12f5f4 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -99,27 +99,31 @@ func (r *ProtocolLXD) GetPrivateImageFile(fingerprint string, secret string, req
 		return nil, fmt.Errorf("No file requested")
 	}
 
-	// Prepare the response
-	resp := ImageFileResponse{}
-
 	// Build the URL
 	uri := fmt.Sprintf("%s/1.0/images/%s/export", r.httpHost, url.QueryEscape(fingerprint))
 	if secret != "" {
 		uri = fmt.Sprintf("%s?secret=%s", uri, url.QueryEscape(secret))
 	}
 
+	return lxdDownloadImage(fingerprint, uri, r.httpUserAgent, r.http, req)
+}
+
+func lxdDownloadImage(fingerprint string, uri string, userAgent string, client *http.Client, req ImageFileRequest) (*ImageFileResponse, error) {
+	// Prepare the response
+	resp := ImageFileResponse{}
+
 	// Prepare the download request
 	request, err := http.NewRequest("GET", uri, nil)
 	if err != nil {
 		return nil, err
 	}
 
-	if r.httpUserAgent != "" {
-		request.Header.Set("User-Agent", r.httpUserAgent)
+	if userAgent != "" {
+		request.Header.Set("User-Agent", userAgent)
 	}
 
 	// Start the request
-	response, doneCh, err := cancel.CancelableDownload(req.Canceler, r.http, request)
+	response, doneCh, err := cancel.CancelableDownload(req.Canceler, client, request)
 	if err != nil {
 		return nil, err
 	}
@@ -127,7 +131,7 @@ func (r *ProtocolLXD) GetPrivateImageFile(fingerprint string, secret string, req
 	defer close(doneCh)
 
 	if response.StatusCode != http.StatusOK {
-		_, _, err := r.parseResponse(response)
+		_, _, err := lxdParseResponse(response)
 		if err != nil {
 			return nil, err
 		}
@@ -412,7 +416,7 @@ func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (
 	defer resp.Body.Close()
 
 	// Handle errors
-	response, _, err := r.parseResponse(resp)
+	response, _, err := lxdParseResponse(resp)
 	if err != nil {
 		return nil, err
 	}

From f80ef7e9c5a935b7f1cb92fa3545567f2ee54fe3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 25 Jul 2018 18:23:02 -0400
Subject: [PATCH 2/2] client: Attempt to fetch through devlxd
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           | 14 ++++++++++++++
 client/simplestreams_images.go | 15 +++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/client/lxd_images.go b/client/lxd_images.go
index e3c12f5f4..9927565df 100644
--- a/client/lxd_images.go
+++ b/client/lxd_images.go
@@ -99,6 +99,20 @@ func (r *ProtocolLXD) GetPrivateImageFile(fingerprint string, secret string, req
 		return nil, fmt.Errorf("No file requested")
 	}
 
+	// Attempt to download from host
+	if secret == "" && shared.PathExists("/dev/lxd/sock") && os.Geteuid() == 0 {
+		unixUri := fmt.Sprintf("http://unix.socket/1.0/images/%s/export", url.QueryEscape(fingerprint))
+
+		// Setup the HTTP client
+		devlxdHttp, err := unixHTTPClient(nil, "/dev/lxd/sock")
+		if err == nil {
+			resp, err := lxdDownloadImage(fingerprint, unixUri, r.httpUserAgent, devlxdHttp, req)
+			if err == nil {
+				return resp, nil
+			}
+		}
+	}
+
 	// Build the URL
 	uri := fmt.Sprintf("%s/1.0/images/%s/export", r.httpHost, url.QueryEscape(fingerprint))
 	if secret != "" {
diff --git a/client/simplestreams_images.go b/client/simplestreams_images.go
index 065bedabe..b9f6bf65a 100644
--- a/client/simplestreams_images.go
+++ b/client/simplestreams_images.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"net/url"
 	"os"
 	"os/exec"
 	"strings"
@@ -53,6 +54,20 @@ func (r *ProtocolSimpleStreams) GetImageFile(fingerprint string, req ImageFileRe
 		return nil, fmt.Errorf("No file requested")
 	}
 
+	// Attempt to download from host
+	if shared.PathExists("/dev/lxd/sock") && os.Geteuid() == 0 {
+		unixUri := fmt.Sprintf("http://unix.socket/1.0/images/%s/export", url.QueryEscape(fingerprint))
+
+		// Setup the HTTP client
+		devlxdHttp, err := unixHTTPClient(nil, "/dev/lxd/sock")
+		if err == nil {
+			resp, err := lxdDownloadImage(fingerprint, unixUri, r.httpUserAgent, devlxdHttp, req)
+			if err == nil {
+				return resp, nil
+			}
+		}
+	}
+
 	// Get the file list
 	files, err := r.ssClient.GetFiles(fingerprint)
 	if err != nil {


More information about the lxc-devel mailing list