Initial commit of Warewulf v4 POC
This commit is contained in:
29
Makefile
Normal file
29
Makefile
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
files:
|
||||
sudo install -d -m 0755 /var/warewulf/provision
|
||||
sudo install -d -m 0755 /var/warewulf/provision/kernels
|
||||
sudo install -d -m 0755 /var/warewulf/provision/overlays
|
||||
sudo install -d -m 0755 /var/warewulf/provision/bases
|
||||
sudo install -d -m 0755 /etc/warewulf/
|
||||
sudo install -m 0644 dhcpd.conf /etc/dhcp/dhcpd.conf
|
||||
sudo install -m 0644 nodes.yaml /etc/warewulf/nodes.yaml
|
||||
sudo cp -r tftpboot/* /var/lib/tftpboot/warewulf/ipxe/
|
||||
sudo cp -r overlays /etc/warewulf/
|
||||
|
||||
services: files
|
||||
sudo systemctl enable tftp
|
||||
sudo systemctl restart tftp
|
||||
sudo systemctl enable dhcpd
|
||||
sudo systemctl restart dhcpd
|
||||
|
||||
build:
|
||||
go build cmd/warewulfd/warewulfd.go
|
||||
go build cmd/wwbuild/wwbuild.go
|
||||
|
||||
clean:
|
||||
rm -f warewulfd
|
||||
rm -f wwbuild
|
||||
|
||||
install: build files services
|
||||
|
||||
18
README.md
18
README.md
@@ -1 +1,17 @@
|
||||
# warewulf
|
||||
# warewulf
|
||||
|
||||
This is built on CentOS-7. More needs to be done to make it work on other
|
||||
distributions and versions specifically with the system service
|
||||
compoenents.
|
||||
|
||||
In a nutshell, to use:
|
||||
|
||||
1. make install
|
||||
2. build VNFS `sudo singularity build --sandbox /var/chroots/centos-7 centos-7.def`
|
||||
3. Edit `/etc/warewulf/nodes.yaml`
|
||||
4. Run the following commands:
|
||||
a. `./wwbuild vnfs`
|
||||
b. `./wwbuild kernel`
|
||||
c. `./wwbuild overlay`
|
||||
c. `./warewulfd`
|
||||
5. Boot your node and watch the console and the output of the Warewulfd process
|
||||
|
||||
17
centos-7.def
Normal file
17
centos-7.def
Normal file
@@ -0,0 +1,17 @@
|
||||
BootStrap: yum
|
||||
OSVersion: 7
|
||||
MirrorURL: http://mirror.centos.org/centos-%{OSVERSION}/%{OSVERSION}/os/x86_64/
|
||||
Include: yum
|
||||
|
||||
|
||||
%post
|
||||
|
||||
sed -i 's/^root:\*:/root::/g' /etc/passwd
|
||||
|
||||
yum install -y basesystem bash chkconfig coreutils e2fsprogs \
|
||||
ethtool filesystem findutils gawk grep initscripts iproute \
|
||||
iputils net-tools nfs-utils pam psmisc rdate rsync sed setup \
|
||||
shadow-utils rsyslog tcp_wrappers tzdata util-linux words \
|
||||
zlib tar less gzip which util-linux openssh-clients \
|
||||
openssh-server dhclient pciutils vim-minimal shadow-utils \
|
||||
strace cronie crontabs cpio wget centos-release
|
||||
117
cmd/warewulfd/warewulfd.go
Normal file
117
cmd/warewulfd/warewulfd.go
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"os"
|
||||
"strconv"
|
||||
"io"
|
||||
"path"
|
||||
|
||||
"net/http"
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
)
|
||||
|
||||
const LocalStateDir = "/var/warewulf"
|
||||
const SysConfDir = "/etc/warewulf"
|
||||
|
||||
|
||||
func ipxe(w http.ResponseWriter, req *http.Request) {
|
||||
url := strings.Split(req.URL.Path, "/");
|
||||
|
||||
if url[2] == "" {
|
||||
fmt.Printf("ERROR: Bad iPXE request from %s\n", req.RemoteAddr)
|
||||
return
|
||||
}
|
||||
|
||||
node := assets.FindByHwaddr(url[2])
|
||||
|
||||
if node.HostName != "" {
|
||||
fmt.Printf("IPXE: %15s: hwaddr=%s\n", node.Fqdn, url[2]);
|
||||
|
||||
fmt.Fprintf(w, "#!ipxe\n");
|
||||
|
||||
fmt.Fprintf(w, "echo Now booting Warewulf - v4 Proof of Concept\n");
|
||||
fmt.Fprintf(w, "set base http://192.168.1.1:9873/\n")
|
||||
fmt.Fprintf(w, "kernel ${base}/files/kernel/%s crashkernel=no quiet\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/files/vnfs/%s\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/files/kmods/%s\n", url[2])
|
||||
fmt.Fprintf(w, "initrd ${base}/files/overlay/%s\n", url[2])
|
||||
fmt.Fprintf(w, "boot\n");
|
||||
} else {
|
||||
fmt.Printf("ERROR: iPXE request from unknown Node (hwaddr=%s)\n", url[2])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
func files(w http.ResponseWriter, req *http.Request) {
|
||||
url := strings.Split(req.URL.Path, "/")
|
||||
|
||||
node := assets.FindByHwaddr(url[3])
|
||||
|
||||
fmt.Printf("GET: %15s: %s\n", node.Fqdn, req.URL.Path)
|
||||
|
||||
if url[2] == "kernel" {
|
||||
if node.KernelVersion != "" {
|
||||
kernelFile := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, node.KernelVersion);
|
||||
|
||||
sendFile(w, kernelFile, node.Fqdn);
|
||||
}
|
||||
} else if url[2] == "kmods" {
|
||||
if node.KernelVersion != "" {
|
||||
kmodsFile := fmt.Sprintf("%s/provision/kernels/kmods-%s.img", LocalStateDir, node.KernelVersion);
|
||||
|
||||
sendFile(w, kmodsFile, node.Fqdn);
|
||||
}
|
||||
} else if url[2] == "vnfs" {
|
||||
if node.Vnfs != "" {
|
||||
vnfsFile := fmt.Sprintf("%s/provision/bases/%s.img.gz", LocalStateDir, path.Base(node.Vnfs))
|
||||
|
||||
sendFile(w, vnfsFile, node.Fqdn);
|
||||
}
|
||||
} else if url[2] == "overlay" {
|
||||
if node.Overlay!= "" {
|
||||
overlayFile := fmt.Sprintf("%s/provision/overlays/%s.img", LocalStateDir, node.Fqdn);
|
||||
|
||||
sendFile(w, overlayFile, node.Fqdn);
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
func sendFile(w http.ResponseWriter, filename string, sendto string) {
|
||||
|
||||
fmt.Printf("SEND: %15s: %s\n", sendto, filename);
|
||||
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: %s\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
FileHeader := make([]byte, 512)
|
||||
fd.Read(FileHeader)
|
||||
FileContentType := http.DetectContentType(FileHeader)
|
||||
FileStat, _ := fd.Stat()
|
||||
FileSize := strconv.FormatInt(FileStat.Size(), 10)
|
||||
|
||||
w.Header().Set("Content-Disposition", "attachment; filename=kernel")
|
||||
w.Header().Set("Content-Type", FileContentType)
|
||||
w.Header().Set("Content-Length", FileSize)
|
||||
|
||||
fd.Seek(0, 0)
|
||||
io.Copy(w, fd)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func main() {
|
||||
|
||||
http.HandleFunc("/ipxe/", ipxe)
|
||||
http.HandleFunc("/files/", files)
|
||||
|
||||
http.ListenAndServe(":9873", nil)
|
||||
}
|
||||
86
cmd/wwbuild/wwbuild.go
Normal file
86
cmd/wwbuild/wwbuild.go
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
package main
|
||||
|
||||
|
||||
import(
|
||||
"os"
|
||||
"os/exec"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"github.com/hpcng/warewulf/internal/pkg/assets"
|
||||
)
|
||||
|
||||
|
||||
const LocalStateDir = "/var/warewulf"
|
||||
|
||||
|
||||
|
||||
func main(){
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Printf("USAGE: %s [vnfs/kernel/overlays/all]\n", os.Args[0]);
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if os.Args[1] == "vnfs" {
|
||||
for _, vnfs := range assets.FindAllVnfs() {
|
||||
if _, err := os.Stat(vnfs); err == nil {
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s/provision/bases/%s.img.gz\"", vnfs, LocalStateDir, path.Base(vnfs));
|
||||
fmt.Printf("BUILDING VNFS: %s\n", vnfs);
|
||||
out, err := exec.Command("/bin/sh", "-c", cmd).Output();
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
|
||||
output := string(out[:])
|
||||
fmt.Println(output)
|
||||
} else {
|
||||
fmt.Printf("SKIPPING VNFS: (bad path) %s\n", vnfs);
|
||||
}
|
||||
}
|
||||
} else if os.Args[1] == "kernel" {
|
||||
for _, kernelVers := range assets.FindAllKernels() {
|
||||
kernelSource := fmt.Sprintf("/boot/vmlinuz-%s", kernelVers)
|
||||
if _, err := os.Stat(kernelSource); err == nil {
|
||||
kernelDestination := fmt.Sprintf("%s/provision/kernels/vmlinuz-%s", LocalStateDir, kernelVers);
|
||||
fmt.Printf("SETUP KERNEL: %s (%s)\n", kernelSource, kernelDestination);
|
||||
err := exec.Command("cp", kernelSource, kernelDestination).Run()
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
|
||||
kernelMods := fmt.Sprintf("/lib/modules/%s", kernelVers)
|
||||
if _, err := os.Stat(kernelMods); err == nil {
|
||||
fmt.Printf("BUILDING MODS: %s\n", kernelMods);
|
||||
cmd := fmt.Sprintf("find %s | cpio --quiet -o -H newc -F \"%s/provision/kernels/kmods-%s.img\"", kernelMods, LocalStateDir, kernelVers);
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run();
|
||||
if err != nil {
|
||||
fmt.Printf("OUTPUT: %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if os.Args[1] == "overlay" {
|
||||
fmt.Printf("note: This needs to create an overlay for each node with macro expansions\n");
|
||||
|
||||
|
||||
for _, node := range assets.FindAllNodes() {
|
||||
overlayDir := fmt.Sprintf("/etc/warewulf/overlays/%s", node.Overlay);
|
||||
if _, err := os.Stat(overlayDir); err == nil {
|
||||
cmd := fmt.Sprintf("cd %s; find . | cpio --quiet -o -H newc | gzip -c > \"%s/provision/overlays/%s.img\"", overlayDir, LocalStateDir, node.Fqdn);
|
||||
fmt.Printf("BUILDING OVERLAY: %s\n", node.Fqdn);
|
||||
err := exec.Command("/bin/sh", "-c", cmd).Run();
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("SKIPPING OVERLAY: (bad path) %s\n", overlayDir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
54
dhcpd.conf
Normal file
54
dhcpd.conf
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
allow booting;
|
||||
allow bootp;
|
||||
ddns-update-style interim;
|
||||
authoritative;
|
||||
|
||||
option space ipxe;
|
||||
|
||||
# Tell iPXE to not wait for ProxyDHCP requests to speed up boot.
|
||||
option ipxe.no-pxedhcp code 176 = unsigned integer 8;
|
||||
option ipxe.no-pxedhcp 1;
|
||||
|
||||
option architecture-type code 93 = unsigned integer 16;
|
||||
|
||||
if exists user-class and option user-class = "iPXE" {
|
||||
#filename "http://192.168.1.1/WW4/ipxe/${mac:hexhyp}";
|
||||
#filename "http://192.168.1.1:9873/ipxe?hwaddr=${mac:hexhyp}";
|
||||
filename "http://192.168.1.1:9873/ipxe/${mac:hexhyp}";
|
||||
} else {
|
||||
if option architecture-type = 00:0B {
|
||||
filename "/warewulf/ipxe/bin-arm64-efi/snp.efi";
|
||||
} elsif option architecture-type = 00:0A {
|
||||
filename "/warewulf/ipxe/bin-arm32-efi/placeholder.efi";
|
||||
} elsif option architecture-type = 00:09 {
|
||||
filename "/warewulf/ipxe/bin-x86_64-efi/snp.efi";
|
||||
} elsif option architecture-type = 00:07 {
|
||||
filename "/warewulf/ipxe/bin-x86_64-efi/snp.efi";
|
||||
} elsif option architecture-type = 00:06 {
|
||||
filename "/warewulf/ipxe/bin-i386-efi/snp.efi";
|
||||
} elsif option architecture-type = 00:00 {
|
||||
filename "/warewulf/ipxe/bin-i386-pcbios/undionly.kpxe";
|
||||
}
|
||||
}
|
||||
|
||||
subnet 192.168.1.0 netmask 255.255.255.0 {
|
||||
range 192.168.1.10 192.168.1.99;
|
||||
next-server 192.168.1.1;
|
||||
}
|
||||
|
||||
|
||||
#subnet 192.168.1.0 netmask 255.255.255.0 {
|
||||
# not authoritative;
|
||||
# option subnet-mask 255.255.255.0;
|
||||
#}
|
||||
|
||||
#group {
|
||||
# host n0000_localdomain-eth0 {
|
||||
# option host-name n0000;
|
||||
# option domain-name "localdomain";
|
||||
# hardware ethernet 00:0c:29:c3:bf:42;
|
||||
# fixed-address 192.168.1.100;
|
||||
# next-server 192.168.1.1;
|
||||
# }
|
||||
#}
|
||||
5
go.mod
Normal file
5
go.mod
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/hpcng/warewulf
|
||||
|
||||
go 1.15
|
||||
|
||||
require gopkg.in/yaml.v2 v2.3.0
|
||||
3
go.sum
Normal file
3
go.sum
Normal file
@@ -0,0 +1,3 @@
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
182
internal/pkg/assets/assets.go
Normal file
182
internal/pkg/assets/assets.go
Normal file
@@ -0,0 +1,182 @@
|
||||
|
||||
package assets
|
||||
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
|
||||
const ConfigFile = "/etc/warewulf/nodes.yaml"
|
||||
|
||||
|
||||
func init() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
type nodeYaml struct {
|
||||
NodeGroups map[string]nodeGroup //`yaml:"nodegroups"`
|
||||
}
|
||||
|
||||
type nodeGroup struct {
|
||||
Comment string
|
||||
Vnfs string
|
||||
Overlay string
|
||||
DomainSuffix string `yaml:"domain suffix"`
|
||||
KernelVersion string `yaml:"kernel version"`
|
||||
Nodes map[string]nodeEntry
|
||||
}
|
||||
|
||||
type nodeEntry struct {
|
||||
Hostname string
|
||||
Vnfs string
|
||||
Overlay string
|
||||
DomainSuffix string `yaml:"domain suffix"`
|
||||
KernelVersion string `yaml:"kernel version"`
|
||||
IpmiIpaddr string `yaml:"ipmi ipaddr"`
|
||||
NetDevs map[string]netDevs
|
||||
}
|
||||
|
||||
type netDevs struct {
|
||||
Type string
|
||||
Hwaddr string
|
||||
Ipaddr string
|
||||
Netmask string
|
||||
Gateway string
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
GroupName string
|
||||
HostName string
|
||||
Fqdn string
|
||||
Vnfs string
|
||||
Overlay string
|
||||
KernelVersion string
|
||||
NetDevs map[string]netDevs
|
||||
}
|
||||
|
||||
|
||||
func FindAllNodes() []NodeInfo {
|
||||
var c nodeYaml
|
||||
var ret []NodeInfo
|
||||
|
||||
fd, err := ioutil.ReadFile(ConfigFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(fd, &c)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
for groupname, group := range c.NodeGroups {
|
||||
for _, node := range group.Nodes {
|
||||
var n NodeInfo
|
||||
|
||||
n.GroupName = groupname
|
||||
n.HostName = node.Hostname
|
||||
|
||||
n.Vnfs = group.Vnfs
|
||||
n.Overlay = group.Overlay
|
||||
n.KernelVersion = group.KernelVersion
|
||||
n.NetDevs = node.NetDevs
|
||||
|
||||
if ( group.DomainSuffix != "" ) {
|
||||
n.Fqdn = node.Hostname + "." + group.DomainSuffix
|
||||
} else {
|
||||
n.Fqdn = node.Hostname
|
||||
}
|
||||
if node.KernelVersion != "" {
|
||||
n.KernelVersion = node.KernelVersion
|
||||
}
|
||||
if node.Vnfs != "" {
|
||||
n.Vnfs = node.Vnfs
|
||||
}
|
||||
if node.Overlay != "" {
|
||||
n.Overlay = node.Overlay
|
||||
}
|
||||
ret = append(ret, n)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
func FindByHwaddr(hwa string) NodeInfo{
|
||||
var ret NodeInfo
|
||||
|
||||
for _, node := range FindAllNodes() {
|
||||
for _, dev := range node.NetDevs {
|
||||
if dev.Hwaddr == hwa {
|
||||
return node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
func FindAllVnfs() []string {
|
||||
var ret []string
|
||||
set := make(map[string]bool)
|
||||
|
||||
for _, node := range FindAllNodes() {
|
||||
if node.Vnfs != "" {
|
||||
set[node.Vnfs] = true
|
||||
}
|
||||
}
|
||||
|
||||
for entry, _ := range set {
|
||||
ret = append(ret, entry)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
func FindAllKernels() []string {
|
||||
var ret []string
|
||||
set := make(map[string]bool)
|
||||
|
||||
for _, node := range FindAllNodes() {
|
||||
if node.KernelVersion != "" {
|
||||
set[node.KernelVersion] = true
|
||||
}
|
||||
}
|
||||
|
||||
for entry, _ := range set {
|
||||
ret = append(ret, entry)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
func FindAllOverlays() []string {
|
||||
var ret []string
|
||||
set := make(map[string]bool)
|
||||
|
||||
for _, node := range FindAllNodes() {
|
||||
if node.Overlay != "" {
|
||||
set[node.Overlay] = true
|
||||
}
|
||||
}
|
||||
|
||||
for entry, _ := range set {
|
||||
ret = append(ret, entry)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
16
internal/pkg/util/util.go
Normal file
16
internal/pkg/util/util.go
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
package util
|
||||
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"crypto/sha1"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func Sha1Sum(input string) []byte{
|
||||
|
||||
|
||||
|
||||
}
|
||||
52
nodes.yaml
Normal file
52
nodes.yaml
Normal file
@@ -0,0 +1,52 @@
|
||||
nodegroups:
|
||||
group_1:
|
||||
comment: This is the group 1
|
||||
vnfs: /var/chroots/test
|
||||
overlay: generic
|
||||
domain suffix: group1
|
||||
nodes:
|
||||
n0000:
|
||||
hostname: n0000
|
||||
kernel version: 3.10.0-1127.el7.x86_64
|
||||
netdevs:
|
||||
eth0:
|
||||
hwaddr: xx:xx:xx:xx:aa
|
||||
ipaddr: x.x.x.x
|
||||
netmask: x.x.x.x
|
||||
gateway: x.x.x.x
|
||||
group_2:
|
||||
comment: This is the group 2
|
||||
vnfs: /var/chroots/test
|
||||
overlay: generic
|
||||
domain suffix: group2
|
||||
kernel version: 3.10.0-1127.el7.x86_64
|
||||
nodes:
|
||||
n0000:
|
||||
hostname: n0000
|
||||
ipmi ipaddr: x.x.x.x
|
||||
netdevs:
|
||||
eth0:
|
||||
hwaddr: 00-0c-29-c3-bf-42
|
||||
ipaddr: x.x.x.x
|
||||
netmask: x.x.x.x
|
||||
gateway: x.x.x.x
|
||||
type: ethernet
|
||||
ib0:
|
||||
hwaddr: xx:xx:xx:xx:xx
|
||||
ipaddr: x.x.x.x
|
||||
netmask: x.x.x.x
|
||||
gateway: x.x.x.x
|
||||
type: infiniband
|
||||
n0001:
|
||||
hostname: n0001
|
||||
ipmi ipaddr: x.x.x.x
|
||||
netdevs:
|
||||
eth0:
|
||||
hwaddr: xx:xx:xx:xx:xx
|
||||
ipaddr: x.x.x.x
|
||||
netmask: x.x.x.x
|
||||
gateway: x.x.x.x
|
||||
ib0:
|
||||
hwaddr: xx:xx:xx:xx:xx
|
||||
ipaddr: x.x.x.x
|
||||
netmask: x.x.x.x
|
||||
14
overlays/generic/init
Executable file
14
overlays/generic/init
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
clear
|
||||
|
||||
mount -t proc none /proc
|
||||
mount -t sysfs none /sys
|
||||
mount -t devtmpfs devtmpfs /dev
|
||||
|
||||
/sbin/ip link set dev lo up
|
||||
|
||||
echo "Calling /sbin/init..."
|
||||
echo
|
||||
|
||||
exec /sbin/init
|
||||
BIN
tftpboot/bin-i386-efi/snp.efi
Normal file
BIN
tftpboot/bin-i386-efi/snp.efi
Normal file
Binary file not shown.
BIN
tftpboot/bin-i386-pcbios/undionly.kpxe
Normal file
BIN
tftpboot/bin-i386-pcbios/undionly.kpxe
Normal file
Binary file not shown.
BIN
tftpboot/bin-x86_64-efi/snp.efi
Normal file
BIN
tftpboot/bin-x86_64-efi/snp.efi
Normal file
Binary file not shown.
Reference in New Issue
Block a user