Unmount local FS before stopping jail
This commit is contained in:
parent
30209d2890
commit
349ea12979
33
cmd/stop.go
33
cmd/stop.go
@ -95,7 +95,12 @@ func destroyVNetInterfaces(jail *Jail) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// Jails copy the ruleset referenced as "devfs_ruleset" when starting, getting a new devsf_ruleset ID.
|
||||
// This new ID can be obtained with 'jls -j $JID devfs_ruleset'
|
||||
// This is the ID which needs to be removed. Original ID referenced is json should not be deleted
|
||||
// or else it will require a restart of "devfs" service.
|
||||
// But, stoppign the jail already removes this >1000 ID.
|
||||
// So no need to call this function.
|
||||
func deleteDevfsRuleset(jail *Jail) error {
|
||||
cmd := "devfs rule showsets"
|
||||
out, err := executeCommand(cmd)
|
||||
@ -256,13 +261,13 @@ func StopJail(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf(" > Remove devfsruleset %s:\n", cj.Config.Devfs_ruleset)
|
||||
/*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)
|
||||
@ -311,6 +316,28 @@ func StopJail(args []string) {
|
||||
fmt.Printf(" > Umount devfs: OK\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Remove local mounts from $JAIL/fstab
|
||||
// The way we get fstab is presumptuous
|
||||
fstab := strings.Replace(cj.ConfigPath, "config.json", "fstab", 1)
|
||||
mounts, err := getFstab(fstab)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err.Error())
|
||||
}
|
||||
if len(mounts) > 0 {
|
||||
fmt.Printf(" > Umount mountpoints from %s\n", fstab)
|
||||
errs := 0
|
||||
for _, m := range mounts {
|
||||
err = umountJailFsFromHost(cj, m.Mountpoint)
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR: %s\n", err.Error())
|
||||
errs += 1
|
||||
}
|
||||
}
|
||||
if errs == 0 {
|
||||
fmt.Printf(" > Umount mountpoints from %s: OK\n", fstab)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ type Jail struct {
|
||||
Config JailConfig
|
||||
RootPath string
|
||||
ConfigPath string
|
||||
ConfigUpdated bool
|
||||
Running bool
|
||||
// No need, Config.Release always represent what is running (plus it know release for non-running jails)
|
||||
//Release string
|
||||
@ -20,6 +21,7 @@ type Jail struct {
|
||||
//
|
||||
// Fields in this struct are acquired by their name using reflection
|
||||
// So these char are forbidden for field name: -+.
|
||||
// Array should be forbidden, or else you'll need to rewrite setJailProperty()
|
||||
//
|
||||
// To allow sorting, just duplicate fields in JailConfigSort below
|
||||
type JailConfig struct {
|
||||
@ -162,6 +164,17 @@ type JailConfig struct {
|
||||
Writeiops string `json:"writeiops"`
|
||||
}
|
||||
|
||||
// Represent an fstab line
|
||||
type Mount struct {
|
||||
Device string
|
||||
Mountpoint string
|
||||
Type string
|
||||
Options []string
|
||||
Fs_Freq int
|
||||
Fs_Passno int
|
||||
}
|
||||
|
||||
|
||||
// This struct hold "sort by jail fields" functions
|
||||
type lessFunc func(j1 *Jail, j2 *Jail) bool
|
||||
|
||||
|
102
cmd/utils.go
102
cmd/utils.go
@ -1,9 +1,15 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"sort"
|
||||
"bufio"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strings"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/*****************************************************************************
|
||||
@ -57,6 +63,102 @@ func executeCommandInJail(jail *Jail, cmdline string) (string, error) {
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Parse an fstab file, returning an array of Mount
|
||||
*****************************************************************************/
|
||||
func getFstab(path string) ([]Mount, error) {
|
||||
var mounts []Mount
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return mounts, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
scan := bufio.NewScanner(f)
|
||||
for scan.Scan() {
|
||||
res := strings.Fields(scan.Text())
|
||||
if len(res) != 6 {
|
||||
return mounts, fmt.Errorf("Incorrect format for fstab line %s", scan.Text())
|
||||
}
|
||||
freq, err := strconv.Atoi(res[4])
|
||||
if err != nil {
|
||||
return mounts, fmt.Errorf("Incorrect format for fstab line %s: Dump is not an integer\n", scan.Text())
|
||||
}
|
||||
pass, err := strconv.Atoi(res[5])
|
||||
if err != nil {
|
||||
return mounts, fmt.Errorf("Incorrect format for fstab line %s: Pass is not an integer\n", scan.Text())
|
||||
}
|
||||
m := Mount{
|
||||
Device : res[0],
|
||||
Mountpoint : res[1],
|
||||
Type : res[2],
|
||||
Options : strings.Split(res[3], ","),
|
||||
Fs_Freq : freq,
|
||||
Fs_Passno : pass,
|
||||
}
|
||||
mounts = append(mounts, m)
|
||||
}
|
||||
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Get a specific jail source reference, to update properties after a range loop
|
||||
*****************************************************************************/
|
||||
func getJailFromArray(internalName string, jarray []Jail) (*Jail, error) {
|
||||
for _, j := range jarray {
|
||||
if internalName == j.InternalName {
|
||||
return &j, nil
|
||||
}
|
||||
}
|
||||
return &Jail{}, errors.New("Jail not found")
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
// Recurse into structure, returning reflect.Kind of named field.
|
||||
// Nested fields are named with a dot (ex "MyStruct.MyField")
|
||||
func getStructFieldKind(parentStruct interface{}, fieldName string) (reflect.Kind, string, error) {
|
||||
v := reflect.ValueOf(parentStruct)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
// For debugging
|
||||
if false {
|
||||
for i := 0 ; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
if f.Kind() == reflect.String {
|
||||
fmt.Printf("%v=%v\n", v.Type().Field(i).Name, f.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(fieldName, ".") {
|
||||
fs := strings.Split(fieldName, ".")
|
||||
f := v.FieldByName(fs[0])
|
||||
if f.Kind() == reflect.Struct {
|
||||
return getStructFieldKind(f.Interface(), strings.Join(fs[1:], "."))
|
||||
} else {
|
||||
return reflect.Kind(0), fieldName, errors.New(fmt.Sprintf("%s is not a struct: %s\n", fs[0], f.Kind().String()))
|
||||
}
|
||||
} else {
|
||||
f := v.FieldByName(fieldName)
|
||||
if f.IsValid() {
|
||||
return f.Kind(), fieldName, nil
|
||||
} else {
|
||||
return reflect.Kind(0), fieldName, errors.New(fmt.Sprintf("Field not found: %s", fieldName))
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.Kind(0), fieldName, errors.New(fmt.Sprintf("Field not found: %s", fieldName))
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user