2 * collectd - src/lpar.c
3 * Copyright (C) 2010 Aurélien Reynaud
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Aurelien Reynaud <collectd at wattapower.net>
26 #include <sys/protosw.h>
27 #include <libperfstat.h>
28 #include <sys/systemcfg.h>
29 #include <sys/utsname.h>
32 # define XINTFRAC ((double)(_system_configuration.Xint) / \
33 (double)(_system_configuration.Xfrac))
36 static const char *config_keys[] =
40 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
41 static int pool_stats = 0;
43 /* As an LPAR can be moved transparently across physical systems
44 * through Live Partition Mobility (LPM), and the resources we are
45 * monitoring are tied to the underlying hardware, we need to keep
46 * track on which physical server we are currently on. This is done
47 * through the plugin instance which holds the chassis' serial.
49 static u_longlong_t last_time_base;
50 static u_longlong_t last_pcpu_user,
54 static u_longlong_t last_pool_idle_time = 0;
55 static u_longlong_t last_idle_donated_purr = 0,
56 last_busy_donated_purr = 0,
57 last_busy_stolen_purr = 0,
58 last_idle_stolen_purr = 0;
59 static int donate_flag = 0;
62 /* Save the current values for the next iteration */
63 static void save_last_values (perfstat_partition_total_t *lparstats)
65 last_time_base = lparstats->timebase_last;
67 last_pcpu_user = lparstats->puser;
68 last_pcpu_sys = lparstats->psys;
69 last_pcpu_idle = lparstats->pidle;
70 last_pcpu_wait = lparstats->pwait;
74 last_idle_donated_purr = lparstats->idle_donated_purr;
75 last_busy_donated_purr = lparstats->busy_donated_purr;
76 last_busy_stolen_purr = lparstats->busy_stolen_purr;
77 last_idle_stolen_purr = lparstats->idle_stolen_purr;
80 last_pool_idle_time = lparstats->pool_idle_time;
83 static int lpar_config (const char *key, const char *value)
85 if (strcasecmp ("CpuPoolStats", key) == 0)
98 } /* int lpar_config */
100 static int lpar_init (void)
102 perfstat_partition_total_t lparstats;
104 /* retrieve the initial metrics */
105 if (!perfstat_partition_total (NULL, &lparstats,
106 sizeof (perfstat_partition_total_t), 1))
108 ERROR ("lpar plugin: perfstat_partition_total failed.");
112 if (!lparstats.type.b.shared_enabled && lparstats.type.b.donate_enabled)
117 /* save the initial data */
118 save_last_values (&lparstats);
121 } /* int lpar_init */
123 static void lpar_submit (const char *plugin_inst, const char *type_instance, double value)
126 value_list_t vl = VALUE_LIST_INIT;
128 values[0].gauge = (gauge_t)value;
132 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
133 sstrncpy (vl.plugin, "lpar", sizeof (vl.plugin));
134 sstrncpy (vl.plugin_instance, plugin_inst, sizeof (vl.plugin));
135 sstrncpy (vl.type, "lpar_pcpu", sizeof (vl.type));
136 sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
138 plugin_dispatch_values (&vl);
141 static int submit_counter (const char *plugin_instance, /* {{{ */
142 const char *type, const char *type_instance, counter_t value)
145 value_list_t vl = VALUE_LIST_INIT;
147 values[0].counter = value;
151 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
152 sstrncpy (vl.plugin, "lpar", sizeof (vl.plugin));
153 sstrncpy (vl.plugin_instance, plugin_inst, sizeof (vl.plugin));
154 sstrncpy (vl.type, type, sizeof (vl.type));
155 sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
157 return (plugin_dispatch_values (&vl));
158 } /* }}} int submit_counter */
160 static int lpar_read (void)
162 u_longlong_t delta_time_base;
163 perfstat_partition_total_t lparstats;
165 char plugin_inst[DATA_MAX_NAME_LEN];
166 _Bool have_donate = 0;
168 /* retrieve the current physical server's id and build the plugin
170 if (uname (&name) != 0)
172 ERROR ("lpar plugin: uname failed.");
175 sstrncpy (plugin_inst, name.machine, sizeof (plugin_inst));
177 /* retrieve the current metrics */
178 if (!perfstat_partition_total (/* name = */ NULL, /* "must be set to NULL" */
179 &lparstats, sizeof (lparstats),
180 /* desired_number = */ 1 /* "must be set to 1" */))
182 ERROR ("lpar plugin: perfstat_partition_total failed.");
186 if (!lparstats.type.b.shared_enabled
187 && lparstats.type.b.donate_enabled)
190 delta_time_base = lparstats.timebase_last - last_time_base;
191 if (delta_time_base == 0)
193 /* The system stats have not been updated since last time */
197 submit_counter (plugin_inst, "cpu", "user", (counter_t) lparstats.puser);
198 submit_counter (plugin_inst, "cpu", "system", (counter_t) lparstats.psys);
199 submit_counter (plugin_inst, "cpu", "idle", (counter_t) lparstats.pidle);
200 submit_counter (plugin_inst, "cpu", "wait", (counter_t) lparstats.pwait);
202 /* FIXME: Use an appropriate GAUGE type here. */
203 lpar_submit (plugin_inst, "ent", (double)lparstats.entitled_proc_capacity / 100.0);
204 lpar_submit (plugin_inst, "max", (double)lparstats.max_proc_capacity / 100.0);
205 lpar_submit (plugin_inst, "min", (double)lparstats.min_proc_capacity / 100.0);
209 dlt_idle_donated = lparstats.idle_donated_purr - last_idle_donated_purr;
210 dlt_busy_donated = lparstats.busy_donated_purr - last_busy_donated_purr;
211 dlt_idle_stolen = lparstats.idle_stolen_purr - last_idle_stolen_purr;
212 dlt_busy_stolen = lparstats.busy_stolen_purr - last_busy_stolen_purr;
214 submit_counter (plugin_inst, "cpu", "donated-idle", (counter_t) lparstats.idle_donated_purr);
215 submit_counter (plugin_inst, "cpu", "donated-busy", (counter_t) lparstats.busy_donated_purr);
216 submit_counter (plugin_inst, "cpu", "stolen-idle", (counter_t) lparstats.idle_stolen_purr);
217 submit_counter (plugin_inst, "cpu", "stolen-busy", (counter_t) lparstats.busy_stolen_purr);
222 if (!lparstats.type.b.pool_util_authority)
224 WARNING ("lpar plugin: Pool utilization data is not available.");
228 u_longlong_t dlt_pit;
230 char type[DATA_MAX_NAME_LEN];
232 /* FIXME: The pool id should probably be used as plugin instance. */
233 dlt_pit = lparstats.pool_idle_time - last_pool_idle_time;
234 total = (double)lparstats.phys_cpus_pool;
235 idle = (double)dlt_pit / XINTFRAC / (double)delta_time_base;
236 ssnprintf (type, sizeof(type), "pool-%X-total", lparstats.pool_id);
237 lpar_submit (plugin_inst, type, total);
238 ssnprintf (type, sizeof(type), "pool-%X-used", lparstats.pool_id);
239 lpar_submit (plugin_inst, type, total - idle);
243 save_last_values (&lparstats);
246 } /* int lpar_read */
248 void module_register (void)
250 plugin_register_config ("lpar", lpar_config,
251 config_keys, config_keys_num);
252 plugin_register_init ("lpar", lpar_init);
253 plugin_register_read ("lpar", lpar_read);
254 } /* void module_register */
256 /* vim: set sw=8 sts=8 ts=8 noet : */