gocage stop now functionnal

This commit is contained in:
yo 2021-12-19 12:42:29 +01:00
parent 8fdd0ffbce
commit eebc7da169

View File

@ -1,10 +1,13 @@
package cmd
import (
"os"
"fmt"
// "log"
// "strings"
"errors"
"os/exec"
// "reflect"
"strings"
)
// TODO : Use SYS_RCTL_GET_RACCT syscall
@ -23,7 +26,7 @@ func removeRctlRules(jail string, rules []string) error {
cmd = append(cmd, "-r")
cmd = append(cmd, fmt.Sprintf("jail:%s:%s", jail, r))
// TODO : Log in another channel than stdout (will scramble diusplay)
// TODO : Log in another channel than stdout (will scramble display)
//log.Println(fmt.Sprintf("Removing all rules for jail %s: %s", jail, cmd))
//out, err := exec.Command(cmd[0], cmd[1:]...).Output()
@ -35,31 +38,121 @@ func removeRctlRules(jail string, rules []string) error {
}
// TODO
func umountJailedZFS(jail *Jail) error {
/*
for _, zd := range jail.Config.Jail_zfs_dataset {
// TODO: Validate with >1 dataset
func umountAndUnjailZFS(jail *Jail) error {
var ds []string
// Make sure we have a string array
ds = append(ds, jail.Config.Jail_zfs_dataset)
for _, zd := range ds {
// 1. Get dataset and childs
cmd := fmt.Sprintf("zfs list -H -r -o name -S name %s/%s", jail.Zpool, zd)
out, err := executeCommand(cmd)
if err != nil {
fmt.Printf(fmt.Sprintf("ERROR listing dataset %s/%s\n", jail.Zpool, zd))
os.Exit(1)
}
for _, c := range strings.Split(out, "\n") {
if len(c) == 0 {
continue
}
fmt.Printf("Unmounting dataset %s: ", c)
cmd := fmt.Sprintf("zfs umount %s", c)
_, err := executeCommandInJail(jail, cmd)
if err != nil {
return err
}
fmt.Printf("OK\n")
}
}
*/
// 2. Unjail dataset from the host
cmd := fmt.Sprintf("zfs unjail %s %s/%s", jail.InternalName, jail.Zpool, ds[len(ds)-1])
_, err := executeCommand(cmd)
if err != nil {
fmt.Printf("ERROR unjailing %s/%s: %s\n", jail.Zpool, ds[len(ds)-1], err.Error())
return err
}
return nil
}
func destroyVNetInterfaces(jail *Jail) error {
for _, i := range strings.Split(jail.Config.Ip4_addr, ",") {
iname := fmt.Sprintf("%s.%d", strings.Split(i, "|")[0], jail.JID)
fmt.Printf("%s: ", iname)
_, err := executeCommand(fmt.Sprintf("ifconfig %s destroy", iname))
if err != nil {
return err
} else {
fmt.Printf("OK\n")
}
}
return nil
}
func deleteDevfsRuleset(jail *Jail) error {
cmd := "devfs rule showsets"
out, err := executeCommand(cmd)
if err != nil {
return errors.New(fmt.Sprintf("ERROR listing rulesets: %s", err.Error()))
}
for _, r := range strings.Split(out, "\n") {
if r == jail.Config.Devfs_ruleset {
cmd := fmt.Sprintf("devfs rule -s %s delset", jail.Config.Devfs_ruleset)
_, err := executeCommand(cmd)
return err
}
}
return nil
}
// Internal usage only
func stopJail(jail *Jail) error {
cmd := "jail -q"
// Test if conf file exist (iocage created)
cf := fmt.Sprintf("/var/run/jail.%s.conf", jail.InternalName)
file, err := os.Open(cf)
if err != nil {
file.Close()
cmd = fmt.Sprintf("%s -f %s", cmd, cf)
}
cmd = fmt.Sprintf("%s -r %s", cmd, jail.InternalName)
_, err = executeCommand(cmd)
if err != nil {
return err
}
return nil
}
/*
Stop jail:
Remove rctl rules
Execute prestop if set (jailhost perimeter)
Execute stop if set (inside jail)
Umount ZFS dataset
Unmount mountpoint
Umount ZFS dataset from inside jail
Unjail ZFS dataset from jailhost
If VNet
Delete VNet interface on host
Delete devfs ruleset
Effectively stop jail process
Umount all mountpoints from $jail/fstab
Use setfib for each command
Shouldnt rctl rules be removed last, when jail is stopped?
*/
func stopJail(args []string) {
func StopJail(args []string) {
// Current jail were stopping
var cj *Jail
@ -83,47 +176,70 @@ func stopJail(args []string) {
out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName))
if err == nil && len(out) > 0 {
fmt.Printf(" > Remove RCTL rules: ")
fmt.Printf(" > Remove RCTL rules:\n")
err := removeRctlRules(cj.InternalName, []string{""})
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf("OK\n")
fmt.Printf(" > Remove RCTL rules: OK\n")
}
}
if len (cj.Config.Exec_prestop) > 0 {
fmt.Printf(" > Execute prestop: ")
out, err := executeCommand(cj.Config.Exec_prestop)
fmt.Printf(" > Execute prestop:\n")
_, err := executeCommand(cj.Config.Exec_prestop)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf("OK\n")
fmt.Printf("%s\n", out)
fmt.Printf(" > Execute prestop: OK\n")
}
}
if len (cj.Config.Exec_stop) > 0 {
fmt.Printf(" > Execute stop: ")
out, err := executeCommandInJail(cj, cj.Config.Exec_stop)
fmt.Printf(" > Execute stop:\n")
_, err := executeCommandInJail(cj, cj.Config.Exec_stop)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf("OK\n")
fmt.Printf("%s\n", out)
fmt.Printf(" > Execute stop: OK\n")
}
}
if cj.Config.Jail_zfs > 0 {
fmt.Printf(" > Umount jailed ZFS: ")
err := umountJailedZFS(cj)
fmt.Printf(" > Umount jailed ZFS:\n")
err := umountAndUnjailZFS(cj)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf("OK\n")
fmt.Printf(" > Umount jailed ZFS: OK\n")
}
}
if cj.Config.Vnet > 0 && len(cj.Config.Ip4_addr) > 0 {
fmt.Printf(" > Destroy VNet interfaces:\n")
err := destroyVNetInterfaces(cj)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Destroy VNet interfaces: OK\n")
}
}
fmt.Printf(" > Remove devfsruleset %s:\n", cj.Config.Devfs_ruleset)
err = deleteDevfsRuleset(cj)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Remove devfsruleset %s: OK\n", cj.Config.Devfs_ruleset)
}
fmt.Printf(" > Stop jail %s:\n", cj.Name)
err = stopJail(cj)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Stop jail %s: OK\n", cj.Name)
}
}
}