Skip to content

Commit

Permalink
incusd/instance/lxc: Basic OCI support
Browse files Browse the repository at this point in the history
Signed-off-by: Stéphane Graber <stgraber@stgraber.org>
  • Loading branch information
stgraber committed Jun 8, 2024
1 parent b2ba983 commit 0ba523a
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
6 changes: 6 additions & 0 deletions cmd/incusd/main_forkstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,11 @@ func (c *cmdForkstart) Run(cmd *cobra.Command, args []string) error {
_ = unix.Dup3(int(logFile.Fd()), 2, 0)
}

// Handle application containers.
execCmd := d.ConfigItem("lxc.execute.cmd")
if len(execCmd) > 0 && execCmd[0] != "" {
return d.StartExecute(nil)
}

return d.Start()
}
120 changes: 120 additions & 0 deletions internal/server/instance/drivers/driver_lxc.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/flosch/pongo2"
"github.com/google/uuid"
"github.com/gorilla/websocket"
"github.com/kballard/go-shellquote"
liblxc "github.com/lxc/go-lxc"
"github.com/pkg/sftp"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -2312,6 +2313,125 @@ func (d *lxc) startCommon() (string, []func() error, error) {
}
}

// Handle application containers.
if util.PathExists(filepath.Join(d.Path(), "config.json")) {
// Parse the OCI config.
data, err := os.ReadFile(filepath.Join(d.Path(), "config.json"))
if err != nil {
return "", nil, err
}

type ociConfig struct {
Process struct {
Terminal bool `json:"terminal"`
User struct {
UID uint32 `json:"uid"`
GID uint32 `json:"gid"`
} `json:"user"`
Args []string `json:"args"`
Env []string `json:"env"`
Cwd string `json:"cwd"`
} `json:"process"`
}

var config ociConfig
err = json.Unmarshal([]byte(data), &config)
if err != nil {
return "", nil, err
}

// FIXME: Should be moved to native environment.XYZ key.
for _, env := range config.Process.Env {
err = lxcSetConfigItem(cc, "lxc.environment", env)
if err != nil {
return "", nil, err
}
}

// Configure the entry point.
err = lxcSetConfigItem(cc, "lxc.execute.cmd", shellquote.Join(config.Process.Args...))
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.init.cwd", config.Process.Cwd)
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.init.uid", fmt.Sprintf("%d", config.Process.User.UID))
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.init.gid", fmt.Sprintf("%d", config.Process.User.GID))
if err != nil {
return "", nil, err
}

// Configure network handling.
err = os.MkdirAll(filepath.Join(d.Path(), "network"), 0711)
if err != nil {
return "", nil, err
}

err = os.MkdirAll(filepath.Join(d.RootfsPath(), "etc"), 0755)
if err != nil && !os.IsExist(err) {
return "", nil, err
}

err = os.WriteFile(filepath.Join(d.Path(), "network", "hosts"), []byte(fmt.Sprintf(`127.0.0.1 localhost
127.0.1.1 %s
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
`, d.name)), 0644)
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s etc/hosts none bind,create=file", filepath.Join(d.Path(), "network", "hosts")))
if err != nil {
return "", nil, err
}

err = os.WriteFile(filepath.Join(d.Path(), "network", "hostname"), []byte(fmt.Sprintf("%s\n", d.name)), 0644)
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s etc/hostname none bind,create=file", filepath.Join(d.Path(), "network", "hostname")))
if err != nil {
return "", nil, err
}

f, err := os.Create(filepath.Join(d.Path(), "network", "resolv.conf"))
if err != nil {
return "", nil, err
}

err = f.Chmod(0644)
if err != nil {
f.Close()
return "", nil, err
}

f.Close()

err = lxcSetConfigItem(cc, "lxc.mount.entry", fmt.Sprintf("%s etc/resolv.conf none bind,create=file", filepath.Join(d.Path(), "network", "resolv.conf")))
if err != nil {
return "", nil, err
}

err = lxcSetConfigItem(cc, "lxc.hook.start-host", fmt.Sprintf("/proc/%d/exe forknet dhcp %s", os.Getpid(), filepath.Join(d.Path(), "network")))
if err != nil {
return "", nil, err
}
}

// Load the LXC raw config.
err = d.loadRawLXCConfig(cc)
if err != nil {
Expand Down

0 comments on commit 0ba523a

Please sign in to comment.