|
| 1 | +(* Ipmi-based monitor *) |
| 2 | +open Eio |
| 3 | +open Eio_luv.Low_level |
| 4 | + |
| 5 | +module Ipmi = struct |
| 6 | + let ipmi args = ("sudo", "sudo" :: "ipmitool" :: args) |
| 7 | + let power_consumption = ipmi [ "sensor"; "reading"; "Pwr Consumption"; "-c" ] |
| 8 | + |
| 9 | + let parse_power_consumption s = |
| 10 | + match String.split_on_char ',' (String.trim s) with |
| 11 | + | "Pwr Consumption" :: watts :: _ -> int_of_string watts |
| 12 | + | _ -> failwith "Couldn't parse the power consumption" |
| 13 | +end |
| 14 | + |
| 15 | +type t = { clock : Eio.Time.clock } |
| 16 | + |
| 17 | +let supported = true |
| 18 | + |
| 19 | +let read_all handle buf = |
| 20 | + let rec read acc = |
| 21 | + try |
| 22 | + let i = Eio_luv.Low_level.Stream.read_into handle buf in |
| 23 | + read (acc + i) |
| 24 | + with End_of_file -> acc |
| 25 | + in |
| 26 | + read 0 |
| 27 | + |
| 28 | +let get_power_consumption () = |
| 29 | + let cmd, args = Ipmi.power_consumption in |
| 30 | + let parent_pipe = Eio_luv.Low_level.Pipe.init () in |
| 31 | + Switch.run @@ fun sw -> |
| 32 | + let handle = Eio_luv.Low_level.Pipe.to_handle ~sw parent_pipe in |
| 33 | + let buf = Luv.Buffer.create 64 in |
| 34 | + let redirect = |
| 35 | + Eio_luv.Low_level.Process. |
| 36 | + [ to_parent_pipe ~fd:Luv.Process.stdout ~parent_pipe () ] |
| 37 | + in |
| 38 | + let t = Process.spawn ~redirect cmd args in |
| 39 | + let _ = Process.await_exit t in |
| 40 | + let read = read_all handle buf in |
| 41 | + Luv.Buffer.to_string (Luv.Buffer.sub buf ~offset:0 ~length:read) |
| 42 | + |
| 43 | +let collect t = |
| 44 | + let pc = |
| 45 | + get_power_consumption () |> Ipmi.parse_power_consumption |> float_of_int |
| 46 | + in |
| 47 | + Info.v (Option.get (Ptime.of_float_s @@ Time.now t.clock)) pc |
0 commit comments