Add creation of basejail (jail based on template, system in readonly, nullfs binded)
This commit is contained in:
parent
56926f7200
commit
a3dd0a7aa2
142
cmd/create.go
142
cmd/create.go
@ -6,6 +6,7 @@ import (
|
|||||||
//"log"
|
//"log"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
"strings"
|
||||||
|
cp "github.com/otiai10/copy"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -46,38 +47,118 @@ func CreateJail(args []string) {
|
|||||||
} else {
|
} else {
|
||||||
ds = &gDatastores[0]
|
ds = &gDatastores[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Create and populate datasets
|
|
||||||
err = zfsCreateDataset(fmt.Sprintf("%s/jails/%s", ds.ZFSDataset, jname), fmt.Sprintf("%s/jails/%s", ds.Mountpoint, jname), "lz4")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = zfsCreateDataset(fmt.Sprintf("%s/jails/%s/root", ds.ZFSDataset, jname), fmt.Sprintf("%s/jails/%s/root", ds.Mountpoint, jname), "lz4")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Get base template if specified
|
// Get base template if specified
|
||||||
if len(gCreateArgs.BaseTemplate) > 0 {
|
if len(gCreateArgs.BaseTemplate) > 0 {
|
||||||
|
/**************************************************************************
|
||||||
|
* Create based jail from a template
|
||||||
|
*/
|
||||||
log.Debugf("Jail will be created from a base template\n")
|
log.Debugf("Jail will be created from a base template\n")
|
||||||
/*bj, err := getJailFromArray(jname, []string{"template"}, gJails)
|
bj, err := getJailFromArray(gCreateArgs.BaseTemplate, []string{"template"}, gJails)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.EqualFold(err.Error(), "Jail not found") {
|
if strings.EqualFold(err.Error(), "Jail not found") {
|
||||||
|
fmt.Printf("Template not found\n")
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("ERROR: %s\n", err.Error())
|
fmt.Printf("ERROR: %s\n", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
fmt.Printf("Jail exist: %s\n", jname)
|
// Create jail datasets
|
||||||
continue
|
dstDset := fmt.Sprintf("%s/jails/%s", ds.ZFSDataset, jname)
|
||||||
}*/
|
fmt.Printf(" > Initialize dataset %s\n", dstDset)
|
||||||
|
err = zfsCreateDataset(dstDset, "", "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR creating dataset %s: %s\n", dstDset, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Create jail root datasets
|
||||||
|
dstRootDset := fmt.Sprintf("%s/jails/%s/root", ds.ZFSDataset, jname)
|
||||||
|
fmt.Printf(" > Initialize dataset %s\n", dstRootDset)
|
||||||
|
err = zfsCreateDataset(dstRootDset, "", "")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR creating dataset %s: %s\n", dstRootDset, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create needed directories with basejail permissions
|
||||||
|
fmt.Printf(" > Create base read-only directories\n")
|
||||||
|
dstRootDir := fmt.Sprintf("%s/jails/%s/root", ds.Mountpoint, jname)
|
||||||
|
for _, d := range append(gBaseDirs, gEmptyDirs...) {
|
||||||
|
srcPerm, err := getPermissions(fmt.Sprintf("%s/%s", bj.RootPath, d))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR getting permissions of %s/%s: %s\n", bj.RootPath, d, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = os.Mkdir(fmt.Sprintf("%s/%s", dstRootDir, d), srcPerm.Mode().Perm())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR creating directory %s/%s: %s\n", dstRootDir, d, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy these from basejail
|
||||||
|
fmt.Printf(" > Create base writable directories\n")
|
||||||
|
for _, d := range gCopyDirs {
|
||||||
|
err := cp.Copy(fmt.Sprintf("%s/%s", bj.RootPath, d), fmt.Sprintf("%s/%s", dstRootDir, d))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR copying %s to %s: %s\n", fmt.Sprintf("%s/%s", bj.RootPath, d),
|
||||||
|
fmt.Sprintf("%s/%s", dstRootDir, d), err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// Copy defaults.json...
|
||||||
|
jailConfPath := fmt.Sprintf("%s/jails/%s/config.json", ds.Mountpoint, jname)
|
||||||
|
err = copyFile(fmt.Sprintf("%s/defaults.json", ds.Mountpoint),
|
||||||
|
jailConfPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR creating config.json: %s\n", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// ... and update it
|
||||||
|
jailConf, err := getJailConfig(jailConfPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("ERROR reading jail config from %s", jailConfPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build jail object from config
|
||||||
|
jailRootPath := fmt.Sprintf("%s/jails/%s/%s", ds.Mountpoint, jname, "root")
|
||||||
|
j := Jail{
|
||||||
|
Name: jailConf.Host_hostuuid,
|
||||||
|
Config: jailConf,
|
||||||
|
ConfigPath: jailConfPath,
|
||||||
|
Datastore: ds.Name,
|
||||||
|
RootPath: jailRootPath,
|
||||||
|
Running: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to store the basejail template. We could :
|
||||||
|
// 1. Use "origin" ?
|
||||||
|
// 2. Add a json item to config ("basejail_template" p.e.), but iocage would delete it once jail is started from iocage
|
||||||
|
// 3. Add a gocage specific config ("config.gocage.json" p.e.)
|
||||||
|
j.Config.Jailtype = "basejail"
|
||||||
|
j.Config.Origin = bj.Name
|
||||||
|
j.Config.Host_hostname = jname
|
||||||
|
j.Config.Host_hostuuid = jname
|
||||||
|
|
||||||
|
j.WriteConfigToDisk(false)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// Create fstab
|
||||||
|
fstabHandle, err := os.Create(fmt.Sprintf("%s/jails/%s/fstab", ds.Mountpoint, jname))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR creating fstab: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fstabHandle.Close()
|
||||||
|
fmt.Printf(" > Jail created!\n")
|
||||||
} else {
|
} else {
|
||||||
// Normal jail with its own freebsd base
|
/**************************************************************************
|
||||||
|
* Create normal jail with its own freebsd base
|
||||||
|
*/
|
||||||
log.Debugf("Creating jail with its own freebsd base\n")
|
log.Debugf("Creating jail with its own freebsd base\n")
|
||||||
|
|
||||||
// First check if we got release on the same datastore
|
// First check if we got release on the same datastore
|
||||||
@ -86,10 +167,9 @@ func CreateJail(args []string) {
|
|||||||
fmt.Printf("ERROR: Release locally not available. Run \"gocage fetch\"\n")
|
fmt.Printf("ERROR: Release locally not available. Run \"gocage fetch\"\n")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
// Create and populate jail filesystem from release
|
||||||
// Create and populate jail filesystem
|
|
||||||
dstDset := fmt.Sprintf("%s/jails/%s", ds.ZFSDataset, jname)
|
dstDset := fmt.Sprintf("%s/jails/%s", ds.ZFSDataset, jname)
|
||||||
fmt.Printf(" > Initialize dataset %s\n", dstDset)
|
fmt.Printf(" > Initialize dataset %s\n", dstDset)
|
||||||
sNow := time.Now().Format("20060102150405")
|
sNow := time.Now().Format("20060102150405")
|
||||||
@ -142,10 +222,7 @@ func CreateJail(args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Jail filesystem successfuly initalized\n")
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
|
||||||
// Copy defaults.json...
|
// Copy defaults.json...
|
||||||
jailConfPath := fmt.Sprintf("%s/jails/%s/config.json", ds.Mountpoint, jname)
|
jailConfPath := fmt.Sprintf("%s/jails/%s/config.json", ds.Mountpoint, jname)
|
||||||
err = copyFile(fmt.Sprintf("%s/defaults.json", ds.Mountpoint),
|
err = copyFile(fmt.Sprintf("%s/defaults.json", ds.Mountpoint),
|
||||||
@ -155,15 +232,13 @@ func CreateJail(args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
|
||||||
// ... and update it
|
// ... and update it
|
||||||
// Get conf from config.json
|
|
||||||
jailConf, err := getJailConfig(jailConfPath)
|
jailConf, err := getJailConfig(jailConfPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("ERROR reading jail config from %s", jailConfPath)
|
log.Println("ERROR reading jail config from %s", jailConfPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Build jail object from config
|
// Build jail object from config
|
||||||
jailRootPath := fmt.Sprintf("%s/jails/%s/%s", ds.Mountpoint, jname, "root")
|
jailRootPath := fmt.Sprintf("%s/jails/%s/%s", ds.Mountpoint, jname, "root")
|
||||||
j := Jail{
|
j := Jail{
|
||||||
Name: jailConf.Host_hostuuid,
|
Name: jailConf.Host_hostuuid,
|
||||||
@ -173,7 +248,7 @@ func CreateJail(args []string) {
|
|||||||
RootPath: jailRootPath,
|
RootPath: jailRootPath,
|
||||||
Running: false,
|
Running: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
j.Config.Release = gCreateArgs.Release
|
j.Config.Release = gCreateArgs.Release
|
||||||
j.Config.Host_hostname = jname
|
j.Config.Host_hostname = jname
|
||||||
j.Config.Host_hostuuid = jname
|
j.Config.Host_hostuuid = jname
|
||||||
@ -181,7 +256,6 @@ func CreateJail(args []string) {
|
|||||||
j.WriteConfigToDisk(false)
|
j.WriteConfigToDisk(false)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
|
||||||
// Create fstab
|
// Create fstab
|
||||||
fstabHandle, err := os.Create(fmt.Sprintf("%s/jails/%s/fstab", ds.Mountpoint, jname))
|
fstabHandle, err := os.Create(fmt.Sprintf("%s/jails/%s/fstab", ds.Mountpoint, jname))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -189,8 +263,8 @@ func CreateJail(args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer fstabHandle.Close()
|
defer fstabHandle.Close()
|
||||||
|
fmt.Printf(" > Jail created!\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : Set JailType
|
// TODO : Set JailType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
cmd/root.go
10
cmd/root.go
@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gVersion = "0.37"
|
gVersion = "0.37a"
|
||||||
|
|
||||||
// TODO : Get from $jail_zpool/defaults.json
|
// TODO : Get from $jail_zpool/defaults.json
|
||||||
MIN_DYN_DEVFS_RULESET = 1000
|
MIN_DYN_DEVFS_RULESET = 1000
|
||||||
@ -65,6 +65,14 @@ var (
|
|||||||
gFetchFrom string
|
gFetchFrom string
|
||||||
gUpgradeRelease string
|
gUpgradeRelease string
|
||||||
|
|
||||||
|
// For a based jail, these are directories binded to basejail
|
||||||
|
gBaseDirs = []string{"bin", "boot", "lib", "libexec", "rescue", "sbin", "usr", "usr/bin",
|
||||||
|
"usr/include", "usr/lib", "usr/lib32", "usr/libdata", "usr/libexec", "usr/sbin", "usr/share"}
|
||||||
|
// These directories are to be created empty
|
||||||
|
gEmptyDirs = []string{"dev", "media", "mnt", "net", "proc"}
|
||||||
|
// Copy these from base template
|
||||||
|
gCopyDirs = []string{"etc", "root", "tmp", "var"}
|
||||||
|
|
||||||
gMdevfs sync.Mutex
|
gMdevfs sync.Mutex
|
||||||
|
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
|
25
cmd/utils.go
25
cmd/utils.go
@ -790,9 +790,20 @@ func doZfsDatasetExist(dataset string) (bool, error) {
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create ZFS dataset. mountpoint can be "none", then the dataset won't be mounted
|
/* Create ZFS dataset
|
||||||
|
* mountpoint can be "none", then the dataset won't be mounted
|
||||||
|
* mountpoint can be "", then it will be inherited
|
||||||
|
* compression can be "", then it wil be inherited
|
||||||
|
*/
|
||||||
func zfsCreateDataset(dataset, mountpoint, compression string) error {
|
func zfsCreateDataset(dataset, mountpoint, compression string) error {
|
||||||
cmd := fmt.Sprintf("zfs create -o mountpoint=%s -o compression=%s %s", mountpoint, compression, dataset)
|
cmd := "zfs create"
|
||||||
|
if len(mountpoint) > 0 {
|
||||||
|
cmd = fmt.Sprintf("%s -o mountpoint=%s", cmd, mountpoint)
|
||||||
|
}
|
||||||
|
if len(compression) > 0 {
|
||||||
|
cmd = fmt.Sprintf("%s -o compression=%s", cmd, compression)
|
||||||
|
}
|
||||||
|
cmd = fmt.Sprintf("%s %s", cmd, dataset)
|
||||||
out, err := executeCommand(cmd)
|
out, err := executeCommand(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf("%v; command returned \"%s\"", err, out))
|
return errors.New(fmt.Sprintf("%v; command returned \"%s\"", err, out))
|
||||||
@ -821,6 +832,11 @@ func zfsDestroy(dataset string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* Filesystem operations
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
/* Copy file */
|
/* Copy file */
|
||||||
func copyFile(src, dst string) error {
|
func copyFile(src, dst string) error {
|
||||||
srcfinfo, err := os.Stat(src)
|
srcfinfo, err := os.Stat(src)
|
||||||
@ -845,6 +861,11 @@ func copyFile(src, dst string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get permissions of file or folder
|
||||||
|
func getPermissions(path string) (os.FileInfo, error) {
|
||||||
|
return os.Stat(path)
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* rc.conf management
|
* rc.conf management
|
||||||
|
Loading…
x
Reference in New Issue
Block a user