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

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 PR links the LXD VM implementation with the lxd-agent running inside the VM.
From fc6577e847ee55f0a4277e5798a980f2ea1fee5c Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 8 Nov 2019 22:46:48 +0000
Subject: [PATCH 1/3] client/connection: Simplifies ConnectLXDHTTP

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 client/connection.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/client/connection.go b/client/connection.go
index 13ab844d6e..dde3e327a1 100644
--- a/client/connection.go
+++ b/client/connection.go
@@ -68,7 +68,7 @@ func ConnectLXD(url string, args *ConnectionArgs) 
(InstanceServer, error) {
 }
 
 // ConnectLXDHTTP lets you connect to a VM agent over a VM socket.
-func ConnectLXDHTTP(vsockID int, args *ConnectionArgs, client *http.Client) 
(InstanceServer, error) {
+func ConnectLXDHTTP(args *ConnectionArgs, client *http.Client) 
(InstanceServer, error) {
        logger.Debugf("Connecting to a VM agent over a VM socket")
 
        // Use empty args if not specified

From 87b276bed527d6d24111dc5bdee41641ff26c890 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 8 Nov 2019 22:51:14 +0000
Subject: [PATCH 2/3] lxd/vm/qemu: Adds agent connection setup

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/vm_qemu.go | 83 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 20 deletions(-)

diff --git a/lxd/vm_qemu.go b/lxd/vm_qemu.go
index b6b7d8e427..cef9508ddc 100644
--- a/lxd/vm_qemu.go
+++ b/lxd/vm_qemu.go
@@ -5,7 +5,6 @@ import (
        "fmt"
        "io"
        "io/ioutil"
-       "net"
        "net/http"
        "os"
        "os/exec"
@@ -15,11 +14,11 @@ import (
        "time"
 
        "github.com/digitalocean/go-qemu/qmp"
-       "github.com/linuxkit/virtsock/pkg/vsock"
        "github.com/pborman/uuid"
        "github.com/pkg/errors"
        "golang.org/x/sys/unix"
 
+       lxdClient "github.com/lxc/lxd/client"
        "github.com/lxc/lxd/lxd/backup"
        "github.com/lxc/lxd/lxd/cluster"
        "github.com/lxc/lxd/lxd/db"
@@ -33,6 +32,7 @@ import (
        "github.com/lxc/lxd/lxd/state"
        storagePools "github.com/lxc/lxd/lxd/storage"
        "github.com/lxc/lxd/lxd/util"
+       "github.com/lxc/lxd/lxd/vsock"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/api"
        log "github.com/lxc/lxd/shared/log15"
@@ -58,6 +58,11 @@ func vmQemuLoad(s *state.State, args db.InstanceArgs, 
profiles []api.Profile) (I
                return nil, err
        }
 
+       err = vm.initAgentClient()
+       if err != nil {
+               return nil, err
+       }
+
        return vm, nil
 }
 
@@ -259,6 +264,55 @@ type vmQemu struct {
        op *operations.Operation
 
        expiryDate time.Time
+
+       agentClient *http.Client
+}
+
+func (vm *vmQemu) initAgentClient() error {
+       agentCertFile, _, err := vm.generateAgentCert()
+       if err != nil {
+               return err
+       }
+
+       agentCert, err := ioutil.ReadFile(agentCertFile)
+       if err != nil {
+               return err
+       }
+
+       // The connection uses mutual authentication, so use the LXD server's 
key & cert for client.
+       clientCertFile := shared.VarPath("server.crt")
+       clientKeyFile := shared.VarPath("server.key")
+
+       clientCert, err := ioutil.ReadFile(clientCertFile)
+       if err != nil {
+               return err
+       }
+
+       clientKey, err := ioutil.ReadFile(clientKeyFile)
+       if err != nil {
+               return err
+       }
+
+       vm.agentClient, err = vsock.HTTPClient(vm.vsockID(), 
string(clientCert), string(clientKey), string(agentCert))
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+// generateAgentCert creates the necessary server key and certificate if 
needed.
+func (vm *vmQemu) generateAgentCert() (agentCertFile string, agentKeyFile 
string, err error) {
+       agentCertFile = filepath.Join(vm.Path(), "agent.crt")
+       agentKeyFile = filepath.Join(vm.Path(), "agent.key")
+
+       // Create server certificate.
+       err = shared.FindOrGenCert(agentCertFile, agentKeyFile, true)
+       if err != nil {
+               return
+       }
+
+       return
 }
 
 func (vm *vmQemu) Freeze() error {
@@ -660,9 +714,7 @@ WantedBy=multi-user.target
        }
 
        // Check if we have both agent.crt and agent.key and if not generate a 
new set.
-       agentCertFile := filepath.Join(vm.Path(), "agent.cert")
-       agentKeyFile := filepath.Join(vm.Path(), "agent.key")
-       err = shared.FindOrGenCert(agentCertFile, agentKeyFile, true)
+       agentCertFile, agentKeyFile, err := vm.generateAgentCert()
        if err != nil {
                return "", err
        }
@@ -1967,7 +2019,9 @@ func (vm *vmQemu) RenderState() (*api.InstanceState, 
error) {
        pid, _ := vm.pid()
 
        status, err := vm.agentGetState()
-       if err == nil {
+       if err != nil {
+               logger.Warn("Could not get VM state from agent", 
log.Ctx{"project": vm.Project(), "instance": vm.Name(), "err": err})
+       } else {
                status.Pid = int64(pid)
                status.Status = statusCode.String()
                status.StatusCode = statusCode
@@ -1987,34 +2041,23 @@ func (vm *vmQemu) RenderState() (*api.InstanceState, 
error) {
 // agentGetState connects to the agent inside of the VM and does
 // an API call to get the current state.
 func (vm *vmQemu) agentGetState() (*api.InstanceState, error) {
-       var status api.InstanceState
-
        // Ensure the correct vhost_vsock kernel module is loaded before 
establishing the vsock.
        err := util.LoadModule("vhost_vsock")
        if err != nil {
                return nil, err
        }
 
-       client := http.Client{
-               Transport: &http.Transport{
-                       Dial: func(network, addr string) (net.Conn, error) {
-                               return vsock.Dial(uint32(vm.vsockID()), 8443)
-                       },
-               },
-       }
-
-       resp, err := client.Get("http://vm.socket/state";)
+       agent, err := lxdClient.ConnectLXDHTTP(nil, vm.agentClient)
        if err != nil {
                return nil, err
        }
-       defer resp.Body.Close()
 
-       err = json.NewDecoder(resp.Body).Decode(&status)
+       status, _, err := agent.GetInstanceState("")
        if err != nil {
                return nil, err
        }
 
-       return &status, nil
+       return status, nil
 }
 
 func (vm *vmQemu) IsRunning() bool {

From c62e95009c98908bf55c472d91bf582b8a7432da Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Fri, 8 Nov 2019 22:51:39 +0000
Subject: [PATCH 3/3] lxd/vsock: Simplifies HTTPClient

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd/vsock/vsock.go | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/lxd/vsock/vsock.go b/lxd/vsock/vsock.go
index 2e3d0a5ecd..1a590738b4 100644
--- a/lxd/vsock/vsock.go
+++ b/lxd/vsock/vsock.go
@@ -8,18 +8,20 @@ import (
        "github.com/lxc/lxd/shared"
 )
 
-func vsockHTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, 
tlsCA string, tlsServerCert string, insecureSkipVerify bool) (*http.Client, 
error) {
+// HTTPClient provides an HTTP client for using over vsock.
+func HTTPClient(vsockID int, tlsClientCert string, tlsClientKey string, 
tlsServerCert string) (*http.Client, error) {
        client := &http.Client{}
 
-       // Get the TLS configuration
-       tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, 
tlsCA, tlsServerCert, insecureSkipVerify)
+       // Get the TLS configuration.
+       // tomp TODO remove insecure skip verify.
+       tlsConfig, err := shared.GetTLSConfigMem(tlsClientCert, tlsClientKey, 
"", tlsServerCert, true)
        if err != nil {
                return nil, err
        }
 
        client.Transport = &http.Transport{
                TLSClientConfig: tlsConfig,
-               // Setup a VM socket dialer
+               // Setup a VM socket dialer.
                Dial: func(network, addr string) (net.Conn, error) {
                        conn, err := dial(uint32(vsockID), 8443)
                        if err != nil {
@@ -28,7 +30,7 @@ func vsockHTTPClient(vsockID int, tlsClientCert string, 
tlsClientKey string, tls
 
                        tlsConn := tls.Client(conn, tlsConfig)
 
-                       // Validate the connection
+                       // Validate the connection.
                        err = tlsConn.Handshake()
                        if err != nil {
                                conn.Close()
@@ -40,9 +42,9 @@ func vsockHTTPClient(vsockID int, tlsClientCert string, 
tlsClientKey string, tls
                DisableKeepAlives: true,
        }
 
-       // Setup redirect policy
+       // Setup redirect policy.
        client.CheckRedirect = func(req *http.Request, via []*http.Request) 
error {
-               // Replicate the headers
+               // Replicate the headers.
                req.Header = via[len(via)-1].Header
 
                return nil
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to