2013-10-28 23:32:39 -04:00
// Copyright © 2013, S.Çağlar Onur
// Use of this source code is governed by a LGPLv2.1
// license that can be found in the LICENSE file.
//
// Authors:
// S.Çağlar Onur <caglar@10ur.org>
2013-09-06 01:36:09 -04:00
2013-10-28 23:32:39 -04:00
// +build linux
2013-03-30 12:14:57 -04:00
package lxc
// #include <lxc/lxccontainer.h>
// #include "lxc.h"
import "C"
import (
2013-09-09 00:40:18 -04:00
"fmt"
2013-11-22 00:21:37 -05:00
"os/exec"
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-12-07 17:18:36 -05:00
mu 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-12-02 21:22:24 -05:00
// Name returns the name of the container
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) Name ( ) string {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-03-30 12:14:57 -04:00
return C . GoString ( lxc . container . name )
}
2013-12-02 21:22:24 -05:00
// Defined returns true if the container is already defined
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Defined ( ) bool {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// Running returns true if the container is already running
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Running ( ) bool {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// MayControl returns true if the caller may control the container
2013-09-30 16:41:17 -04:00
func ( lxc * Container ) MayControl ( ) bool {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . RUnlock ( )
2013-09-30 16:41:17 -04:00
return bool ( C . lxc_container_may_control ( lxc . container ) )
}
2013-10-19 11:57:44 -04:00
// CreateSnapshot creates a new snapshot
2014-01-12 14:19:25 -05:00
func ( lxc * Container ) CreateSnapshot ( ) ( * Snapshot , error ) {
2013-10-11 17:16:41 -04:00
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
2014-01-12 14:19:25 -05:00
return nil , err
2013-10-11 17:16:41 -04:00
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-10-11 17:16:41 -04:00
2014-01-12 14:19:25 -05:00
ret := int ( C . lxc_container_snapshot ( lxc . container ) )
if ret < 0 {
return nil , fmt . Errorf ( errCreateSnapshotFailed , C . GoString ( lxc . container . name ) )
2013-10-11 17:16:41 -04:00
}
2014-01-12 14:19:25 -05:00
return & Snapshot { Name : fmt . Sprintf ( "snap%d" , ret ) } , nil
2013-10-11 17:16:41 -04:00
}
2013-12-02 21:22:24 -05:00
// RestoreSnapshot creates a new container based on a snapshot
2013-10-19 11:57:44 -04:00
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 ) )
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-10-11 17:16:41 -04:00
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-12-02 21:22:24 -05:00
// DestroySnapshot destroys the specified snapshot
2013-10-19 11:57:44 -04:00
func ( lxc * Container ) DestroySnapshot ( snapshot Snapshot ) error {
if ! lxc . Defined ( ) {
return fmt . Errorf ( errNotDefined , C . GoString ( lxc . container . name ) )
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-10-19 11:57:44 -04:00
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
}
2013-12-02 21:22:24 -05:00
// Snapshots returns the list of container snapshots
2013-10-19 11:57:44 -04:00
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 ) )
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// State returns the state of the container
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) State ( ) State {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// InitPID returns the process ID of the container's init process seen from outside the container
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) InitPID ( ) int {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// Daemonize returns whether the container wished to be daemonized
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) Daemonize ( ) bool {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-11-29 18:42:33 -05:00
return bool ( lxc . container . daemonize )
2013-03-30 12:14:57 -04:00
}
2013-12-02 21:22:24 -05:00
// WantDaemonize sets the daemonize flag for the container
2013-11-29 18:42:33 -05:00
func ( lxc * Container ) WantDaemonize ( state bool ) error {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-09-09 00:40:18 -04:00
2013-11-29 18:42:33 -05:00
if ! bool ( C . lxc_container_want_daemonize ( lxc . container , C . bool ( state ) ) ) {
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-11-29 18:42:33 -05:00
// WantCloseAllFds sets the close_all_fds flag for the container
func ( lxc * Container ) WantCloseAllFds ( state bool ) error {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-09-22 12:12:40 -04:00
2013-11-29 18:42:33 -05:00
if ! bool ( C . lxc_container_want_close_all_fds ( lxc . container , C . bool ( state ) ) ) {
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-09-09 00:40:18 -04:00
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-12-02 21:22:24 -05:00
// Unfreeze thaws the frozen container
2013-09-09 00:40:18 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-11-10 22:30:29 -05:00
// FIXME: Support bdevtype and bdev_specs
// bdevtypes:
// "btrfs", "zfs", "lvm", "dir"
//
2013-11-18 00:50:34 -05:00
// best tries to find the best backing store type
2013-11-10 22:30:29 -05:00
//
// bdev_specs:
// zfs requires zfsroot
// lvm requires lvname/vgname/thinpool as well as fstype and fssize
// btrfs requires nothing
// dir requires nothing
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-04-03 12:38:41 -04:00
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
2013-11-18 00:50:34 -05:00
cbdevtype := C . CString ( "dir" )
2013-11-10 22:30:29 -05:00
defer C . free ( unsafe . Pointer ( cbdevtype ) )
2013-09-09 00:40:18 -04:00
ret := false
2013-03-30 12:14:57 -04:00
if args != nil {
2013-11-18 00:50:34 -05:00
cargs := makeNullTerminatedArgs ( args )
defer freeNullTerminatedArgs ( cargs , len ( args ) )
2013-09-09 00:40:18 -04:00
2013-11-10 22:30:29 -05:00
ret = bool ( C . lxc_container_create ( lxc . container , ctemplate , cbdevtype , C . int ( lxc . verbosity ) , cargs ) )
2013-09-09 00:40:18 -04:00
} else {
2013-11-10 22:30:29 -05:00
ret = bool ( C . lxc_container_create ( lxc . container , ctemplate , cbdevtype , C . int ( lxc . verbosity ) , nil ) )
2013-09-09 00:40:18 -04:00
}
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
2013-11-18 00:50:34 -05:00
func ( lxc * Container ) Start ( ) 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-04-03 12:38:41 -04:00
2013-11-18 15:49:26 -05:00
if ! bool ( C . lxc_container_start ( lxc . container , 0 , nil ) ) {
2013-11-18 00:50:34 -05:00
return fmt . Errorf ( errStartFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-09-09 00:40:18 -04:00
2013-12-02 21:22:24 -05:00
// Execute executes the given command in a temporary container
2013-11-22 00:21:37 -05:00
func ( lxc * Container ) Execute ( args ... string ) ( [ ] byte , error ) {
if lxc . Defined ( ) {
return nil , fmt . Errorf ( errAlreadyDefined , C . GoString ( lxc . container . name ) )
}
2013-09-09 00:40:18 -04:00
2013-11-22 00:21:37 -05:00
cargs := [ ] string { "lxc-execute" , "-n" , lxc . Name ( ) , "-P" , lxc . ConfigPath ( ) , "--" }
cargs = append ( cargs , args ... )
2013-09-09 00:40:18 -04:00
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-11-22 00:21:37 -05:00
/ *
* FIXME : Go runtime and src / lxc / start . c signal_handler are not playing nice together so use lxc - execute for now
* /
output , err := exec . Command ( cargs [ 0 ] , cargs [ 1 : ] ... ) . CombinedOutput ( )
if err != nil {
return nil , fmt . Errorf ( errExecuteFailed , C . GoString ( lxc . container . name ) )
}
return output , nil
/ *
2013-11-18 15:49:26 -05:00
cargs := makeNullTerminatedArgs ( args )
defer freeNullTerminatedArgs ( cargs , len ( args ) )
2013-09-09 00:40:18 -04:00
2013-11-18 15:49:26 -05:00
if ! bool ( C . lxc_container_start ( lxc . container , 1 , cargs ) ) {
return fmt . Errorf ( errExecuteFailed , C . GoString ( lxc . container . name ) )
}
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-11-10 22:30:29 -05:00
//
// bdevtypes:
// "btrfs", "zfs", "lvm", "dir" "overlayfs"
//
// bdevdata:
// zfs requires zfsroot
// lvm requires lvname/vgname/thinpool as well as fstype and fssize
// btrfs requires nothing
// dir requires nothing
//
// flags: LXC_CLONE_SNAPSHOT || LXC_CLONE_KEEPNAME || LXC_CLONE_KEEPMACADDR || LXC_CLONE_COPYHOOKS
//
// newsize: for blockdev-backed backingstores
//
// hookargs: additional arguments to pass to the clone hook script
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-04-24 19:32:25 -04:00
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
}
2014-01-14 11:02:20 -05:00
// CloneToBtrfs clones the container using Btrfs backendstore
func ( lxc * Container ) CloneToBtrfs ( name string ) error {
return lxc . Clone ( name , 0 , Btrfs )
2013-10-25 19:28:05 -04:00
}
2014-01-14 11:02:20 -05: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-12-18 21:15:42 -05:00
// Rename renames the container
func ( lxc * Container ) Rename ( name string ) error {
if err := lxc . ensureDefinedButNotRunning ( ) ; err != nil {
return err
}
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
cname := C . CString ( name )
defer C . free ( unsafe . Pointer ( cname ) )
if ! bool ( C . lxc_container_rename ( lxc . container , cname ) ) {
return fmt . Errorf ( errRenameFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-12-02 21:22:24 -05:00
// Wait waits for container to reach a given state or timeouts
2013-03-30 12:14:57 -04:00
func ( lxc * Container ) Wait ( state State , timeout int ) bool {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// ConfigItem returns the value of the given config item
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) ConfigItem ( key string ) [ ] string {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// SetConfigItem sets the value of the given config item
2013-09-09 00:40:18 -04:00
func ( lxc * Container ) SetConfigItem ( key string , value string ) error {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// CgroupItem returns the value of the given cgroup subsystem value
2013-04-23 00:04:51 -04:00
func ( lxc * Container ) CgroupItem ( key string ) [ ] string {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// SetCgroupItem sets the value of given cgroup subsystem value
2013-09-09 00:40:18 -04:00
func ( lxc * Container ) SetCgroupItem ( key string , value string ) error {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// ClearConfigItem clears the value of given config item
2013-09-09 00:40:18 -04:00
func ( lxc * Container ) ClearConfigItem ( key string ) error {
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// ConfigKeys returns the names of the config items
2013-11-10 22:30:29 -05:00
func ( lxc * Container ) ConfigKeys ( key ... string ) [ ] string {
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . RUnlock ( )
2013-09-09 00:40:18 -04:00
2013-11-10 22:30:29 -05:00
var keys * _Ctype_char
2013-09-09 00:40:18 -04:00
2013-11-10 22:30:29 -05:00
if key != nil && len ( key ) == 1 {
ckey := C . CString ( key [ 0 ] )
defer C . free ( unsafe . Pointer ( ckey ) )
2013-09-17 21:29:29 -04:00
2013-11-10 22:30:29 -05:00
// allocated in lxc.c
keys = C . lxc_container_get_keys ( lxc . container , ckey )
defer C . free ( unsafe . Pointer ( keys ) )
} else {
// allocated in lxc.c
keys = C . lxc_container_get_keys ( lxc . container , nil )
defer C . free ( unsafe . Pointer ( keys ) )
}
2013-09-17 21:29:29 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// MemoryUsage returns memory usage of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// SwapUsage returns swap usage of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// MemoryLimit returns memory limit of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// SetMemoryLimit sets memory limit of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-02 21:22:24 -05:00
// SwapLimit returns the swap limit of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-02 21:22:24 -05:00
// SetSwapLimit sets memory limit of the container in bytes
2013-09-29 00:45:28 -04:00
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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
2013-11-10 22:30:29 -05:00
// ttynum: tty number to attempt to allocate or -1 to allocate the first available tty
//
// Returns "ttyfd" on success, -1 on failure. The returned "ttyfd" is
// used to keep the tty allocated. The caller should close "ttyfd" to
// indicate that it is done with the allocated console so that it can
// be allocated by another caller.
2013-09-09 00:40:18 -04:00
func ( lxc * Container ) ConsoleGetFD ( ttynum int ) ( int , error ) {
2013-11-10 22:30:29 -05:00
// FIXME: Make idiomatic
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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
2013-11-10 22:30:29 -05:00
// ttynum: tty number to attempt to allocate, -1 to allocate the first available tty, or 0 to allocate the console
// stdinfd: fd to read input from
// stdoutfd: fd to write output to
// stderrfd: fd to write error output to
// escape: he escape character (1 == 'a', 2 == 'b', ...)
//
// This function will not return until the console has been exited by the user.
2013-09-09 00:40:18 -04:00
func ( lxc * Container ) Console ( ttynum , stdinfd , stdoutfd , stderrfd , escape int ) error {
2013-11-10 22:30:29 -05:00
// FIXME: Make idiomatic
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-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . 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-12-18 21:15:42 -05:00
// AttachShell runs a shell inside the container
func ( lxc * Container ) AttachShell ( ) 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
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-09-17 23:47:47 -04:00
2013-12-18 21:15:42 -05:00
if int ( C . lxc_container_attach ( lxc . container , false ) ) < 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-12-18 21:15:42 -05:00
// AttachShellWithClearEnvironment runs a shell inside the container and clears all environment variables before attaching
func ( lxc * Container ) AttachShellWithClearEnvironment ( ) error {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
if int ( C . lxc_container_attach ( lxc . container , true ) ) < 0 {
return fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
// RunCommand runs the user specified command inside the container and waits it to exit
func ( lxc * Container ) RunCommand ( args ... string ) error {
2013-09-17 23:47:47 -04:00
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
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-09-17 23:47:47 -04:00
2013-10-30 17:21:42 -04:00
cargs := makeNullTerminatedArgs ( args )
defer freeNullTerminatedArgs ( cargs , len ( args ) )
2013-09-17 23:47:47 -04:00
2013-12-18 21:15:42 -05:00
if int ( C . lxc_container_attach_run_wait ( lxc . container , false , cargs ) ) < 0 {
return fmt . Errorf ( errAttachFailed , C . GoString ( lxc . container . name ) )
}
return nil
}
// RunCommandWithClearEnvironment runs the user specified command inside the container and waits it to exit. It also clears all environment variables before attaching.
func ( lxc * Container ) RunCommandWithClearEnvironment ( args ... string ) error {
if args == nil {
return fmt . Errorf ( errInsufficientNumberOfArguments )
}
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
cargs := makeNullTerminatedArgs ( args )
defer freeNullTerminatedArgs ( cargs , len ( args ) )
if int ( C . lxc_container_attach_run_wait ( lxc . container , true , cargs ) ) < 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-12-02 21:22:24 -05:00
// Interfaces returns the name of the network 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
}
2013-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . RUnlock ( )
2013-09-17 21:29:29 -04:00
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
}
2013-12-02 21:22:24 -05:00
// IPAddress returns the IP address of the given network interface from the container
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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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-12-07 17:18:36 -05:00
lxc . mu . RLock ( )
defer lxc . mu . 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
}
2013-11-04 14:31:59 -05:00
// LogFile returns the name of the logfile
func ( lxc * Container ) LogFile ( ) string {
return lxc . ConfigItem ( "lxc.logfile" ) [ 0 ]
}
// SetLogFile sets the logfile to given filename
func ( lxc * Container ) SetLogFile ( filename string ) error {
if err := lxc . SetConfigItem ( "lxc.logfile" , filename ) ; err != nil {
return err
}
return nil
}
// LogLevel returns the name of the logfile
func ( lxc * Container ) LogLevel ( ) LogLevel {
return logLevelMap [ lxc . ConfigItem ( "lxc.loglevel" ) [ 0 ] ]
}
// SetLogLevel sets the logfile to given filename
func ( lxc * Container ) SetLogLevel ( level LogLevel ) error {
if err := lxc . SetConfigItem ( "lxc.loglevel" , level . String ( ) ) ; err != nil {
return err
}
return nil
}
2013-11-13 16:10:05 -05:00
2013-12-02 21:22:24 -05:00
// AddDeviceNode adds specified device to the container
2013-11-13 16:10:05 -05:00
func ( lxc * Container ) AddDeviceNode ( source string , destination ... string ) error {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-11-13 16:10:05 -05:00
csource := C . CString ( source )
defer C . free ( unsafe . Pointer ( csource ) )
if destination != nil && len ( destination ) == 1 {
cdestination := C . CString ( destination [ 0 ] )
defer C . free ( unsafe . Pointer ( cdestination ) )
if ! bool ( C . lxc_container_add_device_node ( lxc . container , csource , cdestination ) ) {
return fmt . Errorf ( "adding device %s to container %q failed" , source , C . GoString ( lxc . container . name ) )
}
return nil
}
if ! bool ( C . lxc_container_add_device_node ( lxc . container , csource , nil ) ) {
return fmt . Errorf ( "adding device %s to container %q failed" , source , C . GoString ( lxc . container . name ) )
}
return nil
}
2013-12-02 21:22:24 -05:00
// RemoveDeviceNode removes the specified device from the container
2013-11-13 16:10:05 -05:00
func ( lxc * Container ) RemoveDeviceNode ( source string , destination ... string ) error {
if err := lxc . ensureDefinedAndRunning ( ) ; err != nil {
return err
}
2013-12-07 17:18:36 -05:00
lxc . mu . Lock ( )
defer lxc . mu . Unlock ( )
2013-11-13 16:10:05 -05:00
csource := C . CString ( source )
defer C . free ( unsafe . Pointer ( csource ) )
if destination != nil && len ( destination ) == 1 {
cdestination := C . CString ( destination [ 0 ] )
defer C . free ( unsafe . Pointer ( cdestination ) )
if ! bool ( C . lxc_container_remove_device_node ( lxc . container , csource , cdestination ) ) {
return fmt . Errorf ( "adding device %s to container %q failed" , source , C . GoString ( lxc . container . name ) )
}
return nil
}
if ! bool ( C . lxc_container_remove_device_node ( lxc . container , csource , nil ) ) {
return fmt . Errorf ( "adding device %s to container %q failed" , source , C . GoString ( lxc . container . name ) )
}
return nil
}