Skip to content

Commit

Permalink
[guest-log] Avoid reporting error if the socket file got closed
Browse files Browse the repository at this point in the history
When a shutdown of the guest OS got
triggered from the guest,
the socket file for the serial console
device could get removed even before virt-launcher-monitor
detects that the VM is down and made virt-tail aware.

Due to that, virt-tail should not exit with an error
when the socket file for the serial console gets removed.

Signed-off-by: Simone Tiraboschi <[email protected]>
  • Loading branch information
tiraboschi committed Jan 15, 2024
1 parent 024e823 commit a0edb23
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
11 changes: 8 additions & 3 deletions cmd/virt-tail/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,16 @@ import (
)

type TermFileError struct{}
type SocketFileError struct{}

func (m *TermFileError) Error() string {
return "termFile got detected"
}

func (m *SocketFileError) Error() string {
return "socketFile got removed"
}

type VirtTail struct {
ctx context.Context
logFile string
Expand Down Expand Up @@ -164,7 +169,7 @@ func (v *VirtTail) watchFS() error {
} else if event.Has(fsnotify.Remove) {
if event.Name == socketFile {
// socket file got deleted, we should quickly terminate
rerr := errors.New("socketFile got removed")
rerr := &SocketFileError{}
log.Log.V(3).Infof("watchFS error: %v", rerr)
return rerr
} else if event.Name == termFile {
Expand Down Expand Up @@ -216,11 +221,11 @@ func main() {

// wait for all errgroup goroutines
if err := g.Wait(); err != nil {
// Exit cleanly on clean termination errors
if !(errors.Is(err, context.Canceled) || errors.Is(err, &TermFileError{})) {
if !(errors.Is(err, context.Canceled) || errors.Is(err, &TermFileError{}) || errors.Is(err, &SocketFileError{})) {
log.Log.V(3).Infof("received error: %v", err)
os.Exit(1)
}
// Exit cleanly on clean termination errors
}
}

Expand Down
1 change: 1 addition & 0 deletions tests/guestlog/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
"//tests/decorators:go_default_library",
"//tests/exec:go_default_library",
"//tests/framework/kubevirt:go_default_library",
"//tests/framework/matcher:go_default_library",
"//tests/libvmi:go_default_library",
"//tests/testsuite:go_default_library",
"//vendor/github.com/google/goexpect:go_default_library",
Expand Down
33 changes: 33 additions & 0 deletions tests/guestlog/guestlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"kubevirt.io/kubevirt/tests/console"
"kubevirt.io/kubevirt/tests/decorators"
"kubevirt.io/kubevirt/tests/framework/kubevirt"
. "kubevirt.io/kubevirt/tests/framework/matcher"
"kubevirt.io/kubevirt/tests/libvmi"
"kubevirt.io/kubevirt/tests/testsuite"
)
Expand Down Expand Up @@ -90,6 +91,38 @@ var _ = Describe("[sig-compute]Guest console log", decorators.SigCompute, func()
Entry("without AutoattachSerialConsole but with LogSerialConsole", false, true, false),
Entry("without AutoattachSerialConsole and without LogSerialConsole", false, false, false),
)

It("it should exit cleanly when the shutdown is initiated by the guest", func() {
By("Starting a VMI")
vmi := tests.RunVMIAndExpectLaunch(cirrosVmi, cirrosStartupTimeout)

By("Finding virt-launcher pod")
virtlauncherPod, err := libvmi.GetPodByVirtualMachineInstance(vmi, testsuite.GetTestNamespace(vmi))
Expect(err).ToNot(HaveOccurred())
foundContainer := false
for _, container := range virtlauncherPod.Spec.Containers {
if container.Name == "guest-console-log" {
foundContainer = true
}
}
Expect(foundContainer).To(Equal(true))

By("Triggering a shutdown from the guest OS")
Expect(console.LoginToCirros(vmi)).To(Succeed())
Expect(console.SafeExpectBatch(vmi, []expect.Batcher{
&expect.BSnd{S: "sudo poweroff\n"},
&expect.BExp{R: "The system is going down NOW!"},
}, 240)).To(Succeed())

By("Ensuring virt-launcher pod is not reporting errors")
Eventually(func(g Gomega) {
virtlauncherPod, err := ThisPod(virtlauncherPod)()
g.Expect(err).ToNot(HaveOccurred())
Expect(virtlauncherPod).ToNot(BeInPhase(k8sv1.PodFailed))
g.Expect(virtlauncherPod).To(BeInPhase(k8sv1.PodSucceeded))
}, 60*time.Second, 1*time.Second).Should(Succeed(), "virt-launcher should reach the PodSucceeded phase never hitting the PodFailed one")
})

})

Context("fetch logs", func() {
Expand Down

0 comments on commit a0edb23

Please sign in to comment.