WIP on start, go fmt on *

This commit is contained in:
yo 2022-04-24 16:49:54 +02:00
parent dbd9153513
commit 43f26d099f
12 changed files with 1498 additions and 1169 deletions

View File

@ -12,7 +12,7 @@ func ShellJail(args []string) error {
jailnames = append(jailnames, a) jailnames = append(jailnames, a)
} }
} }
for _, cj := range gJails { for _, cj := range gJails {
for _, jn := range jailnames { for _, jn := range jailnames {
if strings.EqualFold(cj.Name, jn) { if strings.EqualFold(cj.Name, jn) {
@ -23,7 +23,7 @@ func ShellJail(args []string) error {
} }
} }
} }
return nil return nil
} }
@ -34,6 +34,6 @@ func shellJail(jail Jail) error {
fmt.Errorf("Error executing %s: %s", cmd, err.Error()) fmt.Errorf("Error executing %s: %s", cmd, err.Error())
return err return err
} }
return nil return nil
} }

View File

@ -2,8 +2,8 @@ package cmd
import ( import (
"fmt" "fmt"
"net"
"golang.org/x/net/route" "golang.org/x/net/route"
"net"
) )
var defaultRoute4 = [4]byte{0, 0, 0, 0} var defaultRoute4 = [4]byte{0, 0, 0, 0}
@ -15,9 +15,9 @@ func Inet4AddrToString(ip4 route.Inet4Addr) string {
} }
func Inet6AddrToString(ip6 route.Inet6Addr) string { func Inet6AddrToString(ip6 route.Inet6Addr) string {
return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
ip6.IP[0], ip6.IP[1], ip6.IP[2], ip6.IP[3], ip6.IP[4], ip6.IP[5], ip6.IP[6], ip6.IP[7], ip6.IP[0], ip6.IP[1], ip6.IP[2], ip6.IP[3], ip6.IP[4], ip6.IP[5], ip6.IP[6], ip6.IP[7],
ip6.IP[8], ip6.IP[9], ip6.IP[10], ip6.IP[11], ip6.IP[12], ip6.IP[13], ip6.IP[14], ip6.IP[15]) ip6.IP[8], ip6.IP[9], ip6.IP[10], ip6.IP[11], ip6.IP[12], ip6.IP[13], ip6.IP[14], ip6.IP[15])
} }
/***************************************************************************** /*****************************************************************************
@ -29,28 +29,28 @@ func (jh *JailHost) InitNetworkProperties() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
for _, message := range messages { for _, message := range messages {
route_message := message.(*route.RouteMessage) route_message := message.(*route.RouteMessage)
addresses := route_message.Addrs addresses := route_message.Addrs
card_index := route_message.Index card_index := route_message.Index
if addresses[0].Family() == 2 { if addresses[0].Family() == 2 {
var destination4, gateway4 *route.Inet4Addr var destination4, gateway4 *route.Inet4Addr
ok := false ok := false
if destination4, ok = addresses[0].(*route.Inet4Addr); !ok { if destination4, ok = addresses[0].(*route.Inet4Addr); !ok {
continue continue
} }
if gateway4, ok = addresses[1].(*route.Inet4Addr); !ok { if gateway4, ok = addresses[1].(*route.Inet4Addr); !ok {
continue continue
} }
if destination4 == nil || gateway4 == nil { if destination4 == nil || gateway4 == nil {
continue continue
} }
if destination4.IP == defaultRoute4 { if destination4.IP == defaultRoute4 {
card, _ := net.InterfaceByIndex(card_index) card, _ := net.InterfaceByIndex(card_index)
//fmt.Printf("Default IPv4 gateway is %v on card %s\n", Inet4AddrToString(*gateway4), card.Name) //fmt.Printf("Default IPv4 gateway is %v on card %s\n", Inet4AddrToString(*gateway4), card.Name)
@ -60,19 +60,19 @@ func (jh *JailHost) InitNetworkProperties() {
} else if addresses[0].Family() == 28 { } else if addresses[0].Family() == 28 {
var destination6, gateway6 *route.Inet6Addr var destination6, gateway6 *route.Inet6Addr
ok := false ok := false
if destination6, ok = addresses[0].(*route.Inet6Addr); !ok { if destination6, ok = addresses[0].(*route.Inet6Addr); !ok {
continue continue
} }
if gateway6, ok = addresses[1].(*route.Inet6Addr); !ok { if gateway6, ok = addresses[1].(*route.Inet6Addr); !ok {
continue continue
} }
if destination6 == nil || gateway6 == nil { if destination6 == nil || gateway6 == nil {
continue continue
} }
if destination6.IP == defaultRoute6 && gateway6.IP != local6 { if destination6.IP == defaultRoute6 && gateway6.IP != local6 {
card, _ := net.InterfaceByIndex(card_index) card, _ := net.InterfaceByIndex(card_index)
//fmt.Printf("Default IPv6 gateway is %v on card %s\n", Inet6AddrToString(*gateway6), card.Name) //fmt.Printf("Default IPv6 gateway is %v on card %s\n", Inet6AddrToString(*gateway6), card.Name)
@ -83,7 +83,6 @@ func (jh *JailHost) InitNetworkProperties() {
} }
} }
func (jh *JailHost) GetDefaultInterface() string { func (jh *JailHost) GetDefaultInterface() string {
if len(jh.default_interface) == 0 { if len(jh.default_interface) == 0 {
jh.InitNetworkProperties() jh.InitNetworkProperties()
@ -91,7 +90,6 @@ func (jh *JailHost) GetDefaultInterface() string {
return jh.default_interface return jh.default_interface
} }
func (jh *JailHost) GetDefaultGateway4() string { func (jh *JailHost) GetDefaultGateway4() string {
if len(jh.default_gateway4) == 0 { if len(jh.default_gateway4) == 0 {
jh.InitNetworkProperties() jh.InitNetworkProperties()
@ -99,11 +97,9 @@ func (jh *JailHost) GetDefaultGateway4() string {
return jh.default_gateway4 return jh.default_gateway4
} }
func (jh *JailHost) GetDefaultGateway6() string {
func(jh *JailHost) GetDefaultGateway6() string {
if len(jh.default_gateway6) == 0 { if len(jh.default_gateway6) == 0 {
jh.InitNetworkProperties() jh.InitNetworkProperties()
} }
return jh.default_gateway6 return jh.default_gateway6
} }

View File

@ -1,15 +1,15 @@
package cmd package cmd
import ( import (
"os" "encoding/json"
"fmt" "fmt"
"github.com/spf13/viper"
"gocage/jail"
"io/ioutil"
"log" "log"
"os"
"reflect" "reflect"
"strings" "strings"
"io/ioutil"
"gocage/jail"
"encoding/json"
"github.com/spf13/viper"
) )
/******************************************************************************** /********************************************************************************
@ -25,18 +25,18 @@ func ListJailsProps(args []string) {
fmt.Printf("Error allocating JailConfig: %s\n", err.Error()) fmt.Printf("Error allocating JailConfig: %s\n", err.Error())
return return
} }
conf.Config = jailconf conf.Config = jailconf
result = getStructFieldNames(conf, result, "") result = getStructFieldNames(conf, result, "")
for _, f := range result { for _, f := range result {
fmt.Printf("%s\n", f) fmt.Printf("%s\n", f)
} }
} }
/******************************************************************************** /********************************************************************************
* Get Jails from datastores. Store config and running metadata * Get Jails from datastores. Store config and running metadata
* into gJails global var * into gJails global var
*******************************************************************************/ *******************************************************************************/
func ListJails(args []string, display bool) { func ListJails(args []string, display bool) {
@ -82,7 +82,6 @@ func ListJails(args []string, display bool) {
jails = gJails jails = gJails
} }
/*************************************************************** /***************************************************************
/ Filter jails by names given on command line / Filter jails by names given on command line
/**************************************************************/ /**************************************************************/
@ -112,10 +111,10 @@ func ListJails(args []string, display bool) {
var fctName string var fctName string
if strings.HasPrefix(c, "-") { if strings.HasPrefix(c, "-") {
fctName = fmt.Sprintf("%sDec", strings.Replace(c, "-", "", 1)) fctName = fmt.Sprintf("%sDec", strings.Replace(c, "-", "", 1))
} else { // Par defaut (pas de prefix +/-) on considere un tri incremental } else { // Par defaut (pas de prefix +/-) on considere un tri incremental
fctName = fmt.Sprintf("%sInc", strings.Replace(c, "+", "", 1)) fctName = fmt.Sprintf("%sInc", strings.Replace(c, "+", "", 1))
} }
// Get function by its name // Get function by its name
fct, _, err := getStructFieldValue(js, fctName) fct, _, err := getStructFieldValue(js, fctName)
if err != nil { if err != nil {
@ -123,20 +122,23 @@ func ListJails(args []string, display bool) {
fmt.Printf("ERROR getting JailSort struct field %s. Please check the field name: %s\n", fctName, fieldName) fmt.Printf("ERROR getting JailSort struct field %s. Please check the field name: %s\n", fctName, fieldName)
return return
} }
switch i+1 { switch i + 1 {
case 1: fct1 = fct case 1:
case 2: fct2 = fct fct1 = fct
case 3: fct3 = fct case 2:
fct2 = fct
case 3:
fct3 = fct
} }
} }
switch len(strings.Split(gSortFields, ",")) { switch len(strings.Split(gSortFields, ",")) {
case 1: case 1:
JailsOrderedBy(fct1.Interface().(jailLessFunc)).Sort(jails) JailsOrderedBy(fct1.Interface().(jailLessFunc)).Sort(jails)
case 2: case 2:
JailsOrderedBy(fct1.Interface().(jailLessFunc), fct2.Interface().(jailLessFunc)).Sort(jails) JailsOrderedBy(fct1.Interface().(jailLessFunc), fct2.Interface().(jailLessFunc)).Sort(jails)
case 3: case 3:
JailsOrderedBy(fct1.Interface().(jailLessFunc), fct2.Interface().(jailLessFunc), fct3.Interface().(jailLessFunc)).Sort(jails) JailsOrderedBy(fct1.Interface().(jailLessFunc), fct2.Interface().(jailLessFunc), fct3.Interface().(jailLessFunc)).Sort(jails)
} }
} }
@ -148,47 +150,59 @@ func ListJails(args []string, display bool) {
} }
} }
func listJailsFromDatastore(datastore string) { func listJailsFromDatastore(datastore string) {
fileInfo, err := os.Stat(datastore) fileInfo, err := os.Stat(datastore)
if err != nil { log.Fatalln(fmt.Sprintf("Unable to access %s, check path and/or rights", datastore)) } if err != nil {
if fileInfo.IsDir() == false { log.Fatalln(fmt.Sprintf("%s is not a directory", datastore)) } log.Fatalln(fmt.Sprintf("Unable to access %s, check path and/or rights", datastore))
}
if fileInfo.IsDir() == false {
log.Fatalln(fmt.Sprintf("%s is not a directory", datastore))
}
// A datastore have to contain a "jails" directory // A datastore have to contain a "jails" directory
jailsDir := fmt.Sprintf("%s/jails", datastore) jailsDir := fmt.Sprintf("%s/jails", datastore)
fileInfo, err = os.Stat(jailsDir) fileInfo, err = os.Stat(jailsDir)
if err != nil { log.Fatalln(fmt.Sprintf("Unable to access %s, check path and/or rights", jailsDir)) } if err != nil {
if fileInfo.IsDir() == false { log.Fatalln(fmt.Sprintf("%s is not a directory", jailsDir)) } log.Fatalln(fmt.Sprintf("Unable to access %s, check path and/or rights", jailsDir))
}
if fileInfo.IsDir() == false {
log.Fatalln(fmt.Sprintf("%s is not a directory", jailsDir))
}
listJailsFromDirectory(jailsDir) listJailsFromDirectory(jailsDir)
} }
func listJailsFromDirectory(dir string) []Jail {
func listJailsFromDirectory(dir string) ([]Jail) {
files, err := ioutil.ReadDir(dir) files, err := ioutil.ReadDir(dir)
if err != nil { log.Fatalln(fmt.Sprintf("Unable to browse %s, check path and/or rights", dir)) } if err != nil {
log.Fatalln(fmt.Sprintf("Unable to browse %s, check path and/or rights", dir))
}
for _, fi := range files { for _, fi := range files {
if fi.IsDir() == true { if fi.IsDir() == true {
// 1. Get conf from config.json // 1. Get conf from config.json
jailConfPath := fmt.Sprintf("%s/%s/%s", dir, fi.Name(), "config.json") jailConfPath := fmt.Sprintf("%s/%s/%s", dir, fi.Name(), "config.json")
jailConf, err := getJailConfig(jailConfPath) jailConf, err := getJailConfig(jailConfPath)
if err != nil { log.Println("ERROR reading jail config for %s", jailConfPath) } if err != nil {
log.Println("ERROR reading jail config for %s", jailConfPath)
// 2. Build jail object from config
jailRootPath := fmt.Sprintf("%s/%s/%s", dir, fi.Name(), "root")
j := Jail{
Name: jailConf.Host_hostname,
Config: jailConf,
ConfigPath: jailConfPath,
RootPath: jailRootPath,
Running: false,
} }
// 3. Add current running informations // 2. Build jail object from config
jailRootPath := fmt.Sprintf("%s/%s/%s", dir, fi.Name(), "root")
j := Jail{
Name: jailConf.Host_hostname,
Config: jailConf,
ConfigPath: jailConfPath,
RootPath: jailRootPath,
Running: false,
}
// 3. Add current running informations
rjails, err := jail.GetJails() rjails, err := jail.GetJails()
if err != nil { log.Fatalln("Unable to list running jails") } if err != nil {
log.Fatalln("Unable to list running jails")
}
for _, rj := range rjails { for _, rj := range rjails {
if rj.Path == j.RootPath { if rj.Path == j.RootPath {
j.JID = rj.Jid j.JID = rj.Jid
@ -197,8 +211,8 @@ func listJailsFromDirectory(dir string) ([]Jail) {
break break
} }
} }
/* This op take some 600ms for ~40 jails :^( */ /* This op take some 600ms for ~40 jails :^( */
out, err := executeCommand(fmt.Sprintf("zfs list -H -o name %s", j.RootPath)) out, err := executeCommand(fmt.Sprintf("zfs list -H -o name %s", j.RootPath))
if err != nil { if err != nil {
fmt.Printf("ERROR getting dataset from %s: %s\n", j.RootPath, err.Error()) fmt.Printf("ERROR getting dataset from %s: %s\n", j.RootPath, err.Error())
@ -213,10 +227,11 @@ func listJailsFromDirectory(dir string) ([]Jail) {
return gJails return gJails
} }
func getJailConfig(jailConfigPath string) (JailConfig, error) { func getJailConfig(jailConfigPath string) (JailConfig, error) {
content, err := ioutil.ReadFile(jailConfigPath) content, err := ioutil.ReadFile(jailConfigPath)
if err != nil { log.Fatalln(fmt.Sprintf("Unable to read %s, check path and/or rights", jailConfigPath)) } if err != nil {
log.Fatalln(fmt.Sprintf("Unable to read %s, check path and/or rights", jailConfigPath))
}
// Mandatory constructor to init default values // Mandatory constructor to init default values
jc, err := NewJailConfig() jc, err := NewJailConfig()
@ -224,7 +239,9 @@ func getJailConfig(jailConfigPath string) (JailConfig, error) {
return jc, err return jc, err
} }
err = json.Unmarshal([]byte(content), &jc) err = json.Unmarshal([]byte(content), &jc)
if err != nil { log.Fatalln(fmt.Sprintf("Error occured during unmarshaling %s: %s", jailConfigPath, err.Error())) } if err != nil {
log.Fatalln(fmt.Sprintf("Error occured during unmarshaling %s: %s", jailConfigPath, err.Error()))
}
return jc, err return jc, err
} }

View File

@ -1,17 +1,17 @@
package cmd package cmd
import ( import (
"fmt"
"errors" "errors"
"fmt"
"reflect" "reflect"
"strings"
"strconv" "strconv"
"strings"
) )
func GetJailProperties(args []string) { func GetJailProperties(args []string) {
var props []string var props []string
var jail Jail var jail Jail
if len(args) > 0 { if len(args) > 0 {
for i, a := range args { for i, a := range args {
// Last arg is the jail name // Last arg is the jail name
@ -21,20 +21,20 @@ func GetJailProperties(args []string) {
props = append(props, a) props = append(props, a)
} }
} }
} }
if len(jail.Name) == 0 || len(args) == 0 { if len(jail.Name) == 0 || len(args) == 0 {
// TODO : Show help // TODO : Show help
fmt.Printf("Error\n") fmt.Printf("Error\n")
return return
} }
if isStringInArray(props, "all") { if isStringInArray(props, "all") {
var result []string var result []string
result = getStructFieldNames(jail, result, "") result = getStructFieldNames(jail, result, "")
props = result props = result
} }
for _, p := range props { for _, p := range props {
v, err := getJailProperty(&jail, p) v, err := getJailProperty(&jail, p)
if err != nil { if err != nil {
@ -53,32 +53,32 @@ func getJailProperty(jail *Jail, propName string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
switch val.Kind() { switch val.Kind() {
case reflect.String: case reflect.String:
return val.String(), nil return val.String(), nil
case reflect.Int: case reflect.Int:
return strconv.FormatInt(val.Int(), 10), nil return strconv.FormatInt(val.Int(), 10), nil
case reflect.Bool: case reflect.Bool:
return strconv.FormatBool(val.Bool()), nil return strconv.FormatBool(val.Bool()), nil
default: default:
return "", errors.New(fmt.Sprintf("Error: Unknown type for property %s: %s\n", propName, val.Kind())) return "", errors.New(fmt.Sprintf("Error: Unknown type for property %s: %s\n", propName, val.Kind()))
} }
} }
} }
return "", errors.New(fmt.Sprintf("Jail not found: %s", jail.Name)) return "", errors.New(fmt.Sprintf("Jail not found: %s", jail.Name))
} }
func SetJailProperties(args []string) { func SetJailProperties(args []string) {
type properties struct { type properties struct {
name string name string
value string value string
} }
var jail Jail var jail Jail
var props []properties var props []properties
if len(args) > 0 { if len(args) > 0 {
for i, a := range args { for i, a := range args {
// This is the jail name // This is the jail name
@ -96,14 +96,14 @@ func SetJailProperties(args []string) {
} }
} }
} }
} }
if len(jail.Name) == 0 || len(args) == 0 { if len(jail.Name) == 0 || len(args) == 0 {
// TODO : Show help // TODO : Show help
fmt.Printf("Error\n") fmt.Printf("Error\n")
return return
} }
// Get jail by index to modify it // Get jail by index to modify it
for i, _ := range gJails { for i, _ := range gJails {
if gJails[i].Name == jail.Name { if gJails[i].Name == jail.Name {
@ -120,5 +120,3 @@ func SetJailProperties(args []string) {
} }
} }
} }

View File

@ -1,69 +1,71 @@
package cmd package cmd
import ( import (
"os" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"os"
"strconv" "strconv"
"strings" "strings"
"io/ioutil"
"encoding/json"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
// TODO : Use log
//log "github.com/sirupsen/logrus"
) )
const ( const (
gVersion = "0.25" gVersion = "0.26a"
) )
var ( var (
gJails []Jail gJails []Jail
gUseSudo bool gUseSudo bool
gConfigFile string gConfigFile string
gDisplayColumns string gDisplayColumns string
gFilterJails string gFilterJails string
gSortFields string gSortFields string
gNoLineSep bool gNoLineSep bool
gHostVersion float64 gHostVersion float64
gTimeZone string
gSnapshotName string
rootCmd = & cobra.Command { gTimeZone string
Use: "gocage", gSnapshotName string
Short: "GoCage is a FreeBSD Jail management tool",
Long: `GoCage is a jail management tool. It support VNET, host-only, NAT networks. Provides snapshots and cloning. rootCmd = &cobra.Command{
Use: "gocage",
Short: "GoCage is a FreeBSD Jail management tool",
Long: `GoCage is a jail management tool. It support VNET, host-only, NAT networks. Provides snapshots and cloning.
It support iocage jails and can coexist with iocage.`, It support iocage jails and can coexist with iocage.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("GoCage v.%s on FreeBSD %.1f\n", gVersion, gHostVersion) fmt.Printf("GoCage v.%s on FreeBSD %.1f\n", gVersion, gHostVersion)
fmt.Printf("Use -h flag to display help\n") fmt.Printf("Use -h flag to display help\n")
}, },
} }
versionCmd = &cobra.Command { versionCmd = &cobra.Command{
Use: "version", Use: "version",
Short: "Print the version number of GoCage", Short: "Print the version number of GoCage",
Long: `Let this show you how much fail I had to get this *cough* perfect`, Long: `Let this show you how much fail I had to get this *cough* perfect`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("GoCage v.%s on FreeBSD %.1f\n", gVersion, gHostVersion) fmt.Printf("GoCage v.%s on FreeBSD %.1f\n", gVersion, gHostVersion)
}, },
} }
listCmd = &cobra.Command { listCmd = &cobra.Command{
Use: "list", Use: "list",
Short: "Print jails", Short: "Print jails",
Long: `Display jails, their IP and OS. Long: `Display jails, their IP and OS.
Jail list can be restricted by adding name on command line Jail list can be restricted by adding name on command line
ex: gocage list srv-db srv-web`, ex: gocage list srv-db srv-web`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
ListJails(args, true) ListJails(args, true)
}, },
} }
listPropsCmd = &cobra.Command { listPropsCmd = &cobra.Command{
Use: "properties", Use: "properties",
Short: "Print jails properties", Short: "Print jails properties",
Long: "Display jails properties. You can use properties to filter, get or set them.", Long: "Display jails properties. You can use properties to filter, get or set them.",
@ -71,8 +73,8 @@ ex: gocage list srv-db srv-web`,
ListJailsProps(args) ListJailsProps(args)
}, },
} }
stopCmd = &cobra.Command { stopCmd = &cobra.Command{
Use: "stop", Use: "stop",
Short: "stop jail", Short: "stop jail",
Long: "shutdown jail", Long: "shutdown jail",
@ -83,7 +85,7 @@ ex: gocage list srv-db srv-web`,
}, },
} }
startCmd = &cobra.Command { startCmd = &cobra.Command{
Use: "start", Use: "start",
Short: "start jail", Short: "start jail",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -93,21 +95,21 @@ ex: gocage list srv-db srv-web`,
WriteConfigToDisk(false) WriteConfigToDisk(false)
}, },
} }
/* shellCmd = &cobra.Command { /* shellCmd = &cobra.Command {
Use: "console", Use: "console",
Short: "Execute shell on jail", Short: "Execute shell on jail",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Load inventory // Load inventory
ListJails(args, false) ListJails(args, false)
ShellJail(args) ShellJail(args)
}, },
} }
*/ */
setCmd = &cobra.Command { setCmd = &cobra.Command{
Use: "set", Use: "set",
Short: "Set a jail property", Short: "Set a jail property",
Long: `Set jail property value. Specify property=value, end command with jail name. Long: `Set jail property value. Specify property=value, end command with jail name.
Multiples properties can be specified, separated with space (Ex: gocage set allow_mlock=1 boot=1 myjail)`, Multiples properties can be specified, separated with space (Ex: gocage set allow_mlock=1 boot=1 myjail)`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Load inventory // Load inventory
@ -116,11 +118,11 @@ Multiples properties can be specified, separated with space (Ex: gocage set allo
WriteConfigToDisk(true) WriteConfigToDisk(true)
}, },
} }
getCmd = &cobra.Command { getCmd = &cobra.Command{
Use: "get", Use: "get",
Short: "Get a jail property", Short: "Get a jail property",
Long: `Get jail property value. Specify property, end command with jail name. Long: `Get jail property value. Specify property, end command with jail name.
Multiples properties can be specified, separated with space (Ex: gocage get allow_mlock boot myjail) Multiples properties can be specified, separated with space (Ex: gocage get allow_mlock boot myjail)
For all properties specify "all" (Ex: gocage get all myjail)`, For all properties specify "all" (Ex: gocage get all myjail)`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -129,8 +131,8 @@ For all properties specify "all" (Ex: gocage get all myjail)`,
GetJailProperties(args) GetJailProperties(args)
}, },
} }
snapshotCmd = &cobra.Command { snapshotCmd = &cobra.Command{
Use: "snapshot", Use: "snapshot",
Short: "snapshot jail", Short: "snapshot jail",
Long: "Commands to manage jail snapshots. If no arguments given, ", Long: "Commands to manage jail snapshots. If no arguments given, ",
@ -138,11 +140,11 @@ For all properties specify "all" (Ex: gocage get all myjail)`,
}, },
} }
snapshotListCmd = &cobra.Command { snapshotListCmd = &cobra.Command{
Use: "list", Use: "list",
Short: "list snapshots", Short: "list snapshots",
Long: `List snapshots of a jail by specifying its name. Long: `List snapshots of a jail by specifying its name.
List all snapshots if no jail name specified. List all snapshots if no jail name specified.
You can specify multiple jails.`, You can specify multiple jails.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
@ -151,32 +153,32 @@ You can specify multiple jails.`,
ListJailsSnapshots(args) ListJailsSnapshots(args)
}, },
} }
snapshotCreateCmd = &cobra.Command { snapshotCreateCmd = &cobra.Command{
Use: "create", Use: "create",
Short: "create snapshots", Short: "create snapshots",
Long: `Create snapshot of a jail by specifying snapshot name and jail name.`, Long: `Create snapshot of a jail by specifying snapshot name and jail name.`,
// You can specify multiple jails.`, // You can specify multiple jails.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Load inventory // Load inventory
ListJails(args, false) ListJails(args, false)
CreateJailSnapshot(args) CreateJailSnapshot(args)
}, },
} }
snapshotRollbackCmd = &cobra.Command { snapshotRollbackCmd = &cobra.Command{
Use: "rollback", Use: "rollback",
Short: "Rollback snapshots", Short: "Rollback snapshots",
Long: `Rollback jail to specifyed snapshot.`, Long: `Rollback jail to specifyed snapshot.`,
// You can specify multiple jails.`, // You can specify multiple jails.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// Load inventory // Load inventory
ListJails(args, false) ListJails(args, false)
RollbackJailSnapshot(args) RollbackJailSnapshot(args)
}, },
} }
snapshotDeleteCmd = &cobra.Command { snapshotDeleteCmd = &cobra.Command{
Use: "destroy", Use: "destroy",
Short: "destroy snapshots", Short: "destroy snapshots",
Long: `Destroy snapshot of a jail by specifying snapshot name and jail name.`, Long: `Destroy snapshot of a jail by specifying snapshot name and jail name.`,
@ -189,24 +191,23 @@ You can specify multiple jails.`,
} }
) )
// TODO : Init log level and log output
func init() { func init() {
cobra.OnInitialize(initConfig) cobra.OnInitialize(initConfig)
// Global switches // Global switches
rootCmd.PersistentFlags().StringVarP(&gConfigFile, "config", "c", "/usr/local/etc/gocage.conf.yml", "GoCage configuration file") rootCmd.PersistentFlags().StringVarP(&gConfigFile, "config", "c", "/usr/local/etc/gocage.conf.yml", "GoCage configuration file")
rootCmd.PersistentFlags().BoolVarP(&gUseSudo, "sudo", "u", false, "Use sudo to run commands") rootCmd.PersistentFlags().BoolVarP(&gUseSudo, "sudo", "u", false, "Use sudo to run commands")
rootCmd.PersistentFlags().StringVarP(&gTimeZone, "timezone", "t", "", "Specify timezone. Will get from /var/db/zoneinfo if not set.") rootCmd.PersistentFlags().StringVarP(&gTimeZone, "timezone", "t", "", "Specify timezone. Will get from /var/db/zoneinfo if not set.")
// Command dependant switches // Command dependant switches
// These are persistent so we can reuse them in "gocage list snapshot myjail" command (TODO) // These are persistent so we can reuse them in "gocage list snapshot myjail" command (TODO)
listCmd.PersistentFlags().StringVarP(&gDisplayColumns, "outcol", "o", "JID,Name,Config.Release,Config.Ip4_addr,Running", "Show these columns in output") listCmd.PersistentFlags().StringVarP(&gDisplayColumns, "outcol", "o", "JID,Name,Config.Release,Config.Ip4_addr,Running", "Show these columns in output")
listCmd.PersistentFlags().BoolVarP(&gNoLineSep, "nolinesep", "l", false, "Do not display line separator between jails") listCmd.PersistentFlags().BoolVarP(&gNoLineSep, "nolinesep", "l", false, "Do not display line separator between jails")
listCmd.PersistentFlags().StringVarP(&gFilterJails, "filter", "f", "none", "Only display jails with these values. Ex: \"gocage list -f Config.Boot=1\" will only list started on boot jails") listCmd.PersistentFlags().StringVarP(&gFilterJails, "filter", "f", "none", "Only display jails with these values. Ex: \"gocage list -f Config.Boot=1\" will only list started on boot jails")
listCmd.PersistentFlags().StringVarP(&gSortFields, "sort", "s", "none", "Display jails sorted by field values. Ex: \"gocage list -s +Name,-Config.Priority\" will sort jails by their decreasing name, then increasing start priority. 3 critera max supported.") listCmd.PersistentFlags().StringVarP(&gSortFields, "sort", "s", "none", "Display jails sorted by field values. Ex: \"gocage list -s +Name,-Config.Priority\" will sort jails by their decreasing name, then increasing start priority. 3 critera max supported.")
// This is local flag : Only available to gocage snapshot create command // This is local flag : Only available to gocage snapshot create command
snapshotCreateCmd.Flags().StringVarP(&gSnapshotName, "snapname", "n", "", "Name of the snapshot to create") snapshotCreateCmd.Flags().StringVarP(&gSnapshotName, "snapname", "n", "", "Name of the snapshot to create")
snapshotCreateCmd.MarkFlagRequired("snapname") snapshotCreateCmd.MarkFlagRequired("snapname")
@ -214,8 +215,8 @@ func init() {
snapshotDeleteCmd.MarkFlagRequired("snapname") snapshotDeleteCmd.MarkFlagRequired("snapname")
snapshotRollbackCmd.Flags().StringVarP(&gSnapshotName, "snapname", "n", "", "Name of the snapshot to rollback to") snapshotRollbackCmd.Flags().StringVarP(&gSnapshotName, "snapname", "n", "", "Name of the snapshot to rollback to")
snapshotRollbackCmd.MarkFlagRequired("snapname") snapshotRollbackCmd.MarkFlagRequired("snapname")
// Now declare commands // Now declare commands
rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(listCmd) rootCmd.AddCommand(listCmd)
listCmd.AddCommand(listPropsCmd) listCmd.AddCommand(listPropsCmd)
@ -228,7 +229,7 @@ func init() {
snapshotCmd.AddCommand(snapshotCreateCmd) snapshotCmd.AddCommand(snapshotCreateCmd)
snapshotCmd.AddCommand(snapshotDeleteCmd) snapshotCmd.AddCommand(snapshotDeleteCmd)
snapshotCmd.AddCommand(snapshotRollbackCmd) snapshotCmd.AddCommand(snapshotRollbackCmd)
// Get FreeBSD version // Get FreeBSD version
out, err := executeCommand("freebsd-version") out, err := executeCommand("freebsd-version")
if err != nil { if err != nil {
@ -236,7 +237,7 @@ func init() {
os.Exit(1) os.Exit(1)
} }
gHostVersion, _ = strconv.ParseFloat(strings.Split(out, "-")[0], 32) gHostVersion, _ = strconv.ParseFloat(strings.Split(out, "-")[0], 32)
} }
func initConfig() { func initConfig() {
@ -245,7 +246,7 @@ func initConfig() {
os.Exit(1) os.Exit(1)
} }
// fmt.Printf("We are in initConfig(), with config file %s\n", gConfigFile) // fmt.Printf("We are in initConfig(), with config file %s\n", gConfigFile)
viper.SetConfigFile(gConfigFile) viper.SetConfigFile(gConfigFile)
@ -254,10 +255,10 @@ func initConfig() {
os.Exit(1) os.Exit(1)
} }
// fmt.Println("Using config file:", viper.ConfigFileUsed()) // fmt.Println("Using config file:", viper.ConfigFileUsed())
// fmt.Printf("datastore in config : %s\n", viper.GetStringSlice("datastore")) // fmt.Printf("datastore in config : %s\n", viper.GetStringSlice("datastore"))
// fmt.Printf("datastore.0 in config : %s\n", viper.GetStringSlice("datastore.0")) // fmt.Printf("datastore.0 in config : %s\n", viper.GetStringSlice("datastore.0"))
// Command line flags have priority on config file // Command line flags have priority on config file
if rootCmd.Flags().Lookup("sudo") != nil && false == rootCmd.Flags().Lookup("sudo").Changed { if rootCmd.Flags().Lookup("sudo") != nil && false == rootCmd.Flags().Lookup("sudo").Changed {
gUseSudo = viper.GetBool("sudo") gUseSudo = viper.GetBool("sudo")
@ -292,21 +293,20 @@ func initConfig() {
} }
} }
/******************************************************************************** /********************************************************************************
* Write jails config which been updated to disk. * Write jails config which been updated to disk.
* If changeauto not set, values which are in "auto" mode on disk * If changeauto not set, values which are in "auto" mode on disk
* won't be overwritten (p.ex defaultrouter wont be overwritten with current * won't be overwritten (p.ex defaultrouter wont be overwritten with current
* default route, so if route change on jailhost this will reflect on jail next * default route, so if route change on jailhost this will reflect on jail next
* start) * start)
*******************************************************************************/ *******************************************************************************/
func WriteConfigToDisk(changeauto bool) { func WriteConfigToDisk(changeauto bool) {
for _, j := range gJails { for _, j := range gJails {
if j.ConfigUpdated { if j.ConfigUpdated {
// we will manipulate properties so get a copy // we will manipulate properties so get a copy
jc := j.Config jc := j.Config
if changeauto == false { if changeauto == false {
// Overwrite "auto" properties // Overwrite "auto" properties
ondiskjc, err := getJailConfig(j.ConfigPath) ondiskjc, err := getJailConfig(j.ConfigPath)
@ -317,7 +317,7 @@ func WriteConfigToDisk(changeauto bool) {
// If "auto" then keep it that way before writing ondiskjc to disk // If "auto" then keep it that way before writing ondiskjc to disk
var properties []string var properties []string
properties = getStructFieldNames(ondiskjc, properties, "") properties = getStructFieldNames(ondiskjc, properties, "")
for _, p := range properties { for _, p := range properties {
v, _, err := getStructFieldValue(ondiskjc, p) v, _, err := getStructFieldValue(ondiskjc, p)
if err != nil { if err != nil {
@ -332,7 +332,7 @@ func WriteConfigToDisk(changeauto bool) {
} }
} }
} }
marshaled, err := json.MarshalIndent(jc, "", " ") marshaled, err := json.MarshalIndent(jc, "", " ")
if err != nil { if err != nil {
fmt.Printf("ERROR marshaling config: %s\n", err.Error()) fmt.Printf("ERROR marshaling config: %s\n", err.Error())
@ -352,5 +352,3 @@ func Execute() {
os.Exit(1) os.Exit(1)
} }
} }

View File

@ -1,13 +1,13 @@
package cmd package cmd
import ( import (
"os"
"fmt"
"time"
"bufio" "bufio"
"errors" "errors"
"fmt"
"os"
"regexp" "regexp"
"strings" "strings"
"time"
) )
/******************************************************************************** /********************************************************************************
@ -16,13 +16,13 @@ import (
func ListJailsSnapshots(args []string) { func ListJailsSnapshots(args []string) {
var jailNames []string var jailNames []string
var snapshots []Snapshot var snapshots []Snapshot
if len(args) > 0 { if len(args) > 0 {
for _, a := range args { for _, a := range args {
jailNames = append(jailNames, a) jailNames = append(jailNames, a)
} }
} }
if len(jailNames) == 0 || len(args) == 0 { if len(jailNames) == 0 || len(args) == 0 {
for _, j := range gJails { for _, j := range gJails {
snapshots = append(snapshots, listJailSnapshots(j)...) snapshots = append(snapshots, listJailSnapshots(j)...)
@ -36,16 +36,15 @@ func ListJailsSnapshots(args []string) {
} }
} }
} }
displaySnapshotsFields(snapshots, []string{"Jailname","Name","Creation","Referenced","Used"}) displaySnapshotsFields(snapshots, []string{"Jailname", "Name", "Creation", "Referenced", "Used"})
} }
/******************************************************************************** /********************************************************************************
* List all snapshots a jail have * List all snapshots a jail have
*******************************************************************************/ *******************************************************************************/
func listJailSnapshots(jail Jail) []Snapshot { func listJailSnapshots(jail Jail) []Snapshot {
var snapshots []Snapshot var snapshots []Snapshot
// 1. List all datasets // 1. List all datasets
// TODO : Include mounted filesystems? // TODO : Include mounted filesystems?
rs := strings.Split(jail.RootPath, "/") rs := strings.Split(jail.RootPath, "/")
@ -56,10 +55,10 @@ func listJailSnapshots(jail Jail) []Snapshot {
fmt.Printf("Error: %s\n", err.Error()) fmt.Printf("Error: %s\n", err.Error())
return snapshots return snapshots
} }
dateLayout := "Mon Jan _2 15:04 2006" dateLayout := "Mon Jan _2 15:04 2006"
loc, _ := time.LoadLocation(gTimeZone) loc, _ := time.LoadLocation(gTimeZone)
for _, line := range strings.Split(out, "\n") { for _, line := range strings.Split(out, "\n") {
if len(line) > 0 { if len(line) > 0 {
ls := strings.Split(line, "\t") ls := strings.Split(line, "\t")
@ -71,37 +70,36 @@ func listJailSnapshots(jail Jail) []Snapshot {
} }
// Get subdir to append to snapshot name // Get subdir to append to snapshot name
subdir := strings.Replace(strings.Split(ls[0], "@")[0], rootDataset, "", 1) subdir := strings.Replace(strings.Split(ls[0], "@")[0], rootDataset, "", 1)
snapshots = append(snapshots, Snapshot{Dsname: ls[0], snapshots = append(snapshots, Snapshot{Dsname: ls[0],
Name: fmt.Sprintf("%s%s", strings.Split(ls[0], "@")[1], subdir), Name: fmt.Sprintf("%s%s", strings.Split(ls[0], "@")[1], subdir),
Jailname: jail.Name, Jailname: jail.Name,
Mountpoint: ls[1], Mountpoint: ls[1],
Used: ls[2], Used: ls[2],
Referenced: ls[3], Referenced: ls[3],
Creation: creationts}) Creation: creationts})
} }
} }
// Sort snapshots by creation date // Sort snapshots by creation date
ss := initSnapshotSortStruct() ss := initSnapshotSortStruct()
SnapshotsOrderedBy(ss.CreationInc).Sort(snapshots) SnapshotsOrderedBy(ss.CreationInc).Sort(snapshots)
return snapshots return snapshots
} }
/******************************************************************************** /********************************************************************************
* Create snapshot for jail(s) * Create snapshot for jail(s)
*******************************************************************************/ *******************************************************************************/
func CreateJailSnapshot(args []string) { func CreateJailSnapshot(args []string) {
var jailNames []string var jailNames []string
if len(args) > 0 { if len(args) > 0 {
for _, a := range args { for _, a := range args {
jailNames = append(jailNames, a) jailNames = append(jailNames, a)
} }
} }
for _, cj := range gJails { for _, cj := range gJails {
for _, jn := range jailNames { for _, jn := range jailNames {
if strings.EqualFold(cj.Name, jn) { if strings.EqualFold(cj.Name, jn) {
@ -125,7 +123,7 @@ func createJailSnapshot(jail Jail) error {
return err return err
} }
fmt.Printf("Snapshot %s@%s created\n", rootDataset, gSnapshotName) fmt.Printf("Snapshot %s@%s created\n", rootDataset, gSnapshotName)
return nil return nil
} }
@ -134,13 +132,13 @@ func createJailSnapshot(jail Jail) error {
*******************************************************************************/ *******************************************************************************/
func DeleteJailSnapshot(args []string) { func DeleteJailSnapshot(args []string) {
var jailNames []string var jailNames []string
if len(args) > 0 { if len(args) > 0 {
for _, a := range args { for _, a := range args {
jailNames = append(jailNames, a) jailNames = append(jailNames, a)
} }
} }
for _, cj := range gJails { for _, cj := range gJails {
for _, jn := range jailNames { for _, jn := range jailNames {
if strings.EqualFold(cj.Name, jn) { if strings.EqualFold(cj.Name, jn) {
@ -155,7 +153,7 @@ func DeleteJailSnapshot(args []string) {
*******************************************************************************/ *******************************************************************************/
func deleteJailSnapshot(jail Jail) error { func deleteJailSnapshot(jail Jail) error {
var snaptodel []string var snaptodel []string
// Get all recursive snapshots // Get all recursive snapshots
rs := strings.Split(jail.RootPath, "/") rs := strings.Split(jail.RootPath, "/")
rootDataset := fmt.Sprintf("%s%s", jail.Zpool, strings.Join(rs[:len(rs)-1], "/")) rootDataset := fmt.Sprintf("%s%s", jail.Zpool, strings.Join(rs[:len(rs)-1], "/"))
@ -165,18 +163,18 @@ func deleteJailSnapshot(jail Jail) error {
fmt.Printf("Error: listing snapshots: %s\n", err.Error()) fmt.Printf("Error: listing snapshots: %s\n", err.Error())
return nil return nil
} }
for _, line := range strings.Split(out, "\n") { for _, line := range strings.Split(out, "\n") {
if len(line) > 0 { if len(line) > 0 {
ls := strings.Split(line, "@") ls := strings.Split(line, "@")
matched, _ := regexp.Match(fmt.Sprintf("^%s(\\/.*)?$", gSnapshotName), []byte(ls[1])) matched, _ := regexp.Match(fmt.Sprintf("^%s(\\/.*)?$", gSnapshotName), []byte(ls[1]))
if matched { if matched {
snaptodel = append(snaptodel, strings.Join(ls, "@")) snaptodel = append(snaptodel, strings.Join(ls, "@"))
} }
} }
} }
for _, s := range snaptodel { for _, s := range snaptodel {
cmd := fmt.Sprintf("zfs destroy %s", s) cmd := fmt.Sprintf("zfs destroy %s", s)
_, err := executeCommand(cmd) _, err := executeCommand(cmd)
@ -186,19 +184,19 @@ func deleteJailSnapshot(jail Jail) error {
} }
fmt.Printf("Snapshot %s deleted\n", s) fmt.Printf("Snapshot %s deleted\n", s)
} }
return nil return nil
} }
func RollbackJailSnapshot(args []string) error { func RollbackJailSnapshot(args []string) error {
var jailNames []string var jailNames []string
if len(args) > 0 { if len(args) > 0 {
for _, a := range args { for _, a := range args {
jailNames = append(jailNames, a) jailNames = append(jailNames, a)
} }
} }
for _, cj := range gJails { for _, cj := range gJails {
for _, jn := range jailNames { for _, jn := range jailNames {
if strings.EqualFold(cj.Name, jn) { if strings.EqualFold(cj.Name, jn) {
@ -206,7 +204,7 @@ func RollbackJailSnapshot(args []string) error {
} }
} }
} }
return nil return nil
} }
@ -216,7 +214,7 @@ func RollbackJailSnapshot(args []string) error {
*******************************************************************************/ *******************************************************************************/
func rollbackJailSnapshot(jail Jail) error { func rollbackJailSnapshot(jail Jail) error {
var snaptorb []string var snaptorb []string
if jail.Running { if jail.Running {
fmt.Printf("Jail should be stoped to rollback, should we stop and rollback? (y/n)\n") fmt.Printf("Jail should be stoped to rollback, should we stop and rollback? (y/n)\n")
scanr := bufio.NewScanner(os.Stdin) scanr := bufio.NewScanner(os.Stdin)
@ -231,7 +229,7 @@ func rollbackJailSnapshot(jail Jail) error {
} }
} }
} }
// We need to rollback parent and childs // We need to rollback parent and childs
// Get all recursive snapshots // Get all recursive snapshots
rs := strings.Split(jail.RootPath, "/") rs := strings.Split(jail.RootPath, "/")
@ -242,18 +240,18 @@ func rollbackJailSnapshot(jail Jail) error {
fmt.Printf("Error: listing snapshots: %s\n", err.Error()) fmt.Printf("Error: listing snapshots: %s\n", err.Error())
return err return err
} }
for _, line := range strings.Split(out, "\n") { for _, line := range strings.Split(out, "\n") {
if len(line) > 0 { if len(line) > 0 {
ls := strings.Split(line, "@") ls := strings.Split(line, "@")
matched, _ := regexp.Match(fmt.Sprintf("^%s(\\/.*)?$", gSnapshotName), []byte(ls[1])) matched, _ := regexp.Match(fmt.Sprintf("^%s(\\/.*)?$", gSnapshotName), []byte(ls[1]))
if matched { if matched {
snaptorb = append(snaptorb, strings.Join(ls, "@")) snaptorb = append(snaptorb, strings.Join(ls, "@"))
} }
} }
} }
for _, s := range snaptorb { for _, s := range snaptorb {
cmd := fmt.Sprintf("zfs rollback -r %s", s) cmd := fmt.Sprintf("zfs rollback -r %s", s)
_, err := executeCommand(cmd) _, err := executeCommand(cmd)
@ -263,6 +261,6 @@ func rollbackJailSnapshot(jail Jail) error {
} }
} }
fmt.Printf("Jail is back to %s\n", gSnapshotName) fmt.Printf("Jail is back to %s\n", gSnapshotName)
return nil return nil
} }

View File

@ -1,13 +1,16 @@
package cmd package cmd
import ( import (
"os"
"fmt"
"errors" "errors"
"regexp" "fmt"
"strings" "github.com/c-robinson/iplib"
"strconv" log "github.com/sirupsen/logrus"
"io/ioutil" "io/ioutil"
"net"
"os"
"regexp"
"strconv"
"strings"
) )
// FIXME : Do not work?! // FIXME : Do not work?!
@ -34,7 +37,7 @@ func mountProcFs(jail *Jail) error {
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error mounting procfs on %s/proc: %s", jail.RootPath, err.Error())) return errors.New(fmt.Sprintf("Error mounting procfs on %s/proc: %s", jail.RootPath, err.Error()))
} }
return nil return nil
} }
@ -52,7 +55,7 @@ func mountLinProcFs(jail *Jail) error {
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error mounting linprocfs on %s: %s", ldir, err.Error())) return errors.New(fmt.Sprintf("Error mounting linprocfs on %s: %s", ldir, err.Error()))
} }
return nil return nil
} }
@ -62,7 +65,7 @@ func mountDevFs(jail *Jail) error {
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error mounting devfs on %s/dev: %s", jail.RootPath, err.Error())) return errors.New(fmt.Sprintf("Error mounting devfs on %s/dev: %s", jail.RootPath, err.Error()))
} }
return nil return nil
} }
@ -73,17 +76,17 @@ func mountFdescFs(jail *Jail) error {
jail.Config.Mount_fdescfs = 0 jail.Config.Mount_fdescfs = 0
// Tag config so it will be synced on disk // Tag config so it will be synced on disk
jail.ConfigUpdated = true jail.ConfigUpdated = true
// Should we consider this an error? // Should we consider this an error?
return nil return nil
} }
cmd := fmt.Sprintf("mount -t fdescfs descfs %s/dev/fd", jail.RootPath) cmd := fmt.Sprintf("mount -t fdescfs descfs %s/dev/fd", jail.RootPath)
_, err := executeCommand(cmd) _, err := executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error mounting fdescfs on %s/dev/fd: %s", jail.RootPath, err.Error())) return errors.New(fmt.Sprintf("Error mounting fdescfs on %s/dev/fd: %s", jail.RootPath, err.Error()))
} }
return nil return nil
} }
@ -93,22 +96,22 @@ func mountAllJailFsFromHost(jail *Jail) error {
devfsFound := false devfsFound := false
fdescfsFound := false fdescfsFound := false
cmd := "mount -p" cmd := "mount -p"
out, err := executeCommand(cmd) out, err := executeCommand(cmd)
if err != nil { if err != nil {
return errors.New(fmt.Sprintf("Error executing mount: %s", err.Error())) return errors.New(fmt.Sprintf("Error executing mount: %s", err.Error()))
} }
var outclean []string var outclean []string
remSpPtrn := regexp.MustCompile(`\s+`) remSpPtrn := regexp.MustCompile(`\s+`)
for _, l := range strings.Split(out, "\n") { for _, l := range strings.Split(out, "\n") {
outclean = append(outclean, remSpPtrn.ReplaceAllString(l, " ")) outclean = append(outclean, remSpPtrn.ReplaceAllString(l, " "))
} }
// Check if these FS are already mounted // Check if these FS are already mounted
for _, l := range outclean { for _, l := range outclean {
f := strings.Split(l, " ") f := strings.Split(l, " ")
if len(f) > 2 { if len(f) > 2 {
if strings.EqualFold(f[1], fmt.Sprintf("%s/proc", jail.RootPath)) { if strings.EqualFold(f[1], fmt.Sprintf("%s/proc", jail.RootPath)) {
procfsFound = true procfsFound = true
@ -128,22 +131,22 @@ func mountAllJailFsFromHost(jail *Jail) error {
// Mount wanted FS // Mount wanted FS
if jail.Config.Mount_procfs > 0 && procfsFound == false { if jail.Config.Mount_procfs > 0 && procfsFound == false {
err := mountProcFs(jail) err := mountProcFs(jail)
if err != nil { if err != nil {
return err return err
} }
} }
if jail.Config.Mount_linprocfs > 0 && linProcfsFound == false { if jail.Config.Mount_linprocfs > 0 && linProcfsFound == false {
err = mountLinProcFs(jail) err = mountLinProcFs(jail)
if err != nil { if err != nil {
return err return err
} }
} }
if jail.Config.Mount_devfs > 0 && devfsFound == false { if jail.Config.Mount_devfs > 0 && devfsFound == false {
err := mountDevFs(jail) err := mountDevFs(jail)
if err != nil { if err != nil {
return err return err
} }
} }
if jail.Config.Mount_fdescfs > 0 && fdescfsFound == false { if jail.Config.Mount_fdescfs > 0 && fdescfsFound == false {
@ -153,7 +156,6 @@ func mountAllJailFsFromHost(jail *Jail) error {
} }
} }
// Ces montages doivent-ils etre effectués une fois le jail démarré? // Ces montages doivent-ils etre effectués une fois le jail démarré?
// FreeBSD <= 9.3 do not support fdescfs // FreeBSD <= 9.3 do not support fdescfs
@ -172,7 +174,7 @@ func mountAllJailFsFromHost(jail *Jail) error {
if gHostVersion < 12 { if gHostVersion < 12 {
if jail.Config.Allow_mlock > 0 { if jail.Config.Allow_mlock > 0 {
jail.Config.Allow_mlock = 0 jail.Config.Allow_mlock = 0
jail.ConfigUpdated = true jail.ConfigUpdated = true
/* WIP /* WIP
err = setJailProperty(jail, "Config.Allow_mlock", "0") err = setJailProperty(jail, "Config.Allow_mlock", "0")
@ -186,11 +188,10 @@ func mountAllJailFsFromHost(jail *Jail) error {
} }
} }
return nil return nil
} }
// TODO
// TODO
func prepareJailedZfsDatasets(jail *Jail) error { func prepareJailedZfsDatasets(jail *Jail) error {
if jail.Config.Jail_zfs > 0 { if jail.Config.Jail_zfs > 0 {
// For jail to mount filesystem, enforce_statfs should be 1 or lower (2 is the default) // For jail to mount filesystem, enforce_statfs should be 1 or lower (2 is the default)
@ -229,18 +230,18 @@ func prepareJailedZfsDatasets(jail *Jail) error {
} }
type NatDesc struct { type NatDesc struct {
Proto string Proto string
JailPort string JailPort string
HostPort string HostPort string
} }
// tcp(80:8080),tcp(3300-3310:33060-33070) // tcp(80:8080),tcp(3300-3310:33060-33070)
func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc, error) { func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc, error) {
var res []NatDesc var res []NatDesc
regx := `(tcp|udp)\(([0-9]{1,5}(?:-[0-9]{1,5})?):([0-9]{1,5}(?:-[0-9]{1,5})?)\)` regx := `(tcp|udp)\(([0-9]{1,5}(?:-[0-9]{1,5})?):([0-9]{1,5}(?:-[0-9]{1,5})?)\)`
re := regexp.MustCompile(regx) re := regexp.MustCompile(regx)
for _, match := range re.FindAllStringSubmatch(nat_forwards, -1) { for _, match := range re.FindAllStringSubmatch(nat_forwards, -1) {
if strings.Contains(match[2], "-") == true && decompose_range == true { if strings.Contains(match[2], "-") == true && decompose_range == true {
sjrange, err := strconv.Atoi(strings.Split(match[2], "-")[0]) sjrange, err := strconv.Atoi(strings.Split(match[2], "-")[0])
@ -262,7 +263,7 @@ func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc,
if (ejrange - sjrange) != (ehrange - shrange) { if (ejrange - sjrange) != (ehrange - shrange) {
return res, errors.New(fmt.Sprintf("Invalid port range in nat_forwards: %s", match[0])) return res, errors.New(fmt.Sprintf("Invalid port range in nat_forwards: %s", match[0]))
} }
for i := sjrange ; i <= ejrange ; i++ { for i := sjrange; i <= ejrange; i++ {
nd := NatDesc{Proto: match[1], nd := NatDesc{Proto: match[1],
JailPort: strconv.Itoa(i), JailPort: strconv.Itoa(i),
HostPort: strconv.Itoa(shrange + (i - sjrange)), HostPort: strconv.Itoa(shrange + (i - sjrange)),
@ -271,16 +272,226 @@ func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc,
} }
} else { } else {
nd := NatDesc{Proto: match[1], nd := NatDesc{Proto: match[1],
JailPort: match[2], JailPort: match[2],
HostPort: match[3], HostPort: match[3],
} }
res = append(res, nd) res = append(res, nd)
} }
} }
return res, nil return res, nil
} }
func enableRcKeyValue(rcconfpath string, key string, value string) error {
cmd := fmt.Sprintf("/usr/sbin/sysrc -f %s %s=%s", rcconfpath, key, value)
_, err := executeCommand(cmd)
if err != nil {
return err
}
return nil
}
func disableRcKey(rcconfpath string, key string) error {
cmd := fmt.Sprintf("/usr/sbin/sysrc -f %s -x %s", rcconfpath, key)
_, err := executeCommand(cmd)
if err != nil {
return err
}
return nil
}
/*****************************************************************************
* Enable or disables DHCP or accept_rtadv for interfaces declared with this
* option
****************************************************************************/
func configureDhcpOrAcceptRtadv(jail *Jail, ipproto int, enable bool) error {
var nics []string
// Iocage legacy behavior to enable on all interfaces if Config.Dhcp is set...
if ipproto == IPv4 && jail.Config.Dhcp > 0 || enable == false {
nic_list := strings.Split(jail.Config.Interfaces, ",")
for _, n := range nic_list {
nics = append(nics, strings.Split(n, ":")[0])
}
// ...else enable for selected interface in Config.IpX_addr
} else {
if ipproto == IPv4 {
for _, i := range strings.Split(jail.Config.Ip4_addr, ",") {
if strings.EqualFold(strings.ToLower(strings.Split(i, "|")[1]), "dhcp") {
nics = append(nics, i)
}
}
} else {
for _, i := range strings.Split(jail.Config.Ip6_addr, ",") {
if strings.EqualFold(strings.ToLower(strings.Split(i, "|")[1]), "accept_rtadv") {
nics = append(nics, i)
}
}
}
}
for _, n := range nics {
// vnet0 is epair0b inside jail
if strings.Contains(n, "vnet") {
n = fmt.Sprintf("%sb", strings.Replace(n, "vnet", "epair", 1))
}
key := fmt.Sprintf("ifconfig_%s", n)
value := "SYNCDHCP"
if ipproto == IPv6 {
key = fmt.Sprintf("%s_ipv6", key)
value = "inet6 auto_linklocal accept_rtadv autoconf"
}
if enable == true {
err := enableRcKeyValue(jail.ConfigPath, key, value)
if err != nil {
return fmt.Errorf("ERROR setting %s=%s with sysrc for jail %s: %s\n", key, value, jail.Name, err)
}
} else {
err := disableRcKey(jail.ConfigPath, key)
if err != nil {
return fmt.Errorf("ERROR deleting %s with sysrc for jail %s: %s\n", key, value, jail.Name, err)
}
}
}
return nil
}
func checkRtsold(jail *Jail) error {
if strings.Contains(jail.Config.Ip6_addr, "accept_rtadv") == false {
return fmt.Errorf("Must set at least one ip6_addr to accept_rtadv!\n")
}
err := enableRcKeyValue(jail.ConfigPath, "rtsold_enable", "yes")
if err != nil {
return fmt.Errorf("ERROR setting rtsold_enable=YES with sysrc for jail %s: %s\n", jail.Name, err)
}
return nil
}
func checkNat(backend string) error {
cmd := "/sbin/sysctl -q net.inet.ip.forwarding=1"
_, err := executeCommand(cmd)
if err != nil {
return fmt.Errorf("ERROR executing \"/sbin/sysctl -q net.inet.ip.forwarding=1\": %s", err)
}
if strings.EqualFold(backend, "pf") {
// Load module and enable pf
out, err := executeCommand("/sbin/kldload -n pf")
if err != nil {
if false == strings.Contains(out, "module already loaded or in kernel") {
return fmt.Errorf("ERROR executing \"/sbin/kldload pf\": %s", err)
}
}
out, err = executeCommand("/sbin/pfctl -e")
if err != nil {
if false == strings.Contains(out, "pf already enabled") {
return fmt.Errorf("ERROR executing \"/sbin/pfctl -e\": %s", err)
}
}
} else if strings.EqualFold(backend, "ipwf") {
// Check if module loaded
out, err := executeCommand("/sbin/sysctl net.inet.ip.fw.enable=1")
if err != nil {
if false == strings.Contains(out, "unknown oid 'net.inet.ip.fw.enable'") {
return fmt.Errorf("ERROR executing \"/sbin/sysctl net.inet.ip.fw.enable=1\": %s", err)
}
}
_, _ = executeCommand("/bin/kenv net.inet.ip.fw.default_to_accept=1")
_, _ = executeCommand("/sbin/kldload -n ipfw")
_, _ = executeCommand("/sbin/kldload -n ipfw_nat")
_, err = executeCommand("/sbin/sysctl -q net.inet.ip.fw.enable=1")
if err != nil {
return fmt.Errorf("ERROR executing \"/sbin/sysctl -q net.inet.ip.fw.enable=1\": %s", err)
}
}
return nil
}
func getJailsInUseIPv4() ([]string, error) {
var ips []string
re := regexp.MustCompile(ifconfigipv4re)
for _, j := range gJails {
out, err := executeCommandInJail(&j, "/sbin/ifconfig")
if err != nil {
return ips, fmt.Errorf("ERROR executing \"/sbin/ifconfig\" in jail %s: %s", j.Name, err)
}
for _, line := range strings.Split(out, "\n") {
if re.MatchString(line) {
ips = append(ips, re.FindStringSubmatch(line)[1])
}
}
}
return ips, nil
}
func getHostInUseIPv4() ([]string, error) {
var ips []string
re := regexp.MustCompile(ifconfigipv4re)
out, err := executeCommand("/sbin/ifconfig")
if err != nil {
return ips, fmt.Errorf("ERROR executing \"/sbin/ifconfig\": %s", err)
}
for _, line := range strings.Split(out, "\n") {
if re.MatchString(line) {
ips = append(ips, re.FindStringSubmatch(line)[1])
}
}
return ips, nil
}
func genNatIpv4(jail *Jail) ([]string, error) {
var ippair []string
// Get all IP in use, host and jails
inuseip4, err := getHostInUseIPv4()
if err != nil {
return ippair, err
}
ij, err := getJailsInUseIPv4()
if err != nil {
return ippair, err
}
inuseip4 = append(inuseip4, ij...)
// TODO : Voir https://github.com/iocage/iocage/blob/e94863d4c54f02523fb09e62e48be7db9ac92eda/iocage_lib/ioc_common.py#L1026
for i := 0; i < 256; i++ {
for j := 0; j < 256; j += 4 {
n := iplib.NewNet4(net.ParseIP(fmt.Sprintf("172.16.%d.%d", i, j)), 30)
for _, ip := range n.Enumerate(0, 0) {
ippair = append(ippair, ip.String())
}
found := false
for _, ip := range inuseip4 {
for _, ipn := range ippair {
if ip == ipn {
found = true
}
}
}
if found == false {
return ippair, nil
}
}
}
return ippair, nil
}
/* /*
Start jail: Start jail:
Check jail fstab? Check jail fstab?
@ -309,10 +520,11 @@ func getNatForwardsArray(nat_forwards string, decompose_range bool) ([]NatDesc,
func StartJail(args []string) { func StartJail(args []string) {
// jail we have to start // jail we have to start
var cj *Jail var cj *Jail
var err error
for _, j := range args { for _, j := range args {
fmt.Printf("> Starting jail %s\n", j) fmt.Printf("> Starting jail %s\n", j)
for i, rj := range gJails { for i, rj := range gJails {
if rj.Name == j { if rj.Name == j {
// Get jail reference, not a copy of it; So we can modify attributes // Get jail reference, not a copy of it; So we can modify attributes
@ -324,12 +536,12 @@ func StartJail(args []string) {
fmt.Printf("Jail not found: %s\n", j) fmt.Printf("Jail not found: %s\n", j)
continue continue
} }
if cj.Running == true { if cj.Running == true {
fmt.Printf("Jail %s is already running!\n", cj.Name) fmt.Printf("Jail %s is already running!\n", cj.Name)
continue continue
} }
if len(cj.Config.Hostid) > 0 && cj.Config.Hostid_strict_check > 0 { if len(cj.Config.Hostid) > 0 && cj.Config.Hostid_strict_check > 0 {
hostid, err := ioutil.ReadFile("/etc/hostid") hostid, err := ioutil.ReadFile("/etc/hostid")
if err != nil { if err != nil {
@ -342,10 +554,10 @@ func StartJail(args []string) {
return return
} }
} }
var props_missing []string var props_missing []string
// DHCP can also be set with "DHCP" value in ip4_addr // DHCP can also be set with "dhcp" value in ip4_addr (Eg: "vnet0|dhcp")
if cj.Config.Dhcp > 0 || strings.EqualFold(cj.Config.Ip4_addr, "DHCP") == true { if cj.Config.Dhcp > 0 || strings.Contains(strings.ToLower(cj.Config.Ip4_addr), "dhcp") == true {
if cj.Config.Bpf == 0 { if cj.Config.Bpf == 0 {
props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires bpf", cj.Name)) props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires bpf", cj.Name))
} }
@ -353,10 +565,10 @@ func StartJail(args []string) {
props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires vnet", cj.Name)) props_missing = append(props_missing, fmt.Sprintf("%s: dhcp requires vnet", cj.Name))
} }
} }
// tcp(80:8080),tcp(3300-3310:33000-33010) // tcp(80:8080),tcp(3300-3310:33000-33010)
if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_forwards, "none") == false { if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_forwards, "none") == false {
// If NAT && port forwarding is enabled, check that port does not conflict // If NAT && port forwarding is enabled, check that port does not conflict
// with another running jail // with another running jail
for _, j := range gJails { for _, j := range gJails {
if j.Running == false || strings.EqualFold(j.Config.Nat_forwards, "none") == false || j.Config.Nat != 1 { if j.Running == false || strings.EqualFold(j.Config.Nat_forwards, "none") == false || j.Config.Nat != 1 {
@ -376,7 +588,7 @@ func StartJail(args []string) {
for _, cjn := range cjnd { for _, cjn := range cjnd {
if jn == cjn { if jn == cjn {
fmt.Printf("nat_forwards rule \"%s\" is in conflict with jail %s, won't start\n", fmt.Printf("nat_forwards rule \"%s\" is in conflict with jail %s, won't start\n",
fmt.Sprintf("%s(%s:%s)", cjn.Proto, cjn.JailPort, cjn.HostPort), j.Name) fmt.Sprintf("%s(%s:%s)", cjn.Proto, cjn.JailPort, cjn.HostPort), j.Name)
return return
} }
} }
@ -384,27 +596,68 @@ func StartJail(args []string) {
} }
} }
} }
if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_interface, "none") == true { if cj.Config.Nat > 0 && strings.EqualFold(cj.Config.Nat_interface, "none") == true {
var jhost JailHost var jhost JailHost
cj.Config.Nat_interface = jhost.GetDefaultInterface() cj.Config.Nat_interface = jhost.GetDefaultInterface()
cj.ConfigUpdated = true cj.ConfigUpdated = true
} }
if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter, "auto") == true { if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter, "auto") == true {
var jhost JailHost var jhost JailHost
cj.Config.Defaultrouter = jhost.GetDefaultGateway4() cj.Config.Defaultrouter = jhost.GetDefaultGateway4()
// "auto" default Gateway should not be updated to support jailhost route change // "auto" default Gateway should not be updated to support jailhost route change
} }
if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter6, "auto") == true { if cj.Config.Vnet > 0 && strings.EqualFold(cj.Config.Defaultrouter6, "auto") == true {
var jhost JailHost var jhost JailHost
cj.Config.Defaultrouter6 = jhost.GetDefaultGateway6() cj.Config.Defaultrouter6 = jhost.GetDefaultGateway6()
// "auto" default Gateway should not be updated to support jailhost route change // "auto" default Gateway should not be updated to support jailhost route change
} }
// Continue here if strings.EqualFold(cj.Config.Ip6_addr, "accept_rtadv") && cj.Config.Vnet == 0 {
props_missing = append(props_missing, fmt.Sprintf("%s: accept_rtadv requires vnet", cj.Name))
}
if cj.Config.Bpf > 0 && cj.Config.Vnet == 0 {
props_missing = append(props_missing, fmt.Sprintf("%s: bpf requires vnet", cj.Name))
}
if len(props_missing) > 0 {
for _, m := range props_missing {
fmt.Printf("%s\n", m)
}
return
}
if cj.Config.Dhcp > 0 || strings.Contains(strings.ToLower(cj.Config.Ip4_addr), "dhcp") == true {
err = configureDhcpOrAcceptRtadv(cj, IPv4, true)
} else {
err = configureDhcpOrAcceptRtadv(cj, IPv4, false)
}
if err != nil {
fmt.Printf(err.Error())
return
}
if cj.Config.Rtsold > 0 {
err = checkRtsold(cj)
}
if err != nil {
fmt.Printf(err.Error())
return
}
if strings.Contains(strings.ToLower(cj.Config.Ip6_addr), "accept_rtadv") == true {
err = configureDhcpOrAcceptRtadv(cj, IPv6, true)
} else {
err = configureDhcpOrAcceptRtadv(cj, IPv6, false)
}
if err != nil {
fmt.Printf(err.Error())
return
}
fmt.Printf(" > Mount special filesystems:\n") fmt.Printf(" > Mount special filesystems:\n")
err := mountAllJailFsFromHost(cj) err := mountAllJailFsFromHost(cj)
if err != nil { if err != nil {
@ -412,7 +665,7 @@ func StartJail(args []string) {
} else { } else {
fmt.Printf(" > Mount special filesystems: OK\n") fmt.Printf(" > Mount special filesystems: OK\n")
} }
if cj.Config.Jail_zfs > 0 { if cj.Config.Jail_zfs > 0 {
fmt.Printf(" > Prepare ZFS Datasets:\n") fmt.Printf(" > Prepare ZFS Datasets:\n")
err := prepareJailedZfsDatasets(cj) err := prepareJailedZfsDatasets(cj)
@ -422,77 +675,116 @@ func StartJail(args []string) {
fmt.Printf(" > Prepare ZFS Datasets: OK\n") fmt.Printf(" > Prepare ZFS Datasets: OK\n")
} }
} }
// TODO : Check capabilites relative to FreeBSD Version when executing jail with all parameters
/* // See l.335 of https://github.com/iocage/iocage/blob/e94863d4c54f02523fb09e62e48be7db9ac92eda/iocage_lib/ioc_start.py
out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName)) //checkCapabilities(cj)
if err == nil && len(out) > 0 {
fmt.Printf(" > Remove RCTL rules:\n") // Check NAT backend
err := removeRctlRules(cj.InternalName, []string{""}) if cj.Config.Nat > 0 {
log.Debug("Check NAT backend %s\n", cj.Config.Nat_backend)
err = checkNat(cj.Config.Nat_backend)
if err != nil { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf(err.Error())
return
}
if cj.Config.Vnet == 0 {
log.Debug("Generate NAT IPv4 without VNet")
ip4, err := genNatIpv4(cj)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
log.Debug("Configuring NAT : Set ip4_addr to %s", ip4[0])
// This IP should not be saved into json
cj.Config.Ip4_addr = fmt.Sprintf("%s|%s", cj.Config.Nat_interface, ip4[0])
} else { } else {
fmt.Printf(" > Remove RCTL rules: OK\n") log.Debug("Generate NAT IPv4 with VNet")
ip4, err := genNatIpv4(cj)
if err != nil {
fmt.Printf("%s\n", err.Error())
return
}
log.Debug("Configuring NAT : Set ip4_addr to %s, defaultrouter to %s", ip4[1], ip4[0])
// This IP should not be saved into json
cj.Config.Ip4_addr = fmt.Sprintf("vnet0|%s", ip4[1])
cj.Config.Defaultrouter = ip4[0]
} }
} }
if len (cj.Config.Exec_prestop) > 0 { // CONTINUE HERE
fmt.Printf(" > Execute prestop:\n") // See https://github.com/iocage/iocage/blob/e94863d4c54f02523fb09e62e48be7db9ac92eda/iocage_lib/ioc_start.py:401
_, err := executeCommand(cj.Config.Exec_prestop)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Execute prestop: OK\n")
}
}
if len (cj.Config.Exec_stop) > 0 {
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(" > Execute stop: OK\n")
}
}
if cj.Config.Jail_zfs > 0 { /*
fmt.Printf(" > Umount jailed ZFS:\n") out, err := executeCommand(fmt.Sprintf("rctl jail:%s", cj.InternalName))
err := umountAndUnjailZFS(cj) if err == nil && len(out) > 0 {
if err != nil { fmt.Printf(" > Remove RCTL rules:\n")
fmt.Printf("ERROR: %s\n", err.Error()) err := removeRctlRules(cj.InternalName, []string{""})
} else { if err != nil {
fmt.Printf(" > Umount jailed ZFS: OK\n") fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Remove RCTL rules: OK\n")
}
} }
}
if cj.Config.Vnet > 0 && len(cj.Config.Ip4_addr) > 0 { if len (cj.Config.Exec_prestop) > 0 {
fmt.Printf(" > Destroy VNet interfaces:\n") fmt.Printf(" > Execute prestop:\n")
err := destroyVNetInterfaces(cj) _, err := executeCommand(cj.Config.Exec_prestop)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
fmt.Printf(" > Execute prestop: OK\n")
}
}
if len (cj.Config.Exec_stop) > 0 {
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(" > Execute stop: OK\n")
}
}
if cj.Config.Jail_zfs > 0 {
fmt.Printf(" > Umount jailed ZFS:\n")
err := umountAndUnjailZFS(cj)
if err != nil {
fmt.Printf("ERROR: %s\n", err.Error())
} else {
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 { if err != nil {
fmt.Printf("ERROR: %s\n", err.Error()) fmt.Printf("ERROR: %s\n", err.Error())
} else { } else {
fmt.Printf(" > Destroy VNet interfaces: OK\n") fmt.Printf(" > Remove devfsruleset %s: OK\n", cj.Config.Devfs_ruleset)
} }
}
fmt.Printf(" > Stop jail %s:\n", cj.Name)
fmt.Printf(" > Remove devfsruleset %s:\n", cj.Config.Devfs_ruleset) err = stopJail(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(" > Stop jail %s: OK\n", cj.Name)
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)
}
*/
} }
} }

View File

@ -1,13 +1,13 @@
package cmd package cmd
import ( import (
"os"
"fmt" "fmt"
// "log" "os"
// "log"
"errors" "errors"
"regexp"
"os/exec" "os/exec"
// "reflect" "regexp"
// "reflect"
"strings" "strings"
) )
@ -38,7 +38,6 @@ func removeRctlRules(jail string, rules []string) error {
return nil return nil
} }
// TODO: Validate with >1 dataset // TODO: Validate with >1 dataset
func umountAndUnjailZFS(jail *Jail) error { func umountAndUnjailZFS(jail *Jail) error {
var ds []string var ds []string
@ -75,11 +74,10 @@ func umountAndUnjailZFS(jail *Jail) error {
fmt.Printf("ERROR unjailing %s/%s: %s\n", jail.Zpool, 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
} }
return nil return nil
} }
func destroyVNetInterfaces(jail *Jail) error { func destroyVNetInterfaces(jail *Jail) error {
for _, i := range strings.Split(jail.Config.Ip4_addr, ",") { for _, i := range strings.Split(jail.Config.Ip4_addr, ",") {
iname := fmt.Sprintf("%s.%d", strings.Split(i, "|")[0], jail.JID) iname := fmt.Sprintf("%s.%d", strings.Split(i, "|")[0], jail.JID)
@ -119,7 +117,6 @@ func deleteDevfsRuleset(jail *Jail) error {
return nil return nil
} }
func umountJailFsFromHost(jail *Jail, mountpoint string) error { func umountJailFsFromHost(jail *Jail, mountpoint string) error {
cmd := "mount -p" cmd := "mount -p"
out, err := executeCommand(cmd) out, err := executeCommand(cmd)
@ -145,7 +142,6 @@ func umountJailFsFromHost(jail *Jail, mountpoint string) error {
return nil return nil
} }
// Internal usage only // Internal usage only
func stopJail(jail *Jail) error { func stopJail(jail *Jail) error {
cmd := "jail -q" cmd := "jail -q"
@ -221,7 +217,7 @@ func StopJail(args []string) {
} }
} }
if len (cj.Config.Exec_prestop) > 0 { if len(cj.Config.Exec_prestop) > 0 {
fmt.Printf(" > Execute prestop:\n") fmt.Printf(" > Execute prestop:\n")
_, err := executeCommand(cj.Config.Exec_prestop) _, err := executeCommand(cj.Config.Exec_prestop)
if err != nil { if err != nil {
@ -230,8 +226,8 @@ func StopJail(args []string) {
fmt.Printf(" > Execute prestop: OK\n") fmt.Printf(" > Execute prestop: OK\n")
} }
} }
if len (cj.Config.Exec_stop) > 0 { if len(cj.Config.Exec_stop) > 0 {
fmt.Printf(" > Execute stop:\n") fmt.Printf(" > Execute stop:\n")
_, err := executeCommandInJail(cj, cj.Config.Exec_stop) _, err := executeCommandInJail(cj, cj.Config.Exec_stop)
if err != nil { if err != nil {
@ -260,7 +256,7 @@ func StopJail(args []string) {
fmt.Printf(" > Destroy VNet interfaces: OK\n") fmt.Printf(" > Destroy VNet interfaces: OK\n")
} }
} }
/*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 {
@ -268,7 +264,7 @@ func StopJail(args []string) {
} 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)
if err != nil { if err != nil {
@ -340,4 +336,3 @@ func StopJail(args []string) {
} }
} }
} }

View File

@ -4,19 +4,24 @@ import (
"time" "time"
) )
const (
IPv4 = 0
IPv6 = 1
)
// To allow sorting, just duplicate fields in JailSort below // To allow sorting, just duplicate fields in JailSort below
type Jail struct { type Jail struct {
Name string Name string
InternalName string InternalName string
JID int JID int
Config JailConfig Config JailConfig
RootPath string RootPath string
ConfigPath string ConfigPath string
ConfigUpdated bool 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
Zpool string Zpool string
} }
// iocage struct as stored in config.json // iocage struct as stored in config.json
@ -28,483 +33,483 @@ type Jail struct {
// //
// To allow sorting, just duplicate fields in JailConfigSort below // To allow sorting, just duplicate fields in JailConfigSort below
type JailConfig struct { type JailConfig struct {
Config_version string `json:"CONFIG_VERSION"` Config_version string `json:"CONFIG_VERSION"`
Allow_chflags int `json:"allow_chflags"` Allow_chflags int `json:"allow_chflags"`
Allow_mlock int `json:"allow_mlock"` Allow_mlock int `json:"allow_mlock"`
Allow_mount int `json:"allow_mount"` Allow_mount int `json:"allow_mount"`
Allow_mount_devfs int `json:"allow_mount_devfs"` Allow_mount_devfs int `json:"allow_mount_devfs"`
Allow_mount_fusefs int `json:"allow_mount_fusefs"` Allow_mount_fusefs int `json:"allow_mount_fusefs"`
Allow_mount_nullfs int `json:"allow_mount_nullfs"` Allow_mount_nullfs int `json:"allow_mount_nullfs"`
Allow_mount_procfs int `json:"allow_mount_procfs"` Allow_mount_procfs int `json:"allow_mount_procfs"`
Allow_mount_tmpfs int `json:"allow_mount_tmpfs"` Allow_mount_tmpfs int `json:"allow_mount_tmpfs"`
Allow_mount_zfs int `json:"allow_mount_zfs"` Allow_mount_zfs int `json:"allow_mount_zfs"`
Allow_quotas int `json:"allow_quotas"` Allow_quotas int `json:"allow_quotas"`
Allow_raw_sockets int `json:"allow_raw_sockets"` Allow_raw_sockets int `json:"allow_raw_sockets"`
Allow_set_hostname int `json:"allow_set_hostname"` Allow_set_hostname int `json:"allow_set_hostname"`
Allow_socket_af int `json:"allow_socket_af"` Allow_socket_af int `json:"allow_socket_af"`
Allow_sysvipc int `json:"allow_sysvipc"` Allow_sysvipc int `json:"allow_sysvipc"`
Allow_tun int `json:"allow_tun"` Allow_tun int `json:"allow_tun"`
Allow_vmm int `json:"allow_vmm"` Allow_vmm int `json:"allow_vmm"`
Assign_localhost int `json:"assign_localhost"` Assign_localhost int `json:"assign_localhost"`
Available string `json:"available"` Available string `json:"available"`
Basejail int `json:"basejail"` Basejail int `json:"basejail"`
Boot int `json:"boot"` Boot int `json:"boot"`
Bpf int `json:"bpf"` Bpf int `json:"bpf"`
Children_max string `json:"children_max"` Children_max string `json:"children_max"`
Cloned_release string `json:"cloned_release"` Cloned_release string `json:"cloned_release"`
Comment string `json:"comment"` Comment string `json:"comment"`
Compression string `json:"compression"` Compression string `json:"compression"`
Compressratio string `json:"compressratio"` Compressratio string `json:"compressratio"`
Coredumpsize string `json:"coredumpsize"` Coredumpsize string `json:"coredumpsize"`
Count string `json:"count"` Count string `json:"count"`
Cpuset string `json:"cpuset"` Cpuset string `json:"cpuset"`
Cputime string `json:"cputime"` Cputime string `json:"cputime"`
Datasize string `json:"datasize"` Datasize string `json:"datasize"`
Dedup string `json:"dedup"` Dedup string `json:"dedup"`
Defaultrouter string `json:"defaultrouter"` Defaultrouter string `json:"defaultrouter"`
Defaultrouter6 string `json:"defaultrouter6"` Defaultrouter6 string `json:"defaultrouter6"`
Depends string `json:"depends"` Depends string `json:"depends"`
Devfs_ruleset string `json:"devfs_ruleset"` Devfs_ruleset string `json:"devfs_ruleset"`
Dhcp int `json:"dhcp"` Dhcp int `json:"dhcp"`
Enforce_statfs string `json:"enforce_statfs"` Enforce_statfs string `json:"enforce_statfs"`
Exec_clean int `json:"exec_clean"` Exec_clean int `json:"exec_clean"`
Exec_created string `json:"exec_created"` Exec_created string `json:"exec_created"`
Exec_fib string `json:"exec_fib"` Exec_fib string `json:"exec_fib"`
Exec_jail_user string `json:"exec_jail_user"` Exec_jail_user string `json:"exec_jail_user"`
Exec_poststart string `json:"exec_poststart"` Exec_poststart string `json:"exec_poststart"`
Exec_poststop string `json:"exec_poststop"` Exec_poststop string `json:"exec_poststop"`
Exec_prestart string `json:"exec_prestart"` Exec_prestart string `json:"exec_prestart"`
Exec_prestop string `json:"exec_prestop"` Exec_prestop string `json:"exec_prestop"`
Exec_start string `json:"exec_start"` Exec_start string `json:"exec_start"`
Exec_stop string `json:"exec_stop"` Exec_stop string `json:"exec_stop"`
Exec_system_jail_user string `json:"exec_system_jail_user"` Exec_system_jail_user string `json:"exec_system_jail_user"`
Exec_system_user string `json:"exec_system_user"` Exec_system_user string `json:"exec_system_user"`
Exec_timeout string `json:"exec_timeout"` Exec_timeout string `json:"exec_timeout"`
Host_domainname string `json:"host_domainname"` Host_domainname string `json:"host_domainname"`
Host_hostname string `json:"host_hostname"` Host_hostname string `json:"host_hostname"`
Host_hostuuid string `json:"host_hostuuid"` Host_hostuuid string `json:"host_hostuuid"`
Host_time int `json:"host_time"` Host_time int `json:"host_time"`
Hostid string `json:"hostid"` Hostid string `json:"hostid"`
Hostid_strict_check int `json:"hostid_strict_check"` Hostid_strict_check int `json:"hostid_strict_check"`
Interfaces string `json:"interfaces"` Interfaces string `json:"interfaces"`
Ip4 string `json:"ip4"` Ip4 string `json:"ip4"`
Ip4_addr string `json:"ip4_addr"` Ip4_addr string `json:"ip4_addr"`
Ip4_saddrsel string `json:"ip4_saddrsel"` Ip4_saddrsel string `json:"ip4_saddrsel"`
Ip6 string `json:"ip6"` Ip6 string `json:"ip6"`
Ip6_addr string `json:"ip6_addr"` Ip6_addr string `json:"ip6_addr"`
Ip6_saddrsel string `json:"ip4_saddrsel"` Ip6_saddrsel string `json:"ip4_saddrsel"`
Ip_hostname int `json:"ip_hostname"` Ip_hostname int `json:"ip_hostname"`
Jail_zfs int `json:"jail_zfs"` Jail_zfs int `json:"jail_zfs"`
Jail_zfs_dataset string `json:"jail_zfs_dataset"` Jail_zfs_dataset string `json:"jail_zfs_dataset"`
Jail_zfs_mountpoint string `json:"jail_zfs_mountpoint"` Jail_zfs_mountpoint string `json:"jail_zfs_mountpoint"`
Last_started string `json:"last_started"` Last_started string `json:"last_started"`
Localhost_ip string `json:"localhost_ip"` Localhost_ip string `json:"localhost_ip"`
Login_flags string `json:"login_flags"` Login_flags string `json:"login_flags"`
Mac_prefix string `json:"mac_prefix"` Mac_prefix string `json:"mac_prefix"`
Maxproc string `json:"maxproc"` Maxproc string `json:"maxproc"`
Memorylocked string `json:"memorylocked"` Memorylocked string `json:"memorylocked"`
Memoryuse string `json:"memoryuse"` Memoryuse string `json:"memoryuse"`
Min_dyn_devfs_ruleset string `json:"min_dyn_devfs_ruleset"` Min_dyn_devfs_ruleset string `json:"min_dyn_devfs_ruleset"`
Mount_devfs int `json:"mount_devfs"` Mount_devfs int `json:"mount_devfs"`
Mount_fdescfs int `json:"mount_fdescfs"` Mount_fdescfs int `json:"mount_fdescfs"`
Mount_linprocfs int `json:"mount_linprocfs"` Mount_linprocfs int `json:"mount_linprocfs"`
Mount_procfs int `json:"mount_procfs"` Mount_procfs int `json:"mount_procfs"`
Mountpoint string `json:"mountpoint"` Mountpoint string `json:"mountpoint"`
Msgqqueued string `json:"msgqqueued"` Msgqqueued string `json:"msgqqueued"`
Msgqsize string `json:"msgqsize"` Msgqsize string `json:"msgqsize"`
Nat int `json:"nat"` Nat int `json:"nat"`
Nat_backend string `json:"nat_backend"` Nat_backend string `json:"nat_backend"`
Nat_forwards string `json:"nat_forwards"` Nat_forwards string `json:"nat_forwards"`
Nat_interface string `json:"nat_interface"` Nat_interface string `json:"nat_interface"`
Nat_prefix string `json:"nat_prefix"` Nat_prefix string `json:"nat_prefix"`
Nmsgq string `json:"nmsgq"` Nmsgq string `json:"nmsgq"`
Notes string `json:"notes"` Notes string `json:"notes"`
Nsem string `json:"nsem"` Nsem string `json:"nsem"`
Nsemop string `json:"nsemop"` Nsemop string `json:"nsemop"`
Nshm string `json:"nshm"` Nshm string `json:"nshm"`
Nthr string `json:"nthr"` Nthr string `json:"nthr"`
Openfiles string `json:"openfiles"` Openfiles string `json:"openfiles"`
Origin string `json:"origin"` Origin string `json:"origin"`
Owner string `json:"owner"` Owner string `json:"owner"`
Pcpu string `json:"pcpu"` Pcpu string `json:"pcpu"`
Plugin_name string `json:"plugin_name"` Plugin_name string `json:"plugin_name"`
Plugin_repository string `json:"plugin_repository"` Plugin_repository string `json:"plugin_repository"`
Priority string `json:"priority"` Priority string `json:"priority"`
Pseudoterminals string `json:"pseudoterminals"` Pseudoterminals string `json:"pseudoterminals"`
Quota string `json:"quota"` Quota string `json:"quota"`
Readbps string `json:"readbps"` Readbps string `json:"readbps"`
Readiops string `json:"readiops"` Readiops string `json:"readiops"`
Release string `json:"release"` Release string `json:"release"`
Reservation string `json:"reservation"` Reservation string `json:"reservation"`
Resolver string `json:"resolver"` Resolver string `json:"resolver"`
Rlimits string `json:"rlimits"` Rlimits string `json:"rlimits"`
Rtsold int `json:"rtsold"` Rtsold int `json:"rtsold"`
Securelevel string `json:"securelevel"` Securelevel string `json:"securelevel"`
Shmsize string `json:"shmsize"` Shmsize string `json:"shmsize"`
Stacksize string `json:"stacksize"` Stacksize string `json:"stacksize"`
Stop_timeout string `json:"stop_timeout"` Stop_timeout string `json:"stop_timeout"`
Swapuse string `json:"swapuse"` Swapuse string `json:"swapuse"`
Sync_state string `json:"sync_state"` Sync_state string `json:"sync_state"`
Sync_target string `json:"sync_target"` Sync_target string `json:"sync_target"`
Sync_tgt_zpool string `json:"sync_tgt_zpool"` Sync_tgt_zpool string `json:"sync_tgt_zpool"`
Sysvmsg string `json:"sysvmsg"` Sysvmsg string `json:"sysvmsg"`
Sysvsem string `json:"sysvsem"` Sysvsem string `json:"sysvsem"`
Sysvshm string `json:"sysvshm"` Sysvshm string `json:"sysvshm"`
Template int `json:"template"` Template int `json:"template"`
// Go don't like a variable named "type" (And i dont care about finding a cleaner way) // Go don't like a variable named "type" (And i dont care about finding a cleaner way)
Jailtype string `json:"type"` Jailtype string `json:"type"`
Used string `json:"used"` Used string `json:"used"`
Vmemoryuse string `json:"vmemoryuse"` Vmemoryuse string `json:"vmemoryuse"`
Vnet int `json:"vnet"` Vnet int `json:"vnet"`
Vnet0_mac string `json:"vnet0_mac"` Vnet0_mac string `json:"vnet0_mac"`
Vnet1_mac string `json:"vnet1_mac"` Vnet1_mac string `json:"vnet1_mac"`
Vnet2_mac string `json:"vnet2_mac"` Vnet2_mac string `json:"vnet2_mac"`
Vnet3_mac string `json:"vnet3_mac"` Vnet3_mac string `json:"vnet3_mac"`
Vnet_default_interface string `json:"vnet_default_interface"` Vnet_default_interface string `json:"vnet_default_interface"`
Vnet_interfaces string `json:"vnet_interfaces"` Vnet_interfaces string `json:"vnet_interfaces"`
Wallclock string `json:"wallclock"` Wallclock string `json:"wallclock"`
Writebps string `json:"writebps"` Writebps string `json:"writebps"`
Writeiops string `json:"writeiops"` Writeiops string `json:"writeiops"`
} }
// Represent an fstab line // Represent an fstab line
type Mount struct { type Mount struct {
Device string Device string
Mountpoint string Mountpoint string
Type string Type string
Options []string Options []string
Fs_Freq int Fs_Freq int
Fs_Passno int Fs_Passno int
} }
type Snapshot struct { type Snapshot struct {
// snapshot name is stored after '@' in dataset name // snapshot name is stored after '@' in dataset name
Name string Name string
Dsname string Dsname string
Jailname string Jailname string
Mountpoint string Mountpoint string
Used string Used string
Referenced string Referenced string
Creation time.Time Creation time.Time
} }
// 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: -+.
// //
type JailSort struct { type JailSort struct {
NameInc jailLessFunc NameInc jailLessFunc
NameDec jailLessFunc NameDec jailLessFunc
InternalNameInc jailLessFunc InternalNameInc jailLessFunc
InternalNameDec jailLessFunc InternalNameDec jailLessFunc
JIDInc jailLessFunc JIDInc jailLessFunc
JIDDec jailLessFunc JIDDec jailLessFunc
RootPathInc jailLessFunc RootPathInc jailLessFunc
RootPathDec jailLessFunc RootPathDec jailLessFunc
ConfigPathInc jailLessFunc ConfigPathInc jailLessFunc
ConfigPathDec jailLessFunc ConfigPathDec jailLessFunc
RunningInc jailLessFunc RunningInc jailLessFunc
RunningDec jailLessFunc RunningDec jailLessFunc
ZpoolInc jailLessFunc ZpoolInc jailLessFunc
ZpoolDec jailLessFunc ZpoolDec jailLessFunc
Config JailConfigSort Config JailConfigSort
} }
type JailConfigSort struct { type JailConfigSort struct {
Config_versionInc jailLessFunc Config_versionInc jailLessFunc
Config_versionDec jailLessFunc Config_versionDec jailLessFunc
Allow_chflagsInc jailLessFunc Allow_chflagsInc jailLessFunc
Allow_chflagsDec jailLessFunc Allow_chflagsDec jailLessFunc
Allow_mlockInc jailLessFunc Allow_mlockInc jailLessFunc
Allow_mlockDec jailLessFunc Allow_mlockDec jailLessFunc
Allow_mountInc jailLessFunc Allow_mountInc jailLessFunc
Allow_mountDec jailLessFunc Allow_mountDec jailLessFunc
Allow_mount_devfsInc jailLessFunc Allow_mount_devfsInc jailLessFunc
Allow_mount_devfsDec jailLessFunc Allow_mount_devfsDec jailLessFunc
Allow_mount_fusefsInc jailLessFunc Allow_mount_fusefsInc jailLessFunc
Allow_mount_fusefsDec jailLessFunc Allow_mount_fusefsDec jailLessFunc
Allow_mount_nullfsInc jailLessFunc Allow_mount_nullfsInc jailLessFunc
Allow_mount_nullfsDec jailLessFunc Allow_mount_nullfsDec jailLessFunc
Allow_mount_procfsInc jailLessFunc Allow_mount_procfsInc jailLessFunc
Allow_mount_procfsDec jailLessFunc Allow_mount_procfsDec jailLessFunc
Allow_mount_tmpfsInc jailLessFunc Allow_mount_tmpfsInc jailLessFunc
Allow_mount_tmpfsDec jailLessFunc Allow_mount_tmpfsDec jailLessFunc
Allow_mount_zfsInc jailLessFunc Allow_mount_zfsInc jailLessFunc
Allow_mount_zfsDec jailLessFunc Allow_mount_zfsDec jailLessFunc
Allow_quotasInc jailLessFunc Allow_quotasInc jailLessFunc
Allow_quotasDec jailLessFunc Allow_quotasDec jailLessFunc
Allow_raw_socketsInc jailLessFunc Allow_raw_socketsInc jailLessFunc
Allow_raw_socketsDec jailLessFunc Allow_raw_socketsDec jailLessFunc
Allow_set_hostnameInc jailLessFunc Allow_set_hostnameInc jailLessFunc
Allow_set_hostnameDec jailLessFunc Allow_set_hostnameDec jailLessFunc
Allow_socket_afInc jailLessFunc Allow_socket_afInc jailLessFunc
Allow_socket_afDec jailLessFunc Allow_socket_afDec jailLessFunc
Allow_sysvipcInc jailLessFunc Allow_sysvipcInc jailLessFunc
Allow_sysvipcDec jailLessFunc Allow_sysvipcDec jailLessFunc
Allow_tunInc jailLessFunc Allow_tunInc jailLessFunc
Allow_tunDec jailLessFunc Allow_tunDec jailLessFunc
Allow_vmmInc jailLessFunc Allow_vmmInc jailLessFunc
Allow_vmmDec jailLessFunc Allow_vmmDec jailLessFunc
Assign_localhostInc jailLessFunc Assign_localhostInc jailLessFunc
Assign_localhostDec jailLessFunc Assign_localhostDec jailLessFunc
AvailableInc jailLessFunc AvailableInc jailLessFunc
AvailableDec jailLessFunc AvailableDec jailLessFunc
BasejailInc jailLessFunc BasejailInc jailLessFunc
BasejailDec jailLessFunc BasejailDec jailLessFunc
BootInc jailLessFunc BootInc jailLessFunc
BootDec jailLessFunc BootDec jailLessFunc
BpfInc jailLessFunc BpfInc jailLessFunc
BpfDec jailLessFunc BpfDec jailLessFunc
Children_maxInc jailLessFunc Children_maxInc jailLessFunc
Children_maxDec jailLessFunc Children_maxDec jailLessFunc
Cloned_releaseInc jailLessFunc Cloned_releaseInc jailLessFunc
Cloned_releaseDec jailLessFunc Cloned_releaseDec jailLessFunc
CommentInc jailLessFunc CommentInc jailLessFunc
CommentDec jailLessFunc CommentDec jailLessFunc
CompressionInc jailLessFunc CompressionInc jailLessFunc
CompressionDec jailLessFunc CompressionDec jailLessFunc
CompressratioInc jailLessFunc CompressratioInc jailLessFunc
CompressratioDec jailLessFunc CompressratioDec jailLessFunc
CoredumpsizeInc jailLessFunc CoredumpsizeInc jailLessFunc
CoredumpsizeDec jailLessFunc CoredumpsizeDec jailLessFunc
CountInc jailLessFunc CountInc jailLessFunc
CountDec jailLessFunc CountDec jailLessFunc
CpusetInc jailLessFunc CpusetInc jailLessFunc
CpusetDec jailLessFunc CpusetDec jailLessFunc
CputimeInc jailLessFunc CputimeInc jailLessFunc
CputimeDec jailLessFunc CputimeDec jailLessFunc
DatasizeInc jailLessFunc DatasizeInc jailLessFunc
DatasizeDec jailLessFunc DatasizeDec jailLessFunc
DedupInc jailLessFunc DedupInc jailLessFunc
DedupDec jailLessFunc DedupDec jailLessFunc
DefaultrouterInc jailLessFunc DefaultrouterInc jailLessFunc
DefaultrouterDec jailLessFunc DefaultrouterDec jailLessFunc
Defaultrouter6Inc jailLessFunc Defaultrouter6Inc jailLessFunc
Defaultrouter6Dec jailLessFunc Defaultrouter6Dec jailLessFunc
DependsInc jailLessFunc DependsInc jailLessFunc
DependsDec jailLessFunc DependsDec jailLessFunc
Devfs_rulesetInc jailLessFunc Devfs_rulesetInc jailLessFunc
Devfs_rulesetDec jailLessFunc Devfs_rulesetDec jailLessFunc
DhcpInc jailLessFunc DhcpInc jailLessFunc
DhcpDec jailLessFunc DhcpDec jailLessFunc
Enforce_statfsInc jailLessFunc Enforce_statfsInc jailLessFunc
Enforce_statfsDec jailLessFunc Enforce_statfsDec jailLessFunc
Exec_cleanInc jailLessFunc Exec_cleanInc jailLessFunc
Exec_cleanDec jailLessFunc Exec_cleanDec jailLessFunc
Exec_createdInc jailLessFunc Exec_createdInc jailLessFunc
Exec_createdDec jailLessFunc Exec_createdDec jailLessFunc
Exec_fibInc jailLessFunc Exec_fibInc jailLessFunc
Exec_fibDec jailLessFunc Exec_fibDec jailLessFunc
Exec_jail_userInc jailLessFunc Exec_jail_userInc jailLessFunc
Exec_jail_userDec jailLessFunc Exec_jail_userDec jailLessFunc
Exec_poststartInc jailLessFunc Exec_poststartInc jailLessFunc
Exec_poststartDec jailLessFunc Exec_poststartDec jailLessFunc
Exec_poststopInc jailLessFunc Exec_poststopInc jailLessFunc
Exec_poststopDec jailLessFunc Exec_poststopDec jailLessFunc
Exec_prestartInc jailLessFunc Exec_prestartInc jailLessFunc
Exec_prestartDec jailLessFunc Exec_prestartDec jailLessFunc
Exec_prestopInc jailLessFunc Exec_prestopInc jailLessFunc
Exec_prestopDec jailLessFunc Exec_prestopDec jailLessFunc
Exec_startInc jailLessFunc Exec_startInc jailLessFunc
Exec_startDec jailLessFunc Exec_startDec jailLessFunc
Exec_stopInc jailLessFunc Exec_stopInc jailLessFunc
Exec_stopDec jailLessFunc Exec_stopDec jailLessFunc
Exec_system_jail_userInc jailLessFunc Exec_system_jail_userInc jailLessFunc
Exec_system_jail_userDec jailLessFunc Exec_system_jail_userDec jailLessFunc
Exec_system_userInc jailLessFunc Exec_system_userInc jailLessFunc
Exec_system_userDec jailLessFunc Exec_system_userDec jailLessFunc
Exec_timeoutInc jailLessFunc Exec_timeoutInc jailLessFunc
Exec_timeoutDec jailLessFunc Exec_timeoutDec jailLessFunc
Host_domainnameInc jailLessFunc Host_domainnameInc jailLessFunc
Host_domainnameDec jailLessFunc Host_domainnameDec jailLessFunc
Host_hostnameInc jailLessFunc Host_hostnameInc jailLessFunc
Host_hostnameDec jailLessFunc Host_hostnameDec jailLessFunc
Host_hostuuidInc jailLessFunc Host_hostuuidInc jailLessFunc
Host_hostuuidDec jailLessFunc Host_hostuuidDec jailLessFunc
Host_timeInc jailLessFunc Host_timeInc jailLessFunc
Host_timeDec jailLessFunc Host_timeDec jailLessFunc
HostidInc jailLessFunc HostidInc jailLessFunc
HostidDec jailLessFunc HostidDec jailLessFunc
Hostid_strict_checkInc jailLessFunc Hostid_strict_checkInc jailLessFunc
Hostid_strict_checkDec jailLessFunc Hostid_strict_checkDec jailLessFunc
InterfacesInc jailLessFunc InterfacesInc jailLessFunc
InterfacesDec jailLessFunc InterfacesDec jailLessFunc
Ip4Inc jailLessFunc Ip4Inc jailLessFunc
Ip4Dec jailLessFunc Ip4Dec jailLessFunc
Ip4_addrInc jailLessFunc Ip4_addrInc jailLessFunc
Ip4_addrDec jailLessFunc Ip4_addrDec jailLessFunc
Ip4_saddrselInc jailLessFunc Ip4_saddrselInc jailLessFunc
Ip4_saddrselDec jailLessFunc Ip4_saddrselDec jailLessFunc
Ip6Inc jailLessFunc Ip6Inc jailLessFunc
Ip6Dec jailLessFunc Ip6Dec jailLessFunc
Ip6_addrInc jailLessFunc Ip6_addrInc jailLessFunc
Ip6_addrDec jailLessFunc Ip6_addrDec jailLessFunc
Ip6_saddrselInc jailLessFunc Ip6_saddrselInc jailLessFunc
Ip6_saddrselDec jailLessFunc Ip6_saddrselDec jailLessFunc
Ip_hostnameInc jailLessFunc Ip_hostnameInc jailLessFunc
Ip_hostnameDec jailLessFunc Ip_hostnameDec jailLessFunc
Jail_zfsInc jailLessFunc Jail_zfsInc jailLessFunc
Jail_zfsDec jailLessFunc Jail_zfsDec jailLessFunc
Jail_zfs_datasetInc jailLessFunc Jail_zfs_datasetInc jailLessFunc
Jail_zfs_datasetDec jailLessFunc Jail_zfs_datasetDec jailLessFunc
Jail_zfs_mountpointInc jailLessFunc Jail_zfs_mountpointInc jailLessFunc
Jail_zfs_mountpointDec jailLessFunc Jail_zfs_mountpointDec jailLessFunc
Last_startedInc jailLessFunc Last_startedInc jailLessFunc
Last_startedDec jailLessFunc Last_startedDec jailLessFunc
Localhost_ipInc jailLessFunc Localhost_ipInc jailLessFunc
Localhost_ipDec jailLessFunc Localhost_ipDec jailLessFunc
Login_flagsInc jailLessFunc Login_flagsInc jailLessFunc
Login_flagsDec jailLessFunc Login_flagsDec jailLessFunc
Mac_prefixInc jailLessFunc Mac_prefixInc jailLessFunc
Mac_prefixDec jailLessFunc Mac_prefixDec jailLessFunc
MaxprocInc jailLessFunc MaxprocInc jailLessFunc
MaxprocDec jailLessFunc MaxprocDec jailLessFunc
MemorylockedInc jailLessFunc MemorylockedInc jailLessFunc
MemorylockedDec jailLessFunc MemorylockedDec jailLessFunc
MemoryuseInc jailLessFunc MemoryuseInc jailLessFunc
MemoryuseDec jailLessFunc MemoryuseDec jailLessFunc
Min_dyn_devfs_rulesetInc jailLessFunc Min_dyn_devfs_rulesetInc jailLessFunc
Min_dyn_devfs_rulesetDec jailLessFunc Min_dyn_devfs_rulesetDec jailLessFunc
Mount_devfsInc jailLessFunc Mount_devfsInc jailLessFunc
Mount_devfsDec jailLessFunc Mount_devfsDec jailLessFunc
Mount_fdescfsInc jailLessFunc Mount_fdescfsInc jailLessFunc
Mount_fdescfsDec jailLessFunc Mount_fdescfsDec jailLessFunc
Mount_linprocfsInc jailLessFunc Mount_linprocfsInc jailLessFunc
Mount_linprocfsDec jailLessFunc Mount_linprocfsDec jailLessFunc
Mount_procfsInc jailLessFunc Mount_procfsInc jailLessFunc
Mount_procfsDec jailLessFunc Mount_procfsDec jailLessFunc
MountpointInc jailLessFunc MountpointInc jailLessFunc
MountpointDec jailLessFunc MountpointDec jailLessFunc
MsgqqueuedInc jailLessFunc MsgqqueuedInc jailLessFunc
MsgqqueuedDec jailLessFunc MsgqqueuedDec jailLessFunc
MsgqsizeInc jailLessFunc MsgqsizeInc jailLessFunc
MsgqsizeDec jailLessFunc MsgqsizeDec jailLessFunc
NatInc jailLessFunc NatInc jailLessFunc
NatDec jailLessFunc NatDec jailLessFunc
Nat_backendInc jailLessFunc Nat_backendInc jailLessFunc
Nat_backendDec jailLessFunc Nat_backendDec jailLessFunc
Nat_forwardsInc jailLessFunc Nat_forwardsInc jailLessFunc
Nat_forwardsDec jailLessFunc Nat_forwardsDec jailLessFunc
Nat_interfaceInc jailLessFunc Nat_interfaceInc jailLessFunc
Nat_interfaceDec jailLessFunc Nat_interfaceDec jailLessFunc
Nat_prefixInc jailLessFunc Nat_prefixInc jailLessFunc
Nat_prefixDec jailLessFunc Nat_prefixDec jailLessFunc
NmsgqInc jailLessFunc NmsgqInc jailLessFunc
NmsgqDec jailLessFunc NmsgqDec jailLessFunc
NotesInc jailLessFunc NotesInc jailLessFunc
NotesDec jailLessFunc NotesDec jailLessFunc
NsemInc jailLessFunc NsemInc jailLessFunc
NsemDec jailLessFunc NsemDec jailLessFunc
NsemopInc jailLessFunc NsemopInc jailLessFunc
NsemopDec jailLessFunc NsemopDec jailLessFunc
NshmInc jailLessFunc NshmInc jailLessFunc
NshmDec jailLessFunc NshmDec jailLessFunc
NthrInc jailLessFunc NthrInc jailLessFunc
NthrDec jailLessFunc NthrDec jailLessFunc
OpenfilesInc jailLessFunc OpenfilesInc jailLessFunc
OpenfilesDec jailLessFunc OpenfilesDec jailLessFunc
OriginInc jailLessFunc OriginInc jailLessFunc
OriginDec jailLessFunc OriginDec jailLessFunc
OwnerInc jailLessFunc OwnerInc jailLessFunc
OwnerDec jailLessFunc OwnerDec jailLessFunc
PcpuInc jailLessFunc PcpuInc jailLessFunc
PcpuDec jailLessFunc PcpuDec jailLessFunc
Plugin_nameInc jailLessFunc Plugin_nameInc jailLessFunc
Plugin_nameDec jailLessFunc Plugin_nameDec jailLessFunc
Plugin_repositoryInc jailLessFunc Plugin_repositoryInc jailLessFunc
Plugin_repositoryDec jailLessFunc Plugin_repositoryDec jailLessFunc
PriorityInc jailLessFunc PriorityInc jailLessFunc
PriorityDec jailLessFunc PriorityDec jailLessFunc
PseudoterminalsInc jailLessFunc PseudoterminalsInc jailLessFunc
PseudoterminalsDec jailLessFunc PseudoterminalsDec jailLessFunc
QuotaInc jailLessFunc QuotaInc jailLessFunc
QuotaDec jailLessFunc QuotaDec jailLessFunc
ReadbpsInc jailLessFunc ReadbpsInc jailLessFunc
ReadbpsDec jailLessFunc ReadbpsDec jailLessFunc
ReadiopsInc jailLessFunc ReadiopsInc jailLessFunc
ReadiopsDec jailLessFunc ReadiopsDec jailLessFunc
ReleaseInc jailLessFunc ReleaseInc jailLessFunc
ReleaseDec jailLessFunc ReleaseDec jailLessFunc
ReservationInc jailLessFunc ReservationInc jailLessFunc
ReservationDec jailLessFunc ReservationDec jailLessFunc
ResolverInc jailLessFunc ResolverInc jailLessFunc
ResolverDec jailLessFunc ResolverDec jailLessFunc
RlimitsInc jailLessFunc RlimitsInc jailLessFunc
RlimitsDec jailLessFunc RlimitsDec jailLessFunc
RtsoldInc jailLessFunc RtsoldInc jailLessFunc
RtsoldDec jailLessFunc RtsoldDec jailLessFunc
SecurelevelInc jailLessFunc SecurelevelInc jailLessFunc
SecurelevelDec jailLessFunc SecurelevelDec jailLessFunc
ShmsizeInc jailLessFunc ShmsizeInc jailLessFunc
ShmsizeDec jailLessFunc ShmsizeDec jailLessFunc
StacksizeInc jailLessFunc StacksizeInc jailLessFunc
StacksizeDec jailLessFunc StacksizeDec jailLessFunc
Stop_timeoutInc jailLessFunc Stop_timeoutInc jailLessFunc
Stop_timeoutDec jailLessFunc Stop_timeoutDec jailLessFunc
SwapuseInc jailLessFunc SwapuseInc jailLessFunc
SwapuseDec jailLessFunc SwapuseDec jailLessFunc
Sync_stateInc jailLessFunc Sync_stateInc jailLessFunc
Sync_stateDec jailLessFunc Sync_stateDec jailLessFunc
Sync_targetInc jailLessFunc Sync_targetInc jailLessFunc
Sync_targetDec jailLessFunc Sync_targetDec jailLessFunc
Sync_tgt_zpoolInc jailLessFunc Sync_tgt_zpoolInc jailLessFunc
Sync_tgt_zpoolDec jailLessFunc Sync_tgt_zpoolDec jailLessFunc
SysvmsgInc jailLessFunc SysvmsgInc jailLessFunc
SysvmsgDec jailLessFunc SysvmsgDec jailLessFunc
SysvsemInc jailLessFunc SysvsemInc jailLessFunc
SysvsemDec jailLessFunc SysvsemDec jailLessFunc
SysvshmInc jailLessFunc SysvshmInc jailLessFunc
SysvshmDec jailLessFunc SysvshmDec jailLessFunc
TemplateInc jailLessFunc TemplateInc jailLessFunc
TemplateDec jailLessFunc TemplateDec jailLessFunc
JailtypeInc jailLessFunc JailtypeInc jailLessFunc
JailtypeDec jailLessFunc JailtypeDec jailLessFunc
UsedInc jailLessFunc UsedInc jailLessFunc
UsedDec jailLessFunc UsedDec jailLessFunc
VmemoryuseInc jailLessFunc VmemoryuseInc jailLessFunc
VmemoryuseDec jailLessFunc VmemoryuseDec jailLessFunc
VnetInc jailLessFunc VnetInc jailLessFunc
VnetDec jailLessFunc VnetDec jailLessFunc
Vnet0_macInc jailLessFunc Vnet0_macInc jailLessFunc
Vnet0_macDec jailLessFunc Vnet0_macDec jailLessFunc
Vnet1_macInc jailLessFunc Vnet1_macInc jailLessFunc
Vnet1_macDec jailLessFunc Vnet1_macDec jailLessFunc
Vnet2_macInc jailLessFunc Vnet2_macInc jailLessFunc
Vnet2_macDec jailLessFunc Vnet2_macDec jailLessFunc
Vnet3_macInc jailLessFunc Vnet3_macInc jailLessFunc
Vnet3_macDec jailLessFunc Vnet3_macDec jailLessFunc
Vnet_default_interfaceInc jailLessFunc Vnet_default_interfaceInc jailLessFunc
Vnet_default_interfaceDec jailLessFunc Vnet_default_interfaceDec jailLessFunc
Vnet_interfacesInc jailLessFunc Vnet_interfacesInc jailLessFunc
Vnet_interfacesDec jailLessFunc Vnet_interfacesDec jailLessFunc
WallclockInc jailLessFunc WallclockInc jailLessFunc
WallclockDec jailLessFunc WallclockDec jailLessFunc
WritebpsInc jailLessFunc WritebpsInc jailLessFunc
WritebpsDec jailLessFunc WritebpsDec jailLessFunc
WriteiopsInc jailLessFunc WriteiopsInc jailLessFunc
WriteiopsDec jailLessFunc WriteiopsDec jailLessFunc
} }
type SnapshotSort struct { type SnapshotSort struct {
NameInc snapshotLessFunc NameInc snapshotLessFunc
NameDec snapshotLessFunc NameDec snapshotLessFunc
DsnameInc snapshotLessFunc DsnameInc snapshotLessFunc
DsnameDec snapshotLessFunc DsnameDec snapshotLessFunc
JailnameInc snapshotLessFunc JailnameInc snapshotLessFunc
JailnameDec snapshotLessFunc JailnameDec snapshotLessFunc
MountpointInc snapshotLessFunc MountpointInc snapshotLessFunc
MountpointDec snapshotLessFunc MountpointDec snapshotLessFunc
UsedInc snapshotLessFunc UsedInc snapshotLessFunc
UsedDec snapshotLessFunc UsedDec snapshotLessFunc
ReferencedInc snapshotLessFunc ReferencedInc snapshotLessFunc
ReferencedDec snapshotLessFunc ReferencedDec snapshotLessFunc
CreationInc snapshotLessFunc CreationInc snapshotLessFunc
CreationDec snapshotLessFunc CreationDec snapshotLessFunc
} }
type JailHost struct { type JailHost struct {
hostname string hostname string
hostid string hostid string
default_gateway4 string default_gateway4 string
default_gateway6 string default_gateway6 string
default_interface string default_interface string
} }

File diff suppressed because it is too large Load Diff

2
go.mod
View File

@ -3,6 +3,8 @@ module gocage
go 1.17 go 1.17
require ( require (
github.com/c-robinson/iplib v1.0.3
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.2.1 github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.9.0 github.com/spf13/viper v1.9.0
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420

View File

@ -1,10 +1,9 @@
package main package main
import ( import (
"gocage/cmd" "gocage/cmd"
) )
func main () { func main() {
cmd.Execute() cmd.Execute()
} }