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:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,6 +9,8 @@ examples/console
|
||||
examples/create
|
||||
examples/destroy
|
||||
examples/freeze
|
||||
examples/interfaces
|
||||
examples/ipaddress
|
||||
examples/list
|
||||
examples/shutdown
|
||||
examples/start
|
||||
|
||||
152
container.go
152
container.go
@@ -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
54
examples/interfaces.go
Normal 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
77
examples/ipaddress.go
Normal 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
9
lxc.c
@@ -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
2
lxc.h
@@ -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);
|
||||
|
||||
10
lxc_test.go
10
lxc_test.go
@@ -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
58
util.go
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user