add init command files
This commit is contained in:
		
							
								
								
									
										153
									
								
								cmd/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								cmd/init.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
			
		||||
package cmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/viper"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
/********************************************************************************
 | 
			
		||||
 * Initialize datastore(s) /iocage, /iocage/jails
 | 
			
		||||
 * Put defaults.json,
 | 
			
		||||
 * Update it with hostid, interfaces, and maybe other necessary fields
 | 
			
		||||
 * Initialize bridge
 | 
			
		||||
 *******************************************************************************/
 | 
			
		||||
func InitGoCage(args []string) {
 | 
			
		||||
	// Create datastores
 | 
			
		||||
	for _, dstore := range viper.GetStringSlice("datastore") {
 | 
			
		||||
		log.Debugf("Ranging over %v\n", dstore)
 | 
			
		||||
		dset, err := zfsGetDatasetByMountpoint(dstore)
 | 
			
		||||
		if err != nil && strings.HasSuffix(err.Error(), "No such file or directory\"") {
 | 
			
		||||
			if len(gZPool) == 0 {
 | 
			
		||||
				log.Errorf("Datastore mountpoint \"%s\" does not exist. Specify a pool if you want to create it.", dstore)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			// Create dataset /iocage
 | 
			
		||||
			rootDSName := fmt.Sprintf("%s%s", gZPool, dstore)
 | 
			
		||||
			log.Debugf("Creating dataset %s mounted on %s\n", rootDSName, dstore)
 | 
			
		||||
			if err = zfsCreateDataset(rootDSName, dstore, ""); err != nil {
 | 
			
		||||
				log.Errorf("Error creating dataset %s: %v\n", rootDSName, err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			// Create /iocage/jail, releases, templates
 | 
			
		||||
			for _, l := range []string{"jails","releases","templates"} {
 | 
			
		||||
				cds := fmt.Sprintf("%s/%s", rootDSName, l)
 | 
			
		||||
				cmp := fmt.Sprintf("%s/%s", dstore, l)
 | 
			
		||||
				log.Debugf("Creating dataset %s mounted on %s\n", cds, cmp)
 | 
			
		||||
				if err = zfsCreateDataset(cds, cmp, ""); err != nil {
 | 
			
		||||
					log.Errorf("Error creating dataset %s: %v\n", cds, err)
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			// Create /iocage/defaults.json
 | 
			
		||||
			exists, err := doFileExist(fmt.Sprintf("%s/defaults.json", dstore))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Errorf("Error checking defaults.json: %v\n", err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			if !exists {
 | 
			
		||||
				if err = createDefaultsJson(dstore, gBridge); err != nil {
 | 
			
		||||
					log.Errorf("%v\n", err)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			log.Errorf("Error checking datastore existence: %v\n", err)
 | 
			
		||||
			return
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Debugf("Datastore dataset exist: %s\n", dset)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Check and create bridge
 | 
			
		||||
	// FIXME: What if bridge name is invalid, as we already wrote it in defaults.json in dstore loop?
 | 
			
		||||
	if len(gBridge) > 0 && len(gInterface) > 0 {
 | 
			
		||||
		if err := initBridge(); err != nil {
 | 
			
		||||
			log.Errorf("%v\n", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createDefaultsJson(rootDirectory string, bridge string) error {
 | 
			
		||||
	hostid, err := os.ReadFile("/etc/hostid")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Unable to read /etc/hostid: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	json := strings.Replace(gDefaultsJson, "TO-BE-REPLACED-WITH-HOSTID", strings.Trim(string(hostid), "\n"), 1)
 | 
			
		||||
	json = strings.Replace(json, "TO-BE-REPLACED-WITH-BRIDGE", bridge, 1)
 | 
			
		||||
	if err := os.WriteFile(fmt.Sprintf("%s/defaults.json", rootDirectory), []byte(json), 0640); err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func createInterface(iface string) error {
 | 
			
		||||
	log.Debugf("creating interface \"%s\"\n", iface)
 | 
			
		||||
	cmd := fmt.Sprintf("/sbin/ifconfig %s create", iface)
 | 
			
		||||
	_, err := executeCommand(cmd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bringUpInterface(iface string) error {
 | 
			
		||||
	log.Debugf("bringing up interface \"%s\"\n", iface)
 | 
			
		||||
	cmd := fmt.Sprintf("/sbin/ifconfig %s up", iface)
 | 
			
		||||
	_, err := executeCommand(cmd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addMemberToBridge(bridge string, iface string) error {
 | 
			
		||||
	log.Debugf("adding member interface \"%s\" to bridge \"%s\"\n", iface, bridge)
 | 
			
		||||
	cmd := fmt.Sprintf("/sbin/ifconfig %s addm %s", bridge, iface)
 | 
			
		||||
	_, err := executeCommand(cmd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initBridge() error {
 | 
			
		||||
	hostInt, err := gJailHost.GetInterfaces()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error listing interfaces: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	if !isStringInArray(hostInt, gInterface) {
 | 
			
		||||
		return fmt.Errorf("Interface not found: %s\n", gInterface)
 | 
			
		||||
	}
 | 
			
		||||
	if !isStringInArray(hostInt, gBridge) {
 | 
			
		||||
		if err := createInterface(gBridge); err != nil {
 | 
			
		||||
			return fmt.Errorf("Error creating bridge: %v\n", err)
 | 
			
		||||
		}
 | 
			
		||||
		if err := bringUpInterface(gBridge); err != nil {
 | 
			
		||||
			return fmt.Errorf("Error bringing up bridge: %v\n", err)
 | 
			
		||||
		}
 | 
			
		||||
		log.Infof("bridge was created, but it won't persist reboot. Configure rc.conf to persist. See https://docs.freebsd.org/en/books/handbook/advanced-networking/#network-bridging\n")
 | 
			
		||||
		log.Infof("It is strongly suggested you move interface %s IP to bridge %s\n", gInterface, gBridge)
 | 
			
		||||
	}
 | 
			
		||||
	// FIXME: Need to check if not already member
 | 
			
		||||
	members, err := getBridgeMembers(gBridge)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error getting bridge members: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	// Return if interface already member of the bridge
 | 
			
		||||
	for _, m := range members {
 | 
			
		||||
		log.Debugf("Bridge member: %s\n", m)
 | 
			
		||||
		if strings.EqualFold(m, gInterface) {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err := addMemberToBridge(gBridge, gInterface); err != nil {
 | 
			
		||||
		return fmt.Errorf("Error adding interface to bridge: %v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user