mirror of
https://github.com/containers/podman.git
synced 2025-10-16 18:53:19 +08:00
Merge pull request #21262 from n1hility/net-recovery
Add a net health recovery service to qemu machines
This commit is contained in:
@ -53,15 +53,16 @@ func GetNodeGrp(grpName string) NodeGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DynamicIgnition struct {
|
type DynamicIgnition struct {
|
||||||
Name string
|
Name string
|
||||||
Key string
|
Key string
|
||||||
TimeZone string
|
TimeZone string
|
||||||
UID int
|
UID int
|
||||||
VMName string
|
VMName string
|
||||||
VMType define.VMType
|
VMType define.VMType
|
||||||
WritePath string
|
WritePath string
|
||||||
Cfg Config
|
Cfg Config
|
||||||
Rootful bool
|
Rootful bool
|
||||||
|
NetRecover bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ign *DynamicIgnition) Write() error {
|
func (ign *DynamicIgnition) Write() error {
|
||||||
@ -97,7 +98,7 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
|
|||||||
|
|
||||||
ignStorage := Storage{
|
ignStorage := Storage{
|
||||||
Directories: getDirs(ign.Name),
|
Directories: getDirs(ign.Name),
|
||||||
Files: getFiles(ign.Name, ign.UID, ign.Rootful, ign.VMType),
|
Files: getFiles(ign.Name, ign.UID, ign.Rootful, ign.VMType, ign.NetRecover),
|
||||||
Links: getLinks(ign.Name),
|
Links: getLinks(ign.Name),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +259,21 @@ ExecStart=-/usr/sbin/agetty --autologin root --noclear %I $TERM
|
|||||||
}
|
}
|
||||||
ignSystemd.Units = append(ignSystemd.Units, qemuUnit)
|
ignSystemd.Units = append(ignSystemd.Units, qemuUnit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ign.NetRecover {
|
||||||
|
contents, err := GetNetRecoveryUnitFile().ToString()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
recoveryUnit := Unit{
|
||||||
|
Enabled: BoolToPtr(true),
|
||||||
|
Name: "net-health-recovery.service",
|
||||||
|
Contents: &contents,
|
||||||
|
}
|
||||||
|
ignSystemd.Units = append(ignSystemd.Units, recoveryUnit)
|
||||||
|
}
|
||||||
|
|
||||||
// Only after all checks are done
|
// Only after all checks are done
|
||||||
// it's ready create the ingConfig
|
// it's ready create the ingConfig
|
||||||
ign.Cfg = Config{
|
ign.Cfg = Config{
|
||||||
@ -330,7 +346,7 @@ func getDirs(usrName string) []Directory {
|
|||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType) []File {
|
func getFiles(usrName string, uid int, rootful bool, vmtype define.VMType, netRecover bool) []File {
|
||||||
files := make([]File, 0)
|
files := make([]File, 0)
|
||||||
|
|
||||||
lingerExample := parser.NewUnitFile()
|
lingerExample := parser.NewUnitFile()
|
||||||
@ -601,6 +617,23 @@ Delegate=memory pids cpu io
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Only necessary for qemu on mac
|
||||||
|
if netRecover {
|
||||||
|
files = append(files, File{
|
||||||
|
Node: Node{
|
||||||
|
User: GetNodeUsr("root"),
|
||||||
|
Group: GetNodeGrp("root"),
|
||||||
|
Path: "/usr/local/bin/net-health-recovery.sh",
|
||||||
|
},
|
||||||
|
FileEmbedded1: FileEmbedded1{
|
||||||
|
Mode: IntToPtr(0755),
|
||||||
|
Contents: Resource{
|
||||||
|
Source: EncodeDataURLPtr(GetNetRecoveryFile()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,6 +803,37 @@ func (i *IgnitionBuilder) Build() error {
|
|||||||
return i.dynamicIgnition.Write()
|
return i.dynamicIgnition.Write()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetNetRecoveryFile() string {
|
||||||
|
return `#!/bin/bash
|
||||||
|
# Verify network health, and bounce the network device if host connectivity
|
||||||
|
# is lost. This is a temporary workaround for a known rare qemu/virtio issue
|
||||||
|
# that affects some systems
|
||||||
|
|
||||||
|
sleep 120 # allow time for network setup on initial boot
|
||||||
|
while true; do
|
||||||
|
sleep 30
|
||||||
|
curl -s -o /dev/null --max-time 30 http://192.168.127.1/health
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo "bouncing nic due to loss of connectivity with host"
|
||||||
|
ifconfig enp0s1 down; ifconfig enp0s1 up
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNetRecoveryUnitFile() *parser.UnitFile {
|
||||||
|
recoveryUnit := parser.NewUnitFile()
|
||||||
|
recoveryUnit.Add("Unit", "Description", "Verifies health of network and recovers if necessary")
|
||||||
|
recoveryUnit.Add("Unit", "After", "sshd.socket sshd.service")
|
||||||
|
recoveryUnit.Add("Service", "ExecStart", "/usr/local/bin/net-health-recovery.sh")
|
||||||
|
recoveryUnit.Add("Service", "StandardOutput", "journal")
|
||||||
|
recoveryUnit.Add("Service", "StandardError", "journal")
|
||||||
|
recoveryUnit.Add("Service", "StandardInput", "null")
|
||||||
|
recoveryUnit.Add("Install", "WantedBy", "default.target")
|
||||||
|
|
||||||
|
return recoveryUnit
|
||||||
|
}
|
||||||
|
|
||||||
func DefaultReadyUnitFile() parser.UnitFile {
|
func DefaultReadyUnitFile() parser.UnitFile {
|
||||||
u := parser.NewUnitFile()
|
u := parser.NewUnitFile()
|
||||||
u.Add("Unit", "After", "remove-moby.service sshd.socket sshd.service")
|
u.Add("Unit", "After", "remove-moby.service sshd.socket sshd.service")
|
||||||
|
@ -194,14 +194,15 @@ func (v *MachineVM) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
|
builder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
|
||||||
Name: opts.Username,
|
Name: opts.Username,
|
||||||
Key: key,
|
Key: key,
|
||||||
VMName: v.Name,
|
VMName: v.Name,
|
||||||
VMType: define.QemuVirt,
|
VMType: define.QemuVirt,
|
||||||
TimeZone: opts.TimeZone,
|
TimeZone: opts.TimeZone,
|
||||||
WritePath: v.getIgnitionFile(),
|
WritePath: v.getIgnitionFile(),
|
||||||
UID: v.UID,
|
UID: v.UID,
|
||||||
Rootful: v.Rootful,
|
Rootful: v.Rootful,
|
||||||
|
NetRecover: useNetworkRecover(),
|
||||||
})
|
})
|
||||||
|
|
||||||
// If the user provides an ignition file, we need to
|
// If the user provides an ignition file, we need to
|
||||||
|
@ -11,3 +11,7 @@ func getRuntimeDir() (string, error) {
|
|||||||
}
|
}
|
||||||
return tmpDir, nil
|
return tmpDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useNetworkRecover() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -11,3 +11,7 @@ func getRuntimeDir() (string, error) {
|
|||||||
}
|
}
|
||||||
return tmpDir, nil
|
return tmpDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useNetworkRecover() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -11,3 +11,7 @@ func getRuntimeDir() (string, error) {
|
|||||||
}
|
}
|
||||||
return util.GetRootlessRuntimeDir()
|
return util.GetRootlessRuntimeDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useNetworkRecover() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -11,3 +11,7 @@ func getRuntimeDir() (string, error) {
|
|||||||
}
|
}
|
||||||
return tmpDir, nil
|
return tmpDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func useNetworkRecover() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user