Skip to content

Commit

Permalink
Merge pull request #285 from AkihiroSuda/auto-assign-ssh-localport
Browse files Browse the repository at this point in the history
Assign `ssh.localPort` automatically to an available port
  • Loading branch information
AkihiroSuda authored Oct 8, 2021
2 parents 8091d05 + 0675508 commit 3ff1a15
Show file tree
Hide file tree
Showing 31 changed files with 352 additions and 104 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:
integration:
name: Integration tests
runs-on: macos-11
timeout-minutes: 60
timeout-minutes: 120
strategy:
matrix:
# GHA macOS is slow and flaky, so we only test a few YAMLS here.
Expand Down Expand Up @@ -165,7 +165,7 @@ jobs:
- name: Test
uses: nick-invision/retry@v2
with:
timeout_minutes: 15
timeout_minutes: 30
retry_on: error
max_attempts: 3
command: ./hack/test-example.sh examples/${{ matrix.example }}
Expand Down
35 changes: 35 additions & 0 deletions cmd/limactl/hostagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"os/signal"
"strconv"

"github.com/gorilla/mux"
"github.com/lima-vm/lima/pkg/hostagent"
"github.com/lima-vm/lima/pkg/hostagent/api/server"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand All @@ -21,6 +26,7 @@ func newHostagentCommand() *cobra.Command {
Hidden: true,
}
hostagentCommand.Flags().StringP("pidfile", "p", "", "write pid to file")
hostagentCommand.Flags().String("socket", "", "hostagent socket")
return hostagentCommand
}

Expand All @@ -38,6 +44,13 @@ func hostagentAction(cmd *cobra.Command, args []string) error {
}
defer os.RemoveAll(pidfile)
}
socket, err := cmd.Flags().GetString("socket")
if err != nil {
return err
}
if socket == "" {
return fmt.Errorf("socket must be specified (limactl version mismatch?)")
}

instName := args[0]

Expand All @@ -51,6 +64,28 @@ func hostagentAction(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}

backend := &server.Backend{
Agent: ha,
}
r := mux.NewRouter()
server.AddRoutes(r, backend)
srv := &http.Server{Handler: r}
err = os.RemoveAll(socket)
if err != nil {
return err
}
l, err := net.Listen("unix", socket)
if err != nil {
return err
}
go func() {
defer os.RemoveAll(socket)
defer srv.Close()
if serveErr := srv.Serve(l); serveErr != nil {
logrus.WithError(serveErr).Warn("hostagent API server exited with an error")
}
}()
return ha.Run(cmd.Context())
}

Expand Down
1 change: 1 addition & 0 deletions docs/internal.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Guest agent:

Host agent:
- `ha.pid`: hostagent PID
- `ha.sock`: hostagent REST API
- `ha.stdout.log`: hostagent stdout (JSON lines, see `pkg/hostagent/events.Event`)
- `ha.stderr.log`: hostagent stderr (human-readable messages)

Expand Down
6 changes: 1 addition & 5 deletions examples/alpine.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This example requires Lima v0.7.0 or later.
images:
- location: https://github.com/lima-vm/alpine-lima/releases/download/v0.1.8/alpine-lima-std-3.13.5-x86_64.iso
arch: "x86_64"
Expand All @@ -9,11 +10,6 @@ mounts:
- location: "/tmp/lima"
writable: true

ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60020

firmware:
legacyBIOS: true

Expand Down
6 changes: 1 addition & 5 deletions examples/archlinux.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This example requires Lima v0.5.0 or later
# This example requires Lima v0.7.0 or later
arch: "x86_64"
images:
# NOTE: the image is periodically rotated, if you face 404, see https://mirror.pkgbuild.com/images/ to find the latest image.
Expand All @@ -10,9 +10,5 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60050
firmware:
legacyBIOS: true
5 changes: 1 addition & 4 deletions examples/debian.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This example requires Lima v0.7.0 or later
images:
- location: "https://cloud.debian.org/images/cloud/bullseye/daily/20211005-786/debian-11-generic-amd64-daily-20211005-786.qcow2"
arch: "x86_64"
Expand All @@ -10,7 +11,3 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60030
6 changes: 1 addition & 5 deletions examples/fedora.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This example requires Lima v0.7.0 or later.
arch: "x86_64"
images:
- location: "https://download.fedoraproject.org/pub/fedora/linux/releases/34/Cloud/x86_64/images/Fedora-Cloud-Base-34-1.2.x86_64.qcow2"
Expand All @@ -8,10 +9,5 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60024

firmware:
legacyBIOS: true
5 changes: 2 additions & 3 deletions examples/k3s.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
# $ kubectl get no
# NAME STATUS ROLES AGE VERSION
# lima-k3s Ready control-plane,master 69s v1.21.1+k3s1
#
# This example requires Lima v0.7.0 or later.

images:
# Hint: run `limactl prune` to invalidate the "current" cache
Expand All @@ -19,9 +21,6 @@ images:
# Mounts are disabled in this example, but can be enabled optionally.
mounts: []

ssh:
localPort: 60022

# containerd is managed by k3s, not by Lima, so the values are set to false here.
containerd:
system: false
Expand Down
6 changes: 1 addition & 5 deletions examples/opensuse.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This example requires Lima v0.5.0 or later
# This example requires Lima v0.7.0 or later
images:
# Hint: run `limactl prune` to invalidate the "Current" cache
- location: https://download.opensuse.org/distribution/leap/15.3/appliances/openSUSE-Leap-15.3-JeOS.x86_64-15.3-OpenStack-Cloud-Current.qcow2
Expand All @@ -9,7 +9,3 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60044
5 changes: 1 addition & 4 deletions examples/ubuntu.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This example requires Lima v0.7.0 or later.
images:
# Hint: run `limactl prune` to invalidate the "current" cache
- location: "https://cloud-images.ubuntu.com/hirsute/current/hirsute-server-cloudimg-amd64.img"
Expand All @@ -9,7 +10,3 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60023
5 changes: 0 additions & 5 deletions examples/vmnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ mounts:
writable: false
- location: "/tmp/lima"
writable: true
ssh:
# localPort is changed from 60022 to avoid conflicting with the default.
# (TODO: assign localPort automatically)
localPort: 60105

networks:
# The instance can get routable IP addresses from the vmnet framework using
# https://github.com/lima-vm/vde_vmnet. Available networks are defined in
Expand Down
18 changes: 9 additions & 9 deletions pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func setupEnv(y *limayaml.LimaYAML) (map[string]string, error) {
return env, nil
}

func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error {
func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort int) error {
if err := limayaml.Validate(*y, false); err != nil {
return err
}
Expand All @@ -78,13 +78,13 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error {
return err
}
args := TemplateArgs{
Name: name,
User: u.Username,
UID: uid,
Containerd: Containerd{System: *y.Containerd.System, User: *y.Containerd.User},
SlirpNICName: qemu.SlirpNICName,
SlirpGateway: qemu.SlirpGateway,
SlirpDNS: qemu.SlirpDNS,
Name: name,
User: u.Username,
UID: uid,
Containerd: Containerd{System: *y.Containerd.System, User: *y.Containerd.User},
SlirpNICName: qemu.SlirpNICName,
SlirpGateway: qemu.SlirpGateway,
SlirpDNS: qemu.SlirpDNS,
}

// change instance id on every boot so network config will be processed again
Expand Down Expand Up @@ -120,7 +120,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML) error {
return err
}
if *y.UseHostResolver {
args.UDPDNSLocalPort = y.SSH.LocalPort
args.UDPDNSLocalPort = udpDNSLocalPort
args.DNSAddresses = append(args.DNSAddresses, qemu.SlirpDNS)
} else if len(y.DNS) > 0 {
for _, addr := range y.DNS {
Expand Down
5 changes: 0 additions & 5 deletions pkg/guestagent/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import (
"time"
)

// ErrorJSON is returned with "application/json" content type and non-2XX status code
type ErrorJSON struct {
Message string `json:"message"`
}

var (
IPv4loopback1 = net.IPv4(127, 0, 0, 1)
)
Expand Down
6 changes: 4 additions & 2 deletions pkg/guestagent/api/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/gorilla/mux"
"github.com/lima-vm/lima/pkg/guestagent"
"github.com/lima-vm/lima/pkg/guestagent/api"
"github.com/lima-vm/lima/pkg/httputil"
"github.com/sirupsen/logrus"
)

Expand All @@ -18,8 +19,9 @@ type Backend struct {
func (b *Backend) onError(w http.ResponseWriter, r *http.Request, err error, ec int) {
w.WriteHeader(ec)
w.Header().Set("Content-Type", "application/json")
// it is safe to return the err to the client, because the client is reliable
e := api.ErrorJSON{
// err may potentially contain credential info (in a future version),
// but it is safe to return the err to the client, because we do not expose the socket to the internet
e := httputil.ErrorJSON{
Message: err.Error(),
}
_ = json.NewEncoder(w).Encode(e)
Expand Down
5 changes: 5 additions & 0 deletions pkg/hostagent/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package api

type Info struct {
SSHLocalPort int `json:"sshLocalPort,omitempty"`
}
64 changes: 64 additions & 0 deletions pkg/hostagent/api/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package client

// Forked from https://github.com/rootless-containers/rootlesskit/blob/v0.14.2/pkg/api/client/client.go
// Apache License 2.0

import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/lima-vm/lima/pkg/hostagent/api"
"github.com/lima-vm/lima/pkg/httpclientutil"
)

type HostAgentClient interface {
HTTPClient() *http.Client
Info(context.Context) (*api.Info, error)
}

// NewHostAgentClient creates a client.
// socketPath is a path to the UNIX socket, without unix:// prefix.
func NewHostAgentClient(socketPath string) (HostAgentClient, error) {
hc, err := httpclientutil.NewHTTPClientWithSocketPath(socketPath)
if err != nil {
return nil, err
}
return NewHostAgentClientWithHTTPClient(hc), nil
}

func NewHostAgentClientWithHTTPClient(hc *http.Client) HostAgentClient {
return &client{
Client: hc,
version: "v1",
dummyHost: "lima-hostagent",
}
}

type client struct {
*http.Client
// version is always "v1"
// TODO(AkihiroSuda): negotiate the version
version string
dummyHost string
}

func (c *client) HTTPClient() *http.Client {
return c.Client
}

func (c *client) Info(ctx context.Context) (*api.Info, error) {
u := fmt.Sprintf("http://%s/%s/info", c.dummyHost, c.version)
resp, err := httpclientutil.Get(ctx, c.HTTPClient(), u)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var info api.Info
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(&info); err != nil {
return nil, err
}
return &info, nil
}
Loading

0 comments on commit 3ff1a15

Please sign in to comment.