Giter Club home page Giter Club logo

go-lxc's Introduction

go-lxc

Go Bindings for LXC (Linux Containers)

LXC is the well-known and heavily tested low-level Linux container runtime. It is in active development since 2008 and has proven itself in critical production environments world-wide. Some of its core contributors are the same people that helped to implement various well-known containerization features inside the Linux kernel.

This package implements Go bindings for the LXC C API (liblxc).

Status

Type Service Status
CI (Linux) Github CI tests
Go documentation Godoc GoDoc
Static analysis GoReport Go Report Card

Requirements

This package requires LXC >= 1.0.0 and its development package and their dependencies to be installed. Additionally, go-lxc requires Golang 1.10 or later to work. Following command should install required dependencies on Ubuntu 18.10:

sudo apt update
sudo apt install git golang gcc make liblxc1 liblxc-dev lxc-utils pkg-config

Installing

To install it, run:

go get github.com/lxc/go-lxc

Trying

To try examples, run:

# cd ~/go/src/github.com/lxc/go-lxc/examples/

# make
==> Running go vet
==> Building ...
...

# create/create
2018/12/27 22:39:27 Creating container...

# start/start
2018/12/27 22:39:39 Starting the container...
2018/12/27 22:39:39 Waiting container to startup networking...

# attach/attach
2018/12/27 22:39:46 AttachShell
root@rubik:/# hostname
rubik
root@rubik:/# exit
exit
2018/12/27 22:39:52 RunCommand
uid=0(root) gid=0(root) groups=0(root)

# stop/stop
2018/12/27 22:39:54 Stopping the container...

# destroy/destroy
2018/12/27 22:39:57 Destroying container...

Backwards Compatibility

LXC has always focused on strong backwards compatibility. In fact, the API hasn't been broken from release 1.0.0 onwards. Main LXC is currently at version 2.*.*.

Examples

See the examples directory for some.

Bug reports

Bug reports can be filed at: https://github.com/lxc/go-lxc/issues/new

Contributing

Fixes and new features are greatly appreciated. We'd love to see go-lxc improve. To contribute to go-lxc;

  • Fork the repository
  • Modify your fork
  • Ensure your fork passes all tests
  • Send a pull request
    • Bonus points if the pull request includes what you changed, why you changed it, and tests attached.

Getting help

When you find you need help, the LXC projects provides you with several options.

Discuss Forum

We maintain an discuss forum at

where you can get support.

IRC

You can find support by joining #lxcontainers on Freenode.

Mailing Lists

You can check out one of the two LXC mailing list archives and register if interested:

go-lxc's People

Contributors

adrianreber avatar angiglesias avatar brauner avatar caglar10ur avatar dinesh avatar eraserix avatar fatih avatar hallyn avatar kelseyhightower avatar mihalicyn avatar pdf avatar qq690388648 avatar r10r avatar s3rj1k avatar sethdmoore avatar soffokl avatar stgraber avatar syed avatar theopolis avatar tomponline avatar tych0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-lxc's Issues

seg fault in Interfaces()

Hello,

I got the following segfault in Interfaces():

fatal error: unexpected signal during runtime execution
[signal 0xb code=0x1 addr=0xffffffff pc=0x40c305]

runtime stack:
runtime: unexpected return pc for runtime.sigpanic called from 0x40c305
runtime.throw(0xf0f985)
    /usr/lib/go/src/pkg/runtime/panic.c:520 +0x69
runtime: unexpected return pc for runtime.sigpanic called from 0x40c305
runtime.sigpanic()
    /usr/lib/go/src/pkg/runtime/os_linux.c:222 +0x3d

goroutine 36 [syscall]:
runtime.cgocall(0x40c300, 0x2ad77e7ef5b0)
    /usr/lib/go/src/pkg/runtime/cgocall.c:143 +0xe5 fp=0x2ad77e7ef598 sp=0x2ad77e7ef550
gopkg.in/lxc/go-lxc%2ev2._Cfunc_getArrayLength(0xffffffff, 0x8)
    gopkg.in/lxc/go-lxc.v2/_obj/_cgo_defun.c:83 +0x31 fp=0x2ad77e7ef5b0 sp=0x2ad77e7ef598
gopkg.in/lxc/go-lxc%2ev2.convertArgs(0xffffffff, 0x0, 0x0, 0x0)
    /home/mmccrack/go/src/gopkg.in/lxc/go-lxc.v2/util.go:77 +0x6a fp=0x2ad77e7ef5e0 sp=0x2ad77e7ef5b0
gopkg.in/lxc/go-lxc%2ev2.(*Container).Interfaces(0xc2081b9440, 0x0, 0x0, 0x0, 0x0, 0x0)
    /home/mmccrack/go/src/gopkg.in/lxc/go-lxc.v2/container.go:1188 +0x15d fp=0x2ad77e7ef630 sp=0x2ad77e7ef5e0
github.com/lxc/lxd/shared.getIps(0xc2081b9440, 0x0, 0x0, 0x0)
    /home/mmccrack/go/src/github.com/lxc/lxd/shared/container.go:30 +0x95 fp=0x2ad77e7ef810 sp=0x2ad77e7ef630
github.com/lxc/lxd/shared.NewStatus(0xc2081b9440, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /home/mmccrack/go/src/github.com/lxc/lxd/shared/container.go:56 +0x9a fp=0x2ad77e7ef870 sp=0x2ad77e7ef810
main.(*lxdContainer).RenderState(0xc2080fb9e0, 0x3)
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/containers.go:806 +0x53 fp=0x2ad77e7ef920 sp=0x2ad77e7ef870
main.containerGet(0xc208060420, 0xc2080ddd40, 0x0, 0x0)
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/containers.go:470 +0x1b9 fp=0x2ad77e7ef9c8 sp=0x2ad77e7ef920
main.func·016(0x2ad77e63fdc8, 0xc20810d7c0, 0xc2080ddd40)
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/daemon.go:206 +0x4b9 fp=0x2ad77e7efb68 sp=0x2ad77e7ef9c8
net/http.HandlerFunc.ServeHTTP(0xc208050b00, 0x2ad77e63fdc8, 0xc20810d7c0, 0xc2080ddd40)
    /usr/lib/go/src/pkg/net/http/server.go:1235 +0x40 fp=0x2ad77e7efb88 sp=0x2ad77e7efb68
github.com/gorilla/mux.(*Router).ServeHTTP(0xc20801ab90, 0x2ad77e63fdc8, 0xc20810d7c0, 0xc2080ddd40)
    /home/mmccrack/go/src/github.com/gorilla/mux/mux.go:98 +0x292 fp=0x2ad77e7efc98 sp=0x2ad77e7efb88
net/http.serverHandler.ServeHTTP(0xc2080052c0, 0x2ad77e63fdc8, 0xc20810d7c0, 0xc2080ddd40)
    /usr/lib/go/src/pkg/net/http/server.go:1673 +0x19f fp=0x2ad77e7efcf0 sp=0x2ad77e7efc98
net/http.(*conn).serve(0xc208058380)
    /usr/lib/go/src/pkg/net/http/server.go:1174 +0xa7e fp=0x2ad77e7effa0 sp=0x2ad77e7efcf0
runtime.goexit()
    /usr/lib/go/src/pkg/runtime/proc.c:1445 fp=0x2ad77e7effa8 sp=0x2ad77e7effa0
created by net/http.(*Server).Serve
    /usr/lib/go/src/pkg/net/http/server.go:1721 +0x313

goroutine 16 [chan receive, 3 minutes]:
main.run(0x0, 0x0)
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/main.go:88 +0x57c
main.main()
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/main.go:18 +0x26

goroutine 19 [finalizer wait]:
runtime.park(0x4e0d90, 0x1001cb8, 0xf12ce9)
    /usr/lib/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x1001cb8, 0xf12ce9)
    /usr/lib/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
    /usr/lib/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
    /usr/lib/go/src/pkg/runtime/proc.c:1445

goroutine 20 [syscall, 4 minutes]:
os/signal.loop()
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:21 +0x1e
created by os/signal.init·1
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:27 +0x32

goroutine 17 [syscall, 4 minutes]:
runtime.goexit()
    /usr/lib/go/src/pkg/runtime/proc.c:1445

goroutine 21 [chan receive, 4 minutes]:
database/sql.(*DB).connectionOpener(0xc208058280)
    /usr/lib/go/src/pkg/database/sql/sql.go:583 +0x48
created by database/sql.Open
    /usr/lib/go/src/pkg/database/sql/sql.go:442 +0x27c

goroutine 23 [IO wait]:
net.runtime_pollWait(0x2ad77e63fb30, 0x72, 0x0)
    /usr/lib/go/src/pkg/runtime/netpoll.goc:146 +0x66
net.(*pollDesc).Wait(0xc2080387d0, 0x72, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/fd_poll_runtime.go:84 +0x46
net.(*pollDesc).WaitRead(0xc2080387d0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/fd_poll_runtime.go:89 +0x42
net.(*netFD).accept(0xc208038770, 0xb99c48, 0x0, 0x2ad77e63e3f0, 0xb)
    /usr/lib/go/src/pkg/net/fd_unix.go:419 +0x343
net.(*UnixListener).AcceptUnix(0xc2080bf060, 0x516e53, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/unixsock_posix.go:293 +0x73
net.(*UnixListener).Accept(0xc2080bf060, 0x0, 0x0, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/unixsock_posix.go:304 +0x4b
net/http.(*Server).Serve(0xc2080052c0, 0x2ad77e63fc10, 0xc2080bf060, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/server.go:1698 +0x91
net/http.Serve(0x2ad77e63fc10, 0xc2080bf060, 0x2ad77e63fc48, 0xc20801ab90, 0x0, 0x0)
    /usr/lib/go/src/pkg/net/http/server.go:1576 +0x7c
main.func·020(0x0, 0x0)
    /home/mmccrack/go/src/github.com/lxc/lxd/lxd/daemon.go:350 +0x7f
gopkg.in/tomb%2ev2.(*Tomb).run(0xc208060420, 0xc2080c7770)
    /home/mmccrack/go/src/gopkg.in/tomb.v2/tomb.go:153 +0x23
created by gopkg.in/tomb%2ev2.(*Tomb).Go
    /home/mmccrack/go/src/gopkg.in/tomb.v2/tomb.go:149 +0x110

It might be a liblxc bug, though, investigating more now.

default user/password?

Hello,

I ran your example create.go, which creates a container named rubik.
When I start it, I am not able to login properly. I thought default login/password would be ubuntu/ubuntu but it is not the case.

Am I missing something?
Thanks.

create example not working

I tried running the create/create example and got the following output:

lxc 20220324161237.959 ERROR    conf - conf.c:userns_exec_mapped_root:4499 - No uid mapping for container root
lxc 20220324161237.959 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1292 - Error chowning "/home/lbue/.local/share/lxc/rubik/rootfs" to container root
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4820 - You must either run as root, or define uid mappings
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4821 - To pass uid mappings to lxc-create, you could create
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4822 - ~/.config/lxc/default.conf:
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4823 - lxc.include = /etc/lxc/default.conf
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4824 - lxc.idmap = u 0 100000 65536
lxc 20220324161237.959 ERROR    conf - conf.c:suggest_default_idmap:4825 - lxc.idmap = g 0 100000 65536
lxc 20220324161237.959 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1871 - Failed to create dir storage for rubik

Even tough i have set up the uid mapping in ~/.config/lxc/default.conf:
cat ~/.config/lxc/default.conf

lxc.include = /etc/lxc/default.conf
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536

When using lxc-create -t download test then it will create the container like expected.

lxc-checkconfig Output

LXC version 4.0.6
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled

--- Control groups ---
Cgroups: enabled

Cgroup v1 mount points:
/sys/fs/cgroup/cpuset
/sys/fs/cgroup/cpu
/sys/fs/cgroup/cpuacct
/sys/fs/cgroup/blkio
/sys/fs/cgroup/memory
/sys/fs/cgroup/devices
/sys/fs/cgroup/freezer
/sys/fs/cgroup/net_cls
/sys/fs/cgroup/perf_event
/sys/fs/cgroup/net_prio
/sys/fs/cgroup/hugetlb
/sys/fs/cgroup/pids
/sys/fs/cgroup/rdma

Cgroup v2 mount points:
/sys/fs/cgroup/unified

Cgroup v1 systemd controller: missing
Cgroup v1 clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled, not loaded
Macvlan: enabled, not loaded
Vlan: enabled, not loaded
Bridges: enabled, not loaded
Advanced netfilter: enabled, not loaded
CONFIG_NF_NAT_IPV4: missing
CONFIG_NF_NAT_IPV6: missing
CONFIG_IP_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_IP6_NF_TARGET_MASQUERADE: enabled, not loaded
CONFIG_NETFILTER_XT_TARGET_CHECKSUM: enabled, not loaded
CONFIG_NETFILTER_XT_MATCH_COMMENT: enabled, not loaded
FUSE (for use with lxcfs): enabled, not loaded

--- Checkpoint/Restore ---
checkpoint restore: enabled
CONFIG_FHANDLE: enabled
CONFIG_EVENTFD: enabled
CONFIG_EPOLL: enabled
CONFIG_UNIX_DIAG: enabled
CONFIG_INET_DIAG: enabled
CONFIG_PACKET_DIAG: enabled
CONFIG_NETLINK_DIAG: enabled
File capabilities:

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

go env output:

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/lbue/.cache/go-build"
GOENV="/home/lbue/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/lbue/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/lbue/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.18"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/lbue/go-lxc/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build707100842=/tmp/go-build -gno-record-gcc-switches"

CgroupItem and pids namespace

How can I get pids.max from pids cgroup using CgroupItem?

for some strange reason code below does not work:

        test := c.CgroupItem("pids.max")                                                                                                                                                       
        fmt.Println(test)

Implement bdev specs

I have a simple Terraform provider for LXC and someone reported that they were unable to pass in options such as fstype, fssize, etc.

As seen in the comments, I discovered that the bdev stuff isn't implemented in the go bindings.

How difficult would this be to implement? I'd be happy to give it a shot if someone could point me to something similar to look at.

Thanks!

Execute method always fails

No matter how you invoke it, the Execute method fails.

The example in the v2 branch of the project folder fails, since it does not first create a container

$ go run examples/execute.go
2016/04/18 20:56:01 ERROR: executing the command in a temporary container failed

Here is a code example using NewContainer, Create and Execute method.
Always fails with "container already defined"
https://gist.github.com/sethdmoore/bf4d6e332ec1418c567ddfc9294bd9c6

This is due to the check on these lines: https://github.com/lxc/go-lxc/blob/v2/container.go#L457-L459

According to the lxc-execute(1) man page, " lxc-execute runs the specified command inside the container specified by name. It will setup the container according to the configuration previously defined with the lxc-create command or with the configuration file parameter."

lxc-execute(1) without lxc-create first fails on my machine

$ lxc-execute --name foo -- ls /
lxc-execute: conf.c: mount_autodev: 1175 No such file or directory - Failed mounting tmpfs onto /dev
lxc-execute: conf.c: tmp_proc_mount: 3678 No such file or directory - failed to mount /proc in the container.
lxc-execute: lsm/apparmor.c: apparmor_process_label_set: 183 No such file or directory - failed to change apparmor profile to lxc-container-default
lxc-execute: sync.c: __sync_wait: 51 invalid sequence number 1. expected 4
lxc-execute: start.c: __lxc_start: 1213 failed to spawn 'foo'
lxc-execute: cgmanager.c: cgm_remove_cgroup: 523 call to cgmanager_remove_sync failed: invalid request
lxc-execute: cgmanager.c: cgm_remove_cgroup: 525 Error removing all:lxc/foo-3

If I create the container first, it works

lxc-create --name foo -t /usr/share/lxc/templates/lxc-alpine &>/dev/null && lxc-execute --name foo -- ls /
init.lxc.static: initutils.c: mount_fs: 36 failed to mount /proc : Operation not permitted
init.lxc.static: initutils.c: mount_fs: 36 failed to mount /dev/shm : Operation not permitted
init.lxc.static: initutils.c: mount_fs: 36 failed to mount /dev/mqueue : Operation not permitted
bin              etc              init.lxc.static  linuxrc          mnt              root             sbin             tmp              var
dev              home             lib              media            proc             run              sys              usr

System / Package / Etc below

~/go/src/gopkg.in/lxc/go-lxc.v2 $ git rev-parse HEAD
85d46fc661f9628f265f3f4df15427d15c272e8a

$ go version
go version go1.6.1 linux/amd64

$ uname -a
Linux example.com 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 15.10
Release:        15.10
Codename:       wily

apt-cache policy lxc lxc-dev
lxc:
  Installed: 1.1.5-0ubuntu0.15.10.3
  Candidate: 1.1.5-0ubuntu0.15.10.3
  Version table:
 *** 1.1.5-0ubuntu0.15.10.3 0
        500 http://mirrors.digitalocean.com/ubuntu/ wily-updates/main amd64 Packages
        100 /var/lib/dpkg/status
     1.1.4-0ubuntu1 0
        500 http://mirrors.digitalocean.com/ubuntu/ wily/main amd64 Packages
lxc-dev:
  Installed: 1.1.5-0ubuntu0.15.10.3
  Candidate: 1.1.5-0ubuntu0.15.10.3
  Version table:
 *** 1.1.5-0ubuntu0.15.10.3 0
        500 http://mirrors.digitalocean.com/ubuntu/ wily-updates/main amd64 Packages
        100 /var/lib/dpkg/status
     1.1.4-0ubuntu1 0
        500 http://mirrors.digitalocean.com/ubuntu/ wily/main amd64 Packages

Support lxc attach options with RunCommand*

Specifically we should support standard command options such as:

  • Environment
  • User
  • Cwd

User isn't really a high priority as you can sudo, similar with Cwd (just cd .). Passing environment is fairly complex however.

Package lxc was not found in the pkg-config search path

Hi,
i am trying to install go-lxc in my ubuntu system with the following command.

go get gopkg.in/lxc/go-lxc.v2

I am getting the following error, even though i installed lxc with 'sudo apt-get install lxc'

# pkg-config --cflags lxc
Package lxc was not found in the pkg-config search path.
Perhaps you should add the directory containing `lxc.pc'
to the PKG_CONFIG_PATH environment variable
No package 'lxc' found
exit status 1

When i do dpkg -l lxc, it is showing up there, but there is no executable by name 'lxc', only lxc-* are available.
My machine is ubuntu 14.04

SetConfigItem creates duplicate entries

I am trying to use the SetConfigItem api call to change hostname of a container, and I noticed that this results in multiple lxc.utsname entries in the config file. I tried using the ClearConfigItem, but thats failing with "cant clear cgroup item" error message,

package main

import (
  "fmt"
  "gopkg.in/lxc/go-lxc.v2"
  "os"
)

func main() {
  lxcpath := lxc.DefaultConfigPath()
  ct, err := lxc.NewContainer("test", lxcpath)
  if err != nil {
    fmt.Println(err)
    os.Exit(1)
  }
  /*
    if err := ct.ClearConfigItem("lxc.utsname"); err != nil {
      fmt.Println("Clear config")
      fmt.Println(err)
      os.Exit(1)
    } 
  */
  if err := ct.SetConfigItem("lxc.utsname", "foo"); err != nil { 
    fmt.Println("Set config")
    fmt.Println(err)
    os.Exit(1)
  } 

  fmt.Println(ct.ConfigFileName())
  if err := ct.SaveConfigFile(ct.ConfigFileName()); err != nil {
    fmt.Println("Save config")
    fmt.Println(err)
    os.Exit(1)
  }
} 

Support working without template

The command lxc-start gives the option to use the template "none" that creates a container without template. This feature comes quite handy setting up custom containers without creating a new template and editing the container config and setup the rootfs by other means

go-lxc fails with gccgo

I'm looking into gccgo as a way to build LXD for ppc64el and arm64 where gc doesn't work.

So far it looks like most of our code is fine, but go-lxc itself fails when building using gccgo5.

Here's as simple an example as I could come up with:

ubuntu@lantea:~/go/gopkg.in/lxc/go-lxc.v2/examples$ go install -v console.go 
gopkg.in/lxc/go-lxc.v2
command-line-arguments

ubuntu@lantea:~/go/gopkg.in/lxc/go-lxc.v2/examples$ rm -Rf $GOBIN
ubuntu@lantea:~/go/gopkg.in/lxc/go-lxc.v2/examples$ sudo update-alternatives --config go
There are 2 choices for the alternative go (providing /usr/bin/go).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/golang-go   10        auto mode
  1            /usr/bin/gccgo-go    5         manual mode
  2            /usr/bin/golang-go   10        manual mode

Press enter to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/bin/gccgo-go to provide /usr/bin/go (go) in manual mode

ubuntu@lantea:~/go/gopkg.in/lxc/go-lxc.v2/examples$ go install -v console.go 
command-line-arguments
# command-line-arguments
./console.go:13:24: error: redefinition of ‘lxc’
  "gopkg.in/lxc/go-lxc.v2"
                        ^
./console.go:13:24: note: previous definition of ‘lxc’ was here

ERROR: Creating container faled + other error

Container noob here. Trying to run a modified version of the Create example. Here's my code:

func main() {
	verbose := true
	c, err := lxc.NewContainer("gotest", "/var/snap/lxd/common/lxd/unix.socket")
	if err != nil {
		log.Fatalf("ERROR: %s\n", err.Error())
	}
	defer c.Release()

	log.Printf("Creating container...\n")
	if verbose {
		c.SetVerbosity(lxc.Verbose)
	}

	options := lxc.TemplateOptions{
		Template:             "download",
		Distro:               "ubuntu",
		Release:              "trusty",
		Arch:                 "amd64",
		FlushCache:           false,
		DisableGPGValidation: false,
	}

	if err := c.Create(options); err != nil {
		log.Printf("ERROR: %s\n", err.Error())
	}
}

But I'm getting ERROR: creating the container failed. I'm on Pop OS (based on Ubuntu 19.04) and have installed lxd with apt follow this. I'm able to start a container with lxc start ubuntu.

Also, the Console example fails with ERROR: container is not running: "test". I've verified with lxc list that test is running.

Any help would be great, thanks.

console: handle escape character specification

Currently the console code assumes that the escape character can be simply specified as a rune/char passed into the corresponding C function. But actually lxc_console() assumes that 1 == 'a', 2 == 'b' so you need something similar to this C function in go-lxc:

inline char etoc(const char c)
{
	/* returns "control code" of given expression */
	return 1 + ((c > 'Z') ? (c - 'a') : (c - 'Z'));
}

Container ops fork child processes that inherit file descriptors

Dear go-lxc contributors,

I've observed a issue with concurrently creating file descriptors and performing container operations that involve fork/exec under the hood. I have created a repro case here; for more details, please see below:

Description

go-lxc has a classic CLOEXEC race where the underlying liblxc C library will,
when we wish to start a new container, fork() and exec() the /sbin/init process,
but does not ensure that those children do not inherit file descriptors that have
been concurrently opened in the parent process. As a result, because the inode
reference count will be higher than we expect, application code cannot assume
that close()ing a fd will behave the way we expect it to - in particular, closing
the write half of a pipe may not also close the read half of the pipe, leading to
deadlock-like behaviour.

In contrast, when the Go runtime wants to spawn a child process (e.g. in os/exec),
it takes a lock to ensure mutual
exclusion.

We observed the aforementioned pipe hang on an internal project and created a test case that exhibits the same behaviour.

Example

➜ $ go run main.go
Attempting race with starting go runtime pid 20297
Started precise (init pid: 20342; parent pid: 20306)
Found the following intersecting inodes: [505657 505657]
*** inode race detected after 1 attempts

We can confirm this with manual lsofing:

➜  $ sudo lsof -p 20306 | grep 505657
main    20306 vagrant    4r  FIFO               0,10      0t0     505657 pipe
main    20306 vagrant    5w  FIFO               0,10      0t0     505657 pipe
➜  $ sudo lsof -p 20297 | grep 505657
main    20297 vagrant    4r  FIFO   0,10      0t0  505657 pipe
main    20297 vagrant    5w  FIFO   0,10      0t0  505657 pipe

The relevant bits of the process tree:

vagrant   1776  0.0  0.2  50392 11752 pts/0    Ss   14:38   0:01  |       \_ /bin/zsh -l
vagrant  20274  1.2  0.2 127188 11352 pts/0    Sl+  23:45   0:00  |           \_ go run main.go
vagrant  20297  0.0  0.1 136304  4844 pts/0    Sl+  23:45   0:00  |               \_ /tmp/go-build525531552/command-line-arguments/_obj/exe/main
...
vagrant  20306  0.0  0.0 144732  3932 ?        Ss   23:45   0:00 /tmp/go-build525531552/command-line-arguments/_obj/exe/main
100000   20342  1.0  0.0  24072  3148 ?        Ss   23:45   0:00  \_ /sbin/init
100000   20523  0.0  0.0  15196   184 ?        S    23:45   0:00      \_ upstart-socket-bridge --daemon
100000   20541  0.0  0.0  17240   168 ?        S    23:45   0:00      \_ upstart-udev-bridge --daemon

Suggested fixes

Because the fork() happens in C-land, I'm not sure of a completely clean solution.
One thing that comes to mind that might work is a double-fork, where we let the go
runtime fork first, to ensure that no concurrent fd creation could have been inherited,
and then we let liblxc do its thing. I don't know if such a low-level primitive is
exposed up into golang "userspace", though.

Thank you,
Nathan

use c.Start for Execute

The go-lxc bindings are executing 'lxc-execute' for container execute. Is there a good reason for not using lxccontainer->start() with useinit=1?

I see a comment in the code referring to an issue with signals, but chasing down the links it seems the problem should have been fixed some time ago in go?

go get fails for 8e4bc27

Hi,

this morning one of our builds failed. It turned out that a go get go-lxc.v2 does not work anymore.
I can reproduce the problem:

export GOPATH=/tmp
root@buildroot-trusty:/# apt-get install -y pkg-config lxc-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
lxc-dev is already the newest version.
pkg-config is already the newest version.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

root@buildroot-trusty:/# go get gopkg.in/lxc/go-lxc.v2
# gopkg.in/lxc/go-lxc.v2
tmp/src/gopkg.in/lxc/go-lxc.v2/lxc-binding.go:234: undefined: go_lxc_config_item_is_supported

Seems to be related to accepted pull request #77

starting the container failed

I'm trying to follow a few of the basic examples but am getting an error, starting the container failed.

Here's my simple program:

package main

import (
	"log"
	"time"

	lxc "gopkg.in/lxc/go-lxc.v2"
)

func main() {
	name := "lxc-test"
	c, err := lxc.NewContainer(name, lxc.DefaultConfigPath())
	if err != nil {
		log.Fatalf("ERROR: %s\n", err.Error())
	}
	defer c.Release()

	c.SetVerbosity(lxc.Verbose)
	c.SetLogFile(name + ".log")
	c.SetLogLevel(lxc.TRACE)

	log.Printf("Starting the container...\n")
	if err := c.Start(); err != nil {
		log.Fatalf("ERROR: %s\n", err.Error())
	}

	log.Printf("Waiting container to startup networking...\n")
	if _, err := c.WaitIPAddresses(5 * time.Second); err != nil {
		log.Fatalf("ERROR: %s\n", err.Error())
	}

	if output, err := c.Execute("uname", "-a"); err != nil {
		log.Fatalf("ERROR: %s\n", err.Error())
	} else {
		log.Printf("%s", output)
	}
}

Here's what I get when I try to run this program:

$ go run main.go
2019/10/28 05:26:29 Starting the container...
2019/10/28 05:26:29 ERROR: starting the container failed
exit status 1

Here's the log file:

lxc 20191028052629.271 TRACE    commands - commands.c:lxc_cmd:302 - Connection refused - Command "get_state" failed to connect command socket
lxc 20191028052629.271 TRACE    start - start.c:lxc_init_handler:766 - Created anonymous pair {4,5} of unix sockets
lxc 20191028052629.271 TRACE    commands - commands.c:lxc_cmd_init:1273 - Created abstract unix socket "/home/vagrant/.local/share/lxc/lxc-test/command"
lxc 20191028052629.271 TRACE    start - start.c:lxc_init_handler:779 - Unix domain socket 6 for command server is ready
lxc 20191028052629.271 INFO     lxccontainer - lxccontainer.c:do_lxcapi_start:971 - Set process title to [lxc monitor] /home/vagrant/.local/share/lxc lxc-test
lxc 20191028052629.271 TRACE    start - start.c:lxc_start:2128 - Doing lxc_start
lxc 20191028052629.271 INFO     lsm - lsm/lsm.c:lsm_init:50 - LSM security driver SELinux
lxc 20191028052629.271 TRACE    start - start.c:lxc_init:799 - Initialized LSM
lxc 20191028052629.271 TRACE    start - start.c:lxc_init:806 - Read seccomp policy
lxc 20191028052629.271 TRACE    start - start.c:lxc_serve_state_clients:474 - Set container state to STARTING
lxc 20191028052629.271 TRACE    start - start.c:lxc_serve_state_clients:477 - No state clients registered
lxc 20191028052629.271 TRACE    start - start.c:lxc_init:814 - Set container state to "STARTING"
lxc 20191028052629.271 TRACE    start - start.c:lxc_init:877 - Set environment variables
lxc 20191028052629.271 TRACE    start - start.c:lxc_init:884 - Ran pre-start hooks
lxc 20191028052629.272 TRACE    start - start.c:setup_signal_fd:356 - Created signal file descriptor 7
lxc 20191028052629.272 TRACE    start - start.c:lxc_init:895 - Set up signal fd
lxc 20191028052629.273 DEBUG    terminal - terminal.c:lxc_terminal_peer_default:676 - No such device - The process does not have a controlling terminal
lxc 20191028052629.273 TRACE    start - start.c:lxc_init:903 - Created console
lxc 20191028052629.273 TRACE    start - start.c:lxc_init:910 - Chowned console
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1014 - basecginfo is:
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1015 - 11:hugetlb:/
10:memory:/user.slice/user-1000.slice/session-3.scope
9:net_cls,net_prio:/
8:cpuset:/
7:devices:/user.slice
6:freezer:/
5:perf_event:/
4:pids:/user.slice/user-1000.slice/session-3.scope
3:blkio:/user.slice
2:cpu,cpuacct:/user.slice
1:name=systemd:/user.slice/user-1000.slice/session-3.scope
0::/user.slice/user-1000.slice/session-3.scope

lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 0: hugetlb
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 1: memory
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 2: net_cls
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 3: net_prio
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 4: cpuset
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 5: devices
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 6: freezer
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 7: perf_event
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 8: pids
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 9: blkio
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 10: cpu
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 11: cpuacct
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1018 - kernel subsystem 12: cgroup2
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_basecg_debuginfo:1021 - named subsystem 0: name=systemd
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:cg_hybrid_init:2595 - Writable cgroup hierarchies:
lxc 20191028052629.273 TRACE    cgfsng - cgroups/cgfsng.c:lxc_cgfsng_print_hierarchies:991 -   No hierarchies found
lxc 20191028052629.273 TRACE    cgroup - cgroups/cgroup.c:cgroup_init:56 - Initialized cgroup driver cgfsng
lxc 20191028052629.273 TRACE    cgroup - cgroups/cgroup.c:cgroup_init:61 - Running with hybrid cgroup layout
lxc 20191028052629.273 TRACE    start - start.c:lxc_init:917 - Initialized cgroup driver
lxc 20191028052629.273 INFO     start - start.c:lxc_init:919 - Container "lxc-test" is initialized
lxc 20191028052629.273 ERROR    start - start.c:lxc_spawn:1737 - Operation not permitted - Failed to clone a new set of namespaces
lxc 20191028052629.273 DEBUG    network - network.c:lxc_delete_network_unpriv:2479 - Cannot not guarantee safe deletion of network devices. Manual cleanup maybe needed
lxc 20191028052629.273 DEBUG    network - network.c:lxc_delete_network:3306 - Failed to delete network devices
lxc 20191028052629.273 TRACE    start - start.c:lxc_serve_state_socket_pair:543 - Sent container state "ABORTING" to 5
lxc 20191028052629.273 TRACE    start - start.c:lxc_serve_state_clients:474 - Set container state to ABORTING
lxc 20191028052629.273 TRACE    start - start.c:lxc_serve_state_clients:477 - No state clients registered
lxc 20191028052629.273 ERROR    start - start.c:__lxc_start:2019 - Failed to spawn container "lxc-test"
lxc 20191028052629.273 TRACE    start - start.c:lxc_serve_state_clients:474 - Set container state to STOPPING
lxc 20191028052629.273 TRACE    start - start.c:lxc_serve_state_clients:477 - No state clients registered
lxc 20191028052629.273 TRACE    start - start.c:lxc_fini:1024 - Closed command socket
lxc 20191028052629.273 TRACE    start - start.c:lxc_fini:1035 - Set container state to "STOPPED"
lxc 20191028052629.273 DEBUG    lxccontainer - lxccontainer.c:wait_on_daemonized_start:839 - First child 11384 exited
lxc 20191028052629.273 ERROR    lxccontainer - lxccontainer.c:wait_on_daemonized_start:850 - Received container state "ABORTING" instead of "RUNNING"

I'm on Fedora 30, before running I installed the following:
$ sudo dnf install lxc lxc-templates lxc-devel lxc-extra dnsmasq debootstrap libvirt perl gpg

Here's my info:

$ uname -a
Linux fedora30.localdomain 5.3.5-200.fc30.x86_64 #1 SMP Tue Oct 8 12:41:15 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux 

go get failing ubuntu 15.10

go get gopkg.in/lxc/go-lxc.v2 results in below error

pkg-config --cflags lxc

pkg-config: exec: "pkg-config": executable file not found in $PATH

Shallow copy of container object in Containers(), DefinedContainers() and ActiveContainers()

We are writing a daemon to monitor health of containers running on our server farm. The daemon was hitting panic at random times. Essentially we are doing the following in a loop :-
func ListLXCInstances() {
    c := lxc.Containers()
    for i := range c {
        //Push container name and state to a central server.
    }
}

Code panics when we were trying to read either state or name from the container object using Name() or State() function. On digging around I found Release function was getting called. Following line seems to be issue here :-

for _, v := range ContainerNames(lxcpath...) {
		if container, err := NewContainer(v, lxcpath...); err == nil {
			containers = append(containers, *container)
		}
	}

Here we are making object copy but we are not incrementing reference counter on the underlying C struct (container *C.struct_lxc_container). As we move out of this function, object created by NewContainer() can be destroyed if gc is run. If gc is run at this time, underlying object gets destroyed, while the container objects returned by Containers() function points to the free memory location. This could cause panic when accessed. Following code can easily highlight the issue :-
func ListLXCInstances() {
    c := lxc.Containers()
    runtime.GC() // For a GC.
    for i := range c {
        fmt.Println(c[i].Name(), c[i].State())
    }
}

Here Println() will print garbage values or it could cause panic. Please let me know if my analysis is wrong or if I am using the api correctly.

go get returns 301

Running

go get gopkg.in/lxc/go-lxc.v2

returns a 'Moved Permanently' HTTP Code:

# cd .; git clone https://gopkg.in/lxc/go-lxc.v2 /data/Projects/gitlab/gitlab-ci-multi-runner/src/gopkg.in/lxc/go-lxc.v2
Cloning into '/tmp/src/gopkg.in/lxc/go-lxc.v2'...
error: RPC failed; HTTP 301 curl 22 The requested URL returned error: 301
fatal: The remote end hung up unexpectedly
package gopkg.in/lxc/go-lxc.v2: exit status 128

Running examples/start.go - SIGSEGV: segmentation violation

Hello,

I have latest LXC git from sources.
I need some advice about running a container via examples/start.go.

I have a busybox container named bb2.
I can start it and stop it successfully via
lxc-start -n bb2
and
lxc-start -n bb2 -k

It is installed in the default library, /var/lib/lxc.

Now I try to start it via examples/start.go (see later) and it fails with SIGSEGV.
Here is what I tried:
useradd davids
export GOPATH=/home/davids/go
go get github.com/lxc/go-lxc
cd /home/davids/go/src/github.com/lxc/go-lxc/examples
Now make one change in start.go: change name of the container from "rubik" to "bb2".
Now I ran:
go run start.go
2014/02/22 18:01:19 Starting the container...
SIGSEGV: segmentation violation
PC=0x1234a90
signal arrived during cgo execution

runtime.cgocall(0x402bd0, 0x7f6922eb2e58)
/usr/local/go/src/pkg/runtime/cgocall.c:149 +0x11b fp=0x7f6922eb2e40
github.com/lxc/go-lxc._Cfunc_lxc_start(0x1232420, 0x0, 0x0, 0x0)
github.com/lxc/go-lxc/_obj/_cgo_defun.c:475 +0x31 fp=0x7f6922eb2e58
github.com/lxc/go-lxc.(*Container).Start(0xc21001d330, 0x0, 0x0)
/home/davids/go/src/github.com/lxc/go-lxc/container.go:341 +0xd3 fp=0x7f6922eb2e80
main.main()
/home/davids/go/src/github.com/lxc/go-lxc/examples/start.go:54 +0x280 fp=0x7f6922eb2f48
runtime.main()
/usr/local/go/src/pkg/runtime/proc.c:220 +0x11f fp=0x7f6922eb2fa0
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1394 fp=0x7f6922eb2fa8

goroutine 3 [syscall]:
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1394

rax 0x1234a90
rbx 0x7fff2967b900
rcx 0x1232180
rdx 0x5
rdi 0x12321e0
rsi 0x366365153d
rbp 0x1232660
rsp 0x7fff2967b8d8
r8 0x0
r9 0x1
r10 0x7fff2967b6a0
r11 0x402f40
r12 0x4dc101
r13 0x7fff2967bbd0
r14 0x1232420
r15 0x0
rip 0x1234a90
rflags 0x10206
cs 0x33
fs 0x0
gs 0x0
exit status 2

Missing AppendConfigItem

Per the Python API, there should be an "append_config_item". Without it I can't see a reliable way to set things like lxc.cgroup.devices.allow which accept multiple values.

Build failed when specify ldflags -static

Installed lxc-libs lxc-devel on CentOS7, couldn't find any static link infos with pkg-config --static lxc

go build errors:

GOOS=linux GOARCH=amd64 GO111MODULE=on go build -v -ldflags "--extldflags=-static" lxc.go
# command-line-argusments
/usr/lib/golang/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -llxc

relate versions:

  • lxc-libs-1.0.11-2
  • lxc-devel-1.0.11-2
  • go1.15.5 linux/amd64

Wait() function isn't blocking

When running the following code, you expect the Wait call to block until the state has been reached, or the timeout has expired.

	log.Infof("Waiting for container %s to settle, current state=%s", c.name, c.c.State())

	if !c.c.Wait(lxc.RUNNING, 30*time.Second) {
		return fmt.Errorf("lxccontainer still not running %s", c.name)
	}

However, when running this, I get the following output:

13:24:12.422 director/lxc ▶ INFO b38c Waiting for container example to settle, current state=STOPPED
13:24:12.422 director/lxc ▶ ERRO b38d Error creating container: lxccontainer still not running example

Running lxc-wait manually works fine, so I think it's a problem somewhere in the binding. Running with lxc-2.1

Package name of the tests package

The package name is currently not lxc. Instead it's called lxc_test. Usually package names are the same as the base package name. There might be some exceptions which are listed here: http://stackoverflow.com/questions/19998250/proper-package-naming-for-testing-in-go-lang

As I know we can obey the usual way and rename the package to lxc. This also would enable to access private variables/identifiers. What do you think? If there is no other reason, I'll would like to change this.

Failed to create loopback storage

Hello

I tried to spawn an lxc container with a loopback storage device as backend type.
But it failed to create the storage device.
Following lines were logged:

lxc 20210226152722.259 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1272 - Failed to create "loopback" storage
lxc 20210226152722.259 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1869 - Failed to create loopback storage for test0
lxc 20210226153541.279 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1272 - Failed to create "loopback" storage
lxc 20210226153541.279 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1869 - Failed to create loopback storage for test0
lxc 20210226154424.601 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1272 - Failed to create "loopback" storage
lxc 20210226154424.601 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1869 - Failed to create loopback storage for test0
lxc 20210226154726.197 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1272 - Failed to create "loopback" storage
lxc 20210226154726.197 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1869 - Failed to create loopback storage for test0
lxc 20210226155147.131 ERROR    lxccontainer - lxccontainer.c:do_storage_create:1272 - Failed to create "loopback" storage
lxc 20210226155147.131 ERROR    lxccontainer - lxccontainer.c:do_lxcapi_create:1869 - Failed to create loopback storage for test0

For creating an instance I copied the examples/create.go and modified the function init() inside it:

func init() {
        flag.StringVar(&lxcpath, "lxcpath",  lxc.DefaultConfigPath(), "Use specified container path")
        flag.StringVar(&template, "template", "debian", "Template to use")
        flag.StringVar(&distro, "distro", "debian", "Template to use")
        flag.StringVar(&release, "release", "buster", "Template to use")
        flag.StringVar(&arch, "arch", "amd64", "Template to use")
        flag.StringVar(&name, "name", "test0", "Name of the container")
        flag.BoolVar(&verbose, "verbose", true, "Verbose output")
        flag.BoolVar(&flush, "flush", false, "Flush the cache")
        flag.BoolVar(&validation, "validation", false, "GPG validation")
        flag.StringVar(&bdevtype, "bdev", "loopback", "backing store type")
        flag.StringVar(&fssize, "fssize", "8192MB", "backing store size")
        flag.Parse()
}

I tried this on Ubuntu 20.04 as well as on Debian 10.8 with Go 1.16/1.15.7 and both resulted with the same error.
Are there any required parameters missing to create the loopback storage device? 🤔

If I try to create the container with lxc-create -t debian -B loop --fssize 8192 -n test0 -- -a amd64 -r buster the container instance will be created without any issues.

Import path to gopkg.in/lxc/go-lxc.v2 breaks module replacement

Hi there,

I noticed that the import path gopkg.in/lxc/go-lxc.v2 (proposed by the readme) breaks module replacement.

I used the import path gopkg.in/lxc/go-lxc.v2 in lxcri.
E.g to test lxcri against a development go-lxc remote branch I change the import path in go.mod:

replace gopkg.in/lxc/go-lxc.v2 => github.com/drachenfels-de/go-lxc fixes

When refreshing go.mod I get the following error:

[ruben@k8s-cluster8-controller lxcri]$ go get -u -v gopkg.in/lxc/go-lxc.v2
go: gopkg.in/lxc/[email protected] (replaced by github.com/drachenfels-de/[email protected]): parsing go.mod:
	module declares its path as: github.com/lxc/go-lxc
	        but was required as: gopkg.in/lxc/go-lxc.v2

After changing the import path to github.com/lxc/go-lxc the following module replacement works fine.

replace github.com/lxc/go-lxc => github.com/drachenfels-de/go-lxc fixes

What about changing all gopkg.in/go-lxc.v2 references in README.md to github.com/go-lxc ?

Version checking checks compile time version rather than runtime

Many of version checking related functions (e.g.
lxc.VersionNumber, lxc.VersionAtLeast, VERSION_AT_LEAST ` refer to the lxc versions present at compile time in build host rather than the runtime lxc version linked at process start time.

The issue is that they reference preprocessor definition integer constants (e.g. LXC_VERSION_MAJOR , and compiler inlines them with compile time dependency value.

Looks like it was this was addressed partially in #112 .

Reproduction

Run the following scripts below. The script generates a binary that reports lxc versions and is compiled against 2.0. When running it against 3.0.1, I get the following output (the bottom of the script output):

+ echo ======= RUNNING WITH LXC 3.0
+ echo
+ dpkg -l
+ grep lxc
ii  liblxc-common           3.0.4-0ubuntu1              amd64        Linux Containers userspace tools (common tools)
ii  liblxc1                 3.0.4-0ubuntu1              amd64        Linux Containers userspace tools (library)
ii  lxcfs                   3.0.4-2                     amd64        FUSE based filesystem for LXC
+ /tmp/lxc-temp/lxc-version
STRING VERSION:  3.0.4
NUMBER VERSION  2 0
AT LEAST 2.1.0:  false

Script:

#!/bin/bash

set -ex

mkdir -p /tmp/lxc-temp/

# a basic golang app that reports version through different functions
cat <<'EOF' > /tmp/lxc-temp/main.go
package main

import (
"fmt"

lxc "gopkg.in/lxc/go-lxc.v2"
)

func main() {
verStr := lxc.Version()
fmt.Println("STRING VERSION: ", verStr)

major, minor := lxc.VersionNumber()
fmt.Println("NUMBER VERSION ", major, minor)

fmt.Println("AT LEAST 2.1.0: ", lxc.VersionAtLeast(2, 1, 0))
}
EOF

# compile golang binary with LXC 2.0
# uses old ubuntu to lxc 2.0 and old golang 1.10 but results are the same with latest golang 1.13
cat <<'EOF' | docker run -i --rm -v /tmp/lxc-temp:/tmp/lxc-temp ubuntu:16.04 /bin/bash
set -ex
echo this may take a long time
apt-get update >/dev/null

apt-get install -y golang-1.10 build-essential curl git lxc-dev/xenial-updates >/dev/null
ln -s /usr/lib/go-1.10/bin/go /usr/bin/go

mkdir /go
export GOPATH=/go
go get -u -v gopkg.in/lxc/go-lxc.v2
go build -o /tmp/lxc-temp/lxc-version /tmp/lxc-temp/main.go

echo ======= RUNNING WITH LXC 2.0
echo
dpkg -l |grep lxc
/tmp/lxc-temp/lxc-version
EOF

# now run it in latest ubuntu with latest lxc
cat <<'EOF' | docker run -i --rm -v /tmp/lxc-temp:/tmp/lxc-temp ubuntu:19.10 /bin/bash
set -ex
apt-get update >/dev/null
apt-get install -y liblxc1 >/dev/null

echo ======= RUNNING WITH LXC 3.0
echo
dpkg -l |grep lxc
/tmp/lxc-temp/lxc-version
EOF

ConfigItem not returning lxc.network values

Given the container configuration snippet
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx

The following go code does not function as expected

container := lxc.NewContainer("example", lxc.DefaultConfigPath())
container.ConfigItem("lxc.network") returns "veth"
container.ConfigItem("lxc.network.type") returns []string{""}

expected results are for lxc.network to return nothing or all lxc.network configuration.
expected results are for lxc.network.type to return "veth"

latest go-lxc (commit 4c6cb39)
using daily ppa package, version liblxc1 1.1.0+master20150224-0137-0ubuntu1precise

‘struct lxc_container’ has no member named ‘set_timeout’

Necessary information

  • Distribution: Ubuntu 22.04
  • LXD git version tag: lxd-5.20 (6b2c9592)
  • go-lxc git version: ccae595

Issue description

I am tring to build the lxd form source code following this Tutorial.

After make dep and export the necessary variables, make facing issue while compile go-lxc part.

$ make
......
github.com/lxc/go-lxc
# github.com/lxc/go-lxc
lxc-binding.c: In function ‘go_lxc_set_timeout’:
lxc-binding.c:80:15: error: ‘struct lxc_container’ has no member named ‘set_timeout’
   80 |         if (!c->set_timeout(c, timeout))
      |               ^~
make: *** [Makefile:35: build] Error 1

I have also tried only compile go-lxc from source, facing the exact same error.

DefaultConfigPath not consistent with GetConfigPath and SetConfigPath

DefaultConfigPath in the lxc-binding is setting the path to the container root.

func DefaultConfigPath() string {
	return GlobalConfigItem("lxc.lxcpath")
} 

It seems to be used consistently for this purpose, its in all the examples and seems to be working perfectly. However, its confusing because in container.go I'm seeing SetConfigPath described as being used to set the configuration file's path - not the container root - which it does via go_lxc_set_config_path, which is described as being used to set the path to the containers's config file here:

https://linuxcontainers.org/lxc/apidoc/structlxc__container.html#ad140523960327ab5537629ee8dc62dd3

ConfigPath is used in the same way in container.go via the lxc-binding call to go_lxc_get_config_path. So the getter and the setter seem to be consistent. But the DefaultConfigPath seems to be confusingly misnamed. It should probably be DefaultContainerRoot.

get_config_path is described here:

https://linuxcontainers.org/lxc/apidoc/structlxc__container.html#a3cdd629f0b11a313938178a46b18a263

I'm not sure about advice, because changing that would break things. Its used in the Hashicorp nomad driver.

Should I put up a pr to rename it? It just sounds too hazardous.

undefined reference to `lxc_config_item_is_supported'

Hi guys...
I just found this issue trying to compile lxd from the sources.

/tmp/go-build698508144/gopkg.in/lxc/go-lxc.v2/_obj/lxc-binding.o: In function `go_lxc_config_item_is_supported':
../../../gopkg.in/lxc/go-lxc.v2/lxc-binding.c:451: undefined reference to `lxc_config_item_is_supported'

For the moment I solved by returning true

Recommended way of getting command success status

It looks like the Attach/RunCommand helpers dont allow you to pick up on the result of the command.

Ideally we could return an os.ProcessResult, but even just getting an exit code/success status would fill my needs. I'm not familiar with the LXC C-api, but I could look into what's required to make this available.

Create fails when custom dir is specified; possible use-after-free?

Create exhibits unexpected behavior if you specify a custom options.BackendSpecs.Dir. I've made this simple modification to examples/create/create.go:

--- create.go.orig      2022-04-06 14:34:24.287690956 -0700
+++ create.go   2022-04-06 14:35:20.088339284 -0700
@@ -8,6 +8,7 @@

 import (
        "flag"
+       "fmt"
        "log"

        "github.com/lxc/go-lxc"
@@ -71,6 +72,7 @@
                }
        }

+       dir := fmt.Sprintf("%s/%s/rootfs",lxcpath,name)
        options := lxc.TemplateOptions{
                Template:             template,
                Distro:               distro,
@@ -81,6 +83,7 @@
                Backend:              backend,
                BackendSpecs: &lxc.BackendStoreSpecs{
                        FSSize: uint64(bdevSize),
+                       Dir: &dir,
                },
        }

This results in:

root@lxc:~# ./create -validation -verbose -distro centos -release 8-Stream -name testy
2022/04/06 14:40:25 Creating container...
Using image from local cache
Unpacking the rootfs
tar: /usr/share/lxc/templates/lxc-download: Cannot open: Not a directory
tar: Error is not recoverable: exiting now
2022/04/06 14:40:25 ERROR: creating the container failed

The created config file then contains:

lxc.log.file = log
lxc.log.level = DEBUG
lxc.rootfs.path = dir:/usr/share/lxc/templates/lxc-download

It seems that the list of arguments internally passed to liblxc somehow gets out-of-sync with what liblxc is expecting.

I haven't had a chance to track down the definitive cause, but I did see something that piqued my interest in container.go:2316 in buildBdevSpecs():

	if o.Dir != nil {
		dir := C.CString(*o.Dir)
		specs.dir = dir
		defer C.free(unsafe.Pointer(dir))
	}

I don't have much experience with cgo so forgive me if I'm misreading this, but if we allocate a C.CString and assign it to specs.dir, isn't it incorrect to then free it on return? Wouldn't this cause the dir field in the returned C.struct_bdev_specs to point to freed memory?

goimport delete "gopkg.in/lxc/go-lxc.v2"

goimport deleting import of package:

p1gmale0n@p1air /tmp/go-lxc/examples [v2]
± % goimports -d create.go

diff create.go gofmt/create.go
--- /var/folders/n5/zqjqxfbn1_51h4kqwlvk2x900000gn/T/gofmt301807076 2016-02-13 15:29:23.000000000 +0600
+++ /var/folders/n5/zqjqxfbn1_51h4kqwlvk2x900000gn/T/gofmt666373107 2016-02-13 15:29:23.000000000 +0600
@@ -9,8 +9,6 @@
 import (
    "flag"
    "log"
-
-   "gopkg.in/lxc/go-lxc.v2"
 )

 var (

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.