Skip to content

Commit

Permalink
IH-543: Add IPMI DCMI based power reading rrdd plugin
Browse files Browse the repository at this point in the history
Guard against buggy firmware by ignoring 0 or 65535 Watts
(although xcp-rrdd doesn't actually correctly ignore these yet).

Future-proof plugin by parsing Watts as float, although currently
it is always an integer in the DCMI spec.

Signed-off-by: Edwin Török <[email protected]>
  • Loading branch information
edwintorok committed Apr 22, 2024
1 parent c9bb1f2 commit 22d20ed
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ install: build doc sdk doc-json
install -D -m 755 _build/install/default/bin/xcp-rrdd-iostat $(DESTDIR)$(LIBEXECDIR)/xcp-rrdd-plugins/xcp-rrdd-iostat
install -D -m 755 _build/install/default/bin/xcp-rrdd-squeezed $(DESTDIR)$(LIBEXECDIR)/xcp-rrdd-plugins/xcp-rrdd-squeezed
install -D -m 755 _build/install/default/bin/xcp-rrdd-xenpm $(DESTDIR)$(LIBEXECDIR)/xcp-rrdd-plugins/xcp-rrdd-xenpm
install -D -m 755 _build/install/default/bin/xcp-rrdd-dcmi $(DESTDIR)$(LIBEXECDIR)/xcp-rrdd-plugins/xcp-rrdd-dcmi
install -D -m 644 ocaml/xcp-rrdd/bugtool-plugin/rrdd-plugins.xml $(DESTDIR)$(ETCXENDIR)/bugtool/xcp-rrdd-plugins.xml
install -D -m 644 ocaml/xcp-rrdd/bugtool-plugin/rrdd-plugins/stuff.xml $(DESTDIR)$(ETCXENDIR)/bugtool/xcp-rrdd-plugins/stuff.xml
install -D -m 755 ocaml/xcp-rrdd/bin/rrdp-scripts/sysconfig-rrdd-plugins $(DESTDIR)/etc/sysconfig/xcp-rrdd-plugins
Expand Down
16 changes: 16 additions & 0 deletions ocaml/xcp-rrdd/bin/rrdp-dcmi/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(executable
(modes exe)
(name rrdp_dcmi)
(package rrdd-plugins)
(public_name xcp-rrdd-dcmi)
(libraries
dune-build-info
rrdd-plugin
rrdd-plugins.libs
xapi-idl.rrd
xapi-log
xapi-rrd
astring
)
)

80 changes: 80 additions & 0 deletions ocaml/xcp-rrdd/bin/rrdp-dcmi/rrdp_dcmi.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
(*
* Copyright (c) 2024 Cloud Software Group, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)

(** Read power measurements from IPMI DCMI where available.
There is also IPMI SDR entity 21 that returns the same information (power consumption in watts),
but isn't always available, and seems to be slower to read, especially when missing.
*)

open Rrdd_plugin

module Process = Process (struct let name = "xcp-rrdd-dcmi" end)

open Process

let ipmitool_bin = "/usr/bin/ipmitool"

let ipmitool args =
(* we connect to the local /dev/ipmi0 if available to read measurements from local BMC *)
ipmitool_bin :: "-I" :: "open" :: args |> String.concat " "

let discover () =
Utils.exec_cmd
(module Process.D)
~cmdstring:(ipmitool ["dcmi"; "discover"])
~f:(fun line ->
(* this code runs once on startup, logging all the output here will be useful for debugging *)
D.debug "DCMI discover: %s" line ;
if String.trim line = "Power management available" then
Some ()
else
None
)

let get_dcmi_power_reading () =
Utils.exec_cmd
(module Process.D)
~cmdstring:(ipmitool ["dcmi"; "power"; "reading"])
~f:(fun line ->
(* example line: ' Instantaneous power reading: 34 Watts' *)
try
Scanf.sscanf line " Instantaneous power reading : %f Watts" Option.some
with Scanf.Scan_failure _ | End_of_file -> None
)

let gen_dcmi_power_reading value =
( Rrd.Host
, Ds.ds_make ~name:"DCMI-power-reading"
~description:"Host power usage reported by IPMI DCMI"
~value:(Rrd.VT_Float value) ~ty:Rrd.Gauge ~default:true ~units:"W"
~min:Float.min_float ~max:65534. ()
)

let generate_dss () =
match get_dcmi_power_reading () with
| watts :: _ ->
[gen_dcmi_power_reading watts]
| _ ->
[]

let _ =
initialise () ;
match discover () with
| [] ->
D.info "IPMI DCMI power reading is unavailable" ;
exit 1
| _ ->
D.info "IPMI DCMI power reading is available" ;
main_loop ~neg_shift:0.5 ~target:(Reporter.Local 1)
~protocol:Rrd_interface.V2 ~dss_f:generate_dss
Empty file.
2 changes: 1 addition & 1 deletion ocaml/xcp-rrdd/bin/rrdp-scripts/sysconfig-rrdd-plugins
Original file line number Diff line number Diff line change
@@ -1 +1 @@
PLUGINS="xcp-rrdd-iostat xcp-rrdd-squeezed xcp-rrdd-xenpm"
PLUGINS="xcp-rrdd-iostat xcp-rrdd-squeezed xcp-rrdd-xenpm xcp-rrdd-dcmi"

0 comments on commit 22d20ed

Please sign in to comment.