run systemctl commands in VM
This commit is contained in:
parent
c0ca2cd1c5
commit
fec402c2f8
|
@ -1,15 +1,8 @@
|
|||
package distros
|
||||
|
||||
import (
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"libguestfs.org/guestfs"
|
||||
|
@ -46,154 +39,27 @@ func (mgr *OpensuseTumbleweedTemplateManager) DownloadTemplate(version, codename
|
|||
)
|
||||
}
|
||||
|
||||
const ossPackagesBaseURL = "https://download.opensuse.org/tumbleweed/repo/oss"
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) getSystemdNetworkPackageURL() (string, error) {
|
||||
const indexURL = ossPackagesBaseURL + "/INDEX.gz"
|
||||
mgr.logger.Debug().Msg("Downloading " + indexURL)
|
||||
resp, err := http.Get(indexURL)
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) InstallNetworkManager(handle *guestfs.Guestfs) error {
|
||||
args := []string{"zypper", "--non-interactive", "install", "NetworkManager"}
|
||||
_, err := mgr.logAndRunCommand(handle, args)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return fmt.Errorf("Could not install NetworkManager: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
gzipReader, err := gzip.NewReader(resp.Body)
|
||||
// Make sure dhcp-client is installed because we use it as the
|
||||
// DHCP backend
|
||||
dhclientIsPresent, err := handle.Is_file("/sbin/dhclient", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return fmt.Errorf("Could not determine if /sbin/dhclient is a file: %w", err)
|
||||
}
|
||||
defer gzipReader.Close()
|
||||
body, err := io.ReadAll(gzipReader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
if !dhclientIsPresent {
|
||||
return errors.New("dhclient is not present")
|
||||
}
|
||||
pattern := regexp.MustCompile(`(?m)^\./x86_64/systemd-network-(?:[\d.-]+)\.x86_64\.rpm$`)
|
||||
match := pattern.Find(body)
|
||||
if match == nil {
|
||||
return "", errors.New("Could not find systemd-network package in OpenSUSE Tumbleweed index")
|
||||
}
|
||||
packageURL := ossPackagesBaseURL + "/" + string(match[2:])
|
||||
return packageURL, nil
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) downloadSystemdNetworkPackage() (string, error) {
|
||||
packageURL, err := mgr.getSystemdNetworkPackageURL()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
mgr.logger.Debug().Msg("Downloading " + packageURL)
|
||||
resp, err := http.Get(packageURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// TODO: download to somewhere in /tmp
|
||||
const path = "./systemd-network.rpm"
|
||||
out, err := os.Create(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer out.Close()
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) logAndRunCommand(handle *guestfs.Guestfs, args []string) error {
|
||||
mgr.logger.Debug().Msg("Running command `" + strings.Join(args, " ") + "`")
|
||||
_, err := handle.Command(args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) addSystemUserAndGroup(handle *guestfs.Guestfs, name, uid, gid string) error {
|
||||
matches, err := handle.Grep("^"+name, "/etc/group", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not grep /etc/group: %w", err)
|
||||
}
|
||||
if len(matches) == 0 {
|
||||
err = mgr.logAndRunCommand(handle, []string{
|
||||
"groupadd",
|
||||
"--system",
|
||||
"--gid", gid,
|
||||
name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
matches, err = handle.Grep("^"+name, "/etc/passwd", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not grep /etc/passwd: %w", err)
|
||||
}
|
||||
if len(matches) == 0 {
|
||||
err = mgr.logAndRunCommand(handle, []string{
|
||||
"useradd",
|
||||
"--system",
|
||||
"--no-user-group",
|
||||
"--uid", uid,
|
||||
"--gid", gid,
|
||||
"--home-dir", "/run/systemd",
|
||||
"--shell", "/usr/sbin/nologin",
|
||||
name,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Workaround for bug in VM image: systemd-network user and group are not
|
||||
// present, and are not created when the systemd-network package is installed
|
||||
// Also see: https://github.com/lima-vm/lima/issues/1496
|
||||
//
|
||||
// https://bugzilla.opensuse.org/show_bug.cgi?id=1203393
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) addSystemdNetworkUsersAndGroups(handle *guestfs.Guestfs) error {
|
||||
// UIDs and GIDs were determined by installing systemd-network in
|
||||
// a VM booted from a live ISO image
|
||||
if err := mgr.addSystemUserAndGroup(handle, "systemd-network", "470", "470"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := mgr.addSystemUserAndGroup(handle, "systemd-resolve", "469", "469"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) InstallSystemdNetworkd(handle *guestfs.Guestfs) error {
|
||||
localPath, err := mgr.downloadSystemdNetworkPackage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mgr.logger.Debug().Msg("Copying " + localPath + " to /tmp in VM")
|
||||
err = handle.Copy_in(localPath, "/tmp")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mgr.logger.Debug().Msg("Deleting " + localPath)
|
||||
err = os.Remove(localPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vmPath := "/tmp/" + filepath.Base(localPath)
|
||||
args := []string{"zypper", "--no-remote", "--non-interactive", "install", vmPath}
|
||||
err = mgr.logAndRunCommand(handle, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mgr.logger.Debug().Msg("Deleting " + vmPath + " in VM")
|
||||
err = handle.Rm(vmPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mgr.addSystemdNetworkUsersAndGroups(handle)
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) NeedsDynamicResolvConf() bool {
|
||||
// cloud-init won't work if we overwrite /etc/resolv.conf.
|
||||
// I'm not sure why it works on other distros but not on this one.
|
||||
return true
|
||||
// Workaround for bug in cloud-init which prevents the NetworkManager
|
||||
// backend from being selected if NetworkManager.conf does not exist
|
||||
// https://github.com/canonical/cloud-init/blob/23.1.x/cloudinit/net/network_manager.py#L381
|
||||
const cfgFilePath = "/etc/NetworkManager/NetworkManager.conf"
|
||||
mgr.logger.Debug().Msg("Creating " + cfgFilePath)
|
||||
return handle.Touch(cfgFilePath)
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) removeWelcomeMessage(handle *guestfs.Guestfs) error {
|
||||
|
@ -203,17 +69,16 @@ func (mgr *OpensuseTumbleweedTemplateManager) removeWelcomeMessage(handle *guest
|
|||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) CommandToUpdatePackageCache() []string {
|
||||
return []string{"sudo", "zypper", "refresh"}
|
||||
return []string{"sudo", "zypper", "refresh", "--force"}
|
||||
}
|
||||
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) PerformDistroSpecificModifications(handle *guestfs.Guestfs) (err error) {
|
||||
unitPath, err := getSystemdUnitPath(handle, "wickedd.service")
|
||||
func (mgr *OpensuseTumbleweedTemplateManager) PerformDistroSpecificModifications(handle *guestfs.Guestfs) error {
|
||||
// Newer Tumbleweed images shouldn't be using wickedd anymore
|
||||
wickeddExists, err := handle.Is_file("/lib/systemd/system/wickedd.service", nil)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if unitPath != "" {
|
||||
// OpenSUSE Tumbleweed images should be using NetworkManager
|
||||
// or systemd-networkd (after we install it)
|
||||
if wickeddExists {
|
||||
return errors.New("wickedd.service was unexpectedly found")
|
||||
}
|
||||
return mgr.removeWelcomeMessage(handle)
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
RESOLV_CONF=/run/netconfig/resolv.conf
|
||||
|
||||
sed -i '/^search .*/d' $RESOLV_CONF
|
||||
sed -i '/^options .*/d' $RESOLV_CONF
|
||||
cat <<EOF >> $RESOLV_CONF
|
||||
search csclub.uwaterloo.ca uwaterloo.ca
|
||||
options ndots:2
|
||||
EOF
|
|
@ -52,10 +52,6 @@ type ITemplateManager interface {
|
|||
// An IDistroSpecificTemplateManager performs the distro-specific tasks
|
||||
// when modifying a VM template. It is used by the generic TemplateManager.
|
||||
type IDistroSpecificTemplateManager interface {
|
||||
// On some distros, like OpenSUSE Tumbleweed, we cannot overwrite
|
||||
// /etc/resolv.conf or else cloud-init will fail. Such distros should
|
||||
// override this method to return true.
|
||||
NeedsDynamicResolvConf() bool
|
||||
// GetLatestVersion returns the version number and codename of the
|
||||
// latest version of particular OS (e.g. version="22.04", codename="jammy")
|
||||
GetLatestVersion() (version string, codename string, err error)
|
||||
|
@ -70,21 +66,14 @@ type IDistroSpecificTemplateManager interface {
|
|||
// (but does not upgrade) the packages for this distro, e.g.
|
||||
// "sudo apt update".
|
||||
CommandToUpdatePackageCache() []string
|
||||
// InstallSystemdNetworkd installs the OS-specific package for
|
||||
// systemd-networkd. Since the VM does not have network access, this
|
||||
// will require downloading the package and copying it into the VM.
|
||||
InstallSystemdNetworkd(handle *guestfs.Guestfs) error
|
||||
// InstallNetworkManager installs the OS-specific package for
|
||||
// NetworkManager.
|
||||
InstallNetworkManager(handle *guestfs.Guestfs) error
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) NeedsDynamicResolvConf() bool {
|
||||
// Assume false by default. Individual distros should override this
|
||||
// method if necessary.
|
||||
return false
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) InstallSystemdNetworkd(handle *guestfs.Guestfs) error {
|
||||
func (mgr *TemplateManager) InstallNetworkManager(handle *guestfs.Guestfs) error {
|
||||
// Individual distros should override this method if necessary
|
||||
return errors.New("InstallSystemdNetworkd: not implemented for this distro")
|
||||
return errors.New("InstallNetworkManager: not implemented for this distro")
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) DownloadTemplateGeneric(filename, url string) (path string, err error) {
|
||||
|
@ -175,6 +164,12 @@ func (mgr *TemplateManager) getGuestfsMountedHandle(filename string) (handle *gu
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Needed to install packages in VM
|
||||
log.Debug().Msg("Enabling network access")
|
||||
err = handle.Set_network(true)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Debug().Msg("Adding drive " + filename)
|
||||
if err = handle.Add_drive(filename, nil); err != nil {
|
||||
return
|
||||
|
@ -279,141 +274,37 @@ func isSameFile(handle *guestfs.Guestfs, path1, path2 string) (bool, error) {
|
|||
|
||||
var systemdDirPrefixes = []string{"/etc", "/lib"}
|
||||
|
||||
func getSystemdUnitPath(handle *guestfs.Guestfs, unit string) (string, error) {
|
||||
for _, dirPrefix := range systemdDirPrefixes {
|
||||
possibleUnitPath := dirPrefix + "/systemd/system/" + unit
|
||||
exists, err := handle.Is_file(possibleUnitPath, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not determine if %s is a file: %w", possibleUnitPath, err)
|
||||
}
|
||||
if exists {
|
||||
return possibleUnitPath, nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func getSystemdServiceWantedBy(handle *guestfs.Guestfs, unitPath string) (systemdUnitInstallInfo, error) {
|
||||
installInfo := systemdUnitInstallInfo{}
|
||||
content, err := handle.Cat(unitPath)
|
||||
if err != nil {
|
||||
return installInfo, fmt.Errorf("could not read %s: %w", unitPath, err)
|
||||
}
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "WantedBy=") {
|
||||
if installInfo.WantedBy != "" {
|
||||
return installInfo, fmt.Errorf("multiple WantedBy directives found in %s", unitPath)
|
||||
}
|
||||
installInfo.WantedBy = line[len("WantedBy="):]
|
||||
} else if strings.HasPrefix(line, "Also=") {
|
||||
installInfo.Also = append(installInfo.Also, line[len("Also="):])
|
||||
}
|
||||
}
|
||||
return installInfo, nil
|
||||
}
|
||||
|
||||
type systemdUnitInstallInfo struct {
|
||||
WantedBy string
|
||||
Also []string
|
||||
}
|
||||
|
||||
type systemdUnitInfo struct {
|
||||
UnitPath string
|
||||
Enabled bool
|
||||
systemdUnitInstallInfo
|
||||
}
|
||||
|
||||
// Returns (nil, nil) if the unit does not exist
|
||||
func getSystemdUnitInfo(handle *guestfs.Guestfs, unit string) (*systemdUnitInfo, error) {
|
||||
unitPath, err := getSystemdUnitPath(handle, unit)
|
||||
if err != nil || unitPath == "" {
|
||||
return nil, err
|
||||
}
|
||||
installInfo, err := getSystemdServiceWantedBy(handle, unitPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if installInfo.WantedBy == "" {
|
||||
return nil, fmt.Errorf("could not find WantedBy property for %s", unitPath)
|
||||
}
|
||||
linkName := ""
|
||||
for _, dirPrefix := range systemdDirPrefixes {
|
||||
possibleLinkName := dirPrefix + "/systemd/system/" + installInfo.WantedBy + ".wants/" + unit
|
||||
isSymlink, err := handle.Is_symlink(possibleLinkName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine if %s is a symlink: %w", possibleLinkName, err)
|
||||
}
|
||||
if isSymlink {
|
||||
linkName = possibleLinkName
|
||||
break
|
||||
}
|
||||
}
|
||||
unitInfo := &systemdUnitInfo{
|
||||
UnitPath: unitPath,
|
||||
systemdUnitInstallInfo: installInfo,
|
||||
}
|
||||
if linkName != "" {
|
||||
target, err := handle.Readlink(linkName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read link at %s: %w", linkName, err)
|
||||
}
|
||||
// The target might be in /usr/lib, which will likely be a symlink
|
||||
// to /lib. So we can't compare the paths directly.
|
||||
targetIsUnitFile, err := isSameFile(handle, target, unitPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !targetIsUnitFile {
|
||||
return nil, fmt.Errorf("%s is not the same as %s", target, unitPath)
|
||||
}
|
||||
unitInfo.Enabled = true
|
||||
}
|
||||
return unitInfo, nil
|
||||
func (mgr *TemplateManager) logAndRunCommand(handle *guestfs.Guestfs, args []string) (string, error) {
|
||||
mgr.logger.Debug().Msg("Running command `" + strings.Join(args, " ") + "`")
|
||||
return handle.Command(args)
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) enableSystemdUnit(handle *guestfs.Guestfs, unit string) error {
|
||||
unitInfo, err := getSystemdUnitInfo(handle, unit)
|
||||
if err != nil {
|
||||
_, err := mgr.logAndRunCommand(handle, []string{
|
||||
"systemctl", "enable", unit,
|
||||
})
|
||||
return err
|
||||
}
|
||||
if unitInfo == nil {
|
||||
return fmt.Errorf("Unit %s does not exist", unit)
|
||||
}
|
||||
if unitInfo.Enabled {
|
||||
return nil
|
||||
}
|
||||
if unitInfo.WantedBy == "" {
|
||||
return fmt.Errorf("%s does not have WantedBy directive", unit)
|
||||
}
|
||||
wantsDir := "/etc/systemd/system/" + unitInfo.WantedBy + ".wants"
|
||||
mgr.logger.Debug().Msg("mkdir -p " + wantsDir)
|
||||
err = handle.Mkdir_p(wantsDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
linkPath := wantsDir + "/" + unit
|
||||
mgr.logger.Debug().Msg("ln -sf " + unitInfo.UnitPath + " " + linkPath)
|
||||
err = handle.Ln_sf(unitInfo.UnitPath, linkPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
unitInfo.Enabled = true
|
||||
for _, also := range unitInfo.Also {
|
||||
err = mgr.enableSystemdUnit(handle, also)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func systemdServiceIsEnabled(handle *guestfs.Guestfs, unit string) (bool, error) {
|
||||
unitInfo, err := getSystemdUnitInfo(handle, unit)
|
||||
if err != nil || unitInfo == nil {
|
||||
func (mgr *TemplateManager) systemdServiceIsEnabled(handle *guestfs.Guestfs, unit string) (bool, error) {
|
||||
// Use '|| true' because the exit code will be non-zero if the unit
|
||||
// is not enabled or does not exist
|
||||
command := "systemctl is-enabled " + unit + " || true"
|
||||
mgr.logger.Debug().Msg(`Running sh -c "` + command + `"`)
|
||||
output, err := handle.Sh(command)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return unitInfo.Enabled, nil
|
||||
// Strip newline, if there is one
|
||||
if len(output) > 0 && output[len(output)-1] == '\n' {
|
||||
output = output[:len(output)-1]
|
||||
}
|
||||
if output == "enabled" {
|
||||
return true, nil
|
||||
} else if output == "disabled" || output == "not-found" {
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.New("Unexpected output '" + output + "'")
|
||||
}
|
||||
|
||||
// setChronyOptions sets custom NTP server URLs in a chrony config file.
|
||||
|
@ -515,28 +406,28 @@ func (mgr *TemplateManager) setTimesyncdConf(handle *guestfs.Guestfs) error {
|
|||
return handle.Write("/etc/systemd/timesyncd.conf.d/csclub.conf", getResource("timesyncd.conf"))
|
||||
}
|
||||
|
||||
func usesChrony(handle *guestfs.Guestfs) (bool, error) {
|
||||
func (mgr *TemplateManager) usesChrony(handle *guestfs.Guestfs) (bool, error) {
|
||||
// The systemd service for chrony is called on chrony.service on e.g. Debian,
|
||||
// but is called chronyd.service on e.g. Fedora
|
||||
chronyIsEnabled, err := systemdServiceIsEnabled(handle, "chrony.service")
|
||||
chronyIsEnabled, err := mgr.systemdServiceIsEnabled(handle, "chrony.service")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if chronyIsEnabled {
|
||||
return true, nil
|
||||
}
|
||||
return systemdServiceIsEnabled(handle, "chronyd.service")
|
||||
return mgr.systemdServiceIsEnabled(handle, "chronyd.service")
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) setupCommonNTPConfigs(handle *guestfs.Guestfs) error {
|
||||
usesChrony, err := usesChrony(handle)
|
||||
usesChrony, err := mgr.usesChrony(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesChrony {
|
||||
return mgr.setChronyOptions(handle)
|
||||
}
|
||||
usesSystemdTimesyncd, err := systemdServiceIsEnabled(handle, "systemd-timesyncd.service")
|
||||
usesSystemdTimesyncd, err := mgr.systemdServiceIsEnabled(handle, "systemd-timesyncd.service")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -555,11 +446,11 @@ func (mgr *TemplateManager) setNetworkManagerOptions(handle *guestfs.Guestfs) (e
|
|||
return handle.Write(path, getResource("network-manager-snippet"))
|
||||
}
|
||||
|
||||
func usesNetworkManager(handle *guestfs.Guestfs) (bool, error) {
|
||||
return systemdServiceIsEnabled(handle, "NetworkManager.service")
|
||||
func (mgr *TemplateManager) usesNetworkManager(handle *guestfs.Guestfs) (bool, error) {
|
||||
return mgr.systemdServiceIsEnabled(handle, "NetworkManager.service")
|
||||
}
|
||||
|
||||
func usesEtcNetworkInterfaces(handle *guestfs.Guestfs) (bool, error) {
|
||||
func (mgr *TemplateManager) usesEtcNetworkInterfaces(handle *guestfs.Guestfs) (bool, error) {
|
||||
configPath := "/etc/network/interfaces"
|
||||
configExists, err := handle.Is_file(configPath, nil)
|
||||
if err != nil {
|
||||
|
@ -568,16 +459,7 @@ func usesEtcNetworkInterfaces(handle *guestfs.Guestfs) (bool, error) {
|
|||
if !configExists {
|
||||
return false, nil
|
||||
}
|
||||
return systemdServiceIsEnabled(handle, "networking.service")
|
||||
}
|
||||
|
||||
func usesSysconfigNetwork(handle *guestfs.Guestfs) (bool, error) {
|
||||
configPath := "/etc/sysconfig/network/config"
|
||||
configExists, err := handle.Is_file(configPath, nil)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Could not determine if "+configPath+" is a file: %w", err)
|
||||
}
|
||||
return configExists, err
|
||||
return mgr.systemdServiceIsEnabled(handle, "networking.service")
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) addSystemdNetworkdCloudInitSnippet(handle *guestfs.Guestfs) error {
|
||||
|
@ -587,62 +469,54 @@ func (mgr *TemplateManager) addSystemdNetworkdCloudInitSnippet(handle *guestfs.G
|
|||
return handle.Write(path, getResource("systemd-networkd-cloud-init"))
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) installAndEnableSystemdNetworkd(handle *guestfs.Guestfs) error {
|
||||
isInstalled, err := handle.Is_file("/lib/systemd/system/systemd-networkd.service", nil)
|
||||
func (mgr *TemplateManager) installAndEnableNetworkManager(handle *guestfs.Guestfs) error {
|
||||
isInstalled, err := handle.Is_file("/lib/systemd/system/NetworkManager.service", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isInstalled {
|
||||
err = mgr.impl.InstallSystemdNetworkd(handle)
|
||||
err = mgr.impl.InstallNetworkManager(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return mgr.enableSystemdUnit(handle, "systemd-networkd.service")
|
||||
return mgr.enableSystemdUnit(handle, "NetworkManager.service")
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) setupCommonNetworkConfigs(handle *guestfs.Guestfs) error {
|
||||
usesNetworkManager, err := usesNetworkManager(handle)
|
||||
usesNetworkManager, err := mgr.usesNetworkManager(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesNetworkManager {
|
||||
return mgr.setNetworkManagerOptions(handle)
|
||||
}
|
||||
usesSystemdNetworkd, err := systemdServiceIsEnabled(handle, "systemd-networkd.service")
|
||||
usesSystemdNetworkd, err := mgr.systemdServiceIsEnabled(handle, "systemd-networkd.service")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesSystemdNetworkd {
|
||||
return mgr.addSystemdNetworkdCloudInitSnippet(handle)
|
||||
}
|
||||
usesEtcNetworkInterfaces, err := usesEtcNetworkInterfaces(handle)
|
||||
usesEtcNetworkInterfaces, err := mgr.usesEtcNetworkInterfaces(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesEtcNetworkInterfaces {
|
||||
return mgr.setDhclientOptions(handle)
|
||||
}
|
||||
usesSysconfigNetwork, err := usesSysconfigNetwork(handle)
|
||||
mgr.logger.Info().Msg("Could not determine network backend, resorting to installing NetworkManager")
|
||||
err = mgr.installAndEnableNetworkManager(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if usesSysconfigNetwork {
|
||||
// Handled separately in opensuse_tumbleweed.go
|
||||
return nil
|
||||
}
|
||||
mgr.logger.Info().Msg("Could not determine network backend, resorting to installing systemd-networkd")
|
||||
err = mgr.installAndEnableSystemdNetworkd(handle)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return mgr.addSystemdNetworkdCloudInitSnippet(handle)
|
||||
return mgr.setNetworkManagerOptions(handle)
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) setupIpv6Scripts(handle *guestfs.Guestfs) (err error) {
|
||||
log := mgr.logger
|
||||
scripts := []string{"99_csclub_ipv6_addr.sh"}
|
||||
usesNetworkManager, err := usesNetworkManager(handle)
|
||||
usesNetworkManager, err := mgr.usesNetworkManager(handle)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -671,25 +545,11 @@ func (mgr *TemplateManager) setupIpv6Scripts(handle *guestfs.Guestfs) (err error
|
|||
}
|
||||
|
||||
func (mgr *TemplateManager) setResolvConf(handle *guestfs.Guestfs) (err error) {
|
||||
if mgr.impl.NeedsDynamicResolvConf() {
|
||||
scriptDir := "/var/lib/cloud/scripts/per-boot"
|
||||
if err = handle.Mkdir_p(scriptDir); err != nil {
|
||||
return
|
||||
}
|
||||
filename := "97_csclub_resolv_conf.sh"
|
||||
path := scriptDir + "/" + filename
|
||||
mgr.logger.Debug().Msg("Writing to " + path)
|
||||
if err = handle.Write(path, getResource(filename)); err != nil {
|
||||
return
|
||||
}
|
||||
return handle.Chmod(0755, path)
|
||||
} else {
|
||||
mgr.logger.Debug().Msg("Writing to /etc/resolv.conf")
|
||||
if err = handle.Rm_f("/etc/resolv.conf"); err != nil {
|
||||
return
|
||||
}
|
||||
return handle.Write("/etc/resolv.conf", getResource("resolv.conf"))
|
||||
}
|
||||
}
|
||||
|
||||
func (mgr *TemplateManager) createAugeasHandle(handle *guestfs.Guestfs) (err error) {
|
||||
|
@ -906,16 +766,14 @@ func (mgr *TemplateManager) dnfRemoveUnnecessaryPackages(handle *guestfs.Guestfs
|
|||
// auditd spams the system log and uses lots of disk IO.
|
||||
// bluez is unnecessary on servers.
|
||||
args := []string{"dnf", "-C", "remove", "-y", "sssd-common", "audit", "bluez"}
|
||||
mgr.logger.Debug().Msg("Running '" + strings.Join(args, " ") + "'")
|
||||
_, err = handle.Command(args)
|
||||
_, err = mgr.logAndRunCommand(handle, args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Now that we removed SSSD, we also have to make sure that it's not being used in PAM.
|
||||
// The way to do this on Fedora (and likely other RHEL-based distros) is with authselect.
|
||||
args = []string{"authselect", "select", "minimal"}
|
||||
mgr.logger.Debug().Msg("Running '" + strings.Join(args, " ") + "'")
|
||||
_, err = handle.Command(args)
|
||||
_, err = mgr.logAndRunCommand(handle, args)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -9,4 +9,4 @@ if ! [ -e /usr/bin/qemu-img ]; then
|
|||
export PATH="$DEPS_DIR/usr/bin:$PATH"
|
||||
fi
|
||||
set -x
|
||||
exec $GUESTFISH
|
||||
exec $GUESTFISH --network
|
||||
|
|
Loading…
Reference in New Issue