Merge pull request #252 from gmkurtzer/asset_key_security
Initial commit of asset key tag security check
This commit is contained in:
@@ -2,15 +2,18 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
|
"github.com/talos-systems/go-smbios/smbios"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -48,8 +51,7 @@ func main() {
|
|||||||
if conf.Warewulf.Secure {
|
if conf.Warewulf.Secure {
|
||||||
// Setup local port to something privileged (<1024)
|
// Setup local port to something privileged (<1024)
|
||||||
localTCPAddr.Port = 987
|
localTCPAddr.Port = 987
|
||||||
} else {
|
wwlog.Printf(wwlog.INFO, "Running from trusted port\n")
|
||||||
fmt.Printf("INFO: Running from an insecure port\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
webclient := &http.Client{
|
webclient := &http.Client{
|
||||||
@@ -67,6 +69,30 @@ func main() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smbiosDump, err := smbios.New()
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "Could not get SMBIOS info: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
sysinfoDump := smbiosDump.SystemInformation()
|
||||||
|
localUUID, _ := sysinfoDump.UUID()
|
||||||
|
x := smbiosDump.SystemEnclosure()
|
||||||
|
tag := x.AssetTagNumber()
|
||||||
|
|
||||||
|
cmdline, err := ioutil.ReadFile("/proc/cmdline")
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "Could not read from /proc/cmdline: %s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
wwid_tmp := strings.Split(string(cmdline), "wwid=")
|
||||||
|
if len(wwid_tmp) < 2 {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "'wwid' is not defined in /proc/cmdline\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
wwid := strings.Split(wwid_tmp[1], " ")[0]
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var resp *http.Response
|
var resp *http.Response
|
||||||
counter := 0
|
counter := 0
|
||||||
@@ -74,7 +100,7 @@ func main() {
|
|||||||
for {
|
for {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
getString := fmt.Sprintf("http://%s:%d/overlay-runtime", conf.Ipaddr, conf.Warewulf.Port)
|
getString := fmt.Sprintf("http://%s:%d/overlay-runtime/%s?assetkey=%s&uuid=%s", conf.Ipaddr, conf.Warewulf.Port, wwid, tag, localUUID)
|
||||||
resp, err = webclient.Get(getString)
|
resp, err = webclient.Get(getString)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#!ipxe
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo ================================================================================
|
|
||||||
echo Warewulf v4 now booting: {{.Fqdn}}
|
|
||||||
echo
|
|
||||||
echo Container: {{.ContainerName}}
|
|
||||||
echo Kernel: {{.KernelVersion}}
|
|
||||||
echo KernelArgs: {{.KernelArgs}}
|
|
||||||
echo
|
|
||||||
|
|
||||||
set base http://{{.Ipaddr}}:{{.Port}}
|
|
||||||
|
|
||||||
kernel --name kernel ${base}/kernel/{{.Hwaddr}} || goto reboot
|
|
||||||
imgextract --name container ${base}/container/{{.Hwaddr}} || goto reboot
|
|
||||||
imgextract --name kmods ${base}/kmods/{{.Hwaddr}} || goto reboot
|
|
||||||
imgextract --name system ${base}/overlay-system/{{.Hwaddr}} || goto reboot
|
|
||||||
|
|
||||||
boot kernel initrd=container initrd=kmods initrd=system {{.KernelArgs}} || goto reboot
|
|
||||||
|
|
||||||
:reboot
|
|
||||||
echo
|
|
||||||
echo There was an error, rebooting in 15s...
|
|
||||||
echo
|
|
||||||
sleep 15
|
|
||||||
reboot
|
|
||||||
27
etc/ipxe/bigimage.ipxe
Normal file
27
etc/ipxe/bigimage.ipxe
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#!ipxe
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo ================================================================================
|
||||||
|
echo Warewulf v4 now booting: {{.Fqdn}}
|
||||||
|
echo
|
||||||
|
echo Container: {{.ContainerName}}
|
||||||
|
echo Kernel: {{.KernelVersion}}
|
||||||
|
echo KernelArgs: {{.KernelArgs}}
|
||||||
|
echo
|
||||||
|
|
||||||
|
set base http://{{.Ipaddr}}:{{.Port}}
|
||||||
|
|
||||||
|
kernel --name kernel ${base}/kernel/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
imgextract --name container ${base}/container/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
imgextract --name kmods ${base}/kmods/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
imgextract --name system ${base}/overlay-system/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
imgextract --name runtime ${base}/overlay-runtime/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
|
||||||
|
boot kernel initrd=container initrd=kmods initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot
|
||||||
|
|
||||||
|
:reboot
|
||||||
|
echo
|
||||||
|
echo There was an error, rebooting in 15s...
|
||||||
|
echo
|
||||||
|
sleep 15
|
||||||
|
reboot
|
||||||
@@ -11,13 +11,13 @@ echo
|
|||||||
|
|
||||||
set base http://{{.Ipaddr}}:{{.Port}}
|
set base http://{{.Ipaddr}}:{{.Port}}
|
||||||
|
|
||||||
kernel --name kernel ${base}/kernel/{{.Hwaddr}} || goto reboot
|
kernel --name kernel ${base}/kernel/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
initrd --name container ${base}/container/{{.Hwaddr}} || goto reboot
|
initrd --name container ${base}/container/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
initrd --name kmods ${base}/kmods/{{.Hwaddr}} || goto reboot
|
initrd --name kmods ${base}/kmods/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
initrd --name system ${base}/overlay-system/{{.Hwaddr}} || goto reboot
|
initrd --name system ${base}/overlay-system/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
initrd --name runtime ${base}/overlay-runtime/{{.Hwaddr}} || goto reboot
|
initrd --name runtime ${base}/overlay-runtime/{{.Hwaddr}}?assetkey=${asset}&uuid=${uuid} || goto reboot
|
||||||
|
|
||||||
boot kernel initrd=container initrd=kmods initrd=system initrd=runtime {{.KernelArgs}} || goto reboot
|
boot kernel initrd=container initrd=kmods initrd=system initrd=runtime wwid={{.Hwaddr}} {{.KernelArgs}} || goto reboot
|
||||||
|
|
||||||
:reboot
|
:reboot
|
||||||
echo
|
echo
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -13,6 +13,7 @@ require (
|
|||||||
github.com/opencontainers/umoci v0.4.6
|
github.com/opencontainers/umoci v0.4.6
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/spf13/cobra v1.1.1
|
||||||
|
github.com/talos-systems/go-smbios v0.1.1
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|||||||
5
go.sum
5
go.sum
@@ -227,6 +227,8 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l
|
|||||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
|
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e h1:vUmf0yezR0y7jJ5pceLHthLaYf4bA5T14B6q39S4q2Q=
|
||||||
|
github.com/digitalocean/go-smbios v0.0.0-20180907143718-390a4f403a8e/go.mod h1:YTIHhz/QFSYnu/EhlF2SpU2Uk+32abacUYA5ZPljz1A=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
@@ -354,6 +356,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
@@ -674,6 +677,8 @@ github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG
|
|||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
github.com/talos-systems/go-smbios v0.1.1 h1:Au6obB/Pp0i0JHhvPlzONk5aoNseosO2BUsmvWWi7y8=
|
||||||
|
github.com/talos-systems/go-smbios v0.1.1/go.mod h1:vk76naUSZaWE8Z95wbDn51FgH0goECM4oK3KY2hYSMU=
|
||||||
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I=
|
||||||
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Ipxe", node.Ipxe.Source(), node.Ipxe.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Ipxe", node.Ipxe.Source(), node.Ipxe.Print())
|
||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Init", node.Init.Source(), node.Init.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Init", node.Init.Source(), node.Init.Print())
|
||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Root", node.Root.Source(), node.Root.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "Root", node.Root.Source(), node.Root.Print())
|
||||||
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "AssetKey", node.AssetKey.Source(), node.AssetKey.Print())
|
||||||
|
|
||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiIpaddr", node.IpmiIpaddr.Source(), node.IpmiIpaddr.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiIpaddr", node.IpmiIpaddr.Source(), node.IpmiIpaddr.Print())
|
||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiNetmask", node.IpmiNetmask.Source(), node.IpmiNetmask.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiNetmask", node.IpmiNetmask.Source(), node.IpmiNetmask.Print())
|
||||||
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiPort", node.IpmiPort.Source(), node.IpmiPort.Print())
|
fmt.Printf("%-20s %-18s %-12s %s\n", node.Id.Get(), "IpmiPort", node.IpmiPort.Source(), node.IpmiPort.Print())
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
n.Root.Set(SetRoot)
|
n.Root.Set(SetRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if SetAssetKey != "" {
|
||||||
|
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting asset key to: %s\n", n.Id.Get(), SetAssetKey)
|
||||||
|
n.AssetKey.Set(SetAssetKey)
|
||||||
|
}
|
||||||
|
|
||||||
if SetKernel != "" {
|
if SetKernel != "" {
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Id.Get(), SetKernel)
|
wwlog.Printf(wwlog.VERBOSE, "Node: %s, Setting kernel to: %s\n", n.Id.Get(), SetKernel)
|
||||||
n.KernelVersion.Set(SetKernel)
|
n.KernelVersion.Set(SetKernel)
|
||||||
@@ -232,7 +237,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Id.Get(), SetNetName, SetHwaddr)
|
wwlog.Printf(wwlog.VERBOSE, "Node: %s:%s, Setting HW address to: %s\n", n.Id.Get(), SetNetName, SetHwaddr)
|
||||||
n.NetDevs[SetNetName].Hwaddr.Set(SetHwaddr)
|
n.NetDevs[SetNetName].Hwaddr.Set(strings.ToLower(SetHwaddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
if SetType != "" {
|
if SetType != "" {
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ var (
|
|||||||
SetKey string
|
SetKey string
|
||||||
SetValue string
|
SetValue string
|
||||||
SetKeyDel bool
|
SetKeyDel bool
|
||||||
|
SetAssetKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -94,6 +95,7 @@ func init() {
|
|||||||
baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name")
|
baseCmd.PersistentFlags().StringVar(&SetIpxe, "ipxe", "", "Set the node's iPXE template name")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container")
|
baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container")
|
||||||
baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs")
|
baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs")
|
||||||
|
baseCmd.PersistentFlags().StringVar(&SetAssetKey, "assetkey", "", "Set the node's Asset tag (key)")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetInitOverlay, "wwinit", "O", "", "Set the node's initialization overlay")
|
baseCmd.PersistentFlags().StringVarP(&SetInitOverlay, "wwinit", "O", "", "Set the node's initialization overlay")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
|
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
|
||||||
if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelArgs", profile.KernelArgs.Print())
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "KernelArgs", profile.KernelArgs.Print())
|
||||||
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Init", profile.Init.Print())
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Init", profile.Init.Print())
|
||||||
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Root", profile.Root.Print())
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "Root", profile.Root.Print())
|
||||||
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "AssetKey", profile.AssetKey.Print())
|
||||||
|
|
||||||
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "SystemOverlay", profile.SystemOverlay.Print())
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "SystemOverlay", profile.SystemOverlay.Print())
|
||||||
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "RuntimeOverlay", profile.RuntimeOverlay.Print())
|
fmt.Printf("%-20s %-18s %s\n", profile.Id.Get(), "RuntimeOverlay", profile.RuntimeOverlay.Print())
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ func CobraRunE(cmd *cobra.Command, args []string) error {
|
|||||||
p.Root.Set(SetRoot)
|
p.Root.Set(SetRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if SetAssetKey != "" {
|
||||||
|
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting asset key to: %s\n", p.Id.Get(), SetAssetKey)
|
||||||
|
p.AssetKey.Set(SetAssetKey)
|
||||||
|
}
|
||||||
|
|
||||||
if SetKernel != "" {
|
if SetKernel != "" {
|
||||||
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel to: %s\n", p.Id.Get(), SetKernel)
|
wwlog.Printf(wwlog.VERBOSE, "Profile: %s, Setting Kernel to: %s\n", p.Id.Get(), SetKernel)
|
||||||
p.KernelVersion.Set(SetKernel)
|
p.KernelVersion.Set(SetKernel)
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ var (
|
|||||||
SetKey string
|
SetKey string
|
||||||
SetValue string
|
SetValue string
|
||||||
SetKeyDel bool
|
SetKeyDel bool
|
||||||
|
SetAssetKey string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -90,6 +91,7 @@ func init() {
|
|||||||
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
|
baseCmd.PersistentFlags().StringVarP(&SetIpxe, "ipxe", "P", "", "Set the node's iPXE template name")
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container")
|
baseCmd.PersistentFlags().StringVarP(&SetInit, "init", "i", "", "Define the init process to boot the container")
|
||||||
baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs")
|
baseCmd.PersistentFlags().StringVar(&SetRoot, "root", "", "Define the rootfs")
|
||||||
|
baseCmd.PersistentFlags().StringVar(&SetAssetKey, "assetkey", "", "Set the node's Asset tag (key)")
|
||||||
|
|
||||||
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
|
baseCmd.PersistentFlags().StringVarP(&SetRuntimeOverlay, "runtime", "R", "", "Set the node's runtime overlay")
|
||||||
if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
if err := baseCmd.RegisterFlagCompletionFunc("runtime", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
|||||||
n.SystemOverlay.Set(node.SystemOverlay)
|
n.SystemOverlay.Set(node.SystemOverlay)
|
||||||
n.RuntimeOverlay.Set(node.RuntimeOverlay)
|
n.RuntimeOverlay.Set(node.RuntimeOverlay)
|
||||||
n.Root.Set(node.Root)
|
n.Root.Set(node.Root)
|
||||||
|
n.AssetKey.Set(node.AssetKey)
|
||||||
|
|
||||||
n.Discoverable.SetB(node.Discoverable)
|
n.Discoverable.SetB(node.Discoverable)
|
||||||
|
|
||||||
@@ -142,11 +143,11 @@ func (config *nodeYaml) FindAllNodes() ([]NodeInfo, error) {
|
|||||||
n.IpmiInterface.SetAlt(config.NodeProfiles[p].IpmiInterface, p)
|
n.IpmiInterface.SetAlt(config.NodeProfiles[p].IpmiInterface, p)
|
||||||
n.SystemOverlay.SetAlt(config.NodeProfiles[p].SystemOverlay, p)
|
n.SystemOverlay.SetAlt(config.NodeProfiles[p].SystemOverlay, p)
|
||||||
n.RuntimeOverlay.SetAlt(config.NodeProfiles[p].RuntimeOverlay, p)
|
n.RuntimeOverlay.SetAlt(config.NodeProfiles[p].RuntimeOverlay, p)
|
||||||
|
n.Root.SetAlt(config.NodeProfiles[p].Root, p)
|
||||||
|
n.AssetKey.SetAlt(config.NodeProfiles[p].AssetKey, p)
|
||||||
|
|
||||||
n.Discoverable.SetAltB(config.NodeProfiles[p].Discoverable, p)
|
n.Discoverable.SetAltB(config.NodeProfiles[p].Discoverable, p)
|
||||||
|
|
||||||
n.Root.SetAlt(config.NodeProfiles[p].Root, p)
|
|
||||||
|
|
||||||
for devname, netdev := range config.NodeProfiles[p].NetDevs {
|
for devname, netdev := range config.NodeProfiles[p].NetDevs {
|
||||||
if _, ok := n.NetDevs[devname]; !ok {
|
if _, ok := n.NetDevs[devname]; !ok {
|
||||||
var netdev NetDevEntry
|
var netdev NetDevEntry
|
||||||
@@ -216,6 +217,7 @@ func (config *nodeYaml) FindAllProfiles() ([]NodeInfo, error) {
|
|||||||
p.RuntimeOverlay.Set(profile.RuntimeOverlay)
|
p.RuntimeOverlay.Set(profile.RuntimeOverlay)
|
||||||
p.SystemOverlay.Set(profile.SystemOverlay)
|
p.SystemOverlay.Set(profile.SystemOverlay)
|
||||||
p.Root.Set(profile.Root)
|
p.Root.Set(profile.Root)
|
||||||
|
p.AssetKey.Set(profile.AssetKey)
|
||||||
|
|
||||||
p.Discoverable.SetB(profile.Discoverable)
|
p.Discoverable.SetB(profile.Discoverable)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ type NodeConf struct {
|
|||||||
SystemOverlay string `yaml:"system overlay,omitempty"`
|
SystemOverlay string `yaml:"system overlay,omitempty"`
|
||||||
Init string `yaml:"init,omitempty"`
|
Init string `yaml:"init,omitempty"`
|
||||||
Root string `yaml:"root,omitempty"`
|
Root string `yaml:"root,omitempty"`
|
||||||
|
AssetKey string `yaml:"asset key,omitempty"`
|
||||||
Discoverable bool `yaml:"discoverable,omitempty"`
|
Discoverable bool `yaml:"discoverable,omitempty"`
|
||||||
Profiles []string `yaml:"profiles,omitempty"`
|
Profiles []string `yaml:"profiles,omitempty"`
|
||||||
NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"`
|
NetDevs map[string]*NetDevs `yaml:"network devices,omitempty"`
|
||||||
@@ -85,6 +86,7 @@ type NodeInfo struct {
|
|||||||
Root Entry
|
Root Entry
|
||||||
Discoverable Entry
|
Discoverable Entry
|
||||||
Init Entry //TODO: Finish adding this...
|
Init Entry //TODO: Finish adding this...
|
||||||
|
AssetKey Entry
|
||||||
Profiles []string
|
Profiles []string
|
||||||
GroupProfiles []string
|
GroupProfiles []string
|
||||||
NetDevs map[string]*NetDevEntry
|
NetDevs map[string]*NetDevEntry
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ func (config *nodeYaml) NodeUpdate(node NodeInfo) error {
|
|||||||
config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
|
config.Nodes[nodeID].RuntimeOverlay = node.RuntimeOverlay.GetReal()
|
||||||
config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
|
config.Nodes[nodeID].SystemOverlay = node.SystemOverlay.GetReal()
|
||||||
config.Nodes[nodeID].Root = node.Root.GetReal()
|
config.Nodes[nodeID].Root = node.Root.GetReal()
|
||||||
|
config.Nodes[nodeID].AssetKey = node.AssetKey.GetReal()
|
||||||
|
|
||||||
config.Nodes[nodeID].Discoverable = node.Discoverable.GetRealB()
|
config.Nodes[nodeID].Discoverable = node.Discoverable.GetRealB()
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ func (config *nodeYaml) ProfileUpdate(profile NodeInfo) error {
|
|||||||
config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetReal()
|
config.NodeProfiles[profileID].RuntimeOverlay = profile.RuntimeOverlay.GetReal()
|
||||||
config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetReal()
|
config.NodeProfiles[profileID].SystemOverlay = profile.SystemOverlay.GetReal()
|
||||||
config.NodeProfiles[profileID].Root = profile.Root.GetReal()
|
config.NodeProfiles[profileID].Root = profile.Root.GetReal()
|
||||||
|
config.NodeProfiles[profileID].AssetKey = profile.AssetKey.GetReal()
|
||||||
|
|
||||||
config.NodeProfiles[profileID].Discoverable = profile.Discoverable.GetRealB()
|
config.NodeProfiles[profileID].Discoverable = profile.Discoverable.GetRealB()
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func ContainerSend(w http.ResponseWriter, req *http.Request) {
|
func ContainerSend(w http.ResponseWriter, req *http.Request) {
|
||||||
node, err := getSanity(req)
|
rinfo, err := parseReq(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
daemonLogf("ERROR: %s\n", err)
|
daemonLogf("ERROR: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
|
updateStatus(node.Id.Get(), "CONTAINER", "BAD_ASSET", rinfo.ipaddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if node.ContainerName.Defined() {
|
if node.ContainerName.Defined() {
|
||||||
containerImage := container.ImageFile(node.ContainerName.Get())
|
containerImage := container.ImageFile(node.ContainerName.Get())
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ package warewulfd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"log/syslog"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/version"
|
"github.com/hpcng/warewulf/internal/pkg/version"
|
||||||
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +22,39 @@ const (
|
|||||||
WAREWULFD_LOGFILE = "/var/log/warewulfd.log"
|
WAREWULFD_LOGFILE = "/var/log/warewulfd.log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var logwriter *syslog.Writer
|
||||||
|
var loginit bool
|
||||||
|
|
||||||
|
func daemonLogf(message string, a ...interface{}) {
|
||||||
|
conf, err := warewulfconf.New()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Warewulf.Syslog {
|
||||||
|
if !loginit {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
logwriter, err = syslog.New(syslog.LOG_NOTICE, "warewulfd")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.SetOutput(logwriter)
|
||||||
|
loginit = true
|
||||||
|
|
||||||
|
log.SetFlags(0)
|
||||||
|
log.SetPrefix("")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf(message, a...)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
prefix := fmt.Sprintf("[%s] ", time.Now().Format(time.UnixDate))
|
||||||
|
fmt.Printf(prefix+message, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func DaemonStart() error {
|
func DaemonStart() error {
|
||||||
if os.Getenv("WAREWULFD_BACKGROUND") == "1" {
|
if os.Getenv("WAREWULFD_BACKGROUND") == "1" {
|
||||||
err := RunServer()
|
err := RunServer()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/buildconfig"
|
"github.com/hpcng/warewulf/internal/pkg/buildconfig"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
nodepkg "github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
"github.com/hpcng/warewulf/internal/pkg/wwlog"
|
||||||
@@ -30,18 +30,6 @@ type iPxeTemplate struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
url := strings.Split(req.URL.Path, "/")
|
|
||||||
var unconfiguredNode bool
|
|
||||||
|
|
||||||
if url[2] == "" {
|
|
||||||
daemonLogf("ERROR: Bad iPXE request from %s\n", req.RemoteAddr)
|
|
||||||
w.WriteHeader(404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
|
||||||
|
|
||||||
conf, err := warewulfconf.New()
|
conf, err := warewulfconf.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("ERROR: Could not open Warewulf configuration: %s\n", err)
|
daemonLogf("ERROR: Could not open Warewulf configuration: %s\n", err)
|
||||||
@@ -49,44 +37,51 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeobj, err := GetNode(hwaddr)
|
rinfo, err := parseReq(req)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If we failed to find a node, let's see if we can add one...
|
// If we failed to find a node, let's see if we can add one...
|
||||||
var netdev string
|
var netdev string
|
||||||
|
var unconfiguredNode bool
|
||||||
|
|
||||||
nodeDB, err := node.New()
|
daemonLogf("IPXEREQ: %s (node not configured)\n", rinfo.hwaddr)
|
||||||
|
|
||||||
|
nodeDB, err := nodepkg.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("Could not read node configuration file: %s\n", err)
|
daemonLogf("Could not read node configuration file: %s\n", err)
|
||||||
w.WriteHeader(503)
|
w.WriteHeader(503)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
daemonLogf("IPXEREQ: %s (node not configured)\n", hwaddr)
|
|
||||||
|
|
||||||
n, netdev, err := nodeDB.FindDiscoverableNode()
|
n, netdev, err := nodeDB.FindDiscoverableNode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
unconfiguredNode = true
|
unconfiguredNode = true
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
n.NetDevs[netdev].Hwaddr.Set(hwaddr)
|
n.NetDevs[netdev].Hwaddr.Set(rinfo.hwaddr)
|
||||||
n.Discoverable.SetB(false)
|
n.Discoverable.SetB(false)
|
||||||
err := nodeDB.NodeUpdate(n)
|
err := nodeDB.NodeUpdate(n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("IPXEREQ: %s (failed to set node configuration)\n", hwaddr)
|
daemonLogf("IPXEREQ: %s (failed to set node configuration)\n", rinfo.hwaddr)
|
||||||
|
|
||||||
unconfiguredNode = true
|
unconfiguredNode = true
|
||||||
} else {
|
} else {
|
||||||
err := nodeDB.Persist()
|
err := nodeDB.Persist()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("IPXEREQ: %s (failed to persist node configuration)\n", hwaddr)
|
daemonLogf("IPXEREQ: %s (failed to persist node configuration)\n", rinfo.hwaddr)
|
||||||
|
|
||||||
unconfiguredNode = true
|
unconfiguredNode = true
|
||||||
} else {
|
} else {
|
||||||
nodeobj = n
|
node = n
|
||||||
_ = overlay.BuildAllOverlays([]node.NodeInfo{n})
|
_ = overlay.BuildAllOverlays([]nodepkg.NodeInfo{n})
|
||||||
|
|
||||||
daemonLogf("IPXEREQ: %s (node automatically configured)\n", hwaddr)
|
daemonLogf("IPXEREQ: %s (node automatically configured)\n", rinfo.hwaddr)
|
||||||
|
|
||||||
err := LoadNodeDB()
|
err := LoadNodeDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -96,60 +91,65 @@ func IpxeSend(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if unconfiguredNode {
|
||||||
|
daemonLogf("IPXEREQ: %s (unknown/unconfigured node)\n", rinfo.hwaddr)
|
||||||
|
|
||||||
|
tmpl, err := template.ParseFiles(path.Join(buildconfig.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe"))
|
||||||
|
if err != nil {
|
||||||
|
daemonLogf("ERROR: Could not parse unconfigured node IPXE template: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var replace iPxeTemplate
|
||||||
|
|
||||||
|
replace.Hwaddr = rinfo.hwaddr
|
||||||
|
|
||||||
|
err = tmpl.Execute(w, replace)
|
||||||
|
if err != nil {
|
||||||
|
daemonLogf("ERROR: Could not update unconfigured node IPXE template: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if unconfiguredNode {
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
daemonLogf("IPXEREQ: %s (unknown/unconfigured node)\n", hwaddr)
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
tmpl, err := template.ParseFiles(path.Join(buildconfig.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe"))
|
updateStatus(node.Id.Get(), "IPXE", "BAD_ASSET", rinfo.ipaddr)
|
||||||
if err != nil {
|
|
||||||
daemonLogf("ERROR: Could not parse unconfigured node IPXE template: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var replace iPxeTemplate
|
|
||||||
|
|
||||||
replace.Hwaddr = hwaddr
|
|
||||||
|
|
||||||
err = tmpl.Execute(w, replace)
|
|
||||||
if err != nil {
|
|
||||||
daemonLogf("ERROR: Could not update unconfigured node IPXE template: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
ipxeTemplate := path.Join(buildconfig.SYSCONFDIR(), "warewulf/ipxe/"+nodeobj.Ipxe.Get()+".ipxe")
|
|
||||||
|
|
||||||
tmpl, err := template.ParseFiles(ipxeTemplate)
|
|
||||||
if err != nil {
|
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var replace iPxeTemplate
|
|
||||||
|
|
||||||
replace.Id = nodeobj.Id.Get()
|
|
||||||
replace.Cluster = nodeobj.ClusterName.Get()
|
|
||||||
replace.Fqdn = nodeobj.Id.Get()
|
|
||||||
replace.Ipaddr = conf.Ipaddr
|
|
||||||
replace.Port = strconv.Itoa(conf.Warewulf.Port)
|
|
||||||
replace.Hostname = nodeobj.Id.Get()
|
|
||||||
replace.Hwaddr = url[2]
|
|
||||||
replace.ContainerName = nodeobj.ContainerName.Get()
|
|
||||||
replace.KernelArgs = nodeobj.KernelArgs.Get()
|
|
||||||
replace.KernelVersion = nodeobj.KernelVersion.Get()
|
|
||||||
|
|
||||||
err = tmpl.Execute(w, replace)
|
|
||||||
if err != nil {
|
|
||||||
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
daemonLogf("SEND: %15s: %s\n", nodeobj.Id.Get(), ipxeTemplate)
|
|
||||||
|
|
||||||
updateStatus(nodeobj.Id.Get(), "IPXE_TEMPLATE", nodeobj.Ipxe.Get()+".ipxe", strings.Split(req.RemoteAddr, ":")[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipxeTemplate := path.Join(buildconfig.SYSCONFDIR(), "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe")
|
||||||
|
|
||||||
|
tmpl, err := template.ParseFiles(ipxeTemplate)
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var replace iPxeTemplate
|
||||||
|
|
||||||
|
replace.Id = node.Id.Get()
|
||||||
|
replace.Cluster = node.ClusterName.Get()
|
||||||
|
replace.Fqdn = node.Id.Get()
|
||||||
|
replace.Ipaddr = conf.Ipaddr
|
||||||
|
replace.Port = strconv.Itoa(conf.Warewulf.Port)
|
||||||
|
replace.Hostname = node.Id.Get()
|
||||||
|
replace.Hwaddr = rinfo.hwaddr
|
||||||
|
replace.ContainerName = node.ContainerName.Get()
|
||||||
|
replace.KernelArgs = node.KernelArgs.Get()
|
||||||
|
replace.KernelVersion = node.KernelVersion.Get()
|
||||||
|
|
||||||
|
err = tmpl.Execute(w, replace)
|
||||||
|
if err != nil {
|
||||||
|
wwlog.Printf(wwlog.ERROR, "%s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
daemonLogf("SEND: %15s: %s\n", node.Id.Get(), ipxeTemplate)
|
||||||
|
|
||||||
|
updateStatus(node.Id.Get(), "IPXE", node.Ipxe.Get()+".ipxe", strings.Split(req.RemoteAddr, ":")[0])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func KernelSend(w http.ResponseWriter, req *http.Request) {
|
func KernelSend(w http.ResponseWriter, req *http.Request) {
|
||||||
node, err := getSanity(req)
|
rinfo, err := parseReq(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
daemonLogf("ERROR: %s\n", err)
|
daemonLogf("ERROR: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
|
updateStatus(node.Id.Get(), "KERNEL", "BAD_ASSET", rinfo.ipaddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if node.KernelVersion.Defined() {
|
if node.KernelVersion.Defined() {
|
||||||
fileName := kernel.KernelImage(node.KernelVersion.Get())
|
fileName := kernel.KernelImage(node.KernelVersion.Get())
|
||||||
|
|||||||
@@ -8,13 +8,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func KmodsSend(w http.ResponseWriter, req *http.Request) {
|
func KmodsSend(w http.ResponseWriter, req *http.Request) {
|
||||||
|
rinfo, err := parseReq(req)
|
||||||
node, err := getSanity(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(404)
|
w.WriteHeader(404)
|
||||||
daemonLogf("ERROR: %s\n", err)
|
daemonLogf("ERROR: %s\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
|
updateStatus(node.Id.Get(), "KMODS_OVERLAY", "BAD_ASSET", rinfo.ipaddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if node.KernelVersion.Defined() {
|
if node.KernelVersion.Defined() {
|
||||||
fileName := kernel.KmodsImage(node.KernelVersion.Get())
|
fileName := kernel.KmodsImage(node.KernelVersion.Get())
|
||||||
|
|||||||
50
internal/pkg/warewulfd/parser.go
Normal file
50
internal/pkg/warewulfd/parser.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package warewulfd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type parserInfo struct {
|
||||||
|
hwaddr string
|
||||||
|
ipaddr string
|
||||||
|
remoteport int
|
||||||
|
assetkey string
|
||||||
|
uuid string
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseReq(req *http.Request) (parserInfo, error) {
|
||||||
|
var ret parserInfo
|
||||||
|
|
||||||
|
url := strings.Split(req.URL.Path, "?")[0]
|
||||||
|
hwaddr := strings.Split(url, "/")[2]
|
||||||
|
hwaddr = strings.ReplaceAll(hwaddr, "-", ":")
|
||||||
|
hwaddr = strings.ToLower(hwaddr)
|
||||||
|
|
||||||
|
ret.hwaddr = hwaddr
|
||||||
|
ret.ipaddr = strings.Split(req.RemoteAddr, ":")[0]
|
||||||
|
ret.remoteport, _ = strconv.Atoi(strings.Split(req.RemoteAddr, ":")[1])
|
||||||
|
|
||||||
|
if len(req.URL.Query()["assetkey"]) > 0 {
|
||||||
|
ret.assetkey = req.URL.Query()["assetkey"][0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.URL.Query()["uuid"]) > 0 {
|
||||||
|
ret.uuid = req.URL.Query()["uuid"][0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret.hwaddr == "" {
|
||||||
|
return ret, errors.New("no hwaddr encoded in GET")
|
||||||
|
}
|
||||||
|
if ret.ipaddr == "" {
|
||||||
|
return ret, errors.New("could not obtain ipaddr from HTTP request")
|
||||||
|
}
|
||||||
|
if ret.remoteport == 0 {
|
||||||
|
return ret, errors.New("could not obtain remote port from HTTP request: " + req.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
@@ -2,16 +2,35 @@ package warewulfd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
nodepkg "github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
|
func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
|
||||||
|
rinfo, err := parseReq(req)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
|
updateStatus(node.Id.Get(), "RUNTIME_OVERLAY", "BAD_ASSET", rinfo.ipaddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
conf, err := warewulfconf.New()
|
conf, err := warewulfconf.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
daemonLogf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
||||||
@@ -19,68 +38,33 @@ func RuntimeOverlaySend(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes, err := node.New()
|
|
||||||
if err != nil {
|
|
||||||
daemonLogf("ERROR: Could not read node configuration file: %s\n", err)
|
|
||||||
w.WriteHeader(503)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
remote := strings.Split(req.RemoteAddr, ":")
|
|
||||||
port, err := strconv.Atoi(remote[1])
|
|
||||||
if err != nil {
|
|
||||||
daemonLogf("ERROR: Could not convert port to integer: %s\n", remote[1])
|
|
||||||
w.WriteHeader(503)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
daemonLogf("ERROR: Could not load configuration file: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.Warewulf.Secure {
|
if conf.Warewulf.Secure {
|
||||||
if port >= 1024 {
|
if rinfo.remoteport >= 1024 {
|
||||||
daemonLogf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
|
daemonLogf("DENIED: Connection coming from non-privledged port: %s\n", req.RemoteAddr)
|
||||||
w.WriteHeader(401)
|
w.WriteHeader(401)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := nodes.FindByIpaddr(remote[0])
|
if node.RuntimeOverlay.Defined() {
|
||||||
if err != nil {
|
fileName := overlay.OverlayImage(node.Id.Get(), node.RuntimeOverlay.Get())
|
||||||
daemonLogf("WARNING: Could not find node by IP address: %s\n", remote[0])
|
|
||||||
w.WriteHeader(404)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !n.Id.Defined() {
|
|
||||||
daemonLogf("REQ: %15s: %s (unknown/unconfigured node)\n", n.Id.Get(), req.URL.Path)
|
|
||||||
w.WriteHeader(404)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
daemonLogf("REQ: %15s: %s\n", n.Id.Get(), req.URL.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.RuntimeOverlay.Defined() {
|
|
||||||
fileName := overlay.OverlayImage(n.Id.Get(), n.RuntimeOverlay.Get())
|
|
||||||
|
|
||||||
if conf.Warewulf.AutobuildOverlays {
|
if conf.Warewulf.AutobuildOverlays {
|
||||||
if !util.IsFile(fileName) || util.PathIsNewer(fileName, node.ConfigFile) || util.PathIsNewer(fileName, overlay.OverlaySourceDir(n.RuntimeOverlay.Get())) {
|
if !util.IsFile(fileName) || util.PathIsNewer(fileName, nodepkg.ConfigFile) || util.PathIsNewer(fileName, overlay.OverlaySourceDir(node.RuntimeOverlay.Get())) {
|
||||||
daemonLogf("BUILD: %15s: Runtime Overlay\n", n.Id.Get())
|
daemonLogf("BUILD: %15s: Runtime Overlay\n", node.Id.Get())
|
||||||
_ = overlay.BuildOverlay(n, n.RuntimeOverlay.Get())
|
_ = overlay.BuildOverlay(node, node.RuntimeOverlay.Get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := sendFile(w, fileName, n.Id.Get())
|
err := sendFile(w, fileName, node.Id.Get())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("ERROR: %s\n", err)
|
daemonLogf("ERROR: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(n.Id.Get(), "RUNTIME_OVERLAY", n.RuntimeOverlay.Get()+".img", strings.Split(req.RemoteAddr, ":")[0])
|
updateStatus(node.Id.Get(), "RUNTIME_OVERLAY", node.RuntimeOverlay.Get()+".img", strings.Split(req.RemoteAddr, ":")[0])
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(503)
|
w.WriteHeader(503)
|
||||||
daemonLogf("WARNING: No 'runtime system-overlay' set for node %s\n", n.Id.Get())
|
daemonLogf("WARNING: No 'runtime overlay' set for node %s\n", node.Id.Get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,33 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
nodepkg "github.com/hpcng/warewulf/internal/pkg/node"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
"github.com/hpcng/warewulf/internal/pkg/overlay"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/util"
|
"github.com/hpcng/warewulf/internal/pkg/util"
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SystemOverlaySend(w http.ResponseWriter, req *http.Request) {
|
func SystemOverlaySend(w http.ResponseWriter, req *http.Request) {
|
||||||
|
rinfo, err := parseReq(req)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
node, err := GetNode(rinfo.hwaddr)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(403)
|
||||||
|
daemonLogf("ERROR(%s): %s\n", rinfo.hwaddr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.AssetKey.Defined() && node.AssetKey.Get() != rinfo.assetkey {
|
||||||
|
w.WriteHeader(404)
|
||||||
|
daemonLogf("ERROR: Incorrect asset key for node: %s\n", node.Id.Get())
|
||||||
|
updateStatus(node.Id.Get(), "SYSTEM_OVERLAY", "BAD_ASSET", rinfo.ipaddr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
conf, err := warewulfconf.New()
|
conf, err := warewulfconf.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
daemonLogf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
||||||
@@ -18,32 +38,25 @@ func SystemOverlaySend(w http.ResponseWriter, req *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := getSanity(req)
|
if node.SystemOverlay.Defined() {
|
||||||
if err != nil {
|
fileName := overlay.OverlayImage(node.Id.Get(), node.SystemOverlay.Get())
|
||||||
w.WriteHeader(404)
|
|
||||||
daemonLogf("ERROR: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.SystemOverlay.Defined() {
|
|
||||||
fileName := overlay.OverlayImage(n.Id.Get(), n.SystemOverlay.Get())
|
|
||||||
|
|
||||||
if conf.Warewulf.AutobuildOverlays {
|
if conf.Warewulf.AutobuildOverlays {
|
||||||
if !util.IsFile(fileName) || util.PathIsNewer(fileName, node.ConfigFile) || util.PathIsNewer(fileName, overlay.OverlaySourceDir(n.SystemOverlay.Get())) {
|
if !util.IsFile(fileName) || util.PathIsNewer(fileName, nodepkg.ConfigFile) || util.PathIsNewer(fileName, overlay.OverlaySourceDir(node.SystemOverlay.Get())) {
|
||||||
daemonLogf("BUILD: %15s: System Overlay\n", n.Id.Get())
|
daemonLogf("BUILD: %15s: System Overlay\n", node.Id.Get())
|
||||||
_ = overlay.BuildOverlay(n, n.SystemOverlay.Get())
|
_ = overlay.BuildOverlay(node, node.SystemOverlay.Get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := sendFile(w, fileName, n.Id.Get())
|
err := sendFile(w, fileName, node.Id.Get())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
daemonLogf("ERROR: %s\n", err)
|
daemonLogf("ERROR: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStatus(n.Id.Get(), "SYSTEM_OVERLAY", n.SystemOverlay.Get()+".img", strings.Split(req.RemoteAddr, ":")[0])
|
updateStatus(node.Id.Get(), "SYSTEM_OVERLAY", node.SystemOverlay.Get()+".img", strings.Split(req.RemoteAddr, ":")[0])
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
w.WriteHeader(503)
|
w.WriteHeader(503)
|
||||||
daemonLogf("WARNING: No 'system system-overlay' set for node %s\n", n.Id.Get())
|
daemonLogf("WARNING: No 'system system-overlay' set for node %s\n", node.Id.Get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,14 @@
|
|||||||
package warewulfd
|
package warewulfd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"log/syslog"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/node"
|
|
||||||
"github.com/hpcng/warewulf/internal/pkg/warewulfconf"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var logwriter *syslog.Writer
|
|
||||||
var loginit bool
|
|
||||||
|
|
||||||
func daemonLogf(message string, a ...interface{}) {
|
|
||||||
conf, err := warewulfconf.New()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("ERROR: Could not read Warewulf configuration file: %s\n", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if conf.Warewulf.Syslog {
|
|
||||||
if !loginit {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
logwriter, err = syslog.New(syslog.LOG_NOTICE, "warewulfd")
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.SetOutput(logwriter)
|
|
||||||
loginit = true
|
|
||||||
|
|
||||||
log.SetFlags(0)
|
|
||||||
log.SetPrefix("")
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf(message, a...)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
prefix := fmt.Sprintf("[%s] ", time.Now().Format(time.UnixDate))
|
|
||||||
fmt.Printf(prefix+message, a...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSanity(req *http.Request) (node.NodeInfo, error) {
|
|
||||||
url := strings.Split(req.URL.Path, "/")
|
|
||||||
|
|
||||||
hwaddr := strings.ReplaceAll(url[2], "-", ":")
|
|
||||||
|
|
||||||
nodeobj, err := GetNode(hwaddr)
|
|
||||||
if err != nil {
|
|
||||||
var ret node.NodeInfo
|
|
||||||
return ret, errors.New("Could not find node by HW address: " + req.URL.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
daemonLogf("REQ: %15s: %s\n", nodeobj.Id.Get(), req.URL.Path)
|
|
||||||
|
|
||||||
return nodeobj, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendFile(w http.ResponseWriter, filename string, sendto string) error {
|
func sendFile(w http.ResponseWriter, filename string, sendto string) error {
|
||||||
fd, err := os.Open(filename)
|
fd, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user