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 package cmd
import ( import (
"os"
"fmt" "fmt"
// "log" // "log"
// "strings" "errors"
"os/exec" "os/exec"
// "reflect"
"strings"
) )
// TODO : Use SYS_RCTL_GET_RACCT syscall // 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, "-r")
cmd = append(cmd, fmt.Sprintf("jail:%s:%s", jail, 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)) //log.Println(fmt.Sprintf("Removing all rules for jail %s: %s", jail, cmd))
//out, err := exec.Command(cmd[0], cmd[1:]...).Output() //out, err := exec.Command(cmd[0], cmd[1:]...).Output()
@ -35,31 +38,121 @@ func removeRctlRules(jail string, rules []string) error {
} }
// TODO // TODO: Validate with >1 dataset
func umountJailedZFS(jail *Jail) error { func umountAndUnjailZFS(jail *Jail) error {
/* var ds []string
for _, zd := range jail.Config.Jail_zfs_dataset {
// 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 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: Stop jail:
Remove rctl rules Remove rctl rules
Execute prestop if set (jailhost perimeter) Execute prestop if set (jailhost perimeter)
Execute stop if set (inside jail) Execute stop if set (inside jail)
Umount ZFS dataset Umount ZFS dataset from inside jail
Unmount mountpoint Unjail ZFS dataset from jailhost
If VNet
Delete VNet interface on host
Delete devfs ruleset Delete devfs ruleset
Effectively stop jail process
Umount all mountpoints from $jail/fstab
Use setfib for each command Use setfib for each command
Shouldnt rctl rules be removed last, when jail is stopped? Shouldnt rctl rules be removed last, when jail is stopped?
*/ */
func stopJail(args []string) { func StopJail(args []string) {
// Current jail were stopping // Current jail were stopping
var cj *Jail var cj *Jail
@ -83,47 +176,70 @@ func stopJail(args []string) {
out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName)) out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName))
if err == nil && len(out) > 0 { if err == nil && len(out) > 0 {
fmt.Printf(" > Remove RCTL rules: ") fmt.Printf(" > Remove RCTL rules:\n")
err := removeRctlRules(cj.InternalName, []string{""}) err := removeRctlRules(cj.InternalName, []string{""})
if err != nil { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf("ERROR: %s\n", err.Error())
} else { } else {
fmt.Printf("OK\n") fmt.Printf(" > Remove RCTL rules: OK\n")
} }
} }
if len (cj.Config.Exec_prestop) > 0 { if len (cj.Config.Exec_prestop) > 0 {
fmt.Printf(" > Execute prestop: ") fmt.Printf(" > Execute prestop:\n")
out, err := executeCommand(cj.Config.Exec_prestop) _, err := executeCommand(cj.Config.Exec_prestop)
if err != nil { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf("ERROR: %s\n", err.Error())
} else { } else {
fmt.Printf("OK\n") fmt.Printf(" > Execute prestop: OK\n")
fmt.Printf("%s\n", out)
} }
} }
if len (cj.Config.Exec_stop) > 0 { if len (cj.Config.Exec_stop) > 0 {
fmt.Printf(" > Execute stop: ") fmt.Printf(" > Execute stop:\n")
out, err := executeCommandInJail(cj, cj.Config.Exec_stop) _, err := executeCommandInJail(cj, cj.Config.Exec_stop)
if err != nil { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf("ERROR: %s\n", err.Error())
} else { } else {
fmt.Printf("OK\n") fmt.Printf(" > Execute stop: OK\n")
fmt.Printf("%s\n", out)
} }
} }
if cj.Config.Jail_zfs > 0 { if cj.Config.Jail_zfs > 0 {
fmt.Printf(" > Umount jailed ZFS: ") fmt.Printf(" > Umount jailed ZFS:\n")
err := umountJailedZFS(cj) err := umountAndUnjailZFS(cj)
if err != nil { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf("ERROR: %s\n", err.Error())
} else { } 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)
}
} }
} }