The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3672

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
This branch moves the Daemon.httpClient method (which really depends
only on the Daemon.proxy attribute) into a standalone function. The
goal is to progressively streamline the Daemon structure and factor
out ancillary code, to eventually be able to improve unit-testability
of both Deamon itself and its main consumer, the api*.go files.

While at it, the util.go file has also been moved to the util/
package, and split into two (encoding.go, and kernel.go).

Signed-off-by: Free Ekanayaka <[email protected]>
From 1fe9822d360185d80244c513eebac8443a5aa93a Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <[email protected]>
Date: Wed, 16 Aug 2017 22:39:26 +0000
Subject: [PATCH] Extract Daemon.httpClient into a standalone HTTPClient
 function

This branch moves the Daemon.httpClient method (which really depends
only on the Daemon.proxy attribute) into a standalone function. The
goal is to progressively streamline the Daemon structure and factor
out ancillary code, to eventually be able to improve unit-testability
of both Deamon itself and its main consumer, the api*.go files.

While at it, the util.go file has also been moved to the util/
package, and split into two (encoding.go, and kernel.go).

Signed-off-by: Free Ekanayaka <[email protected]>
---
 lxd/api_1.0.go                    |  5 ++--
 lxd/certificates.go               |  5 ++--
 lxd/container_instance_types.go   |  3 +-
 lxd/container_lxc.go              |  5 ++--
 lxd/container_patch.go            |  3 +-
 lxd/container_put.go              |  3 +-
 lxd/daemon.go                     | 44 -----------------------------
 lxd/daemon_images.go              |  3 +-
 lxd/devlxd.go                     |  3 +-
 lxd/images.go                     | 11 ++++----
 lxd/networks.go                   |  5 ++--
 lxd/profiles.go                   |  5 ++--
 lxd/response.go                   |  7 +++--
 lxd/storage_pools.go              |  5 ++--
 lxd/storage_volumes.go            |  5 ++--
 lxd/storage_zfs.go                |  3 +-
 lxd/{util.go => util/encoding.go} | 19 ++++---------
 lxd/util/http.go                  | 58 +++++++++++++++++++++++++++++++++++++++
 lxd/util/kernel.go                | 18 ++++++++++++
 19 files changed, 124 insertions(+), 86 deletions(-)
 rename lxd/{util.go => util/encoding.go} (64%)
 create mode 100644 lxd/util/http.go
 create mode 100644 lxd/util/kernel.go

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index 58668a089..b29ccf148 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -11,6 +11,7 @@ import (
        "gopkg.in/lxc/go-lxc.v2"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/osarch"
@@ -248,7 +249,7 @@ func api10Put(d *Daemon, r *http.Request) Response {
                return SmartError(err)
        }
 
-       err = etagCheck(r, daemonConfigRender())
+       err = util.EtagCheck(r, daemonConfigRender())
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -267,7 +268,7 @@ func api10Patch(d *Daemon, r *http.Request) Response {
                return SmartError(err)
        }
 
-       err = etagCheck(r, daemonConfigRender())
+       err = util.EtagCheck(r, daemonConfigRender())
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/certificates.go b/lxd/certificates.go
index 008c93c27..d15f0fb53 100644
--- a/lxd/certificates.go
+++ b/lxd/certificates.go
@@ -12,6 +12,7 @@ import (
        "github.com/gorilla/mux"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -193,7 +194,7 @@ func certificateFingerprintPut(d *Daemon, r *http.Request) 
Response {
        }
        fingerprint = oldEntry.Fingerprint
 
-       err = etagCheck(r, oldEntry)
+       err = util.EtagCheck(r, oldEntry)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -215,7 +216,7 @@ func certificateFingerprintPatch(d *Daemon, r 
*http.Request) Response {
        }
        fingerprint = oldEntry.Fingerprint
 
-       err = etagCheck(r, oldEntry)
+       err = util.EtagCheck(r, oldEntry)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/container_instance_types.go b/lxd/container_instance_types.go
index 77259e3bf..c5225b7f8 100644
--- a/lxd/container_instance_types.go
+++ b/lxd/container_instance_types.go
@@ -9,6 +9,7 @@ import (
 
        "gopkg.in/yaml.v2"
 
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/version"
@@ -67,7 +68,7 @@ func instanceRefreshTypes(d *Daemon) error {
        downloadParse := func(filename string, target interface{}) error {
                url := 
fmt.Sprintf("https://images.linuxcontainers.org/meta/instance-types/%s";, 
filename)
 
-               httpClient, err := d.httpClient("")
+               httpClient, err := util.HTTPClient("", d.proxy)
                if err != nil {
                        return err
                }
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 6e21c0be5..edac0c2e3 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -26,6 +26,7 @@ import (
 
        "github.com/lxc/lxd/lxd/db"
        "github.com/lxc/lxd/lxd/types"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -1627,7 +1628,7 @@ func (c *containerLXC) startCommon() (string, error) {
        if kernelModules != "" {
                for _, module := range strings.Split(kernelModules, ",") {
                        module = strings.TrimPrefix(module, " ")
-                       err := loadModule(module)
+                       err := util.LoadModule(module)
                        if err != nil {
                                return "", fmt.Errorf("Failed to load kernel 
module '%s': %s", module, err)
                        }
@@ -3487,7 +3488,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, 
userRequested bool) error {
                        } else if key == "linux.kernel_modules" && value != "" {
                                for _, module := range strings.Split(value, 
",") {
                                        module = strings.TrimPrefix(module, " ")
-                                       err := loadModule(module)
+                                       err := util.LoadModule(module)
                                        if err != nil {
                                                return fmt.Errorf("Failed to 
load kernel module '%s': %s", module, err)
                                        }
diff --git a/lxd/container_patch.go b/lxd/container_patch.go
index 02fd3a0aa..3d042163d 100644
--- a/lxd/container_patch.go
+++ b/lxd/container_patch.go
@@ -10,6 +10,7 @@ import (
        "github.com/gorilla/mux"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/osarch"
@@ -25,7 +26,7 @@ func containerPatch(d *Daemon, r *http.Request) Response {
 
        // Validate the ETag
        etag := []interface{}{c.Architecture(), c.LocalConfig(), 
c.LocalDevices(), c.IsEphemeral(), c.Profiles()}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/container_put.go b/lxd/container_put.go
index 84bc7b99f..351cce765 100644
--- a/lxd/container_put.go
+++ b/lxd/container_put.go
@@ -9,6 +9,7 @@ import (
        "github.com/gorilla/mux"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/osarch"
@@ -28,7 +29,7 @@ func containerPut(d *Daemon, r *http.Request) Response {
 
        // Validate the ETag
        etag := []interface{}{c.Architecture(), c.LocalConfig(), 
c.LocalDevices(), c.IsEphemeral(), c.Profiles()}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 186985219..bc728d098 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -6,7 +6,6 @@ import (
        "crypto/x509"
        "database/sql"
        "encoding/hex"
-       "encoding/pem"
        "fmt"
        "io"
        "io/ioutil"
@@ -107,49 +106,6 @@ type Command struct {
        patch         func(d *Daemon, r *http.Request) Response
 }
 
-func (d *Daemon) httpClient(certificate string) (*http.Client, error) {
-       var err error
-       var cert *x509.Certificate
-
-       if certificate != "" {
-               certBlock, _ := pem.Decode([]byte(certificate))
-               if certBlock == nil {
-                       return nil, fmt.Errorf("Invalid certificate")
-               }
-
-               cert, err = x509.ParseCertificate(certBlock.Bytes)
-               if err != nil {
-                       return nil, err
-               }
-       }
-
-       tlsConfig, err := shared.GetTLSConfig("", "", "", cert)
-       if err != nil {
-               return nil, err
-       }
-
-       tr := &http.Transport{
-               TLSClientConfig:   tlsConfig,
-               Dial:              shared.RFC3493Dialer,
-               Proxy:             d.proxy,
-               DisableKeepAlives: true,
-       }
-
-       myhttp := http.Client{
-               Transport: tr,
-       }
-
-       // Setup redirect policy
-       myhttp.CheckRedirect = func(req *http.Request, via []*http.Request) 
error {
-               // Replicate the headers
-               req.Header = via[len(via)-1].Header
-
-               return nil
-       }
-
-       return &myhttp, nil
-}
-
 func readMyCert() (string, string, error) {
        certf := shared.VarPath("server.crt")
        keyf := shared.VarPath("server.key")
diff --git a/lxd/daemon_images.go b/lxd/daemon_images.go
index 659bb0d1a..145e45ed5 100644
--- a/lxd/daemon_images.go
+++ b/lxd/daemon_images.go
@@ -16,6 +16,7 @@ import (
 
        "github.com/lxc/lxd/client"
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/cancel"
@@ -423,7 +424,7 @@ func (d *Daemon) ImageDownload(op *operation, server 
string, protocol string, ce
                }
        } else if protocol == "direct" {
                // Setup HTTP client
-               httpClient, err := d.httpClient(certificate)
+               httpClient, err := util.HTTPClient(certificate, d.proxy)
                if err != nil {
                        return nil, err
                }
diff --git a/lxd/devlxd.go b/lxd/devlxd.go
index 5dd17b454..68f2ca518 100644
--- a/lxd/devlxd.go
+++ b/lxd/devlxd.go
@@ -16,6 +16,7 @@ import (
        "github.com/gorilla/mux"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/logger"
        "github.com/lxc/lxd/shared/version"
@@ -119,7 +120,7 @@ func hoistReq(f func(container, *http.Request) 
*devLxdResponse, d *Daemon) func(
                        http.Error(w, fmt.Sprintf("%s", resp.content), 
resp.code)
                } else if resp.ctype == "json" {
                        w.Header().Set("Content-Type", "application/json")
-                       WriteJSON(w, resp.content)
+                       util.WriteJSON(w, resp.content, debug)
                } else {
                        w.Header().Set("Content-Type", 
"application/octet-stream")
                        fmt.Fprintf(w, resp.content.(string))
diff --git a/lxd/images.go b/lxd/images.go
index ce016c2cc..c9dc99ae7 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -23,6 +23,7 @@ import (
        "gopkg.in/yaml.v2"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -358,7 +359,7 @@ func imgPostURLInfo(d *Daemon, req api.ImagesPost, op 
*operation) (*api.Image, e
                return nil, fmt.Errorf("Missing URL")
        }
 
-       myhttp, err := d.httpClient("")
+       myhttp, err := util.HTTPClient("", d.proxy)
        if err != nil {
                return nil, err
        }
@@ -1207,7 +1208,7 @@ func imagePut(d *Daemon, r *http.Request) Response {
 
        // Validate ETag
        etag := []interface{}{info.Public, info.AutoUpdate, info.Properties}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -1235,7 +1236,7 @@ func imagePatch(d *Daemon, r *http.Request) Response {
 
        // Validate ETag
        etag := []interface{}{info.Public, info.AutoUpdate, info.Properties}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -1392,7 +1393,7 @@ func aliasPut(d *Daemon, r *http.Request) Response {
        }
 
        // Validate ETag
-       err = etagCheck(r, alias)
+       err = util.EtagCheck(r, alias)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -1428,7 +1429,7 @@ func aliasPatch(d *Daemon, r *http.Request) Response {
        }
 
        // Validate ETag
-       err = etagCheck(r, alias)
+       err = util.EtagCheck(r, alias)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/networks.go b/lxd/networks.go
index a567de196..6f81691b3 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -15,6 +15,7 @@ import (
        log "gopkg.in/inconshreveable/log15.v2"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -305,7 +306,7 @@ func networkPut(d *Daemon, r *http.Request) Response {
        // Validate the ETag
        etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Description, dbInfo.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -330,7 +331,7 @@ func networkPatch(d *Daemon, r *http.Request) Response {
        // Validate the ETag
        etag := []interface{}{dbInfo.Name, dbInfo.Managed, dbInfo.Type, 
dbInfo.Description, dbInfo.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/profiles.go b/lxd/profiles.go
index 9c94633fb..57e6641f9 100644
--- a/lxd/profiles.go
+++ b/lxd/profiles.go
@@ -12,6 +12,7 @@ import (
        _ "github.com/mattn/go-sqlite3"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -165,7 +166,7 @@ func profilePut(d *Daemon, r *http.Request) Response {
 
        // Validate the ETag
        etag := []interface{}{profile.Config, profile.Description, 
profile.Devices}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -188,7 +189,7 @@ func profilePatch(d *Daemon, r *http.Request) Response {
 
        // Validate the ETag
        etag := []interface{}{profile.Config, profile.Description, 
profile.Devices}
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/response.go b/lxd/response.go
index de821a655..41629738e 100644
--- a/lxd/response.go
+++ b/lxd/response.go
@@ -14,6 +14,7 @@ import (
        "github.com/mattn/go-sqlite3"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
 )
@@ -35,7 +36,7 @@ type syncResponse struct {
 func (r *syncResponse) Render(w http.ResponseWriter) error {
        // Set an appropriate ETag header
        if r.etag != nil {
-               etag, err := etagHash(r.etag)
+               etag, err := util.EtagHash(r.etag)
                if err == nil {
                        w.Header().Set("ETag", etag)
                }
@@ -66,7 +67,7 @@ func (r *syncResponse) Render(w http.ResponseWriter) error {
                Metadata: r.metadata,
        }
 
-       return WriteJSON(w, resp)
+       return util.WriteJSON(w, resp, debug)
 }
 
 func (r *syncResponse) String() string {
@@ -237,7 +238,7 @@ func (r *operationResponse) Render(w http.ResponseWriter) 
error {
        w.Header().Set("Location", url)
        w.WriteHeader(202)
 
-       return WriteJSON(w, body)
+       return util.WriteJSON(w, body, debug)
 }
 
 func (r *operationResponse) String() string {
diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index 6a89f3ebb..a616566a5 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -9,6 +9,7 @@ import (
 
        "github.com/gorilla/mux"
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/version"
 )
@@ -123,7 +124,7 @@ func storagePoolPut(d *Daemon, r *http.Request) Response {
        // Validate the ETag
        etag := []interface{}{dbInfo.Name, dbInfo.Driver, dbInfo.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -161,7 +162,7 @@ func storagePoolPatch(d *Daemon, r *http.Request) Response {
        // Validate the ETag
        etag := []interface{}{dbInfo.Name, dbInfo.Driver, dbInfo.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 22c1f6497..556b3450e 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -8,6 +8,7 @@ import (
 
        "github.com/gorilla/mux"
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/version"
@@ -261,7 +262,7 @@ func storagePoolVolumeTypePut(d *Daemon, r *http.Request) 
Response {
        // Validate the ETag
        etag := []interface{}{volume.Name, volume.Type, volume.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
@@ -323,7 +324,7 @@ func storagePoolVolumeTypePatch(d *Daemon, r *http.Request) 
Response {
        // Validate the ETag
        etag := []interface{}{volume.Name, volume.Type, volume.Config}
 
-       err = etagCheck(r, etag)
+       err = util.EtagCheck(r, etag)
        if err != nil {
                return PreconditionFailed(err)
        }
diff --git a/lxd/storage_zfs.go b/lxd/storage_zfs.go
index 2177282a1..0ebcc81a7 100644
--- a/lxd/storage_zfs.go
+++ b/lxd/storage_zfs.go
@@ -14,6 +14,7 @@ import (
        "github.com/gorilla/websocket"
 
        "github.com/lxc/lxd/lxd/db"
+       "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        "github.com/lxc/lxd/shared/logger"
@@ -46,7 +47,7 @@ func (s *storageZfs) StorageCoreInit() error {
        }
        s.sTypeName = typeName
 
-       loadModule("zfs")
+       util.LoadModule("zfs")
 
        if !zfsIsEnabled() {
                return fmt.Errorf("the \"zfs\" tool is not enabled")
diff --git a/lxd/util.go b/lxd/util/encoding.go
similarity index 64%
rename from lxd/util.go
rename to lxd/util/encoding.go
index e85a5a849..71596ba0c 100644
--- a/lxd/util.go
+++ b/lxd/util/encoding.go
@@ -1,4 +1,4 @@
-package main
+package util
 
 import (
        "bytes"
@@ -11,7 +11,7 @@ import (
        "github.com/lxc/lxd/shared"
 )
 
-func WriteJSON(w http.ResponseWriter, body interface{}) error {
+func WriteJSON(w http.ResponseWriter, body interface{}, debug bool) error {
        var output io.Writer
        var captured *bytes.Buffer
 
@@ -30,7 +30,7 @@ func WriteJSON(w http.ResponseWriter, body interface{}) error 
{
        return err
 }
 
-func etagHash(data interface{}) (string, error) {
+func EtagHash(data interface{}) (string, error) {
        etag := sha256.New()
        err := json.NewEncoder(etag).Encode(data)
        if err != nil {
@@ -40,13 +40,13 @@ func etagHash(data interface{}) (string, error) {
        return fmt.Sprintf("%x", etag.Sum(nil)), nil
 }
 
-func etagCheck(r *http.Request, data interface{}) error {
+func EtagCheck(r *http.Request, data interface{}) error {
        match := r.Header.Get("If-Match")
        if match == "" {
                return nil
        }
 
-       hash, err := etagHash(data)
+       hash, err := EtagHash(data)
        if err != nil {
                return err
        }
@@ -57,12 +57,3 @@ func etagCheck(r *http.Request, data interface{}) error {
 
        return nil
 }
-
-func loadModule(module string) error {
-       if shared.PathExists(fmt.Sprintf("/sys/module/%s", module)) {
-               return nil
-       }
-
-       _, err := shared.RunCommand("modprobe", module)
-       return err
-}
diff --git a/lxd/util/http.go b/lxd/util/http.go
new file mode 100644
index 000000000..5f3eff9ff
--- /dev/null
+++ b/lxd/util/http.go
@@ -0,0 +1,58 @@
+package util
+
+import (
+       "crypto/x509"
+       "encoding/pem"
+       "fmt"
+       "net/http"
+       "net/url"
+
+       "github.com/lxc/lxd/shared"
+)
+
+// HTTPClient returns an http.Client using the given certificate and proxy.
+func HTTPClient(certificate string, proxy proxyFunc) (*http.Client, error) {
+       var err error
+       var cert *x509.Certificate
+
+       if certificate != "" {
+               certBlock, _ := pem.Decode([]byte(certificate))
+               if certBlock == nil {
+                       return nil, fmt.Errorf("Invalid certificate")
+               }
+
+               cert, err = x509.ParseCertificate(certBlock.Bytes)
+               if err != nil {
+                       return nil, err
+               }
+       }
+
+       tlsConfig, err := shared.GetTLSConfig("", "", "", cert)
+       if err != nil {
+               return nil, err
+       }
+
+       tr := &http.Transport{
+               TLSClientConfig:   tlsConfig,
+               Dial:              shared.RFC3493Dialer,
+               Proxy:             proxy,
+               DisableKeepAlives: true,
+       }
+
+       myhttp := http.Client{
+               Transport: tr,
+       }
+
+       // Setup redirect policy
+       myhttp.CheckRedirect = func(req *http.Request, via []*http.Request) 
error {
+               // Replicate the headers
+               req.Header = via[len(via)-1].Header
+
+               return nil
+       }
+
+       return &myhttp, nil
+}
+
+// A function capable of proxing an HTTP request.
+type proxyFunc func(req *http.Request) (*url.URL, error)
diff --git a/lxd/util/kernel.go b/lxd/util/kernel.go
new file mode 100644
index 000000000..6f75915ba
--- /dev/null
+++ b/lxd/util/kernel.go
@@ -0,0 +1,18 @@
+package util
+
+import (
+       "fmt"
+
+       "github.com/lxc/lxd/shared"
+)
+
+// LoadModule loads the kernel module with the given name, by invoking
+// modprobe.
+func LoadModule(module string) error {
+       if shared.PathExists(fmt.Sprintf("/sys/module/%s", module)) {
+               return nil
+       }
+
+       _, err := shared.RunCommand("modprobe", module)
+       return err
+}
_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to