From c9c8a683a7a896a20178566234dec7aba56788e7 Mon Sep 17 00:00:00 2001 From: jcsiadal Date: Sat, 5 Feb 2022 02:26:17 +0000 Subject: [PATCH 1/4] Updates specfile to match distro guidelines. Suppots modifying client directory path at build time. - Support relocating client files at build time (required for LSB compliant nodes) - OS varable added to perform some make choices - Saving and exporting the Makefile vars now scripted using list of variables - Updated specfile to match RH and SUSE requirements and guidelines - Moved /usr/local/var to /var/local; dynamic files shall not use /usr. - State files use %sharedstatedir for path (std for SLE and RHEL) - Release value adjusted to meet different DEB and RPM reqs. Signed-off-by: jcsiadal --- Defaults.mk.in | 13 -- Makefile | 165 +++++++++--------- internal/app/wwclient/root.go | 12 +- internal/pkg/buildconfig/defaults.go | 13 +- internal/pkg/buildconfig/setconfigs.go.in | 2 + .../{wwinit/warewulf => wwclient}/config.ww | 0 .../init.d/20-loopback.in} | 2 +- .../50-ipmi => wwclient/init.d/50-ipmi.in} | 2 +- .../init.d/75-vnfs_fixes.in} | 2 +- .../init.d/80-wwclient.in} | 4 +- .../init.d/90-selinux.in} | 2 +- .../warewulf/wwinit => wwclient/wwinit.in} | 4 +- .../{wwclient.service => wwclient.service.in} | 2 +- overlays/wwinit/{init => init.in} | 10 +- warewulf.spec.in | 78 +++++---- 15 files changed, 164 insertions(+), 147 deletions(-) delete mode 100644 Defaults.mk.in rename overlays/{wwinit/warewulf => wwclient}/config.ww (100%) rename overlays/{wwinit/warewulf/init.d/20-loopback => wwclient/init.d/20-loopback.in} (75%) rename overlays/{wwinit/warewulf/init.d/50-ipmi => wwclient/init.d/50-ipmi.in} (99%) rename overlays/{wwinit/warewulf/init.d/75-vnfs_fixes => wwclient/init.d/75-vnfs_fixes.in} (96%) rename overlays/{wwinit/warewulf/init.d/80-wwclient => wwclient/init.d/80-wwclient.in} (59%) rename overlays/{wwinit/warewulf/init.d/90-selinux => wwclient/init.d/90-selinux.in} (97%) rename overlays/{wwinit/warewulf/wwinit => wwclient/wwinit.in} (73%) rename overlays/wwinit/etc/systemd/system/{wwclient.service => wwclient.service.in} (88%) rename overlays/wwinit/{init => init.in} (88%) diff --git a/Defaults.mk.in b/Defaults.mk.in deleted file mode 100644 index a344bdf8..00000000 --- a/Defaults.mk.in +++ /dev/null @@ -1,13 +0,0 @@ -VERSION ?= @VERSION@ -RELEASE ?= @RELEASE@ -PREFIX ?= @PREFIX@ -BINDIR ?= @BINDIR@ -SYSCONFDIR ?= @SYSCONFDIR@ -SRVDIR ?= @SRVDIR@ -DATADIR ?= @DATADIR@ -MANDIR ?= @MANDIR@ -LOCALSTATEDIR ?= @LOCALSTATEDIR@ -TFTPDIR ?= @TFTPDIR@ -FIREWALLDDIR ?= @FIREWALLDDIR@ -SYSTEMDDIR ?= @SYSTEMDDIR@ -BASH_COMPLETION ?= @BASH_COMPLETION@ diff --git a/Makefile b/Makefile index 639cb5e6..e7ecbcce 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,69 @@ .PHONY: all +# Linux distro (set to /etc/os-release ID) +OS ?= rocky + +# List of variables to save or replace in files +VARLIST := OS + -include Defaults.mk +# Project Information +VARLIST += WAREWULF VERSION RELEASE +WAREWULF ?= warewulf VERSION ?= 4.2.0 GIT_TAG := $(shell test -e .git && git describe --tags --long --first-parent --always) ifndef $(GIT_TAG) - RELEASE ?= 1.git_$(GIT_TAG) + ifdef $(filter $(OS),ubuntu debian) + RELEASE ?= 1.git_$(subst -,+,$(GIT_TAG)) + else + RELEASE ?= 1.git_$(subst -,_,$(GIT_TAG)) + endif else - RELEASE ?= 1 + RELEASE ?= 1 endif -# System locations +# System directory paths +VARLIST += PREFIX BINDIR SYSCONFDIR SRVDIR DATADIR MANDIR DOCDIR LOCALSTATEDIR SHAREDSTATEDIR PREFIX ?= /usr/local BINDIR ?= $(PREFIX)/bin SYSCONFDIR ?= $(PREFIX)/etc -SRVDIR ?= $(PREFIX)/srv +SRVDIR ?= /srv DATADIR ?= $(PREFIX)/share MANDIR ?= $(DATADIR)/man +<<<<<<< HEAD LOCALSTATEDIR ?= $(PREFIX)/var WWCLIENTLOC ?= /warewulf/bin +======= +DOCDIR ?= $(DATADIR)/doc +LOCALSTATEDIR ?= /var +SHAREDSTATEDIR ?= /var/local + +# OS-Specific Service Locations +VARLIST += TFTPDIR FIREWALLDDIR SYSTEMDDIR +ifeq ($(OS),suse) +TFTPDIR ?= /srv/tftpboot +endif +ifeq ($(OS),ubuntu) +TFTPDIR ?= /srv/tftp +endif +>>>>>>> 7b0a40a... Updates specfile to match distro guidelines. Suppots modifying client directory path at build time. TFTPDIR ?= /var/lib/tftpboot FIREWALLDDIR ?= /usr/lib/firewalld/services SYSTEMDDIR ?= /usr/lib/systemd/system -BASH_COMPLETION ?= /etc/bash_completion.d/ +BASHCOMPDIR ?= /etc/bash_completion.d -# Warewulf locations -WWPROVISIONDIR = $(SRVDIR)/warewulf -WWOVERLAYDIR = $(LOCALSTATEDIR)/warewulf/overlays -WWCHROOTDIR = $(LOCALSTATEDIR)/warewulf/chroots - -# SuSE -#TFTPDIR ?= /srv/tftpboot -#FIREWALLDIR ?= /srv/tftp +# Warewulf directory paths +VARLIST += WWCLIENTDIR WWCONFIGDIR WWPROVISIONDIR WWOVERLAYDIR WWCHROOTDIR WWTFTPDIR WWDOCDIR +WWCONFIGDIR := $(SYSCONFDIR)/$(WAREWULF) +WWPROVISIONDIR := $(SHAREDSTATEDIR)/$(WAREWULF) +WWOVERLAYDIR := $(SHAREDSTATEDIR)/$(WAREWULF)/overlays +WWCHROOTDIR := $(SHAREDSTATEDIR)/$(WAREWULF)/chroots +WWTFTPDIR := $(TFTPDIR)/$(WAREWULF) +WWDOCDIR := $(DOCDIR)/$(WAREWULF) +WWCLIENTDIR ?= /warewulf # auto installed tooling TOOLS_DIR := .tools @@ -51,7 +81,7 @@ GOPROXY ?= https://proxy.golang.org export GOPROXY # built tags needed for wwbuild binary -WW_BUILD_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree +WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree all: config vendor wwctl wwclient bash_completion.d man_pages @@ -68,10 +98,8 @@ $(GO_TOOLS_BIN): $(GOLANGCI_LINT): @curl -qq -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOLANGCI_LINT_VERSION) - setup: vendor $(TOOLS_DIR) setup_tools -# vendor vendor: go mod tidy -v go mod vendor @@ -81,27 +109,11 @@ $(TOOLS_DIR): # Pre-build steps for source, such as "go generate" config: - set -x ;\ - for i in `find . -type f -name "*.in" -not -path "./vendor/*"`; do \ - NAME=`echo $$i | sed -e 's,\.in,,'`; \ - sed -e 's,@BINDIR@,$(BINDIR),g' \ - -e 's,@SYSCONFDIR@,$(SYSCONFDIR),g' \ - -e 's,@LOCALSTATEDIR@,$(LOCALSTATEDIR),g' \ - -e 's,@PREFIX@,$(PREFIX),g' \ - -e 's,@DATADIR@,$(DATADIR),g' \ - -e 's,@MANDIR@,$(MANDIR),g' \ - -e 's,@SRVDIR@,$(SRVDIR),g' \ - -e 's,@TFTPDIR@,$(TFTPDIR),g' \ - -e 's,@FIREWALLDDIR@,$(FIREWALLDDIR),g' \ - -e 's,@SYSTEMDDIR@,$(SYSTEMDDIR),g' \ - -e 's,@BASH_COMPLETION@,$(BASH_COMPLETION),g' \ - -e 's,@WWOVERLAYDIR@,$(WWOVERLAYDIR),g' \ - -e 's,@WWCHROOTDIR@,$(WWCHROOTDIR),g' \ - -e 's,@WWPROVISIONDIR@,$(WWPROVISIONDIR),g' \ - -e 's,@VERSION@,$(VERSION),g' \ - -e 's,@WWCLIENTLOC@,$(WWCLIENTLOC),g' \ - -e 's,@RELEASE@,$(RELEASE),g' $$i > $$NAME; \ - done + # Store configuration for subsequent runs + printf " $(foreach V,$(VARLIST),$V := $(strip $($V))\n)" > Defaults.mk + # Global variable search and replace for all *.in files + find . -type f -name "*.in" -not -path "./vendor/*" \ + -exec sh -c 'sed -ne "$(foreach V,$(VARLIST),s,@$V@,$(strip $($V)),g;)p" $${0} > $${0%.in}' {} \; touch config rm_config: @@ -109,11 +121,10 @@ rm_config: genconfig: rm_config config - # Lint lint: setup_tools @echo Running golangci-lint... - @$(GOLANGCI_LINT) run --build-tags "$(WW_BUILD_GO_BUILD_TAGS)" --skip-dirs internal/pkg/staticfiles ./... + @$(GOLANGCI_LINT) run --build-tags "$(WW_GO_BUILD_TAGS)" --skip-dirs internal/pkg/staticfiles ./... vet: go vet ./... @@ -137,98 +148,86 @@ files: all install -d -m 0755 $(DESTDIR)$(BINDIR) install -d -m 0755 $(DESTDIR)$(WWCHROOTDIR) install -d -m 0755 $(DESTDIR)$(WWPROVISIONDIR) - install -d -m 0755 $(DESTDIR)$(WWOVERLAYDIR) - install -d -m 0755 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/warewulf/bin/ - install -d -m 0755 $(DESTDIR)$(SYSCONFDIR)/warewulf/ - install -d -m 0755 $(DESTDIR)$(SYSCONFDIR)/warewulf/ipxe - install -d -m 0755 $(DESTDIR)$(TFTPDIR)/warewulf/ipxe/ - install -d -m 0755 $(DESTDIR)$(BASH_COMPLETION) + install -d -m 0755 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR) + install -d -m 0755 $(DESTDIR)$(WWCONFIGDIR)/ipxe + install -d -m 0755 $(DESTDIR)$(WWTFTPDIR)/ipxe/ + install -d -m 0755 $(DESTDIR)$(BASHCOMPDIR) install -d -m 0755 $(DESTDIR)$(MANDIR)/man1 + install -d -m 0755 $(DESTDIR)$(WWDOCDIR) install -d -m 0755 $(DESTDIR)$(FIREWALLDDIR) install -d -m 0755 $(DESTDIR)$(SYSTEMDDIR) - test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/warewulf.conf || install -m 644 etc/warewulf.conf $(DESTDIR)$(SYSCONFDIR)/warewulf/ - test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/hosts.tmpl || install -m 644 etc/hosts.tmpl $(DESTDIR)$(SYSCONFDIR)/warewulf/ - test -f $(DESTDIR)$(SYSCONFDIR)/warewulf/nodes.conf || install -m 644 etc/nodes.conf $(DESTDIR)$(SYSCONFDIR)/warewulf/ - cp -r etc/dhcp $(DESTDIR)$(SYSCONFDIR)/warewulf/ - cp -r etc/ipxe $(DESTDIR)$(SYSCONFDIR)/warewulf/ - cp -r overlays/* $(DESTDIR)$(WWOVERLAYDIR)/ + test -f $(DESTDIR)$(WWCONFIGDIR)/warewulf.conf || install -m 644 etc/warewulf.conf $(DESTDIR)$(WWCONFIGDIR) + test -f $(DESTDIR)$(WWCONFIGDIR)/hosts.tmpl || install -m 644 etc/hosts.tmpl $(DESTDIR)$(WWCONFIGDIR) + test -f $(DESTDIR)$(WWCONFIGDIR)/nodes.conf || install -m 644 etc/nodes.conf $(DESTDIR)$(WWCONFIGDIR) + cp -r etc/dhcp $(DESTDIR)$(WWCONFIGDIR)/ + cp -r etc/ipxe $(DESTDIR)$(WWCONFIGDIR)/ + cp -r overlays/wwinit $(DESTDIR)$(WWOVERLAYDIR)/ + cp -r overlays/generic $(DESTDIR)$(WWOVERLAYDIR)/ + cp -r overlays/wwclient/* $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/ chmod 755 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/init - chmod 755 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/warewulf/wwinit + rm -f $(DESTDIR)$(WWOVERLAYDIR)/wwinit/init.in + find $(DESTDIR)$(WWOVERLAYDIR) -type f -name "*.in" -exec rm -f {} \; + chmod 755 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/wwinit chmod 600 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/etc/ssh/ssh* chmod 644 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/etc/ssh/ssh*.pub.ww install -m 0755 wwctl $(DESTDIR)$(BINDIR) - install -c -m 0644 include/firewalld/warewulf.xml $(DESTDIR)$(FIREWALLDDIR) - install -c -m 0644 include/systemd/warewulfd.service $(DESTDIR)$(SYSTEMDDIR) - cp bash_completion.d/warewulf $(DESTDIR)$(BASH_COMPLETION) + install -m 0644 include/firewalld/warewulf.xml $(DESTDIR)$(FIREWALLDDIR) + install -m 0644 include/systemd/warewulfd.service $(DESTDIR)$(SYSTEMDDIR) + install -m 0644 LICENSE.md $(DESTDIR)$(WWDOCDIR) + cp bash_completion.d/warewulf $(DESTDIR)$(BASHCOMPDIR) cp man_pages/* $(DESTDIR)$(MANDIR)/man1/ init: systemctl daemon-reload - cp -r tftpboot/* $(TFTPDIR)/warewulf/ipxe/ - restorecon -r $(TFTPDIR)/warewulf - -# Overlay file system has changed -#debfiles: debian -# chmod +x $(DESTDIR)$(WWROOT)/warewulf/overlays/system/debian/init -# chmod 600 $(DESTDIR)$(WWROOT)/warewulf/overlays/system/debian/etc/ssh/ssh* -# chmod 644 $(DESTDIR)$(WWROOT)/warewulf/overlays/system/debian/etc/ssh/ssh*.pub.ww -# mkdir -p $(DESTDIR)$(WWROOT)/warewulf/overlays/system/debian/warewulf/bin/ -# cp wwclient $(DESTDIR)$(WWROOT)/warewulf/overlays/system/debian/warewulf/bin/ + cp -r tftpboot/* $(WWTFTPDIR)/ipxe/ + restorecon -r $(WWTFTPDIR) wwctl: - cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../wwctl + cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../wwctl wwclient: cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ -X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient install_wwclient: wwclient - install -m 0755 wwclient $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTLOC)/wwclient - + install -m 0755 wwclient $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/wwclient bash_completion: cd cmd/bash_completion && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ - -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../bash_completion + -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../bash_completion bash_completion.d: bash_completion install -d -m 0755 bash_completion.d - ./bash_completion bash_completion.d/warewulf + ./bash_completion bash_completion.d/warewulf man_page: cd cmd/man_page && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ - -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../man_page + -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../man_page man_pages: man_page install -d man_pages ./man_page ./man_pages cd man_pages; for i in wwctl*1; do echo "Compressing manpage: $$i"; gzip --force $$i; done -#config_defaults: -# cd cmd/config_defaults && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf' \ -# -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf' \ -# -X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.defaultDataStore=$(WWROOT)/warewulf'" \ -# -mod vendor -tags "$(WW_BUILD_GO_BUILD_TAGS)" -o ../../config_defaults - dist: vendor config - rm -rf .dist/warewulf-$(VERSION) - mkdir -p .dist/warewulf-$(VERSION) - cp -rap * .dist/warewulf-$(VERSION)/ - cd .dist; tar -czf ../warewulf-$(VERSION).tar.gz warewulf-$(VERSION) + rm -rf .dist/$(WAREWULF)-$(VERSION) + mkdir -p .dist/$(WAREWULF)-$(VERSION) + cp -rap * .dist/$(WAREWULF)-$(VERSION)/ + cd .dist; tar -czf ../$(WAREWULF)-$(VERSION).tar.gz $(WAREWULF)-$(VERSION) rm -rf .dist clean: rm -f wwclient rm -f wwctl rm -rf .dist - rm -f warewulf-$(VERSION).tar.gz + rm -f $(WAREWULF)-$(VERSION).tar.gz rm -f bash_completion rm -rf bash_completion.d rm -f man_page rm -rf man_pages rm -rf vendor -# rm -f config_defaults rm -f config rm -f Defaults.mk diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index d25b0fc8..a6d4eba9 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -10,6 +10,7 @@ import ( "os" "os/exec" "os/signal" + "path" "strings" "syscall" "time" @@ -62,7 +63,10 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return errors.New("found pidfile " + PIDFile + " not starting") } - if os.Args[0] == buildconfig.WWCLIENTLOC() { + clientDir := buildconfig.WWCLIENTDIR() + testDir := path.Join(clientDir, "wwclient-test") + + if os.Args[0] == path.Join(clientDir, "wwclient") { err := os.Chdir("/") if err != nil { wwlog.Printf(wwlog.ERROR, "failed to change dir: %s", err) @@ -73,15 +77,15 @@ func CobraRunE(cmd *cobra.Command, args []string) error { time.Sleep(5000 * time.Millisecond) } else { fmt.Printf("Called via: %s\n", os.Args[0]) - fmt.Printf("Runtime overlay is being put in '/warewulf/wwclient-test' rather than '/'\n") - err := os.MkdirAll("/warewulf/wwclient-test", 0755) + fmt.Printf("Runtime overlay is being put in '%s' rather than '/'\n", testDir) + err := os.MkdirAll(testDir, 0755) if err != nil { wwlog.Printf(wwlog.ERROR, "failed to create dir: %s", err) _ = os.Remove(PIDFile) os.Exit(1) } - err = os.Chdir("/warewulf/wwclient-test") + err = os.Chdir(testDir) if err != nil { wwlog.Printf(wwlog.ERROR, "failed to change dir: %s", err) _ = os.Remove(PIDFile) diff --git a/internal/pkg/buildconfig/defaults.go b/internal/pkg/buildconfig/defaults.go index dd4554a1..c14db9b0 100644 --- a/internal/pkg/buildconfig/defaults.go +++ b/internal/pkg/buildconfig/defaults.go @@ -6,6 +6,7 @@ var ( bindir string = "UNDEF" sysconfdir string = "UNDEF" localstatedir string = "UNDEF" + sharedstatedir string = "UNDEF" srvdir string = "UNDEF" tftpdir string = "UNDEF" firewallddir string = "UNDEF" @@ -13,6 +14,7 @@ var ( wwoverlaydir string = "UNDEF" wwchrootdir string = "UNDEF" wwprovisiondir string = "UNDEF" + wwclientdir string = "UNDEF" version string = "UNDEF" release string = "UNDEF" wwclientloc string = "UNDEF" @@ -78,7 +80,12 @@ func RELEASE() string { return release } -func WWCLIENTLOC() string { - wwlog.Printf(wwlog.DEBUG, "WWCLIENTLOC = '%s'\n", wwclientloc) - return wwclientloc +func WWCLIENTDIR() string { + wwlog.Printf(wwlog.DEBUG, "WWPROVISIONDIR = '%s'\n", wwclientdir) + return wwclientdir +} + +func SHAREDSTATEDIR() string { + wwlog.Printf(wwlog.DEBUG, "SHAREDSTATEDIR = '%s'\n", sharedstatedir) + return sharedstatedir } diff --git a/internal/pkg/buildconfig/setconfigs.go.in b/internal/pkg/buildconfig/setconfigs.go.in index 1193a80b..b3ed934d 100644 --- a/internal/pkg/buildconfig/setconfigs.go.in +++ b/internal/pkg/buildconfig/setconfigs.go.in @@ -4,6 +4,7 @@ func init() { bindir = "@BINDIR@" sysconfdir = "@SYSCONFDIR@" localstatedir = "@LOCALSTATEDIR@" + sharedstatedir = "@SHAREDSTATEDIR@" srvdir = "@SRVDIR@" tftpdir = "@TFTPDIR@" firewallddir = "@FIREWALLDDIR@" @@ -11,6 +12,7 @@ func init() { wwoverlaydir = "@WWOVERLAYDIR@" wwchrootdir = "@WWCHROOTDIR@" wwprovisiondir = "@WWPROVISIONDIR@" + wwclientdir = "@WWCLIENTDIR@" version = "@VERSION@" release = "@RELEASE@" wwclientloc = "@WWCLIENTLOC" diff --git a/overlays/wwinit/warewulf/config.ww b/overlays/wwclient/config.ww similarity index 100% rename from overlays/wwinit/warewulf/config.ww rename to overlays/wwclient/config.ww diff --git a/overlays/wwinit/warewulf/init.d/20-loopback b/overlays/wwclient/init.d/20-loopback.in similarity index 75% rename from overlays/wwinit/warewulf/init.d/20-loopback rename to overlays/wwclient/init.d/20-loopback.in index 01791174..70d53815 100644 --- a/overlays/wwinit/warewulf/init.d/20-loopback +++ b/overlays/wwclient/init.d/20-loopback.in @@ -1,6 +1,6 @@ #!/bin/sh -. /warewulf/config +. @WWCLIENTDIR@/config echo "Bringing up lo:127.0.0.1" /sbin/ip link set dev lo up diff --git a/overlays/wwinit/warewulf/init.d/50-ipmi b/overlays/wwclient/init.d/50-ipmi.in similarity index 99% rename from overlays/wwinit/warewulf/init.d/50-ipmi rename to overlays/wwclient/init.d/50-ipmi.in index bfe83eea..4d661fa3 100755 --- a/overlays/wwinit/warewulf/init.d/50-ipmi +++ b/overlays/wwclient/init.d/50-ipmi.in @@ -1,6 +1,6 @@ #!/bin/bash -. /warewulf/config +. @WWCLIENTDIR@/config export PATH=/usr/bin:/bin:/usr/sbin:/sbin diff --git a/overlays/wwinit/warewulf/init.d/75-vnfs_fixes b/overlays/wwclient/init.d/75-vnfs_fixes.in similarity index 96% rename from overlays/wwinit/warewulf/init.d/75-vnfs_fixes rename to overlays/wwclient/init.d/75-vnfs_fixes.in index 5ce5b735..d3f8fe28 100644 --- a/overlays/wwinit/warewulf/init.d/75-vnfs_fixes +++ b/overlays/wwclient/init.d/75-vnfs_fixes.in @@ -1,6 +1,6 @@ #!/bin/sh -. /warewulf/config +. @WWCLIENTDIR@/config # This will eventually be optional if true; then diff --git a/overlays/wwinit/warewulf/init.d/80-wwclient b/overlays/wwclient/init.d/80-wwclient.in similarity index 59% rename from overlays/wwinit/warewulf/init.d/80-wwclient rename to overlays/wwclient/init.d/80-wwclient.in index d0945766..30f704ca 100644 --- a/overlays/wwinit/warewulf/init.d/80-wwclient +++ b/overlays/wwclient/init.d/80-wwclient.in @@ -1,7 +1,7 @@ #!/bin/sh -. /warewulf/config +. @WWCLIENTDIR@/config # Only start if the systemd is no available test -e /usr/lib/systemd/systemd && exit 0 echo "Starting wwclient" -nohup /warewulf/bin/wwclient >/var/log/wwclient.log 2>&1 /var/log/wwclient.log 2>&1 /dev/null echo "Calling switch_root and invoking WW Init" - exec /sbin/switch_root /newroot /warewulf/wwinit + exec /sbin/switch_root /newroot @WWCLIENTDIR@/wwinit fi else echo "ERROR: Unknown Warewulf Root file system: $WWROOT" diff --git a/warewulf.spec.in b/warewulf.spec.in index ab0fbaf7..cc16697d 100644 --- a/warewulf.spec.in +++ b/warewulf.spec.in @@ -1,13 +1,16 @@ -%global wwgroup warewulf -%if 0%{?sle_version} -%global tftpdir "/srv/tftpboot" -%global srvdir "/srv" -%else -%global tftpdir "/var/lib/tftpboot" -%global srvdir "%{_localstatedir}/warewulf/srv" -%endif %define debug_package %{nil} +%if 0%{?sle_version} +%global tftpdir /srv/tftpboot +%global srvdir /srv +%else +# Assume Fedora-based OS if not SUSE-based +%global tftpdir /var/lib/tftpboot +%global srvdir %{_sharedstatedir} +%endif + +%global wwgroup warewulf + Name: warewulf Summary: A provisioning system for large clusters of bare metal and/or virtual systems Version: @VERSION@ @@ -27,17 +30,18 @@ Conflicts: warewulf-ipmi BuildRequires: make -%if 0%{?rhel} -BuildRequires: systemd -BuildRequires: golang -Requires: tftp-server -Requires: nfs-utils -%else -# sle_version +%if 0%{?sle_version} BuildRequires: systemd-rpm-macros BuildRequires: go +BuildRequires: firewall-macros Requires: tftp Requires: nfs-kernel-server +%else +BuildRequires: systemd +BuildRequires: golang +BuildRequires: firewalld-filesystem +Requires: tftp-server +Requires: nfs-utils %endif %if 0%{?rhel} >= 8 || 0%{?sle_version} @@ -57,30 +61,36 @@ system for large clusters of bare metal and/or virtual systems. %build -make genconfig PREFIX=/usr \ - SRVDIR=%{srvdir} \ - LOCALSTATEDIR=%{_localstatedir} \ +make genconfig \ + PREFIX=%{_prefix} \ + BINDIR=%{_bindir} \ SYSCONFDIR=%{_sysconfdir} \ DATADIR=%{_datadir} \ + LOCALSTATEDIR=%{_localstatedir} \ + SHAREDSTATEDIR=%{_sharedstatedir} \ MANDIR=%{_mandir} \ - BINDIR=%{_bindir} \ + INFODIR=%{_infodir} \ + DOCDIR=%{_docdir} \ + SRVDIR=%{srvdir} \ TFTPDIR=%{tftpdir} \ SYSTEMDDIR=%{_unitdir} \ - MANDIR=%{_mandir} \ - BASH_COMPLETION=/etc/bash_completion.d/ \ - FIREWALLDDIR=/usr/lib/firewalld/services - + BASHCOMPDIR=/etc/bash_completion.d/ \ + FIREWALLDDIR=/usr/lib/firewalld/services \ + WWCLIENTDIR=%{_libexecdir}/warewulf make + %install make install DESTDIR=%{buildroot} + %pre getent group %{wwgroup} >/dev/null || groupadd -r %{wwgroup} %post %systemd_post warewulfd.service +%firewalld_reload %preun @@ -89,26 +99,34 @@ getent group %{wwgroup} >/dev/null || groupadd -r %{wwgroup} %postun %systemd_postun_with_restart warewulfd.service +%firewalld_reload %files %defattr(-, root, %{wwgroup}) -%dir %{_sysconfdir}/%{name} -%config(noreplace) %{_sysconfdir}/%{name}/* -%config(noreplace) %attr(0640,-,-) %{_sysconfdir}/%{name}/nodes.conf +%dir %{_sysconfdir}/warewulf +%config(noreplace) %{_sysconfdir}/warewulf/* +%config(noreplace) %attr(0640,-,-) %{_sysconfdir}/warewulf/nodes.conf %{_sysconfdir}/bash_completion.d/warewulf -%dir %{_localstatedir}/warewulf -%{_localstatedir}/warewulf/chroots -%{_localstatedir}/warewulf/overlays -%{srvdir} +%dir %{_sharedstatedir}/warewulf +%{_sharedstatedir}/warewulf/chroots +%{_sharedstatedir}/warewulf/overlays +%{srvdir}/warewulf %attr(-, root, root) %{_bindir}/wwctl %attr(-, root, root) %{_prefix}/lib/firewalld/services/warewulf.xml %attr(-, root, root) %{_unitdir}/warewulfd.service %attr(-, root, root) %{_mandir}/man1/wwctl* +%license %{_docdir}/warewulf/LICENSE.md + + %changelog +* Wed Jan 26 2022 Jeremy Siadal - 4.2.0-1 +- Add license install +- Updates for RH and SUSE RPM guidelines + * Sat Jan 15 2022 Gregory Kurtzer - 4.2.0-1 - Integrated genconfig Make options - Cleaned up SPEC to use default RPM macros From 378dda2ca180da7cce80948cb4d3a05e9232c946 Mon Sep 17 00:00:00 2001 From: jcsiadal Date: Thu, 10 Feb 2022 19:54:09 +0000 Subject: [PATCH 2/4] Rebase updates Signed-off-by: jcsiadal --- Makefile | 6 ------ internal/pkg/buildconfig/defaults.go | 1 - internal/pkg/buildconfig/setconfigs.go.in | 1 - 3 files changed, 8 deletions(-) diff --git a/Makefile b/Makefile index e7ecbcce..33288439 100644 --- a/Makefile +++ b/Makefile @@ -32,11 +32,6 @@ SYSCONFDIR ?= $(PREFIX)/etc SRVDIR ?= /srv DATADIR ?= $(PREFIX)/share MANDIR ?= $(DATADIR)/man -<<<<<<< HEAD -LOCALSTATEDIR ?= $(PREFIX)/var -WWCLIENTLOC ?= /warewulf/bin - -======= DOCDIR ?= $(DATADIR)/doc LOCALSTATEDIR ?= /var SHAREDSTATEDIR ?= /var/local @@ -49,7 +44,6 @@ endif ifeq ($(OS),ubuntu) TFTPDIR ?= /srv/tftp endif ->>>>>>> 7b0a40a... Updates specfile to match distro guidelines. Suppots modifying client directory path at build time. TFTPDIR ?= /var/lib/tftpboot FIREWALLDDIR ?= /usr/lib/firewalld/services SYSTEMDDIR ?= /usr/lib/systemd/system diff --git a/internal/pkg/buildconfig/defaults.go b/internal/pkg/buildconfig/defaults.go index c14db9b0..43f31a0f 100644 --- a/internal/pkg/buildconfig/defaults.go +++ b/internal/pkg/buildconfig/defaults.go @@ -17,7 +17,6 @@ var ( wwclientdir string = "UNDEF" version string = "UNDEF" release string = "UNDEF" - wwclientloc string = "UNDEF" ) func BINDIR() string { diff --git a/internal/pkg/buildconfig/setconfigs.go.in b/internal/pkg/buildconfig/setconfigs.go.in index b3ed934d..1b2bbdea 100644 --- a/internal/pkg/buildconfig/setconfigs.go.in +++ b/internal/pkg/buildconfig/setconfigs.go.in @@ -15,5 +15,4 @@ func init() { wwclientdir = "@WWCLIENTDIR@" version = "@VERSION@" release = "@RELEASE@" - wwclientloc = "@WWCLIENTLOC" } From 496674ab9e6f7a7584bae391557ca0efcaa3ba8c Mon Sep 17 00:00:00 2001 From: jcsiadal Date: Fri, 11 Feb 2022 16:49:10 +0000 Subject: [PATCH 3/4] Move configuration work to library Signed-off-by: jcsiadal --- internal/app/wwctl/configure/dhcp/main.go | 138 +---------------- internal/app/wwctl/configure/dhcp/root.go | 8 +- internal/app/wwctl/configure/hosts/main.go | 111 +------------- internal/app/wwctl/configure/hosts/root.go | 10 +- internal/app/wwctl/configure/nfs/main.go | 69 +-------- internal/app/wwctl/configure/nfs/root.go | 8 +- internal/app/wwctl/configure/root.go | 54 ++----- internal/app/wwctl/configure/ssh/main.go | 93 +----------- internal/app/wwctl/configure/ssh/root.go | 8 +- internal/app/wwctl/configure/tftp/main.go | 64 +------- internal/app/wwctl/configure/tftp/root.go | 8 +- internal/pkg/configure/common.go | 30 ++++ internal/pkg/configure/dhcp.go | 139 ++++++++++++++++++ .../dhcp => pkg/configure}/dhcp_main_test.go | 9 +- internal/pkg/configure/hosts.go | 110 ++++++++++++++ internal/pkg/configure/nfs.go | 69 +++++++++ internal/pkg/configure/ssh.go | 69 +++++++++ internal/pkg/configure/tftp.go | 49 ++++++ 18 files changed, 514 insertions(+), 532 deletions(-) create mode 100644 internal/pkg/configure/common.go create mode 100644 internal/pkg/configure/dhcp.go rename internal/{app/wwctl/configure/dhcp => pkg/configure}/dhcp_main_test.go (80%) create mode 100644 internal/pkg/configure/hosts.go create mode 100644 internal/pkg/configure/nfs.go create mode 100644 internal/pkg/configure/ssh.go create mode 100644 internal/pkg/configure/tftp.go diff --git a/internal/app/wwctl/configure/dhcp/main.go b/internal/app/wwctl/configure/dhcp/main.go index f9863584..15b61bd4 100644 --- a/internal/app/wwctl/configure/dhcp/main.go +++ b/internal/app/wwctl/configure/dhcp/main.go @@ -1,144 +1,10 @@ package dhcp import ( - "fmt" - "os" - "path" - "strconv" - "strings" - "text/template" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/pkg/errors" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) -type dhcpTemplate struct { - Ipaddr string - Port string - RangeStart string - RangeEnd string - Network string - Netmask string - Nodes []node.NodeInfo -} - func CobraRunE(cmd *cobra.Command, args []string) error { - return Configure(SetShow) -} - -func Configure(show bool) error { - var d dhcpTemplate - var templateFile string - - nodeDB, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) - os.Exit(1) - } - - controller, err := warewulfconf.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - if controller.Ipaddr == "" { - wwlog.Printf(wwlog.ERROR, "The Warewulf IP Address is not properly configured\n") - os.Exit(1) - } - - if controller.Netmask == "" { - wwlog.Printf(wwlog.ERROR, "The Warewulf Netmask is not properly configured\n") - os.Exit(1) - } - - if !controller.Dhcp.Enabled { - wwlog.Printf(wwlog.INFO, "This system is not configured as a Warewulf DHCP controller\n") - os.Exit(1) - } - - if controller.Dhcp.RangeStart == "" { - wwlog.Printf(wwlog.ERROR, "Configuration is not defined: `dhcpd range start`\n") - os.Exit(1) - } - - if controller.Dhcp.RangeEnd == "" { - wwlog.Printf(wwlog.ERROR, "Configuration is not defined: `dhcpd range end`\n") - os.Exit(1) - } - - if controller.Dhcp.ConfigFile == "" { - controller.Dhcp.ConfigFile = "/etc/dhcp/dhcpd.conf" - } - - nodes, err := nodeDB.FindAllNodes() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err) - os.Exit(1) - } - - d.Nodes = append(d.Nodes, nodes...) - - templateFile = dhcpTemplateFile(controller.Dhcp.Template) - tmpl, err := template.New(path.Base(templateFile)).ParseFiles(templateFile) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - d.Ipaddr = controller.Ipaddr - d.Port = strconv.Itoa(controller.Warewulf.Port) - d.Network = controller.Network - d.Netmask = controller.Netmask - d.RangeStart = controller.Dhcp.RangeStart - d.RangeEnd = controller.Dhcp.RangeEnd - - if !show { - fmt.Printf("Writing the DHCP configuration file\n") - configWriter, err := os.OpenFile(controller.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - defer configWriter.Close() - err = tmpl.Execute(configWriter, d) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - fmt.Printf("Enabling and restarting the DHCP services\n") - err = util.SystemdStart(controller.Dhcp.SystemdName) - if err != nil { - return errors.Wrap(err, "failed to start") - } - } else { - err = tmpl.Execute(os.Stdout, d) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - } - - return nil -} - -// dhcpTemplateFile returns the path of the warewulf dhcp template given controller.Dhcp.Template. -func dhcpTemplateFile(controllerDhcpTemplate string) (templateFile string) { - if controllerDhcpTemplate == "" { - templateFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/default-dhcpd.conf") - } else { - if strings.HasPrefix(controllerDhcpTemplate, "/") { - templateFile = controllerDhcpTemplate - } else { - templateFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/"+controllerDhcpTemplate+"-dhcpd.conf") - } - } - return + return configure.Configure("DHCP", setShow) } diff --git a/internal/app/wwctl/configure/dhcp/root.go b/internal/app/wwctl/configure/dhcp/root.go index d27f8ad3..a4a32716 100644 --- a/internal/app/wwctl/configure/dhcp/root.go +++ b/internal/app/wwctl/configure/dhcp/root.go @@ -7,17 +7,17 @@ import ( var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "dhcp [OPTIONS]", - Short: "Manage and initialize DHCP", + Use: "dhcp [OPTIONS]", + Short: "Manage and initialize DHCP", Long: "DHCP is a dependent service to Warewulf. This command will configure DHCP as defined\n" + "in the warewulf.conf file.", RunE: CobraRunE, } - SetShow bool + setShow bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&SetShow, "show", "s", false, "Show configuration (don't update)") + baseCmd.PersistentFlags().BoolVarP(&setShow, "show", "s", false, "Show configuration (don't update)") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/configure/hosts/main.go b/internal/app/wwctl/configure/hosts/main.go index 9b33710b..9e620ffd 100644 --- a/internal/app/wwctl/configure/hosts/main.go +++ b/internal/app/wwctl/configure/hosts/main.go @@ -1,117 +1,10 @@ package hosts import ( - "bytes" - "os" - "path" - "text/template" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/node" - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" - "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) -type TemplateStruct struct { - PrevHostFile string - Ipaddr string - Fqdn string - AllNodes []node.NodeInfo -} - func CobraRunE(cmd *cobra.Command, args []string) error { - return Configure(SetShow) -} - -func Configure(show bool) error { - var replace TemplateStruct - - if !util.IsFile(path.Join(buildconfig.SYSCONFDIR(), "warewulf/hosts.tmpl")) { - wwlog.Printf(wwlog.WARN, "Template not found, not updating host file\n") - return nil - } - - controller, err := warewulfconf.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - n, err := node.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) - os.Exit(1) - } - - tmpl, err := template.ParseFiles(path.Join(buildconfig.SYSCONFDIR(), "warewulf/hosts.tmpl")) - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not parse hosts template: %s\n", err) - os.Exit(1) - } - - replace.PrevHostFile = "" - w, err := os.Open("/etc/hosts") - if err != nil { - wwlog.Printf(wwlog.WARN, "%s\n", err) - } else { - // if /etc/hosts.ww does not exist, backup /etc/hosts to /etc/hosts.wwbackup - if !util.IsFile("/etc/hosts.wwbackup") { - err = util.CopyFile("/etc/hosts", "/etc/hosts.wwbackup") - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - } - } - - // read all lines before the # warewulf comment and put into PrevHostFile template variable - lines, _ := util.ReadFile("/etc/hosts") - if lines != nil { - var buffer bytes.Buffer - for _, line := range lines { - //wwlog.Printf(wwlog.INFO, "Reading line: %s\n", line) - if util.ValidString(line, "^#.*maintained by warewulf") { - break - } - buffer.WriteString(line) - buffer.WriteString("\n") - } - replace.PrevHostFile = buffer.String() - } - } - - //wwlog.Printf(wwlog.INFO, "PrevHostFile is %s\n", replace.PrevHostFile) - - w.Close() - - nodes, _ := n.FindAllNodes() - - replace.AllNodes = nodes - replace.Ipaddr = controller.Ipaddr - replace.Fqdn = controller.Fqdn - - if !SetShow { - // only open "/etc/hosts" when intended to write, as 'os.O_TRUNC' will empty the file otherwise. - w, err = os.OpenFile("/etc/hosts", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - defer w.Close() - - err = tmpl.Execute(w, replace) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - } else { - err = tmpl.Execute(os.Stdout, replace) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - } - - return nil + return configure.Configure("hosts", setShow) } diff --git a/internal/app/wwctl/configure/hosts/root.go b/internal/app/wwctl/configure/hosts/root.go index 84877a40..e0187947 100644 --- a/internal/app/wwctl/configure/hosts/root.go +++ b/internal/app/wwctl/configure/hosts/root.go @@ -4,18 +4,18 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ - DisableFlagsInUseLine: true, - Use: "hosts [OPTIONS]", - Short: "Update the /etc/hosts file", + DisableFlagsInUseLine: true, + Use: "hosts [OPTIONS]", + Short: "Update the /etc/hosts file", Long: "Write out the /etc/hosts file based on the Warewulf template (hosts.tmpl) in the\n" + "Warewulf configuration directory.", RunE: CobraRunE, } - SetShow bool + setShow bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&SetShow, "show", "s", false, "Show configuration (don't update)") + baseCmd.PersistentFlags().BoolVarP(&setShow, "show", "s", false, "Show configuration (don't update)") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/configure/nfs/main.go b/internal/app/wwctl/configure/nfs/main.go index 548ee8f4..fa5c0df5 100644 --- a/internal/app/wwctl/configure/nfs/main.go +++ b/internal/app/wwctl/configure/nfs/main.go @@ -1,75 +1,10 @@ package nfs import ( - "fmt" - "os" - - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - - "github.com/pkg/errors" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { - return Configure(SetShow) -} - -func Configure(show bool) error { - - controller, err := warewulfconf.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - if controller.Network == "" { - wwlog.Printf(wwlog.ERROR, "Network must be defined in warewulf.conf to configure NFS\n") - os.Exit(1) - } - if controller.Netmask == "" { - wwlog.Printf(wwlog.ERROR, "Netmask must be defined in warewulf.conf to configure NFS\n") - os.Exit(1) - } - - if !SetShow { - - if controller.Nfs.Enabled { - exports, err := os.OpenFile("/etc/exports", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - defer exports.Close() - - fmt.Fprintf(exports, "# This file was written by Warewulf (wwctl configure nfs)\n") - - for _, export := range controller.Nfs.ExportsExtended { - fmt.Fprintf(exports, "%s %s/%s(%s)\n", export.Path, controller.Network, controller.Netmask, export.ExportOptions) - } - - fmt.Printf("Enabling and restarting the NFS services\n") - if controller.Nfs.SystemdName == "" { - err := util.SystemdStart("nfs-server") - if err != nil { - return errors.Wrap(err, "failed to start nfs-server") - } - } else { - err := util.SystemdStart(controller.Nfs.SystemdName) - if err != nil { - return errors.Wrap(err, "failed to start") - } - } - } - } else { - fmt.Printf("/etc/exports:\n") - - for _, export := range controller.Nfs.ExportsExtended { - fmt.Printf("%s %s/%s\n", export.Path, controller.Network, controller.Netmask) - } - fmt.Printf("\n") - } - - return nil + return configure.Configure("NFS", setShow) } diff --git a/internal/app/wwctl/configure/nfs/root.go b/internal/app/wwctl/configure/nfs/root.go index 4e074021..ba403a49 100644 --- a/internal/app/wwctl/configure/nfs/root.go +++ b/internal/app/wwctl/configure/nfs/root.go @@ -5,17 +5,17 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "nfs [OPTIONS]", - Short: "Manage and initialize NFS", + Use: "nfs [OPTIONS]", + Short: "Manage and initialize NFS", Long: "NFS is an optional dependent service of Warewulf, this tool will automatically\n" + "configure NFS as per the configuration in the warewulf.conf file.", RunE: CobraRunE, } - SetShow bool + setShow bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&SetShow, "show", "s", false, "Show configuration (don't update)") + baseCmd.PersistentFlags().BoolVarP(&setShow, "show", "s", false, "Show configuration (don't update)") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/configure/root.go b/internal/app/wwctl/configure/root.go index 6d8a2c41..8a0950c2 100644 --- a/internal/app/wwctl/configure/root.go +++ b/internal/app/wwctl/configure/root.go @@ -1,7 +1,6 @@ package configure import ( - "fmt" "os" "github.com/hpcng/warewulf/internal/app/wwctl/configure/dhcp" @@ -9,20 +8,20 @@ import ( "github.com/hpcng/warewulf/internal/app/wwctl/configure/nfs" "github.com/hpcng/warewulf/internal/app/wwctl/configure/ssh" "github.com/hpcng/warewulf/internal/app/wwctl/configure/tftp" - "github.com/pkg/errors" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "configure [OPTIONS]", - Short: "Manage system services", + Use: "configure [OPTIONS]", + Short: "Manage system services", Long: "This application allows you to manage and initialize Warewulf dependent system\n" + "services based on the configuration in the warewulf.conf file.", RunE: CobraRunE, } - SetDoAll bool + allFunctions bool ) func init() { @@ -32,7 +31,7 @@ func init() { baseCmd.AddCommand(ssh.GetCommand()) baseCmd.AddCommand(nfs.GetCommand()) - baseCmd.PersistentFlags().BoolVarP(&SetDoAll, "all", "a", false, "Configure all services") + baseCmd.PersistentFlags().BoolVarP(&allFunctions, "all", "a", false, "Configure all services") } // GetRootCommand returns the root cobra.Command for the application. @@ -41,44 +40,17 @@ func GetCommand() *cobra.Command { } func CobraRunE(cmd *cobra.Command, args []string) error { - if SetDoAll { - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: DHCP\n") - err := dhcp.Configure(false) - if err != nil { - return errors.Wrap(err, "failed to configure dhcp") - } + var err error + if allFunctions { + for _, s := range [5]string{"DHPC", "hosts", "NFS", "SSH", "TFTP"} { + err = configure.Configure(s, false) + if err != nil { + os.Exit(1) + } - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: TFTP\n") - err = tftp.Configure(false) - if err != nil { - return errors.Wrap(err, "failed to configure tftp") - } - - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: /etc/hosts\n") - err = hosts.Configure(false) - if err != nil { - return errors.Wrap(err, "failed to configure hosts") - } - - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: NFS\n") - err = nfs.Configure(false) - if err != nil { - return errors.Wrap(err, "failed to configure nfs") - } - - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: SSH\n") - err = ssh.Configure(false) - if err != nil { - return errors.Wrap(err, "failed to configure ssh") } } else { - //nolint:errcheck - cmd.Help() + _ = cmd.Help() os.Exit(0) } diff --git a/internal/app/wwctl/configure/ssh/main.go b/internal/app/wwctl/configure/ssh/main.go index 91285287..1d7afb1b 100644 --- a/internal/app/wwctl/configure/ssh/main.go +++ b/internal/app/wwctl/configure/ssh/main.go @@ -1,99 +1,10 @@ package ssh import ( - "fmt" - "os" - "path" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/wwlog" - "github.com/pkg/errors" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { - return Configure(SetShow) -} - -func Configure(show bool) error { - if os.Getuid() == 0 { - fmt.Printf("Updating system keys\n") - - wwkeydir := path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys") + "/" - - err := os.MkdirAll(path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys"), 0755) - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not create base directory: %s\n", err) - os.Exit(1) - } - - if !util.IsFile(wwkeydir + "ssh_host_rsa_key") { - fmt.Printf("Setting up key: ssh_host_rsa_key\n") - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", wwkeydir+"ssh_host_rsa_key", "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - } else { - fmt.Printf("Skipping, key already exists: ssh_host_rsa_key\n") - } - - if !util.IsFile(wwkeydir + "ssh_host_dsa_key") { - fmt.Printf("Setting up key: ssh_host_dsa_key\n") - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "dsa", "-f", wwkeydir+"ssh_host_dsa_key", "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - } else { - fmt.Printf("Skipping, key already exists: ssh_host_dsa_key\n") - } - - if !util.IsFile(wwkeydir + "ssh_host_ecdsa_key") { - fmt.Printf("Setting up key: ssh_host_ecdsa_key\n") - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "ecdsa", "-f", wwkeydir+"ssh_host_ecdsa_key", "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - } else { - fmt.Printf("Skipping, key already exists: ssh_host_ecdsa_key\n") - } - - if !util.IsFile(wwkeydir + "ssh_host_ed25519_key") { - fmt.Printf("Setting up key: ssh_host_ed25519_key\n") - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "ed25519", "-f", wwkeydir+"ssh_host_ed25519_key", "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - } else { - fmt.Printf("Skipping, key already exists: ssh_host_ed25519_key\n") - } - } else { - fmt.Printf("Updating user's keys\n") - } - - homeDir, err := os.UserHomeDir() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not obtain the user's home directory: %s\n", err) - os.Exit(1) - } - - authorizedKeys := path.Join(homeDir, "/.ssh/authorized_keys") - rsaPriv := path.Join(homeDir, "/.ssh/id_rsa") - rsaPub := path.Join(homeDir, "/.ssh/id_rsa.pub") - - if !util.IsFile(authorizedKeys) { - fmt.Printf("Setting up: %s\n", authorizedKeys) - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", rsaPriv, "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - err := util.CopyFile(rsaPub, authorizedKeys) - if err != nil { - return errors.Wrap(err, "failed to copy keys") - } - } else { - fmt.Printf("Skipping, authorized_keys already exists: %s\n", authorizedKeys) - } - - return nil + return configure.Configure("SSH", setShow) } diff --git a/internal/app/wwctl/configure/ssh/root.go b/internal/app/wwctl/configure/ssh/root.go index 2246c0db..a3909e64 100644 --- a/internal/app/wwctl/configure/ssh/root.go +++ b/internal/app/wwctl/configure/ssh/root.go @@ -5,18 +5,18 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "ssh [OPTIONS]", - Short: "Manage and initialize SSH", + Use: "ssh [OPTIONS]", + Short: "Manage and initialize SSH", Long: "SSH is an optionally dependent service for Warewulf, this tool will automatically\n" + "setup the ssh keys nodes using the 'default' system overlay as well as user owned\n" + "keys.", RunE: CobraRunE, } - SetShow bool + setShow bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&SetShow, "show", "s", false, "Show configuration (don't update)") + baseCmd.PersistentFlags().BoolVarP(&setShow, "show", "s", false, "Show configuration (don't update)") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/configure/tftp/main.go b/internal/app/wwctl/configure/tftp/main.go index 4198718f..f122fb28 100644 --- a/internal/app/wwctl/configure/tftp/main.go +++ b/internal/app/wwctl/configure/tftp/main.go @@ -1,70 +1,10 @@ package tftp import ( - "fmt" - "os" - "path" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" - "github.com/hpcng/warewulf/internal/pkg/staticfiles" - "github.com/hpcng/warewulf/internal/pkg/util" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" - "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/hpcng/warewulf/internal/pkg/configure" "github.com/spf13/cobra" ) func CobraRunE(cmd *cobra.Command, args []string) error { - return Configure(SetShow) -} - -func Configure(show bool) error { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - if buildconfig.TFTPDIR() == "" { - wwlog.Printf(wwlog.ERROR, "Tftp root directory is not configured by build\n") - os.Exit(1) - } - - err = os.MkdirAll(path.Join(buildconfig.TFTPDIR(), "warewulf"), 0755) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - if !show { - fmt.Printf("Writing PXE files to: %s\n", path.Join(buildconfig.TFTPDIR(), "warewulf")) - err = staticfiles.WriteData("files/tftp/x86.efi", path.Join(buildconfig.TFTPDIR(), "warewulf/x86.efi")) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - err = staticfiles.WriteData("files/tftp/i386.efi", path.Join(buildconfig.TFTPDIR(), "warewulf/i386.efi")) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - err = staticfiles.WriteData("files/tftp/i386.kpxe", path.Join(buildconfig.TFTPDIR(), "warewulf/i386.kpxe")) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - err = staticfiles.WriteData("files/tftp/arm64.efi", path.Join(buildconfig.TFTPDIR(), "warewulf/arm64.efi")) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - fmt.Printf("Enabling and restarting the TFTP services\n") - err = util.SystemdStart(controller.Tftp.SystemdName) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - } - - return nil + return configure.Configure("TFTP", setShow) } diff --git a/internal/app/wwctl/configure/tftp/root.go b/internal/app/wwctl/configure/tftp/root.go index 7629fa2c..36198f10 100644 --- a/internal/app/wwctl/configure/tftp/root.go +++ b/internal/app/wwctl/configure/tftp/root.go @@ -5,17 +5,17 @@ import "github.com/spf13/cobra" var ( baseCmd = &cobra.Command{ DisableFlagsInUseLine: true, - Use: "tftp [OPTIONS]", - Short: "Manage and initialize TFTP", + Use: "tftp [OPTIONS]", + Short: "Manage and initialize TFTP", Long: "TFTP is a dependent service of Warewulf, this tool will enable the tftp services\n" + "on your Warewulf master.", RunE: CobraRunE, } - SetShow bool + setShow bool ) func init() { - baseCmd.PersistentFlags().BoolVarP(&SetShow, "show", "s", false, "Show configuration (don't update)") + baseCmd.PersistentFlags().BoolVarP(&setShow, "show", "s", false, "Show configuration (don't update)") } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/pkg/configure/common.go b/internal/pkg/configure/common.go new file mode 100644 index 00000000..286cd1e1 --- /dev/null +++ b/internal/pkg/configure/common.go @@ -0,0 +1,30 @@ +package configure + +import ( + "fmt" + + "github.com/pkg/errors" +) + +func Configure(s string, v bool) error { + fmt.Printf("################################################################################\n") + fmt.Printf("Configuring: %s\n", s) + + var err error + switch s { + case "DHCP": + err = configureDHCP(v) + case "hosts": + err = configureHosts(v) + case "NFS": + err = configureNFS(v) + case "SSH": + err = configureSSH(v) + case "TFTP": + err = configureTFTP(v) + } + if err != nil { + return errors.Wrap(err, "Failed to configure "+s) + } + return nil +} diff --git a/internal/pkg/configure/dhcp.go b/internal/pkg/configure/dhcp.go new file mode 100644 index 00000000..1b7b2511 --- /dev/null +++ b/internal/pkg/configure/dhcp.go @@ -0,0 +1,139 @@ +package configure + +import ( + "fmt" + "os" + "path" + "strconv" + "strings" + "text/template" + + "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/pkg/errors" +) + +type dhcpTemplate struct { + Ipaddr string + Port string + RangeStart string + RangeEnd string + Network string + Netmask string + Nodes []node.NodeInfo +} + +func configureDHCP(show bool) error { + var d dhcpTemplate + var templateFile string + + nodeDB, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) + os.Exit(1) + } + + controller, err := warewulfconf.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + if controller.Ipaddr == "" { + wwlog.Printf(wwlog.ERROR, "The Warewulf IP Address is not properly configured\n") + os.Exit(1) + } + + if controller.Netmask == "" { + wwlog.Printf(wwlog.ERROR, "The Warewulf Netmask is not properly configured\n") + os.Exit(1) + } + + if !controller.Dhcp.Enabled { + wwlog.Printf(wwlog.INFO, "This system is not configured as a Warewulf DHCP controller\n") + os.Exit(1) + } + + if controller.Dhcp.RangeStart == "" { + wwlog.Printf(wwlog.ERROR, "Configuration is not defined: `dhcpd range start`\n") + os.Exit(1) + } + + if controller.Dhcp.RangeEnd == "" { + wwlog.Printf(wwlog.ERROR, "Configuration is not defined: `dhcpd range end`\n") + os.Exit(1) + } + + if controller.Dhcp.ConfigFile == "" { + controller.Dhcp.ConfigFile = "/etc/dhcp/dhcpd.conf" + } + + nodes, err := nodeDB.FindAllNodes() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not find all controllers: %s\n", err) + os.Exit(1) + } + + d.Nodes = append(d.Nodes, nodes...) + + templateFile = dhcpTemplateFile(controller.Dhcp.Template) + tmpl, err := template.New(path.Base(templateFile)).ParseFiles(templateFile) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + d.Ipaddr = controller.Ipaddr + d.Port = strconv.Itoa(controller.Warewulf.Port) + d.Network = controller.Network + d.Netmask = controller.Netmask + d.RangeStart = controller.Dhcp.RangeStart + d.RangeEnd = controller.Dhcp.RangeEnd + + if !show { + fmt.Printf("Writing the DHCP configuration file\n") + configWriter, err := os.OpenFile(controller.Dhcp.ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + defer configWriter.Close() + err = tmpl.Execute(configWriter, d) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + fmt.Printf("Enabling and restarting the DHCP services\n") + err = util.SystemdStart(controller.Dhcp.SystemdName) + if err != nil { + return errors.Wrap(err, "failed to start") + } + } else { + err = tmpl.Execute(os.Stdout, d) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + } + + return nil +} + +// dhcpTemplateFile returns the path of the warewulf dhcp template given controller.Dhcp.Template. +func dhcpTemplateFile(controllerDhcpTemplate string) (templateFile string) { + if controllerDhcpTemplate == "" { + templateFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/default-dhcpd.conf") + } else { + if strings.HasPrefix(controllerDhcpTemplate, "/") { + templateFile = controllerDhcpTemplate + } else { + templateFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/"+controllerDhcpTemplate+"-dhcpd.conf") + } + } + return +} diff --git a/internal/app/wwctl/configure/dhcp/dhcp_main_test.go b/internal/pkg/configure/dhcp_main_test.go similarity index 80% rename from internal/app/wwctl/configure/dhcp/dhcp_main_test.go rename to internal/pkg/configure/dhcp_main_test.go index 49dc32e8..bf265141 100644 --- a/internal/app/wwctl/configure/dhcp/dhcp_main_test.go +++ b/internal/pkg/configure/dhcp_main_test.go @@ -1,4 +1,4 @@ -package dhcp +package configure import ( "path" @@ -8,12 +8,12 @@ import ( ) func TestDhcpTemplateFile(t *testing.T) { - tests := []struct{ + tests := []struct { parameter string - expected string + expected string }{ {"", path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/default-dhcpd.conf")}, - {"default", path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/default-dhcpd.conf")}, + {"default", path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/default-dhcpd.conf")}, {"static", path.Join(buildconfig.SYSCONFDIR(), "warewulf/dhcp/static-dhcpd.conf")}, {"/test/absolute/path.conf", "/test/absolute/path.conf"}, } @@ -25,4 +25,3 @@ func TestDhcpTemplateFile(t *testing.T) { } } } - diff --git a/internal/pkg/configure/hosts.go b/internal/pkg/configure/hosts.go new file mode 100644 index 00000000..d0c918fd --- /dev/null +++ b/internal/pkg/configure/hosts.go @@ -0,0 +1,110 @@ +package configure + +import ( + "bytes" + "os" + "path" + "text/template" + + "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +type hostsTemplate struct { + PrevHostFile string + Ipaddr string + Fqdn string + AllNodes []node.NodeInfo +} + +func configureHosts(show bool) error { + var replace hostsTemplate + + if !util.IsFile(path.Join(buildconfig.SYSCONFDIR(), "warewulf/hosts.tmpl")) { + wwlog.Printf(wwlog.WARN, "Template not found, not updating host file\n") + return nil + } + + controller, err := warewulfconf.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + n, err := node.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not open node configuration: %s\n", err) + os.Exit(1) + } + + tmpl, err := template.ParseFiles(path.Join(buildconfig.SYSCONFDIR(), "warewulf/hosts.tmpl")) + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not parse hosts template: %s\n", err) + os.Exit(1) + } + + replace.PrevHostFile = "" + w, err := os.Open("/etc/hosts") + if err != nil { + wwlog.Printf(wwlog.WARN, "%s\n", err) + } else { + // if /etc/hosts.ww does not exist, backup /etc/hosts to /etc/hosts.wwbackup + if !util.IsFile("/etc/hosts.wwbackup") { + err = util.CopyFile("/etc/hosts", "/etc/hosts.wwbackup") + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + } + } + + // read all lines before the # warewulf comment and put into PrevHostFile template variable + lines, _ := util.ReadFile("/etc/hosts") + if lines != nil { + var buffer bytes.Buffer + for _, line := range lines { + //wwlog.Printf(wwlog.INFO, "Reading line: %s\n", line) + if util.ValidString(line, "^#.*maintained by warewulf") { + break + } + buffer.WriteString(line) + buffer.WriteString("\n") + } + replace.PrevHostFile = buffer.String() + } + } + + w.Close() + + nodes, _ := n.FindAllNodes() + + replace.AllNodes = nodes + replace.Ipaddr = controller.Ipaddr + replace.Fqdn = controller.Fqdn + + if !show { + // only open "/etc/hosts" when intended to write, as 'os.O_TRUNC' will empty the file otherwise. + w, err = os.OpenFile("/etc/hosts", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + defer w.Close() + + err = tmpl.Execute(w, replace) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } else { + err = tmpl.Execute(os.Stdout, replace) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + } + + return nil +} diff --git a/internal/pkg/configure/nfs.go b/internal/pkg/configure/nfs.go new file mode 100644 index 00000000..6025f77b --- /dev/null +++ b/internal/pkg/configure/nfs.go @@ -0,0 +1,69 @@ +package configure + +import ( + "fmt" + "os" + + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/pkg/errors" +) + +func configureNFS(show bool) error { + + controller, err := warewulfconf.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + if controller.Network == "" { + wwlog.Printf(wwlog.ERROR, "Network must be defined in warewulf.conf to configure NFS\n") + os.Exit(1) + } + if controller.Netmask == "" { + wwlog.Printf(wwlog.ERROR, "Netmask must be defined in warewulf.conf to configure NFS\n") + os.Exit(1) + } + + if !show { + + if controller.Nfs.Enabled { + exports, err := os.OpenFile("/etc/exports", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + defer exports.Close() + + fmt.Fprintf(exports, "# This file was written by Warewulf (wwctl configure nfs)\n") + + for _, export := range controller.Nfs.ExportsExtended { + fmt.Fprintf(exports, "%s %s/%s(%s)\n", export.Path, controller.Network, controller.Netmask, export.ExportOptions) + } + + fmt.Printf("Enabling and restarting the NFS services\n") + if controller.Nfs.SystemdName == "" { + err := util.SystemdStart("nfs-server") + if err != nil { + return errors.Wrap(err, "failed to start nfs-server") + } + } else { + err := util.SystemdStart(controller.Nfs.SystemdName) + if err != nil { + return errors.Wrap(err, "failed to start") + } + } + } + } else { + fmt.Printf("/etc/exports:\n") + + for _, export := range controller.Nfs.ExportsExtended { + fmt.Printf("%s %s/%s\n", export.Path, controller.Network, controller.Netmask) + } + fmt.Printf("\n") + } + + return nil +} diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go new file mode 100644 index 00000000..00a5f470 --- /dev/null +++ b/internal/pkg/configure/ssh.go @@ -0,0 +1,69 @@ +package configure + +import ( + "fmt" + "os" + "path" + + "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/wwlog" + "github.com/pkg/errors" +) + +func configureSSH(show bool) error { + if os.Getuid() == 0 { + fmt.Printf("Updating system keys\n") + + wwkeydir := path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys") + "/" + + err := os.MkdirAll(path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys"), 0755) + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not create base directory: %s\n", err) + os.Exit(1) + } + + for _, k := range [4]string{"rsa", "dsa", "ecdsa", "ed25519"} { + keytype := "ssh_host_" + k + "_key" + if !util.IsFile(path.Join(wwkeydir, keytype)) { + fmt.Printf("Setting up key: %s\n", keytype) + wwlog.Printf(wwlog.DEBUG, "Creating new %s key\n", keytype) + err = util.ExecInteractive("ssh-keygen", "-q", "-t", k, "-f", path.Join(wwkeydir, keytype), "-C", "", "-N", "") + if err != nil { + wwlog.Printf(wwlog.ERROR, "Failed to exec ssh-keygen: %s\n", err) + return errors.Wrap(err, "failed to exec ssh-keygen command") + } + } else { + fmt.Printf("Skipping, key already exists: %s\n", keytype) + } + } + } else { + fmt.Printf("Updating user's keys\n") + } + + homeDir, err := os.UserHomeDir() + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not obtain the user's home directory: %s\n", err) + os.Exit(1) + } + + authorizedKeys := path.Join(homeDir, "/.ssh/authorized_keys") + rsaPriv := path.Join(homeDir, "/.ssh/id_rsa") + rsaPub := path.Join(homeDir, "/.ssh/id_rsa.pub") + + if !util.IsFile(authorizedKeys) { + fmt.Printf("Setting up: %s\n", authorizedKeys) + err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", rsaPriv, "-C", "", "-N", "") + if err != nil { + return errors.Wrap(err, "failed to exec ssh-keygen command") + } + err := util.CopyFile(rsaPub, authorizedKeys) + if err != nil { + return errors.Wrap(err, "failed to copy keys") + } + } else { + fmt.Printf("Skipping, authorized_keys already exists: %s\n", authorizedKeys) + } + + return nil +} diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go new file mode 100644 index 00000000..237827e1 --- /dev/null +++ b/internal/pkg/configure/tftp.go @@ -0,0 +1,49 @@ +package configure + +import ( + "fmt" + "os" + "path" + + "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/staticfiles" + "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/hpcng/warewulf/internal/pkg/wwlog" +) + +var tftpdir string = path.Join(buildconfig.TFTPDIR(), "warewulf") + +func configureTFTP(show bool) error { + controller, err := warewulfconf.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + err = os.MkdirAll(tftpdir, 0755) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + + if !show { + fmt.Printf("Writing PXE files to: %s\n", tftpdir) + for _, f := range [4]string{"x86.efi", "i386.efi", "i386.kpxe", "arm64.efi"} { + err = staticfiles.WriteData(path.Join("files/tftp", f), path.Join(tftpdir, f)) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + + fmt.Printf("Enabling and restarting the TFTP services\n") + err = util.SystemdStart(controller.Tftp.SystemdName) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + os.Exit(1) + } + } + + return nil +} From c4938b55c77e7f559c726a063bb219c9081e38c5 Mon Sep 17 00:00:00 2001 From: jcsiadal Date: Fri, 11 Feb 2022 18:10:32 +0000 Subject: [PATCH 4/4] Update to support show correctly Signed-off-by: jcsiadal --- internal/pkg/configure/common.go | 6 ++- internal/pkg/configure/ssh.go | 89 +++++++++++++++++--------------- internal/pkg/configure/tftp.go | 30 ++++++----- 3 files changed, 66 insertions(+), 59 deletions(-) diff --git a/internal/pkg/configure/common.go b/internal/pkg/configure/common.go index 286cd1e1..713e08be 100644 --- a/internal/pkg/configure/common.go +++ b/internal/pkg/configure/common.go @@ -7,8 +7,10 @@ import ( ) func Configure(s string, v bool) error { - fmt.Printf("################################################################################\n") - fmt.Printf("Configuring: %s\n", s) + if !v { + fmt.Printf("################################################################################\n") + fmt.Printf("Configuring: %s\n", s) + } var err error switch s { diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go index 00a5f470..cf699253 100644 --- a/internal/pkg/configure/ssh.go +++ b/internal/pkg/configure/ssh.go @@ -12,58 +12,61 @@ import ( ) func configureSSH(show bool) error { - if os.Getuid() == 0 { - fmt.Printf("Updating system keys\n") + if !show { + if os.Getuid() == 0 { + fmt.Printf("Updating system keys\n") - wwkeydir := path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys") + "/" + wwkeydir := path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys") + "/" - err := os.MkdirAll(path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys"), 0755) + err := os.MkdirAll(path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys"), 0755) + if err != nil { + wwlog.Printf(wwlog.ERROR, "Could not create base directory: %s\n", err) + os.Exit(1) + } + + for _, k := range [4]string{"rsa", "dsa", "ecdsa", "ed25519"} { + keytype := "ssh_host_" + k + "_key" + if !util.IsFile(path.Join(wwkeydir, keytype)) { + fmt.Printf("Setting up key: %s\n", keytype) + wwlog.Printf(wwlog.DEBUG, "Creating new %s key\n", keytype) + err = util.ExecInteractive("ssh-keygen", "-q", "-t", k, "-f", path.Join(wwkeydir, keytype), "-C", "", "-N", "") + if err != nil { + wwlog.Printf(wwlog.ERROR, "Failed to exec ssh-keygen: %s\n", err) + return errors.Wrap(err, "failed to exec ssh-keygen command") + } + } else { + fmt.Printf("Skipping, key already exists: %s\n", keytype) + } + } + } else { + fmt.Printf("Updating user's keys\n") + } + + homeDir, err := os.UserHomeDir() if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not create base directory: %s\n", err) + wwlog.Printf(wwlog.ERROR, "Could not obtain the user's home directory: %s\n", err) os.Exit(1) } - for _, k := range [4]string{"rsa", "dsa", "ecdsa", "ed25519"} { - keytype := "ssh_host_" + k + "_key" - if !util.IsFile(path.Join(wwkeydir, keytype)) { - fmt.Printf("Setting up key: %s\n", keytype) - wwlog.Printf(wwlog.DEBUG, "Creating new %s key\n", keytype) - err = util.ExecInteractive("ssh-keygen", "-q", "-t", k, "-f", path.Join(wwkeydir, keytype), "-C", "", "-N", "") - if err != nil { - wwlog.Printf(wwlog.ERROR, "Failed to exec ssh-keygen: %s\n", err) - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - } else { - fmt.Printf("Skipping, key already exists: %s\n", keytype) + authorizedKeys := path.Join(homeDir, "/.ssh/authorized_keys") + rsaPriv := path.Join(homeDir, "/.ssh/id_rsa") + rsaPub := path.Join(homeDir, "/.ssh/id_rsa.pub") + + if !util.IsFile(authorizedKeys) { + fmt.Printf("Setting up: %s\n", authorizedKeys) + err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", rsaPriv, "-C", "", "-N", "") + if err != nil { + return errors.Wrap(err, "failed to exec ssh-keygen command") } + err := util.CopyFile(rsaPub, authorizedKeys) + if err != nil { + return errors.Wrap(err, "failed to copy keys") + } + } else { + fmt.Printf("Skipping, authorized_keys already exists: %s\n", authorizedKeys) } } else { - fmt.Printf("Updating user's keys\n") + fmt.Printf("'ssh -s' is not yet implemented.\n") } - - homeDir, err := os.UserHomeDir() - if err != nil { - wwlog.Printf(wwlog.ERROR, "Could not obtain the user's home directory: %s\n", err) - os.Exit(1) - } - - authorizedKeys := path.Join(homeDir, "/.ssh/authorized_keys") - rsaPriv := path.Join(homeDir, "/.ssh/id_rsa") - rsaPub := path.Join(homeDir, "/.ssh/id_rsa.pub") - - if !util.IsFile(authorizedKeys) { - fmt.Printf("Setting up: %s\n", authorizedKeys) - err = util.ExecInteractive("ssh-keygen", "-q", "-t", "rsa", "-f", rsaPriv, "-C", "", "-N", "") - if err != nil { - return errors.Wrap(err, "failed to exec ssh-keygen command") - } - err := util.CopyFile(rsaPub, authorizedKeys) - if err != nil { - return errors.Wrap(err, "failed to copy keys") - } - } else { - fmt.Printf("Skipping, authorized_keys already exists: %s\n", authorizedKeys) - } - return nil } diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go index 237827e1..9cbbfa31 100644 --- a/internal/pkg/configure/tftp.go +++ b/internal/pkg/configure/tftp.go @@ -15,25 +15,25 @@ import ( var tftpdir string = path.Join(buildconfig.TFTPDIR(), "warewulf") func configureTFTP(show bool) error { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - - err = os.MkdirAll(tftpdir, 0755) - if err != nil { - wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) - } - if !show { + controller, err := warewulfconf.New() + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + return err + } + + err = os.MkdirAll(tftpdir, 0755) + if err != nil { + wwlog.Printf(wwlog.ERROR, "%s\n", err) + return err + } + fmt.Printf("Writing PXE files to: %s\n", tftpdir) for _, f := range [4]string{"x86.efi", "i386.efi", "i386.kpxe", "arm64.efi"} { err = staticfiles.WriteData(path.Join("files/tftp", f), path.Join(tftpdir, f)) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) + return err } } @@ -41,8 +41,10 @@ func configureTFTP(show bool) error { err = util.SystemdStart(controller.Tftp.SystemdName) if err != nil { wwlog.Printf(wwlog.ERROR, "%s\n", err) - os.Exit(1) + return err } + } else { + fmt.Printf("'tftp -s' is not yet implemented.\n") } return nil