This commit is contained in:
parent
7746285212
commit
8b3fd2be97
|
@ -0,0 +1,183 @@
|
|||
// Sample pdnsd configuration file. Must be customized to obtain a working pdnsd setup!
|
||||
// Read the pdnsd.conf(5) manpage for an explanation of the options.
|
||||
// Add or remove '#' in front of options you want to disable or enable, respectively.
|
||||
// Remove '/*' and '*/' to enable complete sections.
|
||||
|
||||
global {
|
||||
perm_cache=8192;
|
||||
cache_dir="/var/cache/pdnsd";
|
||||
# pid_file = "/var/run/pdnsd.pid";
|
||||
run_as="pdnsd";
|
||||
server_ip = any; # Use eth0 here if you want to allow other
|
||||
# machines on your network to query pdnsd.
|
||||
status_ctl = on;
|
||||
# paranoid=on; # This option reduces the chance of cache poisoning
|
||||
# but may make pdnsd less efficient, unfortunately.
|
||||
query_method=udp_tcp;
|
||||
min_ttl=15m; # Retain cached entries at least 15 minutes.
|
||||
max_ttl=1w; # One week.
|
||||
timeout=10; # Global timeout option (10 seconds).
|
||||
neg_domain_pol=on;
|
||||
udpbufsize=1024; # Upper limit on the size of UDP messages.
|
||||
strict_setuid=on;
|
||||
run_ipv4=on;
|
||||
}
|
||||
|
||||
# The following section is most appropriate if you have a fixed connection to
|
||||
# the Internet and an ISP which provides good DNS servers.
|
||||
server {
|
||||
label= "kt";
|
||||
ip = 168.126.63.1, 168.126.63.2; # Put your ISP's DNS-server address(es) here.
|
||||
# proxy_only=on; # Do not query any name servers beside your ISP's.
|
||||
# This may be necessary if you are behind some
|
||||
# kind of firewall and cannot receive replies
|
||||
# from outside name servers.
|
||||
timeout=4; # Server timeout; this may be much shorter
|
||||
# that the global timeout option.
|
||||
uptest=if; # Test if the network interface is active.
|
||||
interface=ip0; # The name of the interface to check.
|
||||
interval=10m; # Check every 10 minutes.
|
||||
purge_cache=off; # Keep stale cache entries in case the ISP's
|
||||
# DNS servers go offline.
|
||||
edns_query=yes; # Use EDNS for outgoing queries to allow UDP messages
|
||||
# larger than 512 bytes. May cause trouble with some
|
||||
# legacy systems.
|
||||
# exclude=.thepiratebay.org, # If your ISP censors certain names, you may
|
||||
# .thepiratebay.se, # want to exclude them here, and provide an
|
||||
# .piratebay.org, # alternative server section below that will
|
||||
# .piratebay.se; # successfully resolve the names.
|
||||
}
|
||||
|
||||
|
||||
|
||||
# The servers provided by OpenDNS are fast, but they do not reply with
|
||||
# NXDOMAIN for non-existant domains, instead they supply you with an
|
||||
# address of one of their search engines. They also lie about the addresses of
|
||||
# of the search engines of google, microsoft and yahoo.
|
||||
# If you do not like this behaviour the "reject" option may be useful.
|
||||
server {
|
||||
label = "opendns";
|
||||
ip = 208.67.222.222, 208.67.220.220;
|
||||
reject = 208.69.32.0/24, # You may need to add additional address ranges
|
||||
208.69.34.0/24, # here if the addresses of their search engines
|
||||
208.67.219.0/24; # change.
|
||||
reject_policy = fail; # If you do not provide any alternative server
|
||||
# sections, like the following root-server
|
||||
# example, "negate" may be more appropriate here.
|
||||
timeout = 4;
|
||||
uptest = ping; # Test availability using ICMP echo requests.
|
||||
ping_timeout = 100; # ping test will time out after 10 seconds.
|
||||
interval = 15m; # Test every 15 minutes.
|
||||
preset = off;
|
||||
}
|
||||
|
||||
# The servers provided by OpenDNS are fast, but they do not reply with
|
||||
# NXDOMAIN for non-existant domains, instead they supply you with an
|
||||
# address of one of their search engines. They also lie about the addresses of
|
||||
# of the search engines of google, microsoft and yahoo.
|
||||
# If you do not like this behaviour the "reject" option may be useful.
|
||||
server {
|
||||
label = "googledns";
|
||||
ip = 8.8.8.8, 8.8.4.4;
|
||||
# example, "negate" may be more appropriate here.
|
||||
timeout = 4;
|
||||
uptest = ping; # Test availability using ICMP echo requests.
|
||||
ping_timeout = 100; # ping test will time out after 10 seconds.
|
||||
interval = 15m; # Test every 15 minutes.
|
||||
preset = off;
|
||||
}
|
||||
|
||||
|
||||
# This section is meant for resolving from root servers.
|
||||
server {
|
||||
label = "root-servers";
|
||||
root_server = discover; # Query the name servers listed below
|
||||
# to obtain a full list of root servers.
|
||||
randomize_servers = on; # Give every root server an equal chance
|
||||
# of being queried.
|
||||
ip = 198.41.0.4, # This list will be expanded to the full
|
||||
192.228.79.201, # list on start up.
|
||||
192.33.4.12,
|
||||
199.7.91.13,
|
||||
192.203.230.10,
|
||||
192.5.5.241,
|
||||
192.112.36.4,
|
||||
198.97.190.53,
|
||||
192.36.148.17,
|
||||
192.58.128.30,
|
||||
193.0.14.129,
|
||||
199.7.83.42,
|
||||
202.12.27.33;
|
||||
timeout = 5;
|
||||
uptest = query; # Test availability using empty DNS queries.
|
||||
query_test_name = .; # To be used if remote servers ignore empty queries.
|
||||
interval = 30m; # Test every half hour.
|
||||
ping_timeout = 300; # Test should time out after 30 seconds.
|
||||
purge_cache = off;
|
||||
# edns_query = yes; # Use EDNS for outgoing queries to allow UDP messages
|
||||
# larger than 512 bytes. May cause trouble with some
|
||||
# legacy systems.
|
||||
exclude = .localdomain;
|
||||
policy = included;
|
||||
preset = off;
|
||||
}
|
||||
|
||||
|
||||
source {
|
||||
owner=localhost;
|
||||
serve_aliases=on;
|
||||
authrec=on;
|
||||
file="/etc/hosts";
|
||||
}
|
||||
|
||||
source {
|
||||
owner=gear.amuz.es;
|
||||
serve_aliases=on;
|
||||
authrec=on;
|
||||
file="/container/hosts";
|
||||
}
|
||||
|
||||
/*
|
||||
include {file="/etc/pdnsd.include";} # Read additional definitions from /etc/pdnsd.include.
|
||||
*/
|
||||
|
||||
rr {
|
||||
name=localhost;
|
||||
reverse=on;
|
||||
a=127.0.0.1;
|
||||
owner=localhost;
|
||||
soa=localhost,root.localhost,42,86400,900,86400,86400;
|
||||
}
|
||||
rr {
|
||||
name = 1.0.0.127.in-addr.arpa;
|
||||
reverse=on;
|
||||
ptr = localhost;
|
||||
owner = localhost;
|
||||
soa = localhost, root.localhost, 42, 86400, 900, 86400, 86400;
|
||||
}
|
||||
|
||||
rr {
|
||||
name = gear.amuz.es;
|
||||
ns = gear.amuz.es;
|
||||
soa = gear.amuz.es, root.gear.amuz.es, 42, 86400, 900, 86400, 86400;
|
||||
}
|
||||
|
||||
rr {
|
||||
name = *.gear.amuz.es;
|
||||
ns = gear.amuz.es;
|
||||
soa = gear.amuz.es, root.gear.amuz.es, 42, 86400, 900, 86400, 86400;
|
||||
}
|
||||
|
||||
/*
|
||||
neg {
|
||||
name=doubleclick.net;
|
||||
types=domain; # This will also block xxx.doubleclick.net, etc.
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
neg {
|
||||
name=bad.server.com; # Badly behaved server you don't want to connect to.
|
||||
types=A,AAAA;
|
||||
}
|
||||
*/
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 13fb20a9787c14bfc4c7996ce27d7224aa815812
|
419
plugin.go
419
plugin.go
|
@ -1,419 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "github.com/ttacon/libphonenumber"
|
||||
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
kingpin "gopkg.in/alecthomas/kingpin.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"strconv"
|
||||
|
||||
errs "github.com/pkg/errors"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
var (
|
||||
app = kingpin.New("plugin", "nspawn Bootstrapper.").Author("Sangbum Kim<sangbumkim@amuz.es>")
|
||||
verbosePtr = app.Flag("verbose", "Enable verbose mode.").Short('v').Bool()
|
||||
clearPtr = app.Flag("clear", "clear os environment.").Short('p').Bool()
|
||||
nspawnPathPtr = app.Flag("nspawn-path", "systemd-nspawn location.").Short('s').String()
|
||||
containerHomePtr = app.Flag("container-home", "container residence path").Default("/container").Short('d').String()
|
||||
configFileNamePtr = app.Flag("config-file", "config file name").Default("settings.yml").HintOptions("FILENAME").Short('c').String()
|
||||
nodeNamePtr = app.Arg("nodeName", "nodename to spawn.").Required().String()
|
||||
bindIfNamePtr = app.Arg("bindInterface", "interface name to bind.").Required().String()
|
||||
)
|
||||
|
||||
type mountPoint struct {
|
||||
Name string `yaml:"name"`
|
||||
Map string `yaml:"map"`
|
||||
Readonly bool `yaml:"readonly"`
|
||||
}
|
||||
|
||||
func (mp mountPoint) Option(nodePath string) (option string, err error) {
|
||||
var mountPointPath string
|
||||
if filepath.IsAbs(mp.Name){
|
||||
mountPointPath= mp.Name
|
||||
}else{
|
||||
mountPointPath= filepath.Clean(filepath.Join(nodePath, "volume", mp.Name))
|
||||
}
|
||||
|
||||
if _, err = os.Stat(mountPointPath); os.IsNotExist(err) {
|
||||
err = errors.New(fmt.Sprintf("mount point %s is not exist", mountPointPath))
|
||||
return
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
if mp.Readonly {
|
||||
buffer.WriteString("--bind-ro=")
|
||||
} else {
|
||||
buffer.WriteString("--bind=")
|
||||
}
|
||||
buffer.WriteString(mountPointPath)
|
||||
buffer.WriteRune(':')
|
||||
buffer.WriteString(mp.Map)
|
||||
option = buffer.String()
|
||||
return
|
||||
}
|
||||
func (mp mountPoint) String() string {
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString(mp.Name)
|
||||
if mp.Readonly {
|
||||
buffer.WriteString("(readonly)")
|
||||
}
|
||||
buffer.WriteString("->")
|
||||
buffer.WriteString(mp.Map)
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
type config struct {
|
||||
MoundPoint []mountPoint `yaml:"mount-point"`
|
||||
}
|
||||
|
||||
func (c config) String() string {
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("config:\n")
|
||||
buffer.WriteString(" mount-point:\n")
|
||||
for _, entry := range c.MoundPoint {
|
||||
buffer.WriteString(" - ")
|
||||
buffer.WriteString(entry.String())
|
||||
buffer.WriteRune('\n')
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
// LookupIP looks up host using the local resolver.
|
||||
// It returns an array of that host's IPv4 and IPv6 addresses.
|
||||
func getIP(host string) (ip net.IP, err error) {
|
||||
var addrs []net.IP
|
||||
addrs, err = net.LookupIP(host)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return addrs[0], nil
|
||||
}
|
||||
|
||||
func getOutboundIPInfo(verbose bool) (gw net.IP, cidr uint64, linkname string, err error) {
|
||||
// netlink.RouteList
|
||||
var links []netlink.Link
|
||||
links, err = netlink.LinkList()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Println("scan system network interfaces:")
|
||||
}
|
||||
for _, link := range links {
|
||||
attrs := link.Attrs()
|
||||
|
||||
if verbose {
|
||||
fmt.Printf(" interface %s : ", attrs.Name)
|
||||
}
|
||||
if (attrs.Flags & net.FlagUp) == 0 {
|
||||
if verbose {
|
||||
fmt.Printf(" not up -- abandon!\n")
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
if verbose {
|
||||
fmt.Printf(" up!\n")
|
||||
}
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Println(" getting routing tables ")
|
||||
}
|
||||
var routes []netlink.Route
|
||||
routes, err = netlink.RouteList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
matchedGw net.IP
|
||||
matchedCidr uint64
|
||||
cidrOk = false
|
||||
)
|
||||
for _, route := range routes {
|
||||
|
||||
if verbose {
|
||||
fmt.Printf(" routing table %s\n", route.String())
|
||||
}
|
||||
if route.Dst == nil {
|
||||
if verbose {
|
||||
fmt.Printf(" - default gateway\n")
|
||||
}
|
||||
matchedGw = route.Gw
|
||||
break
|
||||
} else if verbose {
|
||||
fmt.Printf(" - no default gateway\n")
|
||||
}
|
||||
}
|
||||
if matchedGw == nil {
|
||||
if verbose {
|
||||
fmt.Println(" interface have not a default routing rule.")
|
||||
}
|
||||
continue
|
||||
} else if verbose {
|
||||
fmt.Printf(" interface have a default routing rule. gateway: %s", matchedGw.String())
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Println(" getting networks ")
|
||||
}
|
||||
var networks []netlink.Addr
|
||||
networks, err = netlink.AddrList(link, netlink.FAMILY_V4)
|
||||
if err != nil {
|
||||
fmt.Println(" - cannot getting networks ")
|
||||
continue
|
||||
}
|
||||
for _, network := range networks {
|
||||
if verbose {
|
||||
fmt.Printf(" network %s\n", network.String())
|
||||
}
|
||||
if network.Contains(matchedGw) {
|
||||
if verbose {
|
||||
fmt.Printf(" - default network\n")
|
||||
}
|
||||
netSlice := strings.Split(network.IPNet.String(), "/")
|
||||
if len(netSlice) < 2 {
|
||||
continue
|
||||
}
|
||||
if cidrData, err := strconv.ParseUint(netSlice[len(netSlice)-1], 10, 64); err == nil {
|
||||
matchedCidr = cidrData
|
||||
cidrOk = true
|
||||
break
|
||||
}
|
||||
} else if verbose {
|
||||
fmt.Printf(" - no default network\n")
|
||||
}
|
||||
}
|
||||
if cidrOk {
|
||||
gw, cidr, linkname = matchedGw, matchedCidr, attrs.Name
|
||||
if verbose {
|
||||
fmt.Println(" ok! matched ")
|
||||
}
|
||||
break
|
||||
} else if verbose {
|
||||
fmt.Println(" abandon this interface ")
|
||||
}
|
||||
}
|
||||
if gw == nil {
|
||||
err = errors.New("default gateway or cidr not found!")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func checkInterfaceValid(bindIfName string) (err error) {
|
||||
var link netlink.Link
|
||||
link, err = netlink.LinkByName(bindIfName)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
attrs := link.Attrs()
|
||||
if (attrs.Flags & net.FlagUp) == 0 {
|
||||
err = errors.New("bind interface had been deactivated")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkNodeBasicDirectory(containerHomePath string, nodeName string, configFileName string) (nodePath string, nodeConfigPath string, err error) {
|
||||
var containerHomeInfo os.FileInfo
|
||||
if containerHomeInfo, err = os.Stat(containerHomePath); os.IsNotExist(err) {
|
||||
err = errors.New(fmt.Sprintf("container home path %s is not exist", containerHomePath))
|
||||
return
|
||||
} else if !containerHomeInfo.IsDir() {
|
||||
err = errors.New(fmt.Sprintf("container home path %s is not a directory", containerHomePath))
|
||||
return
|
||||
}
|
||||
|
||||
nodePath = filepath.Join(containerHomePath, nodeName)
|
||||
|
||||
var nodePathInfo os.FileInfo
|
||||
if nodePathInfo, err = os.Stat(nodePath); os.IsNotExist(err) {
|
||||
err = errors.New(fmt.Sprintf("node path %s is not exist", nodePath))
|
||||
return
|
||||
} else if !nodePathInfo.IsDir() {
|
||||
err = errors.New(fmt.Sprintf("node path %s is not a directory", nodePath))
|
||||
return
|
||||
} else {
|
||||
subDirNames := [...]string{"merge", "work", "delta"}
|
||||
for _, subDirName := range subDirNames {
|
||||
subPath := filepath.Join(nodePath, subDirName)
|
||||
|
||||
var subPathInfo os.FileInfo
|
||||
if subPathInfo, err = os.Stat(subPath); os.IsNotExist(err) {
|
||||
err = errors.New(fmt.Sprintf("sub path %s is not exist", subPath))
|
||||
return
|
||||
} else if !subPathInfo.IsDir() {
|
||||
err = errors.New(fmt.Sprintf("sub path %s is not a directory", subPath))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeConfigPath = filepath.Join(containerHomePath, nodeName, configFileName)
|
||||
|
||||
var nodeConfigPathInfo os.FileInfo
|
||||
if nodeConfigPathInfo, err = os.Stat(nodeConfigPath); os.IsNotExist(err) || nodeConfigPathInfo.IsDir() {
|
||||
nodeConfigPath = ""
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func LoadConfig(path string) (config config, err error) {
|
||||
var (
|
||||
source []byte
|
||||
)
|
||||
if path == "" {
|
||||
} else if source, err = ioutil.ReadFile(path); err != nil {
|
||||
} else if err = yaml.Unmarshal(source, &config); err != nil {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
_, err := app.Parse(os.Args[1:])
|
||||
var (
|
||||
verbose = *verbosePtr
|
||||
clear = *clearPtr
|
||||
nodeName = *nodeNamePtr
|
||||
bindIfName = *bindIfNamePtr
|
||||
configFileName = *configFileNamePtr
|
||||
nspawnPath string
|
||||
progress = -1
|
||||
)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Fprintln(os.Stderr, r)
|
||||
os.Exit(progress)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
progress = 1
|
||||
containerHomePath, err := filepath.Abs(*containerHomePtr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
progress++
|
||||
nodePath, nodeConfigPath, err := checkNodeBasicDirectory(containerHomePath, nodeName, configFileName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else if verbose {
|
||||
var nodeConfigPathDesc = "not used"
|
||||
if nodeConfigPath != "" {
|
||||
nodeConfigPathDesc = nodeConfigPath
|
||||
}
|
||||
fmt.Printf(`sane container environment:
|
||||
- container home : %s
|
||||
- node home : %s
|
||||
- node config : %s
|
||||
`, containerHomePath, nodePath, nodeConfigPathDesc)
|
||||
}
|
||||
config, err := LoadConfig(nodeConfigPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else if verbose {
|
||||
fmt.Printf(config.String())
|
||||
}
|
||||
|
||||
progress++
|
||||
|
||||
if nspawnPathPtr != nil && *nspawnPathPtr != "" {
|
||||
nspawnPath = *nspawnPathPtr
|
||||
} else if nspawnPathData, err := exec.LookPath("systemd-nspawn"); err != nil {
|
||||
panic(errs.Wrap(err, "cannot find systemd-nspawn"))
|
||||
} else {
|
||||
nspawnPath = nspawnPathData
|
||||
if verbose {
|
||||
fmt.Printf("systemd-nspawn found : %s\n", nspawnPath)
|
||||
}
|
||||
}
|
||||
|
||||
progress++
|
||||
err = checkInterfaceValid(bindIfName)
|
||||
if err != nil {
|
||||
panic(errs.Wrap(err, "error in checkInterfaceValid"))
|
||||
}
|
||||
progress++
|
||||
nodeAddr, err := getIP(nodeName)
|
||||
|
||||
if err != nil {
|
||||
panic(errs.Wrap(err, "error in getIP"))
|
||||
}
|
||||
|
||||
progress++
|
||||
gw, cidr, linkname, err := getOutboundIPInfo(verbose)
|
||||
if err != nil {
|
||||
panic(errs.Wrap(err, "error in getOutboundIPInfo"))
|
||||
}
|
||||
|
||||
if verbose {
|
||||
fmt.Println("network configuration:")
|
||||
fmt.Printf(" - bind interface{%s} : valid\n", bindIfName)
|
||||
fmt.Printf(" - default routing info : ip %s/%d link %s\n", gw.String(), cidr, linkname)
|
||||
fmt.Printf(" - node{%s} IP address : %s\n", nodeName, nodeAddr.String())
|
||||
}
|
||||
option := []string{
|
||||
"--quiet",
|
||||
"--boot",
|
||||
"--link-journal=try-host",
|
||||
"--notify-ready=true"}
|
||||
option = append(option, fmt.Sprintf("--network-ipvlan=%s", bindIfName))
|
||||
option = append(option, fmt.Sprintf("--setenv=IP_ADDR=%s/%d", nodeAddr.String(), cidr))
|
||||
option = append(option, fmt.Sprintf("--setenv=GATEWAY_ADDR=%s", gw.String()))
|
||||
option = append(option, fmt.Sprintf("--machine=%s", nodeName))
|
||||
option = append(option, fmt.Sprintf("--directory=%s", filepath.Join(nodePath, "merge")))
|
||||
|
||||
for _, mountPoint := range config.MoundPoint {
|
||||
if mountOption, err := mountPoint.Option(nodePath); err != nil {
|
||||
panic(errs.Wrap(err, "error in mountOption"))
|
||||
} else {
|
||||
option = append(option, mountOption)
|
||||
}
|
||||
}
|
||||
var env []string
|
||||
if clear {
|
||||
env = []string{}
|
||||
} else {
|
||||
env = os.Environ()
|
||||
if verbose {
|
||||
fmt.Println("os environment:")
|
||||
for _, segment := range env {
|
||||
fmt.Println(" ", segment)
|
||||
}
|
||||
}
|
||||
}
|
||||
if verbose {
|
||||
fmt.Println("systemd-nspawn spawning:")
|
||||
fmt.Println(nspawnPath, " \\")
|
||||
for _, segment := range option {
|
||||
fmt.Println(" ", segment, " \\")
|
||||
}
|
||||
fmt.Println(" ;")
|
||||
fmt.Println("bye!")
|
||||
}
|
||||
if err := syscall.Exec(nspawnPath, option, env); err != nil {
|
||||
panic(errs.Wrap(err, "error in systemd-nspawn execution"))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Unit]
|
||||
Description=Container %I
|
||||
Documentation=man:systemd-nspawn(1)
|
||||
PartOf=machines.target
|
||||
Before=machines.target
|
||||
After=network.target
|
||||
After=pdnsd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/container/plugin %I igb0 -v
|
||||
KillMode=mixed
|
||||
Type=notify
|
||||
RestartForceExitStatus=133
|
||||
SuccessExitStatus=133
|
||||
Slice=machine.slice
|
||||
Delegate=yes
|
||||
TasksMax=8192
|
||||
|
||||
# Enforce a strict device policy, similar to the one nspawn configures
|
||||
# when it allocates its own scope unit. Make sure to keep these
|
||||
# policies in sync if you change them!
|
||||
DevicePolicy=strict
|
||||
DeviceAllow=/dev/null rwm
|
||||
DeviceAllow=/dev/zero rwm
|
||||
DeviceAllow=/dev/full rwm
|
||||
DeviceAllow=/dev/random rwm
|
||||
DeviceAllow=/dev/urandom rwm
|
||||
DeviceAllow=/dev/tty rwm
|
||||
DeviceAllow=/dev/net/tun rwm
|
||||
DeviceAllow=/dev/pts/ptmx rw
|
||||
DeviceAllow=char-pts rw
|
||||
|
||||
# nspawn itself needs access to /dev/loop-control and /dev/loop, to
|
||||
# implement the --image= option. Add these here, too.
|
||||
DeviceAllow=/dev/loop-control rw
|
||||
DeviceAllow=block-loop rw
|
||||
DeviceAllow=block-blkext rw
|
||||
|
||||
[Install]
|
||||
WantedBy=machines.target
|
|
@ -0,0 +1,8 @@
|
|||
mount-point:
|
||||
- name: minio-config
|
||||
map: /etc/minio
|
||||
readonly: true
|
||||
- name: minio-data
|
||||
map: /var/lib/minio
|
||||
- name: eden-home
|
||||
map: /var/lib/eden
|
Loading…
Reference in New Issue