getJailFromArray filtering by type, add fileCopy, isFirstNetDhcp
This commit is contained in:
parent
45e1c57ce4
commit
6a8b022165
252
cmd/utils.go
252
cmd/utils.go
@ -24,6 +24,141 @@ const (
|
||||
ifconfigipv4re = `inet[[:space:]](` + ipv4re + `)`
|
||||
// Maximum thread qty for start/stop
|
||||
gMaxThreads = 4
|
||||
|
||||
gDefaultsJson = ` {
|
||||
"CONFIG_VERSION": "27",
|
||||
"allow_chflags": 0,
|
||||
"allow_mlock": 0,
|
||||
"allow_mount": 0,
|
||||
"allow_mount_devfs": 0,
|
||||
"allow_mount_fusefs": 0,
|
||||
"allow_mount_nullfs": 0,
|
||||
"allow_mount_procfs": 0,
|
||||
"allow_mount_tmpfs": 0,
|
||||
"allow_mount_zfs": 0,
|
||||
"allow_quotas": 0,
|
||||
"allow_raw_sockets": 0,
|
||||
"allow_set_hostname": 1,
|
||||
"allow_socket_af": 0,
|
||||
"allow_sysvipc": 0,
|
||||
"allow_tun": 0,
|
||||
"allow_vmm": 0,
|
||||
"assign_localhost": 0,
|
||||
"available": "readonly",
|
||||
"basejail": 0,
|
||||
"boot": 0,
|
||||
"bpf": 0,
|
||||
"children_max": "0",
|
||||
"comment": "none",
|
||||
"compression": "lz4",
|
||||
"compressratio": "readonly",
|
||||
"coredumpsize": "off",
|
||||
"count": "1",
|
||||
"cpuset": "off",
|
||||
"cputime": "off",
|
||||
"datasize": "off",
|
||||
"dedup": "off",
|
||||
"defaultrouter": "auto",
|
||||
"defaultrouter6": "auto",
|
||||
"depends": "none",
|
||||
"devfs_ruleset": "4",
|
||||
"dhcp": 0,
|
||||
"enforce_statfs": "2",
|
||||
"exec_clean": 1,
|
||||
"exec_created": "/usr/bin/true",
|
||||
"exec_fib": "0",
|
||||
"exec_jail_user": "root",
|
||||
"exec_poststart": "/usr/bin/true",
|
||||
"exec_poststop": "/usr/bin/true",
|
||||
"exec_prestart": "/usr/bin/true",
|
||||
"exec_prestop": "/usr/bin/true",
|
||||
"exec_start": "/bin/sh /etc/rc",
|
||||
"exec_stop": "/bin/sh /etc/rc.shutdown",
|
||||
"exec_system_jail_user": "0",
|
||||
"exec_system_user": "root",
|
||||
"exec_timeout": "60",
|
||||
"host_domainname": "none",
|
||||
"host_time": 1,
|
||||
"hostid": "36353536-3135-5a43-4a34-313130315a56",
|
||||
"hostid_strict_check": 0,
|
||||
"interfaces": "vnet0:bridge0",
|
||||
"ip4": "new",
|
||||
"ip4_addr": "none",
|
||||
"ip4_saddrsel": 1,
|
||||
"ip6": "new",
|
||||
"ip6_addr": "none",
|
||||
"ip6_saddrsel": 1,
|
||||
"ip_hostname": 0,
|
||||
"jail_zfs": 0,
|
||||
"jail_zfs_mountpoint": "none",
|
||||
"last_started": "none",
|
||||
"localhost_ip": "none",
|
||||
"login_flags": "-f root",
|
||||
"mac_prefix": "2c44fd",
|
||||
"maxproc": "off",
|
||||
"memorylocked": "off",
|
||||
"memoryuse": "off",
|
||||
"min_dyn_devfs_ruleset": "1000",
|
||||
"mount_devfs": 1,
|
||||
"mount_fdescfs": 1,
|
||||
"mount_linprocfs": 0,
|
||||
"mount_procfs": 0,
|
||||
"mountpoint": "readonly",
|
||||
"msgqqueued": "off",
|
||||
"msgqsize": "off",
|
||||
"nat": 0,
|
||||
"nat_backend": "ipfw",
|
||||
"nat_forwards": "none",
|
||||
"nat_interface": "none",
|
||||
"nat_prefix": "172.16",
|
||||
"nmsgq": "off",
|
||||
"notes": "none",
|
||||
"nsem": "off",
|
||||
"nsemop": "off",
|
||||
"nshm": "off",
|
||||
"nthr": "off",
|
||||
"openfiles": "off",
|
||||
"origin": "readonly",
|
||||
"owner": "root",
|
||||
"pcpu": "off",
|
||||
"plugin_name": "none",
|
||||
"plugin_repository": "none",
|
||||
"priority": "99",
|
||||
"pseudoterminals": "off",
|
||||
"quota": "none",
|
||||
"readbps": "off",
|
||||
"readiops": "off",
|
||||
"reservation": "none",
|
||||
"resolver": "/etc/resolv.conf",
|
||||
"rlimits": "off",
|
||||
"rtsold": 0,
|
||||
"securelevel": "2",
|
||||
"shmsize": "off",
|
||||
"stacksize": "off",
|
||||
"stop_timeout": "30",
|
||||
"swapuse": "off",
|
||||
"sync_state": "none",
|
||||
"sync_target": "none",
|
||||
"sync_tgt_zpool": "none",
|
||||
"sysvmsg": "new",
|
||||
"sysvsem": "new",
|
||||
"sysvshm": "new",
|
||||
"template": 0,
|
||||
"type": "jail",
|
||||
"used": "readonly",
|
||||
"vmemoryuse": "off",
|
||||
"vnet": 0,
|
||||
"vnet0_mac": "none",
|
||||
"vnet1_mac": "none",
|
||||
"vnet2_mac": "none",
|
||||
"vnet3_mac": "none",
|
||||
"vnet_default_interface": "auto",
|
||||
"vnet_interfaces": "none",
|
||||
"wallclock": "off",
|
||||
"writebps": "off",
|
||||
"writeiops": "off"
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
/*****************************************************************************
|
||||
@ -218,6 +353,8 @@ func executeCommand(cmdline string) (string, error) {
|
||||
// else
|
||||
word = word + string(c)
|
||||
}
|
||||
|
||||
log.Debugf("executeCommand: %s\n", strings.Join(cmd, " "))
|
||||
|
||||
if len(cmd) > 1 {
|
||||
out, err = exec.Command(cmd[0], cmd[1:]...).CombinedOutput()
|
||||
@ -545,8 +682,11 @@ func zfsSnapshot(dataset string, snapname string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy snapshot to a new dataset
|
||||
// TODO : Intercept death of sending process, then kill receiving
|
||||
func zfsCopy(src string, dest string) error {
|
||||
// First, declare sending process & pipe
|
||||
log.Debugf("Execute: zfs send %s\n", src)
|
||||
cmd_send := exec.Command("zfs", "send", src)
|
||||
stdout_send, err := cmd_send.StdoutPipe()
|
||||
if err != nil {
|
||||
@ -555,6 +695,7 @@ func zfsCopy(src string, dest string) error {
|
||||
}
|
||||
|
||||
// then declare receiving process & pipe
|
||||
log.Debugf("Execute: zfs receive %s\n", dest)
|
||||
cmd_recv := exec.Command("zfs", "receive", dest)
|
||||
stdin_recv, err := cmd_recv.StdinPipe()
|
||||
if err != nil {
|
||||
@ -568,16 +709,19 @@ func zfsCopy(src string, dest string) error {
|
||||
// then start processes and wait for finish
|
||||
if err := cmd_recv.Start(); err != nil {
|
||||
//fmt.Printf("Error: %v\n", err)
|
||||
log.Debugf("zfs receive %s started: %v", dest, err)
|
||||
return errors.New(fmt.Sprintf("Error starting receive process: %v\n", err))
|
||||
}
|
||||
//fmt.Printf("DEBUG: Start \"zfs send %s\"\n", dsconf)
|
||||
if err := cmd_send.Start(); err != nil {
|
||||
//fmt.Printf("Error: %v\n", err)
|
||||
log.Debugf("zfs send %s started: %v", src, err)
|
||||
return errors.New(fmt.Sprintf("Error starting send process: %v\n", err))
|
||||
}
|
||||
|
||||
//fmt.Printf("DEBUG: Wait for zfs send to finish\n")
|
||||
if err := cmd_send.Wait(); err != nil {
|
||||
log.Debugf("zfs send %s stopped with %v", err)
|
||||
//fmt.Printf("Error: zfs send halted with %v\n", err)
|
||||
return errors.New(fmt.Sprintf("send halted with: %v\n", err))
|
||||
}
|
||||
@ -668,6 +812,7 @@ func zfsGetDatasetByMountpoint(mountpoint string) (string, error) {
|
||||
|
||||
// Delete a ZFS Dataset by name
|
||||
func zfsDestroy(dataset string) error {
|
||||
log.Debugf("execute \"zfs destroy -r %s\"\n", dataset)
|
||||
cmd := fmt.Sprintf("zfs destroy -r %s", dataset)
|
||||
out, err := executeCommand(cmd)
|
||||
if err != nil {
|
||||
@ -676,6 +821,30 @@ func zfsDestroy(dataset string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
/* Copy file */
|
||||
func copyFile(src, dst string) error {
|
||||
srcfinfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot find source file: %s", err.Error())
|
||||
}
|
||||
if !srcfinfo.Mode().IsRegular() {
|
||||
return fmt.Errorf("%s is not a regular file", src)
|
||||
}
|
||||
|
||||
srcHandle, err := os.Open(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot open source file: %s", err.Error())
|
||||
}
|
||||
defer srcHandle.Close()
|
||||
dstHandle, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot create destination file: %s", err.Error())
|
||||
}
|
||||
defer dstHandle.Close()
|
||||
_, err = io.Copy(dstHandle, srcHandle)
|
||||
return err
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* rc.conf management
|
||||
@ -818,7 +987,7 @@ func getValueFromRunningConfig(jname string, param string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
for _, line := range strings.Split(string(content), "\n") {
|
||||
if strings.Contains(line, fmt.Sprintf("%s = ", param)) {
|
||||
split := strings.Split(line, "=")
|
||||
@ -833,7 +1002,7 @@ func getValueFromRunningConfig(jname string, param string) (string, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "", fmt.Errorf("Parameter not found: %s", param)
|
||||
}
|
||||
|
||||
@ -852,14 +1021,29 @@ func isStringInArray(strarr []string, searched string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (j Jail) isFirstNetDhcp() bool {
|
||||
for _, n := range strings.Split(j.Config.Ip4_addr, ",") {
|
||||
splitd := strings.Split(n, "|")
|
||||
if len(splitd) > 1 && strings.EqualFold(splitd[1], "dhcp") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Get a specific jail reference, to update properties after a range loop
|
||||
* Name can be short or long form ("myjail" vs "mystore/myjail")
|
||||
* An empty jailtype means "all types"
|
||||
*******************************************************************************/
|
||||
func getJailFromArray(name string, jarray []Jail) (*Jail, error) {
|
||||
func getJailFromArray(name string, jailtypes []string, jarray []Jail) (*Jail, error) {
|
||||
var ds, jail string
|
||||
var jails []Jail
|
||||
|
||||
|
||||
if (len(jailtypes) == 1 && len(jailtypes[0]) == 0) || len(jailtypes) == 0 {
|
||||
jailtypes = []string{"jail", "basetpl"}
|
||||
}
|
||||
|
||||
if strings.Contains(name, "/") {
|
||||
split := strings.Split(name, "/")
|
||||
if len(split) != 2 {
|
||||
@ -872,16 +1056,17 @@ func getJailFromArray(name string, jarray []Jail) (*Jail, error) {
|
||||
}
|
||||
|
||||
for i, j := range jarray {
|
||||
//if jail == j.Name {
|
||||
if strings.HasPrefix(j.Name, jail) {
|
||||
if len(ds) > 0 {
|
||||
if strings.EqualFold(ds, j.Datastore) {
|
||||
return &jarray[i], nil
|
||||
if isStringInArray(jailtypes, j.Config.Jailtype) {
|
||||
if len(ds) > 0 {
|
||||
if strings.EqualFold(ds, j.Datastore) {
|
||||
return &jarray[i], nil
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
jails = append(jails, j)
|
||||
}
|
||||
} else {
|
||||
jails = append(jails, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -913,7 +1098,7 @@ func setJailConfigUpdated(jail *Jail) error {
|
||||
return errors.New(fmt.Sprintf("No config path for jail %s", jail.Name))
|
||||
}
|
||||
|
||||
j, err := getJailFromArray(jail.Name, gJails)
|
||||
j, err := getJailFromArray(jail.Name, []string{""}, gJails)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -987,6 +1172,47 @@ func writeConfigToDisk(j *Jail, changeauto bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func (j Jail) WriteConfigToDisk(changeauto bool) {
|
||||
// we will manipulate properties so get a copy
|
||||
jc := j.Config
|
||||
|
||||
if changeauto == false {
|
||||
// Overwrite "auto" properties
|
||||
ondiskjc, err := getJailConfig(j.ConfigPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// TODO : List all fields, then call getStructFieldValue to compare value with "auto"
|
||||
// If "auto" then keep it that way before writing ondiskjc to disk
|
||||
var properties []string
|
||||
properties = getStructFieldNames(ondiskjc, properties, "")
|
||||
|
||||
for _, p := range properties {
|
||||
v, _, err := getStructFieldValue(ondiskjc, p)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if v.String() == "auto" {
|
||||
err = setStructFieldValue(&jc, p, "auto")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR sanitizing config: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
marshaled, err := json.MarshalIndent(jc, "", " ")
|
||||
if err != nil {
|
||||
fmt.Printf("ERROR marshaling config: %s\n", err.Error())
|
||||
}
|
||||
|
||||
if os.WriteFile(j.ConfigPath, []byte(marshaled), 0644); err != nil {
|
||||
fmt.Printf("Error writing config file %s: %v\n", j.ConfigPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Return the quantity of jails with the name passed as parameter
|
||||
*****************************************************************************/
|
||||
@ -1002,7 +1228,7 @@ func countOfJailsWithThisName(name string) int {
|
||||
|
||||
|
||||
func isNameDistinctive(name string, jails []Jail) bool {
|
||||
_, err := getJailFromArray(name, jails)
|
||||
_, err := getJailFromArray(name, []string{""}, jails)
|
||||
if err != nil {
|
||||
return false
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user