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
|
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 {
|
func deleteDevfsRuleset(jail *Jail) error {
|
||||||
cmd := "devfs rule showsets"
|
cmd := "devfs rule showsets"
|
||||||
out, err := executeCommand(cmd)
|
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)
|
err = deleteDevfsRuleset(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(" > Remove devfsruleset %s: OK\n", cj.Config.Devfs_ruleset)
|
fmt.Printf(" > Remove devfsruleset %s: OK\n", cj.Config.Devfs_ruleset)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
fmt.Printf(" > Stop jail %s:\n", cj.Name)
|
fmt.Printf(" > Stop jail %s:\n", cj.Name)
|
||||||
err = stopJail(cj)
|
err = stopJail(cj)
|
||||||
@ -311,6 +316,28 @@ func StopJail(args []string) {
|
|||||||
fmt.Printf(" > Umount devfs: OK\n")
|
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
|
Config JailConfig
|
||||||
RootPath string
|
RootPath string
|
||||||
ConfigPath string
|
ConfigPath string
|
||||||
|
ConfigUpdated bool
|
||||||
Running bool
|
Running bool
|
||||||
// No need, Config.Release always represent what is running (plus it know release for non-running jails)
|
// No need, Config.Release always represent what is running (plus it know release for non-running jails)
|
||||||
//Release string
|
//Release string
|
||||||
@ -20,6 +21,7 @@ type Jail struct {
|
|||||||
//
|
//
|
||||||
// Fields in this struct are acquired by their name using reflection
|
// Fields in this struct are acquired by their name using reflection
|
||||||
// So these char are forbidden for field name: -+.
|
// 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
|
// To allow sorting, just duplicate fields in JailConfigSort below
|
||||||
type JailConfig struct {
|
type JailConfig struct {
|
||||||
@ -162,6 +164,17 @@ type JailConfig struct {
|
|||||||
Writeiops string `json:"writeiops"`
|
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
|
// This struct hold "sort by jail fields" functions
|
||||||
type lessFunc func(j1 *Jail, j2 *Jail) bool
|
type lessFunc func(j1 *Jail, j2 *Jail) bool
|
||||||
|
|
||||||
|
102
cmd/utils.go
102
cmd/utils.go
@ -1,9 +1,15 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -57,6 +63,102 @@ func executeCommandInJail(jail *Jail, cmdline string) (string, error) {
|
|||||||
return string(out), err
|
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