Skip to content

Commit

Permalink
Merge pull request lxc#25 from caglar10ur/CloneOptions
Browse files Browse the repository at this point in the history
introduce CloneOptions
  • Loading branch information
caglar10ur committed Oct 12, 2014
2 parents 7273606 + 0f242db commit 16b3020
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 106 deletions.
21 changes: 0 additions & 21 deletions const.go

This file was deleted.

87 changes: 51 additions & 36 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ type Snapshot struct {
Path string
}

const (
isDefined = 1 << iota
isNotDefined
isRunning
isNotRunning
)

func (c *Container) makeSure(flags int) error {
if flags&isDefined != 0 && !c.Defined() {
return ErrNotDefined
Expand Down Expand Up @@ -296,11 +303,7 @@ func (c *Container) Unfreeze() error {

// Create creates the container using given TemplateOptions
func (c *Container) Create(options TemplateOptions) error {
// FIXME: Support bdevtype and bdev_specs
// bdevtypes:
// "btrfs", "zfs", "lvm", "dir"
//
// best tries to find the best backing store type
// FIXME: Support bdev_specs
//
// bdev_specs:
// zfs requires zfsroot
Expand Down Expand Up @@ -428,27 +431,25 @@ func (c *Container) Execute(args ...string) ([]byte, error) {
c.mu.Lock()
defer c.mu.Unlock()

/*
* FIXME: Go runtime and src/lxc/start.c signal_handler are not playing nice together so use lxc-execute for now
* go-nuts thread: https://groups.google.com/forum/#!msg/golang-nuts/h9GbvfYv83w/5Ly_jvOr86wJ
*/
// FIXME: Go runtime and src/lxc/start.c signal_handler are not playing nice together so use lxc-execute for now
// go-nuts thread: https://groups.google.com/forum/#!msg/golang-nuts/h9GbvfYv83w/5Ly_jvOr86wJ
output, err := exec.Command(cargs[0], cargs[1:]...).CombinedOutput()
if err != nil {
return nil, ErrExecuteFailed
}

return output, nil
/*
cargs := makeNullTerminatedArgs(args)
if cargs == nil {
return ErrAllocationFailed
}
defer freeNullTerminatedArgs(cargs, len(args))
if !bool(C.go_lxc_start(c.container, 1, cargs)) {
return ErrExecuteFailed
}
return nil
cargs := makeNullTerminatedArgs(args)
if cargs == nil {
return ErrAllocationFailed
}
defer freeNullTerminatedArgs(cargs, len(args))
if !bool(C.go_lxc_start(c.container, 1, cargs)) {
return ErrExecuteFailed
}
return nil
*/
}

Expand Down Expand Up @@ -511,15 +512,9 @@ func (c *Container) Destroy() error {
return nil
}

// CloneUsing clones the container using given arguments with specified backend.
//
// Additional flags to change the cloning behaviour:
// CloneKeepName, CloneKeepMACAddr, CloneSnapshot and CloneMaybeSnapshot
func (c *Container) CloneUsing(name string, backend BackendStore, flags CloneFlags) error {
// FIXME: support lxcpath, bdevtype, bdevdata, newsize and hookargs
//
// bdevtypes:
// "btrfs", "zfs", "lvm", "dir" "overlayfs"
// Clone clones the container using given arguments with specified backend.
func (c *Container) Clone(name string, options CloneOptions) error {
// FIXME: bdevdata, newsize and hookargs
//
// bdevdata:
// zfs requires zfsroot
Expand All @@ -537,23 +532,43 @@ func (c *Container) CloneUsing(name string, backend BackendStore, flags CloneFla
c.mu.Lock()
defer c.mu.Unlock()

// use Directory backend if not set
if options.Backend == 0 {
options.Backend = Directory
}

var flags int
if options.KeepName {
flags |= C.LXC_CLONE_KEEPNAME
}
if options.KeepMAC {
flags |= C.LXC_CLONE_KEEPMACADDR
}
if options.Snapshot {
flags |= C.LXC_CLONE_SNAPSHOT
}

cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))

cbackend := C.CString(backend.String())
cbackend := C.CString(options.Backend.String())
defer C.free(unsafe.Pointer(cbackend))

if !bool(C.go_lxc_clone(c.container, cname, C.int(flags), cbackend)) {
return ErrCloneFailed
if options.ConfigPath != "" {
clxcpath := C.CString(options.ConfigPath)
defer C.free(unsafe.Pointer(clxcpath))

if !bool(C.go_lxc_clone(c.container, cname, clxcpath, C.int(flags), cbackend)) {
return ErrCloneFailed
}
} else {
if !bool(C.go_lxc_clone(c.container, cname, nil, C.int(flags), cbackend)) {
return ErrCloneFailed
}
}
return nil
}

// Clone clones the container using the Directory backendstore.
func (c *Container) Clone(name string) error {
return c.CloneUsing(name, Directory, 0)
}

// Rename renames the container.
func (c *Container) Rename(name string) error {
if err := c.makeSure(isDefined | isNotRunning); err != nil {
Expand Down
1 change: 1 addition & 0 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var (
ErrStartFailed = NewError("starting the container failed")
ErrStopFailed = NewError("stopping the container failed")
ErrUnfreezeFailed = NewError("unfreezing the container failed")
ErrUnknownBackendStore = NewError("unknown backend type")
)

// Error represents a basic error that implies the error interface.
Expand Down
29 changes: 9 additions & 20 deletions examples/clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import (
var (
lxcpath string
name string
backend lxc.BackendStore
)

func init() {
flag.StringVar(&lxcpath, "lxcpath", lxc.DefaultConfigPath(), "Use specified container path")
flag.StringVar(&name, "name", "rubik", "Name of the original container")
flag.Var(&backend, "backend", "Backend type to use, possible values are [dir, zfs, btrfs, lvm, aufs, overlayfs, loopback, best]")
flag.Parse()
}

Expand All @@ -30,28 +32,15 @@ func main() {
log.Fatalf("ERROR: %s\n", err.Error())
}

directoryClone := name + "Directory"
overlayClone := name + "Overlayfs"
btrfsClone := name + "Btrfs"
aufsClone := name + "Aufs"

log.Printf("Cloning the container using Directory backend...\n")
if err := c.Clone(directoryClone); err != nil {
log.Fatalf("ERROR: %s\n", err.Error())
}

log.Printf("Cloning the container using Overlayfs backend...\n")
if err := c.CloneUsing(overlayClone, lxc.Overlayfs, lxc.CloneSnapshot); err != nil {
log.Fatalf("ERROR: %s\n", err.Error())
if backend == 0 {
log.Fatalf("ERROR: %s\n", lxc.ErrUnknownBackendStore)
}

log.Printf("Cloning the container using Aufs backend...\n")
if err := c.CloneUsing(aufsClone, lxc.Aufs, lxc.CloneSnapshot); err != nil {
log.Fatalf("ERROR: %s\n", err.Error())
}

log.Printf("Cloning the container using Btrfs backend...\n")
if err := c.CloneUsing(btrfsClone, lxc.Btrfs, 0); err != nil {
log.Printf("Cloning the container using %s backend...\n", backend)
err = c.Clone(name+"_"+backend.String(), lxc.CloneOptions{
Backend: backend,
})
if err != nil {
log.Fatalf("ERROR: %s\n", err.Error())
}
}
4 changes: 2 additions & 2 deletions lxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ bool go_lxc_save_config(struct lxc_container *c, const char *alt_file) {
return c->save_config(c, alt_file);
}

bool go_lxc_clone(struct lxc_container *c, const char *newname, int flags, const char *bdevtype) {
return c->clone(c, newname, NULL, flags, bdevtype, NULL, 0, NULL) != NULL;
bool go_lxc_clone(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, const char *bdevtype) {
return c->clone(c, newname, lxcpath, flags, bdevtype, NULL, 0, NULL) != NULL;
}

int go_lxc_console_getfd(struct lxc_container *c, int ttynum) {
Expand Down
2 changes: 1 addition & 1 deletion lxc.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
extern bool go_lxc_add_device_node(struct lxc_container *c, const char *src_path, const char *dest_path);
extern void go_lxc_clear_config(struct lxc_container *c);
extern bool go_lxc_clear_config_item(struct lxc_container *c, const char *key);
extern bool go_lxc_clone(struct lxc_container *c, const char *newname, int flags, const char *bdevtype);
extern bool go_lxc_clone(struct lxc_container *c, const char *newname, const char *lxcpath, int flags, const char *bdevtype);
extern bool go_lxc_console(struct lxc_container *c, int ttynum, int stdinfd, int stdoutfd, int stderrfd, int escape);
extern bool go_lxc_create(struct lxc_container *c, const char *t, const char *bdevtype, int flags, char * const argv[]);
extern bool go_lxc_defined(struct lxc_container *c);
Expand Down
22 changes: 17 additions & 5 deletions lxc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func TestClone(t *testing.T) {
t.Errorf(err.Error())
}

if err := c.Clone(ContainerCloneName); err != nil {
if err = c.Clone(ContainerCloneName, DefaultCloneOptions); err != nil {
t.Errorf(err.Error())
}
}
Expand All @@ -173,7 +173,13 @@ func TestCloneUsingOverlayfs(t *testing.T) {
t.Errorf(err.Error())
}

if err := c.CloneUsing(ContainerCloneOverlayName, Overlayfs, CloneSnapshot|CloneKeepName|CloneKeepMACAddr); err != nil {
err = c.Clone(ContainerCloneOverlayName, CloneOptions{
Backend: Overlayfs,
KeepName: true,
KeepMAC: true,
Snapshot: true,
})
if err != nil {
t.Errorf(err.Error())
}
}
Expand All @@ -192,7 +198,13 @@ func TestCloneUsingAufs(t *testing.T) {
t.Errorf(err.Error())
}

if err := c.CloneUsing(ContainerCloneAufsName, Aufs, CloneSnapshot|CloneKeepName|CloneKeepMACAddr); err != nil {
err = c.Clone(ContainerCloneAufsName, CloneOptions{
Backend: Aufs,
KeepName: true,
KeepMAC: true,
Snapshot: true,
})
if err != nil {
t.Errorf(err.Error())
}
}
Expand Down Expand Up @@ -1260,7 +1272,7 @@ func TestBackendStore(t *testing.T) {
store BackendStore
}

if X.store.String() != "<INVALID>" {
if X.store.String() != "" {
t.Error("zero value of BackendStore should be invalid")
}
}
Expand All @@ -1270,7 +1282,7 @@ func TestState(t *testing.T) {
state State
}

if X.state.String() != "<INVALID>" {
if X.state.String() != "" {
t.Error("zero value of State should be invalid")
}
}
25 changes: 25 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var DefaultAttachOptions = AttachOptions{

// TemplateOptions type is used for defining various template options.
type TemplateOptions struct {

// Template specifies the name of the template.
Template string

Expand Down Expand Up @@ -149,3 +150,27 @@ var DefaultConsoleOptions = ConsoleOptions{
StderrFd: os.Stderr.Fd(),
EscapeCharacter: 'a',
}

// CloneOptions type is used for defining various clone options.
type CloneOptions struct {

// Backend specifies the type of the backend.
Backend BackendStore

// lxcpath in which to create the new container. If not set the original container's lxcpath will be used.
ConfigPath string

// Do not change the hostname of the container (in the root filesystem).
KeepName bool

// Use the same MAC address as the original container, rather than generating a new random one.
KeepMAC bool

// Create a snapshot rather than copy.
Snapshot bool
}

// DefaultCloneOptions is a convenient set of options to be used.
var DefaultCloneOptions = CloneOptions{
Backend: Directory,
}
Loading

0 comments on commit 16b3020

Please sign in to comment.