1
0
mirror of https://github.com/lxc/go-lxc.git synced 2026-02-05 15:47:17 +01:00

introduce get_ips support, improvements for cgo allocated memory

This commit is contained in:
S.Çağlar Onur
2013-09-17 21:29:29 -04:00
parent 7fc6496fa3
commit 422c908d2a
8 changed files with 330 additions and 34 deletions

2
.gitignore vendored
View File

@@ -9,6 +9,8 @@ examples/console
examples/create
examples/destroy
examples/freeze
examples/interfaces
examples/ipaddress
examples/list
examples/shutdown
examples/start

View File

@@ -171,9 +171,9 @@ func (lxc *Container) Create(template string, args ...string) error {
ret := false
if args != nil {
cargs := makeArgs(args)
defer freeArgs(cargs)
defer freeArgs(cargs, len(args))
ret = bool(C.lxc_container_create(lxc.container, ctemplate, C.int(lxc.verbosity), &cargs[0]))
ret = bool(C.lxc_container_create(lxc.container, ctemplate, C.int(lxc.verbosity), cargs))
} else {
ret = bool(C.lxc_container_create(lxc.container, ctemplate, C.int(lxc.verbosity), nil))
}
@@ -206,9 +206,9 @@ func (lxc *Container) Start(useinit bool, args ...string) error {
if args != nil {
cargs := makeArgs(args)
defer freeArgs(cargs)
defer freeArgs(cargs, len(args))
ret = bool(C.lxc_container_start(lxc.container, C.int(cuseinit), &cargs[0]))
ret = bool(C.lxc_container_start(lxc.container, C.int(cuseinit), cargs))
} else {
ret = bool(C.lxc_container_start(lxc.container, C.int(cuseinit), nil))
}
@@ -343,7 +343,11 @@ func (lxc *Container) ConfigFileName() string {
lxc.RLock()
defer lxc.RUnlock()
return C.GoString(C.lxc_container_config_file_name(lxc.container))
// allocated in lxc.c
configFileName := C.lxc_container_config_file_name(lxc.container)
defer C.free(unsafe.Pointer(configFileName))
return C.GoString(configFileName)
}
// ConfigItem returns the value of the given key
@@ -354,7 +358,11 @@ func (lxc *Container) ConfigItem(key string) []string {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
ret := strings.TrimSpace(C.GoString(C.lxc_container_get_config_item(lxc.container, ckey)))
// allocated in lxc.c
configItem := C.lxc_container_get_config_item(lxc.container, ckey)
defer C.free(unsafe.Pointer(configItem))
ret := strings.TrimSpace(C.GoString(configItem))
return strings.Split(ret, "\n")
}
@@ -383,7 +391,11 @@ func (lxc *Container) CgroupItem(key string) []string {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
ret := strings.TrimSpace(C.GoString(C.lxc_container_get_cgroup_item(lxc.container, ckey)))
// allocated in lxc.c
cgroupItem := C.lxc_container_get_cgroup_item(lxc.container, ckey)
defer C.free(unsafe.Pointer(cgroupItem))
ret := strings.TrimSpace(C.GoString(cgroupItem))
return strings.Split(ret, "\n")
}
@@ -426,7 +438,11 @@ func (lxc *Container) Keys(key string) []string {
ckey := C.CString(key)
defer C.free(unsafe.Pointer(ckey))
ret := strings.TrimSpace(C.GoString(C.lxc_container_get_keys(lxc.container, ckey)))
// allocated in lxc.c
keys := C.lxc_container_get_keys(lxc.container, ckey)
defer C.free(unsafe.Pointer(keys))
ret := strings.TrimSpace(C.GoString(keys))
return strings.Split(ret, "\n")
}
@@ -480,17 +496,6 @@ func (lxc *Container) SetConfigPath(path string) error {
return nil
}
// NumberOfNetworkInterfaces returns the number of network interfaces
func (lxc *Container) NumberOfNetworkInterfaces() int {
lxc.RLock()
defer lxc.RUnlock()
if lxc.Running() {
return len(lxc.ConfigItem("lxc.network"))
}
return -1
}
// MemoryUsageInBytes returns memory usage in bytes
func (lxc *Container) MemoryUsageInBytes() (ByteSize, error) {
if !lxc.Defined() {
@@ -679,3 +684,112 @@ func (lxc *Container) Console(ttynum, stdinfd, stdoutfd, stderrfd, escape int) e
}
return nil
}
/*
// Interfaces returns the name of the interfaces from the container
func (lxc *Container) Interfaces() (error, []string) {
if !lxc.Defined() {
return fmt.Errorf("there is no container named %q", C.GoString(lxc.container.name)), nil
}
if !lxc.Running() {
return fmt.Errorf("container %q is not running", C.GoString(lxc.container.name)), nil
}
lxc.RLock()
defer lxc.RUnlock()
result := C.lxc_container_get_interfaces(lxc.container)
if result == nil {
return fmt.Errorf("getting interface names for the container %q failed", C.GoString(lxc.container.name)), nil
}
return nil, convertArgs(result)
}
*/
// IPAddress returns the IP address of the given interface
func (lxc *Container) IPAddress(interfaceName string) (error, []string) {
if !lxc.Defined() {
return fmt.Errorf("there is no container named %q", C.GoString(lxc.container.name)), nil
}
if !lxc.Running() {
return fmt.Errorf("container %q is not running", C.GoString(lxc.container.name)), nil
}
lxc.Lock()
defer lxc.Unlock()
cinterface := C.CString(interfaceName)
defer C.free(unsafe.Pointer(cinterface))
result := C.lxc_container_get_ips(lxc.container, cinterface, nil, 0)
if result == nil {
return fmt.Errorf("getting IP address of the interface %s for the container %q failed", interfaceName, C.GoString(lxc.container.name)), nil
}
return nil, convertArgs(result)
}
// IPAddresses returns all IP addresses from the container
func (lxc *Container) IPAddresses() (error, []string) {
if !lxc.Defined() {
return fmt.Errorf("there is no container named %q", C.GoString(lxc.container.name)), nil
}
if !lxc.Running() {
return fmt.Errorf("container %q is not running", C.GoString(lxc.container.name)), nil
}
lxc.Lock()
defer lxc.Unlock()
result := C.lxc_container_get_ips(lxc.container, nil, nil, 0)
if result == nil {
return fmt.Errorf("getting IP addresses for the container %q failed", C.GoString(lxc.container.name)), nil
}
return nil, convertArgs(result)
}
// IPv4Addresses returns all IPv4 addresses from the container
func (lxc *Container) IPv4Addresses() (error, []string) {
if !lxc.Defined() {
return fmt.Errorf("there is no container named %q", C.GoString(lxc.container.name)), nil
}
if !lxc.Running() {
return fmt.Errorf("container %q is not running", C.GoString(lxc.container.name)), nil
}
lxc.Lock()
defer lxc.Unlock()
cfamily := C.CString("inet")
defer C.free(unsafe.Pointer(cfamily))
result := C.lxc_container_get_ips(lxc.container, nil, cfamily, 0)
if result == nil {
return fmt.Errorf("getting IPv4 addresses for the container %q failed", C.GoString(lxc.container.name)), nil
}
return nil, convertArgs(result)
}
// IPv6Addresses returns all IPv6 addresses from the container
func (lxc *Container) IPv6Addresses() (error, []string) {
if !lxc.Defined() {
return fmt.Errorf("there is no container named %q", C.GoString(lxc.container.name)), nil
}
if !lxc.Running() {
return fmt.Errorf("container %q is not running", C.GoString(lxc.container.name)), nil
}
lxc.Lock()
defer lxc.Unlock()
cfamily := C.CString("inet6")
defer C.free(unsafe.Pointer(cfamily))
result := C.lxc_container_get_ips(lxc.container, nil, cfamily, 0)
if result == nil {
return fmt.Errorf("getting IPv6 addresses for the container %q failed", C.GoString(lxc.container.name)), nil
}
return nil, convertArgs(result)
}

54
examples/interfaces.go Normal file
View File

@@ -0,0 +1,54 @@
/*
* interfaces.go
*
* Copyright © 2013, S.Çağlar Onur
*
* Authors:
* S.Çağlar Onur <caglar@10ur.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package main
import (
"flag"
"fmt"
"github.com/caglar10ur/lxc"
)
var (
name string
)
func init() {
flag.StringVar(&name, "name", "rubik", "Name of the original container")
flag.Parse()
}
func main() {
c := lxc.NewContainer(name)
defer lxc.PutContainer(c)
fmt.Printf("Interfaces\n")
/*
if err, interfaces := c.Interfaces(); err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, v := range interfaces {
fmt.Printf("%d) %s\n", i, v)
}
}
*/
}

77
examples/ipaddress.go Normal file
View File

@@ -0,0 +1,77 @@
/*
* ipaddress.go
*
* Copyright © 2013, S.Çağlar Onur
*
* Authors:
* S.Çağlar Onur <caglar@10ur.org>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package main
import (
"flag"
"fmt"
"github.com/caglar10ur/lxc"
)
var (
name string
)
func init() {
flag.StringVar(&name, "name", "rubik", "Name of the original container")
flag.Parse()
}
func main() {
c := lxc.NewContainer(name)
defer lxc.PutContainer(c)
fmt.Printf("IPAddress(\"lo\")\n")
if err, addresses := c.IPAddress("lo"); err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, v := range addresses {
fmt.Printf("%d) %s\n", i, v)
}
}
fmt.Printf("IPAddresses()\n")
if err, addresses := c.IPAddresses(); err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, v := range addresses {
fmt.Printf("%d) %s\n", i, v)
}
}
fmt.Printf("IPv4Addresses()\n")
if err, addresses := c.IPv4Addresses(); err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, v := range addresses {
fmt.Printf("%d) %s\n", i, v)
}
}
fmt.Printf("IPv6Addresses()\n")
if err, addresses := c.IPv6Addresses(); err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
for i, v := range addresses {
fmt.Printf("%d) %s\n", i, v)
}
}
}

9
lxc.c
View File

@@ -21,7 +21,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdbool.h>
#include <lxc/lxc.h>
@@ -174,3 +173,11 @@ extern bool lxc_container_console(struct lxc_container *c, int ttynum, int stdin
}
return false;
}
extern char** lxc_container_get_interfaces(struct lxc_container *c) {
return c->get_interfaces(c);
}
extern char** lxc_container_get_ips(struct lxc_container *c, char *interface, char *family, int scope) {
return c->get_ips(c, interface, family, scope);
}

2
lxc.h
View File

@@ -50,6 +50,8 @@ extern int lxc_container_console_getfd(struct lxc_container *, int);
extern pid_t lxc_container_init_pid(struct lxc_container *);
extern void lxc_container_want_daemonize(struct lxc_container *);
extern char** lxc_container_get_interfaces(struct lxc_container *);
extern char** lxc_container_get_ips(struct lxc_container *, char *, char *, int);
//FIXME: Missing API functionality
// char** (*get_ips)(struct lxc_container *c, char* interface, char* family, int scope);
// int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process);

View File

@@ -369,12 +369,16 @@ func TestKeys(t *testing.T) {
}
}
func TestNumberOfNetworkInterfaces(t *testing.T) {
func TestInterfaces(t *testing.T) {
z := NewContainer(ContainerName)
defer PutContainer(z)
if z.NumberOfNetworkInterfaces() != 1 {
t.Errorf("NumberOfNetworkInterfaces failed...")
if err, interfaces := z.Interfaces(); err != nil {
t.Errorf(err.Error())
} else {
for i, v := range interfaces {
fmt.Printf("%d) %s\n", i, v)
}
}
}

58
util.go
View File

@@ -23,24 +23,60 @@
package lxc
// #include <stdlib.h>
/*
#include <stdlib.h>
static char** makeCharArray(int size) {
return calloc(sizeof(char*), size);
}
static void setArrayString(char **array, char *string, int n) {
array[n] = string;
}
static void freeCharArray(char **array, int size) {
int i;
for (i = 0; i < size; i++)
free(array[i]);
free(array);
}
*/
import "C"
import (
"unsafe"
)
func makeArgs(args []string) []*C.char {
ret := make([]*C.char, len(args)+1)
for i, s := range args {
ret[i] = C.CString(s)
}
ret[len(ret)-1] = nil
return ret
func sptr(p uintptr) *C.char {
return *(**C.char)(unsafe.Pointer(p))
}
func freeArgs(cArgs []*C.char) {
for _, s := range cArgs {
C.free(unsafe.Pointer(s))
func makeArgs(args []string) **C.char {
cparams := C.makeCharArray(C.int(len(args)))
for i, s := range args {
C.setArrayString(cparams, C.CString(s), C.int(i))
}
return cparams
}
func freeArgs(cArgs **C.char, length int) {
C.freeCharArray(cArgs, C.int(length))
}
func convertArgs(cArgs **C.char) []string {
if cArgs == nil {
return nil
}
var s []string
// duplicate
for p := uintptr(unsafe.Pointer(cArgs)); sptr(p) != nil; p += unsafe.Sizeof(uintptr(0)) {
s = append(s, C.GoString(sptr(p)))
}
// free the original
C.freeCharArray(cArgs, C.int(len(s)))
return s
}