banshee est en développement actif : les collecteurs vont encore changer, et une version que vous publiez demandera sans doute des ajustements. Pour un usage stable, attendez la version 1.0.0.

Hardware

banshee/hardware-collection/hardware/ibm/https/hmc/

managed-systems

The state and the attention LED of each IBM Power server an HMC manages, by the HMC REST API.

  • hardware
  • ibm
  • power
  • hmc
  • managed-system
  • server
  • state
  • https

par banshee0 installation1 version

v1Dernière

Publiée le 27 octobre 2026. First version.

Keen 1.0.0 · 109 lignes
// The IBM Power servers a Hardware Management Console (HMC) manages, by its REST API: the state of each
// managed system as the HMC sees it, and its attention LED, which the server lights when it has a problem
// to service. The address is the HMC's, the host's: https://<host:address>/rest/api/.
need('protocol:http');
$address = need('host:address');
$user = need('protocol:http:user');
$password = need('protocol:http:password');

per('system', 'Managed systems');
output('state', 'text', array('label' => 'State', 'per' => 'system'));
output('attention-led', 'text', array('label' => 'Attention LED', 'per' => 'system'));

watch.expect('not-operating', 'System not operating', 'state', array(
    'help'     => 'Raises when the HMC gives a system any other state than the ones listed: powered off, in error, no connection to its service processor.',
    'critical' => array('operating'),
));
watch.state('attention', 'Attention LED lit', 'attention-led', array(
    'help'    => 'The server lights its attention LED when it logs a problem to service; the serviceable events of the HMC say which.',
    'warning' => array('true'),
));
watch.missing('missing', 'System missing', 'state', array('enabled' => false));

// Opens a session: PUT /rest/api/web/Logon, the account in the XML body IBM documents, each value passed by
// xml.escape. The HMC answers a LogonResponse whose X-API-Session is the session; the answer is secret, its
// body having carried the password. The session is kept in the cache, encrypted on the poller, so that one
// session serves every run: IBM warns that sessions opened and never closed wear the HMC's memory.
function logon($address, $user, $password) {
    $body = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
        . '<LogonRequest xmlns="http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/" schemaVersion="V1_1_0">'
        . '<Metadata><Atom/></Metadata>'
        . '<UserID kb="CUR" kxe="false">' . xml.escape($user) . '</UserID>'
        . '<Password kb="CUR" kxe="false">' . xml.escape($password) . '</Password>'
        . '</LogonRequest>';
    $answer = http.put('https://' . $address . '/rest/api/web/Logon', $body,
        headers=array('Content-Type' => 'application/vnd.ibm.powervm.web+xml; type=LogonRequest'));
    if ($answer['status'] == 401 || $answer['status'] == 403) {
        fail('misconfigured', 'The HMC refuses the account, code ' . $answer['status']);
    }
    if ($answer['status'] != 200) {
        fail('unreachable', 'The HMC answers the logon with code ' . $answer['status']);
    }
    $logon = xml.read($answer['body']);
    $session = $logon['LogonResponse'][0]['X-API-Session'][0]['#text'];
    cache.set('session', $session, 604800);
    return $session;
}

// Returns the entries of an Atom feed of the HMC, read by its path (/rest/api/uom/...), with the session kept
// in the cache. A session the HMC no longer knows (expired, HMC restarted) is refused, 401 or 403: it is
// closed by DELETE /rest/api/web/Logon, whatever its answer, and replaced by a new one, once. The HMC answers
// 204, without a body, for a feed with no entry. Each success keeps the session in the cache seven more days.
function hmc_entries($address, $path, $user, $password) {
    if (cache.has('session')) {
        $session = cache.get('session');
    } else {
        $session = logon($address, $user, $password);
    }
    $answer = http.get('https://' . $address . $path, headers=array('X-API-Session' => $session));
    if ($answer['status'] == 401 || $answer['status'] == 403) {
        http.delete('https://' . $address . '/rest/api/web/Logon', headers=array('X-API-Session' => $session), errors=$err);
        $session = logon($address, $user, $password);
        $answer = http.get('https://' . $address . $path, headers=array('X-API-Session' => $session));
    }
    if ($answer['status'] == 401 || $answer['status'] == 403) {
        fail('misconfigured', 'The account may not read ' . $path . ', code ' . $answer['status']);
    }
    if ($answer['status'] == 204) {
        cache.set('session', $session, 604800);
        return array();
    }
    if ($answer['status'] != 200) {
        fail('unreachable', 'The HMC answers ' . $path . ' with code ' . $answer['status']);
    }
    cache.set('session', $session, 604800);
    $feed = xml.read($answer['body']);
    return list.get($feed['feed'][0], 'entry', array());
}

// Returns the text of the first child of that name, '' when the HMC does not give it. The HMC writes each
// value with its attributes: <State kb="ROR" kxe="false">operating</State>.
function child_text($element, $name) {
    $children = list.get($element, $name, array());
    if (list.count($children) == 0) {
        return '';
    }
    return list.get($children[0], '#text', '');
}

// <entry><id>UUID</id><content type="..."><ManagedSystem:ManagedSystem ...> <State>operating</State>
// <SystemName>p10-a</SystemName> <PhysicalSystemAttentionLEDState>false</PhysicalSystemAttentionLEDState>.
// Two systems of one name each keep their own, the second carrying its UUID.
$systems = hmc_entries($address, '/rest/api/uom/ManagedSystem', $user, $password);
if (list.count($systems) == 0) {
    fail('misconfigured', 'The HMC lists no managed system', 'The account sees only the systems its resource role is set on.');
}
$seen = array();
foreach ($systems as $entry) {
    $system = $entry['content'][0]['ManagedSystem:ManagedSystem'][0];
    $name = child_text($system, 'SystemName');
    if ($name == '' || list.has($seen, $name)) {
        $name = $name . ' #' . $entry['id'][0];
    }
    $seen[$name] = true;
    value('state', child_text($system, 'State'), $name);
    $led = child_text($system, 'PhysicalSystemAttentionLEDState');
    if ($led != '') {
        value('attention-led', $led, $name);
    }
}