Safe HaskellNone



KVM daemon

The KVM daemon is responsible for determining whether a given KVM instance was shutdown by an administrator or a user. For more information read the design document on the KVM daemon.

The KVM daemon design is split in 2 parts, namely, monitors for Qmp sockets and directory/file watching.

The monitors are spawned in lightweight Haskell threads and are reponsible for handling the communication between the KVM daemon and the KVM instance using the Qmp protocol. During the communcation, the monitor parses the Qmp messages and if powerdown or shutdown is received, then the shutdown file is written in the KVM control directory. Otherwise, when the communication terminates, that same file is removed. The communication terminates when the KVM instance stops or crashes.

The directory and file watching uses inotify to track down events on the KVM control directory and its parents. There is a directory crawler that will try to add a watch to the KVM control directory if available or its parents, thus replacing watches until the KVM control directory becomes available. When this happens, a monitor for the Qmp socket is spawned. Given that the KVM daemon might stop or crash, the directory watching also simulates events for the Qmp sockets that already exist in the KVM control directory when the KVM daemon starts.



type Lock = MVar () Source #

type Monitors = MVar (Set FilePath) Source #


isPrefixPath :: FilePath -> FilePath -> Bool Source #

isPrefixPath x y determines whether x is a FilePath prefix of FilePath y.

monitorDir :: String Source #

KVM control directory containing the Qmp sockets.

isMonitorPath :: FilePath -> Bool Source #

shutdownPath :: String -> String Source #

touchFile :: FilePath -> IO () Source #

Monitors for Qmp sockets

parseQmp :: Bool -> Bool -> Bool -> String -> (Bool, Bool, Bool) Source #

parseQmp isPowerdown isShutdown isStop str parses the packet str and returns whether a powerdown, shutdown, or stop event is contained in that packet, defaulting to the values isPowerdown, isShutdown, and isStop, otherwise.

receiveQmp :: Handle -> IO Bool Source #

receiveQmp handle listens for Qmp events on handle and, when handle is closed, it returns True if a user shutdown event was received, and False otherwise.

detectMonitor :: FilePath -> Handle -> IO () Source #

detectMonitor monitorFile handle listens for Qmp events on handle for Qmp socket monitorFile and, when communcation terminates, it either creates the shutdown file, if a user shutdown was detected, or it deletes that same file, if an administrator shutdown was detected.

runMonitor :: FilePath -> IO () Source #

runMonitor monitorFile creates a monitor for the Qmp socket monitorFile and calls detectMonitor.

ensureMonitor :: Monitors -> FilePath -> IO () Source #

ensureMonitor monitors monitorFile ensures that there is exactly one monitor running for the Qmp socket monitorFile, given the existing set of monitors monitors.

Directory and file watching

handleGenericEvent :: Lock -> String -> String -> Event -> IO () Source #

Handles an inotify event outside the target directory.

Tracks events on the parent directory of the KVM control directory until one of its parents becomes available.

handleTargetEvent :: Lock -> Monitors -> String -> Event -> IO () Source #

Handles an inotify event in the target directory.

Upon a create or open event inside the KVM control directory, it ensures that there is a monitor running for the new Qmp socket.

handleDir :: Lock -> Monitors -> String -> String -> Event -> IO () Source #

Dispatches inotify events depending on the directory they occur in.

recapDir :: Lock -> Monitors -> FilePath -> IO () Source #

Simulates file creation events for the Qmp sockets that already exist in dir.

watchDir :: Lock -> FilePath -> INotify -> IO () Source #

Crawls tarDir, or its parents until tarDir becomes available, always listening for inotify events.

Used for crawling the KVM control directory and its parents, as well as simulating file creation events.

rewatchDir :: Lock -> FilePath -> INotify -> IO () Source #

Starting point

startWith :: FilePath -> IO () Source #

start :: IO () Source #