Compare commits

..

No commits in common. "7c3e14f0f17942e4ecf7122e7a7d005df0fa6f71" and "7cf4594f3451256cadc6ec932afd87117248196a" have entirely different histories.

4 changed files with 23 additions and 29 deletions

View File

@ -6,13 +6,7 @@ Support iocage jails, so they can coexist.
Gocage is meant to be a complete jail management tool with network, snapshots, jail cloning support and a web interface. This is the hypothetic future. Gocage is meant to be a complete jail management tool with network, snapshots, jail cloning support and a web interface. This is the hypothetic future.
Gocage can handle multiple datastores, so you can have jails on HDD storage and jails on SSD storage. Gocage can handle multiple datastores, so you can have jails on HDD storage and jails on SSD storage.
From v0.33b, due to multi ZFS pool support, gocage is no longer 100% compatible with iocage.
Zfs datasets now should be specified with the ZFS pool. e.g. :
<code>
Config.Jail_zfs = 1
Config.Jail_zfs_dataset = myzfspool/poudriere
Config.Jail_zfs_mountpoint = none
</code>
List jails List jails
---------- ----------

View File

@ -14,7 +14,7 @@ import (
) )
const ( const (
gVersion = "0.33b" gVersion = "0.33a"
// TODO : Get from $jail_zpool/defaults.json // TODO : Get from $jail_zpool/defaults.json
MIN_DYN_DEVFS_RULESET = 1000 MIN_DYN_DEVFS_RULESET = 1000
@ -518,8 +518,10 @@ func WriteConfigToDisk(jailName string, changeauto bool, forceWrite bool) {
fmt.Printf("ERROR marshaling config: %s\n", err.Error()) fmt.Printf("ERROR marshaling config: %s\n", err.Error())
} }
//fmt.Printf("DEBUG: Will write config to disk, with content:\n") fmt.Printf("DEBUG: Will write config to disk, with content:\n")
//fmt.Printf(string(marshaled)) fmt.Printf(string(marshaled))
if os.WriteFile(j.ConfigPath, []byte(marshaled), 0644); err != nil { if os.WriteFile(j.ConfigPath, []byte(marshaled), 0644); err != nil {
fmt.Printf("Error writing config file %s: %v\n", j.ConfigPath, err) fmt.Printf("Error writing config file %s: %v\n", j.ConfigPath, err)

View File

@ -190,26 +190,24 @@ func prepareJailedZfsDatasets(jail *Jail) error {
} }
for _, d := range strings.Split(jail.Config.Jail_zfs_dataset, " ") { for _, d := range strings.Split(jail.Config.Jail_zfs_dataset, " ") {
// Check if dataset exist, create if necessary // Check if dataset exist, create if necessary
// Support jailing datasets on differents pools : dataset should be specified with pool name cmd := fmt.Sprintf("zfs get -H creation %s/%s", jail.Zpool, d)
cmd := fmt.Sprintf("zfs get -H creation %s", d)
out, err := executeCommand(cmd) out, err := executeCommand(cmd)
if err != nil { if err != nil {
if strings.HasSuffix(out, "dataset does not exist") { if strings.HasSuffix(out, "dataset does not exist") {
// Support jailing datasets on differents pools : dataset should be specified with pool name cmd = fmt.Sprintf("zfs create -o compression=lz4 -o mountpoint=none %s/%s", jail.Zpool, d)
cmd = fmt.Sprintf("zfs create -o compression=lz4 -o mountpoint=none %s", d)
_, err = executeCommand(cmd) _, err = executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error creating dataset %s: %s", d, err.Error())) return errors.New(fmt.Sprintf("Error creating dataset %s/%s: %s", jail.Zpool, d, err.Error()))
} }
} else { } else {
return errors.New(fmt.Sprintf("Error getting zfs dataset %s: %s", d, err.Error())) return errors.New(fmt.Sprintf("Error getting zfs dataset %s: %s", d, err.Error()))
} }
} }
cmd = fmt.Sprintf("zfs set jailed=on %s", d) cmd = fmt.Sprintf("zfs set jailed=on %s/%s", jail.Zpool, d)
out, err = executeCommand(cmd) out, err = executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error executing \"zfs set jailed=on %s\": %s", d, err.Error())) return errors.New(fmt.Sprintf("Error executing \"zfs set jailed=on %s/%s\": %s", jail.Zpool, d, err.Error()))
} }
} }
} }
@ -220,27 +218,27 @@ func jailZfsDatasets(jail *Jail) error {
if jail.Config.Jail_zfs > 0 { if jail.Config.Jail_zfs > 0 {
for _, d := range strings.Split(jail.Config.Jail_zfs_dataset, " ") { for _, d := range strings.Split(jail.Config.Jail_zfs_dataset, " ") {
// Jail dataset // Jail dataset
// Support jailing datasets on differents pools : dataset should be specified with pool name cmd := fmt.Sprintf("zfs jail %d %s/%s", jail.JID, jail.Zpool, d)
cmd := fmt.Sprintf("zfs jail %d %s", jail.JID, d)
out, err := executeCommand(cmd) out, err := executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error jailling zfs dataset %s: %v: out", d, err, out)) return errors.New(fmt.Sprintf("Error jailling zfs dataset %s: %v: out", d, err, out))
} }
// Mount from inside jail if mountpoint is set // Mount from inside jail if mountpoint is set
cmd = fmt.Sprintf("zfs get -H -o value mountpoint %s", d) cmd = fmt.Sprintf("zfs get -H -o value mountpoint %s/%s", jail.Zpool, d)
out, err = executeCommand(cmd) out, err = executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error getting zfs dataset %s mountpoint: %v: %s", d, err, out)) return errors.New(fmt.Sprintf("Error getting zfs dataset %s/%s mountpoint: %v: %s", jail.Zpool, d, err, out))
} }
if len(out) > 0 && out != "-" && (false == strings.EqualFold(out, "none")) { if len(out) > 0 && out != "-" && (false == strings.EqualFold(out, "none")) {
// Should we "mount -a" ? cmd = fmt.Sprintf("zfs mount -a") //cmd = fmt.Sprintf("zfs mount %s/%s", jail.Zpool, d)
cmd = fmt.Sprintf("zfs mount %s", d) cmd = fmt.Sprintf("zfs mount -a")
out, err = executeCommandInJail(jail, cmd) out, err = executeCommandInJail(jail, cmd)
if err != nil { if err != nil {
// If already mounted, continue processing // If already mounted, continue processing
if ! strings.HasSuffix(out, "filesystem already mounted\n") { if ! strings.HasSuffix(out, "filesystem already mounted\n") {
return errors.New(fmt.Sprintf("Error mounting zfs dataset %s from inside jail: %v: %s", d, err, out)) //return errors.New(fmt.Sprintf("Error mounting zfs dataset %s/%s: %v: %s", jail.Zpool, d, err, out))
return errors.New(fmt.Sprintf("Error executing \"zfs mount -a\" from inside jail: %v: %s", err, out))
} }
} }
} }
@ -1013,7 +1011,7 @@ func generateResolvConf(jail *Jail) error {
for _, l := range strings.Split(jail.Config.Resolver, ";") { for _, l := range strings.Split(jail.Config.Resolver, ";") {
f.WriteString(fmt.Sprintf("%s\n", l)) f.WriteString(fmt.Sprintf("%s\n", l))
} }
} else if jail.Config.Resolver == "none" || jail.Config.Resolver == "/etc/resolv.conf" { } else if jail.Config.Resolver == "none" {
read, err := ioutil.ReadFile("/etc/resolv.conf") read, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil { if err != nil {
return fmt.Errorf("Error opening /etc/resolv.conf: %v", err) return fmt.Errorf("Error opening /etc/resolv.conf: %v", err)

View File

@ -50,10 +50,10 @@ func umountAndUnjailZFS(jail *Jail) error {
for _, zd := range ds { for _, zd := range ds {
// 1. Get dataset and childs // 1. Get dataset and childs
cmd := fmt.Sprintf("zfs list -H -r -o name -S name %s", zd) cmd := fmt.Sprintf("zfs list -H -r -o name -S name %s/%s", jail.Zpool, zd)
out, err := executeCommand(cmd) out, err := executeCommand(cmd)
if err != nil { if err != nil {
fmt.Printf(fmt.Sprintf("ERROR listing dataset %s\n", zd)) fmt.Printf(fmt.Sprintf("ERROR listing dataset %s/%s\n", jail.Zpool, zd))
os.Exit(1) os.Exit(1)
} }
for _, c := range strings.Split(out, "\n") { for _, c := range strings.Split(out, "\n") {
@ -71,10 +71,10 @@ func umountAndUnjailZFS(jail *Jail) error {
} }
// 2. Unjail dataset from the host // 2. Unjail dataset from the host
cmd := fmt.Sprintf("zfs unjail %s %s", jail.InternalName, ds[len(ds)-1]) cmd := fmt.Sprintf("zfs unjail %s %s/%s", jail.InternalName, jail.Zpool, ds[len(ds)-1])
_, err := executeCommand(cmd) _, err := executeCommand(cmd)
if err != nil { if err != nil {
fmt.Printf("ERROR unjailing %s: %s\n", ds[len(ds)-1], err.Error()) fmt.Printf("ERROR unjailing %s/%s: %s\n", jail.Zpool, ds[len(ds)-1], err.Error())
return err return err
} }