2013-10-28 22:46:49 +02:00
// +build linux
2013-03-30 12:14:57 -04:00
/ *
* container . go : Go bindings for lxc
*
* Copyright © 2013 , S . Çağlar Onur
*
* Authors :
* S . Çağlar Onur < caglar @ 10 ur . org >
*
2013-09-06 01:36:09 -04:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
* This library is distributed in the hope that it will be useful ,
2013-03-30 12:14:57 -04:00
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2013-09-06 01:36:09 -04:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2013-03-30 12:14:57 -04:00
* /
package lxc
// #include <lxc/lxc.h>
// #include <lxc/lxccontainer.h>
// #include "lxc.h"
import "C"
import (
2013-09-09 00:40:18 -04:00
"fmt"
2013-03-30 14:22:08 -04:00
"strconv"
2013-03-30 12:14:57 -04:00
"strings"
2013-04-03 12:38:41 -04:00
"sync"
2013-04-26 15:18:31 -04:00
"time"
2013-03-30 12:14:57 -04:00
"unsafe"
)
2013-09-09 00:40:18 -04:00
// Container struct
2013-03-30 12:14:57 -04:00
type Container struct {
container * C . struct_lxc_container
2013-09-09 00:40:18 -04:00
verbosity Verbosity
2013-04-03 12:38:41 -04:00
sync . RWMutex
2013-03-30 12:14:57 -04:00
}
2013-10-11 17:16:41 -04:00
// Snapshot struct
type Snapshot struct {
Name string
CommentPath string
Timestamp string
Path string
}
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) ensureDefinedAndRunning ( ) error {
if ! lxc . Defined ( ) {
return fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
if ! lxc . Running ( ) {
return fmt . Errorf ( errNotRunning , C . GoString ( lxc . container . name ) )
}
return nil
}
func ( lxc * Container ) ensureDefinedButNotRunning ( ) error {
if ! lxc . Defined ( ) {
return fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
if lxc . Running ( ) {
return fmt . Errorf ( errAlreadyRunning , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-09-09 00:40:18 -04:00
// Name returns container's name
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) Name ( ) string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return C . GoString ( lxc . container . name )
}
2013-09-09 00:40:18 -04:00
// Defined returns whether the container is already defined or not
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Defined ( ) bool {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return bool ( C . lxc_container_defined ( lxc . container ) )
}
2013-09-09 00:40:18 -04:00
// Running returns whether the container is already running or not
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Running ( ) bool {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return bool ( C . lxc_container_running ( lxc . container ) )
}
2013-09-30 16:41:17 -04:00
// MayControl returns whether the container is already running or not
func ( lxc * Container ) MayControl ( ) bool {
lxc . RLock ( )
defer lxc . RUnlock ( )
return bool ( C . lxc_container_may_control ( lxc . container ) )
}
2013-10-19 11:57:44 -04:00
// CreateSnapshot creates a new snapshot
func ( lxc * Container ) CreateSnapshot ( ) error {
2013-10-11 17:16:41 -04:00
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
return err
}
lxc . Lock ( )
defer lxc . Unlock ( )
if int ( C . lxc_container_snapshot ( lxc . container ) ) < 0 {
2013-10-19 11:57:44 -04:00
return fmt . Errorf ( errCreateSnapshotFailed , C . GoString ( lxc . container . name ) )
2013-10-11 17:16:41 -04:00
}
return nil
}
2013-10-19 11:57:44 -04:00
// RestoreSnapshot creates a new snapshot
func ( lxc * Container ) RestoreSnapshot ( snapshot Snapshot , name string ) error {
2013-10-11 17:16:41 -04:00
if ! lxc . Defined ( ) {
return fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
lxc . Lock ( )
defer lxc . Unlock ( )
cname := C . CString ( name )
defer C . free ( unsafe . Pointer ( cname ) )
csnapname := C . CString ( snapshot . Name )
defer C . free ( unsafe . Pointer ( csnapname ) )
if ! bool ( C . lxc_container_snapshot_restore ( lxc . container , csnapname , cname ) ) {
2013-10-19 11:57:44 -04:00
return fmt . Errorf ( errRestoreSnapshotFailed , C . GoString ( lxc . container . name ) )
2013-10-11 17:16:41 -04:00
}
return nil
}
2013-10-19 11:57:44 -04:00
// DestroySnapshot destroys the snapshot
func ( lxc * Container ) DestroySnapshot ( snapshot Snapshot ) error {
if ! lxc . Defined ( ) {
return fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
lxc . Lock ( )
defer lxc . Unlock ( )
csnapname := C . CString ( snapshot . Name )
defer C . free ( unsafe . Pointer ( csnapname ) )
if ! bool ( C . lxc_container_snapshot_destroy ( lxc . container , csnapname ) ) {
return fmt . Errorf ( errDestroySnapshotFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
// Snapshots lists the snapshot of given container
func ( lxc * Container ) Snapshots ( ) ( [ ] Snapshot , error ) {
2013-10-11 17:16:41 -04:00
if ! lxc . Defined ( ) {
return nil , fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
lxc . Lock ( )
defer lxc . Unlock ( )
2013-10-15 18:06:42 -04:00
var csnapshots * C . struct_lxc_snapshot
2013-10-11 17:16:41 -04:00
var snapshots [ ] Snapshot
2013-10-15 18:06:42 -04:00
size := int ( C . lxc_container_snapshot_list ( lxc . container , & csnapshots ) )
defer freeSnapshots ( csnapshots , size )
2013-10-11 17:16:41 -04:00
if size < 1 {
return nil , fmt . Errorf ( "%s has no snapshots" , C . GoString ( lxc . container . name ) )
}
2013-10-15 18:06:42 -04:00
p := uintptr ( unsafe . Pointer ( csnapshots ) )
2013-10-11 17:16:41 -04:00
for i := 0 ; i < size ; i ++ {
z := ( * C . struct_lxc_snapshot ) ( unsafe . Pointer ( p ) )
s := & Snapshot { Name : C . GoString ( z . name ) , Timestamp : C . GoString ( z . timestamp ) , CommentPath : C . GoString ( z . comment_pathname ) , Path : C . GoString ( z . lxcpath ) }
snapshots = append ( snapshots , * s )
2013-10-15 18:06:42 -04:00
p += unsafe . Sizeof ( * csnapshots )
2013-10-11 17:16:41 -04:00
}
return snapshots , nil
}
2013-09-09 00:40:18 -04:00
// State returns the container's state
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) State ( ) State {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return stateMap [ C . GoString ( C . lxc_container_state ( lxc . container ) ) ]
}
2013-09-09 00:40:18 -04:00
// InitPID returns the container's PID
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) InitPID ( ) int {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return int ( C . lxc_container_init_pid ( lxc . container ) )
}
2013-09-09 00:40:18 -04:00
// Daemonize returns whether the daemonize flag is set
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) Daemonize ( ) bool {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return bool ( lxc . container . daemonize != 0 )
}
2013-09-09 00:40:18 -04:00
// SetDaemonize sets the daemonize flag
2013-09-24 15:47:23 -04:00
func ( lxc * Container ) SetDaemonize ( ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
C . lxc_container_want_daemonize ( lxc . container )
2013-09-24 15:47:23 -04:00
if bool ( lxc . container . daemonize == 0 ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errDaemonizeFailed , C . GoString ( lxc . container . name ) )
2013-09-24 15:47:23 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-22 12:12:40 -04:00
// SetCloseAllFds sets the close_all_fds flag for the container
func ( lxc * Container ) SetCloseAllFds ( ) error {
lxc . Lock ( )
defer lxc . Unlock ( )
if ! bool ( C . lxc_container_want_close_all_fds ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errCloseAllFdsFailed , C . GoString ( lxc . container . name ) )
2013-09-22 12:12:40 -04:00
}
return nil
}
2013-09-09 00:40:18 -04:00
// SetVerbosity sets the verbosity level of some API calls
func ( lxc * Container ) SetVerbosity ( verbosity Verbosity ) {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
lxc . verbosity = verbosity
}
// Freeze freezes the running container
func ( lxc * Container ) Freeze ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
if lxc . State ( ) == FROZEN {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errAlreadyFrozen , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
lxc . Lock ( )
defer lxc . Unlock ( )
if ! bool ( C . lxc_container_freeze ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errFreezeFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Unfreeze unfreezes the frozen container
func ( lxc * Container ) Unfreeze ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
if lxc . State ( ) != FROZEN {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errNotFrozen , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_unfreeze ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errUnfreezeFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Create creates the container using given template and arguments
func ( lxc * Container ) Create ( template string , args ... string ) error {
2013-10-25 19:28:05 -04:00
// FIXME: Support bdevtype, bdev_specs and flags
2013-09-09 00:40:18 -04:00
if lxc . Defined ( ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errAlreadyDefined , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-03-30 12:14:57 -04:00
ctemplate := C . CString ( template )
defer C . free ( unsafe . Pointer ( ctemplate ) )
2013-09-09 00:40:18 -04:00
ret := false
2013-03-30 12:14:57 -04:00
if args != nil {
cargs := makeArgs ( args )
2013-09-17 21:29:29 -04:00
defer freeArgs ( cargs , len ( args ) )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
ret = bool ( C . lxc_container_create ( lxc . container , ctemplate , C . int ( lxc . verbosity ) , cargs ) )
2013-09-09 00:40:18 -04:00
} else {
ret = bool ( C . lxc_container_create ( lxc . container , ctemplate , C . int ( lxc . verbosity ) , nil ) )
}
if ! ret {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errCreateFailed , C . GoString ( lxc . container . name ) )
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Start starts the container
func ( lxc * Container ) Start ( useinit bool , args ... string ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
ret := false
2013-03-30 12:14:57 -04:00
cuseinit := 0
if useinit {
cuseinit = 1
}
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
if args != nil {
cargs := makeArgs ( args )
2013-09-17 21:29:29 -04:00
defer freeArgs ( cargs , len ( args ) )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
ret = bool ( C . lxc_container_start ( lxc . container , C . int ( cuseinit ) , cargs ) )
2013-09-09 00:40:18 -04:00
} else {
ret = bool ( C . lxc_container_start ( lxc . container , C . int ( cuseinit ) , nil ) )
}
if ! ret {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errStartFailed , C . GoString ( lxc . container . name ) )
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Stop stops the container
func ( lxc * Container ) Stop ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_stop ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errStopFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Reboot reboots the container
func ( lxc * Container ) Reboot ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-06-24 13:18:26 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_reboot ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errRebootFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-06-24 13:18:26 -04:00
}
2013-09-09 00:40:18 -04:00
// Shutdown shutdowns the container
func ( lxc * Container ) Shutdown ( timeout int ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_shutdown ( lxc . container , C . int ( timeout ) ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errShutdownFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Destroy destroys the container
func ( lxc * Container ) Destroy ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_destroy ( lxc . container ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errDestroyFailed , C . GoString ( lxc . container . name ) )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Clone clones the container
func ( lxc * Container ) Clone ( name string , flags int , backend BackendStore ) error {
2013-10-25 19:28:05 -04:00
// FIXME: support lxcpath, bdevtype, bdevdata, newsize and hookargs
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-04-24 19:32:25 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
cname := C . CString ( name )
defer C . free ( unsafe . Pointer ( cname ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_clone ( lxc . container , cname , C . int ( flags ) , C . CString ( backend . String ( ) ) ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errCloneFailed , C . GoString ( lxc . container . name ) )
2013-04-24 19:32:25 -04:00
}
2013-09-09 00:40:18 -04:00
return nil
}
// CloneToDirectory clones the container using Directory backendstore
func ( lxc * Container ) CloneToDirectory ( name string ) error {
return lxc . Clone ( name , 0 , Directory )
2013-04-24 19:32:25 -04:00
}
2013-10-25 19:28:05 -04:00
// CloneToBtrFS clones the container using BtrFS backendstore
func ( lxc * Container ) CloneToBtrFS ( name string ) error {
return lxc . Clone ( name , 0 , BtrFS )
}
2013-09-09 00:40:18 -04:00
// CloneToOverlayFS clones the container using OverlayFS backendstore
func ( lxc * Container ) CloneToOverlayFS ( name string ) error {
return lxc . Clone ( name , CloneSnapshot , OverlayFS )
2013-04-25 14:05:11 -04:00
}
2013-09-09 00:40:18 -04:00
// Wait waits till the container changes its state or timeouts
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Wait ( state State , timeout int ) bool {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cstate := C . CString ( state . String ( ) )
defer C . free ( unsafe . Pointer ( cstate ) )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return bool ( C . lxc_container_wait ( lxc . container , cstate , C . int ( timeout ) ) )
}
2013-09-09 00:40:18 -04:00
// ConfigFileName returns the container's configuration file's name
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) ConfigFileName ( ) string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
// allocated in lxc.c
configFileName := C . lxc_container_config_file_name ( lxc . container )
defer C . free ( unsafe . Pointer ( configFileName ) )
return C . GoString ( configFileName )
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// ConfigItem returns the value of the given key
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) ConfigItem ( key string ) [ ] string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
// 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 ) )
2013-03-30 12:14:57 -04:00
return strings . Split ( ret , "\n" )
}
2013-09-09 00:40:18 -04:00
// SetConfigItem sets the value of given key
func ( lxc * Container ) SetConfigItem ( key string , value string ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cvalue := C . CString ( value )
defer C . free ( unsafe . Pointer ( cvalue ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_set_config_item ( lxc . container , ckey , cvalue ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errSettingConfigItemFailed , C . GoString ( lxc . container . name ) , key , value )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// CgroupItem returns the value of the given key
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) CgroupItem ( key string ) [ ] string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
// 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 ) )
2013-03-30 12:14:57 -04:00
return strings . Split ( ret , "\n" )
}
2013-09-09 00:40:18 -04:00
// SetCgroupItem sets the value of given key
func ( lxc * Container ) SetCgroupItem ( key string , value string ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cvalue := C . CString ( value )
defer C . free ( unsafe . Pointer ( cvalue ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_set_cgroup_item ( lxc . container , ckey , cvalue ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errSettingCgroupItemFailed , C . GoString ( lxc . container . name ) , key , value )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// ClearConfigItem clears the value of given key
func ( lxc * Container ) ClearConfigItem ( key string ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_clear_config_item ( lxc . container , ckey ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errClearingCgroupItemFailed , C . GoString ( lxc . container . name ) , key )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// Keys returns the keys
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) Keys ( key string ) [ ] string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
ckey := C . CString ( key )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-09 00:40:18 -04:00
2013-09-17 21:29:29 -04:00
// 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 ) )
2013-03-30 12:14:57 -04:00
return strings . Split ( ret , "\n" )
}
2013-09-09 00:40:18 -04:00
// LoadConfigFile loads the configuration file from given path
func ( lxc * Container ) LoadConfigFile ( path string ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cpath := C . CString ( path )
defer C . free ( unsafe . Pointer ( cpath ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_load_config ( lxc . container , cpath ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errLoadConfigFailed , C . GoString ( lxc . container . name ) , path )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// SaveConfigFile saves the configuration file to given path
func ( lxc * Container ) SaveConfigFile ( path string ) error {
2013-04-03 12:38:41 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cpath := C . CString ( path )
defer C . free ( unsafe . Pointer ( cpath ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_save_config ( lxc . container , cpath ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errSaveConfigFailed , C . GoString ( lxc . container . name ) , path )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-09 00:40:18 -04:00
// ConfigPath returns the configuration file's path
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) ConfigPath ( ) string {
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return C . GoString ( C . lxc_container_get_config_path ( lxc . container ) )
}
2013-09-09 00:40:18 -04:00
// SetConfigPath sets the configuration file's path
func ( lxc * Container ) SetConfigPath ( path string ) error {
2013-04-23 00:04:51 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
cpath := C . CString ( path )
defer C . free ( unsafe . Pointer ( cpath ) )
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_set_config_path ( lxc . container , cpath ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errSettingConfigPathFailed , C . GoString ( lxc . container . name ) , path )
2013-09-09 00:40:18 -04:00
}
return nil
2013-03-30 12:14:57 -04:00
}
2013-09-29 00:45:28 -04:00
// MemoryUsage returns memory usage in bytes
func ( lxc * Container ) MemoryUsage ( ) ( ByteSize , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
memUsed , err := strconv . ParseFloat ( lxc . CgroupItem ( "memory.usage_in_bytes" ) [ 0 ] , 64 )
if err != nil {
2013-10-25 19:28:05 -04:00
return - 1 , fmt . Errorf ( errMemLimit )
2013-03-30 14:22:08 -04:00
}
2013-09-09 00:40:18 -04:00
return ByteSize ( memUsed ) , err
2013-03-30 14:22:08 -04:00
}
2013-09-29 00:45:28 -04:00
// SwapUsage returns swap usage in bytes
func ( lxc * Container ) SwapUsage ( ) ( ByteSize , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
swapUsed , err := strconv . ParseFloat ( lxc . CgroupItem ( "memory.memsw.usage_in_bytes" ) [ 0 ] , 64 )
if err != nil {
2013-10-25 19:28:05 -04:00
return - 1 , fmt . Errorf ( errSwapLimit )
2013-03-30 14:22:08 -04:00
}
2013-09-09 00:40:18 -04:00
return ByteSize ( swapUsed ) , err
2013-03-30 14:22:08 -04:00
}
2013-09-29 00:45:28 -04:00
// MemoryLimit returns memory limit in bytes
func ( lxc * Container ) MemoryLimit ( ) ( ByteSize , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
memLimit , err := strconv . ParseFloat ( lxc . CgroupItem ( "memory.limit_in_bytes" ) [ 0 ] , 64 )
if err != nil {
2013-10-25 19:28:05 -04:00
return - 1 , fmt . Errorf ( errMemLimit )
2013-03-30 14:22:08 -04:00
}
2013-09-09 00:40:18 -04:00
return ByteSize ( memLimit ) , err
2013-03-30 14:22:08 -04:00
}
2013-09-29 00:45:28 -04:00
// SetMemoryLimit sets memory limit in bytes
func ( lxc * Container ) SetMemoryLimit ( limit ByteSize ) error {
2013-09-28 21:10:16 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
2013-09-29 00:45:28 -04:00
if err := lxc . SetCgroupItem ( "memory.limit_in_bytes" , fmt . Sprintf ( "%.f" , limit ) ) ; err != nil {
2013-09-28 21:10:16 -04:00
return fmt . Errorf ( errSettingMemoryLimitFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-09-29 00:45:28 -04:00
// SwapLimit returns the swap limit in bytes
func ( lxc * Container ) SwapLimit ( ) ( ByteSize , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
swapLimit , err := strconv . ParseFloat ( lxc . CgroupItem ( "memory.memsw.limit_in_bytes" ) [ 0 ] , 64 )
if err != nil {
2013-10-25 19:28:05 -04:00
return - 1 , fmt . Errorf ( errSwapLimit )
2013-04-03 12:38:41 -04:00
}
2013-09-09 00:40:18 -04:00
return ByteSize ( swapLimit ) , err
2013-04-03 12:38:41 -04:00
}
2013-09-29 00:45:28 -04:00
// SetSwapLimit sets memory limit in bytes
func ( lxc * Container ) SetSwapLimit ( limit ByteSize ) error {
2013-09-28 21:10:16 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
2013-09-29 00:45:28 -04:00
if err := lxc . SetCgroupItem ( "memory.memsw.limit_in_bytes" , fmt . Sprintf ( "%.f" , limit ) ) ; err != nil {
2013-09-28 21:10:16 -04:00
return fmt . Errorf ( errSettingSwapLimitFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-09-09 00:40:18 -04:00
// CPUTime returns the total CPU time (in nanoseconds) consumed by all tasks in this cgroup (including tasks lower in the hierarchy).
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) CPUTime ( ) ( time . Duration , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
cpuUsage , err := strconv . ParseInt ( lxc . CgroupItem ( "cpuacct.usage" ) [ 0 ] , 10 , 64 )
if err != nil {
return - 1 , err
2013-03-30 14:22:08 -04:00
}
2013-09-09 00:40:18 -04:00
return time . Duration ( cpuUsage ) , err
2013-03-30 12:14:57 -04:00
}
2013-04-03 12:38:41 -04:00
2013-09-09 00:40:18 -04:00
// CPUTimePerCPU returns the CPU time (in nanoseconds) consumed on each CPU by all tasks in this cgroup (including tasks lower in the hierarchy).
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) CPUTimePerCPU ( ) ( [ ] time . Duration , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-04-03 12:38:41 -04:00
var cpuTimes [ ] time . Duration
2013-09-09 00:40:18 -04:00
for _ , v := range strings . Split ( lxc . CgroupItem ( "cpuacct.usage_percpu" ) [ 0 ] , " " ) {
cpuUsage , err := strconv . ParseInt ( v , 10 , 64 )
if err != nil {
return nil , err
2013-04-03 12:38:41 -04:00
}
2013-09-09 00:40:18 -04:00
cpuTimes = append ( cpuTimes , time . Duration ( cpuUsage ) )
2013-04-03 12:38:41 -04:00
}
2013-09-09 00:40:18 -04:00
return cpuTimes , nil
2013-04-03 12:38:41 -04:00
}
2013-09-09 00:40:18 -04:00
// CPUStats returns the number of CPU cycles (in the units defined by USER_HZ on the system) consumed by tasks in this cgroup and its children in both user mode and system (kernel) mode.
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) CPUStats ( ) ( [ ] int64 , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-09 00:40:18 -04:00
}
2013-04-03 12:38:41 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-09 00:40:18 -04:00
cpuStat := lxc . CgroupItem ( "cpuacct.stat" )
user , err := strconv . ParseInt ( strings . Split ( cpuStat [ 0 ] , " " ) [ 1 ] , 10 , 64 )
if err != nil {
return nil , err
}
system , err := strconv . ParseInt ( strings . Split ( cpuStat [ 1 ] , " " ) [ 1 ] , 10 , 64 )
if err != nil {
return nil , err
2013-04-03 12:38:41 -04:00
}
2013-09-09 00:40:18 -04:00
return [ ] int64 { user , system } , nil
2013-04-03 12:38:41 -04:00
}
2013-09-05 01:15:05 -04:00
2013-09-09 00:40:18 -04:00
// ConsoleGetFD allocates a console tty from container
func ( lxc * Container ) ConsoleGetFD ( ttynum int ) ( int , error ) {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return - 1 , err
2013-09-09 00:40:18 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-05 01:15:05 -04:00
2013-09-09 00:40:18 -04:00
ret := int ( C . lxc_container_console_getfd ( lxc . container , C . int ( ttynum ) ) )
if ret < 0 {
2013-09-27 16:34:05 -04:00
return - 1 , fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
2013-09-05 01:15:05 -04:00
}
2013-09-09 00:40:18 -04:00
return ret , nil
2013-09-05 01:15:05 -04:00
}
2013-09-09 00:40:18 -04:00
// Console allocates and runs a console tty from container
func ( lxc * Container ) Console ( ttynum , stdinfd , stdoutfd , stderrfd , escape int ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-09 00:40:18 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . Lock ( )
defer lxc . Unlock ( )
2013-09-05 01:15:05 -04:00
2013-09-09 00:40:18 -04:00
if ! bool ( C . lxc_container_console ( lxc . container , C . int ( ttynum ) , C . int ( stdinfd ) , C . int ( stdoutfd ) , C . int ( stderrfd ) , C . int ( escape ) ) ) {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
2013-09-05 01:15:05 -04:00
}
2013-09-09 00:40:18 -04:00
return nil
2013-09-05 01:15:05 -04:00
}
2013-09-17 21:29:29 -04:00
2013-09-17 23:47:47 -04:00
// AttachRunShell runs a shell inside the container
func ( lxc * Container ) AttachRunShell ( ) error {
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-17 23:47:47 -04:00
}
lxc . Lock ( )
defer lxc . Unlock ( )
ret := int ( C . lxc_container_attach ( lxc . container ) )
if ret < 0 {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
2013-09-17 23:47:47 -04:00
}
return nil
}
// AttachRunCommand runs user specified command inside the container and waits it
func ( lxc * Container ) AttachRunCommand ( args ... string ) error {
if args == nil {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errInsufficientNumberOfArguments )
2013-09-17 23:47:47 -04:00
}
2013-09-27 16:34:05 -04:00
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
2013-09-17 23:47:47 -04:00
}
lxc . Lock ( )
defer lxc . Unlock ( )
cargs := makeArgs ( args )
defer freeArgs ( cargs , len ( args ) )
ret := int ( C . lxc_container_attach_run_wait ( lxc . container , cargs ) )
if ret < 0 {
2013-09-27 16:34:05 -04:00
return fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
2013-09-17 23:47:47 -04:00
}
return nil
}
2013-09-17 21:29:29 -04:00
// Interfaces returns the name of the interfaces from the container
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) Interfaces ( ) ( [ ] string , error ) {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-17 21:29:29 -04:00
}
lxc . RLock ( )
defer lxc . RUnlock ( )
result := C . lxc_container_get_interfaces ( lxc . container )
if result == nil {
2013-09-27 16:34:05 -04:00
return nil , fmt . Errorf ( errInterfaces , C . GoString ( lxc . container . name ) )
2013-09-17 21:29:29 -04:00
}
2013-09-27 16:34:05 -04:00
return convertArgs ( result ) , nil
2013-09-17 21:29:29 -04:00
}
// IPAddress returns the IP address of the given interface
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) IPAddress ( interfaceName string ) ( [ ] string , error ) {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-17 21:29:29 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-17 21:29:29 -04:00
cinterface := C . CString ( interfaceName )
defer C . free ( unsafe . Pointer ( cinterface ) )
result := C . lxc_container_get_ips ( lxc . container , cinterface , nil , 0 )
if result == nil {
2013-09-27 16:34:05 -04:00
return nil , fmt . Errorf ( errIPAddress , interfaceName , C . GoString ( lxc . container . name ) )
2013-09-17 21:29:29 -04:00
}
2013-09-27 16:34:05 -04:00
return convertArgs ( result ) , nil
2013-09-17 21:29:29 -04:00
}
// IPAddresses returns all IP addresses from the container
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) IPAddresses ( ) ( [ ] string , error ) {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-17 21:29:29 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-17 21:29:29 -04:00
result := C . lxc_container_get_ips ( lxc . container , nil , nil , 0 )
if result == nil {
2013-09-27 16:34:05 -04:00
return nil , fmt . Errorf ( errIPAddresses , C . GoString ( lxc . container . name ) )
2013-09-17 21:29:29 -04:00
}
2013-09-27 16:34:05 -04:00
return convertArgs ( result ) , nil
2013-09-17 21:29:29 -04:00
}
// IPv4Addresses returns all IPv4 addresses from the container
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) IPv4Addresses ( ) ( [ ] string , error ) {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-17 21:29:29 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-17 21:29:29 -04:00
cfamily := C . CString ( "inet" )
defer C . free ( unsafe . Pointer ( cfamily ) )
result := C . lxc_container_get_ips ( lxc . container , nil , cfamily , 0 )
if result == nil {
2013-09-27 16:34:05 -04:00
return nil , fmt . Errorf ( errIPv4Addresses , C . GoString ( lxc . container . name ) )
2013-09-17 21:29:29 -04:00
}
2013-09-27 16:34:05 -04:00
return convertArgs ( result ) , nil
2013-09-17 21:29:29 -04:00
}
// IPv6Addresses returns all IPv6 addresses from the container
2013-09-27 16:34:05 -04:00
func ( lxc * Container ) IPv6Addresses ( ) ( [ ] string , error ) {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return nil , err
2013-09-17 21:29:29 -04:00
}
2013-09-17 23:47:47 -04:00
lxc . RLock ( )
defer lxc . RUnlock ( )
2013-09-17 21:29:29 -04:00
cfamily := C . CString ( "inet6" )
defer C . free ( unsafe . Pointer ( cfamily ) )
result := C . lxc_container_get_ips ( lxc . container , nil , cfamily , 0 )
if result == nil {
2013-09-27 16:34:05 -04:00
return nil , fmt . Errorf ( errIPv6Addresses , C . GoString ( lxc . container . name ) )
2013-09-17 21:29:29 -04:00
}
2013-09-27 16:34:05 -04:00
return convertArgs ( result ) , nil
2013-09-17 21:29:29 -04:00
}